Remove Octoshock's unmanaged source and the binary

This commit is contained in:
YoshiRulz 2025-01-10 23:20:22 +10:00
parent 64a13ed003
commit 5403e86f1e
No known key found for this signature in database
GPG Key ID: C4DE31C245353FB7
187 changed files with 0 additions and 67769 deletions

Binary file not shown.

View File

@ -1,349 +0,0 @@
/* Mednafen - Multi-system Emulator
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "emuware/emuware.h"
#include "FileStream.h"
#include <stdarg.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
//#include <unistd.h>
#include <string.h>
#include <stdlib.h>
//work around gettext
#define _(X) X
#ifdef _MSC_VER
#include <sys/stat.h>
#include <io.h>
// These are not defined in MSVC version of stat.h
#define S_IWUSR S_IWRITE
#define S_IRUSR S_IREAD
#endif
#ifdef HAVE_MMAP
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#endif
// Some really bad preprocessor abuse follows to handle platforms that don't have fseeko and ftello...and of course
// for largefile support on Windows:
#ifndef HAVE_FSEEKO
#define fseeko fseek
#endif
#ifndef HAVE_FTELLO
#define ftello ftell
#endif
#define STRUCT_STAT struct stat
#if SIZEOF_OFF_T == 4
#ifdef HAVE_FOPEN64
#define fopen fopen64
#endif
#ifdef HAVE_FTELLO64
#undef ftello
#define ftello ftello64
#endif
#ifdef HAVE_FSEEKO64
#undef fseeko
#define fseeko fseeko64
#endif
#ifdef HAVE_FSTAT64
#define fstat fstat64
#define stat stat64
#undef STRUCT_STAT
#define STRUCT_STAT struct stat64
#endif
#ifdef HAVE_FTRUNCATE64
#define ftruncate ftruncate64
#endif
#endif
FileStream::FileStream(const std::string& path, const int mode) : OpenedMode(mode), mapping(NULL), mapping_size(0)
{
path_save = path;
if(mode == MODE_READ)
fp = fopen(path.c_str(), "rb");
else if(mode == MODE_WRITE)
fp = fopen(path.c_str(), "wb");
else if(mode == MODE_WRITE_SAFE || mode == MODE_WRITE_INPLACE) // SO ANNOYING
{
int open_flags = O_WRONLY | O_CREAT;
if(mode == MODE_WRITE_SAFE)
open_flags |= O_EXCL;
#ifdef O_BINARY
open_flags |= O_BINARY;
#elif defined(_O_BINARY)
open_flags |= _O_BINARY;
#endif
#if defined(S_IRGRP) && defined(S_IROTH)
int tmpfd = open(path.c_str(), open_flags, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
#else
int tmpfd = open(path.c_str(), open_flags, S_IRUSR | S_IWUSR);
#endif
if(tmpfd == -1)
{
ErrnoHolder ene(errno);
throw(MDFN_Error(ene.Errno(), _("Error opening file \"%s\": %s"), path_save.c_str(), ene.StrError()));
}
fp = fdopen(tmpfd, "wb");
}
else
abort();
if(!fp)
{
ErrnoHolder ene(errno);
throw(MDFN_Error(ene.Errno(), _("Error opening file \"%s\": %s"), path_save.c_str(), ene.StrError()));
}
}
FileStream::~FileStream()
{
try
{
close();
}
catch(std::exception &e)
{
printf(e.what());
}
}
uint64 FileStream::attributes(void)
{
uint64 ret = ATTRIBUTE_SEEKABLE;
switch(OpenedMode)
{
case MODE_READ:
ret |= ATTRIBUTE_READABLE;
break;
case MODE_WRITE_INPLACE:
case MODE_WRITE_SAFE:
case MODE_WRITE:
ret |= ATTRIBUTE_WRITEABLE;
break;
}
return ret;
}
uint8 *FileStream::map(void) noexcept
{
if(!mapping)
{
#ifdef HAVE_MMAP
uint64 length = size();
int prot = 0;
int flags = 0;
void* tptr;
if(OpenedMode == MODE_READ)
{
prot |= PROT_READ; // | PROT_EXEC;
flags |= MAP_PRIVATE;
}
else
{
prot |= PROT_WRITE;
prot |= MAP_SHARED;
}
if(length > SIZE_MAX)
return(NULL);
tptr = mmap(NULL, length, prot, flags, fileno(fp), 0);
if(tptr != (void*)-1)
{
mapping = tptr;
mapping_size = length;
#ifdef HAVE_MADVISE
// Should probably make this controllable via flag or somesuch.
madvise(mapping, mapping_size, MADV_SEQUENTIAL | MADV_WILLNEED);
#endif
}
#endif
}
return((uint8*)mapping);
}
uint64 FileStream::map_size(void) noexcept
{
return mapping_size;
}
void FileStream::unmap(void) noexcept
{
if(mapping)
{
#ifdef HAVE_MMAP
munmap(mapping, mapping_size);
#endif
mapping = NULL;
mapping_size = 0;
}
}
uint64 FileStream::read(void *data, uint64 count, bool error_on_eos)
{
uint64 read_count;
clearerr(fp);
read_count = fread(data, 1, count, fp);
if(read_count != count)
{
ErrnoHolder ene(errno);
if(ferror(fp))
throw(MDFN_Error(ene.Errno(), _("Error reading from opened file \"%s\": %s"), path_save.c_str(), ene.StrError()));
if(error_on_eos)
throw(MDFN_Error(0, _("Error reading from opened file \"%s\": %s"), path_save.c_str(), _("Unexpected EOF")));
}
return(read_count);
}
void FileStream::write(const void *data, uint64 count)
{
if(fwrite(data, 1, count, fp) != count)
{
ErrnoHolder ene(errno);
throw(MDFN_Error(ene.Errno(), _("Error writing to opened file \"%s\": %s"), path_save.c_str(), ene.StrError()));
}
}
void FileStream::truncate(uint64 length)
{
//not needed by mednadisc
//if(fflush(fp) == EOF || ftruncate(fileno(fp), length) != 0)
{
ErrnoHolder ene(errno);
throw(MDFN_Error(ene.Errno(), _("Error truncating opened file \"%s\": %s"), path_save.c_str(), ene.StrError()));
}
}
void FileStream::seek(int64 offset, int whence)
{
if(fseeko(fp, offset, whence) == -1)
{
ErrnoHolder ene(errno);
throw(MDFN_Error(ene.Errno(), _("Error seeking in opened file \"%s\": %s"), path_save.c_str(), ene.StrError()));
}
}
void FileStream::flush(void)
{
if(fflush(fp) == EOF)
{
ErrnoHolder ene(errno);
throw(MDFN_Error(ene.Errno(), _("Error flushing to opened file \"%s\": %s"), path_save.c_str(), ene.StrError()));
}
}
uint64 FileStream::tell(void)
{
auto offset = ftello(fp);
if(offset == -1)
{
ErrnoHolder ene(errno);
throw(MDFN_Error(ene.Errno(), _("Error getting position in opened file \"%s\": %s"), path_save.c_str(), ene.StrError()));
}
return (std::make_unsigned<decltype(offset)>::type)offset;
}
uint64 FileStream::size(void)
{
STRUCT_STAT buf;
if((OpenedMode != MODE_READ && fflush(fp) == EOF) || fstat(fileno(fp), &buf) == -1)
{
ErrnoHolder ene(errno);
throw(MDFN_Error(ene.Errno(), _("Error getting the size of opened file \"%s\": %s"), path_save.c_str(), ene.StrError()));
}
return (std::make_unsigned<decltype(buf.st_size)>::type)buf.st_size;
}
void FileStream::close(void)
{
if(fp)
{
FILE *tmp = fp;
unmap();
fp = NULL;
if(fclose(tmp) == EOF)
{
ErrnoHolder ene(errno);
throw(MDFN_Error(ene.Errno(), _("Error closing opened file \"%s\": %s"), path_save.c_str(), ene.StrError()));
}
}
}
int FileStream::get_line(std::string &str)
{
int c;
str.clear();
while((c = get_char()) >= 0)
{
if(c == '\r' || c == '\n' || c == 0)
return(c);
str.push_back(c);
}
return(str.length() ? 256 : -1);
}

View File

@ -1,89 +0,0 @@
/* Mednafen - Multi-system Emulator
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __MDFN_FILESTREAM_H
#define __MDFN_FILESTREAM_H
#include "Stream.h"
#include "error.h"
#include <stdio.h>
#include <string>
class FileStream : public Stream
{
public:
enum
{
MODE_READ = 0,
MODE_WRITE,
MODE_WRITE_SAFE, // Will throw an exception instead of overwriting an existing file.
MODE_WRITE_INPLACE, // Like MODE_WRITE, but won't truncate the file if it already exists.
};
FileStream(const std::string& path, const int mode);
virtual ~FileStream() override;
virtual uint64 attributes(void) override;
virtual uint8 *map(void) noexcept override;
virtual uint64 map_size(void) noexcept override;
virtual void unmap(void) noexcept override;
virtual uint64 read(void *data, uint64 count, bool error_on_eos = true) override;
virtual void write(const void *data, uint64 count) override;
virtual void truncate(uint64 length) override;
virtual void seek(int64 offset, int whence) override;
virtual uint64 tell(void) override;
virtual uint64 size(void) override;
virtual void flush(void) override;
virtual void close(void) override;
virtual int get_line(std::string &str) override;
INLINE int get_char(void)
{
int ret;
errno = 0;
ret = fgetc(fp);
if(MDFN_UNLIKELY(errno != 0))
{
ErrnoHolder ene(errno);
throw(MDFN_Error(ene.Errno(), ("Error reading from opened file \"%s\": %s"), path_save.c_str(), ene.StrError()));
}
return(ret);
}
private:
FileStream & operator=(const FileStream &); // Assignment operator
FileStream(const FileStream &); // Copy constructor
//FileStream(FileStream &); // Copy constructor
FILE *fp;
std::string path_save;
const int OpenedMode;
void* mapping;
uint64 mapping_size;
};
#endif

View File

@ -1,81 +0,0 @@
#include "emuware/emuware.h"
#include "Mednadisc.h"
#include "error.h"
#include "cdrom/CDAccess.h"
#include "cdrom/CDUtility.h"
#include "cdrom/cdromif.h"
#include "cdrom/CDAccess_Image.h"
class MednaDisc
{
public:
~MednaDisc()
{
delete disc;
}
CDAccess* disc;
CDUtility::TOC toc;
};
EW_EXPORT void* mednadisc_LoadCD(const char* fname)
{
CDAccess* disc = NULL;
try {
disc = CDAccess_Open(fname,false);
}
catch(MDFN_Error &) {
return NULL;
}
MednaDisc* md = new MednaDisc();
md->disc = disc;
disc->Read_TOC(&md->toc);
return md;
}
struct JustTOC
{
uint8 first_track;
uint8 last_track;
uint8 disc_type;
};
EW_EXPORT void mednadisc_ReadTOC(MednaDisc* md, JustTOC* justToc, CDUtility::TOC_Track *tracks101)
{
CDUtility::TOC &toc = md->toc;
justToc->first_track = toc.first_track;
justToc->last_track = toc.last_track;
justToc->disc_type = toc.disc_type;
memcpy(tracks101,toc.tracks,sizeof(toc.tracks));
}
//NOTE: the subcode will come out interleaved.
//Don't try changing this unless youre REALLY bored. It's convoluted.
//If you do, make sure you have three states: must_interleave, must_deinterleaved and dontcare
EW_EXPORT int32 mednadisc_ReadSector(MednaDisc* md, int lba, void* buf2448)
{
CDAccess* disc = md->disc;
CDUtility::TOC &toc = md->toc;
try
{
//EDIT: this is handled now by the individual readers
//if it's at the lead-out track or beyond, synthesize it as a lead-out sector
//if(lba >= (int32)toc.tracks[100].lba)
// synth_leadout_sector_lba(0x02, toc, lba, (uint8*)buf2448);
//else
disc->Read_Raw_Sector((uint8*)buf2448,lba);
}
catch(MDFN_Error &) {
return 0;
}
return 1;
}
EW_EXPORT void mednadisc_CloseCD(MednaDisc* md)
{
delete md;
}

View File

@ -1,9 +0,0 @@
#pragma once
#include "emuware/emuware.h"
class MednaDisc;
EW_EXPORT void* mednadisc_LoadCD(const char* fname);
EW_EXPORT int32 mednadisc_ReadSector(MednaDisc* disc, int lba, void* buf2448);
EW_EXPORT void mednadisc_CloseCD(MednaDisc* disc);

View File

@ -1,330 +0,0 @@
/* Mednafen - Multi-system Emulator
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <stdlib.h>
#include "MemoryStream.h"
#include "math_ops.h"
#include "error.h"
//work around gettext
#define _(X) X
/*
TODO: Copy and assignment constructor fixes.
Proper negative position behavior?
*/
MemoryStream::MemoryStream() : data_buffer(NULL), data_buffer_size(0), data_buffer_alloced(0), position(0)
{
data_buffer_size = 0;
data_buffer_alloced = 64;
if(!(data_buffer = (uint8*)realloc(data_buffer, data_buffer_alloced)))
throw MDFN_Error(ErrnoHolder(errno));
}
MemoryStream::MemoryStream(uint64 alloc_hint, int alloc_hint_is_size) : data_buffer(NULL), data_buffer_size(0), data_buffer_alloced(0), position(0)
{
if(alloc_hint_is_size != 0)
{
data_buffer_size = alloc_hint;
data_buffer_alloced = alloc_hint;
if(alloc_hint > SIZE_MAX)
throw MDFN_Error(ErrnoHolder(ENOMEM));
}
else
{
data_buffer_size = 0;
data_buffer_alloced = (alloc_hint > SIZE_MAX) ? SIZE_MAX : alloc_hint;
}
if(!(data_buffer = (uint8*)realloc(data_buffer, data_buffer_alloced)))
throw MDFN_Error(ErrnoHolder(errno));
if(alloc_hint_is_size > 0)
memset(data_buffer, 0, data_buffer_size);
}
MemoryStream::MemoryStream(Stream *stream, uint64 size_limit) : data_buffer(NULL), data_buffer_size(0), data_buffer_alloced(0), position(0)
{
try
{
if((position = stream->tell()) != 0)
stream->seek(0, SEEK_SET);
void* tp;
data_buffer_size = data_buffer_alloced = stream->alloc_and_read(&tp, size_limit);
data_buffer = (uint8*)tp;
stream->close();
}
catch(...)
{
if(data_buffer)
{
free(data_buffer);
data_buffer = NULL;
}
delete stream;
throw;
}
delete stream;
}
MemoryStream::MemoryStream(const MemoryStream &zs)
{
data_buffer_size = zs.data_buffer_size;
data_buffer_alloced = zs.data_buffer_alloced;
if(!(data_buffer = (uint8*)malloc(data_buffer_alloced)))
throw MDFN_Error(ErrnoHolder(errno));
memcpy(data_buffer, zs.data_buffer, data_buffer_size);
position = zs.position;
}
#if 0
MemoryStream & MemoryStream::operator=(const MemoryStream &zs)
{
if(this != &zs)
{
if(data_buffer)
{
free(data_buffer);
data_buffer = NULL;
}
data_buffer_size = zs.data_buffer_size;
data_buffer_alloced = zs.data_buffer_alloced;
if(!(data_buffer = (uint8*)malloc(data_buffer_alloced)))
throw MDFN_Error(ErrnoHolder(errno));
memcpy(data_buffer, zs.data_buffer, data_buffer_size);
position = zs.position;
}
return(*this);
}
#endif
MemoryStream::~MemoryStream()
{
if(data_buffer)
{
free(data_buffer);
data_buffer = NULL;
}
}
uint64 MemoryStream::attributes(void)
{
return (ATTRIBUTE_READABLE | ATTRIBUTE_WRITEABLE | ATTRIBUTE_SEEKABLE);
}
uint8 *MemoryStream::map(void) noexcept
{
return data_buffer;
}
uint64 MemoryStream::map_size(void) noexcept
{
return data_buffer_size;
}
void MemoryStream::unmap(void) noexcept
{
}
INLINE void MemoryStream::grow_if_necessary(uint64 new_required_size, uint64 hole_end)
{
if(new_required_size > data_buffer_size)
{
const uint64 old_data_buffer_size = data_buffer_size;
if(new_required_size > data_buffer_alloced)
{
uint64 new_required_alloced = round_up_pow2(new_required_size);
uint8 *new_data_buffer;
// first condition will happen at new_required_size > (1ULL << 63) due to round_up_pow2() "wrapping".
// second condition can occur when running on a 32-bit system.
if(new_required_alloced < new_required_size || new_required_alloced > SIZE_MAX)
new_required_alloced = SIZE_MAX;
// If constrained alloc size isn't enough, throw an out-of-memory/address-space type error.
if(new_required_alloced < new_required_size)
throw MDFN_Error(ErrnoHolder(ENOMEM));
if(!(new_data_buffer = (uint8*)realloc(data_buffer, new_required_alloced)))
throw MDFN_Error(ErrnoHolder(errno));
//
// Assign all in one go after the realloc() so we don't leave our object in an inconsistent state if the realloc() fails.
//
data_buffer = new_data_buffer;
data_buffer_size = new_required_size;
data_buffer_alloced = new_required_alloced;
}
else
data_buffer_size = new_required_size;
if(hole_end > old_data_buffer_size)
memset(data_buffer + old_data_buffer_size, 0, hole_end - old_data_buffer_size);
}
}
void MemoryStream::shrink_to_fit(void) noexcept
{
if(data_buffer_alloced > data_buffer_size)
{
uint8 *new_data_buffer;
new_data_buffer = (uint8*)realloc(data_buffer, data_buffer_size);
if(new_data_buffer != NULL)
{
data_buffer = new_data_buffer;
data_buffer_alloced = data_buffer_size;
}
}
}
uint64 MemoryStream::read(void *data, uint64 count, bool error_on_eos)
{
//printf("%llu %llu %llu\n", position, count, data_buffer_size);
if(count > data_buffer_size)
{
if(error_on_eos)
throw MDFN_Error(0, _("Unexpected EOF"));
count = data_buffer_size;
}
if(position > (data_buffer_size - count))
{
if(error_on_eos)
throw MDFN_Error(0, _("Unexpected EOF"));
if(data_buffer_size > position)
count = data_buffer_size - position;
else
count = 0;
}
memmove(data, &data_buffer[position], count);
position += count;
return count;
}
void MemoryStream::write(const void *data, uint64 count)
{
uint64 nrs = position + count;
if(nrs < position)
throw MDFN_Error(ErrnoHolder(EFBIG));
grow_if_necessary(nrs, position);
memmove(&data_buffer[position], data, count);
position += count;
}
//
// Don't add code to reduce the amount of memory allocated(when possible) without providing a
// per-stream setting to disable that behavior.
//
void MemoryStream::truncate(uint64 length)
{
grow_if_necessary(length, length);
data_buffer_size = length;
}
void MemoryStream::seek(int64 offset, int whence)
{
uint64 new_position;
switch(whence)
{
default:
throw MDFN_Error(ErrnoHolder(EINVAL));
break;
case SEEK_SET:
new_position = offset;
break;
case SEEK_CUR:
new_position = position + offset;
break;
case SEEK_END:
new_position = data_buffer_size + offset;
break;
}
if(new_position < 0)
throw MDFN_Error(ErrnoHolder(EINVAL));
position = new_position;
}
uint64 MemoryStream::tell(void)
{
return position;
}
uint64 MemoryStream::size(void)
{
return data_buffer_size;
}
void MemoryStream::flush(void)
{
}
void MemoryStream::close(void)
{
}
int MemoryStream::get_line(std::string &str)
{
str.clear(); // or str.resize(0)??
while((uint64)position < data_buffer_size)
{
uint8 c = data_buffer[position++];
if(c == '\r' || c == '\n' || c == 0)
return(c);
str.push_back(c); // Should be faster than str.append(1, c)
}
return(str.length() ? 256 : -1);
}

View File

@ -1,77 +0,0 @@
/* Mednafen - Multi-system Emulator
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
Notes:
For performance reasons(like in the state rewinding code), we should try to make sure map()
returns a pointer that is aligned to at least what malloc()/realloc() provides.
(And maybe forcefully align it to at least 16 bytes in the future)
*/
#ifndef __MDFN_MEMORYSTREAM_H
#define __MDFN_MEMORYSTREAM_H
#include "Stream.h"
class MemoryStream : public Stream
{
public:
MemoryStream();
MemoryStream(uint64 alloc_hint, int alloc_hint_is_size = false); // Pass -1 instead of 1 for alloc_hint_is_size to skip initialization of the memory.
MemoryStream(Stream *stream, uint64 size_limit = ~(uint64)0);
// Will create a MemoryStream equivalent of the contents of "stream", and then "delete stream".
// Will only work if stream->tell() == 0, or if "stream" is seekable.
// stream will be deleted even if this constructor throws.
//
// Will throw an exception if the initial size() of the MemoryStream would be greater than size_limit(useful for when passing
// in GZFileStream streams).
MemoryStream(const MemoryStream &zs);
MemoryStream & operator=(const MemoryStream &zs);
virtual ~MemoryStream() override;
virtual uint64 attributes(void) override;
virtual uint8 *map(void) noexcept override;
virtual uint64 map_size(void) noexcept override;
virtual void unmap(void) noexcept override;
virtual uint64 read(void *data, uint64 count, bool error_on_eos = true) override;
virtual void write(const void *data, uint64 count) override;
virtual void truncate(uint64 length) override;
virtual void seek(int64 offset, int whence) override;
virtual uint64 tell(void) override;
virtual uint64 size(void) override;
virtual void flush(void) override;
virtual void close(void) override;
virtual int get_line(std::string &str) override;
void shrink_to_fit(void) noexcept; // Minimizes alloced memory.
private:
uint8 *data_buffer;
uint64 data_buffer_size;
uint64 data_buffer_alloced;
uint64 position;
void grow_if_necessary(uint64 new_required_size, uint64 hole_end);
};
#endif

View File

@ -1,219 +0,0 @@
/* Mednafen - Multi-system Emulator
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <stdlib.h>
#include <stdarg.h>
#include <stdio.h>
#include "emuware/emuware.h"
#include "Stream.h"
#include "error.h"
//work around gettext stuff
#define _(X) X
Stream::Stream()
{
}
Stream::~Stream()
{
}
uint64 Stream::read_discard(uint64 count)
{
uint8 buf[1024];
uint64 tmp;
uint64 ret = 0;
do
{
tmp = read(buf, std::min<uint64>(count, sizeof(buf)), false);
count -= tmp;
ret += tmp;
} while(tmp == sizeof(buf));
return ret;
}
uint64 Stream::alloc_and_read(void** data_out, uint64 size_limit)
{
uint8 *data_buffer = NULL;
uint64 data_buffer_size = 0;
uint64 data_buffer_alloced = 0;
try
{
if(attributes() & ATTRIBUTE_SLOW_SIZE)
{
uint64 rti;
data_buffer_size = 0;
data_buffer_alloced = 65536;
if(!(data_buffer = (uint8*)realloc(data_buffer, data_buffer_alloced)))
throw MDFN_Error(ErrnoHolder(errno));
while((rti = read(data_buffer + data_buffer_size, data_buffer_alloced - data_buffer_size, false)) > 0)
{
uint8* new_data_buffer;
data_buffer_size += rti;
if(data_buffer_size == data_buffer_alloced)
{
data_buffer_alloced <<= 1;
if(data_buffer_alloced > size_limit) // So we can test against our size limit without going far far over it in temporary memory allocations.
data_buffer_alloced = size_limit + 1;
if(data_buffer_size > size_limit)
throw MDFN_Error(0, _("Size limit of %llu bytes would be exceeded."), (unsigned long long)size_limit);
if(!(new_data_buffer = (uint8 *)realloc(data_buffer, data_buffer_alloced)))
throw MDFN_Error(ErrnoHolder(errno));
data_buffer = new_data_buffer;
}
else // EOS
break;
}
if(data_buffer_alloced > data_buffer_size)
{
uint8 *new_data_buffer;
new_data_buffer = (uint8*)realloc(data_buffer, data_buffer_size);
if(new_data_buffer != NULL)
{
data_buffer = new_data_buffer;
data_buffer_alloced = data_buffer_size;
}
}
}
else
{
data_buffer_size = size();
data_buffer_alloced = data_buffer_size;
if(data_buffer_size > size_limit)
throw MDFN_Error(0, _("Size limit of %llu bytes would be exceeded."), (unsigned long long)size_limit);
if(data_buffer_alloced > SIZE_MAX)
throw MDFN_Error(ErrnoHolder(ENOMEM));
if(!(data_buffer = (uint8*)realloc(data_buffer, data_buffer_alloced)))
throw MDFN_Error(ErrnoHolder(errno));
read(data_buffer, data_buffer_size);
}
}
catch(...)
{
if(data_buffer)
{
free(data_buffer);
data_buffer = NULL;
}
throw;
}
*data_out = data_buffer;
return data_buffer_size;
}
uint8* Stream::map(void) noexcept
{
return(NULL);
}
uint64 Stream::map_size(void) noexcept
{
return 0;
}
void Stream::unmap(void) noexcept
{
}
void Stream::put_line(const std::string& str)
{
char l = '\n';
write(&str[0], str.size());
write(&l, sizeof(l));
}
void Stream::print_format(const char *format, ...)
{
char *str = NULL;
int rc;
va_list ap;
int size = 128;
for(;;) {
va_list ap;
va_start(ap, format);
str = (char*)malloc(size);
size *= 2;
int ret = vsprintf(str, format, ap);
va_end(ap);
if(ret>=0)
break;
free(str);
}
if(rc < 0)
throw MDFN_Error(0, "Error in trio_vasprintf()");
else
{
try // Bleck
{
write(str, rc);
}
catch(...)
{
free(str);
throw;
}
free(str);
}
}
int Stream::get_line(std::string &str)
{
uint8 c;
str.clear(); // or str.resize(0)??
while(read(&c, sizeof(c), false) > 0)
{
if(c == '\r' || c == '\n' || c == 0)
return(c);
str.push_back(c);
}
return(str.length() ? 256 : -1);
}

View File

@ -1,223 +0,0 @@
#ifndef __MDFN_STREAM_H
#define __MDFN_STREAM_H
// TODO?: BufferedStream, no virtual functions, yes inline functions, constructor takes a Stream* argument.
#include "emuware/emuware.h"
#include <errno.h>
#include <stdio.h> // For SEEK_* defines, which we will use in Stream out of FORCE OF HABIT.
#include <string.h>
#include <string>
class Stream
{
public:
Stream();
virtual ~Stream();
enum
{
ATTRIBUTE_READABLE = 1U << 0,
ATTRIBUTE_WRITEABLE = 1U << 1,
ATTRIBUTE_SEEKABLE = 1U << 2,
ATTRIBUTE_SLOW_SEEK = 1U << 3,
ATTRIBUTE_SLOW_SIZE = 1U << 4
};
virtual uint64 attributes(void) = 0;
virtual uint8 *map(void) noexcept;
// Map the entirety of the stream data into the address space of the process, if possible, and return a pointer.
// (the returned pointer must be cached, and returned on any subsequent calls to map() without an unmap()
// in-between, to facilitate a sort of "feature-testing", to determine if an alternative like "MemoryStream"
// should be used).
//
// If the mapping fails for whatever reason, return NULL rather than throwing an exception.
//
// For code using this functionality, ensure usage of map_size() instead of size(), unless you're only using a specific derived
// class like MemoryStream() where the value returned by size() won't change unexpectedly due to outside factors.
virtual uint64 map_size(void) noexcept;
// The size of the memory mapping area, point to which returned by map().
//
// Returns 0 on supported, or if no mapping currently exists.
virtual void unmap(void) noexcept;
// Unmap the stream data from the address space. (Possibly invalidating the pointer returned from map()).
// (must automatically be called, if necessary, from the destructor).
//
// If the data can't be "unmapped" as such because it was never mmap()'d or similar in the first place(such as with MemoryStream),
// then this will be a nop.
virtual uint64 read(void *data, uint64 count, bool error_on_eos = true) = 0;
virtual void write(const void *data, uint64 count) = 0;
virtual void truncate(uint64 length) = 0; // Should have ftruncate()-like semantics; but avoid using it to extend files.
virtual void seek(int64 offset, int whence = SEEK_SET) = 0;
inline void rewind(void)
{
seek(0, SEEK_SET);
}
virtual uint64 tell(void) = 0;
virtual uint64 size(void) = 0; // May implicitly call flush() if the stream is writeable.
virtual void flush(void) = 0;
virtual void close(void) = 0; // Flushes(in the case of writeable streams) and closes the stream.
// Necessary since this operation can fail(running out of disk space, for instance),
// and throw an exception in the destructor would be a Bad Idea(TM).
//
// Manually calling this function isn't strictly necessary, but recommended when the
// stream is writeable; it will be called automatically from the destructor, with any
// exceptions thrown caught and logged.
//
// Utility functions(TODO):
//
INLINE uint8 get_u8(void)
{
uint8 ret;
read(&ret, sizeof(ret));
return ret;
}
INLINE void put_u8(uint8 c)
{
write(&c, sizeof(c));
}
template<typename T>
INLINE T get_NE(void)
{
T ret;
read(&ret, sizeof(ret));
return ret;
}
template<typename T>
INLINE T get_RE(void)
{
uint8 tmp[sizeof(T)];
union
{
T ret;
uint8 ret_u8[sizeof(T)];
};
read(tmp, sizeof(tmp));
for(unsigned i = 0; i < sizeof(T); i++)
ret_u8[i] = tmp[sizeof(T) - 1 - i];
return ret;
}
template<typename T>
INLINE void put_NE(T c)
{
write(&c, sizeof(c));
}
template<typename T>
INLINE void put_RE(T c)
{
uint8 tmp[sizeof(T)];
for(unsigned i = 0; i < sizeof(T); i++)
tmp[i] = ((uint8 *)&c)[sizeof(T) - 1 - i];
write(tmp, sizeof(tmp));
}
template<typename T>
INLINE T get_LE(void)
{
#ifdef LSB_FIRST
return get_NE<T>();
#else
return get_RE<T>();
#endif
}
template<typename T>
INLINE void put_LE(T c)
{
#ifdef LSB_FIRST
return put_NE<T>(c);
#else
return put_RE<T>(c);
#endif
}
template<typename T>
INLINE T get_BE(void)
{
#ifndef LSB_FIRST
return get_NE<T>();
#else
return get_RE<T>();
#endif
}
template<typename T>
INLINE void put_BE(T c)
{
#ifndef LSB_FIRST
return put_NE<T>(c);
#else
return put_RE<T>(c);
#endif
}
INLINE void put_string(const char* str)
{
write(str, strlen(str));
}
// Reads a line into "str", overwriting its contents; returns the line-end char('\n' or '\r' or '\0'), or 256 on EOF and
// data has been read into "str", and -1 on EOF when no data has been read into "str".
// The line-end char won't be added to "str".
// It's up to the caller to handle extraneous empty lines caused by DOS-format text lines(\r\n).
// ("str" is passed by reference for the possibility of improved performance by reusing alloced memory for the std::string, though part
// of it would be up to the STL implementation).
// Implemented as virtual so that a higher-performance version can be implemented if possible(IE with MemoryStream)
virtual int get_line(std::string &str);
virtual void put_line(const std::string& str);
virtual void print_format(const char *format, ...) MDFN_FORMATSTR(gnu_printf, 2, 3);
#if 0
int scanf(const char *format, ...) MDFN_FORMATSTR(gnu_scanf, 2, 3);
void put_string(const char *str);
void put_string(const std::string &str);
#endif
//
// Read until end-of-stream(or count), discarding any read data, and returns the amount of data "read".
// (Useful for detecting and printing warnings about extra garbage data without needing to call size(),
// which can be problematic for some types of Streams).
uint64 read_discard(uint64 count = ~(uint64)0);
//
// Reads stream starting at the current stream position(as returned by tell()), into memory allocated with malloc() and realloc(), and
// sets *data_out to a pointer to the memory(which the caller will need to free() at some point).
//
// *data_out is only an output.
//
// If size_limit is/will be exceeded, an exception will be thrown, and *data_out will not be written to.
//
// Will return the amount of data read(and the size of the alloced memory).
//
uint64 alloc_and_read(void** data_out, uint64 size_limit = ~(uint64)0);
};
#endif

View File

@ -1,608 +0,0 @@
/* Mednafen - Multi-system Emulator
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
// AR_Open(), and AudioReader, will NOT take "ownership" of the Stream object(IE it won't ever delete it). Though it does assume it has exclusive access
// to it for as long as the AudioReader object exists.
// Don't allow exceptions to propagate into the vorbis/musepack/etc. libraries, as it could easily leave the state of the library's decoder "object" in an
// inconsistent state, which would cause all sorts of unfun when we try to destroy it while handling the exception farther up.
#include "../mednafen.h"
#include "audioreader.h"
#include <sys/types.h>
#include <sys/stat.h>
#include "../tremor/ivorbisfile.h"
#include "../mpcdec/mpcdec.h"
#ifdef HAVE_LIBSNDFILE
#include <sndfile.h>
#endif
#ifdef HAVE_OPUSFILE
#include "audioreader_opus.h"
#endif
#include <string.h>
#include <errno.h>
#include <time.h>
#include "../general.h"
#include "../endian.h"
AudioReader::AudioReader() : LastReadPos(0)
{
}
AudioReader::~AudioReader()
{
}
int64 AudioReader::Read_(int16 *buffer, int64 frames)
{
abort();
return(false);
}
bool AudioReader::Seek_(int64 frame_offset)
{
abort();
return(false);
}
int64 AudioReader::FrameCount(void)
{
abort();
return(0);
}
/*
**
**
**
**
**
**
**
**
**
*/
class OggVorbisReader : public AudioReader
{
public:
OggVorbisReader(Stream *fp);
~OggVorbisReader();
int64 Read_(int16 *buffer, int64 frames);
bool Seek_(int64 frame_offset);
int64 FrameCount(void);
private:
OggVorbis_File ovfile;
Stream *fw;
};
static size_t iov_read_func(void *ptr, size_t size, size_t nmemb, void *user_data)
{
Stream *fw = (Stream*)user_data;
if(!size)
return(0);
try
{
return fw->read(ptr, size * nmemb, false) / size;
}
catch(...)
{
return(0);
}
}
static int iov_seek_func(void *user_data, ogg_int64_t offset, int whence)
{
Stream *fw = (Stream*)user_data;
try
{
fw->seek(offset, whence);
return(0);
}
catch(...)
{
return(-1);
}
}
static int iov_close_func(void *user_data)
{
Stream *fw = (Stream*)user_data;
try
{
fw->close();
return(0);
}
catch(...)
{
return EOF;
}
}
static long iov_tell_func(void *user_data)
{
Stream *fw = (Stream*)user_data;
try
{
return fw->tell();
}
catch(...)
{
return(-1);
}
}
OggVorbisReader::OggVorbisReader(Stream *fp) : fw(fp)
{
ov_callbacks cb;
memset(&cb, 0, sizeof(cb));
cb.read_func = iov_read_func;
cb.seek_func = iov_seek_func;
cb.close_func = iov_close_func;
cb.tell_func = iov_tell_func;
fp->seek(0, SEEK_SET);
if(ov_open_callbacks(fp, &ovfile, NULL, 0, cb))
throw(0);
}
OggVorbisReader::~OggVorbisReader()
{
ov_clear(&ovfile);
}
int64 OggVorbisReader::Read_(int16 *buffer, int64 frames)
{
uint8 *tw_buf = (uint8 *)buffer;
int cursection = 0;
long toread = frames * sizeof(int16) * 2;
while(toread > 0)
{
long didread = ov_read(&ovfile, (char*)tw_buf, toread, &cursection);
if(didread == 0)
break;
tw_buf = (uint8 *)tw_buf + didread;
toread -= didread;
}
return(frames - toread / sizeof(int16) / 2);
}
bool OggVorbisReader::Seek_(int64 frame_offset)
{
ov_pcm_seek(&ovfile, frame_offset);
return(true);
}
int64 OggVorbisReader::FrameCount(void)
{
return(ov_pcm_total(&ovfile, -1));
}
class MPCReader : public AudioReader
{
public:
MPCReader(Stream *fp);
~MPCReader();
int64 Read_(int16 *buffer, int64 frames);
bool Seek_(int64 frame_offset);
int64 FrameCount(void);
private:
mpc_reader reader;
mpc_demux *demux;
mpc_streaminfo si;
MPC_SAMPLE_FORMAT MPCBuffer[MPC_DECODER_BUFFER_LENGTH];
uint32 MPCBufferIn;
uint32 MPCBufferOffs;
Stream *fw;
};
/// Reads size bytes of data into buffer at ptr.
static mpc_int32_t impc_read(mpc_reader *p_reader, void *ptr, mpc_int32_t size)
{
Stream *fw = (Stream*)(p_reader->data);
try
{
return fw->read(ptr, size, false);
}
catch(...)
{
return(MPC_STATUS_FAIL);
}
}
/// Seeks to byte position offset.
static mpc_bool_t impc_seek(mpc_reader *p_reader, mpc_int32_t offset)
{
Stream *fw = (Stream*)(p_reader->data);
try
{
fw->seek(offset, SEEK_SET);
return(MPC_TRUE);
}
catch(...)
{
return(MPC_FALSE);
}
}
/// Returns the current byte offset in the stream.
static mpc_int32_t impc_tell(mpc_reader *p_reader)
{
Stream *fw = (Stream*)(p_reader->data);
try
{
return fw->tell();
}
catch(...)
{
return(MPC_STATUS_FAIL);
}
}
/// Returns the total length of the source stream, in bytes.
static mpc_int32_t impc_get_size(mpc_reader *p_reader)
{
Stream *fw = (Stream*)(p_reader->data);
try
{
return fw->size();
}
catch(...)
{
return(MPC_STATUS_FAIL);
}
}
/// True if the stream is a seekable stream.
static mpc_bool_t impc_canseek(mpc_reader *p_reader)
{
return(MPC_TRUE);
}
MPCReader::MPCReader(Stream *fp) : fw(fp)
{
fp->seek(0, SEEK_SET);
demux = NULL;
memset(&si, 0, sizeof(si));
memset(MPCBuffer, 0, sizeof(MPCBuffer));
MPCBufferOffs = 0;
MPCBufferIn = 0;
memset(&reader, 0, sizeof(reader));
reader.read = impc_read;
reader.seek = impc_seek;
reader.tell = impc_tell;
reader.get_size = impc_get_size;
reader.canseek = impc_canseek;
reader.data = (void*)fp;
if(!(demux = mpc_demux_init(&reader)))
{
throw(0);
}
mpc_demux_get_info(demux, &si);
if(si.channels != 2)
{
mpc_demux_exit(demux);
demux = NULL;
throw MDFN_Error(0, _("MusePack stream has wrong number of channels(%u); the correct number is 2."), si.channels);
}
if(si.sample_freq != 44100)
{
mpc_demux_exit(demux);
demux = NULL;
throw MDFN_Error(0, _("MusePack stream has wrong samplerate(%u Hz); the correct samplerate is 44100 Hz."), si.sample_freq);
}
}
MPCReader::~MPCReader()
{
if(demux)
{
mpc_demux_exit(demux);
demux = NULL;
}
}
int64 MPCReader::Read_(int16 *buffer, int64 frames)
{
mpc_status err;
int16 *cowbuf = (int16 *)buffer;
int32 toread = frames * 2;
while(toread > 0)
{
int32 tmplen;
if(!MPCBufferIn)
{
mpc_frame_info fi;
memset(&fi, 0, sizeof(fi));
fi.buffer = MPCBuffer;
if((err = mpc_demux_decode(demux, &fi)) < 0 || fi.bits == -1)
return(frames - toread / 2);
MPCBufferIn = fi.samples * 2;
MPCBufferOffs = 0;
}
tmplen = MPCBufferIn;
if(tmplen >= toread)
tmplen = toread;
for(int x = 0; x < tmplen; x++)
{
#ifdef MPC_FIXED_POINT
int32 samp = MPCBuffer[MPCBufferOffs + x] >> MPC_FIXED_POINT_FRACTPART;
#else
#warning Floating-point MPC decoding path not tested.
int32 samp = (int32)(MPCBuffer[MPCBufferOffs + x] * 32767);
#endif
if(samp < -32768)
samp = -32768;
if(samp > 32767)
samp = 32767;
*cowbuf = (int16)samp;
cowbuf++;
}
MPCBufferOffs += tmplen;
toread -= tmplen;
MPCBufferIn -= tmplen;
}
return(frames - toread / 2);
}
bool MPCReader::Seek_(int64 frame_offset)
{
MPCBufferOffs = 0;
MPCBufferIn = 0;
if(mpc_demux_seek_sample(demux, frame_offset) < 0)
return(false);
return(true);
}
int64 MPCReader::FrameCount(void)
{
return(mpc_streaminfo_get_length_samples(&si));
}
/*
**
**
**
**
**
**
**
**
**
*/
#ifdef HAVE_LIBSNDFILE
class SFReader : public AudioReader
{
public:
SFReader(Stream *fp);
~SFReader();
int64 Read_(int16 *buffer, int64 frames);
bool Seek_(int64 frame_offset);
int64 FrameCount(void);
private:
SNDFILE *sf;
SF_INFO sfinfo;
SF_VIRTUAL_IO sfvf;
Stream *fw;
};
static sf_count_t isf_get_filelen(void *user_data)
{
Stream *fw = (Stream*)user_data;
try
{
return fw->size();
}
catch(...)
{
return(-1);
}
}
static sf_count_t isf_seek(sf_count_t offset, int whence, void *user_data)
{
Stream *fw = (Stream*)user_data;
try
{
//printf("Seek: offset=%lld, whence=%lld\n", (long long)offset, (long long)whence);
fw->seek(offset, whence);
return fw->tell();
}
catch(...)
{
//printf(" SEEK FAILED\n");
return(-1);
}
}
static sf_count_t isf_read(void *ptr, sf_count_t count, void *user_data)
{
Stream *fw = (Stream*)user_data;
try
{
sf_count_t ret = fw->read(ptr, count, false);
//printf("Read: count=%lld, ret=%lld\n", (long long)count, (long long)ret);
return ret;
}
catch(...)
{
//printf(" READ FAILED\n");
return(0);
}
}
static sf_count_t isf_write(const void *ptr, sf_count_t count, void *user_data)
{
return(0);
}
static sf_count_t isf_tell(void *user_data)
{
Stream *fw = (Stream*)user_data;
try
{
return fw->tell();
}
catch(...)
{
return(-1);
}
}
SFReader::SFReader(Stream *fp) : fw(fp)
{
fp->seek(0, SEEK_SET);
memset(&sfvf, 0, sizeof(sfvf));
sfvf.get_filelen = isf_get_filelen;
sfvf.seek = isf_seek;
sfvf.read = isf_read;
sfvf.write = isf_write;
sfvf.tell = isf_tell;
memset(&sfinfo, 0, sizeof(sfinfo));
if(!(sf = sf_open_virtual(&sfvf, SFM_READ, &sfinfo, (void*)fp)))
throw(0);
}
SFReader::~SFReader()
{
sf_close(sf);
}
int64 SFReader::Read_(int16 *buffer, int64 frames)
{
return(sf_read_short(sf, (short*)buffer, frames * 2) / 2);
}
bool SFReader::Seek_(int64 frame_offset)
{
// FIXME error condition
if(sf_seek(sf, frame_offset, SEEK_SET) != frame_offset)
return(false);
return(true);
}
int64 SFReader::FrameCount(void)
{
return(sfinfo.frames);
}
#endif
AudioReader *AR_Open(Stream *fp)
{
try
{
return new MPCReader(fp);
}
catch(int i)
{
}
#ifdef HAVE_OPUSFILE
try
{
return new OpusReader(fp);
}
catch(int i)
{
}
#endif
try
{
return new OggVorbisReader(fp);
}
catch(int i)
{
}
#ifdef HAVE_LIBSNDFILE
try
{
return new SFReader(fp);
}
catch(int i)
{
}
#endif
return(NULL);
}

View File

@ -1,43 +0,0 @@
#ifndef __MDFN_AUDIOREADER_H
#define __MDFN_AUDIOREADER_H
#include "../Stream.h"
class AudioReader
{
public:
AudioReader();
virtual ~AudioReader();
virtual int64 FrameCount(void);
INLINE int64 Read(int64 frame_offset, int16 *buffer, int64 frames)
{
int64 ret;
//if(frame_offset >= 0)
{
if(LastReadPos != frame_offset)
{
//puts("SEEK");
if(!Seek_(frame_offset))
return(0);
LastReadPos = frame_offset;
}
}
ret = Read_(buffer, frames);
LastReadPos += ret;
return(ret);
}
private:
virtual int64 Read_(int16 *buffer, int64 frames);
virtual bool Seek_(int64 frame_offset);
int64 LastReadPos;
};
// AR_Open(), and AudioReader, will NOT take "ownership" of the Stream object(IE it won't ever delete it). Though it does assume it has exclusive access
// to it for as long as the AudioReader object exists.
AudioReader *AR_Open(Stream *fp);
#endif

View File

@ -1,24 +0,0 @@

Microsoft Visual Studio Solution File, Format Version 11.00
# Visual Studio 2010
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mednadisc", "mednadisc.vcxproj", "{5F35CAFC-6208-4FBE-AD17-0E69BA3F70EC}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{5F35CAFC-6208-4FBE-AD17-0E69BA3F70EC}.Debug|Win32.ActiveCfg = Debug|Win32
{5F35CAFC-6208-4FBE-AD17-0E69BA3F70EC}.Debug|Win32.Build.0 = Debug|Win32
{5F35CAFC-6208-4FBE-AD17-0E69BA3F70EC}.Release|Win32.ActiveCfg = Release|Win32
{5F35CAFC-6208-4FBE-AD17-0E69BA3F70EC}.Release|Win32.Build.0 = Release|Win32
{5A0DAC84-1170-4B1A-B9A9-F566A1D97790}.Debug|Win32.ActiveCfg = Debug|Win32
{5A0DAC84-1170-4B1A-B9A9-F566A1D97790}.Debug|Win32.Build.0 = Debug|Win32
{5A0DAC84-1170-4B1A-B9A9-F566A1D97790}.Release|Win32.ActiveCfg = Release|Win32
{5A0DAC84-1170-4B1A-B9A9-F566A1D97790}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View File

@ -1,138 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\cdrom\CDAccess.cpp" />
<ClCompile Include="..\cdrom\CDAccess_CCD.cpp" />
<ClCompile Include="..\cdrom\CDAccess_Image.cpp" />
<ClCompile Include="..\cdrom\CDAFReader.cpp" />
<ClCompile Include="..\cdrom\cdromif.cpp" />
<ClCompile Include="..\cdrom\CDUtility.cpp" />
<ClCompile Include="..\cdrom\crc32.cpp" />
<ClCompile Include="..\cdrom\galois.cpp" />
<ClCompile Include="..\cdrom\l-ec.cpp" />
<ClCompile Include="..\cdrom\lec.cpp" />
<ClCompile Include="..\cdrom\recover-raw.cpp" />
<ClCompile Include="..\endian.cpp" />
<ClCompile Include="..\error.cpp" />
<ClCompile Include="..\FileStream.cpp" />
<ClCompile Include="..\general.cpp" />
<ClCompile Include="..\Mednadisc.cpp" />
<ClCompile Include="..\MemoryStream.cpp" />
<ClCompile Include="..\Stream.cpp" />
<ClCompile Include="..\string\trim.cpp" />
<ClCompile Include="..\trio\trio.c" />
<ClCompile Include="..\trio\trionan.c" />
<ClCompile Include="..\trio\triostr.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\cdrom\CDAccess.h" />
<ClInclude Include="..\cdrom\CDAccess_CCD.h" />
<ClInclude Include="..\cdrom\CDAccess_Image.h" />
<ClInclude Include="..\cdrom\CDAFReader.h" />
<ClInclude Include="..\cdrom\cdromif.h" />
<ClInclude Include="..\cdrom\CDUtility.h" />
<ClInclude Include="..\cdrom\dvdisaster.h" />
<ClInclude Include="..\cdrom\galois-inlines.h" />
<ClInclude Include="..\cdrom\lec.h" />
<ClInclude Include="..\cdrom\SimpleFIFO.h" />
<ClInclude Include="..\emuware\emuware.h" />
<ClInclude Include="..\endian.h" />
<ClInclude Include="..\error.h" />
<ClInclude Include="..\FileStream.h" />
<ClInclude Include="..\general.h" />
<ClInclude Include="..\Mednadisc.h" />
<ClInclude Include="..\MemoryStream.h" />
<ClInclude Include="..\Stream.h" />
<ClInclude Include="..\string\trim.h" />
<ClInclude Include="..\trio\trio.h" />
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{5F35CAFC-6208-4FBE-AD17-0E69BA3F70EC}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>mednadisc</RootNamespace>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<OutDir>$(ProjectDir)..\..\..\output\dll\</OutDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(ProjectDir)\..\..\..\output\dll\</OutDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>TRIO_PUBLIC=;TRIO_PRIVATE=static;EW_EXPORT;_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_WINDOWS;_USRDLL;OCTOSHOCK_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>../emuware/msvc;..</AdditionalIncludeDirectories>
<PrecompiledHeaderFile>
</PrecompiledHeaderFile>
<PrecompiledHeaderOutputFile>
</PrecompiledHeaderOutputFile>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<MinimalRebuild>false</MinimalRebuild>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;TRIO_PUBLIC=;TRIO_PRIVATE=static;EW_EXPORT;WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PrecompiledHeaderFile>
</PrecompiledHeaderFile>
<PrecompiledHeaderOutputFile>
</PrecompiledHeaderOutputFile>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<AdditionalIncludeDirectories>../emuware/msvc;..</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -1,119 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="cdrom">
<UniqueIdentifier>{a3ffd332-9644-473f-b3b6-d31b08be5256}</UniqueIdentifier>
</Filter>
<Filter Include="emuware">
<UniqueIdentifier>{99e57b88-966c-4695-8f5c-1db6345b1b26}</UniqueIdentifier>
</Filter>
<Filter Include="string">
<UniqueIdentifier>{798fa5bd-6381-487a-99d2-35a15a6da439}</UniqueIdentifier>
</Filter>
<Filter Include="trio">
<UniqueIdentifier>{a43930f5-41a5-4b2b-92ef-bd90f9716127}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\cdrom\CDAccess_Image.cpp">
<Filter>cdrom</Filter>
</ClCompile>
<ClCompile Include="..\cdrom\cdromif.cpp">
<Filter>cdrom</Filter>
</ClCompile>
<ClCompile Include="..\cdrom\CDUtility.cpp">
<Filter>cdrom</Filter>
</ClCompile>
<ClCompile Include="..\cdrom\crc32.cpp">
<Filter>cdrom</Filter>
</ClCompile>
<ClCompile Include="..\cdrom\galois.cpp">
<Filter>cdrom</Filter>
</ClCompile>
<ClCompile Include="..\cdrom\lec.cpp">
<Filter>cdrom</Filter>
</ClCompile>
<ClCompile Include="..\cdrom\l-ec.cpp">
<Filter>cdrom</Filter>
</ClCompile>
<ClCompile Include="..\cdrom\recover-raw.cpp">
<Filter>cdrom</Filter>
</ClCompile>
<ClCompile Include="..\cdrom\CDAccess.cpp">
<Filter>cdrom</Filter>
</ClCompile>
<ClCompile Include="..\cdrom\CDAccess_CCD.cpp">
<Filter>cdrom</Filter>
</ClCompile>
<ClCompile Include="..\Stream.cpp" />
<ClCompile Include="..\error.cpp" />
<ClCompile Include="..\FileStream.cpp" />
<ClCompile Include="..\endian.cpp" />
<ClCompile Include="..\MemoryStream.cpp" />
<ClCompile Include="..\string\trim.cpp">
<Filter>string</Filter>
</ClCompile>
<ClCompile Include="..\general.cpp" />
<ClCompile Include="..\Mednadisc.cpp" />
<ClCompile Include="..\trio\trio.c">
<Filter>trio</Filter>
</ClCompile>
<ClCompile Include="..\cdrom\CDAFReader.cpp">
<Filter>cdrom</Filter>
</ClCompile>
<ClCompile Include="..\trio\trionan.c">
<Filter>trio</Filter>
</ClCompile>
<ClCompile Include="..\trio\triostr.c">
<Filter>trio</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\cdrom\CDAccess_Image.h">
<Filter>cdrom</Filter>
</ClInclude>
<ClInclude Include="..\cdrom\cdromif.h">
<Filter>cdrom</Filter>
</ClInclude>
<ClInclude Include="..\cdrom\CDUtility.h">
<Filter>cdrom</Filter>
</ClInclude>
<ClInclude Include="..\cdrom\dvdisaster.h">
<Filter>cdrom</Filter>
</ClInclude>
<ClInclude Include="..\cdrom\galois-inlines.h">
<Filter>cdrom</Filter>
</ClInclude>
<ClInclude Include="..\cdrom\lec.h">
<Filter>cdrom</Filter>
</ClInclude>
<ClInclude Include="..\cdrom\SimpleFIFO.h">
<Filter>cdrom</Filter>
</ClInclude>
<ClInclude Include="..\cdrom\CDAccess.h">
<Filter>cdrom</Filter>
</ClInclude>
<ClInclude Include="..\cdrom\CDAccess_CCD.h">
<Filter>cdrom</Filter>
</ClInclude>
<ClInclude Include="..\emuware\emuware.h">
<Filter>emuware</Filter>
</ClInclude>
<ClInclude Include="..\error.h" />
<ClInclude Include="..\Stream.h" />
<ClInclude Include="..\FileStream.h" />
<ClInclude Include="..\endian.h" />
<ClInclude Include="..\MemoryStream.h" />
<ClInclude Include="..\string\trim.h">
<Filter>string</Filter>
</ClInclude>
<ClInclude Include="..\general.h" />
<ClInclude Include="..\Mednadisc.h" />
<ClInclude Include="..\trio\trio.h">
<Filter>trio</Filter>
</ClInclude>
<ClInclude Include="..\cdrom\CDAFReader.h">
<Filter>cdrom</Filter>
</ClInclude>
</ItemGroup>
</Project>

View File

@ -1,83 +0,0 @@
/* Mednafen - Multi-system Emulator
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
// CDAFR_Open(), and CDAFReader, will NOT take "ownership" of the Stream object(IE it won't ever delete it). Though it does assume it has exclusive access
// to it for as long as the CDAFReader object exists.
// Don't allow exceptions to propagate into the vorbis/musepack/etc. libraries, as it could easily leave the state of the library's decoder "object" in an
// inconsistent state, which would cause all sorts of unfun when we try to destroy it while handling the exception farther up.
#include "emuware/emuware.h"
#include "CDAFReader.h"
#include "CDAFReader_Vorbis.h"
#include "CDAFReader_MPC.h"
#ifdef HAVE_LIBSNDFILE
#include "CDAFReader_SF.h"
#endif
CDAFReader::CDAFReader() : LastReadPos(0)
{
}
CDAFReader::~CDAFReader()
{
}
CDAFReader* CDAFR_Null_Open(Stream* fp)
{
return NULL;
}
CDAFReader *CDAFR_Open(Stream *fp)
{
static CDAFReader* (* const OpenFuncs[])(Stream* fp) =
{
#ifdef HAVE_MPC
CDAFR_MPC_Open,
#endif
#ifdef HAVE_VORBIS
CDAFR_Vorbis_Open, // Must come before CDAFR_SF_Open
#endif
#ifdef HAVE_LIBSNDFILE
CDAFR_SF_Open,
#endif
CDAFR_Null_Open
};
for(int idx=0;idx<ARRAY_SIZE(OpenFuncs);idx++)
{
auto f = OpenFuncs[idx];
try
{
fp->rewind();
return f(fp);
}
catch(int i)
{
}
}
return(NULL);
}

View File

@ -1,41 +0,0 @@
#ifndef __MDFN_CDAFREADER_H
#define __MDFN_CDAFREADER_H
#include "Stream.h"
class CDAFReader
{
public:
CDAFReader();
virtual ~CDAFReader();
virtual uint64 FrameCount(void) = 0;
INLINE uint64 Read(uint64 frame_offset, int16 *buffer, uint64 frames)
{
uint64 ret;
if(LastReadPos != frame_offset)
{
//puts("SEEK");
if(!Seek_(frame_offset))
return(0);
LastReadPos = frame_offset;
}
ret = Read_(buffer, frames);
LastReadPos += ret;
return(ret);
}
private:
virtual uint64 Read_(int16 *buffer, uint64 frames) = 0;
virtual bool Seek_(uint64 frame_offset) = 0;
uint64 LastReadPos;
};
// AR_Open(), and CDAFReader, will NOT take "ownership" of the Stream object(IE it won't ever delete it). Though it does assume it has exclusive access
// to it for as long as the CDAFReader object exists.
CDAFReader *CDAFR_Open(Stream *fp);
#endif

View File

@ -1,238 +0,0 @@
/* Mednafen - Multi-system Emulator
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <mednafen/mednafen.h>
#include "CDAFReader.h"
#include "CDAFReader_MPC.h"
#if 0
#include <mpc/mpcdec.h>
#else
#include <mednafen/mpcdec/mpcdec.h>
#endif
class CDAFReader_MPC final : public CDAFReader
{
public:
CDAFReader_MPC(Stream *fp);
~CDAFReader_MPC();
uint64 Read_(int16 *buffer, uint64 frames) override;
bool Seek_(uint64 frame_offset) override;
uint64 FrameCount(void) override;
private:
mpc_reader reader;
mpc_demux *demux;
mpc_streaminfo si;
MPC_SAMPLE_FORMAT MPCBuffer[MPC_DECODER_BUFFER_LENGTH];
uint32 MPCBufferIn;
uint32 MPCBufferOffs;
Stream *fw;
};
/// Reads size bytes of data into buffer at ptr.
static mpc_int32_t impc_read(mpc_reader *p_reader, void *ptr, mpc_int32_t size)
{
Stream *fw = (Stream*)(p_reader->data);
try
{
return fw->read(ptr, size, false);
}
catch(...)
{
return(MPC_STATUS_FAIL);
}
}
/// Seeks to byte position offset.
static mpc_bool_t impc_seek(mpc_reader *p_reader, mpc_int32_t offset)
{
Stream *fw = (Stream*)(p_reader->data);
try
{
fw->seek(offset, SEEK_SET);
return(MPC_TRUE);
}
catch(...)
{
return(MPC_FALSE);
}
}
/// Returns the current byte offset in the stream.
static mpc_int32_t impc_tell(mpc_reader *p_reader)
{
Stream *fw = (Stream*)(p_reader->data);
try
{
return fw->tell();
}
catch(...)
{
return(MPC_STATUS_FAIL);
}
}
/// Returns the total length of the source stream, in bytes.
static mpc_int32_t impc_get_size(mpc_reader *p_reader)
{
Stream *fw = (Stream*)(p_reader->data);
try
{
return fw->size();
}
catch(...)
{
return(MPC_STATUS_FAIL);
}
}
/// True if the stream is a seekable stream.
static mpc_bool_t impc_canseek(mpc_reader *p_reader)
{
return(MPC_TRUE);
}
CDAFReader_MPC::CDAFReader_MPC(Stream *fp) : fw(fp)
{
demux = NULL;
memset(&si, 0, sizeof(si));
memset(MPCBuffer, 0, sizeof(MPCBuffer));
MPCBufferOffs = 0;
MPCBufferIn = 0;
memset(&reader, 0, sizeof(reader));
reader.read = impc_read;
reader.seek = impc_seek;
reader.tell = impc_tell;
reader.get_size = impc_get_size;
reader.canseek = impc_canseek;
reader.data = (void*)fp;
if(!(demux = mpc_demux_init(&reader)))
{
throw(0);
}
mpc_demux_get_info(demux, &si);
if(si.channels != 2)
{
mpc_demux_exit(demux);
demux = NULL;
throw MDFN_Error(0, _("MusePack stream has wrong number of channels(%u); the correct number is 2."), si.channels);
}
if(si.sample_freq != 44100)
{
mpc_demux_exit(demux);
demux = NULL;
throw MDFN_Error(0, _("MusePack stream has wrong samplerate(%u Hz); the correct samplerate is 44100 Hz."), si.sample_freq);
}
}
CDAFReader_MPC::~CDAFReader_MPC()
{
if(demux)
{
mpc_demux_exit(demux);
demux = NULL;
}
}
uint64 CDAFReader_MPC::Read_(int16 *buffer, uint64 frames)
{
mpc_status err;
int16 *cowbuf = (int16 *)buffer;
int32 toread = frames * 2;
while(toread > 0)
{
int32 tmplen;
if(!MPCBufferIn)
{
mpc_frame_info fi;
memset(&fi, 0, sizeof(fi));
fi.buffer = MPCBuffer;
if((err = mpc_demux_decode(demux, &fi)) < 0 || fi.bits == -1)
return(frames - toread / 2);
MPCBufferIn = fi.samples * 2;
MPCBufferOffs = 0;
}
tmplen = MPCBufferIn;
if(tmplen >= toread)
tmplen = toread;
for(int x = 0; x < tmplen; x++)
{
#ifdef MPC_FIXED_POINT
int32 samp = MPCBuffer[MPCBufferOffs + x] >> MPC_FIXED_POINT_FRACTPART;
#else
#warning Floating-point MPC decoding path not tested.
int32 samp = (int32)(MPCBuffer[MPCBufferOffs + x] * 32767);
#endif
if(samp < -32768)
samp = -32768;
if(samp > 32767)
samp = 32767;
*cowbuf = (int16)samp;
cowbuf++;
}
MPCBufferOffs += tmplen;
toread -= tmplen;
MPCBufferIn -= tmplen;
}
return(frames - toread / 2);
}
bool CDAFReader_MPC::Seek_(uint64 frame_offset)
{
MPCBufferOffs = 0;
MPCBufferIn = 0;
if(mpc_demux_seek_sample(demux, frame_offset) < 0)
return(false);
return(true);
}
uint64 CDAFReader_MPC::FrameCount(void)
{
return(mpc_streaminfo_get_length_samples(&si));
}
CDAFReader* CDAFR_MPC_Open(Stream* fp)
{
return new CDAFReader_MPC(fp);
}

View File

@ -1,6 +0,0 @@
#ifndef __MDFN_CDAFREADER_MPC_H
#define __MDFN_CDAFREADER_MPC_H
CDAFReader* CDAFR_MPC_Open(Stream* fp);
#endif

View File

@ -1,155 +0,0 @@
/* Mednafen - Multi-system Emulator
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <mednafen/mednafen.h>
#include "CDAFReader.h"
#include "CDAFReader_SF.h"
#include <sndfile.h>
class CDAFReader_SF final : public CDAFReader
{
public:
CDAFReader_SF(Stream *fp);
~CDAFReader_SF();
uint64 Read_(int16 *buffer, uint64 frames) override;
bool Seek_(uint64 frame_offset) override;
uint64 FrameCount(void) override;
private:
SNDFILE *sf;
SF_INFO sfinfo;
SF_VIRTUAL_IO sfvf;
Stream *fw;
};
static sf_count_t isf_get_filelen(void *user_data)
{
Stream *fw = (Stream*)user_data;
try
{
return fw->size();
}
catch(...)
{
return(-1);
}
}
static sf_count_t isf_seek(sf_count_t offset, int whence, void *user_data)
{
Stream *fw = (Stream*)user_data;
try
{
//printf("Seek: offset=%lld, whence=%lld\n", (long long)offset, (long long)whence);
fw->seek(offset, whence);
return fw->tell();
}
catch(...)
{
//printf(" SEEK FAILED\n");
return(-1);
}
}
static sf_count_t isf_read(void *ptr, sf_count_t count, void *user_data)
{
Stream *fw = (Stream*)user_data;
try
{
sf_count_t ret = fw->read(ptr, count, false);
//printf("Read: count=%lld, ret=%lld\n", (long long)count, (long long)ret);
return ret;
}
catch(...)
{
//printf(" READ FAILED\n");
return(0);
}
}
static sf_count_t isf_write(const void *ptr, sf_count_t count, void *user_data)
{
return(0);
}
static sf_count_t isf_tell(void *user_data)
{
Stream *fw = (Stream*)user_data;
try
{
return fw->tell();
}
catch(...)
{
return(-1);
}
}
CDAFReader_SF::CDAFReader_SF(Stream *fp) : fw(fp)
{
memset(&sfvf, 0, sizeof(sfvf));
sfvf.get_filelen = isf_get_filelen;
sfvf.seek = isf_seek;
sfvf.read = isf_read;
sfvf.write = isf_write;
sfvf.tell = isf_tell;
memset(&sfinfo, 0, sizeof(sfinfo));
if(!(sf = sf_open_virtual(&sfvf, SFM_READ, &sfinfo, (void*)fp)))
throw(0);
}
CDAFReader_SF::~CDAFReader_SF()
{
sf_close(sf);
}
uint64 CDAFReader_SF::Read_(int16 *buffer, uint64 frames)
{
return(sf_read_short(sf, (short*)buffer, frames * 2) / 2);
}
bool CDAFReader_SF::Seek_(uint64 frame_offset)
{
// FIXME error condition
if((uint64)sf_seek(sf, frame_offset, SEEK_SET) != frame_offset)
return(false);
return(true);
}
uint64 CDAFReader_SF::FrameCount(void)
{
return(sfinfo.frames);
}
CDAFReader* CDAFR_SF_Open(Stream* fp)
{
return new CDAFReader_SF(fp);
}

View File

@ -1,6 +0,0 @@
#ifndef __MDFN_CDAFREADER_SF_H
#define __MDFN_CDAFREADER_SF_H
CDAFReader* CDAFR_SF_Open(Stream* fp);
#endif

View File

@ -1,158 +0,0 @@
/* Mednafen - Multi-system Emulator
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <mednafen/mednafen.h>
#include "CDAFReader.h"
#include "CDAFReader_Vorbis.h"
#if 0
#include <tremor/ivorbisfile.h>
#else
#include <mednafen/tremor/ivorbisfile.h>
#endif
class CDAFReader_Vorbis final : public CDAFReader
{
public:
CDAFReader_Vorbis(Stream *fp);
~CDAFReader_Vorbis();
uint64 Read_(int16 *buffer, uint64 frames) override;
bool Seek_(uint64 frame_offset) override;
uint64 FrameCount(void) override;
private:
OggVorbis_File ovfile;
Stream *fw;
};
static size_t iov_read_func(void *ptr, size_t size, size_t nmemb, void *user_data)
{
Stream *fw = (Stream*)user_data;
if(!size)
return(0);
try
{
return fw->read(ptr, size * nmemb, false) / size;
}
catch(...)
{
return(0);
}
}
static int iov_seek_func(void *user_data, ogg_int64_t offset, int whence)
{
Stream *fw = (Stream*)user_data;
try
{
fw->seek(offset, whence);
return(0);
}
catch(...)
{
return(-1);
}
}
static int iov_close_func(void *user_data)
{
Stream *fw = (Stream*)user_data;
try
{
fw->close();
return(0);
}
catch(...)
{
return EOF;
}
}
static long iov_tell_func(void *user_data)
{
Stream *fw = (Stream*)user_data;
try
{
return fw->tell();
}
catch(...)
{
return(-1);
}
}
CDAFReader_Vorbis::CDAFReader_Vorbis(Stream *fp) : fw(fp)
{
ov_callbacks cb;
memset(&cb, 0, sizeof(cb));
cb.read_func = iov_read_func;
cb.seek_func = iov_seek_func;
cb.close_func = iov_close_func;
cb.tell_func = iov_tell_func;
if(ov_open_callbacks(fp, &ovfile, NULL, 0, cb))
throw(0);
}
CDAFReader_Vorbis::~CDAFReader_Vorbis()
{
ov_clear(&ovfile);
}
uint64 CDAFReader_Vorbis::Read_(int16 *buffer, uint64 frames)
{
uint8 *tw_buf = (uint8 *)buffer;
int cursection = 0;
long toread = frames * sizeof(int16) * 2;
while(toread > 0)
{
long didread = ov_read(&ovfile, (char*)tw_buf, toread, &cursection);
if(didread == 0)
break;
tw_buf = (uint8 *)tw_buf + didread;
toread -= didread;
}
return(frames - toread / sizeof(int16) / 2);
}
bool CDAFReader_Vorbis::Seek_(uint64 frame_offset)
{
ov_pcm_seek(&ovfile, frame_offset);
return(true);
}
uint64 CDAFReader_Vorbis::FrameCount(void)
{
return(ov_pcm_total(&ovfile, -1));
}
CDAFReader* CDAFR_Vorbis_Open(Stream* fp)
{
return new CDAFReader_Vorbis(fp);
}

View File

@ -1,7 +0,0 @@
#ifndef __MDFN_CDAFREADER_VORBIS_H
#define __MDFN_CDAFREADER_VORBIS_H
CDAFReader* CDAFR_Vorbis_Open(Stream* fp);
#endif

View File

@ -1,46 +0,0 @@
/* Mednafen - Multi-system Emulator
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "emuware/emuware.h"
#include "CDAccess.h"
#include "CDAccess_Image.h"
#include "CDAccess_CCD.h"
using namespace CDUtility;
CDAccess::CDAccess()
{
}
CDAccess::~CDAccess()
{
}
CDAccess* CDAccess_Open(const std::string& path, bool image_memcache)
{
CDAccess *ret = NULL;
if(path.size() >= 4 && !strcasecmp(path.c_str() + path.size() - 4, ".ccd"))
ret = new CDAccess_CCD(path, image_memcache);
else
ret = new CDAccess_Image(path, image_memcache);
return ret;
}

View File

@ -1,33 +0,0 @@
#ifndef __MDFN_CDROMFILE_H
#define __MDFN_CDROMFILE_H
#include <stdio.h>
#include <string>
#include "CDUtility.h"
class CDAccess
{
public:
CDAccess();
virtual ~CDAccess();
virtual void Read_Raw_Sector(uint8 *buf, int32 lba) = 0;
// Returns false if the read wouldn't be "fast"(i.e. reading from a disk),
// or if the read can't be done in a thread-safe re-entrant manner.
//
// Writes 96 bytes into pwbuf, and returns 'true' otherwise.
virtual bool Fast_Read_Raw_PW_TSRE(uint8* pwbuf, int32 lba) const noexcept = 0;
virtual void Read_TOC(CDUtility::TOC *toc) = 0;
private:
CDAccess(const CDAccess&); // No copy constructor.
CDAccess& operator=(const CDAccess&); // No assignment operator.
};
CDAccess* CDAccess_Open(const std::string& path, bool image_memcache);
#endif

View File

@ -1,432 +0,0 @@
/* Mednafen - Multi-system Emulator
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
//#define CHECK_CCD_GARBAGE_CUBQ_A
//#define CHECK_CCD_GARBAGE_CUBQ_B
//#define CHECK_CCD_GARBAGE_CUBQ_C
//#define CHECK_CCD_GARBAGE_CUBQ_D
#include "emuware/emuware.h"
#include "../general.h"
#include "../string/trim.h"
#include "CDAccess_CCD.h"
#include <trio/trio.h>
//wrapper to repair gettext stuff
#define _(X) X
#include <limits>
#include <limits.h>
#include <map>
using namespace CDUtility;
static void MDFN_strtoupper(std::string &str)
{
const size_t len = str.length();
for(size_t x = 0; x < len; x++)
{
if(str[x] >= 'a' && str[x] <= 'z')
{
str[x] = str[x] - 'a' + 'A';
}
}
}
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);
if(zit == s.end())
{
if(have_defval)
return defval;
else
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 char *vp = v.c_str() + scan_offset;
char *ep = NULL;
if(std::numeric_limits<T>::is_signed)
ret = strtol(vp, &ep, scan_base);
else
ret = strtoul(vp, &ep, scan_base);
if(!vp[0] || ep[0])
{
throw MDFN_Error(0, _("Property %s: Malformed integer: %s"), propname.c_str(), v.c_str());
}
//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 std::string& path, bool image_memcache) : img_numsectors(0)
{
Load(path, image_memcache);
}
void CDAccess_CCD::Load(const std::string& 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 };
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];
trio_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;
tocd.tracks[point].valid = true;
}
else switch(point)
{
default:
throw MDFN_Error(0, "Unsupported TOC entry Point value: %u", point);
break;
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;
tocd.tracks[100].valid = true;
break;
}
}
}
//
// Open image stream.
{
std::string image_path = MDFN_EvalFIP(dir_path, file_base + std::string(".") + std::string(img_extsd), true);
if(image_memcache)
{
img_stream.reset(new MemoryStream(new FileStream(image_path, FileStream::MODE_READ)));
}
else
{
img_stream.reset(new FileStream(image_path, FileStream::MODE_READ));
}
uint64 ss = img_stream->size();
if(ss % 2352)
throw MDFN_Error(0, _("CCD image size is not evenly divisible by 2352."));
if(ss > 0x7FFFFFFF)
throw MDFN_Error(0, _("CCD image is too large."));
img_numsectors = ss / 2352;
}
//
// Open subchannel stream
{
std::string sub_path = MDFN_EvalFIP(dir_path, file_base + std::string(".") + std::string(sub_extsd), true);
FileStream sub_stream(sub_path, FileStream::MODE_READ);
if(sub_stream.size() != (uint64)img_numsectors * 96)
throw MDFN_Error(0, _("CCD SUB file size mismatch."));
sub_data.reset(new uint8[(uint64)img_numsectors * 96]);
sub_stream.read(sub_data.get(), (uint64)img_numsectors * 96);
}
CheckSubQSanity();
}
//
// Checks for Q subchannel mode 1(current time) data that has a correct checksum, but the data is nonsensical or corrupted nonetheless; this is the
// case for some bad rips floating around on the Internet. Allowing these bad rips to be used will cause all sorts of problems during emulation, so we
// error out here if a bad rip is detected.
//
// This check is not as aggressive or exhaustive as it could be, and will not detect all potential Q subchannel rip errors; as such, it should definitely NOT be
// used in an effort to "repair" a broken rip.
//
void CDAccess_CCD::CheckSubQSanity(void)
{
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
{
uint8 pbuf[12];
uint8 qbuf[12];
};
} buf;
memcpy(buf.full, &sub_data[s * 96], 96);
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];
//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)
{
#ifdef CHECK_CCD_GARBAGE_SUBQ_A
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);
#endif
}
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);
#ifdef CHECK_CCD_GARBAGE_SUBQ_B
if(prev_lba != INT_MAX && abs(lba - prev_lba) > 100)
throw MDFN_Error(0, _("Garbage subchannel Q data detected(excessively large jump in AMSF)"));
#endif
#ifdef CHECK_CCD_GARBAGE_SUBQ_C
if(abs(lba - (int)s) > 100) //zero 19-jun-2015 a bit of a sneaky signed/unsigned fixup here
throw MDFN_Error(0, _("Garbage subchannel Q data detected(AMSF value is out of tolerance)"));
#endif
prev_lba = lba;
#ifdef CHECK_CCD_GARBAGE_SUBQ_D
if(track < prev_track)
throw MDFN_Error(0, _("Garbage subchannel Q data detected(bad track number)"));
#endif
//else if(prev_track && track - pre
prev_track = track;
}
checksum_pass_counter++;
}
}
}
//printf("%u/%u\n", checksum_pass_counter, img_numsectors);
}
CDAccess_CCD::~CDAccess_CCD()
{
}
void CDAccess_CCD::Read_Raw_Sector(uint8 *buf, int32 lba)
{
if(lba < 0)
{
synth_udapp_sector_lba(0xFF, tocd, lba, 0, buf);
return;
}
if((size_t)lba >= img_numsectors)
{
synth_leadout_sector_lba(0xFF, tocd, lba, buf);
return;
}
img_stream->seek(lba * 2352, SEEK_SET);
img_stream->read(buf, 2352);
subpw_interleave(&sub_data[lba * 96], buf + 2352);
}
bool CDAccess_CCD::Fast_Read_Raw_PW_TSRE(uint8* pwbuf, int32 lba) const noexcept
{
if(lba < 0)
{
subpw_synth_udapp_lba(tocd, lba, 0, pwbuf);
return true;
}
if((size_t)lba >= img_numsectors)
{
subpw_synth_leadout_lba(tocd, lba, pwbuf);
return true;
}
subpw_interleave(&sub_data[lba * 96], pwbuf);
return true;
}
void CDAccess_CCD::Read_TOC(CDUtility::TOC *toc)
{
*toc = tocd;
}

View File

@ -1,48 +0,0 @@
/* Mednafen - Multi-system Emulator
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "../FileStream.h"
#include "../MemoryStream.h"
#include "CDAccess.h"
#include <memory>
class CDAccess_CCD : public CDAccess
{
public:
CDAccess_CCD(const std::string& path, bool image_memcache);
virtual ~CDAccess_CCD();
virtual void Read_Raw_Sector(uint8 *buf, int32 lba);
virtual bool Fast_Read_Raw_PW_TSRE(uint8* pwbuf, int32 lba) const noexcept;
virtual void Read_TOC(CDUtility::TOC *toc);
private:
void Load(const std::string& path, bool image_memcache);
void Cleanup(void);
void CheckSubQSanity(void);
std::unique_ptr<Stream> img_stream;
std::unique_ptr<uint8[]> sub_data;
size_t img_numsectors;
CDUtility::TOC tocd;
};

File diff suppressed because it is too large Load Diff

View File

@ -1,103 +0,0 @@
#ifndef __MDFN_CDACCESS_IMAGE_H
#define __MDFN_CDACCESS_IMAGE_H
#include <map>
#include <array>
class Stream;
class CDAFReader;
struct CDRFILE_TRACK_INFO
{
int32 LBA;
uint32 DIFormat;
uint8 subq_control;
int32 pregap;
int32 pregap_dv;
int32 postgap;
int32 index[2];
int32 sectors; // Not including pregap sectors!
Stream *fp;
bool FirstFileInstance;
bool RawAudioMSBFirst;
long FileOffset;
unsigned int SubchannelMode;
uint32 LastSamplePos;
CDAFReader *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
{
public:
CDAccess_Image(const std::string& path, bool image_memcache);
virtual ~CDAccess_Image();
virtual void Read_Raw_Sector(uint8 *buf, int32 lba);
virtual bool Fast_Read_Raw_PW_TSRE(uint8* pwbuf, int32 lba) const noexcept;
virtual void Read_TOC(CDUtility::TOC *toc);
private:
int32 NumTracks;
int32 FirstTrack;
int32 LastTrack;
int32 total_sectors;
uint8 disc_type;
CDRFILE_TRACK_INFO Tracks[100]; // Track #0(HMM?) through 99
CDUtility::TOC toc;
std::map<uint32, std::array<uint8, 12>> SubQReplaceMap;
std::string base_dir;
void ImageOpen(const std::string& path, bool image_memcache);
void LoadSBI(const std::string& sbi_path);
void GenerateTOC(void);
void Cleanup(void);
// MakeSubPQ will OR the simulated P and Q subchannel data into SubPWBuf.
int32 MakeSubPQ(int32 lba, uint8 *SubPWBuf) const;
void ParseTOCFileLineInfo(CDRFILE_TRACK_INFO *track, const int tracknum, const std::string &filename, const char *binoffset, const char *msfoffset, const char *length, bool image_memcache, std::map<std::string, Stream*> &toc_streamcache);
uint32 GetSectorCount(CDRFILE_TRACK_INFO *track);
};
#endif

View File

@ -1,456 +0,0 @@
/* Mednafen - Multi-system Emulator
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#define EXTERNAL_LIBCDIO_CONFIG_H 1
#include "../mednafen.h"
#include "../general.h"
#include "CDAccess.h"
#include "CDAccess_Physical.h"
#include <time.h>
#include <stdlib.h>
#include <string>
#include <vector>
#include <cdio/cdio.h>
#include <cdio/mmc.h>
#include <cdio/logging.h>
#if LIBCDIO_VERSION_NUM >= 83
#include <cdio/mmc_cmds.h>
#endif
using namespace CDUtility;
static bool Logging = false;
static std::string LogMessage;
static void LogHandler(cdio_log_level_t level, const char message[])
{
if(!Logging)
return;
try
{
if(LogMessage.size() > 0)
LogMessage.append(" - ");
LogMessage.append(message);
}
catch(...) // Don't throw exceptions through libcdio's code.
{
LogMessage.clear();
}
}
static INLINE void StartLogging(void)
{
Logging = true;
LogMessage.clear();
}
static INLINE void ClearLogging(void)
{
LogMessage.clear();
}
static INLINE std::string StopLogging(void)
{
std::string ret = LogMessage;
Logging = false;
LogMessage.clear();
return(ret);
}
void CDAccess_Physical::DetermineFeatures(void)
{
uint8 buf[256];
mmc_cdb_t cdb = {{0, }};
CDIO_MMC_SET_COMMAND(cdb.field, CDIO_MMC_GPCMD_MODE_SENSE_10);
memset(buf, 0, sizeof(buf));
cdb.field[2] = 0x2A;
cdb.field[7] = sizeof(buf) >> 8;
cdb.field[8] = sizeof(buf) & 0xFF;
StartLogging();
if(mmc_run_cmd ((CdIo *)p_cdio, MMC_TIMEOUT_DEFAULT,
&cdb,
SCSI_MMC_DATA_READ,
sizeof(buf),
buf))
{
throw(MDFN_Error(0, _("MMC [MODE SENSE 10] command failed: %s"), StopLogging().c_str()));
}
else
{
const uint8 *pd = &buf[8];
StopLogging();
if(pd[0] != 0x2A || pd[1] < 0x14)
{
throw(MDFN_Error(0, _("MMC [MODE SENSE 10] command returned bogus data for mode page 0x2A.")));
}
if(!(pd[4] & 0x10))
{
throw(MDFN_Error(0, _("Drive does not support reading Mode 2 Form 1 sectors.")));
}
if(!(pd[4] & 0x20))
{
throw(MDFN_Error(0, _("Drive does not support reading Mode 2 Form 2 sectors.")));
}
if(!(pd[5] & 0x01))
{
throw(MDFN_Error(0, _("Reading CD-DA sectors via \"READ CD\" is not supported.")));
}
if(!(pd[5] & 0x02))
{
throw(MDFN_Error(0, _("Read CD-DA sectors via \"READ CD\" are not positionally-accurate.")));
}
if(!(pd[5] & 0x04))
{
throw(MDFN_Error(0, _("Reading raw subchannel data via \"READ CD\" is not supported.")));
}
}
}
void CDAccess_Physical::PreventAllowMediumRemoval(bool prevent)
{
#if 0
mmc_cdb_t cdb = {{0, }};
uint8 buf[8];
cdb.field[0] = 0x1E;
cdb.field[1] = 0x00;
cdb.field[2] = 0x00;
cdb.field[3] = 0x00;
cdb.field[4] = 0x00; //prevent;
cdb.field[5] = 0x00;
printf("%d\n", mmc_run_cmd_len (p_cdio, MMC_TIMEOUT_DEFAULT,
&cdb, 6,
SCSI_MMC_DATA_READ, 0, buf));
assert(0);
#endif
}
// To be used in the future for constructing semi-raw TOC data.
#if 0
static uint8 cond_hex_to_bcd(uint8 val)
{
if( ((val & 0xF) > 0x9) || ((val & 0xF0) > 0x90) )
return val;
return U8_to_BCD(val);
}
#endif
void CDAccess_Physical::ReadPhysDiscInfo(unsigned retry)
{
mmc_cdb_t cdb = {{0, }};
std::vector<uint8> toc_buffer;
int64 start_time = time(NULL);
int cdio_rc;
toc_buffer.resize(0x3FFF); // (2**(8 * 2 - 1 - 1)) - 1, in case the drive has buggy firmware which chops upper bits off or overflows with values near
// the max of a 16-bit signed value
cdb.field[0] = 0x43; // Read TOC
cdb.field[1] = 0x00;
cdb.field[2] = 0x02; // Format 0010b
cdb.field[3] = 0x00;
cdb.field[4] = 0x00;
cdb.field[5] = 0x00;
cdb.field[6] = 0x01; // First session number
cdb.field[7] = toc_buffer.size() >> 8;
cdb.field[8] = toc_buffer.size() & 0xFF;
cdb.field[9] = 0x00;
StartLogging();
while((cdio_rc = mmc_run_cmd ((CdIo *)p_cdio, MMC_TIMEOUT_DEFAULT,
&cdb,
SCSI_MMC_DATA_READ,
toc_buffer.size(),
&toc_buffer[0])))
{
if(!retry || time(NULL) >= (start_time + retry))
{
throw(MDFN_Error(0, _("Error reading disc TOC: %s"), StopLogging().c_str()));
}
else
ClearLogging();
}
StopLogging();
PhysTOC.Clear();
{
int32 len_counter = MDFN_de16msb(&toc_buffer[0]) - 2;
uint8 *tbi = &toc_buffer[4];
if(len_counter < 0 || (len_counter % 11) != 0)
throw MDFN_Error(0, _("READ TOC command response data is of an invalid length."));
while(len_counter)
{
// Ref: MMC-3 draft revision 10g, page 221
uint8 sess MDFN_NOWARN_UNUSED = tbi[0];
uint8 adr_ctrl = tbi[1];
uint8 tno MDFN_NOWARN_UNUSED = tbi[2];
uint8 point = tbi[3];
uint8 min MDFN_NOWARN_UNUSED = tbi[4];
uint8 sec MDFN_NOWARN_UNUSED = tbi[5];
uint8 frame MDFN_NOWARN_UNUSED = tbi[6];
uint8 hour_phour MDFN_NOWARN_UNUSED = tbi[7];
uint8 pmin = tbi[8];
uint8 psec = tbi[9];
uint8 pframe = tbi[10];
if((adr_ctrl >> 4) == 1)
{
switch(((adr_ctrl >> 4) << 8) | point)
{
case 0x101 ... 0x163:
PhysTOC.tracks[point].adr = adr_ctrl >> 4;
PhysTOC.tracks[point].control = adr_ctrl & 0xF;
PhysTOC.tracks[point].lba = AMSF_to_LBA(pmin, psec, pframe);
break;
case 0x1A0:
PhysTOC.first_track = pmin;
PhysTOC.disc_type = psec;
break;
case 0x1A1:
PhysTOC.last_track = pmin;
break;
case 0x1A2:
PhysTOC.tracks[100].adr = adr_ctrl >> 4;
PhysTOC.tracks[100].control = adr_ctrl & 0xF;
PhysTOC.tracks[100].lba = AMSF_to_LBA(pmin, psec, pframe);
break;
default:
//MDFN_printf("%02x %02x\n", adr_ctrl >> 4, point);
break;
}
}
tbi += 11;
len_counter -= 11;
}
}
if(PhysTOC.first_track < 1 || PhysTOC.first_track > 99)
{
throw(MDFN_Error(0, _("Invalid first track: %d\n"), PhysTOC.first_track));
}
if(PhysTOC.last_track > 99 || PhysTOC.last_track < PhysTOC.first_track)
{
throw(MDFN_Error(0, _("Invalid last track: %d\n"), PhysTOC.last_track));
}
// Convenience leadout track duplication.
if(PhysTOC.last_track < 99)
PhysTOC.tracks[PhysTOC.last_track + 1] = PhysTOC.tracks[100];
}
void CDAccess_Physical::Read_TOC(TOC *toc)
{
*toc = PhysTOC;
}
void CDAccess_Physical::Read_Raw_Sector(uint8 *buf, int32 lba)
{
mmc_cdb_t cdb = {{0, }};
int cdio_rc;
CDIO_MMC_SET_COMMAND(cdb.field, CDIO_MMC_GPCMD_READ_CD);
CDIO_MMC_SET_READ_TYPE (cdb.field, CDIO_MMC_READ_TYPE_ANY);
CDIO_MMC_SET_READ_LBA (cdb.field, lba);
CDIO_MMC_SET_READ_LENGTH24(cdb.field, 1);
StartLogging();
if(SkipSectorRead[(lba >> 3) & 0xFFFF] & (1 << (lba & 7)))
{
printf("Read(skipped): %d\n", lba);
memset(buf, 0, 2352);
cdb.field[9] = 0x00;
cdb.field[10] = 0x01;
if((cdio_rc = mmc_run_cmd ((CdIo *)p_cdio, MMC_TIMEOUT_DEFAULT,
&cdb,
SCSI_MMC_DATA_READ,
96,
buf + 2352)))
{
throw(MDFN_Error(0, _("MMC Read Error: %s"), StopLogging().c_str()));
}
}
else
{
cdb.field[9] = 0xF8;
cdb.field[10] = 0x01;
if((cdio_rc = mmc_run_cmd ((CdIo *)p_cdio, MMC_TIMEOUT_DEFAULT,
&cdb,
SCSI_MMC_DATA_READ,
2352 + 96,
buf)))
{
throw(MDFN_Error(0, _("MMC Read Error: %s"), StopLogging().c_str()));
}
}
StopLogging();
}
CDAccess_Physical::CDAccess_Physical(const std::string& path)
{
char **devices = NULL;
char **parseit = NULL;
p_cdio = NULL;
cdio_init();
cdio_log_set_handler(LogHandler);
//
//
//
try
{
devices = cdio_get_devices(DRIVER_DEVICE);
parseit = devices;
if(parseit)
{
MDFN_printf(_("Connected physical devices:\n"));
MDFN_indent(1);
while(*parseit)
{
MDFN_printf("%s\n", *parseit);
parseit++;
}
MDFN_indent(-1);
}
if(!parseit || parseit == devices)
{
throw(MDFN_Error(0, _("No CDROM drives detected(or no disc present).")));
}
if(devices)
{
cdio_free_device_list(devices);
devices = NULL;
}
StartLogging();
p_cdio = cdio_open_cd(path.c_str());
if(!p_cdio)
{
throw(MDFN_Error(0, _("Error opening physical CD: %s"), StopLogging().c_str()));
}
StopLogging();
//PreventAllowMediumRemoval(true);
ReadPhysDiscInfo(0);
//
// Determine how we can read this CD.
//
DetermineFeatures();
memset(SkipSectorRead, 0, sizeof(SkipSectorRead));
}
catch(std::exception &e)
{
if(devices)
cdio_free_device_list(devices);
if(p_cdio)
cdio_destroy((CdIo *)p_cdio);
throw;
}
}
CDAccess_Physical::~CDAccess_Physical()
{
cdio_destroy((CdIo *)p_cdio);
}
bool CDAccess_Physical::Is_Physical(void) throw()
{
return(true);
}
void CDAccess_Physical::Eject(bool eject_status)
{
int cdio_rc;
StartLogging();
#if LIBCDIO_VERSION_NUM >= 83
if((cdio_rc = mmc_start_stop_unit((CdIo *)p_cdio, eject_status, false, 0, 0)) != 0)
{
if(cdio_rc != DRIVER_OP_UNSUPPORTED) // Don't error out if it's just an unsupported operation.
throw(MDFN_Error(0, _("Error ejecting medium: %s"), StopLogging().c_str()));
}
#else
if((cdio_rc = mmc_start_stop_media((CdIo *)p_cdio, eject_status, false, 0)) != 0)
{
if(cdio_rc != DRIVER_OP_UNSUPPORTED) // Don't error out if it's just an unsupported operation.
throw(MDFN_Error(0, _("Error ejecting medium: %s"), StopLogging().c_str()));
}
#endif
StopLogging();
if(!eject_status)
{
try
{
ReadPhysDiscInfo(10);
}
catch(std::exception &e)
{
#if LIBCDIO_VERSION_NUM >= 83
mmc_start_stop_unit((CdIo *)p_cdio, true, false, 0, 0); // Eject disc, if possible.
#else
mmc_start_stop_media((CdIo *)p_cdio, true, false, 0); // Eject disc, if possible.
#endif
throw;
}
}
}

View File

@ -1,39 +0,0 @@
#ifndef __MDFN_CDACCESS_PHYSICAL_H
#define __MDFN_CDACCESS_PHYSICAL_H
//
// This class's methods are NOT re-entrant!
//
// Don't include <cdio.h> here, else it will pollute with its #define's.
class CDAccess_Physical : public CDAccess
{
public:
CDAccess_Physical(const std::string& path);
virtual ~CDAccess_Physical();
virtual void Read_Raw_Sector(uint8 *buf, int32 lba);
virtual void Read_TOC(CDUtility::TOC *toc);
virtual bool Is_Physical(void) throw();
virtual void Eject(bool eject_status);
private:
void *p_cdio;
void DetermineFeatures(void);
void ReadPhysDiscInfo(unsigned retry);
void PreventAllowMediumRemoval(bool prevent);
CDUtility::TOC PhysTOC;
// TODO: 1-bit per sector on the physical CD. If set, don't read that sector.
uint8 SkipSectorRead[65536];
};
#endif

View File

@ -1,435 +0,0 @@
/* Mednafen - Multi-system Emulator
*
* Subchannel Q CRC Code: Copyright (C) 1998 Andreas Mueller <mueller@daneb.ping.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <string.h>
#include <assert.h>
#include "emuware/emuware.h"
#include "CDUtility.h"
#include "dvdisaster.h"
#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
};
static uint8 scramble_table[2352 - 12];
static bool CDUtility_Inited = false;
static void InitScrambleTable(void)
{
unsigned cv = 1;
for(unsigned i = 12; i < 2352; i++)
{
unsigned char z = 0;
for(int b = 0; b < 8; b++)
{
z |= (cv & 1) << b;
int feedback = ((cv >> 1) & 1) ^ (cv & 1);
cv = (cv >> 1) | (feedback << 14);
}
scramble_table[i - 12] = z;
}
//for(int i = 0; i < 2352 - 12; i++)
// printf("0x%02x, ", scramble_table[i]);
}
void CDUtility_Init(void)
{
if(!CDUtility_Inited)
{
Init_LEC_Correct();
InitScrambleTable();
CDUtility_Inited = true;
}
}
void encode_mode0_sector(uint32 aba, uint8 *sector_data)
{
CDUtility_Init();
lec_encode_mode0_sector(aba, sector_data);
}
void encode_mode1_sector(uint32 aba, uint8 *sector_data)
{
CDUtility_Init();
lec_encode_mode1_sector(aba, sector_data);
}
void encode_mode2_sector(uint32 aba, uint8 *sector_data)
{
CDUtility_Init();
lec_encode_mode2_sector(aba, sector_data);
}
void encode_mode2_form1_sector(uint32 aba, uint8 *sector_data)
{
CDUtility_Init();
lec_encode_mode2_form1_sector(aba, sector_data);
}
void encode_mode2_form2_sector(uint32 aba, uint8 *sector_data)
{
CDUtility_Init();
lec_encode_mode2_form2_sector(aba, sector_data);
}
bool edc_check(const uint8 *sector_data, bool xa)
{
CDUtility_Init();
return(CheckEDC(sector_data, xa));
}
bool edc_lec_check_and_correct(uint8 *sector_data, bool xa)
{
CDUtility_Init();
return(ValidateRawSector(sector_data, xa));
}
bool subq_check_checksum(const uint8 *SubQBuf)
{
uint16 crc = 0;
uint16 stored_crc = 0;
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);
crc = ~crc;
return(crc == stored_crc);
}
void subq_generate_checksum(uint8 *buf)
{
uint16 crc = 0;
for(int i = 0; i < 0xA; i++)
crc = subq_crctab[(crc >> 8) ^ buf[i]] ^ (crc << 8);
// Checksum
buf[0xa] = ~(crc >> 8);
buf[0xb] = ~(crc);
}
void subq_deinterleave(const uint8 *SubPWBuf, uint8 *qbuf)
{
memset(qbuf, 0, 0xC);
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);
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));
}
}
}
// 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);
for(unsigned d = 0; d < 12; d++)
{
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;
}
}
}
// NOTES ON LEADOUT AREA SYNTHESIS
//
// I'm not trusting that the "control" field for the TOC leadout entry will always be set properly, so | the control fields for the last track entry
// and the leadout entry together before extracting the D2 bit. Audio track->data leadout is fairly benign though maybe noisy(especially if we ever implement
// data scrambling properly), but data track->audio leadout could break things in an insidious manner for the more accurate drive emulation code).
//
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;
lba_relative = lba - toc.tracks[100].lba;
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);
uint8 adr = 0x1; // Q channel data encodes position
uint8 control = toc.tracks[100].control;
if(toc.tracks[toc.last_track].valid)
control |= toc.tracks[toc.last_track].control & 0x4;
else if(toc.disc_type == DISC_TYPE_CD_I)
control |= 0x4;
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);
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);
subq_generate_checksum(buf);
for(int i = 0; i < 96; i++)
SubPWBuf[i] = (((buf[i >> 3] >> (7 - (i & 0x7))) & 1) ? 0x40 : 0x00) | 0x80;
}
void synth_leadout_sector_lba(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);
if(out_buf[2352 + 1] & 0x40)
{
if(mode == 0xFF)
{
if(toc.disc_type == DISC_TYPE_CD_XA || toc.disc_type == DISC_TYPE_CD_I)
mode = 0x02;
else
mode = 0x01;
}
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 0x02:
out_buf[12 + 6] = 0x20;
out_buf[12 + 10] = 0x20;
encode_mode2_form2_sector(LBA_to_ABA(lba), out_buf);
break;
}
}
}
// ISO/IEC 10149:1995 (E): 20.2
//
void subpw_synth_udapp_lba(const TOC& toc, const int32 lba, const int32 lba_subq_relative_offs, uint8* SubPWBuf)
{
uint8 buf[0xC];
uint32 lba_relative;
uint32 ma, sa, fa;
uint32 m, s, f;
if(lba < -150 || lba >= 0)
printf("[BUG] subpw_synth_udapp_lba() lba out of range --- %d\n", lba);
{
int32 lba_tmp = lba + lba_subq_relative_offs;
if(lba_tmp < 0)
lba_relative = 0 - 1 - lba_tmp;
else
lba_relative = lba_tmp - 0;
}
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);
uint8 adr = 0x1; // Q channel data encodes position
uint8 control;
if(toc.disc_type == DISC_TYPE_CD_I && toc.first_track > 1)
control = 0x4;
else if(toc.tracks[toc.first_track].valid)
control = toc.tracks[toc.first_track].control;
else
control = 0x0;
memset(buf, 0, 0xC);
buf[0] = (adr << 0) | (control << 4);
buf[1] = U8_to_BCD(toc.first_track);
buf[2] = U8_to_BCD(0x00);
// 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
// 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);
for(int i = 0; i < 96; i++)
SubPWBuf[i] = (((buf[i >> 3] >> (7 - (i & 0x7))) & 1) ? 0x40 : 0x00) | 0x80;
}
void synth_udapp_sector_lba(uint8 mode, const TOC& toc, const int32 lba, int32 lba_subq_relative_offs, uint8* out_buf)
{
memset(out_buf, 0, 2352 + 96);
subpw_synth_udapp_lba(toc, lba, lba_subq_relative_offs, out_buf + 2352);
if(out_buf[2352 + 1] & 0x40)
{
if(mode == 0xFF)
{
if(toc.disc_type == DISC_TYPE_CD_XA || toc.disc_type == DISC_TYPE_CD_I)
mode = 0x02;
else
mode = 0x01;
}
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 0x02:
out_buf[12 + 6] = 0x20;
out_buf[12 + 10] = 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];
}
}

View File

@ -1,234 +0,0 @@
#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
{
ADR_NOQINFO = 0x00,
ADR_CURPOS = 0x01,
ADR_MCN = 0x02,
ADR_ISRC = 0x03
};
struct TOC_Track
{
uint8 adr;
uint8 control;
uint32 lba;
bool valid; // valid/present; oh CD-i...
};
// 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) const
{
int32 lvt = 0;
for(int32 track = 1; track <= 100; track++)
{
if(!tracks[track].valid)
continue;
if(LBA < tracks[track].lba)
break;
lvt = track;
}
return(lvt);
}
uint8 first_track;
uint8 last_track;
uint8 disc_type;
TOC_Track tracks[100 + 1]; // [0] is unused, [100] is for the leadout track.
};
//
// 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
// User data area pre-pause(MSF 00:00:00 through 00:01:74), lba -150 through -1
// out_buf must be able to contain 2352+96 bytes.
// "mode" is not used if the area is to be encoded as audio.
// pass 0xFF for "mode" for "don't know", and to make guess based on the TOC.
void synth_udapp_sector_lba(uint8 mode, const TOC& toc, const int32 lba, int32 lba_subq_relative_offs, uint8* out_buf);
void subpw_synth_udapp_lba(const TOC& toc, const int32 lba, const int32 lba_subq_relative_offs, uint8* SubPWBuf);
// out_buf must be able to contain 2352+96 bytes.
// "mode" is not used if the area is to be encoded as audio.
// pass 0xFF for "mode" for "don't know", and to make guess based on the TOC.
void synth_leadout_sector_lba(uint8 mode, const TOC& toc, const int32 lba, uint8* out_buf);
void subpw_synth_leadout_lba(const TOC& toc, const int32 lba, uint8* SubPWBuf);
//
// 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);
}
#endif

View File

@ -1,11 +0,0 @@
mednafen_SOURCES += cdrom/cdromif.cpp cdrom/scsicd.cpp
mednafen_SOURCES += cdrom/CDUtility.cpp cdrom/crc32.cpp cdrom/galois.cpp cdrom/l-ec.cpp cdrom/recover-raw.cpp
mednafen_SOURCES += cdrom/lec.cpp cdrom/CDAccess.cpp cdrom/CDAccess_Image.cpp cdrom/CDAccess_CCD.cpp
mednafen_SOURCES += cdrom/CDAFReader.cpp
mednafen_SOURCES += cdrom/CDAFReader_Vorbis.cpp
mednafen_SOURCES += cdrom/CDAFReader_MPC.cpp
if HAVE_LIBSNDFILE
mednafen_SOURCES += cdrom/CDAFReader_SF.cpp
endif

View File

@ -1,140 +0,0 @@
#ifndef __MDFN_SIMPLEFIFO_H
#define __MDFN_SIMPLEFIFO_H
#include <vector>
#include <assert.h>
#include "../math_ops.h"
template<typename T>
class SimpleFIFO
{
public:
// Constructor
SimpleFIFO(uint32 the_size) // Size should be a power of 2!
{
data.resize(round_up_pow2(the_size));
size = the_size;
read_pos = 0;
write_pos = 0;
in_count = 0;
}
// Destructor
INLINE ~SimpleFIFO()
{
}
INLINE void SaveStatePostLoad(void)
{
read_pos %= data.size();
write_pos %= data.size();
in_count %= (data.size() + 1);
}
#if 0
INLINE int StateAction(StateMem *sm, int load, int data_only, const char* sname)
{
SFORMAT StateRegs[] =
{
std::vector<T> data;
uint32 size;
SFVAR(read_pos),
SFVAR(write_pos),
SFVAR(in_count),
SFEND;
}
int ret = MDFNSS_StateAction(sm, load, data_only, sname);
if(load)
{
read_pos %= data.size();
write_pos %= data.size();
in_count %= (data.size() + 1);
}
return(ret);
}
#endif
INLINE uint32 CanRead(void)
{
return(in_count);
}
INLINE uint32 CanWrite(void)
{
return(size - in_count);
}
INLINE T ReadUnit(bool peek = false)
{
T ret;
assert(in_count > 0);
ret = data[read_pos];
if(!peek)
{
read_pos = (read_pos + 1) & (data.size() - 1);
in_count--;
}
return(ret);
}
INLINE uint8 ReadByte(bool peek = false)
{
assert(sizeof(T) == 1);
return(ReadUnit(peek));
}
INLINE void Write(const T *happy_data, uint32 happy_count)
{
assert(CanWrite() >= happy_count);
while(happy_count)
{
data[write_pos] = *happy_data;
write_pos = (write_pos + 1) & (data.size() - 1);
in_count++;
happy_data++;
happy_count--;
}
}
INLINE void WriteUnit(const T& wr_data)
{
Write(&wr_data, 1);
}
INLINE void WriteByte(const T& wr_data)
{
assert(sizeof(T) == 1);
Write(&wr_data, 1);
}
INLINE void Flush(void)
{
read_pos = 0;
write_pos = 0;
in_count = 0;
}
//private:
std::vector<T> data;
uint32 size;
uint32 read_pos; // Read position
uint32 write_pos; // Write position
uint32 in_count; // Number of units in the FIFO
};
#endif

View File

@ -1,898 +0,0 @@
/* Mednafen - Multi-system Emulator
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <string.h>
#include <sys/types.h>
#include <trio/trio.h>
#include "emuware/emuware.h"
#include "cdromif.h"
#include "CDAccess.h"
#include "general.h"
#include "error.h"
//undo gettext stuff
#define _(X) X
#include <algorithm>
using namespace CDUtility;
enum
{
// Status/Error messages
CDIF_MSG_DONE = 0, // Read -> emu. args: No args.
CDIF_MSG_INFO, // Read -> emu. args: str_message
CDIF_MSG_FATAL_ERROR, // Read -> emu. args: *TODO ARGS*
//
// Command messages.
//
CDIF_MSG_DIEDIEDIE, // Emu -> read
CDIF_MSG_READ_SECTOR, /* Emu -> read
args[0] = lba
*/
};
class CDIF_Message
{
public:
CDIF_Message();
CDIF_Message(unsigned int message_, uint32 arg0 = 0, uint32 arg1 = 0, uint32 arg2 = 0, uint32 arg3 = 0);
CDIF_Message(unsigned int message_, const std::string &str);
~CDIF_Message();
unsigned int message;
uint32 args[4];
void *parg;
std::string str_message;
};
#ifdef WANT_QUEUE
class CDIF_Queue
{
public:
CDIF_Queue();
~CDIF_Queue();
bool Read(CDIF_Message *message, bool blocking = TRUE);
void Write(const CDIF_Message &message);
private:
std::queue<CDIF_Message> ze_queue;
MDFN_Mutex *ze_mutex;
MDFN_Cond *ze_cond;
};
#endif
typedef struct
{
bool valid;
bool error;
int32 lba;
uint8 data[2352 + 96];
} CDIF_Sector_Buffer;
#ifdef WANT_QUEUE
// TODO: prohibit copy constructor
class CDIF_MT : public CDIF
{
public:
CDIF_MT(CDAccess *cda);
virtual ~CDIF_MT();
virtual void HintReadSector(int32 lba);
virtual bool ReadRawSector(uint8 *buf, int32 lba);
virtual bool ReadRawSectorPWOnly(uint8* pwbuf, int32 lba, bool hint_fullread);
// FIXME: Semi-private:
int ReadThreadStart(void);
private:
CDAccess *disc_cdaccess;
MDFN_Thread *CDReadThread;
// Queue for messages to the read thread.
CDIF_Queue ReadThreadQueue;
// Queue for messages to the emu thread.
CDIF_Queue EmuThreadQueue;
enum { SBSize = 256 };
CDIF_Sector_Buffer SectorBuffers[SBSize];
uint32 SBWritePos;
MDFN_Mutex *SBMutex;
MDFN_Cond *SBCond;
//
// Read-thread-only:
//
int32 ra_lba;
int32 ra_count;
int32 last_read_lba;
};
#endif //WANT_QUEUE
// TODO: prohibit copy constructor
class CDIF_ST : public CDIF
{
public:
CDIF_ST(CDAccess *cda);
virtual ~CDIF_ST();
virtual void HintReadSector(int32 lba);
virtual bool ReadRawSector(uint8 *buf, int32 lba);
virtual bool ReadRawSectorPWOnly(uint8* pwbuf, int32 lba, bool hint_fullread);
private:
CDAccess *disc_cdaccess;
};
CDIF::CDIF() : UnrecoverableError(false)
{
}
CDIF::~CDIF()
{
}
CDIF_Message::CDIF_Message()
{
message = 0;
memset(args, 0, sizeof(args));
}
CDIF_Message::CDIF_Message(unsigned int message_, uint32 arg0, uint32 arg1, uint32 arg2, uint32 arg3)
{
message = message_;
args[0] = arg0;
args[1] = arg1;
args[2] = arg2;
args[3] = arg3;
}
CDIF_Message::CDIF_Message(unsigned int message_, const std::string &str)
{
message = message_;
str_message = str;
}
CDIF_Message::~CDIF_Message()
{
}
#ifdef WANT_QUEUE
CDIF_Queue::CDIF_Queue()
{
ze_mutex = MDFND_CreateMutex();
ze_cond = MDFND_CreateCond();
}
CDIF_Queue::~CDIF_Queue()
{
MDFND_DestroyMutex(ze_mutex);
MDFND_DestroyCond(ze_cond);
}
// Returns FALSE if message not read, TRUE if it was read. Will always return TRUE if "blocking" is set.
// Will throw MDFN_Error if the read message code is CDIF_MSG_FATAL_ERROR
bool CDIF_Queue::Read(CDIF_Message *message, bool blocking)
{
bool ret = true;
//
//
//
MDFND_LockMutex(ze_mutex);
if(blocking)
{
while(ze_queue.size() == 0) // while, not just if.
{
MDFND_WaitCond(ze_cond, ze_mutex);
}
}
if(ze_queue.size() == 0)
ret = false;
else
{
*message = ze_queue.front();
ze_queue.pop();
}
MDFND_UnlockMutex(ze_mutex);
//
//
//
if(ret && message->message == CDIF_MSG_FATAL_ERROR)
throw MDFN_Error(0, "%s", message->str_message.c_str());
return(ret);
}
void CDIF_Queue::Write(const CDIF_Message &message)
{
MDFND_LockMutex(ze_mutex);
try
{
ze_queue.push(message);
}
catch(...)
{
fprintf(stderr, "\n\nCDIF_Message queue push failed!!! (We now return you to your regularly unscheduled lockup)\n\n");
}
MDFND_SignalCond(ze_cond); // Signal while the mutex is held to prevent icky race conditions.
MDFND_UnlockMutex(ze_mutex);
}
struct RTS_Args
{
CDIF_MT *cdif_ptr;
};
static int ReadThreadStart_C(void *v_arg)
{
RTS_Args *args = (RTS_Args *)v_arg;
return args->cdif_ptr->ReadThreadStart();
}
int CDIF_MT::ReadThreadStart()
{
bool Running = TRUE;
SBWritePos = 0;
ra_lba = 0;
ra_count = 0;
last_read_lba = LBA_Read_Maximum + 1;
try
{
disc_cdaccess->Read_TOC(&disc_toc);
if(disc_toc.first_track < 1 || disc_toc.last_track > 99 || disc_toc.first_track > disc_toc.last_track)
{
throw(MDFN_Error(0, _("TOC first(%d)/last(%d) track numbers bad."), disc_toc.first_track, disc_toc.last_track));
}
SBWritePos = 0;
ra_lba = 0;
ra_count = 0;
last_read_lba = LBA_Read_Maximum + 1;
memset(SectorBuffers, 0, SBSize * sizeof(CDIF_Sector_Buffer));
}
catch(std::exception &e)
{
EmuThreadQueue.Write(CDIF_Message(CDIF_MSG_FATAL_ERROR, std::string(e.what())));
return(0);
}
EmuThreadQueue.Write(CDIF_Message(CDIF_MSG_DONE));
while(Running)
{
CDIF_Message msg;
// Only do a blocking-wait for a message if we don't have any sectors to read-ahead.
// MDFN_DispMessage("%d %d %d\n", last_read_lba, ra_lba, ra_count);
if(ReadThreadQueue.Read(&msg, ra_count ? FALSE : TRUE))
{
switch(msg.message)
{
case CDIF_MSG_DIEDIEDIE:
Running = FALSE;
break;
case CDIF_MSG_READ_SECTOR:
{
static const int max_ra = 16;
static const int initial_ra = 1;
static const int speedmult_ra = 2;
int32 new_lba = msg.args[0];
assert((unsigned int)max_ra < (SBSize / 4));
if(new_lba == (last_read_lba + 1))
{
int how_far_ahead = ra_lba - new_lba;
if(how_far_ahead <= max_ra)
ra_count = std::min(speedmult_ra, 1 + max_ra - how_far_ahead);
else
ra_count++;
}
else if(new_lba != last_read_lba)
{
ra_lba = new_lba;
ra_count = initial_ra;
}
last_read_lba = new_lba;
}
break;
}
}
//
// Don't read beyond what the disc (image) readers can handle sanely.
//
if(ra_count && ra_lba == LBA_Read_Maximum)
{
ra_count = 0;
//printf("Ephemeral scarabs: %d!\n", ra_lba);
}
if(ra_count)
{
uint8 tmpbuf[2352 + 96];
bool error_condition = false;
try
{
disc_cdaccess->Read_Raw_Sector(tmpbuf, ra_lba);
}
catch(std::exception &e)
{
MDFN_PrintError(_("Sector %u read error: %s"), ra_lba, e.what());
memset(tmpbuf, 0, sizeof(tmpbuf));
error_condition = true;
}
//
//
MDFND_LockMutex(SBMutex);
SectorBuffers[SBWritePos].lba = ra_lba;
memcpy(SectorBuffers[SBWritePos].data, tmpbuf, 2352 + 96);
SectorBuffers[SBWritePos].valid = TRUE;
SectorBuffers[SBWritePos].error = error_condition;
SBWritePos = (SBWritePos + 1) % SBSize;
MDFND_SignalCond(SBCond);
MDFND_UnlockMutex(SBMutex);
//
//
ra_lba++;
ra_count--;
}
}
return(1);
}
CDIF_MT::CDIF_MT(CDAccess *cda) : disc_cdaccess(cda), CDReadThread(NULL), SBMutex(NULL), SBCond(NULL)
{
try
{
CDIF_Message msg;
RTS_Args s;
if(!(SBMutex = MDFND_CreateMutex()))
throw MDFN_Error(0, _("Error creating CD read thread mutex."));
if(!(SBCond = MDFND_CreateCond()))
throw MDFN_Error(0, _("Error creating CD read thread condition variable."));
UnrecoverableError = false;
s.cdif_ptr = this;
if(!(CDReadThread = MDFND_CreateThread(ReadThreadStart_C, &s)))
throw MDFN_Error(0, _("Error creating CD read thread."));
EmuThreadQueue.Read(&msg);
}
catch(...)
{
if(CDReadThread)
{
MDFND_WaitThread(CDReadThread, NULL);
CDReadThread = NULL;
}
if(SBMutex)
{
MDFND_DestroyMutex(SBMutex);
SBMutex = NULL;
}
if(SBCond)
{
MDFND_DestroyCond(SBCond);
SBCond = NULL;
}
if(disc_cdaccess)
{
delete disc_cdaccess;
disc_cdaccess = NULL;
}
throw;
}
}
CDIF_MT::~CDIF_MT()
{
bool thread_deaded_failed = false;
try
{
ReadThreadQueue.Write(CDIF_Message(CDIF_MSG_DIEDIEDIE));
}
catch(std::exception &e)
{
MDFND_PrintError(e.what());
thread_deaded_failed = true;
}
if(!thread_deaded_failed)
MDFND_WaitThread(CDReadThread, NULL);
if(SBMutex)
{
MDFND_DestroyMutex(SBMutex);
SBMutex = NULL;
}
if(SBCond)
{
MDFND_DestroyCond(SBCond);
SBCond = NULL;
}
if(disc_cdaccess)
{
delete disc_cdaccess;
disc_cdaccess = NULL;
}
}
#endif //WANT_QUEUE
bool CDIF::ValidateRawSector(uint8 *buf)
{
int mode = buf[12 + 3];
if(mode != 0x1 && mode != 0x2)
return(false);
if(!edc_lec_check_and_correct(buf, mode == 2))
return(false);
return(true);
}
#ifdef WANT_QUEUE
bool CDIF_MT::ReadRawSector(uint8 *buf, int32 lba)
{
bool found = FALSE;
bool error_condition = false;
if(UnrecoverableError)
{
memset(buf, 0, 2352 + 96);
return(false);
}
if(lba < LBA_Read_Minimum || lba > LBA_Read_Maximum)
{
printf("Attempt to read sector out of bounds; LBA=%d\n", lba);
memset(buf, 0, 2352 + 96);
return(false);
}
ReadThreadQueue.Write(CDIF_Message(CDIF_MSG_READ_SECTOR, lba));
//
//
//
MDFND_LockMutex(SBMutex);
do
{
for(int i = 0; i < SBSize; i++)
{
if(SectorBuffers[i].valid && SectorBuffers[i].lba == lba)
{
error_condition = SectorBuffers[i].error;
memcpy(buf, SectorBuffers[i].data, 2352 + 96);
found = TRUE;
}
}
if(!found)
{
//int32 swt = MDFND_GetTime();
MDFND_WaitCond(SBCond, SBMutex);
//printf("SB Waited: %d\n", MDFND_GetTime() - swt);
}
} while(!found);
MDFND_UnlockMutex(SBMutex);
//
//
//
return(!error_condition);
}
bool CDIF_MT::ReadRawSectorPWOnly(uint8* pwbuf, int32 lba, bool hint_fullread)
{
if(UnrecoverableError)
{
memset(pwbuf, 0, 96);
return(false);
}
if(lba < LBA_Read_Minimum || lba > LBA_Read_Maximum)
{
printf("Attempt to read sector out of bounds; LBA=%d\n", lba);
memset(pwbuf, 0, 96);
return(false);
}
if(disc_cdaccess->Fast_Read_Raw_PW_TSRE(pwbuf, lba))
{
if(hint_fullread)
ReadThreadQueue.Write(CDIF_Message(CDIF_MSG_READ_SECTOR, lba));
return(true);
}
else
{
uint8 tmpbuf[2352 + 96];
bool ret;
ret = ReadRawSector(tmpbuf, lba);
memcpy(pwbuf, tmpbuf + 2352, 96);
return ret;
}
}
void CDIF_MT::HintReadSector(int32 lba)
{
if(UnrecoverableError)
return;
ReadThreadQueue.Write(CDIF_Message(CDIF_MSG_READ_SECTOR, lba));
}
#endif //WANT_QUEUE
int CDIF::ReadSector(uint8* buf, int32 lba, uint32 sector_count, bool suppress_uncorrectable_message)
{
int ret = 0;
if(UnrecoverableError)
return(false);
while(sector_count--)
{
uint8 tmpbuf[2352 + 96];
if(!ReadRawSector(tmpbuf, lba))
{
puts("CDIF Raw Read error");
return(FALSE_0);
}
if(!ValidateRawSector(tmpbuf))
{
if(!suppress_uncorrectable_message)
{
printf(_("Uncorrectable data at sector %d"), lba);
}
return(false);
}
const int mode = tmpbuf[12 + 3];
if(!ret)
ret = mode;
if(mode == 1)
{
memcpy(buf, &tmpbuf[12 + 4], 2048);
}
else if(mode == 2)
{
memcpy(buf, &tmpbuf[12 + 4 + 8], 2048);
}
else
{
printf("CDIF_ReadSector() invalid sector type at LBA=%u\n", (unsigned int)lba);
return(false);
}
buf += 2048;
lba++;
}
return(ret);
}
//
//
// Single-threaded implementation follows.
//
//
CDIF_ST::CDIF_ST(CDAccess *cda) : disc_cdaccess(cda)
{
//puts("***WARNING USING SINGLE-THREADED CD READER***");
UnrecoverableError = false;
disc_cdaccess->Read_TOC(&disc_toc);
if(disc_toc.first_track < 1 || disc_toc.last_track > 99 || disc_toc.first_track > disc_toc.last_track)
{
throw(MDFN_Error(0, _("TOC first(%d)/last(%d) track numbers bad."), disc_toc.first_track, disc_toc.last_track));
}
}
CDIF_ST::~CDIF_ST()
{
if(disc_cdaccess)
{
delete disc_cdaccess;
disc_cdaccess = NULL;
}
}
void CDIF_ST::HintReadSector(int32 lba)
{
// TODO: disc_cdaccess seek hint? (probably not, would require asynchronousitycamel)
}
bool CDIF_ST::ReadRawSector(uint8 *buf, int32 lba)
{
if(UnrecoverableError)
{
memset(buf, 0, 2352 + 96);
return(false);
}
if(lba < LBA_Read_Minimum || lba > LBA_Read_Maximum)
{
printf("Attempt to read sector out of bounds; LBA=%d\n", lba);
memset(buf, 0, 2352 + 96);
return(false);
}
try
{
disc_cdaccess->Read_Raw_Sector(buf, lba);
}
catch(std::exception &e)
{
printf(_("Sector %u read error: %s"), lba, e.what());
memset(buf, 0, 2352 + 96);
return(false);
}
return(true);
}
bool CDIF_ST::ReadRawSectorPWOnly(uint8* pwbuf, int32 lba, bool hint_fullread)
{
if(UnrecoverableError)
{
memset(pwbuf, 0, 96);
return(false);
}
if(lba < LBA_Read_Minimum || lba > LBA_Read_Maximum)
{
printf("Attempt to read sector out of bounds; LBA=%d\n", lba);
memset(pwbuf, 0, 96);
return(false);
}
if(disc_cdaccess->Fast_Read_Raw_PW_TSRE(pwbuf, lba))
return(true);
else
{
uint8 tmpbuf[2352 + 96];
bool ret;
ret = ReadRawSector(tmpbuf, lba);
memcpy(pwbuf, tmpbuf + 2352, 96);
return ret;
}
}
class CDIF_Stream_Thing : public Stream
{
public:
CDIF_Stream_Thing(CDIF *cdintf_arg, uint32 lba_arg, uint32 sector_count_arg);
~CDIF_Stream_Thing();
virtual uint64 attributes(void) override;
virtual uint64 read(void *data, uint64 count, bool error_on_eos = true) override;
virtual void write(const void *data, uint64 count) override;
virtual void truncate(uint64 length) override;
virtual void seek(int64 offset, int whence) override;
virtual uint64 tell(void) override;
virtual uint64 size(void) override;
virtual void flush(void) override;
virtual void close(void) override;
private:
CDIF *cdintf;
const uint32 start_lba;
const uint32 sector_count;
int64 position;
};
CDIF_Stream_Thing::CDIF_Stream_Thing(CDIF *cdintf_arg, uint32 start_lba_arg, uint32 sector_count_arg) : cdintf(cdintf_arg), start_lba(start_lba_arg), sector_count(sector_count_arg)
{
}
CDIF_Stream_Thing::~CDIF_Stream_Thing()
{
}
uint64 CDIF_Stream_Thing::attributes(void)
{
return(ATTRIBUTE_READABLE | ATTRIBUTE_SEEKABLE);
}
uint64 CDIF_Stream_Thing::read(void *data, uint64 count, bool error_on_eos)
{
if(count > (((uint64)sector_count * 2048) - position))
{
if(error_on_eos)
{
throw MDFN_Error(0, "EOF");
}
count = ((uint64)sector_count * 2048) - position;
}
if(!count)
return(0);
for(uint64 rp = position; rp < (position + count); rp = (rp &~ 2047) + 2048)
{
uint8 buf[2048];
if(!cdintf->ReadSector(buf, start_lba + (rp / 2048), 1))
{
throw MDFN_Error(ErrnoHolder(EIO));
}
//::printf("Meow: %08llx -- %08llx\n", count, (rp - position) + std::min<uint64>(2048 - (rp & 2047), count - (rp - position)));
memcpy((uint8*)data + (rp - position), buf + (rp & 2047), std::min<uint64>(2048 - (rp & 2047), count - (rp - position)));
}
position += count;
return count;
}
void CDIF_Stream_Thing::write(const void *data, uint64 count)
{
throw MDFN_Error(ErrnoHolder(EBADF));
}
void CDIF_Stream_Thing::truncate(uint64 length)
{
throw MDFN_Error(ErrnoHolder(EBADF));
}
void CDIF_Stream_Thing::seek(int64 offset, int whence)
{
int64 new_position;
switch(whence)
{
default:
throw MDFN_Error(ErrnoHolder(EINVAL));
break;
case SEEK_SET:
new_position = offset;
break;
case SEEK_CUR:
new_position = position + offset;
break;
case SEEK_END:
new_position = ((int64)sector_count * 2048) + offset;
break;
}
if(new_position < 0 || new_position > ((int64)sector_count * 2048))
throw MDFN_Error(ErrnoHolder(EINVAL));
position = new_position;
}
uint64 CDIF_Stream_Thing::tell(void)
{
return position;
}
uint64 CDIF_Stream_Thing::size(void)
{
return(sector_count * 2048);
}
void CDIF_Stream_Thing::flush(void)
{
}
void CDIF_Stream_Thing::close(void)
{
}
Stream *CDIF::MakeStream(int32 lba, uint32 sector_count)
{
return new CDIF_Stream_Thing(this, lba, sector_count);
}
CDIF *CDIF_Open(const std::string& path, bool image_memcache)
{
CDAccess *cda = CDAccess_Open(path, image_memcache);
#ifdef WANT_QUEUE
if(!image_memcache)
return new CDIF_MT(cda);
else
#endif
return new CDIF_ST(cda);
}

View File

@ -1,66 +0,0 @@
/* Mednafen - Multi-system Emulator
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __MDFN_CDROM_CDROMIF_H
#define __MDFN_CDROM_CDROMIF_H
#include "CDUtility.h"
#include "stream.h"
#include <queue>
typedef CDUtility::TOC CD_TOC;
class CDIF
{
public:
CDIF();
virtual ~CDIF();
static const int32 LBA_Read_Minimum = -150;
static const int32 LBA_Read_Maximum = 449849; // 100 * 75 * 60 - 150 - 1
inline void ReadTOC(CDUtility::TOC *read_target)
{
*read_target = disc_toc;
}
virtual void HintReadSector(int32 lba) = 0;
virtual bool ReadRawSector(uint8 *buf, int32 lba) = 0; // Reads 2352+96 bytes of data into buf.
virtual bool ReadRawSectorPWOnly(uint8* pwbuf, int32 lba, bool hint_fullread) = 0; // Reads 96 bytes(of raw subchannel PW data) into pwbuf.
// Call for mode 1 or mode 2 form 1 only.
bool ValidateRawSector(uint8 *buf);
// Utility/Wrapped functions
// Reads mode 1 and mode2 form 1 sectors(2048 bytes per sector returned)
// Will return the type(1, 2) of the first sector read to the buffer supplied, 0 on error
int ReadSector(uint8* buf, int32 lba, uint32 sector_count, bool suppress_uncorrectable_message = false);
// For Mode 1, or Mode 2 Form 1.
// No reference counting or whatever is done, so if you destroy the CDIF object before you destroy the returned Stream, things will go BOOM.
Stream *MakeStream(int32 lba, uint32 sector_count);
protected:
bool UnrecoverableError;
CDUtility::TOC disc_toc;
};
CDIF *CDIF_Open(const std::string& path, bool image_memcache);
#endif

View File

@ -1,130 +0,0 @@
/* dvdisaster: Additional error correction for optical media.
* Copyright (C) 2004-2007 Carsten Gnoerlich.
* Project home page: http://www.dvdisaster.com
* Email: carsten@dvdisaster.com -or- cgnoerlich@fsfe.org
*
* CRC32 code based upon public domain code by Ross Williams (see notes below)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA,
* or direct your browser at http://www.gnu.org.
*/
#include "dvdisaster.h"
/***
*** EDC checksum used in CDROM sectors
***/
/*****************************************************************/
/* */
/* CRC LOOKUP TABLE */
/* ================ */
/* The following CRC lookup table was generated automagically */
/* by the Rocksoft^tm Model CRC Algorithm Table Generation */
/* Program V1.0 using the following model parameters: */
/* */
/* Width : 4 bytes. */
/* Poly : 0x8001801BL */
/* Reverse : TRUE. */
/* */
/* For more information on the Rocksoft^tm Model CRC Algorithm, */
/* see the document titled "A Painless Guide to CRC Error */
/* Detection Algorithms" by Ross Williams */
/* (ross@guest.adelaide.edu.au.). This document is likely to be */
/* in the FTP archive "ftp.adelaide.edu.au/pub/rocksoft". */
/* */
/*****************************************************************/
unsigned long edctable[256] =
{
0x00000000L, 0x90910101L, 0x91210201L, 0x01B00300L,
0x92410401L, 0x02D00500L, 0x03600600L, 0x93F10701L,
0x94810801L, 0x04100900L, 0x05A00A00L, 0x95310B01L,
0x06C00C00L, 0x96510D01L, 0x97E10E01L, 0x07700F00L,
0x99011001L, 0x09901100L, 0x08201200L, 0x98B11301L,
0x0B401400L, 0x9BD11501L, 0x9A611601L, 0x0AF01700L,
0x0D801800L, 0x9D111901L, 0x9CA11A01L, 0x0C301B00L,
0x9FC11C01L, 0x0F501D00L, 0x0EE01E00L, 0x9E711F01L,
0x82012001L, 0x12902100L, 0x13202200L, 0x83B12301L,
0x10402400L, 0x80D12501L, 0x81612601L, 0x11F02700L,
0x16802800L, 0x86112901L, 0x87A12A01L, 0x17302B00L,
0x84C12C01L, 0x14502D00L, 0x15E02E00L, 0x85712F01L,
0x1B003000L, 0x8B913101L, 0x8A213201L, 0x1AB03300L,
0x89413401L, 0x19D03500L, 0x18603600L, 0x88F13701L,
0x8F813801L, 0x1F103900L, 0x1EA03A00L, 0x8E313B01L,
0x1DC03C00L, 0x8D513D01L, 0x8CE13E01L, 0x1C703F00L,
0xB4014001L, 0x24904100L, 0x25204200L, 0xB5B14301L,
0x26404400L, 0xB6D14501L, 0xB7614601L, 0x27F04700L,
0x20804800L, 0xB0114901L, 0xB1A14A01L, 0x21304B00L,
0xB2C14C01L, 0x22504D00L, 0x23E04E00L, 0xB3714F01L,
0x2D005000L, 0xBD915101L, 0xBC215201L, 0x2CB05300L,
0xBF415401L, 0x2FD05500L, 0x2E605600L, 0xBEF15701L,
0xB9815801L, 0x29105900L, 0x28A05A00L, 0xB8315B01L,
0x2BC05C00L, 0xBB515D01L, 0xBAE15E01L, 0x2A705F00L,
0x36006000L, 0xA6916101L, 0xA7216201L, 0x37B06300L,
0xA4416401L, 0x34D06500L, 0x35606600L, 0xA5F16701L,
0xA2816801L, 0x32106900L, 0x33A06A00L, 0xA3316B01L,
0x30C06C00L, 0xA0516D01L, 0xA1E16E01L, 0x31706F00L,
0xAF017001L, 0x3F907100L, 0x3E207200L, 0xAEB17301L,
0x3D407400L, 0xADD17501L, 0xAC617601L, 0x3CF07700L,
0x3B807800L, 0xAB117901L, 0xAAA17A01L, 0x3A307B00L,
0xA9C17C01L, 0x39507D00L, 0x38E07E00L, 0xA8717F01L,
0xD8018001L, 0x48908100L, 0x49208200L, 0xD9B18301L,
0x4A408400L, 0xDAD18501L, 0xDB618601L, 0x4BF08700L,
0x4C808800L, 0xDC118901L, 0xDDA18A01L, 0x4D308B00L,
0xDEC18C01L, 0x4E508D00L, 0x4FE08E00L, 0xDF718F01L,
0x41009000L, 0xD1919101L, 0xD0219201L, 0x40B09300L,
0xD3419401L, 0x43D09500L, 0x42609600L, 0xD2F19701L,
0xD5819801L, 0x45109900L, 0x44A09A00L, 0xD4319B01L,
0x47C09C00L, 0xD7519D01L, 0xD6E19E01L, 0x46709F00L,
0x5A00A000L, 0xCA91A101L, 0xCB21A201L, 0x5BB0A300L,
0xC841A401L, 0x58D0A500L, 0x5960A600L, 0xC9F1A701L,
0xCE81A801L, 0x5E10A900L, 0x5FA0AA00L, 0xCF31AB01L,
0x5CC0AC00L, 0xCC51AD01L, 0xCDE1AE01L, 0x5D70AF00L,
0xC301B001L, 0x5390B100L, 0x5220B200L, 0xC2B1B301L,
0x5140B400L, 0xC1D1B501L, 0xC061B601L, 0x50F0B700L,
0x5780B800L, 0xC711B901L, 0xC6A1BA01L, 0x5630BB00L,
0xC5C1BC01L, 0x5550BD00L, 0x54E0BE00L, 0xC471BF01L,
0x6C00C000L, 0xFC91C101L, 0xFD21C201L, 0x6DB0C300L,
0xFE41C401L, 0x6ED0C500L, 0x6F60C600L, 0xFFF1C701L,
0xF881C801L, 0x6810C900L, 0x69A0CA00L, 0xF931CB01L,
0x6AC0CC00L, 0xFA51CD01L, 0xFBE1CE01L, 0x6B70CF00L,
0xF501D001L, 0x6590D100L, 0x6420D200L, 0xF4B1D301L,
0x6740D400L, 0xF7D1D501L, 0xF661D601L, 0x66F0D700L,
0x6180D800L, 0xF111D901L, 0xF0A1DA01L, 0x6030DB00L,
0xF3C1DC01L, 0x6350DD00L, 0x62E0DE00L, 0xF271DF01L,
0xEE01E001L, 0x7E90E100L, 0x7F20E200L, 0xEFB1E301L,
0x7C40E400L, 0xECD1E501L, 0xED61E601L, 0x7DF0E700L,
0x7A80E800L, 0xEA11E901L, 0xEBA1EA01L, 0x7B30EB00L,
0xE8C1EC01L, 0x7850ED00L, 0x79E0EE00L, 0xE971EF01L,
0x7700F000L, 0xE791F101L, 0xE621F201L, 0x76B0F300L,
0xE541F401L, 0x75D0F500L, 0x7460F600L, 0xE4F1F701L,
0xE381F801L, 0x7310F900L, 0x72A0FA00L, 0xE231FB01L,
0x71C0FC00L, 0xE151FD01L, 0xE0E1FE01L, 0x7070FF00L
};
/*
* CDROM EDC calculation
*/
uint32 EDCCrc32(const unsigned char *data, int len)
{
uint32 crc = 0;
while(len--)
crc = edctable[(crc ^ *data++) & 0xFF] ^ (crc >> 8);
return crc;
}

View File

@ -1,173 +0,0 @@
/* dvdisaster: Additional error correction for optical media.
* Copyright (C) 2004-2007 Carsten Gnoerlich.
* Project home page: http://www.dvdisaster.com
* Email: carsten@dvdisaster.com -or- cgnoerlich@fsfe.org
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA,
* or direct your browser at http://www.gnu.org.
*/
#ifndef DVDISASTER_H
#define DVDISASTER_H
/* "Dare to be gorgeous and unique.
* But don't ever be cryptic or otherwise unfathomable.
* Make it unforgettably great."
*
* From "A Final Note on Style",
* Amiga Intuition Reference Manual, 1986, p. 231
*/
/***
*** I'm too lazy to mess with #include dependencies.
*** Everything #includeable is rolled up herein...
*/
//#include "../types.h"
#include "emuware/emuware.h"
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <math.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdarg.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//#include <unistd.h>
/***
*** dvdisaster.c
***/
void PrepareDeadSector(void);
void CreateEcc(void);
void FixEcc(void);
void Verify(void);
uint32 EDCCrc32(const unsigned char*, int);
/***
*** galois.c
***
* This is currently the hardcoded GF(2**8).
* int32 gives abundant space for the GF.
* Squeezing it down to uint8 won't probably gain much,
* so we implement this defensively here.
*
* Note that some performance critical stuff needs to
* be #included from galois-inlines.h
*/
/* Galois field parameters for 8bit symbol Reed-Solomon code */
#define GF_SYMBOLSIZE 8
#define GF_FIELDSIZE (1<<GF_SYMBOLSIZE)
#define GF_FIELDMAX (GF_FIELDSIZE-1)
#define GF_ALPHA0 GF_FIELDMAX
/* Lookup tables for Galois field arithmetic */
typedef struct _GaloisTables
{ int32 gfGenerator; /* GF generator polynomial */
int32 *indexOf; /* log */
int32 *alphaTo; /* inverse log */
int32 *encAlphaTo; /* inverse log optimized for encoder */
} GaloisTables;
/* Lookup and working tables for the ReedSolomon codecs */
typedef struct _ReedSolomonTables
{ GaloisTables *gfTables;/* from above */
int32 *gpoly; /* RS code generator polynomial */
int32 fcr; /* first consecutive root of RS generator polynomial */
int32 primElem; /* primitive field element */
int32 nroots; /* degree of RS generator polynomial */
int32 ndata; /* data bytes per ecc block */
} ReedSolomonTables;
GaloisTables* CreateGaloisTables(int32);
void FreeGaloisTables(GaloisTables*);
ReedSolomonTables *CreateReedSolomonTables(GaloisTables*, int32, int32, int);
void FreeReedSolomonTables(ReedSolomonTables*);
/***
*** l-ec.c
***/
#define N_P_VECTORS 86 /* 43 16bit p vectors */
#define P_VECTOR_SIZE 26 /* using RS(26,24) ECC */
#define N_Q_VECTORS 52 /* 26 16bit q vectors */
#define Q_VECTOR_SIZE 45 /* using RS(45,43) ECC */
#define P_PADDING 229 /* padding values for */
#define Q_PADDING 210 /* shortened RS code */
int PToByteIndex(int, int);
int QToByteIndex(int, int);
void ByteIndexToP(int, int*, int*);
void ByteIndexToQ(int, int*, int*);
void GetPVector(unsigned char*, unsigned char*, int);
void SetPVector(unsigned char*, unsigned char*, int);
void FillPVector(unsigned char*, unsigned char, int);
void AndPVector(unsigned char*, unsigned char, int);
void OrPVector(unsigned char*, unsigned char, int);
void GetQVector(unsigned char*, unsigned char*, int);
void SetQVector(unsigned char*, unsigned char*, int);
void FillQVector(unsigned char*, unsigned char, int);
void AndQVector(unsigned char*, unsigned char, int);
void OrQVector(unsigned char*, unsigned char, int);
int DecodePQ(ReedSolomonTables*, unsigned char*, int, int*, int);
int CountC2Errors(unsigned char*);
/***
*** misc.c
***/
char* sgettext(char*);
char* sgettext_utf8(char*);
int64 uchar_to_int64(unsigned char*);
void int64_to_uchar(unsigned char*, int64);
void CalcSectors(int64, int64*, int*);
/***
*** recover-raw.c
***/
#define CD_RAW_SECTOR_SIZE 2352
#define CD_RAW_C2_SECTOR_SIZE (2352+294) /* main channel plus C2 vector */
int CheckEDC(const unsigned char*, bool);
int CheckMSF(unsigned char*, int);
int ValidateRawSector(unsigned char *frame, bool xaMode);
bool Init_LEC_Correct(void);
void Kill_LEC_Correct(void);
#endif /* DVDISASTER_H */

View File

@ -1,40 +0,0 @@
/* dvdisaster: Additional error correction for optical media.
* Copyright (C) 2004-2007 Carsten Gnoerlich.
* Project home page: http://www.dvdisaster.com
* Email: carsten@dvdisaster.com -or- cgnoerlich@fsfe.org
*
* The Reed-Solomon error correction draws a lot of inspiration - and even code -
* from Phil Karn's excellent Reed-Solomon library: http://www.ka9q.net/code/fec/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA,
* or direct your browser at http://www.gnu.org.
*/
#include "dvdisaster.h"
/*
* The following routine is performance critical.
*/
static inline int mod_fieldmax(int x)
{
while (x >= GF_FIELDMAX)
{
x -= GF_FIELDMAX;
x = (x >> GF_SYMBOLSIZE) + (x & GF_FIELDMAX);
}
return x;
}

View File

@ -1,156 +0,0 @@
/* dvdisaster: Additional error correction for optical media.
* Copyright (C) 2004-2007 Carsten Gnoerlich.
* Project home page: http://www.dvdisaster.com
* Email: carsten@dvdisaster.com -or- cgnoerlich@fsfe.org
*
* The Reed-Solomon error correction draws a lot of inspiration - and even code -
* from Phil Karn's excellent Reed-Solomon library: http://www.ka9q.net/code/fec/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA,
* or direct your browser at http://www.gnu.org.
*/
#include "dvdisaster.h"
#include "galois-inlines.h"
/***
*** Galois field arithmetic.
***
* Calculations are done over the extension field GF(2**n).
* Be careful not to overgeneralize these arithmetics;
* they only work for the case of GF(p**n) with p being prime.
*/
/* Initialize the Galois field tables */
GaloisTables* CreateGaloisTables(int32 gf_generator)
{
GaloisTables *gt = (GaloisTables *)calloc(1, sizeof(GaloisTables));
int32 b,log;
/* Allocate the tables.
The encoder uses a special version of alpha_to which has the mod_fieldmax()
folded into the table. */
gt->gfGenerator = 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++)
{ gt->indexOf[b] = log;
gt->alphaTo[log] = b;
b = b << 1;
if(b & GF_FIELDSIZE)
b = b ^ gf_generator;
}
if(b!=1)
{
printf("Failed to create the Galois field log tables!\n");
exit(1);
}
/* we're even closed using infinity (makes things easier) */
gt->indexOf[0] = GF_ALPHA0; /* log(0) = inf */
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)];
return gt;
}
void FreeGaloisTables(GaloisTables *gt)
{
if(gt->indexOf) free(gt->indexOf);
if(gt->alphaTo) free(gt->alphaTo);
if(gt->encAlphaTo) free(gt->encAlphaTo);
free(gt);
}
/***
*** Create the the Reed-Solomon generator polynomial
*** and some auxiliary data structures.
*/
ReedSolomonTables *CreateReedSolomonTables(GaloisTables *gt,
int32 first_consecutive_root,
int32 prim_elem,
int nroots_in)
{ ReedSolomonTables *rt = (ReedSolomonTables *)calloc(1, sizeof(ReedSolomonTables));
int32 i,j,root;
rt->gfTables = gt;
rt->fcr = first_consecutive_root;
rt->primElem = prim_elem;
rt->nroots = nroots_in;
rt->ndata = GF_FIELDMAX - rt->nroots;
rt->gpoly = (int32 *)calloc((rt->nroots+1), sizeof(int32));
/* Create the RS code generator polynomial */
rt->gpoly[0] = 1;
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) */
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)];
}
/* 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
return rt;
}
void FreeReedSolomonTables(ReedSolomonTables *rt)
{
if(rt->gpoly) free(rt->gpoly);
free(rt);
}

View File

@ -1,478 +0,0 @@
/* dvdisaster: Additional error correction for optical media.
* Copyright (C) 2004-2007 Carsten Gnoerlich.
* Project home page: http://www.dvdisaster.com
* Email: carsten@dvdisaster.com -or- cgnoerlich@fsfe.org
*
* The Reed-Solomon error correction draws a lot of inspiration - and even code -
* from Phil Karn's excellent Reed-Solomon library: http://www.ka9q.net/code/fec/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA,
* or direct your browser at http://www.gnu.org.
*/
#include "dvdisaster.h"
#include "galois-inlines.h"
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
/***
*** Mapping between cd frame and parity vectors
***/
/*
* Mapping of frame bytes to P/Q Vectors
*/
int PToByteIndex(int p, int i)
{ return 12 + p + i*86;
}
void ByteIndexToP(int b, int *p, int *i)
{ *p = (b-12)%86;
*i = (b-12)/86;
}
int QToByteIndex(int q, int i)
{ int offset = 12 + (q & 1);
if(i == 43) return 2248+q;
if(i == 44) return 2300+q;
q&=~1;
return offset + (q*43 + i*88) % 2236;
}
void ByteIndexToQ(int b, int *q, int *i)
{ int x,y,offset;
if(b >= 2300)
{ *i = 44;
*q = (b-2300);
return;
}
if(b >= 2248)
{ *i = 43;
*q = (b-2248);
return;
}
offset = b&1;
b = (b-12)/2;
x = b/43;
y = (b-(x*43))%26;
*i = b-(x*43);
*q = 2*((x+26-y)%26)+offset;
}
/*
* There are 86 vectors of P-parity, yielding a RS(26,24) code.
*/
void GetPVector(unsigned char *frame, unsigned char *data, int n)
{ int i;
int w_idx = n+12;
for(i=0; i<26; i++, w_idx+=86)
data[i] = frame[w_idx];
}
void SetPVector(unsigned char *frame, unsigned char *data, int n)
{ int i;
int w_idx = n+12;
for(i=0; i<26; i++, w_idx+=86)
frame[w_idx] = data[i];
}
void FillPVector(unsigned char *frame, unsigned char data, int n)
{ int i;
int w_idx = n+12;
for(i=0; i<26; i++, w_idx+=86)
frame[w_idx] = data;
}
void OrPVector(unsigned char *frame, unsigned char value, int n)
{ int i;
int w_idx = n+12;
for(i=0; i<26; i++, w_idx+=86)
frame[w_idx] |= value;
}
void AndPVector(unsigned char *frame, unsigned char value, int n)
{ int i;
int w_idx = n+12;
for(i=0; i<26; i++, w_idx+=86)
frame[w_idx] &= value;
}
/*
* There are 52 vectors of Q-parity, yielding a RS(45,43) code.
*/
void GetQVector(unsigned char *frame, unsigned char *data, int n)
{ int offset = 12 + (n & 1);
int w_idx = (n&~1) * 43;
int i;
for(i=0; i<43; i++, w_idx+=88)
data[i] = frame[(w_idx % 2236) + offset];
data[43] = frame[2248 + n];
data[44] = frame[2300 + n];
}
void SetQVector(unsigned char *frame, unsigned char *data, int n)
{ int offset = 12 + (n & 1);
int w_idx = (n&~1) * 43;
int i;
for(i=0; i<43; i++, w_idx+=88)
frame[(w_idx % 2236) + offset] = data[i];
frame[2248 + n] = data[43];
frame[2300 + n] = data[44];
}
void FillQVector(unsigned char *frame, unsigned char data, int n)
{ int offset = 12 + (n & 1);
int w_idx = (n&~1) * 43;
int i;
for(i=0; i<43; i++, w_idx+=88)
frame[(w_idx % 2236) + offset] = data;
frame[2248 + n] = data;
frame[2300 + n] = data;
}
void OrQVector(unsigned char *frame, unsigned char data, int n)
{ int offset = 12 + (n & 1);
int w_idx = (n&~1) * 43;
int i;
for(i=0; i<43; i++, w_idx+=88)
frame[(w_idx % 2236) + offset] |= data;
frame[2248 + n] |= data;
frame[2300 + n] |= data;
}
void AndQVector(unsigned char *frame, unsigned char data, int n)
{ int offset = 12 + (n & 1);
int w_idx = (n&~1) * 43;
int i;
for(i=0; i<43; i++, w_idx+=88)
frame[(w_idx % 2236) + offset] &= data;
frame[2248 + n] &= data;
frame[2300 + n] &= data;
}
/***
*** C2 error counting
***/
int CountC2Errors(unsigned char *frame)
{ int i,count = 0;
frame += 2352;
for(i=0; i<294; i++, frame++)
{ if(*frame & 0x01) count++;
if(*frame & 0x02) count++;
if(*frame & 0x04) count++;
if(*frame & 0x08) count++;
if(*frame & 0x10) count++;
if(*frame & 0x20) count++;
if(*frame & 0x40) count++;
if(*frame & 0x80) count++;
}
return count;
}
/***
*** L-EC error correction for CD raw data sectors
***/
/*
* These could be used from ReedSolomonTables,
* but hardcoding them is faster.
*/
#define NROOTS 2
#define LEC_FIRST_ROOT 0 //GF_ALPHA0
#define LEC_PRIM_ELEM 1
#define LEC_PRIMTH_ROOT 1
/*
* Calculate the error syndrome
*/
int DecodePQ(ReedSolomonTables *rt, unsigned char *data, int padding,
int *erasure_list, int erasure_count)
{ GaloisTables *gt = rt->gfTables;
int syndrome[NROOTS];
int lambda[NROOTS+1];
int omega[NROOTS+1];
int b[NROOTS+1];
int reg[NROOTS+1];
int root[NROOTS];
int loc[NROOTS];
int syn_error;
int deg_lambda,lambda_roots;
int deg_omega;
int shortened_size = GF_FIELDMAX - 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];
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)];
/*** Convert syndrome to index form, check for nonzero condition. */
syn_error = 0;
for(i=0; i<NROOTS; i++)
{ syn_error |= syndrome[i];
syndrome[i] = gt->indexOf[syndrome[i]];
}
/*** If the syndrome is zero, everything is fine. */
if(!syn_error)
return 0;
/*** Initialize lambda to be the erasure locator polynomial */
lambda[0] = 1;
lambda[1] = lambda[2] = 0;
erasure_list[0] += padding;
erasure_list[1] += padding;
if(erasure_count > 2) /* sanity check */
erasure_count = 0;
if(erasure_count > 0)
{ lambda[1] = gt->alphaTo[mod_fieldmax(LEC_PRIM_ELEM*(GF_FIELDMAX-1-erasure_list[0]))];
for(i=1; i<erasure_count; i++)
{ 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]];
if(tmp != GF_ALPHA0)
lambda[j] ^= gt->alphaTo[mod_fieldmax(u + tmp)];
}
}
}
for(i=0; i<NROOTS+1; i++)
b[i] = gt->indexOf[lambda[i]];
/*** Berlekamp-Massey algorithm to determine error+erasure locator polynomial */
r = erasure_count; /* r is the step number */
el = erasure_count;
/* Compute discrepancy at the r-th step in poly-form */
while(++r <= NROOTS)
{ 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])];
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;
}
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];
}
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;
}
memcpy(lambda, t, (NROOTS+1)*sizeof(t[0]));
}
}
/*** Convert lambda to index form and compute deg(lambda(x)) */
deg_lambda = 0;
for(i=0; i<NROOTS+1; i++)
{ lambda[i] = gt->indexOf[lambda[i]];
if(lambda[i] != GF_ALPHA0)
deg_lambda = i;
}
/*** Find roots of the error+erasure locator polynomial by Chien search */
memcpy(reg+1, lambda+1, NROOTS*sizeof(reg[0]));
lambda_roots = 0; /* Number of roots of lambda(x) */
for(i=1, k=LEC_PRIMTH_ROOT-1; i<=GF_FIELDMAX; i++, k=mod_fieldmax(k+LEC_PRIMTH_ROOT))
{ int q=1; /* lambda[0] is always 0 */
for(j=deg_lambda; j>0; j--)
{ if(reg[j] != GF_ALPHA0)
{ reg[j] = mod_fieldmax(reg[j] + j);
q ^= gt->alphaTo[reg[j]];
}
}
if(q != 0) continue; /* Not a root */
/* store root in index-form and the error location number */
root[lambda_roots] = i;
loc[lambda_roots] = k;
/* If we've already found max possible roots, abort the search to save time */
if(++lambda_roots == deg_lambda) break;
}
/* deg(lambda) unequal to number of roots => uncorrectable error detected
This is not reliable for very small numbers of roots, e.g. nroots = 2 */
if(deg_lambda != lambda_roots)
{ return -1;
}
/* Compute err+eras evaluator poly omega(x) = syn(x)*lambda(x)
(modulo x**nroots). in index form. Also find deg(omega). */
deg_omega = deg_lambda-1;
for(i=0; i<=deg_omega; i++)
{ int tmp = 0;
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])];
}
omega[i] = gt->indexOf[tmp];
}
/* Compute error values in poly-form.
num1 = omega(inv(X(l))),
num2 = inv(X(l))**(FIRST_ROOT-1) and
den = lambda_pr(inv(X(l))) all in poly-form. */
for(j=lambda_roots-1; j>=0; j--)
{ int num1 = 0;
int num2;
int den;
int location = loc[j];
for(i=deg_omega; i>=0; i--)
{ if(omega[i] != GF_ALPHA0)
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])];
}
/* 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])];
/* 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 1
else return -3;
#endif
}
/*** Form the syndromes: Evaluate data(x) at roots of g(x) */
for(i=0; i<NROOTS; i++)
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)];
}
/*** Convert syndrome to index form, check for nonzero condition. */
#if 1
for(i=0; i<NROOTS; i++)
if(syndrome[i])
return -2;
#endif
return corrected;
}

View File

@ -1,691 +0,0 @@
/* cdrdao - write audio CD-Rs in disc-at-once mode
*
* Copyright (C) 1998-2002 Andreas Mueller <andreas@daneb.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <assert.h>
#include <sys/types.h>
#include "lec.h"
#define GF8_PRIM_POLY 0x11d /* x^8 + x^4 + x^3 + x^2 + 1 */
#define EDC_POLY 0x8001801b /* (x^16 + x^15 + x^2 + 1) (x^16 + x^2 + x + 1) */
#define LEC_HEADER_OFFSET 12
#define LEC_DATA_OFFSET 16
#define LEC_MODE1_DATA_LEN 2048
#define LEC_MODE1_EDC_OFFSET 2064
#define LEC_MODE1_INTERMEDIATE_OFFSET 2068
#define LEC_MODE1_P_PARITY_OFFSET 2076
#define LEC_MODE1_Q_PARITY_OFFSET 2248
#define LEC_MODE2_FORM1_DATA_LEN (2048+8)
#define LEC_MODE2_FORM1_EDC_OFFSET 2072
#define LEC_MODE2_FORM2_DATA_LEN (2324+8)
#define LEC_MODE2_FORM2_EDC_OFFSET 2348
typedef u_int8_t gf8_t;
static u_int8_t GF8_LOG[256];
static gf8_t GF8_ILOG[256];
static const class Gf8_Q_Coeffs_Results_01 {
private:
u_int16_t table[43][256];
public:
Gf8_Q_Coeffs_Results_01();
~Gf8_Q_Coeffs_Results_01() {}
const u_int16_t *operator[] (int i) const { return &table[i][0]; }
operator const u_int16_t *() const { return &table[0][0]; }
} CF8_Q_COEFFS_RESULTS_01;
static const class CrcTable {
private:
u_int32_t table[256];
public:
CrcTable();
~CrcTable() {}
u_int32_t operator[](int i) const { return table[i]; }
operator const u_int32_t *() const { return table; }
} CRCTABLE;
static const class ScrambleTable {
private:
u_int8_t table[2340];
public:
ScrambleTable();
~ScrambleTable() {}
u_int8_t operator[](int i) const { return table[i]; }
operator const u_int8_t *() const { return table; }
} SCRAMBLE_TABLE;
/* Creates the logarithm and inverse logarithm table that is required
* for performing multiplication in the GF(8) domain.
*/
static void gf8_create_log_tables()
{
u_int8_t log;
u_int16_t b;
for (b = 0; b <= 255; b++) {
GF8_LOG[b] = 0;
GF8_ILOG[b] = 0;
}
b = 1;
for (log = 0; log < 255; log++) {
GF8_LOG[(u_int8_t)b] = log;
GF8_ILOG[log] = (u_int8_t)b;
b <<= 1;
if ((b & 0x100) != 0)
b ^= GF8_PRIM_POLY;
}
}
/* Addition in the GF(8) domain: just the XOR of the values.
*/
#define gf8_add(a, b) (a) ^ (b)
/* Multiplication in the GF(8) domain: add the logarithms (modulo 255)
* and return the inverse logarithm. Not used!
*/
#if 0
static gf8_t gf8_mult(gf8_t a, gf8_t b)
{
int16_t sum;
if (a == 0 || b == 0)
return 0;
sum = GF8_LOG[a] + GF8_LOG[b];
if (sum >= 255)
sum -= 255;
return GF8_ILOG[sum];
}
#endif
/* Division in the GF(8) domain: Like multiplication but logarithms a
* subtracted.
*/
static gf8_t gf8_div(gf8_t a, gf8_t b)
{
int16_t sum;
assert(b != 0);
if (a == 0)
return 0;
sum = GF8_LOG[a] - GF8_LOG[b];
if (sum < 0)
sum += 255;
return GF8_ILOG[sum];
}
Gf8_Q_Coeffs_Results_01::Gf8_Q_Coeffs_Results_01()
{
int i, j;
u_int16_t c;
gf8_t GF8_COEFFS_HELP[2][45];
u_int8_t GF8_Q_COEFFS[2][45];
gf8_create_log_tables();
/* build matrix H:
* 1 1 ... 1 1
* a^44 a^43 ... a^1 a^0
*
*
*/
for (j = 0; j < 45; j++) {
GF8_COEFFS_HELP[0][j] = 1; /* e0 */
GF8_COEFFS_HELP[1][j] = GF8_ILOG[44-j]; /* e1 */
}
/* resolve equation system for parity byte 0 and 1 */
/* e1' = e1 + e0 */
for (j = 0; j < 45; j++) {
GF8_Q_COEFFS[1][j] = gf8_add(GF8_COEFFS_HELP[1][j],
GF8_COEFFS_HELP[0][j]);
}
/* e1'' = e1' / (a^1 + 1) */
for (j = 0; j < 45; j++) {
GF8_Q_COEFFS[1][j] = gf8_div(GF8_Q_COEFFS[1][j], GF8_Q_COEFFS[1][43]);
}
/* e0' = e0 + e1 / a^1 */
for (j = 0; j < 45; j++) {
GF8_Q_COEFFS[0][j] = gf8_add(GF8_COEFFS_HELP[0][j],
gf8_div(GF8_COEFFS_HELP[1][j],
GF8_ILOG[1]));
}
/* e0'' = e0' / (1 + 1 / a^1) */
for (j = 0; j < 45; j++) {
GF8_Q_COEFFS[0][j] = gf8_div(GF8_Q_COEFFS[0][j], GF8_Q_COEFFS[0][44]);
}
/*
* Compute the products of 0..255 with all of the Q coefficients in
* advance. When building the scalar product between the data vectors
* and the P/Q vectors the individual products can be looked up in
* this table
*
* The P parity coefficients are just a subset of the Q coefficients so
* that we do not need to create a separate table for them.
*/
for (j = 0; j < 43; j++) {
table[j][0] = 0;
for (i = 1; i < 256; i++) {
c = GF8_LOG[i] + GF8_LOG[GF8_Q_COEFFS[0][j]];
if (c >= 255) c -= 255;
table[j][i] = GF8_ILOG[c];
c = GF8_LOG[i] + GF8_LOG[GF8_Q_COEFFS[1][j]];
if (c >= 255) c -= 255;
table[j][i] |= GF8_ILOG[c]<<8;
}
}
}
/* Reverses the bits in 'd'. 'bits' defines the bit width of 'd'.
*/
static u_int32_t mirror_bits(u_int32_t d, int bits)
{
int i;
u_int32_t r = 0;
for (i = 0; i < bits; i++) {
r <<= 1;
if ((d & 0x1) != 0)
r |= 0x1;
d >>= 1;
}
return r;
}
/* Build the CRC lookup table for EDC_POLY poly. The CRC is 32 bit wide
* and reversed (i.e. the bit stream is divided by the EDC_POLY with the
* LSB first order).
*/
CrcTable::CrcTable ()
{
u_int32_t i, j;
u_int32_t r;
for (i = 0; i < 256; i++) {
r = mirror_bits(i, 8);
r <<= 24;
for (j = 0; j < 8; j++) {
if ((r & 0x80000000) != 0) {
r <<= 1;
r ^= EDC_POLY;
}
else {
r <<= 1;
}
}
r = mirror_bits(r, 32);
table[i] = r;
}
}
/* Calculates the CRC of given data with given lengths based on the
* table lookup algorithm.
*/
static u_int32_t calc_edc(u_int8_t *data, int len)
{
u_int32_t crc = 0;
while (len--) {
crc = CRCTABLE[(int)(crc ^ *data++) & 0xff] ^ (crc >> 8);
}
return crc;
}
/* Build the scramble table as defined in the yellow book. The bytes
12 to 2351 of a sector will be XORed with the data of this table.
*/
ScrambleTable::ScrambleTable()
{
u_int16_t i, j;
u_int16_t reg = 1;
u_int8_t d;
for (i = 0; i < 2340; i++) {
d = 0;
for (j = 0; j < 8; j++) {
d >>= 1;
if ((reg & 0x1) != 0)
d |= 0x80;
if ((reg & 0x1) != ((reg >> 1) & 0x1)) {
reg >>= 1;
reg |= 0x4000; /* 15-bit register */
}
else {
reg >>= 1;
}
}
table[i] = d;
}
}
/* Calc EDC for a MODE 1 sector
*/
static void calc_mode1_edc(u_int8_t *sector)
{
u_int32_t crc = calc_edc(sector, LEC_MODE1_DATA_LEN + 16);
sector[LEC_MODE1_EDC_OFFSET] = crc & 0xffL;
sector[LEC_MODE1_EDC_OFFSET + 1] = (crc >> 8) & 0xffL;
sector[LEC_MODE1_EDC_OFFSET + 2] = (crc >> 16) & 0xffL;
sector[LEC_MODE1_EDC_OFFSET + 3] = (crc >> 24) & 0xffL;
}
/* Calc EDC for a XA form 1 sector
*/
static void calc_mode2_form1_edc(u_int8_t *sector)
{
u_int32_t crc = calc_edc(sector + LEC_DATA_OFFSET,
LEC_MODE2_FORM1_DATA_LEN);
sector[LEC_MODE2_FORM1_EDC_OFFSET] = crc & 0xffL;
sector[LEC_MODE2_FORM1_EDC_OFFSET + 1] = (crc >> 8) & 0xffL;
sector[LEC_MODE2_FORM1_EDC_OFFSET + 2] = (crc >> 16) & 0xffL;
sector[LEC_MODE2_FORM1_EDC_OFFSET + 3] = (crc >> 24) & 0xffL;
}
/* Calc EDC for a XA form 2 sector
*/
static void calc_mode2_form2_edc(u_int8_t *sector)
{
u_int32_t crc = calc_edc(sector + LEC_DATA_OFFSET,
LEC_MODE2_FORM2_DATA_LEN);
sector[LEC_MODE2_FORM2_EDC_OFFSET] = crc & 0xffL;
sector[LEC_MODE2_FORM2_EDC_OFFSET + 1] = (crc >> 8) & 0xffL;
sector[LEC_MODE2_FORM2_EDC_OFFSET + 2] = (crc >> 16) & 0xffL;
sector[LEC_MODE2_FORM2_EDC_OFFSET + 3] = (crc >> 24) & 0xffL;
}
/* Writes the sync pattern to the given sector.
*/
static void set_sync_pattern(u_int8_t *sector)
{
sector[0] = 0;
sector[1] = sector[2] = sector[3] = sector[4] = sector[5] =
sector[6] = sector[7] = sector[8] = sector[9] = sector[10] = 0xff;
sector[11] = 0;
}
static u_int8_t bin2bcd(u_int8_t b)
{
return (((b/10) << 4) & 0xf0) | ((b%10) & 0x0f);
}
/* Builds the sector header.
*/
static void set_sector_header(u_int8_t mode, u_int32_t adr, u_int8_t *sector)
{
sector[LEC_HEADER_OFFSET] = bin2bcd(adr / (60*75));
sector[LEC_HEADER_OFFSET + 1] = bin2bcd((adr / 75) % 60);
sector[LEC_HEADER_OFFSET + 2] = bin2bcd(adr % 75);
sector[LEC_HEADER_OFFSET + 3] = mode;
}
/* Calculate the P parities for the sector.
* The 43 P vectors of length 24 are combined with the GF8_P_COEFFS.
*/
static void calc_P_parity(u_int8_t *sector)
{
int i, j;
u_int16_t p01_msb, p01_lsb;
u_int8_t *p_lsb_start;
u_int8_t *p_lsb;
u_int8_t *p0, *p1;
u_int8_t d0,d1;
p_lsb_start = sector + LEC_HEADER_OFFSET;
p1 = sector + LEC_MODE1_P_PARITY_OFFSET;
p0 = sector + LEC_MODE1_P_PARITY_OFFSET + 2 * 43;
for (i = 0; i <= 42; i++) {
p_lsb = p_lsb_start;
p01_lsb = p01_msb = 0;
for (j = 19; j <= 42; j++) {
d0 = *p_lsb;
d1 = *(p_lsb+1);
p01_lsb ^= CF8_Q_COEFFS_RESULTS_01[j][d0];
p01_msb ^= CF8_Q_COEFFS_RESULTS_01[j][d1];
p_lsb += 2 * 43;
}
*p0 = p01_lsb;
*(p0 + 1) = p01_msb;
*p1 = p01_lsb>>8;
*(p1 + 1) = p01_msb>>8;
p0 += 2;
p1 += 2;
p_lsb_start += 2;
}
}
/* Calculate the Q parities for the sector.
* The 26 Q vectors of length 43 are combined with the GF8_Q_COEFFS.
*/
static void calc_Q_parity(u_int8_t *sector)
{
int i, j;
u_int16_t q01_lsb, q01_msb;
u_int8_t *q_lsb_start;
u_int8_t *q_lsb;
u_int8_t *q0, *q1, *q_start;
u_int8_t d0,d1;
q_lsb_start = sector + LEC_HEADER_OFFSET;
q_start = sector + LEC_MODE1_Q_PARITY_OFFSET;
q1 = sector + LEC_MODE1_Q_PARITY_OFFSET;
q0 = sector + LEC_MODE1_Q_PARITY_OFFSET + 2 * 26;
for (i = 0; i <= 25; i++) {
q_lsb = q_lsb_start;
q01_lsb = q01_msb = 0;
for (j = 0; j <= 42; j++) {
d0 = *q_lsb;
d1 = *(q_lsb+1);
q01_lsb ^= CF8_Q_COEFFS_RESULTS_01[j][d0];
q01_msb ^= CF8_Q_COEFFS_RESULTS_01[j][d1];
q_lsb += 2 * 44;
if (q_lsb >= q_start) {
q_lsb -= 2 * 1118;
}
}
*q0 = q01_lsb;
*(q0 + 1) = q01_msb;
*q1 = q01_lsb>>8;
*(q1 + 1) = q01_msb>>8;
q0 += 2;
q1 += 2;
q_lsb_start += 2 * 43;
}
}
/* Encodes a MODE 0 sector.
* 'adr' is the current physical sector address
* 'sector' must be 2352 byte wide
*/
void lec_encode_mode0_sector(u_int32_t adr, u_int8_t *sector)
{
u_int16_t i;
set_sync_pattern(sector);
set_sector_header(0, adr, sector);
sector += 16;
for (i = 0; i < 2336; i++)
*sector++ = 0;
}
/* Encodes a MODE 1 sector.
* 'adr' is the current physical sector address
* 'sector' must be 2352 byte wide containing 2048 bytes user data at
* offset 16
*/
void lec_encode_mode1_sector(u_int32_t adr, u_int8_t *sector)
{
set_sync_pattern(sector);
set_sector_header(1, adr, sector);
calc_mode1_edc(sector);
/* clear the intermediate field */
sector[LEC_MODE1_INTERMEDIATE_OFFSET] =
sector[LEC_MODE1_INTERMEDIATE_OFFSET + 1] =
sector[LEC_MODE1_INTERMEDIATE_OFFSET + 2] =
sector[LEC_MODE1_INTERMEDIATE_OFFSET + 3] =
sector[LEC_MODE1_INTERMEDIATE_OFFSET + 4] =
sector[LEC_MODE1_INTERMEDIATE_OFFSET + 5] =
sector[LEC_MODE1_INTERMEDIATE_OFFSET + 6] =
sector[LEC_MODE1_INTERMEDIATE_OFFSET + 7] = 0;
calc_P_parity(sector);
calc_Q_parity(sector);
}
/* Encodes a MODE 2 sector.
* 'adr' is the current physical sector address
* 'sector' must be 2352 byte wide containing 2336 bytes user data at
* offset 16
*/
void lec_encode_mode2_sector(u_int32_t adr, u_int8_t *sector)
{
set_sync_pattern(sector);
set_sector_header(2, adr, sector);
}
/* Encodes a XA form 1 sector.
* 'adr' is the current physical sector address
* 'sector' must be 2352 byte wide containing 2048+8 bytes user data at
* offset 16
*/
void lec_encode_mode2_form1_sector(u_int32_t adr, u_int8_t *sector)
{
set_sync_pattern(sector);
calc_mode2_form1_edc(sector);
/* P/Q partiy must not contain the sector header so clear it */
sector[LEC_HEADER_OFFSET] =
sector[LEC_HEADER_OFFSET + 1] =
sector[LEC_HEADER_OFFSET + 2] =
sector[LEC_HEADER_OFFSET + 3] = 0;
calc_P_parity(sector);
calc_Q_parity(sector);
/* finally add the sector header */
set_sector_header(2, adr, sector);
}
/* Encodes a XA form 2 sector.
* 'adr' is the current physical sector address
* 'sector' must be 2352 byte wide containing 2324+8 bytes user data at
* offset 16
*/
void lec_encode_mode2_form2_sector(u_int32_t adr, u_int8_t *sector)
{
set_sync_pattern(sector);
calc_mode2_form2_edc(sector);
set_sector_header(2, adr, sector);
}
/* Scrambles and byte swaps an encoded sector.
* 'sector' must be 2352 byte wide.
*/
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;
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++) {
/* 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

@ -1,77 +0,0 @@
/* cdrdao - write audio CD-Rs in disc-at-once mode
*
* Copyright (C) 1998-2002 Andreas Mueller <mueller@daneb.ping.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef __LEC_H__
#define __LEC_H__
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <sys/types.h>
#include <inttypes.h>
typedef uint32_t u_int32_t;
typedef uint16_t u_int16_t;
typedef uint8_t u_int8_t;
#ifndef TRUE
#define TRUE 1
#endif
/* Encodes a MODE 0 sector.
* 'adr' is the current physical sector address
* 'sector' must be 2352 byte wide
*/
void lec_encode_mode0_sector(u_int32_t adr, u_int8_t *sector);
/* Encodes a MODE 1 sector.
* 'adr' is the current physical sector address
* 'sector' must be 2352 byte wide containing 2048 bytes user data at
* offset 16
*/
void lec_encode_mode1_sector(u_int32_t adr, u_int8_t *sector);
/* Encodes a MODE 2 sector.
* 'adr' is the current physical sector address
* 'sector' must be 2352 byte wide containing 2336 bytes user data at
* offset 16
*/
void lec_encode_mode2_sector(u_int32_t adr, u_int8_t *sector);
/* Encodes a XA form 1 sector.
* 'adr' is the current physical sector address
* 'sector' must be 2352 byte wide containing 2048+8 bytes user data at
* offset 16
*/
void lec_encode_mode2_form1_sector(u_int32_t adr, u_int8_t *sector);
/* Encodes a XA form 2 sector.
* 'adr' is the current physical sector address
* 'sector' must be 2352 byte wide containing 2324+8 bytes user data at
* offset 16
*/
void lec_encode_mode2_form2_sector(u_int32_t adr, u_int8_t *sector);
/* Scrambles and byte swaps an encoded sector.
* 'sector' must be 2352 byte wide.
*/
void lec_scramble(u_int8_t *sector);
#endif

View File

@ -1,203 +0,0 @@
/* dvdisaster: Additional error correction for optical media.
* Copyright (C) 2004-2007 Carsten Gnoerlich.
* Project home page: http://www.dvdisaster.com
* Email: carsten@dvdisaster.com -or- cgnoerlich@fsfe.org
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA,
* or direct your browser at http://www.gnu.org.
*/
#include "dvdisaster.h"
static GaloisTables *gt = NULL; /* for L-EC Reed-Solomon */
static ReedSolomonTables *rt = NULL;
bool Init_LEC_Correct(void)
{
gt = CreateGaloisTables(0x11d);
rt = CreateReedSolomonTables(gt, 0, 1, 10);
return(1);
}
void Kill_LEC_Correct(void)
{
FreeGaloisTables(gt);
FreeReedSolomonTables(rt);
}
/***
*** CD level CRC calculation
***/
/*
* Test raw sector against its 32bit CRC.
* Returns TRUE if frame is good.
*/
int CheckEDC(const unsigned char *cd_frame, bool xa_mode)
{
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;
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);
}
}
/***
*** A very simple L-EC error correction.
***
* Perform just one pass over the Q and P vectors to see if everything
* is okay respectively correct minor errors. This is pretty much the
* same stuff the drive is supposed to do in the final L-EC stage.
*/
static int simple_lec(unsigned char *frame)
{
unsigned char byte_state[2352];
unsigned char p_vector[P_VECTOR_SIZE];
unsigned char q_vector[Q_VECTOR_SIZE];
unsigned char p_state[P_VECTOR_SIZE];
int erasures[Q_VECTOR_SIZE], erasure_count;
int ignore[2];
int p_failures, q_failures;
int p_corrected, q_corrected;
int p,q;
/* Setup */
memset(byte_state, 0, 2352);
p_failures = q_failures = 0;
p_corrected = q_corrected = 0;
/* Perform Q-Parity error correction */
for(q=0; q<N_Q_VECTORS; q++)
{ int err;
/* We have no erasure information for Q vectors */
GetQVector(frame, q_vector, q);
err = DecodePQ(rt, q_vector, Q_PADDING, ignore, 0);
/* 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++;
}
}
}
/* Perform P-Parity error correction */
for(p=0; p<N_P_VECTORS; p++)
{ int err,i;
/* Try error correction without erasure information */
GetPVector(frame, p_vector, p);
err = DecodePQ(rt, p_vector, P_PADDING, ignore, 0);
/* If unsuccessful, try again using erasures.
Erasure information is uncertain, so try this last. */
if(err < 0 || err > 2)
{ 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;
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++;
}
else /* Correctable. */
{ 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 0;
}
/***
*** Validate CD raw sector
***/
int ValidateRawSector(unsigned char *frame, bool xaMode)
{
int lec_did_sth = FALSE_0;
/* 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))
{
/* EDC failure in RAW sector */
return FALSE_0;
}
return TRUE_1;
}

View File

@ -1,259 +0,0 @@
/********************************************************
* *
* PC Engine CD Command 0xD8 - SAPSP *
* *
********************************************************/
static void DoNEC_PCE_SAPSP(const uint8 *cdb)
{
uint32 new_read_sec_start;
//printf("Set audio start: %02x %02x %02x %02x %02x %02x %02x\n", cdb[9], cdb[1], cdb[2], cdb[3], cdb[4], cdb[5], cdb[6]);
switch (cdb[9] & 0xc0)
{
default: //SCSIDBG("Unknown SAPSP 9: %02x\n", cdb[9]);
case 0x00:
new_read_sec_start = (cdb[3] << 16) | (cdb[4] << 8) | cdb[5];
break;
case 0x40:
new_read_sec_start = AMSF_to_LBA(BCD_to_U8(cdb[2]), BCD_to_U8(cdb[3]), BCD_to_U8(cdb[4]));
break;
case 0x80:
{
int track = BCD_to_U8(cdb[2]);
if(!track)
track = 1;
else if(track >= toc.last_track + 1)
track = 100;
new_read_sec_start = toc.tracks[track].lba;
}
break;
}
//printf("%lld\n", (long long)(monotonic_timestamp - pce_lastsapsp_timestamp) * 1000 / System_Clock);
if(cdda.CDDAStatus == CDDASTATUS_PLAYING && new_read_sec_start == read_sec_start && ((int64)(monotonic_timestamp - pce_lastsapsp_timestamp) * 1000 / System_Clock) < 190)
{
pce_lastsapsp_timestamp = monotonic_timestamp;
SendStatusAndMessage(STATUS_GOOD, 0x00);
CDIRQCallback(SCSICD_IRQ_DATA_TRANSFER_DONE);
return;
}
pce_lastsapsp_timestamp = monotonic_timestamp;
read_sec = read_sec_start = new_read_sec_start;
read_sec_end = toc.tracks[100].lba;
cdda.CDDAReadPos = 588;
cdda.CDDAStatus = CDDASTATUS_PAUSED;
cdda.PlayMode = PLAYMODE_SILENT;
if(cdb[1])
{
cdda.PlayMode = PLAYMODE_NORMAL;
cdda.CDDAStatus = CDDASTATUS_PLAYING;
}
if(read_sec < toc.tracks[100].lba)
Cur_CDIF->HintReadSector(read_sec);
SendStatusAndMessage(STATUS_GOOD, 0x00);
CDIRQCallback(SCSICD_IRQ_DATA_TRANSFER_DONE);
}
/********************************************************
* *
* PC Engine CD Command 0xD9 - SAPEP *
* *
********************************************************/
static void DoNEC_PCE_SAPEP(const uint8 *cdb)
{
uint32 new_read_sec_end;
//printf("Set audio end: %02x %02x %02x %02x %02x %02x %02x\n", cdb[9], cdb[1], cdb[2], cdb[3], cdb[4], cdb[5], cdb[6]);
switch (cdb[9] & 0xc0)
{
default: //SCSIDBG("Unknown SAPEP 9: %02x\n", cdb[9]);
case 0x00:
new_read_sec_end = (cdb[3] << 16) | (cdb[4] << 8) | cdb[5];
break;
case 0x40:
new_read_sec_end = BCD_to_U8(cdb[4]) + 75 * (BCD_to_U8(cdb[3]) + 60 * BCD_to_U8(cdb[2]));
new_read_sec_end -= 150;
break;
case 0x80:
{
int track = BCD_to_U8(cdb[2]);
if(!track)
track = 1;
else if(track >= toc.last_track + 1)
track = 100;
new_read_sec_end = toc.tracks[track].lba;
}
break;
}
read_sec_end = new_read_sec_end;
switch(cdb[1]) // PCE CD(TODO: Confirm these, and check the mode mask):
{
default:
case 0x03: cdda.PlayMode = PLAYMODE_NORMAL;
cdda.CDDAStatus = CDDASTATUS_PLAYING;
break;
case 0x02: cdda.PlayMode = PLAYMODE_INTERRUPT;
cdda.CDDAStatus = CDDASTATUS_PLAYING;
break;
case 0x01: cdda.PlayMode = PLAYMODE_LOOP;
cdda.CDDAStatus = CDDASTATUS_PLAYING;
break;
case 0x00: cdda.PlayMode = PLAYMODE_SILENT;
cdda.CDDAStatus = CDDASTATUS_STOPPED;
break;
}
SendStatusAndMessage(STATUS_GOOD, 0x00);
}
/********************************************************
* *
* PC Engine CD Command 0xDA - Pause *
* *
********************************************************/
static void DoNEC_PCE_PAUSE(const uint8 *cdb)
{
if(cdda.CDDAStatus != CDDASTATUS_STOPPED) // Hmm, should we give an error if it tries to pause and it's already paused?
{
cdda.CDDAStatus = CDDASTATUS_PAUSED;
SendStatusAndMessage(STATUS_GOOD, 0x00);
}
else // Definitely give an error if it tries to pause when no track is playing!
{
CommandCCError(SENSEKEY_ILLEGAL_REQUEST, NSE_AUDIO_NOT_PLAYING);
}
}
/********************************************************
* *
* PC Engine CD Command 0xDD - Read Subchannel Q *
* *
********************************************************/
static void DoNEC_PCE_READSUBQ(const uint8 *cdb)
{
uint8 *SubQBuf = cd.SubQBuf[QMode_Time];
uint8 data_in[8192];
memset(data_in, 0x00, 10);
data_in[2] = SubQBuf[1]; // Track
data_in[3] = SubQBuf[2]; // Index
data_in[4] = SubQBuf[3]; // M(rel)
data_in[5] = SubQBuf[4]; // S(rel)
data_in[6] = SubQBuf[5]; // F(rel)
data_in[7] = SubQBuf[7]; // M(abs)
data_in[8] = SubQBuf[8]; // S(abs)
data_in[9] = SubQBuf[9]; // F(abs)
if(cdda.CDDAStatus == CDDASTATUS_PAUSED)
data_in[0] = 2; // Pause
else if(cdda.CDDAStatus == CDDASTATUS_PLAYING || cdda.CDDAStatus == CDDASTATUS_SCANNING) // FIXME: Is this the correct status code for scanning playback?
data_in[0] = 0; // Playing
else
data_in[0] = 3; // Stopped
DoSimpleDataIn(data_in, 10);
}
/********************************************************
* *
* PC Engine CD Command 0xDE - Get Directory Info *
* *
********************************************************/
static void DoNEC_PCE_GETDIRINFO(const uint8 *cdb)
{
// Problems:
// Returned data lengths on real PCE are not confirmed.
// Mode 0x03 behavior not tested on real PCE
uint8 data_in[2048];
uint32 data_in_size = 0;
memset(data_in, 0, sizeof(data_in));
switch(cdb[1])
{
default: //MDFN_DispMessage("Unknown GETDIRINFO Mode: %02x", cdb[1]);
//printf("Unknown GETDIRINFO Mode: %02x", cdb[1]);
case 0x0:
data_in[0] = U8_to_BCD(toc.first_track);
data_in[1] = U8_to_BCD(toc.last_track);
data_in_size = 2;
break;
case 0x1:
{
uint8 m, s, f;
LBA_to_AMSF(toc.tracks[100].lba, &m, &s, &f);
data_in[0] = U8_to_BCD(m);
data_in[1] = U8_to_BCD(s);
data_in[2] = U8_to_BCD(f);
data_in_size = 3;
}
break;
case 0x2:
{
uint8 m, s, f;
int track = BCD_to_U8(cdb[2]);
if(!track)
track = 1;
else if(cdb[2] == 0xAA)
{
track = 100;
}
else if(track > 99)
{
CommandCCError(SENSEKEY_ILLEGAL_REQUEST, NSE_INVALID_PARAMETER);
return;
}
LBA_to_AMSF(toc.tracks[track].lba, &m, &s, &f);
data_in[0] = U8_to_BCD(m);
data_in[1] = U8_to_BCD(s);
data_in[2] = U8_to_BCD(f);
data_in[3] = toc.tracks[track].control;
data_in_size = 4;
}
break;
}
DoSimpleDataIn(data_in, data_in_size);
}

File diff suppressed because it is too large Load Diff

View File

@ -1,99 +0,0 @@
#ifndef __PCFX_SCSICD_H
#define __PCFX_SCSICD_H
typedef int32 scsicd_timestamp_t;
typedef struct
{
// Data bus(FIXME: we should have a variable for the target and the initiator, and OR them together to be truly accurate).
uint8 DB;
uint32 signals;
// Signals under our(the "target") control.
//bool BSY, MSG, CD, REQ, IO;
// Signals under the control of the initiator(not us!)
//bool kingACK, kingRST, kingSEL, kingATN;
} scsicd_bus_t;
extern scsicd_bus_t cd_bus; // Don't access this structure directly by name outside of scsicd.c, but use the macros below.
// Signals under our(the "target") control.
#define SCSICD_IO_mask 0x001
#define SCSICD_CD_mask 0x002
#define SCSICD_MSG_mask 0x004
#define SCSICD_REQ_mask 0x008
#define SCSICD_BSY_mask 0x010
// Signals under the control of the initiator(not us!)
#define SCSICD_kingRST_mask 0x020
#define SCSICD_kingACK_mask 0x040
#define SCSICD_kingATN_mask 0x080
#define SCSICD_kingSEL_mask 0x100
#define BSY_signal ((const bool)(cd_bus.signals & SCSICD_BSY_mask))
#define ACK_signal ((const bool)(cd_bus.signals & SCSICD_kingACK_mask))
#define RST_signal ((const bool)(cd_bus.signals & SCSICD_kingRST_mask))
#define MSG_signal ((const bool)(cd_bus.signals & SCSICD_MSG_mask))
#define SEL_signal ((const bool)(cd_bus.signals & SCSICD_kingSEL_mask))
#define REQ_signal ((const bool)(cd_bus.signals & SCSICD_REQ_mask))
#define IO_signal ((const bool)(cd_bus.signals & SCSICD_IO_mask))
#define CD_signal ((const bool)(cd_bus.signals & SCSICD_CD_mask))
#define ATN_signal ((const bool)(cd_bus.signals & SCSICD_kingATN_mask))
#define DB_signal ((const uint8)cd_bus.DB)
#define SCSICD_GetDB() DB_signal
#define SCSICD_GetBSY() BSY_signal
#define SCSICD_GetIO() IO_signal
#define SCSICD_GetCD() CD_signal
#define SCSICD_GetMSG() MSG_signal
#define SCSICD_GetREQ() REQ_signal
// Should we phase out getting these initiator-driven signals like this(the initiator really should keep track of them itself)?
#define SCSICD_GetACK() ACK_signal
#define SCSICD_GetRST() RST_signal
#define SCSICD_GetSEL() SEL_signal
#define SCSICD_GetATN() ATN_signal
void SCSICD_Power(scsicd_timestamp_t system_timestamp);
void SCSICD_SetDB(uint8 data);
// These SCSICD_Set* functions are kind of misnomers, at least in comparison to the SCSICD_Get* functions...
// They will set/clear the bits corresponding to the KING's side of the bus.
void SCSICD_SetACK(bool set);
void SCSICD_SetSEL(bool set);
void SCSICD_SetRST(bool set);
void SCSICD_SetATN(bool set);
uint32 SCSICD_Run(scsicd_timestamp_t);
void SCSICD_ResetTS(uint32 ts_base);
enum
{
SCSICD_PCE = 1,
SCSICD_PCFX
};
enum
{
SCSICD_IRQ_DATA_TRANSFER_DONE = 1,
SCSICD_IRQ_DATA_TRANSFER_READY,
SCSICD_IRQ_MAGICAL_REQ,
};
void SCSICD_GetCDDAValues(int16 &left, int16 &right);
void SCSICD_SetLog(void (*logfunc)(const char *, const char *, ...));
void SCSICD_Init(int type, int CDDATimeDiv, int32* left_hrbuf, int32* right_hrbuf, uint32 TransferRate, uint32 SystemClock, void (*IRQFunc)(int), void (*SSCFunc)(uint8, int));
void SCSICD_Close(void);
void SCSICD_SetTransferRate(uint32 TransferRate);
void SCSICD_SetCDDAVolume(double left, double right);
void SCSICD_StateAction(StateMem *sm, const unsigned load, const bool data_only, const char *sname);
void SCSICD_SetDisc(bool tray_open, CDIF *cdif, bool no_emu_side_effects = false);
#endif

View File

@ -1,69 +0,0 @@
// WARNING: Check resampling algorithm in scsicd.cpp for overflows if any value in here is negative.
/* -1 */ { 1777, 12211, 27812, 27640, 11965, 1703, 9, 0 }, // 83117 83119.332059(diff = 2.332059)
/* 0 */ { 1702, 11965, 27640, 27811, 12211, 1777, 11, 0 }, // 83117 83121.547903(diff = 4.547903)
/* 1 */ { 1630, 11720, 27463, 27977, 12459, 1854, 14, 0 }, // 83117 83123.444392(diff = 6.444392)
/* 2 */ { 1560, 11478, 27282, 28139, 12708, 1933, 17, 0 }, // 83117 83125.036510(diff = 8.036510)
/* 3 */ { 1492, 11238, 27098, 28296, 12959, 2014, 20, 0 }, // 83117 83126.338722(diff = 9.338722)
/* 4 */ { 1427, 11000, 26909, 28448, 13212, 2098, 23, 0 }, // 83117 83127.364983(diff = 10.364983)
/* 5 */ { 1363, 10764, 26716, 28595, 13467, 2185, 27, 0 }, // 83117 83128.128743(diff = 11.128743)
/* 6 */ { 1302, 10530, 26519, 28738, 13723, 2274, 31, 0 }, // 83117 83128.642956(diff = 11.642956)
/* 7 */ { 1242, 10299, 26319, 28876, 13981, 2365, 35, 0 }, // 83117 83128.920096(diff = 11.920096)
/* 8 */ { 1185, 10071, 26115, 29009, 14239, 2459, 39, 0 }, // 83117 83128.972128(diff = 11.972128)
/* 9 */ { 1129, 9844, 25907, 29137, 14499, 2556, 45, 0 }, // 83117 83128.810568(diff = 11.810568)
/* 10 */ { 1076, 9620, 25695, 29260, 14761, 2655, 50, 0 }, // 83117 83128.446456(diff = 11.446456)
/* 11 */ { 1024, 9399, 25481, 29377, 15023, 2757, 56, 0 }, // 83117 83127.890369(diff = 10.890369)
/* 12 */ { 975, 9180, 25263, 29489, 15287, 2861, 62, 0 }, // 83117 83127.152431(diff = 10.152431)
/* 13 */ { 927, 8964, 25041, 29596, 15552, 2968, 69, 0 }, // 83117 83126.242312(diff = 9.242312)
/* 14 */ { 880, 8750, 24817, 29698, 15818, 3078, 76, 0 }, // 83117 83125.169251(diff = 8.169251)
/* 15 */ { 836, 8539, 24590, 29794, 16083, 3191, 84, 0 }, // 83117 83123.942037(diff = 6.942037)
/* 16 */ { 793, 8331, 24359, 29884, 16350, 3307, 93, 0 }, // 83117 83122.569034(diff = 5.569034)
/* 17 */ { 752, 8125, 24126, 29969, 16618, 3425, 102, 0 }, // 83117 83121.058175(diff = 4.058175)
/* 18 */ { 712, 7923, 23890, 30049, 16886, 3546, 111, 0 }, // 83117 83119.416975(diff = 2.416975)
/* 19 */ { 674, 7723, 23651, 30123, 17154, 3670, 122, 0 }, // 83117 83117.652622(diff = 0.652622)
/* 20 */ { 638, 7526, 23410, 30191, 17422, 3797, 133, 0 }, // 83117 83115.771622(diff = 1.228378)
/* 21 */ { 603, 7331, 23167, 30254, 17691, 3927, 144, 0 }, // 83117 83113.780335(diff = 3.219665)
/* 22 */ { 569, 7140, 22922, 30310, 17960, 4059, 157, 0 }, // 83117 83111.684630(diff = 5.315370)
/* 23 */ { 537, 6951, 22674, 30361, 18229, 4195, 170, 0 }, // 83117 83109.489972(diff = 7.510028)
/* 24 */ { 506, 6766, 22424, 30407, 18497, 4334, 183, 0 }, // 83117 83107.201429(diff = 9.798571)
/* 25 */ { 477, 6583, 22172, 30446, 18766, 4475, 198, 0 }, // 83117 83104.823668(diff = 12.176332)
/* 26 */ { 449, 6403, 21919, 30479, 19034, 4619, 214, 0 }, // 83117 83102.360963(diff = 14.639037)
/* 27 */ { 422, 6226, 21664, 30507, 19301, 4767, 230, 0 }, // 83117 83099.817193(diff = 17.182807)
/* 28 */ { 396, 6053, 21407, 30529, 19568, 4917, 247, 0 }, // 83117 83097.195820(diff = 19.804180)
/* 29 */ { 372, 5882, 21148, 30545, 19834, 5071, 265, 0 }, // 83117 83094.499993(diff = 22.500007)
/* 30 */ { 348, 5714, 20888, 30555, 20100, 5227, 285, 0 }, // 83117 83091.732389(diff = 25.267611)
/* 31 */ { 326, 5549, 20627, 30559, 20365, 5386, 305, 0 }, // 83117 83088.895321(diff = 28.104679)
/* 32 */ { 305, 5386, 20365, 30559, 20627, 5549, 326, 0 }, // 83117 83088.895321(diff = 28.104679)
/* 33 */ { 285, 5227, 20100, 30555, 20888, 5714, 348, 0 }, // 83117 83091.732389(diff = 25.267611)
/* 34 */ { 265, 5071, 19834, 30545, 21148, 5882, 372, 0 }, // 83117 83094.499993(diff = 22.500007)
/* 35 */ { 247, 4917, 19568, 30529, 21407, 6053, 396, 0 }, // 83117 83097.195820(diff = 19.804180)
/* 36 */ { 230, 4767, 19301, 30507, 21664, 6226, 422, 0 }, // 83117 83099.817193(diff = 17.182807)
/* 37 */ { 214, 4619, 19034, 30479, 21919, 6403, 449, 0 }, // 83117 83102.360963(diff = 14.639037)
/* 38 */ { 198, 4475, 18766, 30446, 22172, 6583, 477, 0 }, // 83117 83104.823668(diff = 12.176332)
/* 39 */ { 183, 4334, 18497, 30407, 22424, 6766, 506, 0 }, // 83117 83107.201429(diff = 9.798571)
/* 40 */ { 170, 4195, 18229, 30361, 22674, 6951, 537, 0 }, // 83117 83109.489972(diff = 7.510028)
/* 41 */ { 157, 4059, 17960, 30310, 22922, 7140, 569, 0 }, // 83117 83111.684630(diff = 5.315370)
/* 42 */ { 144, 3927, 17691, 30254, 23167, 7331, 603, 0 }, // 83117 83113.780335(diff = 3.219665)
/* 43 */ { 133, 3797, 17422, 30191, 23410, 7526, 638, 0 }, // 83117 83115.771622(diff = 1.228378)
/* 44 */ { 122, 3670, 17154, 30123, 23651, 7723, 674, 0 }, // 83117 83117.652622(diff = 0.652622)
/* 45 */ { 111, 3546, 16886, 30049, 23890, 7923, 712, 0 }, // 83117 83119.416975(diff = 2.416975)
/* 46 */ { 102, 3425, 16618, 29969, 24126, 8125, 752, 0 }, // 83117 83121.058175(diff = 4.058175)
/* 47 */ { 93, 3307, 16350, 29884, 24359, 8331, 793, 0 }, // 83117 83122.569034(diff = 5.569034)
/* 48 */ { 84, 3191, 16083, 29794, 24590, 8539, 836, 0 }, // 83117 83123.942037(diff = 6.942037)
/* 49 */ { 76, 3078, 15818, 29698, 24817, 8750, 880, 0 }, // 83117 83125.169251(diff = 8.169251)
/* 50 */ { 69, 2968, 15552, 29596, 25041, 8964, 927, 0 }, // 83117 83126.242312(diff = 9.242312)
/* 51 */ { 62, 2861, 15287, 29489, 25263, 9180, 975, 0 }, // 83117 83127.152431(diff = 10.152431)
/* 52 */ { 56, 2757, 15023, 29377, 25481, 9399, 1024, 0 }, // 83117 83127.890369(diff = 10.890369)
/* 53 */ { 50, 2655, 14761, 29260, 25695, 9620, 1076, 0 }, // 83117 83128.446456(diff = 11.446456)
/* 54 */ { 45, 2556, 14499, 29137, 25907, 9844, 1129, 0 }, // 83117 83128.810568(diff = 11.810568)
/* 55 */ { 39, 2459, 14239, 29009, 26115, 10071, 1185, 0 }, // 83117 83128.972128(diff = 11.972128)
/* 56 */ { 35, 2365, 13981, 28876, 26319, 10299, 1242, 0 }, // 83117 83128.920096(diff = 11.920096)
/* 57 */ { 31, 2274, 13723, 28738, 26519, 10530, 1302, 0 }, // 83117 83128.642956(diff = 11.642956)
/* 58 */ { 27, 2185, 13467, 28595, 26716, 10764, 1363, 0 }, // 83117 83128.128743(diff = 11.128743)
/* 59 */ { 23, 2098, 13212, 28448, 26909, 11000, 1427, 0 }, // 83117 83127.364983(diff = 10.364983)
/* 60 */ { 20, 2014, 12959, 28296, 27098, 11238, 1492, 0 }, // 83117 83126.338722(diff = 9.338722)
/* 61 */ { 17, 1933, 12708, 28139, 27282, 11478, 1560, 0 }, // 83117 83125.036510(diff = 8.036510)
/* 62 */ { 14, 1854, 12459, 27977, 27463, 11720, 1630, 0 }, // 83117 83123.444392(diff = 6.444392)
/* 63 */ { 11, 1777, 12211, 27811, 27640, 11965, 1702, 0 }, // 83117 83121.547903(diff = 4.547903)
/* 64 */ { 9, 1703, 11965, 27640, 27812, 12211, 1777, 0 }, // 83117 83119.332059(diff = 2.332059)

View File

@ -1,96 +0,0 @@
#include "EW_state.h"
#include <cstring>
#include <algorithm>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
namespace EW {
NewStateDummy::NewStateDummy()
:length(0)
{
}
void NewStateDummy::Save(const void *ptr, size_t size, const char *name)
{
length += size;
}
void NewStateDummy::Load(void *ptr, size_t size, const char *name)
{
}
NewStateExternalBuffer::NewStateExternalBuffer(char *buffer, long maxlength)
:buffer(buffer), length(0), maxlength(maxlength)
{
}
void NewStateExternalBuffer::Save(const void *ptr, size_t size, const char *name)
{
if (maxlength - length >= (long)size)
{
std::memcpy(buffer + length, ptr, size);
}
length += size;
}
void NewStateExternalBuffer::Load(void *ptr, size_t size, const char *name)
{
char *dst = static_cast<char *>(ptr);
if (maxlength - length >= (long)size)
{
std::memcpy(dst, buffer + length, size);
}
length += size;
}
NewStateExternalFunctions::NewStateExternalFunctions(const FPtrs *ff)
:Save_(ff->Save_),
Load_(ff->Load_),
EnterSection_(ff->EnterSection_),
ExitSection_(ff->ExitSection_)
{
}
void NewStateExternalFunctions::Save(const void *ptr, size_t size, const char *name)
{
Save_(ptr, size, name);
}
void NewStateExternalFunctions::Load(void *ptr, size_t size, const char *name)
{
Load_(ptr, size, name);
}
void NewStateExternalFunctions::EnterSection(const char *name, ...)
{
//analysis: multiple passes to generate string not ideal, but there arent many sections.. so it should be OK. improvement would be special vararg overload
va_list ap;
va_start(ap,name);
char easybuf[32];
int size = vsnprintf(easybuf,0,name,ap);
char *ptr = easybuf;
if(size>31)
ptr = (char*)malloc(size+1);
vsprintf(ptr,name,ap);
EnterSection_(ptr);
if(ptr != easybuf)
free(ptr);
va_end(ap);
}
void NewStateExternalFunctions::ExitSection(const char *name, ...)
{
va_list ap;
va_start(ap,name);
char easybuf[32];
int size = vsnprintf(easybuf,0,name,ap);
char *ptr = easybuf;
if(size>31)
ptr = (char*)malloc(size+1);
vsprintf(ptr,name,ap);
ExitSection_(ptr);
if(ptr != easybuf)
free(ptr);
va_end(ap);
}
}

View File

@ -1,105 +0,0 @@
#ifndef NEWSTATE_H
#define NEWSTATE_H
#include <cstring>
#include <cstddef>
namespace EW
{
class NewState
{
public:
virtual void Save(const void *ptr, size_t size, const char *name) = 0;
virtual void Load(void *ptr, size_t size, const char *name) = 0;
virtual void EnterSection(const char *name, ...) { }
virtual void ExitSection(const char *name, ...) { }
};
class NewStateDummy : public NewState
{
private:
long length;
public:
NewStateDummy();
long GetLength() { return length; }
void Rewind() { length = 0; }
virtual void Save(const void *ptr, size_t size, const char *name);
virtual void Load(void *ptr, size_t size, const char *name);
};
class NewStateExternalBuffer : public NewState
{
private:
char *const buffer;
long length;
const long maxlength;
public:
NewStateExternalBuffer(char *buffer, long maxlength);
long GetLength() { return length; }
void Rewind() { length = 0; }
bool Overflow() { return length > maxlength; }
virtual void Save(const void *ptr, size_t size, const char *name);
virtual void Load(void *ptr, size_t size, const char *name);
};
struct FPtrs
{
void (*Save_)(const void *ptr, size_t size, const char *name);
void (*Load_)(void *ptr, size_t size, const char *name);
void (*EnterSection_)(const char *name);
void (*ExitSection_)(const char *name);
};
class NewStateExternalFunctions : public NewState
{
private:
void (*Save_)(const void *ptr, size_t size, const char *name);
void (*Load_)(void *ptr, size_t size, const char *name);
void (*EnterSection_)(const char *name);
void (*ExitSection_)(const char *name);
public:
NewStateExternalFunctions(const FPtrs *ff);
virtual void Save(const void *ptr, size_t size, const char *name);
virtual void Load(void *ptr, size_t size, const char *name);
virtual void EnterSection(const char *name, ...);
virtual void ExitSection(const char *name, ...);
};
// defines and explicitly instantiates
#define SYNCFUNC(x)\
template void x::SyncState<false>(EW::NewState *ns);\
template void x::SyncState<true>(EW::NewState *ns);\
template<bool isReader>void x::SyncState(EW::NewState *ns)
// N = normal variable
// P = pointer to fixed size data
// S = "sub object"
// T = "ptr to sub object"
// R = pointer, store its offset from some other pointer
// E = general purpose cased value "enum"
// first line is default value in converted enum; last line is default value in argument x
#define EBS(x,d) do { int _ttmp = (d); if (isReader) ns->Load(&_ttmp, sizeof(_ttmp), #x); if (0)
#define EVS(x,v,n) else if (!isReader && (x) == (v)) _ttmp = (n); else if (isReader && _ttmp == (n)) (x) = (v)
#define EES(x,d) else if (isReader) (x) = (d); if (!isReader) ns->Save(&_ttmp, sizeof(_ttmp), #x); } while (0)
#define RSS(x,b) do { if (isReader)\
{ ptrdiff_t _ttmp; ns->Load(&_ttmp, sizeof(_ttmp), #x); (x) = (_ttmp == (ptrdiff_t)0xdeadbeef ? 0 : (b) + _ttmp); }\
else\
{ ptrdiff_t _ttmp = (x) == 0 ? 0xdeadbeef : (x) - (b); ns->Save(&_ttmp, sizeof(_ttmp), #x); } } while (0)
#define PSS(x,s) do { if (isReader) ns->Load((x), (s), #x); else ns->Save((x), (s), #x); } while (0)
#define NSS(x) do { if (isReader) ns->Load(&(x), sizeof(x), #x); else ns->Save(&(x), sizeof(x), #x); } while (0)
#define SSS(x) do { ns->EnterSection(#x); (x).SyncState<isReader>(ns); ns->ExitSection(#x); } while (0)
#define TSS(x) do { ns->EnterSection(#x); (x)->SyncState<isReader>(ns); ns->ExitSection(#x); } while (0)
}
#endif //NEWSTATE_H

View File

@ -1,12 +0,0 @@
#ifndef __GNUC__
#pragma pack(push, 1)
#pragma warning(disable : 4103)
#endif
#ifndef __PACKED
#ifdef __GNUC__
#define __PACKED __attribute__((__packed__))
#else
#define __PACKED
#endif
#endif

View File

@ -1,3 +0,0 @@
#ifndef __GNUC__
#pragma pack(pop)
#endif

View File

@ -1,3 +0,0 @@
#include "emuware.h"
//this file intentionally empty

View File

@ -1,160 +0,0 @@
#pragma once
#include <inttypes.h>
#include <stdint.h>
#include <cstdlib>
#ifdef _MSC_VER
typedef __int64 s64;
typedef __int32 s32;
typedef __int16 s16;
typedef __int8 s8;
typedef unsigned __int64 u64;
typedef unsigned __int32 u32;
typedef unsigned __int16 u16;
typedef unsigned __int8 u8;
typedef __int64 int64;
typedef __int32 int32;
typedef __int16 int16;
typedef __int8 int8;
typedef unsigned __int64 uint64;
typedef unsigned __int32 uint32;
typedef unsigned __int16 uint16;
typedef unsigned __int8 uint8;
#else
typedef __int64_t s64;
typedef __int32_t s32;
typedef __int16_t s16;
typedef __int8_t s8;
typedef __uint64_t u64;
typedef __uint32_t u32;
typedef __uint16_t u16;
typedef __uint8_t u8;
typedef __int64_t int64;
typedef __int32_t int32;
typedef __int16_t int16;
typedef __int8_t int8;
typedef __uint64_t uint64;
typedef __uint32_t uint32;
typedef __uint16_t uint16;
typedef __uint8_t uint8;
#endif
#define final
#define noexcept
#ifdef _MSC_VER
#include <intrin.h>
//http://stackoverflow.com/questions/355967/how-to-use-msvc-intrinsics-to-get-the-equivalent-of-this-gcc-code
//if needed
//uint32_t __inline ctz( uint32_t value )
//{
// DWORD trailing_zero = 0;
//
// if ( _BitScanForward( &trailing_zero, value ) )
// {
// return trailing_zero;
// }
// else
// {
// // This is undefined, I better choose 32 than 0
// return 32;
// }
//}
uint32 __inline __builtin_clz( uint32_t value )
{
unsigned long leading_zero = 0;
if ( _BitScanReverse( &leading_zero, value ) )
{
return 31 - leading_zero;
}
else
{
// Same remarks as above
return 32;
}
}
#endif
//#if MDFN_GCC_VERSION >= MDFN_MAKE_GCCV(4,7,0)
// #define MDFN_ASSUME_ALIGNED(p, align) __builtin_assume_aligned((p), (align))
//#else
// #define MDFN_ASSUME_ALIGNED(p, align) (p)
//#endif
#define MDFN_ASSUME_ALIGNED(p, align) (p)
//#define MDFN_WARN_UNUSED_RESULT __attribute__ ((warn_unused_result))
#define MDFN_WARN_UNUSED_RESULT
//#define MDFN_COLD __attribute__((cold))
#define MDFN_COLD
//#define NO_INLINE __attribute__((noinline))
#define NO_INLINE
//#define MDFN_UNLIKELY(n) __builtin_expect((n) != 0, 0)
//#define MDFN_LIKELY(n) __builtin_expect((n) != 0, 1)
#define MDFN_UNLIKELY(n) (n)
#define MDFN_LIKELY(n) (n)
//#define MDFN_NOWARN_UNUSED __attribute__((unused))
#define MDFN_NOWARN_UNUSED
//#define MDFN_FORMATSTR(a,b,c) __attribute__ ((format (a, b, c)))
#define MDFN_FORMATSTR(a,b,c)
#define INLINE inline
#ifndef UNALIGNED
#define UNALIGNED
#endif
#ifdef _MSC_VER
#define snprintf _snprintf
#define vsnprintf _vsnprintf
#define strcasecmp _stricmp
#define strncasecmp _strnicmp
#endif
#define TRUE_1 1
#define FALSE_0 0
#ifndef ARRAY_SIZE
//taken from winnt.h
extern "C++" // templates cannot be declared to have 'C' linkage
template <typename T, size_t N>
char (*BLAHBLAHBLAH( UNALIGNED T (&)[N] ))[N];
#define ARRAY_SIZE(A) (sizeof(*BLAHBLAHBLAH(A)))
#endif
//------------alignment macros-------------
//dont apply these to types without further testing. it only works portably here on declarations of variables
//cant we find a pattern other people use more successfully?
#if defined(_MSC_VER) || defined(__INTEL_COMPILER)
#define EW_VAR_ALIGN(X) __declspec(align(X))
#elif defined(__GNUC__)
#define EW_VAR_ALIGN(X) __attribute__ ((aligned (X)))
#else
#error
#endif
//---------------------------------------------
#ifdef EW_EXPORT
#undef EW_EXPORT
#define EW_EXPORT extern "C" __declspec(dllexport)
#else
#define EW_EXPORT extern "C" __declspec(dllimport)
#endif
#define SIZEOF_DOUBLE 8
#define LSB_FIRST
//no MSVC support, no use anyway??
#define override

View File

@ -1,138 +0,0 @@
------------------------------------------------------------------------
r26 | 2009-10-02 13:36:47 +0400 | 2 lines
[Issue 5] Change <stdint.h> to "stdint.h" to let compiler search for it in local directory.
------------------------------------------------------------------------
r25 | 2009-09-17 23:46:49 +0400 | 2 lines
[Issue 4] Fix incorrect int8_t behaviour if compiled with /J flag.
------------------------------------------------------------------------
r24 | 2009-05-13 14:53:48 +0400 | 2 lines
Forgot about #ifdef __cplusplus guard around 'extern "C"', so inclusion to C files has been broken.
------------------------------------------------------------------------
r23 | 2009-05-12 01:27:45 +0400 | 3 lines
[Issue 2] Always wrap <wcharîàž with external "C" {}.
It turns out that not only Visual Studio 6 requires this, but also newer versions when compiling for ARM.
------------------------------------------------------------------------
r22 | 2009-05-11 22:22:15 +0400 | 3 lines
[Issue 3] Visual Studio 6 and Embedded Visual C++ 4 doesn't realize that, e.g. char has the same size as __int8 so we give up on __intX for them.
his should close Issue 3 in issue tracker.
------------------------------------------------------------------------
r21 | 2008-07-17 09:47:22 +0400 | 4 lines
Get rid of these compiler warnings when compiling for 32-bit:
warning C4311: 'type cast' : pointer truncation from 'void *' to 'uintptr_t'
warning C4312: 'type cast' : conversion from 'uintptr_t' to 'const void *' of greater size
------------------------------------------------------------------------
r20 | 2007-10-09 16:54:27 +0400 | 2 lines
Better C99 conformance: macros for format specifiers should only be included in C++ implementations if __STDC_FORMAT_MACROS is defined before <inttypes.h> is included.
------------------------------------------------------------------------
r19 | 2007-07-04 02:14:40 +0400 | 3 lines
Explicitly cast to appropriate type INT8_MIN, INT16_MIN, INT32_MIN and INT64_MIN constants.
Due to their unusual definition in Visual Studio headers (-_Ix_MAX-1) they are propagated to int and thus do not have expected type, causing VS6 strict compiler to claim about type inconsistency.
------------------------------------------------------------------------
r18 | 2007-06-26 16:53:23 +0400 | 2 lines
Better handling of (U)INTx_C macros - now they generate constants of exact width.
------------------------------------------------------------------------
r17 | 2007-03-29 20:16:14 +0400 | 2 lines
Fix typo: Miscrosoft -> Microsoft.
------------------------------------------------------------------------
r16 | 2007-02-24 17:32:58 +0300 | 4 lines
Remove <BaseTsd.h> include, as it is not present in Visual Studio 2005 Epxress Edition and required only for INT_PTR and UINT_PTR types.
'intptr_t' and 'uintptr_t' types now defined explicitly with #ifdef _WIN64.
------------------------------------------------------------------------
r15 | 2007-02-11 20:53:05 +0300 | 2 lines
More correct fix for compilation under VS6.
------------------------------------------------------------------------
r14 | 2007-02-11 20:04:32 +0300 | 2 lines
Bugfix: fix compiling under VS6, when stdint.h enclosed in 'extern "C" {}'.
------------------------------------------------------------------------
r13 | 2006-12-13 16:53:11 +0300 | 2 lines
Make _inline modifier for imaxdiv default option. Use STATIC_IMAXDIV to make it static.
------------------------------------------------------------------------
r12 | 2006-12-13 16:42:24 +0300 | 2 lines
Error message changed: VC6 supported from now.
------------------------------------------------------------------------
r11 | 2006-12-13 16:39:33 +0300 | 2 lines
All (U)INT* types changed to (unsigned) __int*. This should make stdint.h compatible with VC6.
------------------------------------------------------------------------
r10 | 2006-12-13 16:20:57 +0300 | 3 lines
Added INLINE_IMAXDIV define switch.
If INLINE_IMAXDIV is defined imaxdiv() have static modifier. If not - it is _inline.
------------------------------------------------------------------------
r9 | 2006-12-13 15:53:52 +0300 | 2 lines
Error message for non-MSC compiler changed.
------------------------------------------------------------------------
r8 | 2006-12-13 12:47:48 +0300 | 2 lines
Added #ifndef for SIZE_MAX (it is defined in limits.h on MSVSC 8).
------------------------------------------------------------------------
r7 | 2006-12-13 01:08:02 +0300 | 2 lines
License chaged to BSD-derivative.
------------------------------------------------------------------------
r6 | 2006-12-13 00:53:20 +0300 | 2 lines
Added <wchar.h> include to avoid warnings when it is included after stdint.h.
------------------------------------------------------------------------
r5 | 2006-12-12 00:58:05 +0300 | 2 lines
BUGFIX: Definitions of INTPTR_MIN, INTPTR_MAX and UINTPTR_MAX for WIN32 and WIN64 was mixed up.
------------------------------------------------------------------------
r4 | 2006-12-12 00:51:55 +0300 | 2 lines
Rise #error if _MSC_VER is not defined. I.e. compiler other then Microsoft Visual C++ is used.
------------------------------------------------------------------------
r3 | 2006-12-11 22:54:14 +0300 | 2 lines
Added <limits.h> include to stdint.h.
------------------------------------------------------------------------
r2 | 2006-12-11 21:39:27 +0300 | 2 lines
Initial check in.
------------------------------------------------------------------------
r1 | 2006-12-11 21:30:23 +0300 | 1 line
Initial directory structure.
------------------------------------------------------------------------

View File

@ -1,305 +0,0 @@
// ISO C9x compliant inttypes.h for Microsoft Visual Studio
// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124
//
// Copyright (c) 2006 Alexander Chemeris
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// 3. The name of the author may be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////////
#ifndef _MSC_VER // [
#error "Use this header only with Microsoft Visual C++ compilers!"
#endif // _MSC_VER ]
#ifndef _MSC_INTTYPES_H_ // [
#define _MSC_INTTYPES_H_
#if _MSC_VER > 1000
#pragma once
#endif
#include "stdint.h"
// 7.8 Format conversion of integer types
typedef struct {
intmax_t quot;
intmax_t rem;
} imaxdiv_t;
// 7.8.1 Macros for format specifiers
#if !defined(__cplusplus) || defined(__STDC_FORMAT_MACROS) // [ See footnote 185 at page 198
// The fprintf macros for signed integers are:
#define PRId8 "d"
#define PRIi8 "i"
#define PRIdLEAST8 "d"
#define PRIiLEAST8 "i"
#define PRIdFAST8 "d"
#define PRIiFAST8 "i"
#define PRId16 "hd"
#define PRIi16 "hi"
#define PRIdLEAST16 "hd"
#define PRIiLEAST16 "hi"
#define PRIdFAST16 "hd"
#define PRIiFAST16 "hi"
#define PRId32 "I32d"
#define PRIi32 "I32i"
#define PRIdLEAST32 "I32d"
#define PRIiLEAST32 "I32i"
#define PRIdFAST32 "I32d"
#define PRIiFAST32 "I32i"
#define PRId64 "I64d"
#define PRIi64 "I64i"
#define PRIdLEAST64 "I64d"
#define PRIiLEAST64 "I64i"
#define PRIdFAST64 "I64d"
#define PRIiFAST64 "I64i"
#define PRIdMAX "I64d"
#define PRIiMAX "I64i"
#define PRIdPTR "Id"
#define PRIiPTR "Ii"
// The fprintf macros for unsigned integers are:
#define PRIo8 "o"
#define PRIu8 "u"
#define PRIx8 "x"
#define PRIX8 "X"
#define PRIoLEAST8 "o"
#define PRIuLEAST8 "u"
#define PRIxLEAST8 "x"
#define PRIXLEAST8 "X"
#define PRIoFAST8 "o"
#define PRIuFAST8 "u"
#define PRIxFAST8 "x"
#define PRIXFAST8 "X"
#define PRIo16 "ho"
#define PRIu16 "hu"
#define PRIx16 "hx"
#define PRIX16 "hX"
#define PRIoLEAST16 "ho"
#define PRIuLEAST16 "hu"
#define PRIxLEAST16 "hx"
#define PRIXLEAST16 "hX"
#define PRIoFAST16 "ho"
#define PRIuFAST16 "hu"
#define PRIxFAST16 "hx"
#define PRIXFAST16 "hX"
#define PRIo32 "I32o"
#define PRIu32 "I32u"
#define PRIx32 "I32x"
#define PRIX32 "I32X"
#define PRIoLEAST32 "I32o"
#define PRIuLEAST32 "I32u"
#define PRIxLEAST32 "I32x"
#define PRIXLEAST32 "I32X"
#define PRIoFAST32 "I32o"
#define PRIuFAST32 "I32u"
#define PRIxFAST32 "I32x"
#define PRIXFAST32 "I32X"
#define PRIo64 "I64o"
#define PRIu64 "I64u"
#define PRIx64 "I64x"
#define PRIX64 "I64X"
#define PRIoLEAST64 "I64o"
#define PRIuLEAST64 "I64u"
#define PRIxLEAST64 "I64x"
#define PRIXLEAST64 "I64X"
#define PRIoFAST64 "I64o"
#define PRIuFAST64 "I64u"
#define PRIxFAST64 "I64x"
#define PRIXFAST64 "I64X"
#define PRIoMAX "I64o"
#define PRIuMAX "I64u"
#define PRIxMAX "I64x"
#define PRIXMAX "I64X"
#define PRIoPTR "Io"
#define PRIuPTR "Iu"
#define PRIxPTR "Ix"
#define PRIXPTR "IX"
// The fscanf macros for signed integers are:
#define SCNd8 "d"
#define SCNi8 "i"
#define SCNdLEAST8 "d"
#define SCNiLEAST8 "i"
#define SCNdFAST8 "d"
#define SCNiFAST8 "i"
#define SCNd16 "hd"
#define SCNi16 "hi"
#define SCNdLEAST16 "hd"
#define SCNiLEAST16 "hi"
#define SCNdFAST16 "hd"
#define SCNiFAST16 "hi"
#define SCNd32 "ld"
#define SCNi32 "li"
#define SCNdLEAST32 "ld"
#define SCNiLEAST32 "li"
#define SCNdFAST32 "ld"
#define SCNiFAST32 "li"
#define SCNd64 "I64d"
#define SCNi64 "I64i"
#define SCNdLEAST64 "I64d"
#define SCNiLEAST64 "I64i"
#define SCNdFAST64 "I64d"
#define SCNiFAST64 "I64i"
#define SCNdMAX "I64d"
#define SCNiMAX "I64i"
#ifdef _WIN64 // [
# define SCNdPTR "I64d"
# define SCNiPTR "I64i"
#else // _WIN64 ][
# define SCNdPTR "ld"
# define SCNiPTR "li"
#endif // _WIN64 ]
// The fscanf macros for unsigned integers are:
#define SCNo8 "o"
#define SCNu8 "u"
#define SCNx8 "x"
#define SCNX8 "X"
#define SCNoLEAST8 "o"
#define SCNuLEAST8 "u"
#define SCNxLEAST8 "x"
#define SCNXLEAST8 "X"
#define SCNoFAST8 "o"
#define SCNuFAST8 "u"
#define SCNxFAST8 "x"
#define SCNXFAST8 "X"
#define SCNo16 "ho"
#define SCNu16 "hu"
#define SCNx16 "hx"
#define SCNX16 "hX"
#define SCNoLEAST16 "ho"
#define SCNuLEAST16 "hu"
#define SCNxLEAST16 "hx"
#define SCNXLEAST16 "hX"
#define SCNoFAST16 "ho"
#define SCNuFAST16 "hu"
#define SCNxFAST16 "hx"
#define SCNXFAST16 "hX"
#define SCNo32 "lo"
#define SCNu32 "lu"
#define SCNx32 "lx"
#define SCNX32 "lX"
#define SCNoLEAST32 "lo"
#define SCNuLEAST32 "lu"
#define SCNxLEAST32 "lx"
#define SCNXLEAST32 "lX"
#define SCNoFAST32 "lo"
#define SCNuFAST32 "lu"
#define SCNxFAST32 "lx"
#define SCNXFAST32 "lX"
#define SCNo64 "I64o"
#define SCNu64 "I64u"
#define SCNx64 "I64x"
#define SCNX64 "I64X"
#define SCNoLEAST64 "I64o"
#define SCNuLEAST64 "I64u"
#define SCNxLEAST64 "I64x"
#define SCNXLEAST64 "I64X"
#define SCNoFAST64 "I64o"
#define SCNuFAST64 "I64u"
#define SCNxFAST64 "I64x"
#define SCNXFAST64 "I64X"
#define SCNoMAX "I64o"
#define SCNuMAX "I64u"
#define SCNxMAX "I64x"
#define SCNXMAX "I64X"
#ifdef _WIN64 // [
# define SCNoPTR "I64o"
# define SCNuPTR "I64u"
# define SCNxPTR "I64x"
# define SCNXPTR "I64X"
#else // _WIN64 ][
# define SCNoPTR "lo"
# define SCNuPTR "lu"
# define SCNxPTR "lx"
# define SCNXPTR "lX"
#endif // _WIN64 ]
#endif // __STDC_FORMAT_MACROS ]
// 7.8.2 Functions for greatest-width integer types
// 7.8.2.1 The imaxabs function
#define imaxabs _abs64
// 7.8.2.2 The imaxdiv function
// This is modified version of div() function from Microsoft's div.c found
// in %MSVC.NET%\crt\src\div.c
#ifdef STATIC_IMAXDIV // [
static
#else // STATIC_IMAXDIV ][
_inline
#endif // STATIC_IMAXDIV ]
imaxdiv_t __cdecl imaxdiv(intmax_t numer, intmax_t denom)
{
imaxdiv_t result;
result.quot = numer / denom;
result.rem = numer % denom;
if (numer < 0 && result.rem > 0) {
// did division wrong; must fix up
++result.quot;
result.rem -= denom;
}
return result;
}
// 7.8.2.3 The strtoimax and strtoumax functions
#define strtoimax _strtoi64
#define strtoumax _strtoui64
// 7.8.2.4 The wcstoimax and wcstoumax functions
#define wcstoimax _wcstoi64
#define wcstoumax _wcstoui64
#endif // _MSC_INTTYPES_H_ ]

View File

@ -1,247 +0,0 @@
// ISO C9x compliant stdint.h for Microsoft Visual Studio
// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124
//
// Copyright (c) 2006-2008 Alexander Chemeris
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// 3. The name of the author may be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////////
#ifndef _MSC_VER // [
#error "Use this header only with Microsoft Visual C++ compilers!"
#endif // _MSC_VER ]
#ifndef _MSC_STDINT_H_ // [
#define _MSC_STDINT_H_
#if _MSC_VER > 1000
#pragma once
#endif
#include <limits.h>
// For Visual Studio 6 in C++ mode and for many Visual Studio versions when
// compiling for ARM we should wrap <wchar.h> include with 'extern "C++" {}'
// or compiler give many errors like this:
// error C2733: second C linkage of overloaded function 'wmemchr' not allowed
#ifdef __cplusplus
extern "C" {
#endif
# include <wchar.h>
#ifdef __cplusplus
}
#endif
// Define _W64 macros to mark types changing their size, like intptr_t.
#ifndef _W64
# if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300
# define _W64 __w64
# else
# define _W64
# endif
#endif
// 7.18.1 Integer types
// 7.18.1.1 Exact-width integer types
// Visual Studio 6 and Embedded Visual C++ 4 doesn't
// realize that, e.g. char has the same size as __int8
// so we give up on __intX for them.
#if (_MSC_VER < 1300)
typedef signed char int8_t;
typedef signed short int16_t;
typedef signed int int32_t;
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
#else
typedef signed __int8 int8_t;
typedef signed __int16 int16_t;
typedef signed __int32 int32_t;
typedef unsigned __int8 uint8_t;
typedef unsigned __int16 uint16_t;
typedef unsigned __int32 uint32_t;
#endif
typedef signed __int64 int64_t;
typedef unsigned __int64 uint64_t;
// 7.18.1.2 Minimum-width integer types
typedef int8_t int_least8_t;
typedef int16_t int_least16_t;
typedef int32_t int_least32_t;
typedef int64_t int_least64_t;
typedef uint8_t uint_least8_t;
typedef uint16_t uint_least16_t;
typedef uint32_t uint_least32_t;
typedef uint64_t uint_least64_t;
// 7.18.1.3 Fastest minimum-width integer types
typedef int8_t int_fast8_t;
typedef int16_t int_fast16_t;
typedef int32_t int_fast32_t;
typedef int64_t int_fast64_t;
typedef uint8_t uint_fast8_t;
typedef uint16_t uint_fast16_t;
typedef uint32_t uint_fast32_t;
typedef uint64_t uint_fast64_t;
// 7.18.1.4 Integer types capable of holding object pointers
#ifdef _WIN64 // [
typedef signed __int64 intptr_t;
typedef unsigned __int64 uintptr_t;
#else // _WIN64 ][
typedef _W64 signed int intptr_t;
typedef _W64 unsigned int uintptr_t;
#endif // _WIN64 ]
// 7.18.1.5 Greatest-width integer types
typedef int64_t intmax_t;
typedef uint64_t uintmax_t;
// 7.18.2 Limits of specified-width integer types
#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and footnote 221 at page 259
// 7.18.2.1 Limits of exact-width integer types
#define INT8_MIN ((int8_t)_I8_MIN)
#define INT8_MAX _I8_MAX
#define INT16_MIN ((int16_t)_I16_MIN)
#define INT16_MAX _I16_MAX
#define INT32_MIN ((int32_t)_I32_MIN)
#define INT32_MAX _I32_MAX
#define INT64_MIN ((int64_t)_I64_MIN)
#define INT64_MAX _I64_MAX
#define UINT8_MAX _UI8_MAX
#define UINT16_MAX _UI16_MAX
#define UINT32_MAX _UI32_MAX
#define UINT64_MAX _UI64_MAX
// 7.18.2.2 Limits of minimum-width integer types
#define INT_LEAST8_MIN INT8_MIN
#define INT_LEAST8_MAX INT8_MAX
#define INT_LEAST16_MIN INT16_MIN
#define INT_LEAST16_MAX INT16_MAX
#define INT_LEAST32_MIN INT32_MIN
#define INT_LEAST32_MAX INT32_MAX
#define INT_LEAST64_MIN INT64_MIN
#define INT_LEAST64_MAX INT64_MAX
#define UINT_LEAST8_MAX UINT8_MAX
#define UINT_LEAST16_MAX UINT16_MAX
#define UINT_LEAST32_MAX UINT32_MAX
#define UINT_LEAST64_MAX UINT64_MAX
// 7.18.2.3 Limits of fastest minimum-width integer types
#define INT_FAST8_MIN INT8_MIN
#define INT_FAST8_MAX INT8_MAX
#define INT_FAST16_MIN INT16_MIN
#define INT_FAST16_MAX INT16_MAX
#define INT_FAST32_MIN INT32_MIN
#define INT_FAST32_MAX INT32_MAX
#define INT_FAST64_MIN INT64_MIN
#define INT_FAST64_MAX INT64_MAX
#define UINT_FAST8_MAX UINT8_MAX
#define UINT_FAST16_MAX UINT16_MAX
#define UINT_FAST32_MAX UINT32_MAX
#define UINT_FAST64_MAX UINT64_MAX
// 7.18.2.4 Limits of integer types capable of holding object pointers
#ifdef _WIN64 // [
# define INTPTR_MIN INT64_MIN
# define INTPTR_MAX INT64_MAX
# define UINTPTR_MAX UINT64_MAX
#else // _WIN64 ][
# define INTPTR_MIN INT32_MIN
# define INTPTR_MAX INT32_MAX
# define UINTPTR_MAX UINT32_MAX
#endif // _WIN64 ]
// 7.18.2.5 Limits of greatest-width integer types
#define INTMAX_MIN INT64_MIN
#define INTMAX_MAX INT64_MAX
#define UINTMAX_MAX UINT64_MAX
// 7.18.3 Limits of other integer types
#ifdef _WIN64 // [
# define PTRDIFF_MIN _I64_MIN
# define PTRDIFF_MAX _I64_MAX
#else // _WIN64 ][
# define PTRDIFF_MIN _I32_MIN
# define PTRDIFF_MAX _I32_MAX
#endif // _WIN64 ]
#define SIG_ATOMIC_MIN INT_MIN
#define SIG_ATOMIC_MAX INT_MAX
#ifndef SIZE_MAX // [
# ifdef _WIN64 // [
# define SIZE_MAX _UI64_MAX
# else // _WIN64 ][
# define SIZE_MAX _UI32_MAX
# endif // _WIN64 ]
#endif // SIZE_MAX ]
// WCHAR_MIN and WCHAR_MAX are also defined in <wchar.h>
#ifndef WCHAR_MIN // [
# define WCHAR_MIN 0
#endif // WCHAR_MIN ]
#ifndef WCHAR_MAX // [
# define WCHAR_MAX _UI16_MAX
#endif // WCHAR_MAX ]
#define WINT_MIN 0
#define WINT_MAX _UI16_MAX
#endif // __STDC_LIMIT_MACROS ]
// 7.18.4 Limits of other integer types
#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260
// 7.18.4.1 Macros for minimum-width integer constants
#define INT8_C(val) val##i8
#define INT16_C(val) val##i16
#define INT32_C(val) val##i32
#define INT64_C(val) val##i64
#define UINT8_C(val) val##ui8
#define UINT16_C(val) val##ui16
#define UINT32_C(val) val##ui32
#define UINT64_C(val) val##ui64
// 7.18.4.2 Macros for greatest-width integer constants
#define INTMAX_C INT64_C
#define UINTMAX_C UINT64_C
#endif // __STDC_CONSTANT_MACROS ]
#endif // _MSC_STDINT_H_ ]

View File

@ -1,151 +0,0 @@
/* Mednafen - Multi-system Emulator
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <stdio.h>
#include "emuware/emuware.h"
#include "endian.h"
void Endian_A16_Swap(void *src, uint32 nelements)
{
uint32 i;
uint8 *nsrc = (uint8 *)src;
for(i = 0; i < nelements; i++)
{
uint8 tmp = nsrc[i * 2];
nsrc[i * 2] = nsrc[i * 2 + 1];
nsrc[i * 2 + 1] = tmp;
}
}
void Endian_A32_Swap(void *src, uint32 nelements)
{
uint32 i;
uint8 *nsrc = (uint8 *)src;
for(i = 0; i < nelements; i++)
{
uint8 tmp1 = nsrc[i * 4];
uint8 tmp2 = nsrc[i * 4 + 1];
nsrc[i * 4] = nsrc[i * 4 + 3];
nsrc[i * 4 + 1] = nsrc[i * 4 + 2];
nsrc[i * 4 + 2] = tmp2;
nsrc[i * 4 + 3] = tmp1;
}
}
void Endian_A64_Swap(void *src, uint32 nelements)
{
uint32 i;
uint8 *nsrc = (uint8 *)src;
for(i = 0; i < nelements; i++)
{
uint8 *base = &nsrc[i * 8];
for(int z = 0; z < 4; z++)
{
uint8 tmp = base[z];
base[z] = base[7 - z];
base[7 - z] = tmp;
}
}
}
void Endian_A16_NE_LE(void *src, uint32 nelements)
{
#ifdef MSB_FIRST
Endian_A16_Swap(src, nelements);
#endif
}
void Endian_A32_NE_LE(void *src, uint32 nelements)
{
#ifdef MSB_FIRST
Endian_A32_Swap(src, nelements);
#endif
}
void Endian_A64_NE_LE(void *src, uint32 nelements)
{
#ifdef MSB_FIRST
Endian_A64_Swap(src, nelements);
#endif
}
//
//
//
void Endian_A16_NE_BE(void *src, uint32 nelements)
{
#ifdef LSB_FIRST
Endian_A16_Swap(src, nelements);
#endif
}
void Endian_A32_NE_BE(void *src, uint32 nelements)
{
#ifdef LSB_FIRST
Endian_A32_Swap(src, nelements);
#endif
}
void Endian_A64_NE_BE(void *src, uint32 nelements)
{
#ifdef LSB_FIRST
Endian_A64_Swap(src, nelements);
#endif
}
static void FlipByteOrder(uint8 *src, uint32 count)
{
uint8 *start=src;
uint8 *end=src+count-1;
if((count&1) || !count) return; /* This shouldn't happen. */
count >>= 1;
while(count--)
{
uint8 tmp;
tmp=*end;
*end=*start;
*start=tmp;
end--;
start++;
}
}
void Endian_V_NE_LE(void *src, uint32 bytesize)
{
#ifdef MSB_FIRST
FlipByteOrder((uint8 *)src, bytesize);
#endif
}
void Endian_V_NE_BE(void *src, uint32 bytesize)
{
#ifdef LSB_FIRST
FlipByteOrder((uint8 *)src, bytesize);
#endif
}

View File

@ -1,296 +0,0 @@
#ifndef __MDFN_ENDIAN_H
#define __MDFN_ENDIAN_H
#pragma warning(once : 4519)
static INLINE uint32 BitsExtract(const uint8* ptr, const size_t bit_offset, const size_t bit_count)
{
uint32 ret = 0;
for(size_t x = 0; x < bit_count; x++)
{
size_t co = bit_offset + x;
bool b = (ptr[co >> 3] >> (co & 7)) & 1;
ret |= (uint64)b << x;
}
return ret;
}
static INLINE void BitsIntract(uint8* ptr, const size_t bit_offset, const size_t bit_count, uint32 value)
{
for(size_t x = 0; x < bit_count; x++)
{
size_t co = bit_offset + x;
bool b = (value >> x) & 1;
uint8 tmp = ptr[co >> 3];
tmp &= ~(1 << (co & 7));
tmp |= b << (co & 7);
ptr[co >> 3] = tmp;
}
}
/*
Regarding safety of calling MDFN_*sb<true> on dynamically-allocated memory with new uint8[], see C++ standard 3.7.3.1(i.e. it should be
safe provided the offsets into the memory are aligned/multiples of the MDFN_*sb access type). malloc()'d and calloc()'d
memory should be safe as well.
Statically-allocated arrays/memory should be unioned with a big POD type or C++11 "alignas"'d. (May need to audit code to ensure
this is being done).
*/
void Endian_A16_Swap(void *src, uint32 nelements);
void Endian_A32_Swap(void *src, uint32 nelements);
void Endian_A64_Swap(void *src, uint32 nelements);
void Endian_A16_NE_LE(void *src, uint32 nelements);
void Endian_A32_NE_LE(void *src, uint32 nelements);
void Endian_A64_NE_LE(void *src, uint32 nelements);
void Endian_A16_NE_BE(void *src, uint32 nelements);
void Endian_A32_NE_BE(void *src, uint32 nelements);
void Endian_A64_NE_BE(void *src, uint32 nelements);
void Endian_V_NE_LE(void *src, uint32 bytesize);
void Endian_V_NE_BE(void *src, uint32 bytesize);
static INLINE uint16 MDFN_bswap16(uint16 v)
{
return (v << 8) | (v >> 8);
}
static INLINE uint32 MDFN_bswap32(uint32 v)
{
return (v << 24) | ((v & 0xFF00) << 8) | ((v >> 8) & 0xFF00) | (v >> 24);
}
static INLINE uint64 MDFN_bswap64(uint64 v)
{
//octoshock edit
//return (v << 56) | (v >> 56) | ((v & 0xFF00) << 40) | ((v >> 40) & 0xFF00) | ((uint64)MDFN_bswap32(v >> 16) << 16);
return (v << 56) | (v >> 56) | ((v & 0xFF00) << 40) | ((v >> 40) & 0xFF00) | ((uint64)MDFN_bswap32(((uint32)v) >> 16) << 16);
}
#ifdef LSB_FIRST
#define MDFN_ENDIANH_IS_BIGENDIAN 0
#else
#define MDFN_ENDIANH_IS_BIGENDIAN 1
#endif
//
// X endian.
//
template<int isbigendian, typename T, bool aligned>
static INLINE T MDFN_deXsb(const void* ptr)
{
T tmp;
memcpy(&tmp, MDFN_ASSUME_ALIGNED(ptr, (aligned ? sizeof(T) : 1)), sizeof(T));
if(isbigendian != -1 && isbigendian != MDFN_ENDIANH_IS_BIGENDIAN)
{
static_assert(sizeof(T) == 1 || sizeof(T) == 2 || sizeof(T) == 4 || sizeof(T) == 8, "Gummy penguins.");
if(sizeof(T) == 8)
return (T)MDFN_bswap64(tmp);
else if(sizeof(T) == 4)
return (T)MDFN_bswap32(tmp);
else if(sizeof(T) == 2)
return (T)MDFN_bswap16(tmp);
}
return tmp;
}
//
// Native endian.
//
template<typename T, bool aligned = false>
static INLINE T MDFN_densb(const void* ptr)
{
return MDFN_deXsb<-1, T, aligned>(ptr);
}
//
// Little endian.
//
template<typename T, bool aligned = false>
static INLINE T MDFN_delsb(const void* ptr)
{
return MDFN_deXsb<0, T, aligned>(ptr);
}
template<bool aligned = false>
static INLINE uint16 MDFN_de16lsb(const void* ptr)
{
return MDFN_delsb<uint16, aligned>(ptr);
}
static INLINE uint32 MDFN_de24lsb(const void* ptr)
{
const uint8* morp = (const uint8*)ptr;
return(morp[0]|(morp[1]<<8)|(morp[2]<<16));
}
template<bool aligned = false>
static INLINE uint32 MDFN_de32lsb(const void* ptr)
{
return MDFN_delsb<uint32, aligned>(ptr);
}
template<bool aligned = false>
static INLINE uint64 MDFN_de64lsb(const void* ptr)
{
return MDFN_delsb<uint64, aligned>(ptr);
}
//
// Big endian.
//
template<typename T, bool aligned = false>
static INLINE T MDFN_demsb(const void* ptr)
{
return MDFN_deXsb<1, T, aligned>(ptr);
}
template<bool aligned = false>
static INLINE uint16 MDFN_de16msb(const void* ptr)
{
return MDFN_demsb<uint16, aligned>(ptr);
}
static INLINE uint32 MDFN_de24msb(const void* ptr)
{
const uint8* morp = (const uint8*)ptr;
return((morp[2]<<0)|(morp[1]<<8)|(morp[0]<<16));
}
template<bool aligned = false>
static INLINE uint32 MDFN_de32msb(const void* ptr)
{
return MDFN_demsb<uint32, aligned>(ptr);
}
template<bool aligned = false>
static INLINE uint64 MDFN_de64msb(const void* ptr)
{
return MDFN_demsb<uint64, aligned>(ptr);
}
//
//
//
//
//
//
//
//
//
// X endian.
//
template<int isbigendian, typename T, bool aligned>
static INLINE void MDFN_enXsb(void* ptr, T value)
{
T tmp = value;
if(isbigendian != -1 && isbigendian != MDFN_ENDIANH_IS_BIGENDIAN)
{
static_assert(sizeof(T) == 1 || sizeof(T) == 2 || sizeof(T) == 4 || sizeof(T) == 8, "Gummy penguins.");
if(sizeof(T) == 8)
tmp = (T)MDFN_bswap64(value);
else if(sizeof(T) == 4)
tmp = (T)MDFN_bswap32(value);
else if(sizeof(T) == 2)
tmp = (T)MDFN_bswap16(value);
}
memcpy(MDFN_ASSUME_ALIGNED(ptr, (aligned ? sizeof(T) : 1)), &tmp, sizeof(T));
}
//
// Native endian.
//
template<typename T, bool aligned = false>
static INLINE void MDFN_ennsb(void* ptr, T value)
{
MDFN_enXsb<-1, T, aligned>(ptr, value);
}
//
// Little endian.
//
template<typename T, bool aligned = false>
static INLINE void MDFN_enlsb(void* ptr, T value)
{
MDFN_enXsb<0, T, aligned>(ptr, value);
}
template<bool aligned = false>
static INLINE void MDFN_en16lsb(void* ptr, uint16 value)
{
MDFN_enlsb<uint16, aligned>(ptr, value);
}
static INLINE void MDFN_en24lsb(void* ptr, uint32 value)
{
uint8* morp = (uint8*)ptr;
morp[0] = value;
morp[1] = value >> 8;
morp[2] = value >> 16;
}
template<bool aligned = false>
static INLINE void MDFN_en32lsb(void* ptr, uint32 value)
{
MDFN_enlsb<uint32, aligned>(ptr, value);
}
template<bool aligned = false>
static INLINE void MDFN_en64lsb(void* ptr, uint64 value)
{
MDFN_enlsb<uint64, aligned>(ptr, value);
}
//
// Big endian.
//
template<typename T, bool aligned = false>
static INLINE void MDFN_enmsb(void* ptr, T value)
{
MDFN_enXsb<1, T, aligned>(ptr, value);
}
template<bool aligned = false>
static INLINE void MDFN_en16msb(void* ptr, uint16 value)
{
MDFN_enmsb<uint16, aligned>(ptr, value);
}
static INLINE void MDFN_en24msb(void* ptr, uint32 value)
{
uint8* morp = (uint8*)ptr;
morp[0] = value;
morp[1] = value >> 8;
morp[2] = value >> 16;
}
template<bool aligned = false>
static INLINE void MDFN_en32msb(void* ptr, uint32 value)
{
MDFN_enmsb<uint32, aligned>(ptr, value);
}
template<bool aligned = false>
static INLINE void MDFN_en64msb(void* ptr, uint64 value)
{
MDFN_enmsb<uint64, aligned>(ptr, value);
}
#endif

View File

@ -1,155 +0,0 @@
/* Mednafen - Multi-system Emulator
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <string.h>
#include <stdarg.h>
#include <stdio.h>
#include "emuware/emuware.h"
#include "error.h"
MDFN_Error::MDFN_Error() noexcept
{
abort();
}
MDFN_Error::MDFN_Error(int errno_code_new, const char *format, ...) noexcept
{
errno_code = errno_code_new;
error_message = NULL;
int size = 128;
for(;;) {
va_list ap;
va_start(ap, format);
error_message = (char*)malloc(size);
size *= 2;
int ret = vsprintf(error_message, format, ap);
va_end(ap);
if(ret>=0)
break;
free(error_message);
}
}
MDFN_Error::MDFN_Error(const ErrnoHolder &enh)
{
errno_code = enh.Errno();
int size = 128;
for(;;) {
error_message = (char*)malloc(size);
size *= 2;
int ret = sprintf("%s", enh.StrError());
if(ret>=0)
break;
free(error_message);
}
}
MDFN_Error::~MDFN_Error() noexcept
{
if(error_message)
{
free(error_message);
error_message = NULL;
}
}
MDFN_Error::MDFN_Error(const MDFN_Error &ze_error) noexcept
{
if(ze_error.error_message)
error_message = strdup(ze_error.error_message);
else
error_message = NULL;
errno_code = ze_error.errno_code;
}
MDFN_Error& MDFN_Error::operator=(const MDFN_Error &ze_error) noexcept
{
char *new_error_message = ze_error.error_message ? strdup(ze_error.error_message) : NULL;
int new_errno_code = ze_error.errno_code;
if(error_message)
free(error_message);
error_message = new_error_message;
errno_code = new_errno_code;
return(*this);
}
const char * MDFN_Error::what(void) const noexcept
{
if(!error_message)
return("Error allocating memory for the error message!");
return(error_message);
}
int MDFN_Error::GetErrno(void) const noexcept
{
return(errno_code);
}
static const char *srr_wrap(int ret, const char *local_strerror)
{
if(ret == -1)
return("ERROR IN strerror_r()!!!");
return(local_strerror);
}
static const char *srr_wrap(const char *ret, const char *local_strerror)
{
if(ret == NULL)
return("ERROR IN strerror_r()!!!");
return(ret);
}
void ErrnoHolder::SetErrno(int the_errno)
{
local_errno = the_errno;
if(the_errno == 0)
local_strerror[0] = 0;
else
{
#ifdef HAVE_STRERROR_R
const char *retv;
retv = srr_wrap(strerror_r(the_errno, local_strerror, 256), local_strerror);
if(retv != local_strerror)
strncpy(local_strerror, retv, 255);
#else // No strerror_r :(
strncpy(local_strerror, strerror(the_errno), 255);
#endif
local_strerror[255] = 0;
}
}

View File

@ -1,75 +0,0 @@
#ifndef __MDFN_ERROR_H
#define __MDFN_ERROR_H
#include <errno.h>
#include <string.h>
#include <exception>
#ifdef __cplusplus
class ErrnoHolder;
class MDFN_Error : public std::exception
{
public:
MDFN_Error() noexcept;
MDFN_Error(int errno_code_new, const char *format, ...) noexcept MDFN_FORMATSTR(gnu_printf, 3, 4);
MDFN_Error(const ErrnoHolder &enh);
~MDFN_Error() noexcept;
MDFN_Error(const MDFN_Error &ze_error) noexcept;
MDFN_Error & operator=(const MDFN_Error &ze_error) noexcept;
virtual const char *what(void) const noexcept;
int GetErrno(void) const noexcept;
private:
int errno_code;
char *error_message;
};
class ErrnoHolder
{
public:
ErrnoHolder()
{
//SetErrno(0);
local_errno = 0;
local_strerror[0] = 0;
}
ErrnoHolder(int the_errno)
{
SetErrno(the_errno);
}
inline int Errno(void) const
{
return(local_errno);
}
const char *StrError(void) const
{
return(local_strerror);
}
void operator=(int the_errno)
{
SetErrno(the_errno);
}
private:
void SetErrno(int the_errno);
int local_errno;
char local_strerror[256];
};
#endif
#endif

View File

@ -1,366 +0,0 @@
/* Mednafen - Multi-system Emulator
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "emuware/emuware.h"
#include <string.h>
#include <stdarg.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string>
#include <map>
#include "general.h"
#include "error.h"
#define _(X) X
#ifdef WIN32
#define PSS "\\"
#else
#define PSS "/"
#endif
static struct {
bool untrusted_fip_check;
} s_settings;
using namespace std;
static string BaseDirectory;
static string FileBase;
static string FileExt; /* Includes the . character, as in ".nes" */
static string FileBaseDirectory;
void MDFN_SetBaseDirectory(const std::string& dir)
{
BaseDirectory = string(dir);
}
std::string MDFN_GetBaseDirectory(void)
{
return BaseDirectory;
}
// Really dumb, maybe we should use boost?
static bool IsAbsolutePath(const char *path)
{
#if PSS_STYLE==4
if(path[0] == ':')
#elif PSS_STYLE==1
if(path[0] == '/')
#else
if(path[0] == '\\'
#if PSS_STYLE!=3
|| path[0] == '/'
#endif
)
#endif
{
return(true);
}
#if defined(WIN32) || defined(DOS)
if((path[0] >= 'a' && path[0] <= 'z') || (path[0] >= 'A' && path[0] <= 'Z'))
{
if(path[1] == ':')
{
return(true);
}
}
#endif
return(false);
}
static bool IsAbsolutePath(const std::string &path)
{
return(IsAbsolutePath(path.c_str()));
}
bool MDFN_IsFIROPSafe(const std::string &path)
{
//
// First, check for any 8-bit characters, and print a warning about portability.
//
for(size_t x = 0; x < path.size(); x++)
{
if(path[x] & 0x80)
{
printf(_("WARNING: Referenced path \"%s\" contains at least one 8-bit non-ASCII character; this may cause portability issues.\n"), path.c_str());
break;
}
}
// We could make this more OS-specific, but it shouldn't hurt to try to weed out usage of characters that are path
// separators in one OS but not in another, and we'd also run more of a risk of missing a special path separator case
// in some OS.
if(!s_settings.untrusted_fip_check)
return(true);
if(path.find('\0') != string::npos)
return(false);
if(path.find(':') != string::npos)
return(false);
if(path.find('\\') != string::npos)
return(false);
if(path.find('/') != string::npos)
return(false);
#if defined(DOS) || defined(WIN32)
//
// http://support.microsoft.com/kb/74496
//
{
static const char* dev_names[] =
{
"CON", "PRN", "AUX", "CLOCK$", "NUL", "COM1", "COM2", "COM3", "COM4", "LPT1", "LPT2", "LPT3", NULL
};
for(const char** ls = dev_names; *ls != NULL; ls++)
{
if(!strcasecmp(*ls, path.c_str()))
return(false);
}
}
#endif
return(true);
}
void MDFN_GetFilePathComponents(const std::string &file_path, std::string *dir_path_out, std::string *file_base_out, std::string *file_ext_out)
{
size_t final_ds; // in file_path
string file_name;
size_t fn_final_dot; // in local var file_name
// Temporary output:
string dir_path, file_base, file_ext;
#if PSS_STYLE==4
final_ds = file_path.find_last_of(':');
#elif PSS_STYLE==1
final_ds = file_path.find_last_of('/');
#else
final_ds = file_path.find_last_of('\\');
#if PSS_STYLE!=3
{
size_t alt_final_ds = file_path.find_last_of('/');
if(final_ds == string::npos || (alt_final_ds != string::npos && alt_final_ds > final_ds))
final_ds = alt_final_ds;
}
#endif
#endif
if(final_ds == string::npos)
{
dir_path = string(".");
file_name = file_path;
}
else
{
dir_path = file_path.substr(0, final_ds);
file_name = file_path.substr(final_ds + 1);
}
fn_final_dot = file_name.find_last_of('.');
if(fn_final_dot != string::npos)
{
file_base = file_name.substr(0, fn_final_dot);
file_ext = file_name.substr(fn_final_dot);
}
else
{
file_base = file_name;
file_ext = string("");
}
if(dir_path_out)
*dir_path_out = dir_path;
if(file_base_out)
*file_base_out = file_base;
if(file_ext_out)
*file_ext_out = file_ext;
}
std::string MDFN_EvalFIP(const std::string &dir_path, const std::string &rel_path, bool skip_safety_check)
{
if(!skip_safety_check && !MDFN_IsFIROPSafe(rel_path))
throw MDFN_Error(0, _("Referenced path \"%s\" is potentially unsafe. See \"filesys.untrusted_fip_check\" setting.\n"), rel_path.c_str());
if(IsAbsolutePath(rel_path.c_str()))
return(rel_path);
else
{
return(dir_path + std::string(PSS) + rel_path);
}
}
typedef std::map<char, std::string> FSMap;
static std::string EvalPathFS(const std::string &fstring, /*const (won't work because entry created if char doesn't exist) */ FSMap &fmap)
{
std::string ret = "";
const char *str = fstring.c_str();
bool in_spec = false;
while(*str)
{
int c = *str;
if(!in_spec && c == '%')
in_spec = true;
else if(in_spec == true)
{
if(c == '%')
ret = ret + std::string("%");
else
ret = ret + fmap[(char)c];
in_spec = false;
}
else
{
char ct[2];
ct[0] = c;
ct[1] = 0;
ret += std::string(ct);
}
str++;
}
return(ret);
}
#if 0
static void CreateMissingDirs(const char *path)
{
const char *s = path;
bool first_psep = true;
char last_char = 0;
const char char_test1 = '/', char_test2 = '/';
while(*s)
{
if(*s == char_test1 || *s == char_test2)
{
if(last_char != *s) //char_test1 && last_char != char_test2)
{
if(!first_psep)
{
char tmpbuf[(s - path) + 1];
tmpbuf[s - path] = 0;
strncpy(tmpbuf, path, s - path);
puts(tmpbuf);
//MDFN_mkdir(tmpbuf, S_IRWXU);
}
}
first_psep = false;
}
last_char = *s;
s++;
}
}
#endif
const char * GetFNComponent(const char *str)
{
const char *tp1;
#if PSS_STYLE==4
tp1=((char *)strrchr(str,':'));
#elif PSS_STYLE==1
tp1=((char *)strrchr(str,'/'));
#else
tp1=((char *)strrchr(str,'\\'));
#if PSS_STYLE!=3
{
const char *tp3;
tp3=((char *)strrchr(str,'/'));
if(tp1<tp3) tp1=tp3;
}
#endif
#endif
if(tp1)
return(tp1+1);
else
return(str);
}
void GetFileBase(const char *f)
{
const char *tp1,*tp3;
#if PSS_STYLE==4
tp1=((char *)strrchr(f,':'));
#elif PSS_STYLE==1
tp1=((char *)strrchr(f,'/'));
#else
tp1=((char *)strrchr(f,'\\'));
#if PSS_STYLE!=3
tp3=((char *)strrchr(f,'/'));
if(tp1<tp3) tp1=tp3;
#endif
#endif
if(!tp1)
{
tp1=f;
FileBaseDirectory = ".";
}
else
{
char* tmpfn = (char*)alloca(tp1 - f + 1);
memcpy(tmpfn,f,tp1-f);
tmpfn[tp1-f]=0;
FileBaseDirectory = string(tmpfn);
tp1++;
}
if(((tp3=strrchr(f,'.'))!=NULL) && (tp3>tp1))
{
char* tmpbase = (char*)alloca(tp3 - tp1 + 1);
memcpy(tmpbase,tp1,tp3-tp1);
tmpbase[tp3-tp1]=0;
FileBase = string(tmpbase);
FileExt = string(tp3);
}
else
{
FileBase = string(tp1);
FileExt = "";
}
}

View File

@ -1,52 +0,0 @@
#ifndef _GENERAL_H
#define _GENERAL_H
#include <string>
#if 0
class FilePathMaker
{
void SetBaseDirectory(const char* path);
std::string GetBaseDirectory(void);
void BuildPath(unsigned type, int id1, const char* cd1);
static void GetFileBase(
};
#endif
void MDFN_SetBaseDirectory(const std::string& dir);
std::string MDFN_GetBaseDirectory(void);
void GetFileBase(const char *f);
// File-inclusion for-read-only path, for PSF and CUE/TOC sheet usage.
bool MDFN_IsFIROPSafe(const std::string &path);
std::string MDFN_MakeFName(int type, int id1, const char *cd1);
typedef enum
{
MDFNMKF_STATE = 0,
MDFNMKF_SNAP,
MDFNMKF_SAV,
MDFNMKF_CHEAT,
MDFNMKF_PALETTE,
MDFNMKF_IPS,
MDFNMKF_MOVIE,
MDFNMKF_AUX,
MDFNMKF_SNAP_DAT,
MDFNMKF_CHEAT_TMP,
MDFNMKF_FIRMWARE
} MakeFName_Type;
std::string MDFN_MakeFName(MakeFName_Type type, int id1, const char *cd1);
INLINE std::string MDFN_MakeFName(MakeFName_Type type, int id1, const std::string& cd1) { return MDFN_MakeFName(type, id1, cd1.c_str()); }
const char * GetFNComponent(const char *str);
void MDFN_GetFilePathComponents(const std::string &file_path, std::string *dir_path_out, std::string *file_base_out = NULL, std::string *file_ext_out = NULL);
std::string MDFN_EvalFIP(const std::string &dir_path, const std::string &rel_path, bool skip_safety_check = false);
#endif

View File

@ -1,87 +0,0 @@
#ifndef __MDFN_MATH_OPS_H
#define __MDFN_MATH_OPS_H
// Source: http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2
// Rounds up to the nearest power of 2.
static INLINE uint64 round_up_pow2(uint64 v)
{
v--;
v |= v >> 1;
v |= v >> 2;
v |= v >> 4;
v |= v >> 8;
v |= v >> 16;
v |= v >> 32;
v++;
v += (v == 0);
return(v);
}
static INLINE uint32 uilog2(uint32 v)
{
// http://graphics.stanford.edu/~seander/bithacks.html#IntegerLogDeBruijn
static const uint32 MultiplyDeBruijnBitPosition[32] =
{
0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30,
8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31
};
v |= v >> 1; // first round down to one less than a power of 2
v |= v >> 2;
v |= v >> 4;
v |= v >> 8;
v |= v >> 16;
return MultiplyDeBruijnBitPosition[(uint32_t)(v * 0x07C4ACDDU) >> 27];
}
// Some compilers' optimizers and some platforms might fubar the generated code from these macros,
// so some tests are run in...tests.cpp
#define sign_8_to_s16(_value) ((int16)(int8)(_value))
#define sign_9_to_s16(_value) (((int16)((unsigned int)(_value) << 7)) >> 7)
#define sign_10_to_s16(_value) (((int16)((uint32)(_value) << 6)) >> 6)
#define sign_11_to_s16(_value) (((int16)((uint32)(_value) << 5)) >> 5)
#define sign_12_to_s16(_value) (((int16)((uint32)(_value) << 4)) >> 4)
#define sign_13_to_s16(_value) (((int16)((uint32)(_value) << 3)) >> 3)
#define sign_14_to_s16(_value) (((int16)((uint32)(_value) << 2)) >> 2)
#define sign_15_to_s16(_value) (((int16)((uint32)(_value) << 1)) >> 1)
// This obviously won't convert higher-than-32 bit numbers to signed 32-bit ;)
// Also, this shouldn't be used for 8-bit and 16-bit signed numbers, since you can
// convert those faster with typecasts...
#define sign_x_to_s32(_bits, _value) (((int32)((uint32)(_value) << (32 - _bits))) >> (32 - _bits))
static INLINE int32 clamp_to_u8(int32 i)
{
if(i & 0xFFFFFF00)
i = (((~i) >> 30) & 0xFF);
return(i);
}
static INLINE int32 clamp_to_u16(int32 i)
{
if(i & 0xFFFF0000)
i = (((~i) >> 31) & 0xFFFF);
return(i);
}
template<typename T, typename U, typename V> static INLINE void clamp(T *val, U minimum, V maximum)
{
if(*val < minimum)
{
//printf("Warning: clamping to minimum(%d)\n", (int)minimum);
*val = minimum;
}
if(*val > maximum)
{
//printf("Warning: clamping to maximum(%d)\n", (int)maximum);
*val = maximum;
}
}
#endif

View File

@ -1,560 +0,0 @@
/*
* Copyright 2001-2004 Unicode, Inc.
*
* Disclaimer
*
* This source code is provided as is by Unicode, Inc. No claims are
* made as to fitness for any particular purpose. No warranties of any
* kind are expressed or implied. The recipient agrees to determine
* applicability of information provided. If this file has been
* purchased on magnetic or optical media from Unicode, Inc., the
* sole remedy for any claim will be exchange of defective media
* within 90 days of receipt.
*
* Limitations on Rights to Redistribute This Code
*
* Unicode, Inc. hereby grants the right to freely use the information
* supplied in this file in the creation of products supporting the
* Unicode Standard, and to make copies of this file in any form
* for internal or external distribution as long as this notice
* remains attached.
*/
/* ---------------------------------------------------------------------
Conversions between UTF32, UTF-16, and UTF-8. Source code file.
Author: Mark E. Davis, 1994.
Rev History: Rick McGowan, fixes & updates May 2001.
Sept 2001: fixed const & error conditions per
mods suggested by S. Parent & A. Lillich.
June 2002: Tim Dodd added detection and handling of incomplete
source sequences, enhanced error detection, added casts
to eliminate compiler warnings.
July 2003: slight mods to back out aggressive FFFE detection.
Jan 2004: updated switches in from-UTF8 conversions.
Oct 2004: updated to use UNI_MAX_LEGAL_UTF32 in UTF-32 conversions.
See the header file "ConvertUTF.h" for complete documentation.
------------------------------------------------------------------------ */
#include "../types.h"
#include "ConvertUTF.h"
#ifdef CVTUTF_DEBUG
#include <stdio.h>
#endif
#include <string.h>
#include <stdlib.h>
static const int halfShift = 10; /* used for shifting by 10 bits */
static const UTF32 halfBase = 0x0010000UL;
static const UTF32 halfMask = 0x3FFUL;
#define UNI_SUR_HIGH_START (UTF32)0xD800
#define UNI_SUR_HIGH_END (UTF32)0xDBFF
#define UNI_SUR_LOW_START (UTF32)0xDC00
#define UNI_SUR_LOW_END (UTF32)0xDFFF
#define false 0
#define true 1
/* --------------------------------------------------------------------- */
ConversionResult ConvertUTF32toUTF16 (
const UTF32** sourceStart, const UTF32* sourceEnd,
UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags) {
ConversionResult result = conversionOK;
const UTF32* source = *sourceStart;
UTF16* target = *targetStart;
while (source < sourceEnd) {
UTF32 ch;
if (target >= targetEnd) {
result = targetExhausted; break;
}
ch = *source++;
if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */
/* UTF-16 surrogate values are illegal in UTF-32; 0xffff or 0xfffe are both reserved values */
if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
if (flags == strictConversion) {
--source; /* return to the illegal value itself */
result = sourceIllegal;
break;
} else {
*target++ = UNI_REPLACEMENT_CHAR;
}
} else {
*target++ = (UTF16)ch; /* normal case */
}
} else if (ch > UNI_MAX_LEGAL_UTF32) {
if (flags == strictConversion) {
result = sourceIllegal;
} else {
*target++ = UNI_REPLACEMENT_CHAR;
}
} else {
/* target is a character in range 0xFFFF - 0x10FFFF. */
if (target + 1 >= targetEnd) {
--source; /* Back up source pointer! */
result = targetExhausted; break;
}
ch -= halfBase;
*target++ = (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START);
*target++ = (UTF16)((ch & halfMask) + UNI_SUR_LOW_START);
}
}
*sourceStart = source;
*targetStart = target;
return result;
}
/* --------------------------------------------------------------------- */
ConversionResult ConvertUTF16toUTF32 (
const UTF16** sourceStart, const UTF16* sourceEnd,
UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags) {
ConversionResult result = conversionOK;
const UTF16* source = *sourceStart;
UTF32* target = *targetStart;
UTF32 ch, ch2;
while (source < sourceEnd) {
const UTF16* oldSource = source; /* In case we have to back up because of target overflow. */
ch = *source++;
/* If we have a surrogate pair, convert to UTF32 first. */
if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END) {
/* If the 16 bits following the high surrogate are in the source buffer... */
if (source < sourceEnd) {
ch2 = *source;
/* If it's a low surrogate, convert to UTF32. */
if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END) {
ch = ((ch - UNI_SUR_HIGH_START) << halfShift)
+ (ch2 - UNI_SUR_LOW_START) + halfBase;
++source;
} else if (flags == strictConversion) { /* it's an unpaired high surrogate */
--source; /* return to the illegal value itself */
result = sourceIllegal;
break;
}
} else { /* We don't have the 16 bits following the high surrogate. */
--source; /* return to the high surrogate */
result = sourceExhausted;
break;
}
} else if (flags == strictConversion) {
/* UTF-16 surrogate values are illegal in UTF-32 */
if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END) {
--source; /* return to the illegal value itself */
result = sourceIllegal;
break;
}
}
if (target >= targetEnd) {
source = oldSource; /* Back up source pointer! */
result = targetExhausted; break;
}
*target++ = ch;
}
*sourceStart = source;
*targetStart = target;
#ifdef CVTUTF_DEBUG
if (result == sourceIllegal) {
fprintf(stderr, "ConvertUTF16toUTF32 illegal seq 0x%04x,%04x\n", ch, ch2);
fflush(stderr);
}
#endif
return result;
}
/* --------------------------------------------------------------------- */
/*
* Index into the table below with the first byte of a UTF-8 sequence to
* get the number of trailing bytes that are supposed to follow it.
* Note that *legal* UTF-8 values can't have 4 or 5-bytes. The table is
* left as-is for anyone who may want to do such conversion, which was
* allowed in earlier algorithms.
*/
static const char trailingBytesForUTF8[256] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5
};
/*
* Magic values subtracted from a buffer value during UTF8 conversion.
* This table contains as many values as there might be trailing bytes
* in a UTF-8 sequence.
*/
static const UTF32 offsetsFromUTF8[6] = { 0x00000000UL, 0x00003080UL, 0x000E2080UL,
0x03C82080UL, 0xFA082080UL, 0x82082080UL };
/*
* Once the bits are split out into bytes of UTF-8, this is a mask OR-ed
* into the first byte, depending on how many bytes follow. There are
* as many entries in this table as there are UTF-8 sequence types.
* (I.e., one byte sequence, two byte... etc.). Remember that sequencs
* for *legal* UTF-8 will be 4 or fewer bytes total.
*/
static const UTF8 firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
/* --------------------------------------------------------------------- */
/* The interface converts a whole buffer to avoid function-call overhead.
* Constants have been gathered. Loops & conditionals have been removed as
* much as possible for efficiency, in favor of drop-through switches.
* (See "Note A" at the bottom of the file for equivalent code.)
* If your compiler supports it, the "isLegalUTF8" call can be turned
* into an inline function.
*/
/* --------------------------------------------------------------------- */
ConversionResult ConvertUTF16toUTF8 (
const UTF16** sourceStart, const UTF16* sourceEnd,
UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags) {
ConversionResult result = conversionOK;
const UTF16* source = *sourceStart;
UTF8* target = *targetStart;
while (source < sourceEnd) {
UTF32 ch;
unsigned short bytesToWrite = 0;
const UTF32 byteMask = 0xBF;
const UTF32 byteMark = 0x80;
const UTF16* oldSource = source; /* In case we have to back up because of target overflow. */
ch = *source++;
/* If we have a surrogate pair, convert to UTF32 first. */
if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END) {
/* If the 16 bits following the high surrogate are in the source buffer... */
if (source < sourceEnd) {
UTF32 ch2 = *source;
/* If it's a low surrogate, convert to UTF32. */
if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END) {
ch = ((ch - UNI_SUR_HIGH_START) << halfShift)
+ (ch2 - UNI_SUR_LOW_START) + halfBase;
++source;
} else if (flags == strictConversion) { /* it's an unpaired high surrogate */
--source; /* return to the illegal value itself */
result = sourceIllegal;
break;
}
} else { /* We don't have the 16 bits following the high surrogate. */
--source; /* return to the high surrogate */
result = sourceExhausted;
break;
}
} else if (flags == strictConversion) {
/* UTF-16 surrogate values are illegal in UTF-32 */
if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END) {
--source; /* return to the illegal value itself */
result = sourceIllegal;
break;
}
}
/* Figure out how many bytes the result will require */
if (ch < (UTF32)0x80) { bytesToWrite = 1;
} else if (ch < (UTF32)0x800) { bytesToWrite = 2;
} else if (ch < (UTF32)0x10000) { bytesToWrite = 3;
} else if (ch < (UTF32)0x110000) { bytesToWrite = 4;
} else { bytesToWrite = 3;
ch = UNI_REPLACEMENT_CHAR;
}
target += bytesToWrite;
if (target > targetEnd) {
source = oldSource; /* Back up source pointer! */
target -= bytesToWrite; result = targetExhausted; break;
}
switch (bytesToWrite) { /* note: everything falls through. */
case 4: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
case 3: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
case 2: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
case 1: *--target = (UTF8)(ch | firstByteMark[bytesToWrite]);
}
target += bytesToWrite;
}
*sourceStart = source;
*targetStart = target;
return result;
}
/* --------------------------------------------------------------------- */
/*
* Utility routine to tell whether a sequence of bytes is legal UTF-8.
* This must be called with the length pre-determined by the first byte.
* If not calling this from ConvertUTF8to*, then the length can be set by:
* length = trailingBytesForUTF8[*source]+1;
* and the sequence is illegal right away if there aren't that many bytes
* available.
* If presented with a length > 4, this returns false. The Unicode
* definition of UTF-8 goes up to 4-byte sequences.
*/
static bool isLegalUTF8(const UTF8 *source, int length) {
UTF8 a;
const UTF8 *srcptr = source+length;
switch (length) {
default: return false;
/* Everything else falls through when "true"... */
case 4: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false;
case 3: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false;
case 2: if ((a = (*--srcptr)) > 0xBF) return false;
switch (*source) {
/* no fall-through in this inner switch */
case 0xE0: if (a < 0xA0) return false; break;
case 0xED: if (a > 0x9F) return false; break;
case 0xF0: if (a < 0x90) return false; break;
case 0xF4: if (a > 0x8F) return false; break;
default: if (a < 0x80) return false;
}
case 1: if (*source >= 0x80 && *source < 0xC2) return false;
}
if (*source > 0xF4) return false;
return true;
}
/* --------------------------------------------------------------------- */
/*
* Exported function to return whether a UTF-8 sequence is legal or not.
* This is not used here; it's just exported.
*/
bool isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd) {
int length = trailingBytesForUTF8[*source]+1;
if (source+length > sourceEnd) {
return false;
}
return isLegalUTF8(source, length);
}
/* --------------------------------------------------------------------- */
ConversionResult ConvertUTF8toUTF16 (
const UTF8** sourceStart, const UTF8* sourceEnd,
UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags) {
ConversionResult result = conversionOK;
const UTF8* source = *sourceStart;
UTF16* target = *targetStart;
while (source < sourceEnd) {
UTF32 ch = 0;
unsigned short extraBytesToRead = trailingBytesForUTF8[*source];
if (source + extraBytesToRead >= sourceEnd) {
result = sourceExhausted; break;
}
/* Do this check whether lenient or strict */
if (! isLegalUTF8(source, extraBytesToRead+1)) {
result = sourceIllegal;
break;
}
/*
* The cases all fall through. See "Note A" below.
*/
switch (extraBytesToRead) {
case 5: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */
case 4: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */
case 3: ch += *source++; ch <<= 6;
case 2: ch += *source++; ch <<= 6;
case 1: ch += *source++; ch <<= 6;
case 0: ch += *source++;
}
ch -= offsetsFromUTF8[extraBytesToRead];
if (target >= targetEnd) {
source -= (extraBytesToRead+1); /* Back up source pointer! */
result = targetExhausted; break;
}
if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */
/* UTF-16 surrogate values are illegal in UTF-32 */
if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
if (flags == strictConversion) {
source -= (extraBytesToRead+1); /* return to the illegal value itself */
result = sourceIllegal;
break;
} else {
*target++ = UNI_REPLACEMENT_CHAR;
}
} else {
*target++ = (UTF16)ch; /* normal case */
}
} else if (ch > UNI_MAX_UTF16) {
if (flags == strictConversion) {
result = sourceIllegal;
source -= (extraBytesToRead+1); /* return to the start */
break; /* Bail out; shouldn't continue */
} else {
*target++ = UNI_REPLACEMENT_CHAR;
}
} else {
/* target is a character in range 0xFFFF - 0x10FFFF. */
if (target + 1 >= targetEnd) {
source -= (extraBytesToRead+1); /* Back up source pointer! */
result = targetExhausted; break;
}
ch -= halfBase;
*target++ = (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START);
*target++ = (UTF16)((ch & halfMask) + UNI_SUR_LOW_START);
}
}
*sourceStart = source;
*targetStart = target;
return result;
}
/* --------------------------------------------------------------------- */
ConversionResult ConvertUTF32toUTF8 (
const UTF32** sourceStart, const UTF32* sourceEnd,
UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags) {
ConversionResult result = conversionOK;
const UTF32* source = *sourceStart;
UTF8* target = *targetStart;
while (source < sourceEnd) {
UTF32 ch;
unsigned short bytesToWrite = 0;
const UTF32 byteMask = 0xBF;
const UTF32 byteMark = 0x80;
ch = *source++;
if (flags == strictConversion ) {
/* UTF-16 surrogate values are illegal in UTF-32 */
if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
--source; /* return to the illegal value itself */
result = sourceIllegal;
break;
}
}
/*
* Figure out how many bytes the result will require. Turn any
* illegally large UTF32 things (> Plane 17) into replacement chars.
*/
if (ch < (UTF32)0x80) { bytesToWrite = 1;
} else if (ch < (UTF32)0x800) { bytesToWrite = 2;
} else if (ch < (UTF32)0x10000) { bytesToWrite = 3;
} else if (ch <= UNI_MAX_LEGAL_UTF32) { bytesToWrite = 4;
} else { bytesToWrite = 3;
ch = UNI_REPLACEMENT_CHAR;
result = sourceIllegal;
}
target += bytesToWrite;
if (target > targetEnd) {
--source; /* Back up source pointer! */
target -= bytesToWrite; result = targetExhausted; break;
}
switch (bytesToWrite) { /* note: everything falls through. */
case 4: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
case 3: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
case 2: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
case 1: *--target = (UTF8) (ch | firstByteMark[bytesToWrite]);
}
target += bytesToWrite;
}
*sourceStart = source;
*targetStart = target;
return result;
}
/* --------------------------------------------------------------------- */
ConversionResult ConvertUTF8toUTF32 (
const UTF8** sourceStart, const UTF8* sourceEnd,
UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags) {
ConversionResult result = conversionOK;
const UTF8* source = *sourceStart;
UTF32* target = *targetStart;
while (source < sourceEnd) {
UTF32 ch = 0;
unsigned short extraBytesToRead = trailingBytesForUTF8[*source];
if (source + extraBytesToRead >= sourceEnd) {
result = sourceExhausted; break;
}
/* Do this check whether lenient or strict */
if (! isLegalUTF8(source, extraBytesToRead+1)) {
result = sourceIllegal;
break;
}
/*
* The cases all fall through. See "Note A" below.
*/
switch (extraBytesToRead) {
case 5: ch += *source++; ch <<= 6;
case 4: ch += *source++; ch <<= 6;
case 3: ch += *source++; ch <<= 6;
case 2: ch += *source++; ch <<= 6;
case 1: ch += *source++; ch <<= 6;
case 0: ch += *source++;
}
ch -= offsetsFromUTF8[extraBytesToRead];
if (target >= targetEnd) {
source -= (extraBytesToRead+1); /* Back up the source pointer! */
result = targetExhausted; break;
}
if (ch <= UNI_MAX_LEGAL_UTF32) {
/*
* UTF-16 surrogate values are illegal in UTF-32, and anything
* over Plane 17 (> 0x10FFFF) is illegal.
*/
if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
if (flags == strictConversion) {
source -= (extraBytesToRead+1); /* return to the illegal value itself */
result = sourceIllegal;
break;
} else {
*target++ = UNI_REPLACEMENT_CHAR;
}
} else {
*target++ = ch;
}
} else { /* i.e., ch > UNI_MAX_LEGAL_UTF32 */
result = sourceIllegal;
*target++ = UNI_REPLACEMENT_CHAR;
}
}
*sourceStart = source;
*targetStart = target;
return result;
}
UTF32 *MakeUTF32FromUTF8(UTF8 *string)
{
UTF32 *ret, *tstart;
const UTF8 *tstring = string;
size_t string_length = strlen((char *)string);
tstart = ret = (UTF32 *)malloc(string_length * sizeof(UTF32) + 1);
ConvertUTF8toUTF32(&tstring, &string[string_length], &tstart, &tstart[string_length], lenientConversion);
*tstart = 0;
return(ret);
}
/* ---------------------------------------------------------------------
Note A.
The fall-through switches in UTF-8 reading code save a
temp variable, some decrements & conditionals. The switches
are equivalent to the following loop:
{
int tmpBytesToRead = extraBytesToRead+1;
do {
ch += *source++;
--tmpBytesToRead;
if (tmpBytesToRead) ch <<= 6;
} while (tmpBytesToRead > 0);
}
In UTF-8 writing code, the switches on "bytesToWrite" are
similarly unrolled loops.
--------------------------------------------------------------------- */

View File

@ -1,149 +0,0 @@
/*
* Copyright 2001-2004 Unicode, Inc.
*
* Disclaimer
*
* This source code is provided as is by Unicode, Inc. No claims are
* made as to fitness for any particular purpose. No warranties of any
* kind are expressed or implied. The recipient agrees to determine
* applicability of information provided. If this file has been
* purchased on magnetic or optical media from Unicode, Inc., the
* sole remedy for any claim will be exchange of defective media
* within 90 days of receipt.
*
* Limitations on Rights to Redistribute This Code
*
* Unicode, Inc. hereby grants the right to freely use the information
* supplied in this file in the creation of products supporting the
* Unicode Standard, and to make copies of this file in any form
* for internal or external distribution as long as this notice
* remains attached.
*/
/* ---------------------------------------------------------------------
Conversions between UTF32, UTF-16, and UTF-8. Header file.
Several funtions are included here, forming a complete set of
conversions between the three formats. UTF-7 is not included
here, but is handled in a separate source file.
Each of these routines takes pointers to input buffers and output
buffers. The input buffers are const.
Each routine converts the text between *sourceStart and sourceEnd,
putting the result into the buffer between *targetStart and
targetEnd. Note: the end pointers are *after* the last item: e.g.
*(sourceEnd - 1) is the last item.
The return result indicates whether the conversion was successful,
and if not, whether the problem was in the source or target buffers.
(Only the first encountered problem is indicated.)
After the conversion, *sourceStart and *targetStart are both
updated to point to the end of last text successfully converted in
the respective buffers.
Input parameters:
sourceStart - pointer to a pointer to the source buffer.
The contents of this are modified on return so that
it points at the next thing to be converted.
targetStart - similarly, pointer to pointer to the target buffer.
sourceEnd, targetEnd - respectively pointers to the ends of the
two buffers, for overflow checking only.
These conversion functions take a ConversionFlags argument. When this
flag is set to strict, both irregular sequences and isolated surrogates
will cause an error. When the flag is set to lenient, both irregular
sequences and isolated surrogates are converted.
Whether the flag is strict or lenient, all illegal sequences will cause
an error return. This includes sequences such as: <F4 90 80 80>, <C0 80>,
or <A0> in UTF-8, and values above 0x10FFFF in UTF-32. Conformant code
must check for illegal sequences.
When the flag is set to lenient, characters over 0x10FFFF are converted
to the replacement character; otherwise (when the flag is set to strict)
they constitute an error.
Output parameters:
The value "sourceIllegal" is returned from some routines if the input
sequence is malformed. When "sourceIllegal" is returned, the source
value will point to the illegal value that caused the problem. E.g.,
in UTF-8 when a sequence is malformed, it points to the start of the
malformed sequence.
Author: Mark E. Davis, 1994.
Rev History: Rick McGowan, fixes & updates May 2001.
Fixes & updates, Sept 2001.
------------------------------------------------------------------------ */
/* ---------------------------------------------------------------------
The following 4 definitions are compiler-specific.
The C standard does not guarantee that wchar_t has at least
16 bits, so wchar_t is no less portable than unsigned short!
All should be unsigned values to avoid sign extension during
bit mask & shift operations.
------------------------------------------------------------------------ */
/* Some fundamental constants */
#define UNI_REPLACEMENT_CHAR (UTF32)0x0000FFFD
#define UNI_MAX_BMP (UTF32)0x0000FFFF
#define UNI_MAX_UTF16 (UTF32)0x0010FFFF
#define UNI_MAX_UTF32 (UTF32)0x7FFFFFFF
#define UNI_MAX_LEGAL_UTF32 (UTF32)0x0010FFFF
typedef enum {
conversionOK, /* conversion successful */
sourceExhausted, /* partial character in source, but hit end */
targetExhausted, /* insuff. room in target for conversion */
sourceIllegal /* source sequence is illegal/malformed */
} ConversionResult;
typedef enum {
strictConversion = 0,
lenientConversion
} ConversionFlags;
/* This is for C++ and does no harm in C */
#ifdef __cplusplus
extern "C" {
#endif
ConversionResult ConvertUTF8toUTF16 (
const UTF8** sourceStart, const UTF8* sourceEnd,
UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags);
ConversionResult ConvertUTF16toUTF8 (
const UTF16** sourceStart, const UTF16* sourceEnd,
UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags);
ConversionResult ConvertUTF8toUTF32 (
const UTF8** sourceStart, const UTF8* sourceEnd,
UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags);
ConversionResult ConvertUTF32toUTF8 (
const UTF32** sourceStart, const UTF32* sourceEnd,
UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags);
ConversionResult ConvertUTF16toUTF32 (
const UTF16** sourceStart, const UTF16* sourceEnd,
UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags);
ConversionResult ConvertUTF32toUTF16 (
const UTF32** sourceStart, const UTF32* sourceEnd,
UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags);
bool isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd);
/* Extra Mednafen convenience functions. */
UTF32 *MakeUTF32FromUTF8(UTF8 *string);
#ifdef __cplusplus
}
#endif
/* --------------------------------------------------------------------- */

View File

@ -1,2 +0,0 @@
mednafen_SOURCES += string/escape.cpp string/trim.cpp string/ConvertUTF.cpp

View File

@ -1,157 +0,0 @@
/* Mednafen - Multi-system Emulator
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "../mednafen.h"
#include "escape.h"
static unsigned int hex_nibble_to_val(char nibble)
{
unsigned int ret = 0;
nibble = tolower(nibble);
if(nibble >= '0' && nibble <= '9')
ret = nibble - '0';
else
ret = nibble - 'a';
return(ret);
}
void unescape_string(char *string)
{
char *src = string;
bool inescape = 0;
uint8 hoval = 0;
int inhex = 0;
int inoctal = 0;
while(*src)
{
if(*src == '\\')
{
inescape = TRUE;
inhex = 0;
inoctal = 0;
}
else if(inhex)
{
if(inhex == 1)
{
hoval = hex_nibble_to_val(*src) << 4;
inhex++;
}
else if(inhex == 2)
{
hoval |= hex_nibble_to_val(*src);
*string = hoval;
string++;
hoval = 0;
inhex = 0;
}
}
else if(inoctal)
{
if(inoctal == 1)
{
hoval = (*src - '0') * 8 * 8;
}
else if(inoctal == 2)
{
hoval += (*src - '0') * 8;
}
else
{
hoval += *src - '0';
*string = hoval;
string++;
hoval = 0;
inoctal = 0;
}
}
else if(inescape)
{
switch(*src)
{
case 'a': *string = 7; string++; break;
case 'b': *string = 8; string++; break;
case 'f': *string = 12; string++; break;
case 'n': *string = 10; string++; break;
case 'r': *string = 13; string++; break;
case 't': *string = 9; string++; break;
case 'v': *string = 11; string++; break;
case '\\': *string = '\\'; string++; break;
case '?': *string = '?'; string++; break;
case '\'': *string = '\''; string++; break;
case '"': *string = '"'; string++; break;
case 'o': inoctal = 1; break;
case 'x': inhex = 1; break;
default: *string = *src; string++; break;
}
inescape = 0;
}
else
{
*string = *src;
string++;
}
src++;
}
*string = 0;
}
char *escape_string(const char *text)
{
uint32 slen = strlen(text);
char *ret = (char*)malloc(slen * 4 + 1); // \xFF
char *outoo = ret;
for(uint32 x = 0; x < slen; x++)
{
int c = (uint8)text[x];
if(c < 0x20 || c == 0x7F || c == '\\' || c == '\'' || c == '"')
{
*outoo++ = '\\';
switch(c)
{
case '\\': *outoo++ = '\\'; break;
case '\'': *outoo++ = '\''; break;
case '"': *outoo++ = '"'; break;
case 7: *outoo++ = 'a'; break;
case 8: *outoo++ = 'b'; break;
case 12: *outoo++ = 'f'; break;
case 10: *outoo++ = 'n'; break;
case 13: *outoo++ = 'r'; break;
case 9: *outoo++ = 't'; break;
case 11: *outoo++ = 'v'; break;
default: outoo += sprintf(outoo, "x%02x", c); break;
}
}
else
*outoo++ = c;
}
*outoo = 0;
return(ret);
}

View File

@ -1,9 +0,0 @@
#ifndef __MDFN_ESCAPE_H
#define __MDFN_ESCAPE_H
// These functions are safe to call before calling MDFNI_Initialize().
void unescape_string(char *string);
char* escape_string(const char *text);
#endif

View File

@ -1,147 +0,0 @@
/* Mednafen - Multi-system Emulator
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <string>
#include "emuware/emuware.h"
#include "trim.h"
// Remove whitespace from beginning of string
void MDFN_ltrim(char *string)
{
int32 di, si;
bool InWhitespace = true;
di = si = 0;
while(string[si])
{
if(InWhitespace && (string[si] == ' ' || string[si] == '\r' || string[si] == '\n' || string[si] == '\t' || string[si] == 0x0b))
{
}
else
{
InWhitespace = false;
string[di] = string[si];
di++;
}
si++;
}
string[di] = 0;
}
// Remove whitespace from end of string
void MDFN_rtrim(char *string)
{
int32 len = strlen(string);
if(len)
{
for(int32 x = len - 1; x >= 0; x--)
{
if(string[x] == ' ' || string[x] == '\r' || string[x] == '\n' || string[x] == '\t' || string[x] == 0x0b)
string[x] = 0;
else
break;
}
}
}
void MDFN_trim(char *string)
{
MDFN_rtrim(string);
MDFN_ltrim(string);
}
// Remove whitespace from beginning of string
void MDFN_ltrim(std::string &string)
{
size_t len = string.length();
size_t di, si;
bool InWhitespace = true;
di = si = 0;
while(si < len)
{
if(InWhitespace && (string[si] == ' ' || string[si] == '\r' || string[si] == '\n' || string[si] == '\t' || string[si] == 0x0b))
{
}
else
{
InWhitespace = false;
string[di] = string[si];
di++;
}
si++;
}
string.resize(di);
}
// Remove whitespace from end of string
void MDFN_rtrim(std::string &string)
{
size_t len = string.length();
if(len)
{
size_t x = len;
size_t new_len = len;
do
{
x--;
if(!(string[x] == ' ' || string[x] == '\r' || string[x] == '\n' || string[x] == '\t' || string[x] == 0x0b))
break;
new_len--;
} while(x);
string.resize(new_len);
}
}
void MDFN_trim(std::string &string)
{
MDFN_rtrim(string);
MDFN_ltrim(string);
}
char *MDFN_RemoveControlChars(char *str)
{
char *orig = str;
if(str)
{
while(*str)
{
if((unsigned char)*str < 0x20)
*str = 0x20;
str++;
}
}
return(orig);
}

View File

@ -1,14 +0,0 @@
#ifndef __MDFN_STRING_TRIM_H
#define __MDFN_STRING_TRIM_H
void MDFN_ltrim(char *string);
void MDFN_rtrim(char *string);
void MDFN_trim(char *string);
void MDFN_ltrim(std::string &string);
void MDFN_rtrim(std::string &string);
void MDFN_trim(std::string &string);
char *MDFN_RemoveControlChars(char *str);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,270 +0,0 @@
/*************************************************************************
*
* $Id$
*
* Copyright (C) 1998 Bjorn Reese and Daniel Stenberg.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND
* CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER.
*
*************************************************************************
*
* http://ctrio.sourceforge.net/
*
************************************************************************/
#ifndef TRIO_TRIO_H
#define TRIO_TRIO_H
#if !defined(WITHOUT_TRIO)
/*
* Use autoconf defines if present. Packages using trio must define
* HAVE_CONFIG_H as a compiler option themselves.
*/
#if defined(HAVE_CONFIG_H)
# include <config.h>
#endif
#include "triop.h"
#include <stdio.h>
#ifdef __cplusplus
extern "C" {
#endif
/*
* Error codes.
*
* Remember to add a textual description to trio_strerror.
*/
enum {
TRIO_EOF = 1,
TRIO_EINVAL = 2,
TRIO_ETOOMANY = 3,
TRIO_EDBLREF = 4,
TRIO_EGAP = 5,
TRIO_ENOMEM = 6,
TRIO_ERANGE = 7,
TRIO_ERRNO = 8,
TRIO_ECUSTOM = 9
};
/* Error macros */
#define TRIO_ERROR_CODE(x) ((-(x)) & 0x00FF)
#define TRIO_ERROR_POSITION(x) ((-(x)) >> 8)
#define TRIO_ERROR_NAME(x) trio_strerror(x)
/* Argument function types */
enum {
TRIO_TYPE_POINTER = 1,
TRIO_TYPE_CHAR = 2,
TRIO_TYPE_SHORT = 3,
TRIO_TYPE_INT = 4,
TRIO_TYPE_LONG = 5,
TRIO_TYPE_ULONGLONG = 6,
TRIO_TYPE_UINTMAX = 7,
TRIO_TYPE_PTRDIFF = 8,
TRIO_TYPE_SIZE = 9,
TRIO_TYPE_PCHAR = 10,
TRIO_TYPE_PWCHAR = 11,
TRIO_TYPE_FLOAT = 12,
TRIO_TYPE_DOUBLE = 13,
TRIO_TYPE_LONGDOUBLE = 14
};
typedef trio_pointer_t (*trio_argfunc_t) TRIO_PROTO((trio_pointer_t, int, int));
typedef int (*trio_outstream_t) TRIO_PROTO((trio_pointer_t, int));
typedef int (*trio_instream_t) TRIO_PROTO((trio_pointer_t));
TRIO_CONST char *trio_strerror TRIO_PROTO((int));
/*************************************************************************
* Print Functions
*/
#if defined(TRIO_COMPILER_GCC) && !TRIO_EXTENSION
# define TRIO_PROTO_PRINTF(x,a) TRIO_PROTO(x) __attribute__ ((format (gnu_printf, a, a+1)))
# define TRIO_PROTO_SCANF(x,a) TRIO_PROTO(x) __attribute__ ((format (gnu_scanf, a, a+1)))
#else
# define TRIO_PROTO_PRINTF(x,a) TRIO_PROTO(x)
# define TRIO_PROTO_SCANF(x,a) TRIO_PROTO(x)
#endif
int trio_printf TRIO_PROTO_PRINTF((TRIO_CONST char *format, ...), 1);
int trio_vprintf TRIO_PROTO((TRIO_CONST char *format, va_list args));
int trio_printfv TRIO_PROTO((TRIO_CONST char *format, trio_pointer_t *args));
int trio_fprintf TRIO_PROTO_PRINTF((FILE *file, TRIO_CONST char *format, ...), 2);
int trio_vfprintf TRIO_PROTO((FILE *file, TRIO_CONST char *format, va_list args));
int trio_fprintfv TRIO_PROTO((FILE *file, TRIO_CONST char *format, trio_pointer_t *args));
int trio_dprintf TRIO_PROTO_PRINTF((int fd, TRIO_CONST char *format, ...), 2);
int trio_vdprintf TRIO_PROTO((int fd, TRIO_CONST char *format, va_list args));
int trio_dprintfv TRIO_PROTO((int fd, TRIO_CONST char *format, trio_pointer_t *args));
int trio_cprintf TRIO_PROTO_PRINTF((trio_outstream_t stream, trio_pointer_t closure,
TRIO_CONST char *format, ...),
3);
int trio_vcprintf TRIO_PROTO((trio_outstream_t stream, trio_pointer_t closure,
TRIO_CONST char *format, va_list args));
int trio_cprintfv TRIO_PROTO((trio_outstream_t stream, trio_pointer_t closure,
TRIO_CONST char *format, trio_pointer_t *args));
int trio_cprintff TRIO_PROTO((trio_outstream_t stream, trio_pointer_t closure,
TRIO_CONST char *format,
trio_argfunc_t func, trio_pointer_t context));
int trio_sprintf TRIO_PROTO_PRINTF((char *buffer, TRIO_CONST char *format, ...), 2);
int trio_vsprintf TRIO_PROTO((char *buffer, TRIO_CONST char *format, va_list args));
int trio_sprintfv TRIO_PROTO((char *buffer, TRIO_CONST char *format, trio_pointer_t *args));
int trio_snprintf TRIO_PROTO_PRINTF((char *buffer, size_t max, TRIO_CONST char *format, ...), 3);
int trio_vsnprintf TRIO_PROTO((char *buffer, size_t bufferSize, TRIO_CONST char *format,
va_list args));
int trio_snprintfv TRIO_PROTO((char *buffer, size_t bufferSize, TRIO_CONST char *format,
trio_pointer_t *args));
int trio_snprintfcat TRIO_PROTO_PRINTF((char *buffer, size_t max, TRIO_CONST char *format, ...), 3);
int trio_vsnprintfcat TRIO_PROTO((char *buffer, size_t bufferSize, TRIO_CONST char *format,
va_list args));
#if defined(TRIO_DEPRECATED)
char *trio_aprintf TRIO_PROTO_PRINTF((TRIO_CONST char *format, ...), 1);
char *trio_vaprintf TRIO_PROTO((TRIO_CONST char *format, va_list args));
#endif
int trio_asprintf TRIO_PROTO_PRINTF((char **ret, TRIO_CONST char *format, ...), 2);
int trio_vasprintf TRIO_PROTO((char **ret, TRIO_CONST char *format, va_list args));
int trio_asprintfv TRIO_PROTO((char **result, TRIO_CONST char *format, trio_pointer_t * args));
/*************************************************************************
* Scan Functions
*/
int trio_scanf TRIO_PROTO_SCANF((TRIO_CONST char *format, ...), 1);
int trio_vscanf TRIO_PROTO((TRIO_CONST char *format, va_list args));
int trio_scanfv TRIO_PROTO((TRIO_CONST char *format, void **args));
int trio_fscanf TRIO_PROTO_SCANF((FILE *file, TRIO_CONST char *format, ...), 2);
int trio_vfscanf TRIO_PROTO((FILE *file, TRIO_CONST char *format, va_list args));
int trio_fscanfv TRIO_PROTO((FILE *file, TRIO_CONST char *format, void **args));
int trio_dscanf TRIO_PROTO_SCANF((int fd, TRIO_CONST char *format, ...), 2);
int trio_vdscanf TRIO_PROTO((int fd, TRIO_CONST char *format, va_list args));
int trio_dscanfv TRIO_PROTO((int fd, TRIO_CONST char *format, void **args));
int trio_cscanf TRIO_PROTO_SCANF((trio_instream_t stream, trio_pointer_t closure,
TRIO_CONST char *format, ...),
3);
int trio_vcscanf TRIO_PROTO((trio_instream_t stream, trio_pointer_t closure,
TRIO_CONST char *format, va_list args));
int trio_cscanfv TRIO_PROTO((trio_instream_t stream, trio_pointer_t closure,
TRIO_CONST char *format, void **args));
int trio_cscanff TRIO_PROTO((trio_instream_t stream, trio_pointer_t closure,
TRIO_CONST char *format,
trio_argfunc_t func, trio_pointer_t context));
int trio_sscanf TRIO_PROTO_SCANF((TRIO_CONST char *buffer, TRIO_CONST char *format, ...), 2);
int trio_vsscanf TRIO_PROTO((TRIO_CONST char *buffer, TRIO_CONST char *format, va_list args));
int trio_sscanfv TRIO_PROTO((TRIO_CONST char *buffer, TRIO_CONST char *format, void **args));
/*************************************************************************
* Locale Functions
*/
void trio_locale_set_decimal_point TRIO_PROTO((char *decimalPoint));
void trio_locale_set_thousand_separator TRIO_PROTO((char *thousandSeparator));
void trio_locale_set_grouping TRIO_PROTO((char *grouping));
/*************************************************************************
* Renaming
*/
#ifdef TRIO_REPLACE_STDIO
/* Replace the <stdio.h> functions */
#ifndef HAVE_PRINTF
# undef printf
# define printf trio_printf
#endif
#ifndef HAVE_VPRINTF
# undef vprintf
# define vprintf trio_vprintf
#endif
#ifndef HAVE_FPRINTF
# undef fprintf
# define fprintf trio_fprintf
#endif
#ifndef HAVE_VFPRINTF
# undef vfprintf
# define vfprintf trio_vfprintf
#endif
#ifndef HAVE_SPRINTF
# undef sprintf
# define sprintf trio_sprintf
#endif
#ifndef HAVE_VSPRINTF
# undef vsprintf
# define vsprintf trio_vsprintf
#endif
#ifndef HAVE_SNPRINTF
# undef snprintf
# define snprintf trio_snprintf
#endif
#ifndef HAVE_VSNPRINTF
# undef vsnprintf
# define vsnprintf trio_vsnprintf
#endif
#ifndef HAVE_SCANF
# undef scanf
# define scanf trio_scanf
#endif
#ifndef HAVE_VSCANF
# undef vscanf
# define vscanf trio_vscanf
#endif
#ifndef HAVE_FSCANF
# undef fscanf
# define fscanf trio_fscanf
#endif
#ifndef HAVE_VFSCANF
# undef vfscanf
# define vfscanf trio_vfscanf
#endif
#ifndef HAVE_SSCANF
# undef sscanf
# define sscanf trio_sscanf
#endif
#ifndef HAVE_VSSCANF
# undef vsscanf
# define vsscanf trio_vsscanf
#endif
/* These aren't stdio functions, but we make them look similar */
#undef dprintf
#define dprintf trio_dprintf
#undef vdprintf
#define vdprintf trio_vdprintf
#undef aprintf
#define aprintf trio_aprintf
#undef vaprintf
#define vaprintf trio_vaprintf
#undef asprintf
#define asprintf trio_asprintf
#undef vasprintf
#define vasprintf trio_vasprintf
#undef dscanf
#define dscanf trio_dscanf
#undef vdscanf
#define vdscanf trio_vdscanf
#endif
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* WITHOUT_TRIO */
#endif /* TRIO_TRIO_H */

View File

@ -1,375 +0,0 @@
/*************************************************************************
*
* $Id$
*
* Copyright (C) 2001 Bjorn Reese <breese@users.sourceforge.net>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND
* CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER.
*
************************************************************************/
#ifndef TRIO_TRIODEF_H
#define TRIO_TRIODEF_H
/*************************************************************************
* Compiler support detection
*/
#if defined(__GNUC__)
# define TRIO_COMPILER_GCC
#endif
#if defined(__SUNPRO_CC)
# define TRIO_COMPILER_SUNPRO __SUNPRO_CC
#else
# if defined(__SUNPRO_C)
# define TRIO_COMPILER_SUNPRO __SUNPRO_C
# endif
#endif
#if defined(__xlC__) || defined(__IBMC__) || defined(__IBMCPP__)
# define TRIO_COMPILER_XLC
#else
# if defined(_AIX) && !defined(__GNUC__)
# define TRIO_COMPILER_XLC /* Workaround for old xlc */
# endif
#endif
#if defined(__DECC) || defined(__DECCXX)
# define TRIO_COMPILER_DECC
#else
# if defined(__osf__) && defined(__LANGUAGE_C__) && !defined(__GNUC__)
# define TRIO_COMPILER_DECC /* Workaround for old DEC C compilers */
# endif
#endif
#if defined(__HP_aCC) || defined(__HP_cc)
# define TRIO_COMPILER_HP
#endif
#if defined(sgi) || defined(__sgi)
# define TRIO_COMPILER_MIPSPRO
#endif
#if defined(_MSC_VER)
# define TRIO_COMPILER_MSVC
#endif
#if defined(__BORLANDC__)
# define TRIO_COMPILER_BCB
#endif
/*************************************************************************
* Platform support detection
*/
#if defined(VMS) || defined(__VMS)
# define TRIO_PLATFORM_VMS
#endif
#if defined(unix) || defined(__unix) || defined(__unix__)
# define TRIO_PLATFORM_UNIX
#endif
#if defined(TRIO_COMPILER_XLC) || defined(_AIX)
# define TRIO_PLATFORM_UNIX
#endif
#if defined(TRIO_COMPILER_DECC) || defined(__osf___)
# if !defined(TRIO_PLATFORM_VMS)
# define TRIO_PLATFORM_UNIX
# endif
#endif
#if defined(__NetBSD__)
# define TRIO_PLATFORM_UNIX
#endif
#if defined(__Lynx__)
# define TRIO_PLATFORM_UNIX
# define TRIO_PLATFORM_LYNX
#endif
#if defined(__APPLE__) && defined(__MACH__)
# define TRIO_PLATFORM_UNIX
#endif
#if defined(__QNX__)
# define TRIO_PLATFORM_UNIX
# define TRIO_PLATFORM_QNX
#endif
#if defined(__CYGWIN__)
# define TRIO_PLATFORM_UNIX
#endif
#if defined(AMIGA) && defined(TRIO_COMPILER_GCC)
# define TRIO_PLATFORM_UNIX
#endif
#if defined(TRIO_COMPILER_MSVC) || defined(WIN32) || defined(_WIN32)
# define TRIO_PLATFORM_WIN32
#endif
#if defined(_WIN32_WCE)
# define TRIO_PLATFORM_WINCE
#endif
#if defined(mpeix) || defined(__mpexl)
# define TRIO_PLATFORM_MPEIX
#endif
#if defined(_AIX)
# define TRIO_PLATFORM_AIX
#endif
#if defined(__hpux)
# define TRIO_PLATFORM_HPUX
#endif
#if defined(sun) || defined(__sun__)
# if defined(__SVR4) || defined(__svr4__)
# define TRIO_PLATFORM_SOLARIS
# else
# define TRIO_PLATFORM_SUNOS
# endif
#endif
#if defined(__powerpc) || defined(__powerpc__) || defined(_ARCH_PPC)
# define TRIO_CPU_POWERPC
#endif
#if defined(__sparc) || defined(__sparc__)
# define TRIO_CPU_SPARC
#endif
#if defined(__s390x__) || defined(__zarch__) || defined(__SYSC_ZARCH__)
# define TRIO_CPU_SYSTEMZ
#endif
/*************************************************************************
* Standards support detection
*/
#if defined(__STDC__) \
|| defined(_MSC_EXTENSIONS) \
|| defined(TRIO_COMPILER_BCB)
# define PREDEF_STANDARD_C89
#endif
#if defined(__STDC_VERSION__)
# define PREDEF_STANDARD_C90
#endif
#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199409L)
# define PREDEF_STANDARD_C94
#endif
#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
# define PREDEF_STANDARD_C99
#endif
#if defined(TRIO_COMPILER_SUNPRO) && (TRIO_COMPILER_SUNPRO >= 0x420)
# if !defined(PREDEF_STANDARD_C94)
# define PREDEF_STANDARD_C94
# endif
#endif
#if defined(__cplusplus)
# define PREDEF_STANDARD_CXX
#endif
#if defined(__cplusplus) && (__cplusplus >= 199711L)
# define PREDEF_STANDARD_CXX89
#endif
#if defined(TRIO_PLATFORM_UNIX)
# include <unistd.h>
#endif
#if defined(_POSIX_VERSION)
# define PREDEF_STANDARD_POSIX _POSIX_VERSION
# if (_POSIX_VERSION >= 199506L)
# define PREDEF_STANDARD_POSIX_1996
# endif
#endif
#if (_XOPEN_VERSION - 0 >= 3) || defined(_XOPEN_XPG3)
# define PREDEF_STANDARD_XPG3
#endif
#if (_XOPEN_VERSION - 0 >= 4) || defined(_XOPEN_XPG4)
# define PREDEF_STANDARD_XPG4
#endif
#if (_XOPEN_VERSION - 0 > 4) \
|| (defined(_XOPEN_UNIX) && (_XOPEN_VERSION - 0 == 4))
# define PREDEF_STANDARD_UNIX95
#endif
#if (_XOPEN_VERSION - 0 >= 500)
# define PREDEF_STANDARD_UNIX98
#endif
#if (_XOPEN_VERSION - 0 >= 600)
# define PREDEF_STANDARD_UNIX03
#endif
/*************************************************************************
* Generic defines
*/
#if !defined(TRIO_PUBLIC)
/* Based on http://gcc.gnu.org/wiki/Visibility */
# if defined(TRIO_PLATFORM_WIN32) || defined (__CYGWIN__)
# if defined(BUILDING_DLL)
# if defined(TRIO_COMPILER_GCC)
# define TRIO_PUBLIC __attribute__ ((dllexport))
# else
# define TRIO_PUBLIC __declspec(dllexport)
# endif
# else
# if defined(TRIO_COMPILER_GCC)
# define TRIO_PUBLIC __attribute__ ((dllimport))
# else
# define TRIO_PUBLIC __declspec(dllimport)
# endif
# endif
# else
# if defined(TRIO_COMPILER_GCC) && __GNUC__ >= 4
# define TRIO_PUBLIC __attribute__ ((visibility ("default")))
# define TRIO_PRIVATE __attribute__ ((visibility ("hidden")))
# else
# define TRIO_PUBLIC
# endif
# endif
#endif
#if !defined(TRIO_PRIVATE)
# define TRIO_PRIVATE static
#endif
#if !(defined(PREDEF_STANDARD_C89) || defined(PREDEF_STANDARD_CXX))
# define TRIO_COMPILER_ANCIENT
#endif
#if defined(TRIO_COMPILER_ANCIENT)
# define TRIO_CONST
# define TRIO_VOLATILE
# define TRIO_SIGNED
typedef double trio_long_double_t;
typedef char * trio_pointer_t;
# define TRIO_SUFFIX_LONG(x) x
# define TRIO_PROTO(x) ()
# define TRIO_NOARGS
# define TRIO_ARGS1(list,a1) list a1;
# define TRIO_ARGS2(list,a1,a2) list a1; a2;
# define TRIO_ARGS3(list,a1,a2,a3) list a1; a2; a3;
# define TRIO_ARGS4(list,a1,a2,a3,a4) list a1; a2; a3; a4;
# define TRIO_ARGS5(list,a1,a2,a3,a4,a5) list a1; a2; a3; a4; a5;
# define TRIO_ARGS6(list,a1,a2,a3,a4,a5,a6) list a1; a2; a3; a4; a5; a6;
# define TRIO_ARGS7(list,a1,a2,a3,a4,a5,a6,a7) list a1; a2; a3; a4; a5; a6; a7;
# define TRIO_ARGS8(list,a1,a2,a3,a4,a5,a6,a7,a8) list a1; a2; a3; a4; a5; a6; a7; a8;
# define TRIO_VARGS2(list,a1,a2) list a1; a2
# define TRIO_VARGS3(list,a1,a2,a3) list a1; a2; a3
# define TRIO_VARGS4(list,a1,a2,a3,a4) list a1; a2; a3; a4
# define TRIO_VARGS5(list,a1,a2,a3,a4,a5) list a1; a2; a3; a4; a5
# define TRIO_VA_DECL va_dcl
# define TRIO_VA_START(x,y) va_start(x)
# define TRIO_VA_END(x) va_end(x)
#else /* ANSI C */
# define TRIO_CONST const
# define TRIO_VOLATILE volatile
# define TRIO_SIGNED signed
typedef long double trio_long_double_t;
typedef void * trio_pointer_t;
# define TRIO_SUFFIX_LONG(x) x ## L
# define TRIO_PROTO(x) x
# define TRIO_NOARGS void
# define TRIO_ARGS1(list,a1) (a1)
# define TRIO_ARGS2(list,a1,a2) (a1,a2)
# define TRIO_ARGS3(list,a1,a2,a3) (a1,a2,a3)
# define TRIO_ARGS4(list,a1,a2,a3,a4) (a1,a2,a3,a4)
# define TRIO_ARGS5(list,a1,a2,a3,a4,a5) (a1,a2,a3,a4,a5)
# define TRIO_ARGS6(list,a1,a2,a3,a4,a5,a6) (a1,a2,a3,a4,a5,a6)
# define TRIO_ARGS7(list,a1,a2,a3,a4,a5,a6,a7) (a1,a2,a3,a4,a5,a6,a7)
# define TRIO_ARGS8(list,a1,a2,a3,a4,a5,a6,a7,a8) (a1,a2,a3,a4,a5,a6,a7,a8)
# define TRIO_VARGS2 TRIO_ARGS2
# define TRIO_VARGS3 TRIO_ARGS3
# define TRIO_VARGS4 TRIO_ARGS4
# define TRIO_VARGS5 TRIO_ARGS5
# define TRIO_VA_DECL ...
# define TRIO_VA_START(x,y) va_start(x,y)
# define TRIO_VA_END(x) va_end(x)
#endif
#if defined(PREDEF_STANDARD_C99) || defined(PREDEF_STANDARD_CXX)
# define TRIO_INLINE inline
#else
# if defined(TRIO_COMPILER_GCC)
# define TRIO_INLINE __inline__
# endif
# if defined(TRIO_COMPILER_MSVC)
# define TRIO_INLINE _inline
# endif
# if defined(TRIO_COMPILER_BCB)
# define TRIO_INLINE __inline
# endif
#endif
#if !defined(TRIO_INLINE)
# define TRIO_INLINE
#endif
/*************************************************************************
* Workarounds
*/
#if defined(TRIO_PLATFORM_VMS)
/*
* Computations done with constants at compile time can trigger these
* even when compiling with IEEE enabled.
*/
# pragma message disable (UNDERFLOW, FLOATOVERFL)
# if (__CRTL_VER < 80210001)
/*
* Although the compiler supports C99 language constructs, the C
* run-time library does not contain all C99 functions.
*/
# if defined(PREDEF_STANDARD_C99)
# undef PREDEF_STANDARD_C99
# endif
# endif
#endif
/*
* Not all preprocessors supports the LL token.
*/
#if defined(TRIO_COMPILER_MSVC) || defined(TRIO_COMPILER_BCB)
#else
# define TRIO_COMPILER_SUPPORTS_LL
#endif
#if defined(__CYGWIN__)
/*
* Cygwin defines the macros for hosted C99, but does not support certain
* long double math functions.
*/
# include <cygwin/version.h>
# define TRIO_CYGWIN_VERSION_API CYGWIN_VERSION_API_MAJOR * 1000 + \
CYGWIN_VERSION_API_MINOR
/*
* Please change the version number below when the Cygwin API supports
* long double math functions (powl, fmodl, etc.)
*/
# if TRIO_CYGWIN_VERSION_API < 99999999
# define TRIO_NO_FLOORL 1
# define TRIO_NO_CEILL 1
# define TRIO_NO_POWL 1
# define TRIO_NO_FMODL 1
# define TRIO_NO_LOG10L 1
# endif
#endif
# if defined(TRIO_CPU_POWERPC) || defined(TRIO_CPU_SPARC) || defined(TRIO_CPU_SYSTEMZ)
# define TRIO_DOUBLE_DOUBLE
# endif
#endif /* TRIO_TRIODEF_H */

File diff suppressed because it is too large Load Diff

View File

@ -1,183 +0,0 @@
/*************************************************************************
*
* $Id$
*
* Copyright (C) 2001 Bjorn Reese <breese@users.sourceforge.net>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND
* CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER.
*
************************************************************************/
#ifndef TRIO_TRIONAN_H
#define TRIO_TRIONAN_H
#include "triodef.h"
#ifdef __cplusplus
extern "C" {
#endif
#if !defined(TRIO_PUBLIC_NAN)
# if !defined(TRIO_PUBLIC)
# define TRIO_PUBLIC
# endif
# define TRIO_PUBLIC_NAN TRIO_PUBLIC
#endif
enum {
TRIO_FP_INFINITE,
TRIO_FP_NAN,
TRIO_FP_NORMAL,
TRIO_FP_SUBNORMAL,
TRIO_FP_ZERO
};
/*************************************************************************
* Dependencies
*/
#if defined(TRIO_EMBED_NAN)
/*
* The application that trionan is embedded in must define which functions
* it uses.
*
* The following resolves internal dependencies.
*/
# if defined(TRIO_FUNC_ISNAN) \
|| defined(TRIO_FUNC_ISINF)
# if !defined(TRIO_FUNC_FPCLASSIFY_AND_SIGNBIT)
# define TRIO_FUNC_FPCLASSIFY_AND_SIGNBIT
# endif
# endif
# if defined(TRIO_FUNC_NAN)
# if !defined(TRIO_FUNC_PINF)
# define TRIO_FUNC_PINF
# endif
# endif
# if defined(TRIO_FUNC_NINF)
# if !defined(TRIO_FUNC_PINF)
# define TRIO_FUNC_PINF
# endif
# endif
#else
/*
* When trionan is not embedded all all functions are defined.
*/
# define TRIO_FUNC_NAN
# define TRIO_FUNC_PINF
# define TRIO_FUNC_NINF
# define TRIO_FUNC_NZERO
# define TRIO_FUNC_ISNAN
# define TRIO_FUNC_ISINF
# define TRIO_FUNC_ISFINITE
# define TRIO_FUNC_SIGNBIT
# define TRIO_FUNC_FPCLASSIFY
# define TRIO_FUNC_FPCLASSIFY_AND_SIGNBIT
#endif
/*************************************************************************
* Functions
*/
/*
* Return NaN (Not-a-Number).
*/
#if defined(TRIO_FUNC_NAN)
TRIO_PUBLIC_NAN double
trio_nan
TRIO_PROTO((void));
#endif
/*
* Return positive infinity.
*/
#if defined(TRIO_FUNC_PINF)
TRIO_PUBLIC_NAN double
trio_pinf
TRIO_PROTO((void));
#endif
/*
* Return negative infinity.
*/
#if defined(TRIO_FUNC_NINF)
TRIO_PUBLIC_NAN double
trio_ninf
TRIO_PROTO((void));
#endif
/*
* Return negative zero.
*/
#if defined(TRIO_FUNC_NZERO)
TRIO_PUBLIC_NAN double
trio_nzero
TRIO_PROTO((TRIO_NOARGS));
#endif
/*
* If number is a NaN return non-zero, otherwise return zero.
*/
#if defined(TRIO_FUNC_ISNAN)
TRIO_PUBLIC_NAN int
trio_isnan
TRIO_PROTO((double number));
#endif
/*
* If number is positive infinity return 1, if number is negative
* infinity return -1, otherwise return 0.
*/
#if defined(TRIO_FUNC_ISINF)
TRIO_PUBLIC_NAN int
trio_isinf
TRIO_PROTO((double number));
#endif
/*
* If number is finite return non-zero, otherwise return zero.
*/
#if defined(TRIO_FUNC_ISFINITE)
TRIO_PUBLIC_NAN int
trio_isfinite
TRIO_PROTO((double number));
#endif
#if defined(TRIO_FUNC_SIGNBIT)
TRIO_PUBLIC_NAN int
trio_signbit
TRIO_PROTO((double number));
#endif
#if defined(TRIO_FUNC_FPCLASSIFY)
TRIO_PUBLIC_NAN int
trio_fpclassify
TRIO_PROTO((double number));
#endif
#if defined(TRIO_FUNC_FPCLASSIFY_AND_SIGNBIT)
TRIO_PUBLIC_NAN int
trio_fpclassify_and_signbit
TRIO_PROTO((double number, int *is_negative));
#endif
#ifdef __cplusplus
}
#endif
#endif /* TRIO_TRIONAN_H */

View File

@ -1,496 +0,0 @@
/*************************************************************************
*
* $Id$
*
* Copyright (C) 2000 Bjorn Reese and Daniel Stenberg.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND
* CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER.
*
************************************************************************
*
* Private functions, types, etc. used for callback functions.
*
* The ref pointer is an opaque type and should remain as such.
* Private data must only be accessible through the getter and
* setter functions.
*
************************************************************************/
#ifndef TRIO_TRIOP_H
#define TRIO_TRIOP_H
#include "triodef.h"
#include <stdlib.h>
#if defined(TRIO_COMPILER_ANCIENT)
# include <varargs.h>
#else
# include <stdarg.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
/*************************************************************************
* Supported standards
*/
/*
* TRIO_C99 (=0 or =1)
*
* Define this to 0 to disable C99 format specifier extensions, or
* define to 1 to enable them. The format specifiers that are
* disabled by this switch are labelled with [C99] in the format
* specifier documentation.
*/
#if !defined(TRIO_C99)
# define TRIO_C99 1
#endif
/*
* TRIO_BSD (=0 or =1)
*
* Define this to 0 to disable BSD format specifier extensions, or
* define to 1 to enable them. The format specifiers that are
* disabled by this switch are labelled with [BSD] in the format
* specifier documentation.
*/
#if !defined(TRIO_BSD)
# define TRIO_BSD 1
#endif
/*
* TRIO_GNU (=0 or =1)
*
* Define this to 0 to disable GNU format specifier extensions, or
* define to 1 to enable them. The format specifiers that are
* disabled by this switch are labelled with [GNU] in the format
* specifier documentation.
*/
#if !defined(TRIO_GNU)
# define TRIO_GNU 1
#endif
/*
* TRIO_MISC (=0 or =1)
*
* Define this to 0 to disable miscellaneous format specifier
* extensions, or define to 1 to enable them. The format specifiers
* that are disabled by this switch are labelled with [MISC] in the
* format specifier documentation.
*/
#if !defined(TRIO_MISC)
# define TRIO_MISC 1
#endif
/*
* TRIO_UNIX98 (=0 or =1)
*
* Define this to 0 to disable UNIX98 format specifier extensions,
* or define to 1 to enable them. The format specifiers that are
* disabled by this switch are labelled with [UNIX98] in the format
* specifier documentation.
*/
#if !defined(TRIO_UNIX98)
# define TRIO_UNIX98 1
#endif
/*
* TRIO_MICROSOFT (=0 or =1)
*
* Define this to 0 to disable Microsoft Visual C format specifier
* extensions, or define to 1 to enable them. The format specifiers
* that are disabled by this switch are labelled with [MSVC] in the
* format specifier documentation.
*/
#if !defined(TRIO_MICROSOFT)
# define TRIO_MICROSOFT 1
#endif
/*
* TRIO_EXTENSION (=0 or =1)
*
* Define this to 0 to disable Trio-specific extensions, or define
* to 1 to enable them. This has two effects: it controls whether
* or not the Trio user-defined formating mechanism
* (trio_register() etc) is supported, and it enables or disables
* Trio's own format specifier extensions. The format specifiers
* that are disabled by this switch are labelled with [TRIO] in
* the format specifier documentation.
*/
#if !defined(TRIO_EXTENSION)
# define TRIO_EXTENSION 1
#endif
/*
* TRIO_DEPRECATED (=0 or =1)
*
* Define this to 0 to disable deprecated functionality, or define
* to 1 to enable them.
*/
#if !defined(TRIO_DEPRECATED)
# define TRIO_DEPRECATED 1
#endif
/*************************************************************************
* Features
*/
#if defined(TRIO_SNPRINTF_ONLY)
# define TRIO_FEATURE_SCANF 0
# define TRIO_FEATURE_FILE 0
# define TRIO_FEATURE_STDIO 0
# define TRIO_FEATURE_FD 0
# define TRIO_FEATURE_DYNAMICSTRING 0
# define TRIO_FEATURE_CLOSURE 0
# define TRIO_FEATURE_ARGFUNC 0
# define TRIO_FEATURE_STRERR 0
# define TRIO_FEATURE_LOCALE 0
# define TRIO_EMBED_NAN 1
# define TRIO_EMBED_STRING 1
#endif
/*
* TRIO_FEATURE_SCANF (=0 or =1)
*
* Define this to 0 to disable all the scanf() variants, or define to 1
* to enable them.
*/
#if !defined(TRIO_FEATURE_SCANF)
# define TRIO_FEATURE_SCANF 1
#endif
/*
* TRIO_FEATURE_FILE (=0 or =1)
*
* Define this to 0 to disable compilation of the trio_fprintf() and
* trio_fscanf() family of functions, or define to 1 to enable them.
*
* This may be useful on an embedded platform with no filesystem.
* Note that trio_printf() uses fwrite to write to stdout, so if you
* do not have an implementation of fwrite() at all then you must also
* define TRIO_FEATURE_STDIO to 0.
*/
#if !defined(TRIO_FEATURE_FILE)
# define TRIO_FEATURE_FILE 1
#endif
/*
* TRIO_FEATURE_STDIO (=0 or =1)
*
* Define this to 0 to disable compilation of the trio_printf() and
* trio_scanf() family of functions, or define to 1 to enable them.
*
* This may be useful on an embedded platform with no standard I/O.
*/
#if !defined(TRIO_FEATURE_STDIO)
# define TRIO_FEATURE_STDIO 1
#endif
/*
* TRIO_FEATURE_FD (=0 or =1)
*
* Define this to 0 to disable compilation of the trio_dprintf() and
* trio_dscanf() family of functions, or define to 1 to enable them.
*
* This may be useful on an embedded platform with no filesystem, or on
* a platform that supports file I/O using FILE* but not using raw file
* descriptors.
*/
#if !defined(TRIO_FEATURE_FD)
# define TRIO_FEATURE_FD 1
#endif
/*
* TRIO_FEATURE_DYNAMICSTRING (=0 or =1)
*
* Define this to 0 to disable compilation of the trio_aprintf()
* family of functions, or define to 1 to enable them.
*
* If you define both this and TRIO_MINIMAL to 0, then Trio will never
* call malloc or free.
*/
#if !defined(TRIO_FEATURE_DYNAMICSTRING)
# define TRIO_FEATURE_DYNAMICSTRING 1
#endif
/*
* TRIO_FEATURE_CLOSURE (=0 or =1)
*
* Define this to 0 to disable compilation of the trio_cprintf() and
* trio_cscanf() family of functions, or define to 1 to enable them.
*
* These functions are rarely needed. This saves a (small) amount of code.
*/
#if !defined(TRIO_FEATURE_CLOSURE)
# define TRIO_FEATURE_CLOSURE 1
#endif
/*
* TRIO_FEATURE_ARGFUNC (=0 or =1)
*
* Define this to 0 to disable compilation of trio_cprintff() and
* trio_cscanff() functions and related code (might have a tiny
* performance gain), or define to 1 to enable them.
*
* This functionality is needed only if you have to fetch the arguments using
* a pull model instead of passing them all at once (for example if you plan
* to plug the library into a script interpreter or validate the types).
*
* Only the closure family of functions are available with this interface,
* because if you need this, you usually provide custom input/output
* handling too (and so this forces TRIO_FEATURE_CLOSURE to enabled).
*/
#if !defined(TRIO_FEATURE_ARGFUNC)
# define TRIO_FEATURE_ARGFUNC 1
#endif
#if TRIO_FEATURE_ARGFUNC
# undef TRIO_FEATURE_CLOSURE
# define TRIO_FEATURE_CLOSURE 1
#endif
/*
* TRIO_FEATURE_ERRORCODE (=0 or =1)
*
* Define this to 0 to return -1 from the print and scan function on
* error, or define to 1 to return a negative number with debugging
* information as part of the return code.
*
* If enabled, the return code will be a negative number, which encodes
* an error code and an error location. These can be decoded with the
* TRIO_ERROR_CODE and TRIO_ERROR_POSITION macros.
*/
#if defined(TRIO_ERRORS)
# define TRIO_FEATURE_ERRORCODE TRIO_ERRORS
#endif
#if !defined(TRIO_FEATURE_ERRORCODE)
# define TRIO_FEATURE_ERRORCODE 1
#endif
/*
* TRIO_FEATURE_STRERR (=0 or =1)
*
* Define this to 0 if you do not use trio_strerror(), or define to 1 if
* you do use it.
*
* This saves a (small) amount of code.
*/
#if !defined(TRIO_FEATURE_STRERR)
# define TRIO_FEATURE_STRERR 1
#endif
/*
* TRIO_FEATURE_FLOAT (=0 or =1)
*
* Define this to 0 to disable all floating-point support, or define
* to 1 to enable it.
*
* This is useful in restricted embedded platforms that do not support
* floating-point. Obviously you cannot use floating-point format
* specifiers if you define this.
*
* Do not compile trionan.c if you disable this.
*/
#if !defined(TRIO_FEATURE_FLOAT)
# define TRIO_FEATURE_FLOAT 1
#endif
/*
* TRIO_FEATURE_LOCALE (=0 or =1)
*
* Define this to 0 to disable customized locale support, or define
* to 1 to enable it.
*
* This saves a (small) amount of code.
*/
#if !defined(TRIO_FEATURE_LOCALE)
# define TRIO_FEATURE_LOCALE 1
#endif
/*
* TRIO_MINIMAL
*
* Define this to disable building the public trionan.h and triostr.h.
* If you define this, then you must not compile trionan.c and triostr.c
* separately.
*/
#if defined(TRIO_MINIMAL)
# if !defined(TRIO_EMBED_NAN)
# define TRIO_EMBED_NAN
# endif
# if !defined(TRIO_EMBED_STRING)
# define TRIO_EMBED_STRING
# endif
#endif
/* Does not work yet. Do not enable */
#ifndef TRIO_FEATURE_WIDECHAR
# define TRIO_FEATURE_WIDECHAR 0
#endif
/*************************************************************************
* Mapping standards to internal features
*/
#if !defined(TRIO_FEATURE_HEXFLOAT)
# define TRIO_FEATURE_HEXFLOAT (TRIO_C99 && TRIO_FEATURE_FLOAT)
#endif
#if !defined(TRIO_FEATURE_LONGDOUBLE)
# define TRIO_FEATURE_LONGDOUBLE TRIO_FEATURE_FLOAT
#endif
#if !defined(TRIO_FEATURE_ERRNO)
# define TRIO_FEATURE_ERRNO TRIO_GNU
#endif
#if !defined(TRIO_FEATURE_QUAD)
# define TRIO_FEATURE_QUAD (TRIO_BSD || TRIO_GNU)
#endif
#if !defined(TRIO_FEATURE_SIZE_T)
# define TRIO_FEATURE_SIZE_T TRIO_C99
#endif
#if !defined(TRIO_FEATURE_SIZE_T_UPPER)
# define TRIO_FEATURE_SIZE_T_UPPER TRIO_GNU
#endif
#if !defined(TRIO_FEATURE_PTRDIFF_T)
# define TRIO_FEATURE_PTRDIFF_T TRIO_C99
#endif
#if !defined(TRIO_FEATURE_INTMAX_T)
# define TRIO_FEATURE_INTMAX_T TRIO_C99
#endif
#if !defined(TRIO_FEATURE_FIXED_SIZE)
# define TRIO_FEATURE_FIXED_SIZE TRIO_MICROSOFT
#endif
#if !defined(TRIO_FEATURE_POSITIONAL)
# define TRIO_FEATURE_POSITIONAL TRIO_UNIX98
#endif
#if !defined(TRIO_FEATURE_USER_DEFINED)
# define TRIO_FEATURE_USER_DEFINED TRIO_EXTENSION
#endif
#if !defined(TRIO_FEATURE_BINARY)
# define TRIO_FEATURE_BINARY TRIO_EXTENSION
#endif
#if !defined(TRIO_FEATURE_QUOTE)
# define TRIO_FEATURE_QUOTE TRIO_EXTENSION
#endif
#if !defined(TRIO_FEATURE_STICKY)
# define TRIO_FEATURE_STICKY TRIO_EXTENSION
#endif
#if !defined(TRIO_FEATURE_VARSIZE)
# define TRIO_FEATURE_VARSIZE TRIO_EXTENSION
#endif
#if !defined(TRIO_FEATURE_ROUNDING)
# define TRIO_FEATURE_ROUNDING TRIO_EXTENSION
#endif
/*************************************************************************
* Memory handling
*/
#ifndef TRIO_MALLOC
# define TRIO_MALLOC(n) malloc(n)
#endif
#ifndef TRIO_REALLOC
# define TRIO_REALLOC(x,n) realloc((x),(n))
#endif
#ifndef TRIO_FREE
# define TRIO_FREE(x) free(x)
#endif
/*************************************************************************
* User-defined specifiers
*/
typedef int (*trio_callback_t) TRIO_PROTO((trio_pointer_t));
trio_pointer_t trio_register TRIO_PROTO((trio_callback_t callback, const char *name));
void trio_unregister TRIO_PROTO((trio_pointer_t handle));
TRIO_CONST char *trio_get_format TRIO_PROTO((trio_pointer_t ref));
TRIO_CONST trio_pointer_t trio_get_argument TRIO_PROTO((trio_pointer_t ref));
/* Modifiers */
int trio_get_width TRIO_PROTO((trio_pointer_t ref));
void trio_set_width TRIO_PROTO((trio_pointer_t ref, int width));
int trio_get_precision TRIO_PROTO((trio_pointer_t ref));
void trio_set_precision TRIO_PROTO((trio_pointer_t ref, int precision));
int trio_get_base TRIO_PROTO((trio_pointer_t ref));
void trio_set_base TRIO_PROTO((trio_pointer_t ref, int base));
int trio_get_padding TRIO_PROTO((trio_pointer_t ref));
void trio_set_padding TRIO_PROTO((trio_pointer_t ref, int is_padding));
int trio_get_short TRIO_PROTO((trio_pointer_t ref)); /* h */
void trio_set_shortshort TRIO_PROTO((trio_pointer_t ref, int is_shortshort));
int trio_get_shortshort TRIO_PROTO((trio_pointer_t ref)); /* hh */
void trio_set_short TRIO_PROTO((trio_pointer_t ref, int is_short));
int trio_get_long TRIO_PROTO((trio_pointer_t ref)); /* l */
void trio_set_long TRIO_PROTO((trio_pointer_t ref, int is_long));
int trio_get_longlong TRIO_PROTO((trio_pointer_t ref)); /* ll */
void trio_set_longlong TRIO_PROTO((trio_pointer_t ref, int is_longlong));
int trio_get_longdouble TRIO_PROTO((trio_pointer_t ref)); /* L */
void trio_set_longdouble TRIO_PROTO((trio_pointer_t ref, int is_longdouble));
int trio_get_alternative TRIO_PROTO((trio_pointer_t ref)); /* # */
void trio_set_alternative TRIO_PROTO((trio_pointer_t ref, int is_alternative));
int trio_get_alignment TRIO_PROTO((trio_pointer_t ref)); /* - */
void trio_set_alignment TRIO_PROTO((trio_pointer_t ref, int is_leftaligned));
int trio_get_spacing TRIO_PROTO((trio_pointer_t ref)); /* (space) */
void trio_set_spacing TRIO_PROTO((trio_pointer_t ref, int is_space));
int trio_get_sign TRIO_PROTO((trio_pointer_t ref)); /* + */
void trio_set_sign TRIO_PROTO((trio_pointer_t ref, int is_showsign));
#if TRIO_FEATURE_QUOTE
int trio_get_quote TRIO_PROTO((trio_pointer_t ref)); /* ' */
void trio_set_quote TRIO_PROTO((trio_pointer_t ref, int is_quote));
#endif
int trio_get_upper TRIO_PROTO((trio_pointer_t ref));
void trio_set_upper TRIO_PROTO((trio_pointer_t ref, int is_upper));
#if TRIO_FEATURE_INTMAX_T
int trio_get_largest TRIO_PROTO((trio_pointer_t ref)); /* j */
void trio_set_largest TRIO_PROTO((trio_pointer_t ref, int is_largest));
#endif
#if TRIO_FEATURE_PTRDIFF_T
int trio_get_ptrdiff TRIO_PROTO((trio_pointer_t ref)); /* t */
void trio_set_ptrdiff TRIO_PROTO((trio_pointer_t ref, int is_ptrdiff));
#endif
#if TRIO_FEATURE_SIZE_T
int trio_get_size TRIO_PROTO((trio_pointer_t ref)); /* z / Z */
void trio_set_size TRIO_PROTO((trio_pointer_t ref, int is_size));
#endif
/* Printing */
int trio_print_ref TRIO_PROTO((trio_pointer_t ref, const char *format, ...));
int trio_vprint_ref TRIO_PROTO((trio_pointer_t ref, const char *format, va_list args));
int trio_printv_ref TRIO_PROTO((trio_pointer_t ref, const char *format, trio_pointer_t *args));
void trio_print_int TRIO_PROTO((trio_pointer_t ref, int number));
void trio_print_uint TRIO_PROTO((trio_pointer_t ref, unsigned int number));
/* void trio_print_long TRIO_PROTO((trio_pointer_t ref, long number)); */
/* void trio_print_ulong TRIO_PROTO((trio_pointer_t ref, unsigned long number)); */
void trio_print_double TRIO_PROTO((trio_pointer_t ref, double number));
void trio_print_string TRIO_PROTO((trio_pointer_t ref, TRIO_CONST char *string));
void trio_print_pointer TRIO_PROTO((trio_pointer_t ref, trio_pointer_t pointer));
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* TRIO_TRIOP_H */

File diff suppressed because it is too large Load Diff

View File

@ -1,681 +0,0 @@
/*************************************************************************
*
* $Id$
*
* Copyright (C) 2001 Bjorn Reese and Daniel Stenberg.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND
* CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER.
*
************************************************************************/
#ifndef TRIO_TRIOSTR_H
#define TRIO_TRIOSTR_H
/*
* Documentation is located in triostr.c
*/
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "triodef.h"
#include "triop.h"
#ifdef __cplusplus
extern "C" {
#endif
enum {
TRIO_HASH_NONE = 0,
TRIO_HASH_PLAIN,
TRIO_HASH_TWOSIGNED
};
#if !defined(TRIO_PUBLIC_STRING)
# if !defined(TRIO_PUBLIC)
# define TRIO_PUBLIC
# endif
# define TRIO_PUBLIC_STRING TRIO_PUBLIC
#endif
/*************************************************************************
* Dependencies
*/
#if defined(TRIO_EMBED_STRING)
/*
* The application that triostr is embedded in must define which functions
* it uses.
*
* The following resolves internal dependencies.
*/
# if defined(TRIO_FUNC_XSTRING_SET)
# if !defined(TRIO_FUNC_DUPLICATE)
# define TRIO_FUNC_DUPLICATE
# endif
# endif
# if defined(TRIO_FUNC_DUPLICATE) \
|| defined(TRIO_FUNC_DUPLICATE_MAX) \
|| defined(TRIO_FUNC_STRING_DUPLICATE) \
|| defined(TRIO_FUNC_XSTRING_DUPLICATE)
# if !defined(TRIO_FUNC_CREATE)
# define TRIO_FUNC_CREATE
# endif
# if !defined(TRIO_FUNC_COPY_MAX)
# define TRIO_FUNC_COPY_MAX
# endif
# endif
# if defined(TRIO_FUNC_STRING_CREATE)
# if !defined(TRIO_FUNC_STRING_DESTROY)
# define TRIO_FUNC_STRING_DESTROY
# endif
# endif
# if defined(TRIO_FUNC_STRING_DESTROY) \
|| defined(TRIO_FUNC_XSTRING_SET)
# if !defined(TRIO_FUNC_DESTROY)
# define TRIO_FUNC_DESTROY
# endif
# endif
# if defined(TRIO_FUNC_EQUAL_LOCALE) \
|| defined(TRIO_FUNC_STRING_EQUAL) \
|| defined(TRIO_FUNC_XSTRING_EQUAL)
# if !defined(TRIO_FUNC_EQUAL)
# define TRIO_FUNC_EQUAL
# endif
# endif
# if defined(TRIO_FUNC_EQUAL_CASE) \
|| defined(TRIO_FUNC_STRING_EQUAL_CASE) \
|| defined(TRIO_FUNC_XSTRING_EQUAL_CASE)
# if !defined(TRIO_FUNC_EQUAL_CASE)
# define TRIO_FUNC_EQUAL_CASE
# endif
# endif
# if defined(TRIO_FUNC_SUBSTRING_MAX) \
|| defined(TRIO_FUNC_STRING_EQUAL_MAX) \
|| defined(TRIO_FUNC_XSTRING_EQUAL_MAX)
# if !defined(TRIO_FUNC_EQUAL_MAX)
# define TRIO_FUNC_EQUAL_MAX
# endif
# endif
# if defined(TRIO_FUNC_TO_DOUBLE) \
|| defined(TRIO_FUNC_TO_FLOAT)
# if !defined(TRIO_FUNC_TO_LONG_DOUBLE)
# define TRIO_FUNC_TO_LONG_DOUBLE
# endif
# endif
# if defined(TRIO_FUNC_STRING_TERMINATE)
# if !defined(TRIO_FUNC_XSTRING_APPEND_CHAR)
# define TRIO_FUNC_XSTRING_APPEND_CHAR
# endif
# endif
# if defined(TRIO_FUNC_XSTRING_APPEND_CHAR)
# if !defined(TRIO_FUNC_STRING_SIZE)
# define TRIO_FUNC_STRING_SIZE
# endif
# endif
#else
/*
* When triostr is not embedded all functions are defined.
*/
# define TRIO_FUNC_APPEND
# define TRIO_FUNC_APPEND_MAX
# define TRIO_FUNC_CONTAINS
# define TRIO_FUNC_COPY
# define TRIO_FUNC_COPY_MAX
# define TRIO_FUNC_CREATE
# define TRIO_FUNC_DESTROY
# define TRIO_FUNC_DUPLICATE
# define TRIO_FUNC_DUPLICATE_MAX
# define TRIO_FUNC_EQUAL
# define TRIO_FUNC_EQUAL_CASE
# define TRIO_FUNC_EQUAL_CASE_MAX
# define TRIO_FUNC_EQUAL_LOCALE
# define TRIO_FUNC_EQUAL_MAX
# define TRIO_FUNC_ERROR
# if !defined(TRIO_PLATFORM_WINCE)
# define TRIO_FUNC_FORMAT_DATE_MAX
# endif
# define TRIO_FUNC_HASH
# define TRIO_FUNC_INDEX
# define TRIO_FUNC_INDEX_LAST
# define TRIO_FUNC_LENGTH
# define TRIO_FUNC_LENGTH_MAX
# define TRIO_FUNC_LOWER
# define TRIO_FUNC_MATCH
# define TRIO_FUNC_MATCH_CASE
# define TRIO_FUNC_SPAN_FUNCTION
# define TRIO_FUNC_SUBSTRING
# define TRIO_FUNC_SUBSTRING_MAX
# define TRIO_FUNC_TO_DOUBLE
# define TRIO_FUNC_TO_FLOAT
# define TRIO_FUNC_TO_LONG
# define TRIO_FUNC_TO_LONG_DOUBLE
# define TRIO_FUNC_TO_LOWER
# define TRIO_FUNC_TO_UNSIGNED_LONG
# define TRIO_FUNC_TO_UPPER
# define TRIO_FUNC_TOKENIZE
# define TRIO_FUNC_UPPER
# define TRIO_FUNC_STRING_APPEND
# define TRIO_FUNC_STRING_CONTAINS
# define TRIO_FUNC_STRING_COPY
# define TRIO_FUNC_STRING_CREATE
# define TRIO_FUNC_STRING_DESTROY
# define TRIO_FUNC_STRING_DUPLICATE
# define TRIO_FUNC_STRING_EQUAL
# define TRIO_FUNC_STRING_EQUAL_CASE
# define TRIO_FUNC_STRING_EQUAL_CASE_MAX
# define TRIO_FUNC_STRING_EQUAL_MAX
# define TRIO_FUNC_STRING_EXTRACT
# if !defined(TRIO_PLATFORM_WINCE)
# define TRIO_FUNC_STRING_FORMAT_DATE_MAX
# endif
# define TRIO_FUNC_STRING_GET
# define TRIO_FUNC_STRING_INDEX
# define TRIO_FUNC_STRING_INDEX_LAST
# define TRIO_FUNC_STRING_LENGTH
# define TRIO_FUNC_STRING_LOWER
# define TRIO_FUNC_STRING_MATCH
# define TRIO_FUNC_STRING_MATCH_CASE
# define TRIO_FUNC_STRING_SIZE
# define TRIO_FUNC_STRING_SUBSTRING
# define TRIO_FUNC_STRING_TERMINATE
# define TRIO_FUNC_STRING_UPPER
# define TRIO_FUNC_XSTRING_APPEND
# define TRIO_FUNC_XSTRING_APPEND_CHAR
# define TRIO_FUNC_XSTRING_APPEND_MAX
# define TRIO_FUNC_XSTRING_CONTAINS
# define TRIO_FUNC_XSTRING_COPY
# define TRIO_FUNC_XSTRING_DUPLICATE
# define TRIO_FUNC_XSTRING_EQUAL
# define TRIO_FUNC_XSTRING_EQUAL_CASE
# define TRIO_FUNC_XSTRING_EQUAL_CASE_MAX
# define TRIO_FUNC_XSTRING_EQUAL_MAX
# define TRIO_FUNC_XSTRING_MATCH
# define TRIO_FUNC_XSTRING_MATCH_CASE
# define TRIO_FUNC_XSTRING_SET
# define TRIO_FUNC_XSTRING_SUBSTRING
#endif
/*************************************************************************
* String functions
*/
#if defined(TRIO_FUNC_APPEND)
TRIO_PUBLIC_STRING int
trio_append
TRIO_PROTO((char *target, TRIO_CONST char *source));
#endif
#if defined(TRIO_FUNC_APPEND_MAX)
TRIO_PUBLIC_STRING int
trio_append_max
TRIO_PROTO((char *target, size_t max, TRIO_CONST char *source));
#endif
#if defined(TRIO_FUNC_CONTAINS)
TRIO_PUBLIC_STRING int
trio_contains
TRIO_PROTO((TRIO_CONST char *string, TRIO_CONST char *substring));
#endif
#if defined(TRIO_FUNC_COPY)
TRIO_PUBLIC_STRING int
trio_copy
TRIO_PROTO((char *target, TRIO_CONST char *source));
#endif
#if defined(TRIO_FUNC_COPY_MAX)
TRIO_PUBLIC_STRING int
trio_copy_max
TRIO_PROTO((char *target, size_t max, TRIO_CONST char *source));
#endif
#if defined(TRIO_FUNC_CREATE)
TRIO_PUBLIC_STRING char *
trio_create
TRIO_PROTO((size_t size));
#endif
#if defined(TRIO_FUNC_DESTROY)
TRIO_PUBLIC_STRING void
trio_destroy
TRIO_PROTO((char *string));
#endif
#if defined(TRIO_FUNC_DUPLICATE)
TRIO_PUBLIC_STRING char *
trio_duplicate
TRIO_PROTO((TRIO_CONST char *source));
#endif
#if defined(TRIO_FUNC_DUPLICATE_MAX)
TRIO_PUBLIC_STRING char *
trio_duplicate_max
TRIO_PROTO((TRIO_CONST char *source, size_t max));
#endif
#if defined(TRIO_FUNC_EQUAL)
TRIO_PUBLIC_STRING int
trio_equal
TRIO_PROTO((TRIO_CONST char *first, TRIO_CONST char *second));
#endif
#if defined(TRIO_FUNC_EQUAL_CASE)
TRIO_PUBLIC_STRING int
trio_equal_case
TRIO_PROTO((TRIO_CONST char *first, TRIO_CONST char *second));
#endif
#if defined(TRIO_FUNC_EQUAL_CASE_MAX)
TRIO_PUBLIC_STRING int
trio_equal_case_max
TRIO_PROTO((TRIO_CONST char *first, size_t max, TRIO_CONST char *second));
#endif
#if defined(TRIO_FUNC_EQUAL_LOCALE)
TRIO_PUBLIC_STRING int
trio_equal_locale
TRIO_PROTO((TRIO_CONST char *first, TRIO_CONST char *second));
#endif
#if defined(TRIO_FUNC_EQUAL_MAX)
TRIO_PUBLIC_STRING int
trio_equal_max
TRIO_PROTO((TRIO_CONST char *first, size_t max, TRIO_CONST char *second));
#endif
#if defined(TRIO_FUNC_ERROR)
TRIO_PUBLIC_STRING TRIO_CONST char *
trio_error
TRIO_PROTO((int));
#endif
#if defined(TRIO_FUNC_FORMAT_DATE_MAX)
TRIO_PUBLIC_STRING size_t
trio_format_date_max
TRIO_PROTO((char *target, size_t max, TRIO_CONST char *format, TRIO_CONST struct tm *datetime));
#endif
#if defined(TRIO_FUNC_HASH)
TRIO_PUBLIC_STRING unsigned long
trio_hash
TRIO_PROTO((TRIO_CONST char *string, int type));
#endif
#if defined(TRIO_FUNC_INDEX)
TRIO_PUBLIC_STRING char *
trio_index
TRIO_PROTO((TRIO_CONST char *string, int character));
#endif
#if defined(TRIO_FUNC_INDEX_LAST)
TRIO_PUBLIC_STRING char *
trio_index_last
TRIO_PROTO((TRIO_CONST char *string, int character));
#endif
#if defined(TRIO_FUNC_LENGTH)
TRIO_PUBLIC_STRING size_t
trio_length
TRIO_PROTO((TRIO_CONST char *string));
#endif
#if defined(TRIO_FUNC_LENGTH_MAX)
TRIO_PUBLIC_STRING size_t
trio_length_max
TRIO_PROTO((TRIO_CONST char *string, size_t max));
#endif
#if defined(TRIO_FUNC_LOWER)
TRIO_PUBLIC_STRING int
trio_lower
TRIO_PROTO((char *target));
#endif
#if defined(TRIO_FUNC_MATCH)
TRIO_PUBLIC_STRING int
trio_match
TRIO_PROTO((TRIO_CONST char *string, TRIO_CONST char *pattern));
#endif
#if defined(TRIO_FUNC_MATCH_CASE)
TRIO_PUBLIC_STRING int
trio_match_case
TRIO_PROTO((TRIO_CONST char *string, TRIO_CONST char *pattern));
#endif
#if defined(TRIO_FUNC_SPAN_FUNCTION)
TRIO_PUBLIC_STRING size_t
trio_span_function
TRIO_PROTO((char *target, TRIO_CONST char *source, int (*Function) TRIO_PROTO((int))));
#endif
#if defined(TRIO_FUNC_SUBSTRING)
TRIO_PUBLIC_STRING char *
trio_substring
TRIO_PROTO((TRIO_CONST char *string, TRIO_CONST char *substring));
#endif
#if defined(TRIO_FUNC_SUBSTRING_MAX)
TRIO_PUBLIC_STRING char *
trio_substring_max
TRIO_PROTO((TRIO_CONST char *string, size_t max, TRIO_CONST char *substring));
#endif
#if defined(TRIO_FUNC_TO_DOUBLE)
TRIO_PUBLIC_STRING double
trio_to_double
TRIO_PROTO((TRIO_CONST char *source, char **endp));
#endif
#if defined(TRIO_FUNC_TO_FLOAT)
TRIO_PUBLIC_STRING float
trio_to_float
TRIO_PROTO((TRIO_CONST char *source, char **endp));
#endif
#if defined(TRIO_FUNC_TO_LONG)
TRIO_PUBLIC_STRING long
trio_to_long
TRIO_PROTO((TRIO_CONST char *source, char **endp, int base));
#endif
#if defined(TRIO_FUNC_TO_LOWER)
TRIO_PUBLIC_STRING int
trio_to_lower
TRIO_PROTO((int source));
#endif
#if defined(TRIO_FUNC_TO_LONG_DOUBLE)
TRIO_PUBLIC_STRING trio_long_double_t
trio_to_long_double
TRIO_PROTO((TRIO_CONST char *source, char **endp));
#endif
#if defined(TRIO_FUNC_TO_UNSIGNED_LONG)
TRIO_PUBLIC_STRING unsigned long
trio_to_unsigned_long
TRIO_PROTO((TRIO_CONST char *source, char **endp, int base));
#endif
#if defined(TRIO_FUNC_TO_UPPER)
TRIO_PUBLIC_STRING int
trio_to_upper
TRIO_PROTO((int source));
#endif
#if defined(TRIO_FUNC_TOKENIZE)
TRIO_PUBLIC_STRING char *
trio_tokenize
TRIO_PROTO((char *string, TRIO_CONST char *delimiters));
#endif
#if defined(TRIO_FUNC_UPPER)
TRIO_PUBLIC_STRING int
trio_upper
TRIO_PROTO((char *target));
#endif
/*************************************************************************
* Dynamic string functions
*/
/*
* Opaque type for dynamic strings
*/
typedef struct _trio_string_t trio_string_t;
#if defined(TRIO_FUNC_STRING_APPEND)
TRIO_PUBLIC_STRING int
trio_string_append
TRIO_PROTO((trio_string_t *self, trio_string_t *other));
#endif
#if defined(TRIO_FUNC_STRING_CONTAINS)
TRIO_PUBLIC_STRING int
trio_string_contains
TRIO_PROTO((trio_string_t *self, trio_string_t *other));
#endif
#if defined(TRIO_FUNC_STRING_COPY)
TRIO_PUBLIC_STRING int
trio_string_copy
TRIO_PROTO((trio_string_t *self, trio_string_t *other));
#endif
#if defined(TRIO_FUNC_STRING_CREATE)
TRIO_PUBLIC_STRING trio_string_t *
trio_string_create
TRIO_PROTO((int initial_size));
#endif
#if defined(TRIO_FUNC_STRING_DESTROY)
TRIO_PUBLIC_STRING void
trio_string_destroy
TRIO_PROTO((trio_string_t *self));
#endif
#if defined(TRIO_FUNC_STRING_DUPLICATE)
TRIO_PUBLIC_STRING trio_string_t *
trio_string_duplicate
TRIO_PROTO((trio_string_t *other));
#endif
#if defined(TRIO_FUNC_STRING_EQUAL)
TRIO_PUBLIC_STRING int
trio_string_equal
TRIO_PROTO((trio_string_t *self, trio_string_t *other));
#endif
#if defined(TRIO_FUNC_STRING_EQUAL_MAX)
TRIO_PUBLIC_STRING int
trio_string_equal_max
TRIO_PROTO((trio_string_t *self, size_t max, trio_string_t *second));
#endif
#if defined(TRIO_FUNC_STRING_EQUAL_CASE)
TRIO_PUBLIC_STRING int
trio_string_equal_case
TRIO_PROTO((trio_string_t *self, trio_string_t *other));
#endif
#if defined(TRIO_FUNC_STRING_EQUAL_CASE_MAX)
TRIO_PUBLIC_STRING int
trio_string_equal_case_max
TRIO_PROTO((trio_string_t *self, size_t max, trio_string_t *other));
#endif
#if defined(TRIO_FUNC_STRING_EXTRACT)
TRIO_PUBLIC_STRING char *
trio_string_extract
TRIO_PROTO((trio_string_t *self));
#endif
#if defined(TRIO_FUNC_STRING_FORMAT_DATE_MAX)
TRIO_PUBLIC_STRING size_t
trio_string_format_date_max
TRIO_PROTO((trio_string_t *self, size_t max, TRIO_CONST char *format, TRIO_CONST struct tm *datetime));
#endif
#if defined(TRIO_FUNC_STRING_GET)
TRIO_PUBLIC_STRING char *
trio_string_get
TRIO_PROTO((trio_string_t *self, int offset));
#endif
#if defined(TRIO_FUNC_STRING_INDEX)
TRIO_PUBLIC_STRING char *
trio_string_index
TRIO_PROTO((trio_string_t *self, int character));
#endif
#if defined(TRIO_FUNC_STRING_INDEX_LAST)
TRIO_PUBLIC_STRING char *
trio_string_index_last
TRIO_PROTO((trio_string_t *self, int character));
#endif
#if defined(TRIO_FUNC_STRING_LENGTH)
TRIO_PUBLIC_STRING int
trio_string_length
TRIO_PROTO((trio_string_t *self));
#endif
#if defined(TRIO_FUNC_STRING_LOWER)
TRIO_PUBLIC_STRING int
trio_string_lower
TRIO_PROTO((trio_string_t *self));
#endif
#if defined(TRIO_FUNC_STRING_MATCH)
TRIO_PUBLIC_STRING int
trio_string_match
TRIO_PROTO((trio_string_t *self, trio_string_t *other));
#endif
#if defined(TRIO_FUNC_STRING_MATCH_CASE)
TRIO_PUBLIC_STRING int
trio_string_match_case
TRIO_PROTO((trio_string_t *self, trio_string_t *other));
#endif
#if defined(TRIO_FUNC_STRING_SIZE)
TRIO_PUBLIC_STRING int
trio_string_size
TRIO_PROTO((trio_string_t *self));
#endif
#if defined(TRIO_FUNC_STRING_SUBSTRING)
TRIO_PUBLIC_STRING char *
trio_string_substring
TRIO_PROTO((trio_string_t *self, trio_string_t *other));
#endif
#if defined(TRIO_FUNC_STRING_TERMINATE)
TRIO_PUBLIC_STRING void
trio_string_terminate
TRIO_PROTO((trio_string_t *self));
#endif
#if defined(TRIO_FUNC_STRING_UPPER)
TRIO_PUBLIC_STRING int
trio_string_upper
TRIO_PROTO((trio_string_t *self));
#endif
#if defined(TRIO_FUNC_XSTRING_APPEND)
TRIO_PUBLIC_STRING int
trio_xstring_append
TRIO_PROTO((trio_string_t *self, TRIO_CONST char *other));
#endif
#if defined(TRIO_FUNC_XSTRING_APPEND_CHAR)
TRIO_PUBLIC_STRING int
trio_xstring_append_char
TRIO_PROTO((trio_string_t *self, char character));
#endif
#if defined(TRIO_FUNC_XSTRING_APPEND_MAX)
TRIO_PUBLIC_STRING int
trio_xstring_append_max
TRIO_PROTO((trio_string_t *self, TRIO_CONST char *other, size_t max));
#endif
#if defined(TRIO_FUNC_XSTRING_CONTAINS)
TRIO_PUBLIC_STRING int
trio_xstring_contains
TRIO_PROTO((trio_string_t *self, TRIO_CONST char *other));
#endif
#if defined(TRIO_FUNC_XSTRING_COPY)
TRIO_PUBLIC_STRING int
trio_xstring_copy
TRIO_PROTO((trio_string_t *self, TRIO_CONST char *other));
#endif
#if defined(TRIO_FUNC_XSTRING_DUPLICATE)
TRIO_PUBLIC_STRING trio_string_t *
trio_xstring_duplicate
TRIO_PROTO((TRIO_CONST char *other));
#endif
#if defined(TRIO_FUNC_XSTRING_EQUAL)
TRIO_PUBLIC_STRING int
trio_xstring_equal
TRIO_PROTO((trio_string_t *self, TRIO_CONST char *other));
#endif
#if defined(TRIO_FUNC_XSTRING_EQUAL_MAX)
TRIO_PUBLIC_STRING int
trio_xstring_equal_max
TRIO_PROTO((trio_string_t *self, size_t max, TRIO_CONST char *other));
#endif
#if defined(TRIO_FUNC_XSTRING_EQUAL_CASE)
TRIO_PUBLIC_STRING int
trio_xstring_equal_case
TRIO_PROTO((trio_string_t *self, TRIO_CONST char *other));
#endif
#if defined(TRIO_FUNC_XSTRING_EQUAL_CASE_MAX)
TRIO_PUBLIC_STRING int
trio_xstring_equal_case_max
TRIO_PROTO((trio_string_t *self, size_t max, TRIO_CONST char *other));
#endif
#if defined(TRIO_FUNC_XSTRING_MATCH)
TRIO_PUBLIC_STRING int
trio_xstring_match
TRIO_PROTO((trio_string_t *self, TRIO_CONST char *other));
#endif
#if defined(TRIO_FUNC_XSTRING_MATCH_CASE)
TRIO_PUBLIC_STRING int
trio_xstring_match_case
TRIO_PROTO((trio_string_t *self, TRIO_CONST char *other));
#endif
#if defined(TRIO_FUNC_XSTRING_SET)
TRIO_PUBLIC_STRING void
trio_xstring_set
TRIO_PROTO((trio_string_t *self, char *buffer));
#endif
#if defined(TRIO_FUNC_XSTRING_SUBSTRING)
TRIO_PUBLIC_STRING char *
trio_xstring_substring
TRIO_PROTO((trio_string_t *self, TRIO_CONST char *other));
#endif
#ifdef __cplusplus
}
#endif
#endif /* TRIO_TRIOSTR_H */

View File

@ -1,106 +0,0 @@
// TODO/WIP
/* Mednafen - Multi-system Emulator
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <sys/stat.h>
#include "mednafen.h"
#include "Stream.h"
#include "FileStream.h"
#include <trio/trio.h>
#include <stdarg.h>
#include <string.h>
#ifdef _WIN32
#include <io.h>
#else
#include <unistd.h>
#endif
#define fseeko fseek
#define ftello ftell
FileStream::FileStream(const char *path, const int mode): OpenedMode(mode)
{
if(!(fp = fopen(path, (mode == FileStream::MODE_WRITE) ? "wb" : "rb")))
{
ErrnoHolder ene(errno);
throw(MDFN_Error(ene.Errno(), _("Error opening file %s"), ene.StrError()));
}
}
FileStream::~FileStream()
{
}
uint64 FileStream::attributes(void)
{
uint64 ret = ATTRIBUTE_SEEKABLE;
switch(OpenedMode)
{
case FileStream::MODE_READ:
ret |= ATTRIBUTE_READABLE;
break;
case FileStream::MODE_WRITE_SAFE:
case FileStream::MODE_WRITE:
ret |= ATTRIBUTE_WRITEABLE;
break;
}
return ret;
}
uint64 FileStream::read(void *data, uint64 count, bool error_on_eos)
{
return fread(data, 1, count, fp);
}
void FileStream::write(const void *data, uint64 count)
{
fwrite(data, 1, count, fp);
}
void FileStream::seek(int64 offset, int whence)
{
fseeko(fp, offset, whence);
}
int64 FileStream::tell(void)
{
return ftello(fp);
}
int64 FileStream::size(void) {
struct stat buf;
fstat(fileno(fp), &buf);
return(buf.st_size);
}
void FileStream::close(void)
{
if(!fp)
return;
FILE *tmp = fp;
fp = NULL;
fclose(tmp);
}

View File

@ -1,56 +0,0 @@
/* Mednafen - Multi-system Emulator
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
// TODO/WIP
#ifndef __MDFN_FILESTREAM_H
#define __MDFN_FILESTREAM_H
#include "Stream.h"
#include "FileWrapper.h"
class FileStream : public Stream
{
public:
enum
{
MODE_READ = FileWrapper::MODE_READ,
MODE_WRITE = FileWrapper::MODE_WRITE,
MODE_WRITE_SAFE = FileWrapper::MODE_WRITE_SAFE,
};
FileStream(const char *path, const int mode);
virtual ~FileStream();
virtual uint64 attributes(void);
virtual uint64 read(void *data, uint64 count, bool error_on_eos = true);
virtual void write(const void *data, uint64 count);
virtual void seek(int64 offset, int whence);
virtual int64 tell(void);
virtual int64 size(void);
virtual void close(void);
private:
FILE *fp;
const int OpenedMode;
};
#endif

View File

@ -1,135 +0,0 @@
/* Mednafen - Multi-system Emulator
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <sys/stat.h>
#include "mednafen.h"
#include "FileWrapper.h"
#include <trio/trio.h>
#include <stdarg.h>
#include <string.h>
#ifdef _WIN32
#include <io.h>
#else
#include <unistd.h>
#endif
// Some really bad preprocessor abuse follows to handle platforms that don't have fseeko and ftello...and of course
// for largefile support on Windows:
#define fseeko fseek
#define ftello ftell
// For special uses, IE in classes that take a path or a FileWrapper & in the constructor, and the FileWrapper non-pointer member
// is in the initialization list for the path constructor but not the constructor with FileWrapper&
FileWrapper::FileWrapper(const char *path, const int mode, const char *purpose) : OpenedMode(mode)
{
if(!(fp = fopen(path, (mode == MODE_WRITE) ? "wb" : "rb")))
{
ErrnoHolder ene(errno);
throw(MDFN_Error(ene.Errno(), _("Error opening file %s"), ene.StrError()));
}
}
FileWrapper::~FileWrapper()
{
close();
}
void FileWrapper::close(void)
{
if(!fp)
return;
FILE *tmp = fp;
fp = NULL;
fclose(tmp);
}
uint64 FileWrapper::read(void *data, uint64 count, bool error_on_eof)
{
return fread(data, 1, count, fp);
}
void FileWrapper::flush(void)
{
fflush(fp);
}
void FileWrapper::write(const void *data, uint64 count)
{
fwrite(data, 1, count, fp);
}
int FileWrapper::scanf(const char *format, ...)
{
va_list ap;
int ret;
va_start(ap, format);
ret = trio_vfscanf(fp, format, ap);
va_end(ap);
return ret;
}
void FileWrapper::put_char(int c)
{
fputc(c, fp);
}
void FileWrapper::put_string(const char *str)
{
write(str, strlen(str));
}
// We need to decide whether to prohibit NULL characters in output and input strings via std::string.
// Yes for correctness, no for potential security issues(though unlikely in context all things considered).
void FileWrapper::put_string(const std::string &str)
{
write(str.data(), str.size());
}
char *FileWrapper::get_line(char *buf_s, int buf_size)
{
return ::fgets(buf_s, buf_size, fp);
}
void FileWrapper::seek(int64 offset, int whence)
{
fseeko(fp, offset, whence);
}
int64 FileWrapper::size(void)
{
struct stat buf;
fstat(fileno(fp), &buf);
return(buf.st_size);
}
int64 FileWrapper::tell(void)
{
return ftello(fp);
}

View File

@ -1,57 +0,0 @@
#ifndef __MDFN_FILEWRAPPER_H
#define __MDFN_FILEWRAPPER_H
// A stdio FILE wrapper(with some BSD and POSIXisms, and a little dash of Win32, thrown in for special behaviors)
class FileWrapper
{
public:
enum
{
MODE_READ = 0,
MODE_WRITE,
MODE_WRITE_SAFE // Will throw an exception instead of overwriting an existing file.
};
FileWrapper(const char *path, const int mode, const char *purpose = NULL);
~FileWrapper();
uint64 read(void *data, uint64 count, bool error_on_eof = true);
void write(const void *data, uint64 count);
int scanf(const char *format, ...) MDFN_FORMATSTR(scanf, 2, 3);
void put_char(int c);
void put_string(const char *str);
void put_string(const std::string &str);
char *get_line(char *s, int size); // Same semantics as fgets(), for now
void seek(int64 offset, int whence);
int64 tell(void);
int64 size(void);
void flush(void);
void close(void); // Flushes and closes the underlying OS/C lib file. Calling any other method of this class after a call to
// this method is illegal(except for the implicit call to the destructor).
//
// This is necessary since there can be errors when closing a file, and we can't safely throw an
// exception from the destructor.
//
// Manually calling this method isn't strictly necessary, it'll be called from the destructor
// automatically, but calling is strongly recommended when the file is opened for writing.
private:
FileWrapper & operator=(const FileWrapper &); // Assignment operator
FileWrapper(const FileWrapper &); // Copy constructor
FILE *fp;
const int OpenedMode;
};
#endif

View File

@ -1,112 +0,0 @@
// TODO/WIP
/* Mednafen - Multi-system Emulator
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "octoshock.h"
#include "Stream.h"
//#include <trio/trio.h>
Stream::Stream()
{
}
Stream::~Stream()
{
}
void Stream::put_line(const std::string& str)
{
char l = '\n';
write(&str[0], str.size());
write(&l, sizeof(l));
}
void Stream::print_format(const char *format, ...)
{
//char *str = NULL;
//int rc;
//va_list ap;
//va_start(ap, format);
//rc = trio_vasprintf(&str, format, ap);
//va_end(ap);
//if(rc < 0)
// throw MDFN_Error(0, "Error in trio_vasprintf()");
//else
//{
// try // Bleck
// {
// write(str, rc);
// }
// catch(...)
// {
// free(str);
// throw;
// }
// free(str);
//}
}
int Stream::get_line(std::string &str)
{
uint8 c;
str.clear(); // or str.resize(0)??
while(read(&c, sizeof(c), false) > 0)
{
if(c == '\r' || c == '\n' || c == 0)
return(c);
str.push_back(c);
}
return(str.length() ? 256 : -1);
}
StreamFilter::StreamFilter()
{
target_stream = NULL;
}
StreamFilter::StreamFilter(Stream *target_arg)
{
target_stream = target_arg;
}
StreamFilter::~StreamFilter()
{
if(target_stream)
delete target_stream;
}
Stream* StreamFilter::steal(void)
{
Stream *ret = target_stream;
target_stream = NULL;
return ret;
}

View File

@ -1,206 +0,0 @@
#ifndef __MDFN_STREAM_H
#define __MDFN_STREAM_H
// TODO/WIP
// TODO?: BufferedStream, no virtual functions, yes inline functions, constructor takes a Stream* argument.
#include <errno.h>
#include <stdio.h> // For SEEK_* defines, which we will use in Stream out of FORCE OF HABIT.
#include <string>
#include "octoshock.h"
class Stream
{
public:
Stream();
virtual ~Stream();
enum
{
ATTRIBUTE_READABLE = 1U << 0,
ATTRIBUTE_WRITEABLE = 1U << 1,
ATTRIBUTE_SEEKABLE = 1U << 2,
ATTRIBUTE_SLOW_SEEK = 1U << 3,
ATTRIBUTE_SLOW_SIZE = 1U << 4
};
virtual uint64 attributes(void) = 0;
virtual uint8 *map(void) = 0; // Map the entirety of the stream data into the address space of the process, if possible, and return a pointer.
// (the returned pointer must be cached, and returned on any subsequent calls to map() without an unmap()
// in-between, to facilitate a sort of "feature-testing", to determine if an alternative like "MemoryStream"
// should be used).
//
// If the mapping fails for whatever reason, return NULL rather than throwing an exception.
//
virtual void unmap(void) = 0; // Unmap the stream data from the address space. (Possibly invalidating the pointer returned from map()).
// (must automatically be called, if necessary, from the destructor).
//
// If the data can't be "unmapped" as such because it was never mmap()'d or similar in the first place(such as with MemoryStream),
// then this will be a nop.
virtual uint64 read(void *data, uint64 count, bool error_on_eos = true) = 0;
virtual void write(const void *data, uint64 count) = 0;
virtual void seek(int64 offset, int whence = SEEK_SET) = 0;
inline void rewind(void)
{
seek(0, SEEK_SET);
}
virtual int64 tell(void) = 0;
virtual int64 size(void) = 0;
virtual void close(void) = 0; // Flushes(in the case of writeable streams) and closes the stream.
// Necessary since this operation can fail(running out of disk space, for instance),
// and throw an exception in the destructor would be a Bad Idea(TM).
//
// Manually calling this function isn't strictly necessary, but recommended when the
// stream is writeable; it will be called automatically from the destructor, with any
// exceptions thrown caught and logged.
//
// Utility functions(TODO):
//
INLINE uint8 get_u8(void)
{
uint8 ret;
read(&ret, sizeof(ret));
return ret;
}
INLINE void put_u8(uint8 c)
{
write(&c, sizeof(c));
}
template<typename T>
INLINE T get_NE(void)
{
T ret;
read(&ret, sizeof(ret));
return ret;
}
template<typename T>
INLINE void put_NE(T c)
{
write(&c, sizeof(c));
}
template<typename T>
INLINE T get_RE(void)
{
uint8 tmp[sizeof(T)];
T ret = 0;
read(tmp, sizeof(tmp));
for(unsigned i = 0; i < sizeof(T); i++)
ret |= (T)tmp[i] << (i * 8);
return ret;
}
template<typename T>
INLINE void put_RE(T c)
{
uint8 tmp[sizeof(T)];
for(unsigned i = 0; i < sizeof(T); i++)
tmp[i] = ((uint8 *)&c)[sizeof(T) - 1 - i];
write(tmp, sizeof(tmp));
}
template<typename T>
INLINE T get_LE(void)
{
#ifdef LSB_FIRST
return get_NE<T>();
#else
return get_RE<T>();
#endif
}
template<typename T>
INLINE void put_LE(T c)
{
#ifdef LSB_FIRST
return put_NE<T>(c);
#else
return put_RE<T>(c);
#endif
}
template<typename T>
INLINE T get_BE(void)
{
#ifndef LSB_FIRST
return get_NE<T>();
#else
return get_RE<T>();
#endif
}
template<typename T>
INLINE void put_BE(T c)
{
#ifndef LSB_FIRST
return put_NE<T>(c);
#else
return put_RE<T>(c);
#endif
}
// Reads a line into "str", overwriting its contents; returns the line-end char('\n' or '\r' or '\0'), or 256 on EOF and
// data has been read into "str", and -1 on EOF when no data has been read into "str".
// The line-end char won't be added to "str".
// It's up to the caller to handle extraneous empty lines caused by DOS-format text lines(\r\n).
// ("str" is passed by reference for the possibility of improved performance by reusing alloced memory for the std::string, though part
// of it would be up to the STL implementation).
// Implemented as virtual so that a higher-performance version can be implemented if possible(IE with MemoryStream)
virtual int get_line(std::string &str);
virtual void put_line(const std::string& str);
virtual void print_format(const char *format, ...);
#if 0
int scanf(const char *format, ...) MDFN_FORMATSTR(gnu_scanf, 2, 3);
void put_string(const char *str);
void put_string(const std::string &str);
#endif
};
// StreamFilter takes ownership of the Stream pointer passed, and will delete it in its destructor.
class StreamFilter : public Stream
{
public:
StreamFilter();
StreamFilter(Stream *target_arg);
virtual ~StreamFilter();
virtual uint64 read(void *data, uint64 count, bool error_on_eos = true) = 0;
virtual void write(const void *data, uint64 count) = 0;
virtual void seek(int64 offset, int whence) = 0;
virtual int64 tell(void) = 0;
virtual int64 size(void) = 0;
virtual void close(void) = 0;
virtual Stream *steal(void);
private:
Stream *target_stream;
};
#endif

View File

@ -1,31 +0,0 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.5.33627.172
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "octoshock", "octoshock.vcxproj", "{8610A02C-7420-4237-89D3-31BBC9A459AD}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "miniclient", "..\test\miniclient\miniclient.vcxproj", "{5A0DAC84-1170-4B1A-B9A9-F566A1D97790}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{8610A02C-7420-4237-89D3-31BBC9A459AD}.Debug|x64.ActiveCfg = Debug|x64
{8610A02C-7420-4237-89D3-31BBC9A459AD}.Debug|x64.Build.0 = Debug|x64
{8610A02C-7420-4237-89D3-31BBC9A459AD}.Release|x64.ActiveCfg = Release|x64
{8610A02C-7420-4237-89D3-31BBC9A459AD}.Release|x64.Build.0 = Release|x64
{5A0DAC84-1170-4B1A-B9A9-F566A1D97790}.Debug|x64.ActiveCfg = Debug|x64
{5A0DAC84-1170-4B1A-B9A9-F566A1D97790}.Debug|x64.Build.0 = Debug|x64
{5A0DAC84-1170-4B1A-B9A9-F566A1D97790}.Release|x64.ActiveCfg = Release|x64
{5A0DAC84-1170-4B1A-B9A9-F566A1D97790}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {6A43C902-0FB5-4B9E-8E9F-D2417DCDFA5B}
EndGlobalSection
EndGlobal

View File

@ -1,169 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>17.0</VCProjectVersion>
<ProjectGuid>{8610A02C-7420-4237-89D3-31BBC9A459AD}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<AdditionalIncludeDirectories>..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>EW_EXPORT;WANT_LEC_CHECK;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<PostBuildEvent>
<Command>copy /Y "$(TargetDir)$(TargetName).dll" "$(SolutionDir)..\..\..\Assets\dll\$(TargetName).dll"
copy /Y "$(TargetDir)$(TargetName).dll" "$(SolutionDir)..\..\..\output\dll\$(TargetName).dll"</Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<AdditionalIncludeDirectories>..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>EW_EXPORT;WANT_LEC_CHECK;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<WholeProgramOptimization>true</WholeProgramOptimization>
</ClCompile>
<PostBuildEvent>
<Command>copy /Y "$(TargetDir)$(TargetName).dll" "$(SolutionDir)..\..\..\Assets\dll\$(TargetName).dll"
copy /Y "$(TargetDir)$(TargetName).dll" "$(SolutionDir)..\..\..\output\dll\$(TargetName).dll"</Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\cdrom\CDUtility.cpp" />
<ClCompile Include="..\cdrom\crc32.cpp" />
<ClCompile Include="..\cdrom\galois.cpp" />
<ClCompile Include="..\cdrom\l-ec.cpp" />
<ClCompile Include="..\cdrom\lec.cpp" />
<ClCompile Include="..\cdrom\recover-raw.cpp" />
<ClCompile Include="..\emuware\emuware.cpp" />
<ClCompile Include="..\emuware\EW_state.cpp" />
<ClCompile Include="..\endian.cpp" />
<ClCompile Include="..\error.cpp" />
<ClCompile Include="..\octoshock.cpp" />
<ClCompile Include="..\psx\cdc.cpp" />
<ClCompile Include="..\psx\cpu.cpp" />
<ClCompile Include="..\psx\dis.cpp" />
<ClCompile Include="..\psx\dma.cpp" />
<ClCompile Include="..\psx\frontio.cpp" />
<ClCompile Include="..\psx\gpu.cpp" />
<ClCompile Include="..\psx\gpu_line.cpp" />
<ClCompile Include="..\psx\gpu_polygon.cpp" />
<ClCompile Include="..\psx\gpu_sprite.cpp" />
<ClCompile Include="..\psx\gte.cpp" />
<ClCompile Include="..\psx\input\dualanalog.cpp" />
<ClCompile Include="..\psx\input\dualshock.cpp" />
<ClCompile Include="..\psx\input\gamepad.cpp" />
<ClCompile Include="..\psx\input\guncon.cpp" />
<ClCompile Include="..\psx\input\justifier.cpp" />
<ClCompile Include="..\psx\input\memcard.cpp" />
<ClCompile Include="..\psx\input\mouse.cpp" />
<ClCompile Include="..\psx\input\multitap.cpp" />
<ClCompile Include="..\psx\input\negcon.cpp" />
<ClCompile Include="..\psx\irq.cpp" />
<ClCompile Include="..\psx\mdec.cpp" />
<ClCompile Include="..\psx\psx.cpp" />
<ClCompile Include="..\psx\sio.cpp" />
<ClCompile Include="..\psx\spu.cpp" />
<ClCompile Include="..\psx\timer.cpp" />
<ClCompile Include="..\Stream.cpp" />
<ClCompile Include="..\tests.cpp" />
<ClCompile Include="..\video\convert.cpp" />
<ClCompile Include="..\video\Deinterlacer.cpp" />
<ClCompile Include="..\video\surface.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\cdrom\CDUtility.h" />
<ClInclude Include="..\cdrom\dvdisaster.h" />
<ClInclude Include="..\cdrom\galois-inlines.h" />
<ClInclude Include="..\cdrom\lec.h" />
<ClInclude Include="..\cdrom\SimpleFIFO.h" />
<ClInclude Include="..\emuware\emuware.h" />
<ClInclude Include="..\emuware\EW_state.h" />
<ClInclude Include="..\emuware\msvc\inttypes.h" />
<ClInclude Include="..\emuware\msvc\stdint.h" />
<ClInclude Include="..\endian.h" />
<ClInclude Include="..\error.h" />
<ClInclude Include="..\git.h" />
<ClInclude Include="..\math_ops.h" />
<ClInclude Include="..\octoshock.h" />
<ClInclude Include="..\psx\cdc.h" />
<ClInclude Include="..\psx\cpu.h" />
<ClInclude Include="..\psx\debug.h" />
<ClInclude Include="..\psx\dis.h" />
<ClInclude Include="..\psx\dma.h" />
<ClInclude Include="..\psx\FastFIFO.h" />
<ClInclude Include="..\psx\frontio.h" />
<ClInclude Include="..\psx\gpu.h" />
<ClInclude Include="..\psx\gte.h" />
<ClInclude Include="..\psx\input\dualanalog.h" />
<ClInclude Include="..\psx\input\dualshock.h" />
<ClInclude Include="..\psx\input\gamepad.h" />
<ClInclude Include="..\psx\input\guncon.h" />
<ClInclude Include="..\psx\input\justifier.h" />
<ClInclude Include="..\psx\input\memcard.h" />
<ClInclude Include="..\psx\input\mouse.h" />
<ClInclude Include="..\psx\input\multitap.h" />
<ClInclude Include="..\psx\input\negcon.h" />
<ClInclude Include="..\psx\irq.h" />
<ClInclude Include="..\psx\masmem.h" />
<ClInclude Include="..\psx\mdec.h" />
<ClInclude Include="..\psx\psx.h" />
<ClInclude Include="..\psx\sio.h" />
<ClInclude Include="..\psx\spu.h" />
<ClInclude Include="..\psx\timer.h" />
<ClInclude Include="..\Stream.h" />
<ClInclude Include="..\tests.h" />
<ClInclude Include="..\video.h" />
<ClInclude Include="..\video\convert.h" />
<ClInclude Include="..\video\Deinterlacer.h" />
<ClInclude Include="..\video\surface.h" />
</ItemGroup>
<ItemGroup>
<None Include="..\psx\gpu_common.inc" />
<None Include="..\psx\spu_fir_table.inc" />
<None Include="..\psx\spu_reverb.inc" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -1,269 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="psx">
<UniqueIdentifier>{00f73db4-1182-4bf7-b891-66bf860d3742}</UniqueIdentifier>
</Filter>
<Filter Include="emuware">
<UniqueIdentifier>{f69cc8f2-7480-44d6-9a32-9dca789d2bf6}</UniqueIdentifier>
</Filter>
<Filter Include="cdrom">
<UniqueIdentifier>{57a8e6ec-9225-410d-b38f-ba209abae070}</UniqueIdentifier>
</Filter>
<Filter Include="psx\input">
<UniqueIdentifier>{76abb796-5411-4d33-b3e0-f1f3873f138e}</UniqueIdentifier>
</Filter>
<Filter Include="emuware\msvc">
<UniqueIdentifier>{cb700979-4dce-4b10-8521-3ab71a313271}</UniqueIdentifier>
</Filter>
<Filter Include="video">
<UniqueIdentifier>{d1f71901-17a5-441a-8b4f-f7da34a057c1}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\psx\cdc.cpp">
<Filter>psx</Filter>
</ClCompile>
<ClCompile Include="..\psx\psx.cpp">
<Filter>psx</Filter>
</ClCompile>
<ClCompile Include="..\psx\dis.cpp">
<Filter>psx</Filter>
</ClCompile>
<ClCompile Include="..\psx\gte.cpp">
<Filter>psx</Filter>
</ClCompile>
<ClCompile Include="..\psx\spu.cpp">
<Filter>psx</Filter>
</ClCompile>
<ClCompile Include="..\Stream.cpp" />
<ClCompile Include="..\psx\frontio.cpp">
<Filter>psx</Filter>
</ClCompile>
<ClCompile Include="..\psx\cpu.cpp">
<Filter>psx</Filter>
</ClCompile>
<ClCompile Include="..\psx\dma.cpp">
<Filter>psx</Filter>
</ClCompile>
<ClCompile Include="..\psx\irq.cpp">
<Filter>psx</Filter>
</ClCompile>
<ClCompile Include="..\psx\mdec.cpp">
<Filter>psx</Filter>
</ClCompile>
<ClCompile Include="..\psx\sio.cpp">
<Filter>psx</Filter>
</ClCompile>
<ClCompile Include="..\psx\timer.cpp">
<Filter>psx</Filter>
</ClCompile>
<ClCompile Include="..\endian.cpp" />
<ClCompile Include="..\psx\input\dualshock.cpp">
<Filter>psx\input</Filter>
</ClCompile>
<ClCompile Include="..\psx\input\gamepad.cpp">
<Filter>psx\input</Filter>
</ClCompile>
<ClCompile Include="..\psx\input\guncon.cpp">
<Filter>psx\input</Filter>
</ClCompile>
<ClCompile Include="..\psx\input\justifier.cpp">
<Filter>psx\input</Filter>
</ClCompile>
<ClCompile Include="..\psx\input\memcard.cpp">
<Filter>psx\input</Filter>
</ClCompile>
<ClCompile Include="..\psx\input\mouse.cpp">
<Filter>psx\input</Filter>
</ClCompile>
<ClCompile Include="..\psx\input\multitap.cpp">
<Filter>psx\input</Filter>
</ClCompile>
<ClCompile Include="..\psx\input\negcon.cpp">
<Filter>psx\input</Filter>
</ClCompile>
<ClCompile Include="..\psx\input\dualanalog.cpp">
<Filter>psx\input</Filter>
</ClCompile>
<ClCompile Include="..\octoshock.cpp" />
<ClCompile Include="..\emuware\emuware.cpp">
<Filter>emuware</Filter>
</ClCompile>
<ClCompile Include="..\video\surface.cpp">
<Filter>video</Filter>
</ClCompile>
<ClCompile Include="..\video\Deinterlacer.cpp">
<Filter>video</Filter>
</ClCompile>
<ClCompile Include="..\video\convert.cpp">
<Filter>video</Filter>
</ClCompile>
<ClCompile Include="..\emuware\EW_state.cpp">
<Filter>emuware</Filter>
</ClCompile>
<ClCompile Include="..\psx\gpu.cpp">
<Filter>psx</Filter>
</ClCompile>
<ClCompile Include="..\psx\gpu_line.cpp">
<Filter>psx</Filter>
</ClCompile>
<ClCompile Include="..\psx\gpu_polygon.cpp">
<Filter>psx</Filter>
</ClCompile>
<ClCompile Include="..\psx\gpu_sprite.cpp">
<Filter>psx</Filter>
</ClCompile>
<ClCompile Include="..\cdrom\CDUtility.cpp">
<Filter>cdrom</Filter>
</ClCompile>
<ClCompile Include="..\tests.cpp" />
<ClCompile Include="..\cdrom\lec.cpp">
<Filter>cdrom</Filter>
</ClCompile>
<ClCompile Include="..\cdrom\l-ec.cpp">
<Filter>cdrom</Filter>
</ClCompile>
<ClCompile Include="..\cdrom\recover-raw.cpp">
<Filter>cdrom</Filter>
</ClCompile>
<ClCompile Include="..\cdrom\galois.cpp">
<Filter>cdrom</Filter>
</ClCompile>
<ClCompile Include="..\cdrom\crc32.cpp">
<Filter>cdrom</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\psx\cdc.h">
<Filter>psx</Filter>
</ClInclude>
<ClInclude Include="..\psx\psx.h">
<Filter>psx</Filter>
</ClInclude>
<ClInclude Include="..\emuware\emuware.h">
<Filter>emuware</Filter>
</ClInclude>
<ClInclude Include="..\psx\dis.h">
<Filter>psx</Filter>
</ClInclude>
<ClInclude Include="..\psx\gte.h">
<Filter>psx</Filter>
</ClInclude>
<ClInclude Include="..\math_ops.h" />
<ClInclude Include="..\git.h" />
<ClInclude Include="..\octoshock.h" />
<ClInclude Include="..\psx\spu.h">
<Filter>psx</Filter>
</ClInclude>
<ClInclude Include="..\endian.h" />
<ClInclude Include="..\Stream.h" />
<ClInclude Include="..\error.h" />
<ClInclude Include="..\psx\frontio.h">
<Filter>psx</Filter>
</ClInclude>
<ClInclude Include="..\psx\cpu.h">
<Filter>psx</Filter>
</ClInclude>
<ClInclude Include="..\psx\dma.h">
<Filter>psx</Filter>
</ClInclude>
<ClInclude Include="..\psx\irq.h">
<Filter>psx</Filter>
</ClInclude>
<ClInclude Include="..\psx\mdec.h">
<Filter>psx</Filter>
</ClInclude>
<ClInclude Include="..\psx\sio.h">
<Filter>psx</Filter>
</ClInclude>
<ClInclude Include="..\psx\timer.h">
<Filter>psx</Filter>
</ClInclude>
<ClInclude Include="..\psx\input\dualanalog.h">
<Filter>psx\input</Filter>
</ClInclude>
<ClInclude Include="..\psx\input\dualshock.h">
<Filter>psx\input</Filter>
</ClInclude>
<ClInclude Include="..\psx\input\gamepad.h">
<Filter>psx\input</Filter>
</ClInclude>
<ClInclude Include="..\psx\input\guncon.h">
<Filter>psx\input</Filter>
</ClInclude>
<ClInclude Include="..\psx\input\justifier.h">
<Filter>psx\input</Filter>
</ClInclude>
<ClInclude Include="..\psx\input\memcard.h">
<Filter>psx\input</Filter>
</ClInclude>
<ClInclude Include="..\psx\input\mouse.h">
<Filter>psx\input</Filter>
</ClInclude>
<ClInclude Include="..\psx\input\multitap.h">
<Filter>psx\input</Filter>
</ClInclude>
<ClInclude Include="..\psx\input\negcon.h">
<Filter>psx\input</Filter>
</ClInclude>
<ClInclude Include="..\emuware\msvc\inttypes.h">
<Filter>emuware\msvc</Filter>
</ClInclude>
<ClInclude Include="..\emuware\msvc\stdint.h">
<Filter>emuware\msvc</Filter>
</ClInclude>
<ClInclude Include="..\video\surface.h">
<Filter>video</Filter>
</ClInclude>
<ClInclude Include="..\video\Deinterlacer.h">
<Filter>video</Filter>
</ClInclude>
<ClInclude Include="..\video\convert.h">
<Filter>video</Filter>
</ClInclude>
<ClInclude Include="..\emuware\EW_state.h">
<Filter>emuware</Filter>
</ClInclude>
<ClInclude Include="..\cdrom\SimpleFIFO.h">
<Filter>cdrom</Filter>
</ClInclude>
<ClInclude Include="..\psx\gpu.h">
<Filter>psx</Filter>
</ClInclude>
<ClInclude Include="..\psx\masmem.h">
<Filter>psx</Filter>
</ClInclude>
<ClInclude Include="..\cdrom\CDUtility.h">
<Filter>cdrom</Filter>
</ClInclude>
<ClInclude Include="..\cdrom\dvdisaster.h">
<Filter>cdrom</Filter>
</ClInclude>
<ClInclude Include="..\cdrom\galois-inlines.h">
<Filter>cdrom</Filter>
</ClInclude>
<ClInclude Include="..\cdrom\lec.h">
<Filter>cdrom</Filter>
</ClInclude>
<ClInclude Include="..\psx\debug.h">
<Filter>psx</Filter>
</ClInclude>
<ClInclude Include="..\psx\FastFIFO.h">
<Filter>psx</Filter>
</ClInclude>
<ClInclude Include="..\tests.h" />
<ClInclude Include="..\video.h" />
</ItemGroup>
<ItemGroup>
<None Include="..\psx\spu_fir_table.inc">
<Filter>psx</Filter>
</None>
<None Include="..\psx\spu_reverb.inc">
<Filter>psx</Filter>
</None>
<None Include="..\psx\gpu_common.inc">
<Filter>psx</Filter>
</None>
</ItemGroup>
</Project>

View File

@ -1,629 +0,0 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
9E11BE571A41204F00CC7F6B /* CDUtility.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9E11BDEB1A41204F00CC7F6B /* CDUtility.cpp */; };
9E11BE581A41204F00CC7F6B /* CDUtility.h in Headers */ = {isa = PBXBuildFile; fileRef = 9E11BDEC1A41204F00CC7F6B /* CDUtility.h */; };
9E11BE591A41204F00CC7F6B /* crc32.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9E11BDED1A41204F00CC7F6B /* crc32.cpp */; };
9E11BE5C1A41204F00CC7F6B /* galois.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9E11BDF01A41204F00CC7F6B /* galois.cpp */; };
9E11BE5D1A41204F00CC7F6B /* l-ec.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9E11BDF11A41204F00CC7F6B /* l-ec.cpp */; };
9E11BE5E1A41204F00CC7F6B /* lec.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9E11BDF21A41204F00CC7F6B /* lec.cpp */; };
9E11BE5F1A41204F00CC7F6B /* lec.h in Headers */ = {isa = PBXBuildFile; fileRef = 9E11BDF31A41204F00CC7F6B /* lec.h */; };
9E11BE601A41204F00CC7F6B /* recover-raw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9E11BDF41A41204F00CC7F6B /* recover-raw.cpp */; };
9E11BE631A41204F00CC7F6B /* emuware.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9E11BDF81A41204F00CC7F6B /* emuware.cpp */; };
9E11BE641A41204F00CC7F6B /* emuware.h in Headers */ = {isa = PBXBuildFile; fileRef = 9E11BDF91A41204F00CC7F6B /* emuware.h */; };
9E11BE651A41204F00CC7F6B /* EW_state.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9E11BDFA1A41204F00CC7F6B /* EW_state.cpp */; };
9E11BE661A41204F00CC7F6B /* EW_state.h in Headers */ = {isa = PBXBuildFile; fileRef = 9E11BDFB1A41204F00CC7F6B /* EW_state.h */; };
9E11BE691A41204F00CC7F6B /* PACKED.h in Headers */ = {isa = PBXBuildFile; fileRef = 9E11BE001A41204F00CC7F6B /* PACKED.h */; };
9E11BE6A1A41204F00CC7F6B /* PACKED_END.h in Headers */ = {isa = PBXBuildFile; fileRef = 9E11BE011A41204F00CC7F6B /* PACKED_END.h */; };
9E11BE6B1A41204F00CC7F6B /* endian.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9E11BE021A41204F00CC7F6B /* endian.cpp */; };
9E11BE6C1A41204F00CC7F6B /* endian.h in Headers */ = {isa = PBXBuildFile; fileRef = 9E11BE031A41204F00CC7F6B /* endian.h */; };
9E11BE6D1A41204F00CC7F6B /* error.h in Headers */ = {isa = PBXBuildFile; fileRef = 9E11BE041A41204F00CC7F6B /* error.h */; };
9E11BE741A41204F00CC7F6B /* git.h in Headers */ = {isa = PBXBuildFile; fileRef = 9E11BE0B1A41204F00CC7F6B /* git.h */; };
9E11BE751A41204F00CC7F6B /* math_ops.h in Headers */ = {isa = PBXBuildFile; fileRef = 9E11BE0C1A41204F00CC7F6B /* math_ops.h */; };
9E11BE761A41204F00CC7F6B /* octoshock.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9E11BE0D1A41204F00CC7F6B /* octoshock.cpp */; };
9E11BE771A41204F00CC7F6B /* octoshock.h in Headers */ = {isa = PBXBuildFile; fileRef = 9E11BE0E1A41204F00CC7F6B /* octoshock.h */; };
9E11BE781A41204F00CC7F6B /* cdc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9E11BE101A41204F00CC7F6B /* cdc.cpp */; };
9E11BE791A41204F00CC7F6B /* cdc.h in Headers */ = {isa = PBXBuildFile; fileRef = 9E11BE111A41204F00CC7F6B /* cdc.h */; };
9E11BE7A1A41204F00CC7F6B /* cpu.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9E11BE121A41204F00CC7F6B /* cpu.cpp */; };
9E11BE7B1A41204F00CC7F6B /* cpu.h in Headers */ = {isa = PBXBuildFile; fileRef = 9E11BE131A41204F00CC7F6B /* cpu.h */; };
9E11BE7C1A41204F00CC7F6B /* cpu_bigswitch.inc in Sources */ = {isa = PBXBuildFile; fileRef = 9E11BE141A41204F00CC7F6B /* cpu_bigswitch.inc */; };
9E11BE7D1A41204F00CC7F6B /* cpu_computedgoto.inc in Sources */ = {isa = PBXBuildFile; fileRef = 9E11BE151A41204F00CC7F6B /* cpu_computedgoto.inc */; };
9E11BE801A41204F00CC7F6B /* dis.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9E11BE181A41204F00CC7F6B /* dis.cpp */; };
9E11BE811A41204F00CC7F6B /* dis.h in Headers */ = {isa = PBXBuildFile; fileRef = 9E11BE191A41204F00CC7F6B /* dis.h */; };
9E11BE821A41204F00CC7F6B /* dma.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9E11BE1A1A41204F00CC7F6B /* dma.cpp */; };
9E11BE831A41204F00CC7F6B /* dma.h in Headers */ = {isa = PBXBuildFile; fileRef = 9E11BE1B1A41204F00CC7F6B /* dma.h */; };
9E11BE841A41204F00CC7F6B /* frontio.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9E11BE1C1A41204F00CC7F6B /* frontio.cpp */; };
9E11BE851A41204F00CC7F6B /* frontio.h in Headers */ = {isa = PBXBuildFile; fileRef = 9E11BE1D1A41204F00CC7F6B /* frontio.h */; };
9E11BE861A41204F00CC7F6B /* gpu.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9E11BE1E1A41204F00CC7F6B /* gpu.cpp */; };
9E11BE871A41204F00CC7F6B /* gpu.h in Headers */ = {isa = PBXBuildFile; fileRef = 9E11BE1F1A41204F00CC7F6B /* gpu.h */; };
9E11BE881A41204F00CC7F6B /* gpu_common.inc in Sources */ = {isa = PBXBuildFile; fileRef = 9E11BE201A41204F00CC7F6B /* gpu_common.inc */; };
9E11BE891A41204F00CC7F6B /* gpu_line.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9E11BE211A41204F00CC7F6B /* gpu_line.cpp */; };
9E11BE8A1A41204F00CC7F6B /* gpu_polygon.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9E11BE221A41204F00CC7F6B /* gpu_polygon.cpp */; };
9E11BE8B1A41204F00CC7F6B /* gpu_sprite.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9E11BE231A41204F00CC7F6B /* gpu_sprite.cpp */; };
9E11BE8C1A41204F00CC7F6B /* gte.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9E11BE241A41204F00CC7F6B /* gte.cpp */; };
9E11BE8D1A41204F00CC7F6B /* gte.h in Headers */ = {isa = PBXBuildFile; fileRef = 9E11BE251A41204F00CC7F6B /* gte.h */; };
9E11BE8E1A41204F00CC7F6B /* dualanalog.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9E11BE271A41204F00CC7F6B /* dualanalog.cpp */; };
9E11BE8F1A41204F00CC7F6B /* dualanalog.h in Headers */ = {isa = PBXBuildFile; fileRef = 9E11BE281A41204F00CC7F6B /* dualanalog.h */; };
9E11BE901A41204F00CC7F6B /* dualshock.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9E11BE291A41204F00CC7F6B /* dualshock.cpp */; };
9E11BE911A41204F00CC7F6B /* dualshock.h in Headers */ = {isa = PBXBuildFile; fileRef = 9E11BE2A1A41204F00CC7F6B /* dualshock.h */; };
9E11BE921A41204F00CC7F6B /* gamepad.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9E11BE2B1A41204F00CC7F6B /* gamepad.cpp */; };
9E11BE931A41204F00CC7F6B /* gamepad.h in Headers */ = {isa = PBXBuildFile; fileRef = 9E11BE2C1A41204F00CC7F6B /* gamepad.h */; };
9E11BE941A41204F00CC7F6B /* guncon.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9E11BE2D1A41204F00CC7F6B /* guncon.cpp */; };
9E11BE951A41204F00CC7F6B /* guncon.h in Headers */ = {isa = PBXBuildFile; fileRef = 9E11BE2E1A41204F00CC7F6B /* guncon.h */; };
9E11BE961A41204F00CC7F6B /* justifier.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9E11BE2F1A41204F00CC7F6B /* justifier.cpp */; };
9E11BE971A41204F00CC7F6B /* justifier.h in Headers */ = {isa = PBXBuildFile; fileRef = 9E11BE301A41204F00CC7F6B /* justifier.h */; };
9E11BE981A41204F00CC7F6B /* memcard.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9E11BE311A41204F00CC7F6B /* memcard.cpp */; };
9E11BE991A41204F00CC7F6B /* memcard.h in Headers */ = {isa = PBXBuildFile; fileRef = 9E11BE321A41204F00CC7F6B /* memcard.h */; };
9E11BE9A1A41204F00CC7F6B /* mouse.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9E11BE331A41204F00CC7F6B /* mouse.cpp */; };
9E11BE9B1A41204F00CC7F6B /* mouse.h in Headers */ = {isa = PBXBuildFile; fileRef = 9E11BE341A41204F00CC7F6B /* mouse.h */; };
9E11BE9C1A41204F00CC7F6B /* multitap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9E11BE351A41204F00CC7F6B /* multitap.cpp */; };
9E11BE9D1A41204F00CC7F6B /* multitap.h in Headers */ = {isa = PBXBuildFile; fileRef = 9E11BE361A41204F00CC7F6B /* multitap.h */; };
9E11BE9E1A41204F00CC7F6B /* negcon.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9E11BE371A41204F00CC7F6B /* negcon.cpp */; };
9E11BE9F1A41204F00CC7F6B /* negcon.h in Headers */ = {isa = PBXBuildFile; fileRef = 9E11BE381A41204F00CC7F6B /* negcon.h */; };
9E11BEA01A41204F00CC7F6B /* irq.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9E11BE391A41204F00CC7F6B /* irq.cpp */; };
9E11BEA11A41204F00CC7F6B /* irq.h in Headers */ = {isa = PBXBuildFile; fileRef = 9E11BE3A1A41204F00CC7F6B /* irq.h */; };
9E11BEA21A41204F00CC7F6B /* masmem.h in Headers */ = {isa = PBXBuildFile; fileRef = 9E11BE3D1A41204F00CC7F6B /* masmem.h */; };
9E11BEA31A41204F00CC7F6B /* mdec.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9E11BE3E1A41204F00CC7F6B /* mdec.cpp */; };
9E11BEA41A41204F00CC7F6B /* mdec.h in Headers */ = {isa = PBXBuildFile; fileRef = 9E11BE3F1A41204F00CC7F6B /* mdec.h */; };
9E11BEA51A41204F00CC7F6B /* psx.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9E11BE401A41204F00CC7F6B /* psx.cpp */; };
9E11BEA61A41204F00CC7F6B /* psx.h in Headers */ = {isa = PBXBuildFile; fileRef = 9E11BE411A41204F00CC7F6B /* psx.h */; };
9E11BEA71A41204F00CC7F6B /* sio.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9E11BE421A41204F00CC7F6B /* sio.cpp */; };
9E11BEA81A41204F00CC7F6B /* sio.h in Headers */ = {isa = PBXBuildFile; fileRef = 9E11BE431A41204F00CC7F6B /* sio.h */; };
9E11BEA91A41204F00CC7F6B /* spu.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9E11BE441A41204F00CC7F6B /* spu.cpp */; };
9E11BEAA1A41204F00CC7F6B /* spu.h in Headers */ = {isa = PBXBuildFile; fileRef = 9E11BE451A41204F00CC7F6B /* spu.h */; };
9E11BEAB1A41204F00CC7F6B /* spu_fir_table.inc in Sources */ = {isa = PBXBuildFile; fileRef = 9E11BE461A41204F00CC7F6B /* spu_fir_table.inc */; };
9E11BEAC1A41204F00CC7F6B /* spu_reverb.inc in Sources */ = {isa = PBXBuildFile; fileRef = 9E11BE471A41204F00CC7F6B /* spu_reverb.inc */; };
9E11BEAD1A41204F00CC7F6B /* timer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9E11BE481A41204F00CC7F6B /* timer.cpp */; };
9E11BEAE1A41204F00CC7F6B /* timer.h in Headers */ = {isa = PBXBuildFile; fileRef = 9E11BE491A41204F00CC7F6B /* timer.h */; };
9E11BEAF1A41204F00CC7F6B /* Stream.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9E11BE4A1A41204F00CC7F6B /* Stream.cpp */; };
9E11BEB01A41204F00CC7F6B /* Stream.h in Headers */ = {isa = PBXBuildFile; fileRef = 9E11BE4B1A41204F00CC7F6B /* Stream.h */; };
9E11BEB11A41204F00CC7F6B /* Deinterlacer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9E11BE4D1A41204F00CC7F6B /* Deinterlacer.cpp */; };
9E11BEB21A41204F00CC7F6B /* Deinterlacer.h in Headers */ = {isa = PBXBuildFile; fileRef = 9E11BE4E1A41204F00CC7F6B /* Deinterlacer.h */; };
9E11BEB31A41204F00CC7F6B /* surface.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9E11BE4F1A41204F00CC7F6B /* surface.cpp */; };
9E11BEB41A41204F00CC7F6B /* surface.h in Headers */ = {isa = PBXBuildFile; fileRef = 9E11BE501A41204F00CC7F6B /* surface.h */; };
9E11BEB81A41213D00CC7F6B /* dvdisaster.h in Headers */ = {isa = PBXBuildFile; fileRef = 9E11BEB71A41213D00CC7F6B /* dvdisaster.h */; };
9E11BEBA1A41215900CC7F6B /* SimpleFIFO.h in Headers */ = {isa = PBXBuildFile; fileRef = 9E11BEB91A41215900CC7F6B /* SimpleFIFO.h */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
9E11BDDF1A411DA300CC7F6B /* liboctoshock.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = liboctoshock.dylib; sourceTree = BUILT_PRODUCTS_DIR; };
9E11BDEB1A41204F00CC7F6B /* CDUtility.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CDUtility.cpp; sourceTree = "<group>"; };
9E11BDEC1A41204F00CC7F6B /* CDUtility.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDUtility.h; sourceTree = "<group>"; };
9E11BDED1A41204F00CC7F6B /* crc32.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = crc32.cpp; sourceTree = "<group>"; };
9E11BDF01A41204F00CC7F6B /* galois.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = galois.cpp; sourceTree = "<group>"; };
9E11BDF11A41204F00CC7F6B /* l-ec.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "l-ec.cpp"; sourceTree = "<group>"; };
9E11BDF21A41204F00CC7F6B /* lec.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = lec.cpp; sourceTree = "<group>"; };
9E11BDF31A41204F00CC7F6B /* lec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = lec.h; sourceTree = "<group>"; };
9E11BDF41A41204F00CC7F6B /* recover-raw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "recover-raw.cpp"; sourceTree = "<group>"; };
9E11BDF81A41204F00CC7F6B /* emuware.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = emuware.cpp; sourceTree = "<group>"; };
9E11BDF91A41204F00CC7F6B /* emuware.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = emuware.h; sourceTree = "<group>"; };
9E11BDFA1A41204F00CC7F6B /* EW_state.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = EW_state.cpp; sourceTree = "<group>"; };
9E11BDFB1A41204F00CC7F6B /* EW_state.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EW_state.h; sourceTree = "<group>"; };
9E11BE001A41204F00CC7F6B /* PACKED.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PACKED.h; sourceTree = "<group>"; };
9E11BE011A41204F00CC7F6B /* PACKED_END.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PACKED_END.h; sourceTree = "<group>"; };
9E11BE021A41204F00CC7F6B /* endian.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = endian.cpp; path = ../endian.cpp; sourceTree = "<group>"; };
9E11BE031A41204F00CC7F6B /* endian.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = endian.h; path = ../endian.h; sourceTree = "<group>"; };
9E11BE041A41204F00CC7F6B /* error.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = error.h; path = ../error.h; sourceTree = "<group>"; };
9E11BE0B1A41204F00CC7F6B /* git.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = git.h; path = ../git.h; sourceTree = "<group>"; };
9E11BE0C1A41204F00CC7F6B /* math_ops.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = math_ops.h; path = ../math_ops.h; sourceTree = "<group>"; };
9E11BE0D1A41204F00CC7F6B /* octoshock.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = octoshock.cpp; path = ../octoshock.cpp; sourceTree = "<group>"; };
9E11BE0E1A41204F00CC7F6B /* octoshock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = octoshock.h; path = ../octoshock.h; sourceTree = "<group>"; };
9E11BE101A41204F00CC7F6B /* cdc.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = cdc.cpp; sourceTree = "<group>"; };
9E11BE111A41204F00CC7F6B /* cdc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cdc.h; sourceTree = "<group>"; };
9E11BE121A41204F00CC7F6B /* cpu.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = cpu.cpp; sourceTree = "<group>"; };
9E11BE131A41204F00CC7F6B /* cpu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cpu.h; sourceTree = "<group>"; };
9E11BE141A41204F00CC7F6B /* cpu_bigswitch.inc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.pascal; path = cpu_bigswitch.inc; sourceTree = "<group>"; };
9E11BE151A41204F00CC7F6B /* cpu_computedgoto.inc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.pascal; path = cpu_computedgoto.inc; sourceTree = "<group>"; };
9E11BE181A41204F00CC7F6B /* dis.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = dis.cpp; sourceTree = "<group>"; };
9E11BE191A41204F00CC7F6B /* dis.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dis.h; sourceTree = "<group>"; };
9E11BE1A1A41204F00CC7F6B /* dma.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = dma.cpp; sourceTree = "<group>"; };
9E11BE1B1A41204F00CC7F6B /* dma.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dma.h; sourceTree = "<group>"; };
9E11BE1C1A41204F00CC7F6B /* frontio.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = frontio.cpp; sourceTree = "<group>"; };
9E11BE1D1A41204F00CC7F6B /* frontio.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = frontio.h; sourceTree = "<group>"; };
9E11BE1E1A41204F00CC7F6B /* gpu.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = gpu.cpp; sourceTree = "<group>"; };
9E11BE1F1A41204F00CC7F6B /* gpu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = gpu.h; sourceTree = "<group>"; };
9E11BE201A41204F00CC7F6B /* gpu_common.inc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.pascal; path = gpu_common.inc; sourceTree = "<group>"; };
9E11BE211A41204F00CC7F6B /* gpu_line.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = gpu_line.cpp; sourceTree = "<group>"; };
9E11BE221A41204F00CC7F6B /* gpu_polygon.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = gpu_polygon.cpp; sourceTree = "<group>"; };
9E11BE231A41204F00CC7F6B /* gpu_sprite.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = gpu_sprite.cpp; sourceTree = "<group>"; };
9E11BE241A41204F00CC7F6B /* gte.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = gte.cpp; sourceTree = "<group>"; };
9E11BE251A41204F00CC7F6B /* gte.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = gte.h; sourceTree = "<group>"; };
9E11BE271A41204F00CC7F6B /* dualanalog.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = dualanalog.cpp; sourceTree = "<group>"; };
9E11BE281A41204F00CC7F6B /* dualanalog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dualanalog.h; sourceTree = "<group>"; };
9E11BE291A41204F00CC7F6B /* dualshock.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = dualshock.cpp; sourceTree = "<group>"; };
9E11BE2A1A41204F00CC7F6B /* dualshock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dualshock.h; sourceTree = "<group>"; };
9E11BE2B1A41204F00CC7F6B /* gamepad.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = gamepad.cpp; sourceTree = "<group>"; };
9E11BE2C1A41204F00CC7F6B /* gamepad.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = gamepad.h; sourceTree = "<group>"; };
9E11BE2D1A41204F00CC7F6B /* guncon.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = guncon.cpp; sourceTree = "<group>"; };
9E11BE2E1A41204F00CC7F6B /* guncon.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = guncon.h; sourceTree = "<group>"; };
9E11BE2F1A41204F00CC7F6B /* justifier.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = justifier.cpp; sourceTree = "<group>"; };
9E11BE301A41204F00CC7F6B /* justifier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = justifier.h; sourceTree = "<group>"; };
9E11BE311A41204F00CC7F6B /* memcard.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = memcard.cpp; sourceTree = "<group>"; };
9E11BE321A41204F00CC7F6B /* memcard.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = memcard.h; sourceTree = "<group>"; };
9E11BE331A41204F00CC7F6B /* mouse.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = mouse.cpp; sourceTree = "<group>"; };
9E11BE341A41204F00CC7F6B /* mouse.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mouse.h; sourceTree = "<group>"; };
9E11BE351A41204F00CC7F6B /* multitap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = multitap.cpp; sourceTree = "<group>"; };
9E11BE361A41204F00CC7F6B /* multitap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = multitap.h; sourceTree = "<group>"; };
9E11BE371A41204F00CC7F6B /* negcon.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = negcon.cpp; sourceTree = "<group>"; };
9E11BE381A41204F00CC7F6B /* negcon.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = negcon.h; sourceTree = "<group>"; };
9E11BE391A41204F00CC7F6B /* irq.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = irq.cpp; sourceTree = "<group>"; };
9E11BE3A1A41204F00CC7F6B /* irq.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = irq.h; sourceTree = "<group>"; };
9E11BE3D1A41204F00CC7F6B /* masmem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = masmem.h; sourceTree = "<group>"; };
9E11BE3E1A41204F00CC7F6B /* mdec.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = mdec.cpp; sourceTree = "<group>"; };
9E11BE3F1A41204F00CC7F6B /* mdec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mdec.h; sourceTree = "<group>"; };
9E11BE401A41204F00CC7F6B /* psx.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = psx.cpp; sourceTree = "<group>"; };
9E11BE411A41204F00CC7F6B /* psx.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = psx.h; sourceTree = "<group>"; };
9E11BE421A41204F00CC7F6B /* sio.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = sio.cpp; sourceTree = "<group>"; };
9E11BE431A41204F00CC7F6B /* sio.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sio.h; sourceTree = "<group>"; };
9E11BE441A41204F00CC7F6B /* spu.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = spu.cpp; sourceTree = "<group>"; };
9E11BE451A41204F00CC7F6B /* spu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = spu.h; sourceTree = "<group>"; };
9E11BE461A41204F00CC7F6B /* spu_fir_table.inc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.pascal; path = spu_fir_table.inc; sourceTree = "<group>"; };
9E11BE471A41204F00CC7F6B /* spu_reverb.inc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.pascal; path = spu_reverb.inc; sourceTree = "<group>"; };
9E11BE481A41204F00CC7F6B /* timer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = timer.cpp; sourceTree = "<group>"; };
9E11BE491A41204F00CC7F6B /* timer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = timer.h; sourceTree = "<group>"; };
9E11BE4A1A41204F00CC7F6B /* Stream.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Stream.cpp; path = ../Stream.cpp; sourceTree = "<group>"; };
9E11BE4B1A41204F00CC7F6B /* Stream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Stream.h; path = ../Stream.h; sourceTree = "<group>"; };
9E11BE4D1A41204F00CC7F6B /* Deinterlacer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Deinterlacer.cpp; sourceTree = "<group>"; };
9E11BE4E1A41204F00CC7F6B /* Deinterlacer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Deinterlacer.h; sourceTree = "<group>"; };
9E11BE4F1A41204F00CC7F6B /* surface.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = surface.cpp; sourceTree = "<group>"; };
9E11BE501A41204F00CC7F6B /* surface.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = surface.h; sourceTree = "<group>"; };
9E11BEB71A41213D00CC7F6B /* dvdisaster.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dvdisaster.h; sourceTree = "<group>"; };
9E11BEB91A41215900CC7F6B /* SimpleFIFO.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SimpleFIFO.h; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
9E11BDDC1A411DA300CC7F6B /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
9E11BDD61A411DA300CC7F6B = {
isa = PBXGroup;
children = (
9E11BDE61A41204F00CC7F6B /* cdrom */,
9E11BDF71A41204F00CC7F6B /* emuware */,
9E11BE021A41204F00CC7F6B /* endian.cpp */,
9E11BE031A41204F00CC7F6B /* endian.h */,
9E11BE041A41204F00CC7F6B /* error.h */,
9E11BE0B1A41204F00CC7F6B /* git.h */,
9E11BE0C1A41204F00CC7F6B /* math_ops.h */,
9E11BE0D1A41204F00CC7F6B /* octoshock.cpp */,
9E11BE0E1A41204F00CC7F6B /* octoshock.h */,
9E11BE0F1A41204F00CC7F6B /* psx */,
9E11BE4A1A41204F00CC7F6B /* Stream.cpp */,
9E11BE4B1A41204F00CC7F6B /* Stream.h */,
9E11BE4C1A41204F00CC7F6B /* video */,
9E11BDE01A411DA300CC7F6B /* Products */,
);
sourceTree = "<group>";
};
9E11BDE01A411DA300CC7F6B /* Products */ = {
isa = PBXGroup;
children = (
9E11BDDF1A411DA300CC7F6B /* liboctoshock.dylib */,
);
name = Products;
sourceTree = "<group>";
};
9E11BDE61A41204F00CC7F6B /* cdrom */ = {
isa = PBXGroup;
children = (
9E11BEB91A41215900CC7F6B /* SimpleFIFO.h */,
9E11BDEC1A41204F00CC7F6B /* CDUtility.h */,
9E11BEB71A41213D00CC7F6B /* dvdisaster.h */,
9E11BDEB1A41204F00CC7F6B /* CDUtility.cpp */,
9E11BDED1A41204F00CC7F6B /* crc32.cpp */,
9E11BDF01A41204F00CC7F6B /* galois.cpp */,
9E11BDF11A41204F00CC7F6B /* l-ec.cpp */,
9E11BDF21A41204F00CC7F6B /* lec.cpp */,
9E11BDF31A41204F00CC7F6B /* lec.h */,
9E11BDF41A41204F00CC7F6B /* recover-raw.cpp */,
);
name = cdrom;
path = ../cdrom;
sourceTree = "<group>";
};
9E11BDF71A41204F00CC7F6B /* emuware */ = {
isa = PBXGroup;
children = (
9E11BDF81A41204F00CC7F6B /* emuware.cpp */,
9E11BDF91A41204F00CC7F6B /* emuware.h */,
9E11BDFA1A41204F00CC7F6B /* EW_state.cpp */,
9E11BDFB1A41204F00CC7F6B /* EW_state.h */,
9E11BE001A41204F00CC7F6B /* PACKED.h */,
9E11BE011A41204F00CC7F6B /* PACKED_END.h */,
);
name = emuware;
path = ../emuware;
sourceTree = "<group>";
};
9E11BE0F1A41204F00CC7F6B /* psx */ = {
isa = PBXGroup;
children = (
9E11BE101A41204F00CC7F6B /* cdc.cpp */,
9E11BE111A41204F00CC7F6B /* cdc.h */,
9E11BE121A41204F00CC7F6B /* cpu.cpp */,
9E11BE131A41204F00CC7F6B /* cpu.h */,
9E11BE141A41204F00CC7F6B /* cpu_bigswitch.inc */,
9E11BE151A41204F00CC7F6B /* cpu_computedgoto.inc */,
9E11BE181A41204F00CC7F6B /* dis.cpp */,
9E11BE191A41204F00CC7F6B /* dis.h */,
9E11BE1A1A41204F00CC7F6B /* dma.cpp */,
9E11BE1B1A41204F00CC7F6B /* dma.h */,
9E11BE1C1A41204F00CC7F6B /* frontio.cpp */,
9E11BE1D1A41204F00CC7F6B /* frontio.h */,
9E11BE1E1A41204F00CC7F6B /* gpu.cpp */,
9E11BE1F1A41204F00CC7F6B /* gpu.h */,
9E11BE201A41204F00CC7F6B /* gpu_common.inc */,
9E11BE211A41204F00CC7F6B /* gpu_line.cpp */,
9E11BE221A41204F00CC7F6B /* gpu_polygon.cpp */,
9E11BE231A41204F00CC7F6B /* gpu_sprite.cpp */,
9E11BE241A41204F00CC7F6B /* gte.cpp */,
9E11BE251A41204F00CC7F6B /* gte.h */,
9E11BE261A41204F00CC7F6B /* input */,
9E11BE391A41204F00CC7F6B /* irq.cpp */,
9E11BE3A1A41204F00CC7F6B /* irq.h */,
9E11BE3D1A41204F00CC7F6B /* masmem.h */,
9E11BE3E1A41204F00CC7F6B /* mdec.cpp */,
9E11BE3F1A41204F00CC7F6B /* mdec.h */,
9E11BE401A41204F00CC7F6B /* psx.cpp */,
9E11BE411A41204F00CC7F6B /* psx.h */,
9E11BE421A41204F00CC7F6B /* sio.cpp */,
9E11BE431A41204F00CC7F6B /* sio.h */,
9E11BE441A41204F00CC7F6B /* spu.cpp */,
9E11BE451A41204F00CC7F6B /* spu.h */,
9E11BE461A41204F00CC7F6B /* spu_fir_table.inc */,
9E11BE471A41204F00CC7F6B /* spu_reverb.inc */,
9E11BE481A41204F00CC7F6B /* timer.cpp */,
9E11BE491A41204F00CC7F6B /* timer.h */,
);
name = psx;
path = ../psx;
sourceTree = "<group>";
};
9E11BE261A41204F00CC7F6B /* input */ = {
isa = PBXGroup;
children = (
9E11BE271A41204F00CC7F6B /* dualanalog.cpp */,
9E11BE281A41204F00CC7F6B /* dualanalog.h */,
9E11BE291A41204F00CC7F6B /* dualshock.cpp */,
9E11BE2A1A41204F00CC7F6B /* dualshock.h */,
9E11BE2B1A41204F00CC7F6B /* gamepad.cpp */,
9E11BE2C1A41204F00CC7F6B /* gamepad.h */,
9E11BE2D1A41204F00CC7F6B /* guncon.cpp */,
9E11BE2E1A41204F00CC7F6B /* guncon.h */,
9E11BE2F1A41204F00CC7F6B /* justifier.cpp */,
9E11BE301A41204F00CC7F6B /* justifier.h */,
9E11BE311A41204F00CC7F6B /* memcard.cpp */,
9E11BE321A41204F00CC7F6B /* memcard.h */,
9E11BE331A41204F00CC7F6B /* mouse.cpp */,
9E11BE341A41204F00CC7F6B /* mouse.h */,
9E11BE351A41204F00CC7F6B /* multitap.cpp */,
9E11BE361A41204F00CC7F6B /* multitap.h */,
9E11BE371A41204F00CC7F6B /* negcon.cpp */,
9E11BE381A41204F00CC7F6B /* negcon.h */,
);
path = input;
sourceTree = "<group>";
};
9E11BE4C1A41204F00CC7F6B /* video */ = {
isa = PBXGroup;
children = (
9E11BE4D1A41204F00CC7F6B /* Deinterlacer.cpp */,
9E11BE4E1A41204F00CC7F6B /* Deinterlacer.h */,
9E11BE4F1A41204F00CC7F6B /* surface.cpp */,
9E11BE501A41204F00CC7F6B /* surface.h */,
);
name = video;
path = ../video;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXHeadersBuildPhase section */
9E11BDDD1A411DA300CC7F6B /* Headers */ = {
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
9E11BEA11A41204F00CC7F6B /* irq.h in Headers */,
9E11BE831A41204F00CC7F6B /* dma.h in Headers */,
9E11BE9D1A41204F00CC7F6B /* multitap.h in Headers */,
9E11BEB01A41204F00CC7F6B /* Stream.h in Headers */,
9E11BE6A1A41204F00CC7F6B /* PACKED_END.h in Headers */,
9E11BE771A41204F00CC7F6B /* octoshock.h in Headers */,
9E11BE691A41204F00CC7F6B /* PACKED.h in Headers */,
9E11BE661A41204F00CC7F6B /* EW_state.h in Headers */,
9E11BEB81A41213D00CC7F6B /* dvdisaster.h in Headers */,
9E11BEAA1A41204F00CC7F6B /* spu.h in Headers */,
9E11BEB21A41204F00CC7F6B /* Deinterlacer.h in Headers */,
9E11BE811A41204F00CC7F6B /* dis.h in Headers */,
9E11BE911A41204F00CC7F6B /* dualshock.h in Headers */,
9E11BE8F1A41204F00CC7F6B /* dualanalog.h in Headers */,
9E11BE991A41204F00CC7F6B /* memcard.h in Headers */,
9E11BE971A41204F00CC7F6B /* justifier.h in Headers */,
9E11BE951A41204F00CC7F6B /* guncon.h in Headers */,
9E11BEA61A41204F00CC7F6B /* psx.h in Headers */,
9E11BE931A41204F00CC7F6B /* gamepad.h in Headers */,
9E11BE9B1A41204F00CC7F6B /* mouse.h in Headers */,
9E11BEBA1A41215900CC7F6B /* SimpleFIFO.h in Headers */,
9E11BE581A41204F00CC7F6B /* CDUtility.h in Headers */,
9E11BE791A41204F00CC7F6B /* cdc.h in Headers */,
9E11BE7B1A41204F00CC7F6B /* cpu.h in Headers */,
9E11BE5F1A41204F00CC7F6B /* lec.h in Headers */,
9E11BE6D1A41204F00CC7F6B /* error.h in Headers */,
9E11BE6C1A41204F00CC7F6B /* endian.h in Headers */,
9E11BE641A41204F00CC7F6B /* emuware.h in Headers */,
9E11BE741A41204F00CC7F6B /* git.h in Headers */,
9E11BE751A41204F00CC7F6B /* math_ops.h in Headers */,
9E11BE9F1A41204F00CC7F6B /* negcon.h in Headers */,
9E11BE8D1A41204F00CC7F6B /* gte.h in Headers */,
9E11BE871A41204F00CC7F6B /* gpu.h in Headers */,
9E11BEA41A41204F00CC7F6B /* mdec.h in Headers */,
9E11BEB41A41204F00CC7F6B /* surface.h in Headers */,
9E11BE851A41204F00CC7F6B /* frontio.h in Headers */,
9E11BEA81A41204F00CC7F6B /* sio.h in Headers */,
9E11BEAE1A41204F00CC7F6B /* timer.h in Headers */,
9E11BEA21A41204F00CC7F6B /* masmem.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXHeadersBuildPhase section */
/* Begin PBXNativeTarget section */
9E11BDDE1A411DA300CC7F6B /* octoshock */ = {
isa = PBXNativeTarget;
buildConfigurationList = 9E11BDE31A411DA300CC7F6B /* Build configuration list for PBXNativeTarget "octoshock" */;
buildPhases = (
9E11BDDB1A411DA300CC7F6B /* Sources */,
9E11BDDC1A411DA300CC7F6B /* Frameworks */,
9E11BDDD1A411DA300CC7F6B /* Headers */,
);
buildRules = (
);
dependencies = (
);
name = octoshock;
productName = octoshock;
productReference = 9E11BDDF1A411DA300CC7F6B /* liboctoshock.dylib */;
productType = "com.apple.product-type.library.dynamic";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
9E11BDD71A411DA300CC7F6B /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0610;
ORGANIZATIONNAME = bizhawk;
TargetAttributes = {
9E11BDDE1A411DA300CC7F6B = {
CreatedOnToolsVersion = 6.1.1;
};
};
};
buildConfigurationList = 9E11BDDA1A411DA300CC7F6B /* Build configuration list for PBXProject "octoshock" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
en,
);
mainGroup = 9E11BDD61A411DA300CC7F6B;
productRefGroup = 9E11BDE01A411DA300CC7F6B /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
9E11BDDE1A411DA300CC7F6B /* octoshock */,
);
};
/* End PBXProject section */
/* Begin PBXSourcesBuildPhase section */
9E11BDDB1A411DA300CC7F6B /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
9E11BEA71A41204F00CC7F6B /* sio.cpp in Sources */,
9E11BE8C1A41204F00CC7F6B /* gte.cpp in Sources */,
9E11BE5E1A41204F00CC7F6B /* lec.cpp in Sources */,
9E11BEA01A41204F00CC7F6B /* irq.cpp in Sources */,
9E11BE651A41204F00CC7F6B /* EW_state.cpp in Sources */,
9E11BEB31A41204F00CC7F6B /* surface.cpp in Sources */,
9E11BE7C1A41204F00CC7F6B /* cpu_bigswitch.inc in Sources */,
9E11BE8A1A41204F00CC7F6B /* gpu_polygon.cpp in Sources */,
9E11BE781A41204F00CC7F6B /* cdc.cpp in Sources */,
9E11BE801A41204F00CC7F6B /* dis.cpp in Sources */,
9E11BE9C1A41204F00CC7F6B /* multitap.cpp in Sources */,
9E11BE631A41204F00CC7F6B /* emuware.cpp in Sources */,
9E11BEAC1A41204F00CC7F6B /* spu_reverb.inc in Sources */,
9E11BE881A41204F00CC7F6B /* gpu_common.inc in Sources */,
9E11BEA31A41204F00CC7F6B /* mdec.cpp in Sources */,
9E11BE861A41204F00CC7F6B /* gpu.cpp in Sources */,
9E11BEA91A41204F00CC7F6B /* spu.cpp in Sources */,
9E11BE6B1A41204F00CC7F6B /* endian.cpp in Sources */,
9E11BE981A41204F00CC7F6B /* memcard.cpp in Sources */,
9E11BEAB1A41204F00CC7F6B /* spu_fir_table.inc in Sources */,
9E11BE841A41204F00CC7F6B /* frontio.cpp in Sources */,
9E11BE961A41204F00CC7F6B /* justifier.cpp in Sources */,
9E11BE8E1A41204F00CC7F6B /* dualanalog.cpp in Sources */,
9E11BE5D1A41204F00CC7F6B /* l-ec.cpp in Sources */,
9E11BE941A41204F00CC7F6B /* guncon.cpp in Sources */,
9E11BE7D1A41204F00CC7F6B /* cpu_computedgoto.inc in Sources */,
9E11BE7A1A41204F00CC7F6B /* cpu.cpp in Sources */,
9E11BE761A41204F00CC7F6B /* octoshock.cpp in Sources */,
9E11BE921A41204F00CC7F6B /* gamepad.cpp in Sources */,
9E11BE571A41204F00CC7F6B /* CDUtility.cpp in Sources */,
9E11BE821A41204F00CC7F6B /* dma.cpp in Sources */,
9E11BEA51A41204F00CC7F6B /* psx.cpp in Sources */,
9E11BEB11A41204F00CC7F6B /* Deinterlacer.cpp in Sources */,
9E11BE601A41204F00CC7F6B /* recover-raw.cpp in Sources */,
9E11BEAF1A41204F00CC7F6B /* Stream.cpp in Sources */,
9E11BE9A1A41204F00CC7F6B /* mouse.cpp in Sources */,
9E11BE9E1A41204F00CC7F6B /* negcon.cpp in Sources */,
9E11BE5C1A41204F00CC7F6B /* galois.cpp in Sources */,
9E11BE901A41204F00CC7F6B /* dualshock.cpp in Sources */,
9E11BE891A41204F00CC7F6B /* gpu_line.cpp in Sources */,
9E11BEAD1A41204F00CC7F6B /* timer.cpp in Sources */,
9E11BE591A41204F00CC7F6B /* crc32.cpp in Sources */,
9E11BE8B1A41204F00CC7F6B /* gpu_sprite.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin XCBuildConfiguration section */
9E11BDE11A411DA300CC7F6B /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ARCHS = "$(ARCHS_STANDARD_32_BIT)";
CLANG_CXX_LANGUAGE_STANDARD = "c++0x";
CLANG_CXX_LIBRARY = "libstdc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
"_USRDLL=1",
"OCTOSHOCK_EXPORTS=1",
"_DEBUG=1",
"_CRT_SECURE_NO_WARNINGS=1",
"EW_EXPORT=1",
);
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
HEADER_SEARCH_PATHS = (
"$(inherited)",
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
"$(SRCROOT)/../",
);
MACOSX_DEPLOYMENT_TARGET = 10.7;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = macosx;
};
name = Debug;
};
9E11BDE21A411DA300CC7F6B /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ARCHS = "$(ARCHS_STANDARD_32_BIT)";
CLANG_CXX_LANGUAGE_STANDARD = "c++0x";
CLANG_CXX_LIBRARY = "libstdc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = YES;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_PREPROCESSOR_DEFINITIONS = (
"_CRT_SECURE_NO_WARNINGS=1",
"EW_EXPORT=1",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
HEADER_SEARCH_PATHS = (
"$(inherited)",
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
"$(SRCROOT)/../",
);
MACOSX_DEPLOYMENT_TARGET = 10.7;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = macosx;
};
name = Release;
};
9E11BDE41A411DA300CC7F6B /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ARCHS = "$(ARCHS_STANDARD_32_BIT)";
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
EXECUTABLE_PREFIX = lib;
MACOSX_DEPLOYMENT_TARGET = 10.7;
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Debug;
};
9E11BDE51A411DA300CC7F6B /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ARCHS = "$(ARCHS_STANDARD_32_BIT)";
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
EXECUTABLE_PREFIX = lib;
MACOSX_DEPLOYMENT_TARGET = 10.7;
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
9E11BDDA1A411DA300CC7F6B /* Build configuration list for PBXProject "octoshock" */ = {
isa = XCConfigurationList;
buildConfigurations = (
9E11BDE11A411DA300CC7F6B /* Debug */,
9E11BDE21A411DA300CC7F6B /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
9E11BDE31A411DA300CC7F6B /* Build configuration list for PBXNativeTarget "octoshock" */ = {
isa = XCConfigurationList;
buildConfigurations = (
9E11BDE41A411DA300CC7F6B /* Debug */,
9E11BDE51A411DA300CC7F6B /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 9E11BDD71A411DA300CC7F6B /* Project object */;
}

View File

@ -1,7 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:octoshock.xcodeproj">
</FileRef>
</Workspace>

View File

@ -1,182 +0,0 @@
/* Mednafen - Multi-system Emulator
*
* Subchannel Q CRC Code: Copyright (C) 1998 Andreas Mueller <mueller@daneb.ping.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <string.h>
#include <assert.h>
#include "dvdisaster.h"
#include "octoshock.h"
#include "CDUtility.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
};
static uint8 scramble_table[2352 - 12];
static bool CDUtility_Inited = false;
static void InitScrambleTable(void)
{
unsigned cv = 1;
for (unsigned i = 12; i < 2352; i++)
{
unsigned char z = 0;
for (int b = 0; b < 8; b++)
{
z |= (cv & 1) << b;
int feedback = ((cv >> 1) & 1) ^ (cv & 1);
cv = (cv >> 1) | (feedback << 14);
}
scramble_table[i - 12] = z;
}
//for(int i = 0; i < 2352 - 12; i++)
// printf("0x%02x, ", scramble_table[i]);
}
void CDUtility_Init(void)
{
if (!CDUtility_Inited)
{
#ifdef WANT_LEC_CHECK
Init_LEC_Correct();
InitScrambleTable();
#endif
CDUtility_Inited = true;
}
}
bool edc_lec_check_and_correct(uint8 *sector_data, bool xa)
{
CDUtility_Init();
return !!ValidateRawSector(sector_data, xa);
}
bool subq_check_checksum(const uint8 *SubQBuf)
{
uint16 crc = 0;
uint16 stored_crc = 0;
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);
crc = ~crc;
return(crc == stored_crc);
}
void subq_generate_checksum(uint8 *buf)
{
uint16 crc = 0;
for(int i = 0; i < 0xA; i++)
crc = subq_crctab[(crc >> 8) ^ buf[i]] ^ (crc << 8);
// Checksum
buf[0xa] = ~(crc >> 8);
buf[0xb] = ~(crc);
}
// 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);
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));
}
}
}
// 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);
for(unsigned d = 0; d < 12; d++)
{
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;
}
}
}
}

View File

@ -1,176 +0,0 @@
#ifndef __MDFN_CDROM_CDUTILITY_H
#define __MDFN_CDROM_CDUTILITY_H
#include <string.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
{
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.
};
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++)
{
if(track == (last_track + 1))
{
if(LBA < tracks[100].lba)
return(track - 1);
}
else
{
if(LBA < tracks[track].lba)
return(track - 1);
}
}
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).
};
//
// 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) );
}
// 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);
// 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 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);
}
#endif

View File

@ -1,155 +0,0 @@
#ifndef __MDFN_SIMPLEFIFO_H
#define __MDFN_SIMPLEFIFO_H
#include <vector>
#include <assert.h>
#include "../math_ops.h"
template<typename T>
class SimpleFIFO
{
public:
// Constructor
SimpleFIFO(uint32 the_size) // Size should be a power of 2!
{
data.resize((unsigned long)round_up_pow2(the_size));
size = the_size;
read_pos = 0;
write_pos = 0;
in_count = 0;
}
// Destructor
INLINE ~SimpleFIFO()
{
}
INLINE void SaveStatePostLoad(void)
{
//I think this is crap about file format (buffer size) change recovery. screw it.
//read_pos %= data.size();
//write_pos %= data.size();
//in_count %= (data.size() + 1);
}
#if 0
INLINE int StateAction(StateMem *sm, int load, int data_only, const char* sname)
{
SFORMAT StateRegs[] =
{
std::vector<T> data;
uint32 size;
SFVAR(read_pos),
SFVAR(write_pos),
SFVAR(in_count),
SFEND;
}
int ret = MDFNSS_StateAction(sm, load, data_only, sname);
if(load)
{
read_pos %= data.size();
write_pos %= data.size();
in_count %= (data.size() + 1);
}
return(ret);
}
#endif
INLINE uint32 CanRead(void)
{
return(in_count);
}
INLINE uint32 CanWrite(void)
{
return(size - in_count);
}
INLINE T ReadUnit(bool peek = false)
{
T ret;
assert(in_count > 0);
ret = data[read_pos];
if(!peek)
{
read_pos = (read_pos + 1) & (data.size() - 1);
in_count--;
}
return(ret);
}
INLINE uint8 ReadByte(bool peek = false)
{
assert(sizeof(T) == 1);
return(ReadUnit(peek));
}
INLINE void Write(const T *happy_data, uint32 happy_count)
{
assert(CanWrite() >= happy_count);
while(happy_count)
{
data[write_pos] = *happy_data;
write_pos = (write_pos + 1) & (data.size() - 1);
in_count++;
happy_data++;
happy_count--;
}
}
INLINE void WriteUnit(const T& wr_data)
{
Write(&wr_data, 1);
}
INLINE void WriteByte(const T& wr_data)
{
assert(sizeof(T) == 1);
Write(&wr_data, 1);
}
INLINE void Flush(void)
{
read_pos = 0;
write_pos = 0;
in_count = 0;
}
//private:
std::vector<T> data;
uint32 size;
uint32 read_pos; // Read position
uint32 write_pos; // Write position
uint32 in_count; // Number of units in the FIFO
template<bool isReader> void SyncState(EW::NewState *ns)
{
//I dont like this class...
PSS(&data[0], data.capacity()*sizeof(T));
NSS(read_pos);
NSS(write_pos);
NSS(in_count);
SaveStatePostLoad();
}
};
#endif

View File

@ -1,130 +0,0 @@
/* dvdisaster: Additional error correction for optical media.
* Copyright (C) 2004-2007 Carsten Gnoerlich.
* Project home page: http://www.dvdisaster.com
* Email: carsten@dvdisaster.com -or- cgnoerlich@fsfe.org
*
* CRC32 code based upon public domain code by Ross Williams (see notes below)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA,
* or direct your browser at http://www.gnu.org.
*/
#include "dvdisaster.h"
/***
*** EDC checksum used in CDROM sectors
***/
/*****************************************************************/
/* */
/* CRC LOOKUP TABLE */
/* ================ */
/* The following CRC lookup table was generated automagically */
/* by the Rocksoft^tm Model CRC Algorithm Table Generation */
/* Program V1.0 using the following model parameters: */
/* */
/* Width : 4 bytes. */
/* Poly : 0x8001801BL */
/* Reverse : TRUE. */
/* */
/* For more information on the Rocksoft^tm Model CRC Algorithm, */
/* see the document titled "A Painless Guide to CRC Error */
/* Detection Algorithms" by Ross Williams */
/* (ross@guest.adelaide.edu.au.). This document is likely to be */
/* in the FTP archive "ftp.adelaide.edu.au/pub/rocksoft". */
/* */
/*****************************************************************/
unsigned long edctable[256] =
{
0x00000000L, 0x90910101L, 0x91210201L, 0x01B00300L,
0x92410401L, 0x02D00500L, 0x03600600L, 0x93F10701L,
0x94810801L, 0x04100900L, 0x05A00A00L, 0x95310B01L,
0x06C00C00L, 0x96510D01L, 0x97E10E01L, 0x07700F00L,
0x99011001L, 0x09901100L, 0x08201200L, 0x98B11301L,
0x0B401400L, 0x9BD11501L, 0x9A611601L, 0x0AF01700L,
0x0D801800L, 0x9D111901L, 0x9CA11A01L, 0x0C301B00L,
0x9FC11C01L, 0x0F501D00L, 0x0EE01E00L, 0x9E711F01L,
0x82012001L, 0x12902100L, 0x13202200L, 0x83B12301L,
0x10402400L, 0x80D12501L, 0x81612601L, 0x11F02700L,
0x16802800L, 0x86112901L, 0x87A12A01L, 0x17302B00L,
0x84C12C01L, 0x14502D00L, 0x15E02E00L, 0x85712F01L,
0x1B003000L, 0x8B913101L, 0x8A213201L, 0x1AB03300L,
0x89413401L, 0x19D03500L, 0x18603600L, 0x88F13701L,
0x8F813801L, 0x1F103900L, 0x1EA03A00L, 0x8E313B01L,
0x1DC03C00L, 0x8D513D01L, 0x8CE13E01L, 0x1C703F00L,
0xB4014001L, 0x24904100L, 0x25204200L, 0xB5B14301L,
0x26404400L, 0xB6D14501L, 0xB7614601L, 0x27F04700L,
0x20804800L, 0xB0114901L, 0xB1A14A01L, 0x21304B00L,
0xB2C14C01L, 0x22504D00L, 0x23E04E00L, 0xB3714F01L,
0x2D005000L, 0xBD915101L, 0xBC215201L, 0x2CB05300L,
0xBF415401L, 0x2FD05500L, 0x2E605600L, 0xBEF15701L,
0xB9815801L, 0x29105900L, 0x28A05A00L, 0xB8315B01L,
0x2BC05C00L, 0xBB515D01L, 0xBAE15E01L, 0x2A705F00L,
0x36006000L, 0xA6916101L, 0xA7216201L, 0x37B06300L,
0xA4416401L, 0x34D06500L, 0x35606600L, 0xA5F16701L,
0xA2816801L, 0x32106900L, 0x33A06A00L, 0xA3316B01L,
0x30C06C00L, 0xA0516D01L, 0xA1E16E01L, 0x31706F00L,
0xAF017001L, 0x3F907100L, 0x3E207200L, 0xAEB17301L,
0x3D407400L, 0xADD17501L, 0xAC617601L, 0x3CF07700L,
0x3B807800L, 0xAB117901L, 0xAAA17A01L, 0x3A307B00L,
0xA9C17C01L, 0x39507D00L, 0x38E07E00L, 0xA8717F01L,
0xD8018001L, 0x48908100L, 0x49208200L, 0xD9B18301L,
0x4A408400L, 0xDAD18501L, 0xDB618601L, 0x4BF08700L,
0x4C808800L, 0xDC118901L, 0xDDA18A01L, 0x4D308B00L,
0xDEC18C01L, 0x4E508D00L, 0x4FE08E00L, 0xDF718F01L,
0x41009000L, 0xD1919101L, 0xD0219201L, 0x40B09300L,
0xD3419401L, 0x43D09500L, 0x42609600L, 0xD2F19701L,
0xD5819801L, 0x45109900L, 0x44A09A00L, 0xD4319B01L,
0x47C09C00L, 0xD7519D01L, 0xD6E19E01L, 0x46709F00L,
0x5A00A000L, 0xCA91A101L, 0xCB21A201L, 0x5BB0A300L,
0xC841A401L, 0x58D0A500L, 0x5960A600L, 0xC9F1A701L,
0xCE81A801L, 0x5E10A900L, 0x5FA0AA00L, 0xCF31AB01L,
0x5CC0AC00L, 0xCC51AD01L, 0xCDE1AE01L, 0x5D70AF00L,
0xC301B001L, 0x5390B100L, 0x5220B200L, 0xC2B1B301L,
0x5140B400L, 0xC1D1B501L, 0xC061B601L, 0x50F0B700L,
0x5780B800L, 0xC711B901L, 0xC6A1BA01L, 0x5630BB00L,
0xC5C1BC01L, 0x5550BD00L, 0x54E0BE00L, 0xC471BF01L,
0x6C00C000L, 0xFC91C101L, 0xFD21C201L, 0x6DB0C300L,
0xFE41C401L, 0x6ED0C500L, 0x6F60C600L, 0xFFF1C701L,
0xF881C801L, 0x6810C900L, 0x69A0CA00L, 0xF931CB01L,
0x6AC0CC00L, 0xFA51CD01L, 0xFBE1CE01L, 0x6B70CF00L,
0xF501D001L, 0x6590D100L, 0x6420D200L, 0xF4B1D301L,
0x6740D400L, 0xF7D1D501L, 0xF661D601L, 0x66F0D700L,
0x6180D800L, 0xF111D901L, 0xF0A1DA01L, 0x6030DB00L,
0xF3C1DC01L, 0x6350DD00L, 0x62E0DE00L, 0xF271DF01L,
0xEE01E001L, 0x7E90E100L, 0x7F20E200L, 0xEFB1E301L,
0x7C40E400L, 0xECD1E501L, 0xED61E601L, 0x7DF0E700L,
0x7A80E800L, 0xEA11E901L, 0xEBA1EA01L, 0x7B30EB00L,
0xE8C1EC01L, 0x7850ED00L, 0x79E0EE00L, 0xE971EF01L,
0x7700F000L, 0xE791F101L, 0xE621F201L, 0x76B0F300L,
0xE541F401L, 0x75D0F500L, 0x7460F600L, 0xE4F1F701L,
0xE381F801L, 0x7310F900L, 0x72A0FA00L, 0xE231FB01L,
0x71C0FC00L, 0xE151FD01L, 0xE0E1FE01L, 0x7070FF00L
};
/*
* CDROM EDC calculation
*/
uint32 EDCCrc32(const unsigned char *data, int len)
{
uint32 crc = 0;
while(len--)
crc = edctable[(crc ^ *data++) & 0xFF] ^ (crc >> 8);
return crc;
}

View File

@ -1,170 +0,0 @@
/* dvdisaster: Additional error correction for optical media.
* Copyright (C) 2004-2007 Carsten Gnoerlich.
* Project home page: http://www.dvdisaster.com
* Email: carsten@dvdisaster.com -or- cgnoerlich@fsfe.org
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA,
* or direct your browser at http://www.gnu.org.
*/
#ifndef DVDISASTER_H
#define DVDISASTER_H
/* "Dare to be gorgeous and unique.
* But don't ever be cryptic or otherwise unfathomable.
* Make it unforgettably great."
*
* From "A Final Note on Style",
* Amiga Intuition Reference Manual, 1986, p. 231
*/
/***
*** I'm too lazy to mess with #include dependencies.
*** Everything #includeable is rolled up herein...
*/
#include "octoshock.h"
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <math.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdarg.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/***
*** dvdisaster.c
***/
void PrepareDeadSector(void);
void CreateEcc(void);
void FixEcc(void);
void Verify(void);
uint32 EDCCrc32(const unsigned char*, int);
/***
*** galois.c
***
* This is currently the hardcoded GF(2**8).
* int32 gives abundant space for the GF.
* Squeezing it down to uint8 won't probably gain much,
* so we implement this defensively here.
*
* Note that some performance critical stuff needs to
* be #included from galois-inlines.h
*/
/* Galois field parameters for 8bit symbol Reed-Solomon code */
#define GF_SYMBOLSIZE 8
#define GF_FIELDSIZE (1<<GF_SYMBOLSIZE)
#define GF_FIELDMAX (GF_FIELDSIZE-1)
#define GF_ALPHA0 GF_FIELDMAX
/* Lookup tables for Galois field arithmetic */
typedef struct _GaloisTables
{ int32 gfGenerator; /* GF generator polynomial */
int32 *indexOf; /* log */
int32 *alphaTo; /* inverse log */
int32 *encAlphaTo; /* inverse log optimized for encoder */
} GaloisTables;
/* Lookup and working tables for the ReedSolomon codecs */
typedef struct _ReedSolomonTables
{ GaloisTables *gfTables;/* from above */
int32 *gpoly; /* RS code generator polynomial */
int32 fcr; /* first consecutive root of RS generator polynomial */
int32 primElem; /* primitive field element */
int32 nroots; /* degree of RS generator polynomial */
int32 ndata; /* data bytes per ecc block */
} ReedSolomonTables;
GaloisTables* CreateGaloisTables(int32);
void FreeGaloisTables(GaloisTables*);
ReedSolomonTables *CreateReedSolomonTables(GaloisTables*, int32, int32, int);
void FreeReedSolomonTables(ReedSolomonTables*);
/***
*** l-ec.c
***/
#define N_P_VECTORS 86 /* 43 16bit p vectors */
#define P_VECTOR_SIZE 26 /* using RS(26,24) ECC */
#define N_Q_VECTORS 52 /* 26 16bit q vectors */
#define Q_VECTOR_SIZE 45 /* using RS(45,43) ECC */
#define P_PADDING 229 /* padding values for */
#define Q_PADDING 210 /* shortened RS code */
int PToByteIndex(int, int);
int QToByteIndex(int, int);
void ByteIndexToP(int, int*, int*);
void ByteIndexToQ(int, int*, int*);
void GetPVector(unsigned char*, unsigned char*, int);
void SetPVector(unsigned char*, unsigned char*, int);
void FillPVector(unsigned char*, unsigned char, int);
void AndPVector(unsigned char*, unsigned char, int);
void OrPVector(unsigned char*, unsigned char, int);
void GetQVector(unsigned char*, unsigned char*, int);
void SetQVector(unsigned char*, unsigned char*, int);
void FillQVector(unsigned char*, unsigned char, int);
void AndQVector(unsigned char*, unsigned char, int);
void OrQVector(unsigned char*, unsigned char, int);
int DecodePQ(ReedSolomonTables*, unsigned char*, int, int*, int);
int CountC2Errors(unsigned char*);
/***
*** misc.c
***/
char* sgettext(char*);
char* sgettext_utf8(char*);
int64 uchar_to_int64(unsigned char*);
void int64_to_uchar(unsigned char*, int64);
void CalcSectors(int64, int64*, int*);
/***
*** recover-raw.c
***/
#define CD_RAW_SECTOR_SIZE 2352
#define CD_RAW_C2_SECTOR_SIZE (2352+294) /* main channel plus C2 vector */
int CheckEDC(const unsigned char*, bool);
int CheckMSF(unsigned char*, int);
int ValidateRawSector(unsigned char *frame, bool xaMode);
bool Init_LEC_Correct(void);
void Kill_LEC_Correct(void);
#endif /* DVDISASTER_H */

View File

@ -1,40 +0,0 @@
/* dvdisaster: Additional error correction for optical media.
* Copyright (C) 2004-2007 Carsten Gnoerlich.
* Project home page: http://www.dvdisaster.com
* Email: carsten@dvdisaster.com -or- cgnoerlich@fsfe.org
*
* The Reed-Solomon error correction draws a lot of inspiration - and even code -
* from Phil Karn's excellent Reed-Solomon library: http://www.ka9q.net/code/fec/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA,
* or direct your browser at http://www.gnu.org.
*/
#include "dvdisaster.h"
/*
* The following routine is performance critical.
*/
static inline int mod_fieldmax(int x)
{
while (x >= GF_FIELDMAX)
{
x -= GF_FIELDMAX;
x = (x >> GF_SYMBOLSIZE) + (x & GF_FIELDMAX);
}
return x;
}

View File

@ -1,156 +0,0 @@
/* dvdisaster: Additional error correction for optical media.
* Copyright (C) 2004-2007 Carsten Gnoerlich.
* Project home page: http://www.dvdisaster.com
* Email: carsten@dvdisaster.com -or- cgnoerlich@fsfe.org
*
* The Reed-Solomon error correction draws a lot of inspiration - and even code -
* from Phil Karn's excellent Reed-Solomon library: http://www.ka9q.net/code/fec/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA,
* or direct your browser at http://www.gnu.org.
*/
#include "dvdisaster.h"
#include "galois-inlines.h"
/***
*** Galois field arithmetic.
***
* Calculations are done over the extension field GF(2**n).
* Be careful not to overgeneralize these arithmetics;
* they only work for the case of GF(p**n) with p being prime.
*/
/* Initialize the Galois field tables */
GaloisTables* CreateGaloisTables(int32 gf_generator)
{
GaloisTables *gt = (GaloisTables *)calloc(1, sizeof(GaloisTables));
int32 b,log;
/* Allocate the tables.
The encoder uses a special version of alpha_to which has the mod_fieldmax()
folded into the table. */
gt->gfGenerator = 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++)
{ gt->indexOf[b] = log;
gt->alphaTo[log] = b;
b = b << 1;
if(b & GF_FIELDSIZE)
b = b ^ gf_generator;
}
if(b!=1)
{
printf("Failed to create the Galois field log tables!\n");
exit(1);
}
/* we're even closed using infinity (makes things easier) */
gt->indexOf[0] = GF_ALPHA0; /* log(0) = inf */
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)];
return gt;
}
void FreeGaloisTables(GaloisTables *gt)
{
if(gt->indexOf) free(gt->indexOf);
if(gt->alphaTo) free(gt->alphaTo);
if(gt->encAlphaTo) free(gt->encAlphaTo);
free(gt);
}
/***
*** Create the the Reed-Solomon generator polynomial
*** and some auxiliary data structures.
*/
ReedSolomonTables *CreateReedSolomonTables(GaloisTables *gt,
int32 first_consecutive_root,
int32 prim_elem,
int nroots_in)
{ ReedSolomonTables *rt = (ReedSolomonTables *)calloc(1, sizeof(ReedSolomonTables));
int32 i,j,root;
rt->gfTables = gt;
rt->fcr = first_consecutive_root;
rt->primElem = prim_elem;
rt->nroots = nroots_in;
rt->ndata = GF_FIELDMAX - rt->nroots;
rt->gpoly = (int32 *)calloc((rt->nroots+1), sizeof(int32));
/* Create the RS code generator polynomial */
rt->gpoly[0] = 1;
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) */
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)];
}
/* 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
return rt;
}
void FreeReedSolomonTables(ReedSolomonTables *rt)
{
if(rt->gpoly) free(rt->gpoly);
free(rt);
}

View File

@ -1,478 +0,0 @@
/* dvdisaster: Additional error correction for optical media.
* Copyright (C) 2004-2007 Carsten Gnoerlich.
* Project home page: http://www.dvdisaster.com
* Email: carsten@dvdisaster.com -or- cgnoerlich@fsfe.org
*
* The Reed-Solomon error correction draws a lot of inspiration - and even code -
* from Phil Karn's excellent Reed-Solomon library: http://www.ka9q.net/code/fec/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA,
* or direct your browser at http://www.gnu.org.
*/
#include "dvdisaster.h"
#include "galois-inlines.h"
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
/***
*** Mapping between cd frame and parity vectors
***/
/*
* Mapping of frame bytes to P/Q Vectors
*/
int PToByteIndex(int p, int i)
{ return 12 + p + i*86;
}
void ByteIndexToP(int b, int *p, int *i)
{ *p = (b-12)%86;
*i = (b-12)/86;
}
int QToByteIndex(int q, int i)
{ int offset = 12 + (q & 1);
if(i == 43) return 2248+q;
if(i == 44) return 2300+q;
q&=~1;
return offset + (q*43 + i*88) % 2236;
}
void ByteIndexToQ(int b, int *q, int *i)
{ int x,y,offset;
if(b >= 2300)
{ *i = 44;
*q = (b-2300);
return;
}
if(b >= 2248)
{ *i = 43;
*q = (b-2248);
return;
}
offset = b&1;
b = (b-12)/2;
x = b/43;
y = (b-(x*43))%26;
*i = b-(x*43);
*q = 2*((x+26-y)%26)+offset;
}
/*
* There are 86 vectors of P-parity, yielding a RS(26,24) code.
*/
void GetPVector(unsigned char *frame, unsigned char *data, int n)
{ int i;
int w_idx = n+12;
for(i=0; i<26; i++, w_idx+=86)
data[i] = frame[w_idx];
}
void SetPVector(unsigned char *frame, unsigned char *data, int n)
{ int i;
int w_idx = n+12;
for(i=0; i<26; i++, w_idx+=86)
frame[w_idx] = data[i];
}
void FillPVector(unsigned char *frame, unsigned char data, int n)
{ int i;
int w_idx = n+12;
for(i=0; i<26; i++, w_idx+=86)
frame[w_idx] = data;
}
void OrPVector(unsigned char *frame, unsigned char value, int n)
{ int i;
int w_idx = n+12;
for(i=0; i<26; i++, w_idx+=86)
frame[w_idx] |= value;
}
void AndPVector(unsigned char *frame, unsigned char value, int n)
{ int i;
int w_idx = n+12;
for(i=0; i<26; i++, w_idx+=86)
frame[w_idx] &= value;
}
/*
* There are 52 vectors of Q-parity, yielding a RS(45,43) code.
*/
void GetQVector(unsigned char *frame, unsigned char *data, int n)
{ int offset = 12 + (n & 1);
int w_idx = (n&~1) * 43;
int i;
for(i=0; i<43; i++, w_idx+=88)
data[i] = frame[(w_idx % 2236) + offset];
data[43] = frame[2248 + n];
data[44] = frame[2300 + n];
}
void SetQVector(unsigned char *frame, unsigned char *data, int n)
{ int offset = 12 + (n & 1);
int w_idx = (n&~1) * 43;
int i;
for(i=0; i<43; i++, w_idx+=88)
frame[(w_idx % 2236) + offset] = data[i];
frame[2248 + n] = data[43];
frame[2300 + n] = data[44];
}
void FillQVector(unsigned char *frame, unsigned char data, int n)
{ int offset = 12 + (n & 1);
int w_idx = (n&~1) * 43;
int i;
for(i=0; i<43; i++, w_idx+=88)
frame[(w_idx % 2236) + offset] = data;
frame[2248 + n] = data;
frame[2300 + n] = data;
}
void OrQVector(unsigned char *frame, unsigned char data, int n)
{ int offset = 12 + (n & 1);
int w_idx = (n&~1) * 43;
int i;
for(i=0; i<43; i++, w_idx+=88)
frame[(w_idx % 2236) + offset] |= data;
frame[2248 + n] |= data;
frame[2300 + n] |= data;
}
void AndQVector(unsigned char *frame, unsigned char data, int n)
{ int offset = 12 + (n & 1);
int w_idx = (n&~1) * 43;
int i;
for(i=0; i<43; i++, w_idx+=88)
frame[(w_idx % 2236) + offset] &= data;
frame[2248 + n] &= data;
frame[2300 + n] &= data;
}
/***
*** C2 error counting
***/
int CountC2Errors(unsigned char *frame)
{ int i,count = 0;
frame += 2352;
for(i=0; i<294; i++, frame++)
{ if(*frame & 0x01) count++;
if(*frame & 0x02) count++;
if(*frame & 0x04) count++;
if(*frame & 0x08) count++;
if(*frame & 0x10) count++;
if(*frame & 0x20) count++;
if(*frame & 0x40) count++;
if(*frame & 0x80) count++;
}
return count;
}
/***
*** L-EC error correction for CD raw data sectors
***/
/*
* These could be used from ReedSolomonTables,
* but hardcoding them is faster.
*/
#define NROOTS 2
#define LEC_FIRST_ROOT 0 //GF_ALPHA0
#define LEC_PRIM_ELEM 1
#define LEC_PRIMTH_ROOT 1
/*
* Calculate the error syndrome
*/
int DecodePQ(ReedSolomonTables *rt, unsigned char *data, int padding,
int *erasure_list, int erasure_count)
{ GaloisTables *gt = rt->gfTables;
int syndrome[NROOTS];
int lambda[NROOTS+1];
int omega[NROOTS+1];
int b[NROOTS+1];
int reg[NROOTS+1];
int root[NROOTS];
int loc[NROOTS];
int syn_error;
int deg_lambda,lambda_roots;
int deg_omega;
int shortened_size = GF_FIELDMAX - 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];
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)];
/*** Convert syndrome to index form, check for nonzero condition. */
syn_error = 0;
for(i=0; i<NROOTS; i++)
{ syn_error |= syndrome[i];
syndrome[i] = gt->indexOf[syndrome[i]];
}
/*** If the syndrome is zero, everything is fine. */
if(!syn_error)
return 0;
/*** Initialize lambda to be the erasure locator polynomial */
lambda[0] = 1;
lambda[1] = lambda[2] = 0;
erasure_list[0] += padding;
erasure_list[1] += padding;
if(erasure_count > 2) /* sanity check */
erasure_count = 0;
if(erasure_count > 0)
{ lambda[1] = gt->alphaTo[mod_fieldmax(LEC_PRIM_ELEM*(GF_FIELDMAX-1-erasure_list[0]))];
for(i=1; i<erasure_count; i++)
{ 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]];
if(tmp != GF_ALPHA0)
lambda[j] ^= gt->alphaTo[mod_fieldmax(u + tmp)];
}
}
}
for(i=0; i<NROOTS+1; i++)
b[i] = gt->indexOf[lambda[i]];
/*** Berlekamp-Massey algorithm to determine error+erasure locator polynomial */
r = erasure_count; /* r is the step number */
el = erasure_count;
/* Compute discrepancy at the r-th step in poly-form */
while(++r <= NROOTS)
{ 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])];
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;
}
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];
}
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;
}
memcpy(lambda, t, (NROOTS+1)*sizeof(t[0]));
}
}
/*** Convert lambda to index form and compute deg(lambda(x)) */
deg_lambda = 0;
for(i=0; i<NROOTS+1; i++)
{ lambda[i] = gt->indexOf[lambda[i]];
if(lambda[i] != GF_ALPHA0)
deg_lambda = i;
}
/*** Find roots of the error+erasure locator polynomial by Chien search */
memcpy(reg+1, lambda+1, NROOTS*sizeof(reg[0]));
lambda_roots = 0; /* Number of roots of lambda(x) */
for(i=1, k=LEC_PRIMTH_ROOT-1; i<=GF_FIELDMAX; i++, k=mod_fieldmax(k+LEC_PRIMTH_ROOT))
{ int q=1; /* lambda[0] is always 0 */
for(j=deg_lambda; j>0; j--)
{ if(reg[j] != GF_ALPHA0)
{ reg[j] = mod_fieldmax(reg[j] + j);
q ^= gt->alphaTo[reg[j]];
}
}
if(q != 0) continue; /* Not a root */
/* store root in index-form and the error location number */
root[lambda_roots] = i;
loc[lambda_roots] = k;
/* If we've already found max possible roots, abort the search to save time */
if(++lambda_roots == deg_lambda) break;
}
/* deg(lambda) unequal to number of roots => uncorrectable error detected
This is not reliable for very small numbers of roots, e.g. nroots = 2 */
if(deg_lambda != lambda_roots)
{ return -1;
}
/* Compute err+eras evaluator poly omega(x) = syn(x)*lambda(x)
(modulo x**nroots). in index form. Also find deg(omega). */
deg_omega = deg_lambda-1;
for(i=0; i<=deg_omega; i++)
{ int tmp = 0;
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])];
}
omega[i] = gt->indexOf[tmp];
}
/* Compute error values in poly-form.
num1 = omega(inv(X(l))),
num2 = inv(X(l))**(FIRST_ROOT-1) and
den = lambda_pr(inv(X(l))) all in poly-form. */
for(j=lambda_roots-1; j>=0; j--)
{ int num1 = 0;
int num2;
int den;
int location = loc[j];
for(i=deg_omega; i>=0; i--)
{ if(omega[i] != GF_ALPHA0)
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])];
}
/* 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])];
/* 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 1
else return -3;
#endif
}
/*** Form the syndromes: Evaluate data(x) at roots of g(x) */
for(i=0; i<NROOTS; i++)
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)];
}
/*** Convert syndrome to index form, check for nonzero condition. */
#if 1
for(i=0; i<NROOTS; i++)
if(syndrome[i])
return -2;
#endif
return corrected;
}

View File

@ -1,691 +0,0 @@
/* cdrdao - write audio CD-Rs in disc-at-once mode
*
* Copyright (C) 1998-2002 Andreas Mueller <andreas@daneb.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <assert.h>
#include <sys/types.h>
#include "lec.h"
#define GF8_PRIM_POLY 0x11d /* x^8 + x^4 + x^3 + x^2 + 1 */
#define EDC_POLY 0x8001801b /* (x^16 + x^15 + x^2 + 1) (x^16 + x^2 + x + 1) */
#define LEC_HEADER_OFFSET 12
#define LEC_DATA_OFFSET 16
#define LEC_MODE1_DATA_LEN 2048
#define LEC_MODE1_EDC_OFFSET 2064
#define LEC_MODE1_INTERMEDIATE_OFFSET 2068
#define LEC_MODE1_P_PARITY_OFFSET 2076
#define LEC_MODE1_Q_PARITY_OFFSET 2248
#define LEC_MODE2_FORM1_DATA_LEN (2048+8)
#define LEC_MODE2_FORM1_EDC_OFFSET 2072
#define LEC_MODE2_FORM2_DATA_LEN (2324+8)
#define LEC_MODE2_FORM2_EDC_OFFSET 2348
typedef u_int8_t gf8_t;
static u_int8_t GF8_LOG[256];
static gf8_t GF8_ILOG[256];
static const class Gf8_Q_Coeffs_Results_01 {
private:
u_int16_t table[43][256];
public:
Gf8_Q_Coeffs_Results_01();
~Gf8_Q_Coeffs_Results_01() {}
const u_int16_t *operator[] (int i) const { return &table[i][0]; }
operator const u_int16_t *() const { return &table[0][0]; }
} CF8_Q_COEFFS_RESULTS_01;
static const class CrcTable {
private:
u_int32_t table[256];
public:
CrcTable();
~CrcTable() {}
u_int32_t operator[](int i) const { return table[i]; }
operator const u_int32_t *() const { return table; }
} CRCTABLE;
static const class ScrambleTable {
private:
u_int8_t table[2340];
public:
ScrambleTable();
~ScrambleTable() {}
u_int8_t operator[](int i) const { return table[i]; }
operator const u_int8_t *() const { return table; }
} SCRAMBLE_TABLE;
/* Creates the logarithm and inverse logarithm table that is required
* for performing multiplication in the GF(8) domain.
*/
static void gf8_create_log_tables()
{
u_int8_t log;
u_int16_t b;
for (b = 0; b <= 255; b++) {
GF8_LOG[b] = 0;
GF8_ILOG[b] = 0;
}
b = 1;
for (log = 0; log < 255; log++) {
GF8_LOG[(u_int8_t)b] = log;
GF8_ILOG[log] = (u_int8_t)b;
b <<= 1;
if ((b & 0x100) != 0)
b ^= GF8_PRIM_POLY;
}
}
/* Addition in the GF(8) domain: just the XOR of the values.
*/
#define gf8_add(a, b) (a) ^ (b)
/* Multiplication in the GF(8) domain: add the logarithms (modulo 255)
* and return the inverse logarithm. Not used!
*/
#if 0
static gf8_t gf8_mult(gf8_t a, gf8_t b)
{
int16_t sum;
if (a == 0 || b == 0)
return 0;
sum = GF8_LOG[a] + GF8_LOG[b];
if (sum >= 255)
sum -= 255;
return GF8_ILOG[sum];
}
#endif
/* Division in the GF(8) domain: Like multiplication but logarithms a
* subtracted.
*/
static gf8_t gf8_div(gf8_t a, gf8_t b)
{
int16_t sum;
assert(b != 0);
if (a == 0)
return 0;
sum = GF8_LOG[a] - GF8_LOG[b];
if (sum < 0)
sum += 255;
return GF8_ILOG[sum];
}
Gf8_Q_Coeffs_Results_01::Gf8_Q_Coeffs_Results_01()
{
int i, j;
u_int16_t c;
gf8_t GF8_COEFFS_HELP[2][45];
u_int8_t GF8_Q_COEFFS[2][45];
gf8_create_log_tables();
/* build matrix H:
* 1 1 ... 1 1
* a^44 a^43 ... a^1 a^0
*
*
*/
for (j = 0; j < 45; j++) {
GF8_COEFFS_HELP[0][j] = 1; /* e0 */
GF8_COEFFS_HELP[1][j] = GF8_ILOG[44-j]; /* e1 */
}
/* resolve equation system for parity byte 0 and 1 */
/* e1' = e1 + e0 */
for (j = 0; j < 45; j++) {
GF8_Q_COEFFS[1][j] = gf8_add(GF8_COEFFS_HELP[1][j],
GF8_COEFFS_HELP[0][j]);
}
/* e1'' = e1' / (a^1 + 1) */
for (j = 0; j < 45; j++) {
GF8_Q_COEFFS[1][j] = gf8_div(GF8_Q_COEFFS[1][j], GF8_Q_COEFFS[1][43]);
}
/* e0' = e0 + e1 / a^1 */
for (j = 0; j < 45; j++) {
GF8_Q_COEFFS[0][j] = gf8_add(GF8_COEFFS_HELP[0][j],
gf8_div(GF8_COEFFS_HELP[1][j],
GF8_ILOG[1]));
}
/* e0'' = e0' / (1 + 1 / a^1) */
for (j = 0; j < 45; j++) {
GF8_Q_COEFFS[0][j] = gf8_div(GF8_Q_COEFFS[0][j], GF8_Q_COEFFS[0][44]);
}
/*
* Compute the products of 0..255 with all of the Q coefficients in
* advance. When building the scalar product between the data vectors
* and the P/Q vectors the individual products can be looked up in
* this table
*
* The P parity coefficients are just a subset of the Q coefficients so
* that we do not need to create a separate table for them.
*/
for (j = 0; j < 43; j++) {
table[j][0] = 0;
for (i = 1; i < 256; i++) {
c = GF8_LOG[i] + GF8_LOG[GF8_Q_COEFFS[0][j]];
if (c >= 255) c -= 255;
table[j][i] = GF8_ILOG[c];
c = GF8_LOG[i] + GF8_LOG[GF8_Q_COEFFS[1][j]];
if (c >= 255) c -= 255;
table[j][i] |= GF8_ILOG[c]<<8;
}
}
}
/* Reverses the bits in 'd'. 'bits' defines the bit width of 'd'.
*/
static u_int32_t mirror_bits(u_int32_t d, int bits)
{
int i;
u_int32_t r = 0;
for (i = 0; i < bits; i++) {
r <<= 1;
if ((d & 0x1) != 0)
r |= 0x1;
d >>= 1;
}
return r;
}
/* Build the CRC lookup table for EDC_POLY poly. The CRC is 32 bit wide
* and reversed (i.e. the bit stream is divided by the EDC_POLY with the
* LSB first order).
*/
CrcTable::CrcTable ()
{
u_int32_t i, j;
u_int32_t r;
for (i = 0; i < 256; i++) {
r = mirror_bits(i, 8);
r <<= 24;
for (j = 0; j < 8; j++) {
if ((r & 0x80000000) != 0) {
r <<= 1;
r ^= EDC_POLY;
}
else {
r <<= 1;
}
}
r = mirror_bits(r, 32);
table[i] = r;
}
}
/* Calculates the CRC of given data with given lengths based on the
* table lookup algorithm.
*/
static u_int32_t calc_edc(u_int8_t *data, int len)
{
u_int32_t crc = 0;
while (len--) {
crc = CRCTABLE[(int)(crc ^ *data++) & 0xff] ^ (crc >> 8);
}
return crc;
}
/* Build the scramble table as defined in the yellow book. The bytes
12 to 2351 of a sector will be XORed with the data of this table.
*/
ScrambleTable::ScrambleTable()
{
u_int16_t i, j;
u_int16_t reg = 1;
u_int8_t d;
for (i = 0; i < 2340; i++) {
d = 0;
for (j = 0; j < 8; j++) {
d >>= 1;
if ((reg & 0x1) != 0)
d |= 0x80;
if ((reg & 0x1) != ((reg >> 1) & 0x1)) {
reg >>= 1;
reg |= 0x4000; /* 15-bit register */
}
else {
reg >>= 1;
}
}
table[i] = d;
}
}
/* Calc EDC for a MODE 1 sector
*/
static void calc_mode1_edc(u_int8_t *sector)
{
u_int32_t crc = calc_edc(sector, LEC_MODE1_DATA_LEN + 16);
sector[LEC_MODE1_EDC_OFFSET] = crc & 0xffL;
sector[LEC_MODE1_EDC_OFFSET + 1] = (crc >> 8) & 0xffL;
sector[LEC_MODE1_EDC_OFFSET + 2] = (crc >> 16) & 0xffL;
sector[LEC_MODE1_EDC_OFFSET + 3] = (crc >> 24) & 0xffL;
}
/* Calc EDC for a XA form 1 sector
*/
static void calc_mode2_form1_edc(u_int8_t *sector)
{
u_int32_t crc = calc_edc(sector + LEC_DATA_OFFSET,
LEC_MODE2_FORM1_DATA_LEN);
sector[LEC_MODE2_FORM1_EDC_OFFSET] = crc & 0xffL;
sector[LEC_MODE2_FORM1_EDC_OFFSET + 1] = (crc >> 8) & 0xffL;
sector[LEC_MODE2_FORM1_EDC_OFFSET + 2] = (crc >> 16) & 0xffL;
sector[LEC_MODE2_FORM1_EDC_OFFSET + 3] = (crc >> 24) & 0xffL;
}
/* Calc EDC for a XA form 2 sector
*/
static void calc_mode2_form2_edc(u_int8_t *sector)
{
u_int32_t crc = calc_edc(sector + LEC_DATA_OFFSET,
LEC_MODE2_FORM2_DATA_LEN);
sector[LEC_MODE2_FORM2_EDC_OFFSET] = crc & 0xffL;
sector[LEC_MODE2_FORM2_EDC_OFFSET + 1] = (crc >> 8) & 0xffL;
sector[LEC_MODE2_FORM2_EDC_OFFSET + 2] = (crc >> 16) & 0xffL;
sector[LEC_MODE2_FORM2_EDC_OFFSET + 3] = (crc >> 24) & 0xffL;
}
/* Writes the sync pattern to the given sector.
*/
static void set_sync_pattern(u_int8_t *sector)
{
sector[0] = 0;
sector[1] = sector[2] = sector[3] = sector[4] = sector[5] =
sector[6] = sector[7] = sector[8] = sector[9] = sector[10] = 0xff;
sector[11] = 0;
}
static u_int8_t bin2bcd(u_int8_t b)
{
return (((b/10) << 4) & 0xf0) | ((b%10) & 0x0f);
}
/* Builds the sector header.
*/
static void set_sector_header(u_int8_t mode, u_int32_t adr, u_int8_t *sector)
{
sector[LEC_HEADER_OFFSET] = bin2bcd(adr / (60*75));
sector[LEC_HEADER_OFFSET + 1] = bin2bcd((adr / 75) % 60);
sector[LEC_HEADER_OFFSET + 2] = bin2bcd(adr % 75);
sector[LEC_HEADER_OFFSET + 3] = mode;
}
/* Calculate the P parities for the sector.
* The 43 P vectors of length 24 are combined with the GF8_P_COEFFS.
*/
static void calc_P_parity(u_int8_t *sector)
{
int i, j;
u_int16_t p01_msb, p01_lsb;
u_int8_t *p_lsb_start;
u_int8_t *p_lsb;
u_int8_t *p0, *p1;
u_int8_t d0,d1;
p_lsb_start = sector + LEC_HEADER_OFFSET;
p1 = sector + LEC_MODE1_P_PARITY_OFFSET;
p0 = sector + LEC_MODE1_P_PARITY_OFFSET + 2 * 43;
for (i = 0; i <= 42; i++) {
p_lsb = p_lsb_start;
p01_lsb = p01_msb = 0;
for (j = 19; j <= 42; j++) {
d0 = *p_lsb;
d1 = *(p_lsb+1);
p01_lsb ^= CF8_Q_COEFFS_RESULTS_01[j][d0];
p01_msb ^= CF8_Q_COEFFS_RESULTS_01[j][d1];
p_lsb += 2 * 43;
}
*p0 = p01_lsb;
*(p0 + 1) = p01_msb;
*p1 = p01_lsb>>8;
*(p1 + 1) = p01_msb>>8;
p0 += 2;
p1 += 2;
p_lsb_start += 2;
}
}
/* Calculate the Q parities for the sector.
* The 26 Q vectors of length 43 are combined with the GF8_Q_COEFFS.
*/
static void calc_Q_parity(u_int8_t *sector)
{
int i, j;
u_int16_t q01_lsb, q01_msb;
u_int8_t *q_lsb_start;
u_int8_t *q_lsb;
u_int8_t *q0, *q1, *q_start;
u_int8_t d0,d1;
q_lsb_start = sector + LEC_HEADER_OFFSET;
q_start = sector + LEC_MODE1_Q_PARITY_OFFSET;
q1 = sector + LEC_MODE1_Q_PARITY_OFFSET;
q0 = sector + LEC_MODE1_Q_PARITY_OFFSET + 2 * 26;
for (i = 0; i <= 25; i++) {
q_lsb = q_lsb_start;
q01_lsb = q01_msb = 0;
for (j = 0; j <= 42; j++) {
d0 = *q_lsb;
d1 = *(q_lsb+1);
q01_lsb ^= CF8_Q_COEFFS_RESULTS_01[j][d0];
q01_msb ^= CF8_Q_COEFFS_RESULTS_01[j][d1];
q_lsb += 2 * 44;
if (q_lsb >= q_start) {
q_lsb -= 2 * 1118;
}
}
*q0 = q01_lsb;
*(q0 + 1) = q01_msb;
*q1 = q01_lsb>>8;
*(q1 + 1) = q01_msb>>8;
q0 += 2;
q1 += 2;
q_lsb_start += 2 * 43;
}
}
/* Encodes a MODE 0 sector.
* 'adr' is the current physical sector address
* 'sector' must be 2352 byte wide
*/
void lec_encode_mode0_sector(u_int32_t adr, u_int8_t *sector)
{
u_int16_t i;
set_sync_pattern(sector);
set_sector_header(0, adr, sector);
sector += 16;
for (i = 0; i < 2336; i++)
*sector++ = 0;
}
/* Encodes a MODE 1 sector.
* 'adr' is the current physical sector address
* 'sector' must be 2352 byte wide containing 2048 bytes user data at
* offset 16
*/
void lec_encode_mode1_sector(u_int32_t adr, u_int8_t *sector)
{
set_sync_pattern(sector);
set_sector_header(1, adr, sector);
calc_mode1_edc(sector);
/* clear the intermediate field */
sector[LEC_MODE1_INTERMEDIATE_OFFSET] =
sector[LEC_MODE1_INTERMEDIATE_OFFSET + 1] =
sector[LEC_MODE1_INTERMEDIATE_OFFSET + 2] =
sector[LEC_MODE1_INTERMEDIATE_OFFSET + 3] =
sector[LEC_MODE1_INTERMEDIATE_OFFSET + 4] =
sector[LEC_MODE1_INTERMEDIATE_OFFSET + 5] =
sector[LEC_MODE1_INTERMEDIATE_OFFSET + 6] =
sector[LEC_MODE1_INTERMEDIATE_OFFSET + 7] = 0;
calc_P_parity(sector);
calc_Q_parity(sector);
}
/* Encodes a MODE 2 sector.
* 'adr' is the current physical sector address
* 'sector' must be 2352 byte wide containing 2336 bytes user data at
* offset 16
*/
void lec_encode_mode2_sector(u_int32_t adr, u_int8_t *sector)
{
set_sync_pattern(sector);
set_sector_header(2, adr, sector);
}
/* Encodes a XA form 1 sector.
* 'adr' is the current physical sector address
* 'sector' must be 2352 byte wide containing 2048+8 bytes user data at
* offset 16
*/
void lec_encode_mode2_form1_sector(u_int32_t adr, u_int8_t *sector)
{
set_sync_pattern(sector);
calc_mode2_form1_edc(sector);
/* P/Q partiy must not contain the sector header so clear it */
sector[LEC_HEADER_OFFSET] =
sector[LEC_HEADER_OFFSET + 1] =
sector[LEC_HEADER_OFFSET + 2] =
sector[LEC_HEADER_OFFSET + 3] = 0;
calc_P_parity(sector);
calc_Q_parity(sector);
/* finally add the sector header */
set_sector_header(2, adr, sector);
}
/* Encodes a XA form 2 sector.
* 'adr' is the current physical sector address
* 'sector' must be 2352 byte wide containing 2324+8 bytes user data at
* offset 16
*/
void lec_encode_mode2_form2_sector(u_int32_t adr, u_int8_t *sector)
{
set_sync_pattern(sector);
calc_mode2_form2_edc(sector);
set_sector_header(2, adr, sector);
}
/* Scrambles and byte swaps an encoded sector.
* 'sector' must be 2352 byte wide.
*/
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;
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++) {
/* 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

@ -1,77 +0,0 @@
/* cdrdao - write audio CD-Rs in disc-at-once mode
*
* Copyright (C) 1998-2002 Andreas Mueller <mueller@daneb.ping.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef __LEC_H__
#define __LEC_H__
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <sys/types.h>
#include <inttypes.h>
typedef uint32_t u_int32_t;
typedef uint16_t u_int16_t;
typedef uint8_t u_int8_t;
#ifndef TRUE
#define TRUE 1
#endif
/* Encodes a MODE 0 sector.
* 'adr' is the current physical sector address
* 'sector' must be 2352 byte wide
*/
void lec_encode_mode0_sector(u_int32_t adr, u_int8_t *sector);
/* Encodes a MODE 1 sector.
* 'adr' is the current physical sector address
* 'sector' must be 2352 byte wide containing 2048 bytes user data at
* offset 16
*/
void lec_encode_mode1_sector(u_int32_t adr, u_int8_t *sector);
/* Encodes a MODE 2 sector.
* 'adr' is the current physical sector address
* 'sector' must be 2352 byte wide containing 2336 bytes user data at
* offset 16
*/
void lec_encode_mode2_sector(u_int32_t adr, u_int8_t *sector);
/* Encodes a XA form 1 sector.
* 'adr' is the current physical sector address
* 'sector' must be 2352 byte wide containing 2048+8 bytes user data at
* offset 16
*/
void lec_encode_mode2_form1_sector(u_int32_t adr, u_int8_t *sector);
/* Encodes a XA form 2 sector.
* 'adr' is the current physical sector address
* 'sector' must be 2352 byte wide containing 2324+8 bytes user data at
* offset 16
*/
void lec_encode_mode2_form2_sector(u_int32_t adr, u_int8_t *sector);
/* Scrambles and byte swaps an encoded sector.
* 'sector' must be 2352 byte wide.
*/
void lec_scramble(u_int8_t *sector);
#endif

Some files were not shown because too many files have changed in this diff Show More