diff --git a/psx/mednadisc/FileStream.cpp b/psx/mednadisc/FileStream.cpp deleted file mode 100644 index 61b5d5ca326..00000000000 --- a/psx/mednadisc/FileStream.cpp +++ /dev/null @@ -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 -#include -#include -#include -//#include -#include -#include - -//work around gettext -#define _(X) X - -#ifdef _MSC_VER -#include -#include -// 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 -#include -#include -#include -#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::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::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); -} - diff --git a/psx/mednadisc/FileStream.h b/psx/mednadisc/FileStream.h deleted file mode 100644 index 3066eb6994a..00000000000 --- a/psx/mednadisc/FileStream.h +++ /dev/null @@ -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 -#include - -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 diff --git a/psx/mednadisc/Mednadisc.cpp b/psx/mednadisc/Mednadisc.cpp deleted file mode 100644 index bcc3cd73d7c..00000000000 --- a/psx/mednadisc/Mednadisc.cpp +++ /dev/null @@ -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; -} diff --git a/psx/mednadisc/Mednadisc.h b/psx/mednadisc/Mednadisc.h deleted file mode 100644 index 1c080adb163..00000000000 --- a/psx/mednadisc/Mednadisc.h +++ /dev/null @@ -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); \ No newline at end of file diff --git a/psx/mednadisc/MemoryStream.cpp b/psx/mednadisc/MemoryStream.cpp deleted file mode 100644 index 4dd932f0467..00000000000 --- a/psx/mednadisc/MemoryStream.cpp +++ /dev/null @@ -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 -#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); -} - diff --git a/psx/mednadisc/MemoryStream.h b/psx/mednadisc/MemoryStream.h deleted file mode 100644 index 0b245482e53..00000000000 --- a/psx/mednadisc/MemoryStream.h +++ /dev/null @@ -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 diff --git a/psx/mednadisc/Stream.cpp b/psx/mednadisc/Stream.cpp deleted file mode 100644 index 67389e86d5b..00000000000 --- a/psx/mednadisc/Stream.cpp +++ /dev/null @@ -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 -#include -#include - -#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(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); -} - diff --git a/psx/mednadisc/Stream.h b/psx/mednadisc/Stream.h deleted file mode 100644 index 3830f5c6e61..00000000000 --- a/psx/mednadisc/Stream.h +++ /dev/null @@ -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 - -#include // For SEEK_* defines, which we will use in Stream out of FORCE OF HABIT. -#include - -#include - -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 - INLINE T get_NE(void) - { - T ret; - - read(&ret, sizeof(ret)); - - return ret; - } - - - template - 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 - INLINE void put_NE(T c) - { - write(&c, sizeof(c)); - } - - template - 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 - INLINE T get_LE(void) - { - #ifdef LSB_FIRST - return get_NE(); - #else - return get_RE(); - #endif - } - - template - INLINE void put_LE(T c) - { - #ifdef LSB_FIRST - return put_NE(c); - #else - return put_RE(c); - #endif - } - - template - INLINE T get_BE(void) - { - #ifndef LSB_FIRST - return get_NE(); - #else - return get_RE(); - #endif - } - - template - INLINE void put_BE(T c) - { - #ifndef LSB_FIRST - return put_NE(c); - #else - return put_RE(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 diff --git a/psx/mednadisc/audioreader.cpp b/psx/mednadisc/audioreader.cpp deleted file mode 100644 index 20d1fe23cab..00000000000 --- a/psx/mednadisc/audioreader.cpp +++ /dev/null @@ -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 -#include - -#include "../tremor/ivorbisfile.h" -#include "../mpcdec/mpcdec.h" - -#ifdef HAVE_LIBSNDFILE -#include -#endif - -#ifdef HAVE_OPUSFILE -#include "audioreader_opus.h" -#endif - -#include -#include -#include - -#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); -} - diff --git a/psx/mednadisc/audioreader.h b/psx/mednadisc/audioreader.h deleted file mode 100644 index 014a3e48d37..00000000000 --- a/psx/mednadisc/audioreader.h +++ /dev/null @@ -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 diff --git a/psx/mednadisc/bizhawk/mednadisc.sln b/psx/mednadisc/bizhawk/mednadisc.sln deleted file mode 100644 index 948842cfccc..00000000000 --- a/psx/mednadisc/bizhawk/mednadisc.sln +++ /dev/null @@ -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 diff --git a/psx/mednadisc/bizhawk/mednadisc.vcxproj b/psx/mednadisc/bizhawk/mednadisc.vcxproj deleted file mode 100644 index f912984e5c4..00000000000 --- a/psx/mednadisc/bizhawk/mednadisc.vcxproj +++ /dev/null @@ -1,138 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - {5F35CAFC-6208-4FBE-AD17-0E69BA3F70EC} - Win32Proj - mednadisc - - - - DynamicLibrary - true - Unicode - - - DynamicLibrary - false - true - Unicode - - - - - - - - - - - - - true - $(ProjectDir)..\..\..\output\dll\ - - - false - $(ProjectDir)\..\..\..\output\dll\ - - - - NotUsing - Level3 - Disabled - TRIO_PUBLIC=;TRIO_PRIVATE=static;EW_EXPORT;_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_WINDOWS;_USRDLL;OCTOSHOCK_EXPORTS;%(PreprocessorDefinitions) - ../emuware/msvc;.. - - - - - true - false - - - Windows - true - - - - - Level3 - NotUsing - MaxSpeed - true - true - _CRT_SECURE_NO_WARNINGS;TRIO_PUBLIC=;TRIO_PRIVATE=static;EW_EXPORT;WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) - - - - - true - ../emuware/msvc;.. - - - Windows - true - true - true - - - - - - \ No newline at end of file diff --git a/psx/mednadisc/bizhawk/mednadisc.vcxproj.filters b/psx/mednadisc/bizhawk/mednadisc.vcxproj.filters deleted file mode 100644 index 2b0d826726f..00000000000 --- a/psx/mednadisc/bizhawk/mednadisc.vcxproj.filters +++ /dev/null @@ -1,119 +0,0 @@ - - - - - {a3ffd332-9644-473f-b3b6-d31b08be5256} - - - {99e57b88-966c-4695-8f5c-1db6345b1b26} - - - {798fa5bd-6381-487a-99d2-35a15a6da439} - - - {a43930f5-41a5-4b2b-92ef-bd90f9716127} - - - - - cdrom - - - cdrom - - - cdrom - - - cdrom - - - cdrom - - - cdrom - - - cdrom - - - cdrom - - - cdrom - - - cdrom - - - - - - - - string - - - - - trio - - - cdrom - - - trio - - - trio - - - - - cdrom - - - cdrom - - - cdrom - - - cdrom - - - cdrom - - - cdrom - - - cdrom - - - cdrom - - - cdrom - - - emuware - - - - - - - - string - - - - - trio - - - cdrom - - - \ No newline at end of file diff --git a/psx/mednadisc/cdrom/CDAFReader.cpp b/psx/mednadisc/cdrom/CDAFReader.cpp deleted file mode 100644 index 37bafe358c2..00000000000 --- a/psx/mednadisc/cdrom/CDAFReader.cpp +++ /dev/null @@ -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;idxrewind(); - return f(fp); - } - catch(int i) - { - - } - } - - return(NULL); -} - diff --git a/psx/mednadisc/cdrom/CDAFReader.h b/psx/mednadisc/cdrom/CDAFReader.h deleted file mode 100644 index 9ac08802941..00000000000 --- a/psx/mednadisc/cdrom/CDAFReader.h +++ /dev/null @@ -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 diff --git a/psx/mednadisc/cdrom/CDAFReader_MPC.cpp b/psx/mednadisc/cdrom/CDAFReader_MPC.cpp deleted file mode 100644 index 3f26026c17f..00000000000 --- a/psx/mednadisc/cdrom/CDAFReader_MPC.cpp +++ /dev/null @@ -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 -#include "CDAFReader.h" -#include "CDAFReader_MPC.h" - -#if 0 - #include -#else - #include -#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); -} diff --git a/psx/mednadisc/cdrom/CDAFReader_MPC.h b/psx/mednadisc/cdrom/CDAFReader_MPC.h deleted file mode 100644 index 6580fba79cf..00000000000 --- a/psx/mednadisc/cdrom/CDAFReader_MPC.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef __MDFN_CDAFREADER_MPC_H -#define __MDFN_CDAFREADER_MPC_H - -CDAFReader* CDAFR_MPC_Open(Stream* fp); - -#endif diff --git a/psx/mednadisc/cdrom/CDAFReader_SF.cpp b/psx/mednadisc/cdrom/CDAFReader_SF.cpp deleted file mode 100644 index 9abc6a6f0d3..00000000000 --- a/psx/mednadisc/cdrom/CDAFReader_SF.cpp +++ /dev/null @@ -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 -#include "CDAFReader.h" -#include "CDAFReader_SF.h" - -#include - -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); -} diff --git a/psx/mednadisc/cdrom/CDAFReader_SF.h b/psx/mednadisc/cdrom/CDAFReader_SF.h deleted file mode 100644 index 2ab145bb37d..00000000000 --- a/psx/mednadisc/cdrom/CDAFReader_SF.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef __MDFN_CDAFREADER_SF_H -#define __MDFN_CDAFREADER_SF_H - -CDAFReader* CDAFR_SF_Open(Stream* fp); - -#endif diff --git a/psx/mednadisc/cdrom/CDAFReader_Vorbis.cpp b/psx/mednadisc/cdrom/CDAFReader_Vorbis.cpp deleted file mode 100644 index 5975b215b28..00000000000 --- a/psx/mednadisc/cdrom/CDAFReader_Vorbis.cpp +++ /dev/null @@ -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 -#include "CDAFReader.h" -#include "CDAFReader_Vorbis.h" - -#if 0 - #include -#else - #include -#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); -} diff --git a/psx/mednadisc/cdrom/CDAFReader_Vorbis.h b/psx/mednadisc/cdrom/CDAFReader_Vorbis.h deleted file mode 100644 index f4a8c55b4f0..00000000000 --- a/psx/mednadisc/cdrom/CDAFReader_Vorbis.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef __MDFN_CDAFREADER_VORBIS_H -#define __MDFN_CDAFREADER_VORBIS_H - -CDAFReader* CDAFR_Vorbis_Open(Stream* fp); - -#endif - diff --git a/psx/mednadisc/cdrom/CDAccess.cpp b/psx/mednadisc/cdrom/CDAccess.cpp deleted file mode 100644 index 14cf659adf0..00000000000 --- a/psx/mednadisc/cdrom/CDAccess.cpp +++ /dev/null @@ -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; -} - diff --git a/psx/mednadisc/cdrom/CDAccess.h b/psx/mednadisc/cdrom/CDAccess.h deleted file mode 100644 index fd4338d15ea..00000000000 --- a/psx/mednadisc/cdrom/CDAccess.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef __MDFN_CDROMFILE_H -#define __MDFN_CDROMFILE_H - -#include -#include - -#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 diff --git a/psx/mednadisc/cdrom/CDAccess_CCD.cpp b/psx/mednadisc/cdrom/CDAccess_CCD.cpp deleted file mode 100644 index 0ec073e17dd..00000000000 --- a/psx/mednadisc/cdrom/CDAccess_CCD.cpp +++ /dev/null @@ -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 - -//wrapper to repair gettext stuff -#define _(X) X - -#include -#include -#include - -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 CCD_Section; - -template -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::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 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(ds, "TOCENTRIES"); - unsigned num_sessions = CCD_ReadInt(ds, "SESSIONS"); - bool data_tracks_scrambled = CCD_ReadInt(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(ts, "SESSION"); - uint8 point = CCD_ReadInt(ts, "POINT"); - uint8 adr = CCD_ReadInt(ts, "ADR"); - uint8 control = CCD_ReadInt(ts, "CONTROL"); - uint8 pmin = CCD_ReadInt(ts, "PMIN"); - uint8 psec = CCD_ReadInt(ts, "PSEC"); - //uint8 pframe = CCD_ReadInt(ts, "PFRAME"); - signed plba = CCD_ReadInt(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; -} - diff --git a/psx/mednadisc/cdrom/CDAccess_CCD.h b/psx/mednadisc/cdrom/CDAccess_CCD.h deleted file mode 100644 index ffc2efa9957..00000000000 --- a/psx/mednadisc/cdrom/CDAccess_CCD.h +++ /dev/null @@ -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 - -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 img_stream; - std::unique_ptr sub_data; - - size_t img_numsectors; - CDUtility::TOC tocd; -}; diff --git a/psx/mednadisc/cdrom/CDAccess_Image.cpp b/psx/mednadisc/cdrom/CDAccess_Image.cpp deleted file mode 100644 index 8e7ae71a372..00000000000 --- a/psx/mednadisc/cdrom/CDAccess_Image.cpp +++ /dev/null @@ -1,1319 +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 and TODO: - - POSTGAP in CUE sheets may not be handled properly, should the directive automatically increment the index number? - - INDEX nn where 02 <= nn <= 99 is not supported in CUE sheets. - - TOC reading code is extremely barebones, leaving out support for more esoteric features. - - A PREGAP statement in the first track definition in a CUE sheet may not work properly(depends on what is proper); - it will be added onto the implicit default 00:02:00 of pregap. -*/ - -#include "emuware/emuware.h" - -//undo gettext stuff -#define _(X) (X) - -#include - -#include -#include -#include -#include -#include - -#include "general.h" -#include "string/trim.h" -#include "endian.h" -#include "FileStream.h" -#include "MemoryStream.h" - -#include "CDAccess.h" -#include "CDAccess_Image.h" - -#include "CDAFReader.h" - -#include - -using namespace CDUtility; - -enum -{ - CDRF_SUBM_NONE = 0, - CDRF_SUBM_RW = 1, - CDRF_SUBM_RW_RAW = 2 -}; - -// Disk-image(rip) track/sector formats -enum -{ - DI_FORMAT_AUDIO = 0x00, - DI_FORMAT_MODE1 = 0x01, - DI_FORMAT_MODE1_RAW = 0x02, - DI_FORMAT_MODE2 = 0x03, - DI_FORMAT_MODE2_FORM1 = 0x04, - DI_FORMAT_MODE2_FORM2 = 0x05, - DI_FORMAT_MODE2_RAW = 0x06, - DI_FORMAT_CDI_RAW = 0x07, - _DI_FORMAT_COUNT -}; - -static const int32 DI_Size_Table[8] = -{ - 2352, // Audio - 2048, // MODE1 - 2352, // MODE1 RAW - 2336, // MODE2 - 2048, // MODE2 Form 1 - 2324, // Mode 2 Form 2 - 2352, // MODE2 RAW - 2352, // CD-I RAW -}; - -static const char *DI_CDRDAO_Strings[8] = -{ - "AUDIO", - "MODE1", - "MODE1_RAW", - "MODE2", - "MODE2_FORM1", - "MODE2_FORM2", - "MODE2_RAW", - "CDI_RAW" -}; - -static const char *DI_CUE_Strings[8] = -{ - "AUDIO", - "MODE1/2048", - "MODE1/2352", - "MODE2/2336", // FIXME: A guess - "MODE2/2048", // FIXME: A guess - "MODE2/2324", // FIXME: A guess - "MODE2/2352", // FIXME: A guess - "CDI/2352", -}; - -// Should return an offset to the start of the next argument(past any whitespace), or if there isn't a next argument, -// it'll return the length of the src string. -static size_t UnQuotify(const std::string &src, size_t source_offset, std::string &dest, bool parse_quotes = true) -{ - const size_t source_len = src.length(); - bool in_quote = 0; - bool already_normal = 0; - - dest.clear(); - - while(source_offset < source_len) - { - if(src[source_offset] == ' ' || src[source_offset] == '\t') - { - if(!in_quote) - { - if(already_normal) // Trailing whitespace(IE we're done with this argument) - break; - else // Leading whitespace, ignore it. - { - source_offset++; - continue; - } - } - } - - if(src[source_offset] == '"' && parse_quotes) - { - if(in_quote) - { - source_offset++; -// Not sure which behavior is most useful(or correct :b). -#if 0 - in_quote = false; - already_normal = true; -#else - break; -#endif - } - else - in_quote = 1; - } - else - { - dest.push_back(src[source_offset]); - already_normal = 1; - } - source_offset++; - } - - while(source_offset < source_len) - { - if(src[source_offset] != ' ' && src[source_offset] != '\t') - break; - - source_offset++; - } - - return source_offset; -} - -uint32 CDAccess_Image::GetSectorCount(CDRFILE_TRACK_INFO *track) -{ - if(track->DIFormat == DI_FORMAT_AUDIO) - { - if(track->AReader) - return(((track->AReader->FrameCount() * 4) - track->FileOffset) / 2352); - else - { - const int64 size = track->fp->size(); - - //printf("%d %d %d\n", (int)stat_buf.st_size, (int)track->FileOffset, (int)stat_buf.st_size - (int)track->FileOffset); - if(track->SubchannelMode) - return((size - track->FileOffset) / (2352 + 96)); - else - return((size - track->FileOffset) / 2352); - } - } - else - { - const int64 size = track->fp->size(); - - return((size - track->FileOffset) / DI_Size_Table[track->DIFormat]); - } - - return(0); -} - -void CDAccess_Image::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 &toc_streamcache) -{ - long offset = 0; // In bytes! - long tmp_long; - int m, s, f; - uint32 sector_mult; - long sectors; - std::map::iterator ribbit; - - ribbit = toc_streamcache.find(filename); - - if(ribbit != toc_streamcache.end()) - { - track->FirstFileInstance = 0; - - track->fp = ribbit->second; - } - else - { - std::string efn; - - track->FirstFileInstance = 1; - - efn = MDFN_EvalFIP(base_dir, filename); - - if(image_memcache) - track->fp = new MemoryStream(new FileStream(efn, FileStream::MODE_READ)); - else - track->fp = new FileStream(efn, FileStream::MODE_READ); - - toc_streamcache[filename] = track->fp; - } - - if(filename.length() >= 4 && !strcasecmp(filename.c_str() + filename.length() - 4, ".wav")) - { - track->AReader = CDAFR_Open(track->fp); - - if(!track->AReader) - throw MDFN_Error(0, "TODO ERROR"); - } - - sector_mult = DI_Size_Table[track->DIFormat]; - - if(track->SubchannelMode) - sector_mult += 96; - - if(binoffset && trio_sscanf(binoffset, "%ld", &tmp_long) == 1) - { - offset += tmp_long; - } - - if(msfoffset && trio_sscanf(msfoffset, "%d:%d:%d", &m, &s, &f) == 3) - { - offset += ((m * 60 + s) * 75 + f) * sector_mult; - } - - track->FileOffset = offset; // Make sure this is set before calling GetSectorCount()! - sectors = GetSectorCount(track); - //printf("Track: %d, offset: %ld, %ld\n", tracknum, offset, sectors); - - if(length) - { - tmp_long = sectors; - - if(trio_sscanf(length, "%d:%d:%d", &m, &s, &f) == 3) - tmp_long = (m * 60 + s) * 75 + f; - else if(track->DIFormat == DI_FORMAT_AUDIO) - { - char *endptr = NULL; - - tmp_long = strtol(length, &endptr, 10); - - // Error? - if(endptr == length) - { - tmp_long = sectors; - } - else - tmp_long /= 588; - - } - - if(tmp_long > sectors) - { - throw MDFN_Error(0, _("Length specified in TOC file for track %d is too large by %ld sectors!\n"), tracknum, (long)(tmp_long - sectors)); - } - sectors = tmp_long; - } - - track->sectors = sectors; -} - -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'; - } - } -} - -#if 0 -std::string MDFN_toupper(const std::string &str) -{ - const size_t len = str.length(); - std::string new_str; - - new_str.reserve(len); - - for(size_t x = 0; x < len; x++) - { - int c = str[x]; - - if(c >= 'a' && c <= 'z') - c = c - 'a' + 'A'; - - new_str.push_back(c); - } -} -#endif - -void CDAccess_Image::LoadSBI(const std::string& sbi_path) -{ - //test whether it exists - FILE* inf = fopen(sbi_path.c_str(),"rb"); - if(inf == NULL) - return; - - printf(_("Loading SBI file \"%s\"...\n"), sbi_path.c_str()); - - { - //MDFN_AutoIndent aind(1); - - try - { - FileStream sbis(sbi_path, FileStream::MODE_READ); - uint8 header[4]; - uint8 ed[4 + 10]; - uint8 tmpq[12]; - - sbis.read(header, 4); - - if(memcmp(header, "SBI\0", 4)) - throw MDFN_Error(0, _("Not recognized a valid SBI file.")); - - while(sbis.read(ed, sizeof(ed), false) == sizeof(ed)) - { - if(!BCD_is_valid(ed[0]) || !BCD_is_valid(ed[1]) || !BCD_is_valid(ed[2])) - throw MDFN_Error(0, _("Bad BCD MSF offset in SBI file: %02x:%02x:%02x"), ed[0], ed[1], ed[2]); - - if(ed[3] != 0x01) - throw MDFN_Error(0, _("Unrecognized boogly oogly in SBI file: %02x"), ed[3]); - - memcpy(tmpq, &ed[4], 10); - - // - subq_generate_checksum(tmpq); - tmpq[10] ^= 0xFF; - tmpq[11] ^= 0xFF; - // - - //printf("%02x:%02x:%02x --- ", ed[0], ed[1], ed[2]); - //for(unsigned i = 0; i < 12; i++) - // printf("%02x ", tmpq[i]); - //printf("\n"); - - uint32 aba = AMSF_to_ABA(BCD_to_U8(ed[0]), BCD_to_U8(ed[1]), BCD_to_U8(ed[2])); - - memcpy(SubQReplaceMap[aba].data(), tmpq, 12); - } - printf(_("Loaded Q subchannel replacements for %zu sectors.\n"), SubQReplaceMap.size()); - } - catch(MDFN_Error &e) - { - if(e.GetErrno() != ENOENT) - throw; - else - printf(_("Error: %s\n"), e.what()); - } - catch(std::exception &e) - { - throw; - } - } -} - -static void StringToMSF(const char* str, unsigned* m, unsigned* s, unsigned* f) -{ - if(trio_sscanf(str, "%u:%u:%u", m, s, f) != 3) - throw MDFN_Error(0, _("M:S:F time \"%s\" is malformed."), str); - - if(*m > 99 || *s > 59 || *f > 74) - throw MDFN_Error(0, _("M:S:F time \"%s\" contains component(s) out of range."), str); -} - -void CDAccess_Image::ImageOpen(const std::string& path, bool image_memcache) -{ - MemoryStream fp(new FileStream(path, FileStream::MODE_READ)); - static const unsigned max_args = 4; - std::string linebuf; - std::string cmdbuf, args[max_args]; - bool IsTOC = FALSE_0; - int32 active_track = -1; - int32 AutoTrackInc = 1; // For TOC - CDRFILE_TRACK_INFO TmpTrack; - std::string file_base, file_ext; - std::map toc_streamcache; - - disc_type = DISC_TYPE_CDDA_OR_M1; - memset(&TmpTrack, 0, sizeof(TmpTrack)); - - MDFN_GetFilePathComponents(path, &base_dir, &file_base, &file_ext); - - if(!strcasecmp(file_ext.c_str(), ".toc")) - { - printf(_("TOC file detected.\n")); - IsTOC = true; - } - - // Check for annoying UTF-8 BOM. - if(!IsTOC) - { - uint8 bom_tmp[3]; - - if(fp.read(bom_tmp, 3, false) == 3 && bom_tmp[0] == 0xEF && bom_tmp[1] == 0xBB && bom_tmp[2] == 0xBF) - { - // Print an annoying error message, but don't actually error out. - printf(_("UTF-8 BOM detected at start of CUE sheet.")); - } - else - fp.seek(0, SEEK_SET); - } - - - // Assign opposite maximum values so our tests will work! - FirstTrack = 99; - LastTrack = 0; - - linebuf.reserve(1024); - while(fp.get_line(linebuf) >= 0) - { - unsigned argcount = 0; - - if(IsTOC) - { - // Handle TOC format comments - size_t ss_loc = linebuf.find("//"); - - if(ss_loc != std::string::npos) - linebuf.resize(ss_loc); - } - - // Call trim AFTER we handle TOC-style comments, so we'll be sure to remove trailing whitespace in lines like: MONKEY // BABIES - MDFN_trim(linebuf); - - if(linebuf.length() == 0) // Skip blank lines. - continue; - - // Grab command and arguments. - { - size_t offs = 0; - - offs = UnQuotify(linebuf, offs, cmdbuf, false); - for(argcount = 0; argcount < max_args && offs < linebuf.length(); argcount++) - offs = UnQuotify(linebuf, offs, args[argcount]); - - // Make sure unused arguments are cleared out so we don't have inter-line leaks! - for(unsigned x = argcount; x < max_args; x++) - args[x].clear(); - - MDFN_strtoupper(cmdbuf); - } - - //printf("%s\n", cmdbuf.c_str()); //: %s %s %s %s\n", cmdbuf.c_str(), args[0].c_str(), args[1].c_str(), args[2].c_str(), args[3].c_str()); - - if(IsTOC) - { - if(cmdbuf == "TRACK") - { - if(active_track >= 0) - { - memcpy(&Tracks[active_track], &TmpTrack, sizeof(TmpTrack)); - memset(&TmpTrack, 0, sizeof(TmpTrack)); - active_track = -1; - } - - if(AutoTrackInc > 99) - { - throw(MDFN_Error(0, _("Invalid track number: %d"), AutoTrackInc)); - } - - active_track = AutoTrackInc++; - if(active_track < FirstTrack) - FirstTrack = active_track; - if(active_track > LastTrack) - LastTrack = active_track; - - int format_lookup; - for(format_lookup = 0; format_lookup < _DI_FORMAT_COUNT; format_lookup++) - { - if(!strcasecmp(args[0].c_str(), DI_CDRDAO_Strings[format_lookup])) - { - TmpTrack.DIFormat = format_lookup; - break; - } - } - - if(format_lookup == _DI_FORMAT_COUNT) - { - throw(MDFN_Error(0, _("Invalid track format: %s"), args[0].c_str())); - } - - if(TmpTrack.DIFormat == DI_FORMAT_AUDIO) - TmpTrack.RawAudioMSBFirst = TRUE_1; // Silly cdrdao... - - if(!strcasecmp(args[1].c_str(), "RW")) - { - TmpTrack.SubchannelMode = CDRF_SUBM_RW; - throw(MDFN_Error(0, _("\"RW\" format subchannel data not supported, only \"RW_RAW\" is!"))); - } - else if(!strcasecmp(args[1].c_str(), "RW_RAW")) - TmpTrack.SubchannelMode = CDRF_SUBM_RW_RAW; - - } // end to TRACK - else if(cmdbuf == "SILENCE") - { - //throw MDFN_Error(0, _("Unsupported directive: %s"), cmdbuf.c_str()); - } - else if(cmdbuf == "ZERO") - { - //throw MDFN_Error(0, _("Unsupported directive: %s"), cmdbuf.c_str()); - } - else if(cmdbuf == "FIFO") - { - throw MDFN_Error(0, _("Unsupported directive: %s"), cmdbuf.c_str()); - } - else if(cmdbuf == "FILE" || cmdbuf == "AUDIOFILE") - { - const char *binoffset = NULL; - const char *msfoffset = NULL; - const char *length = NULL; - - if(args[1].c_str()[0] == '#') - { - binoffset = args[1].c_str() + 1; - msfoffset = args[2].c_str(); - length = args[3].c_str(); - } - else - { - msfoffset = args[1].c_str(); - length = args[2].c_str(); - } - //printf("%s, %s, %s, %s\n", args[0].c_str(), binoffset, msfoffset, length); - ParseTOCFileLineInfo(&TmpTrack, active_track, args[0], binoffset, msfoffset, length, image_memcache, toc_streamcache); - } - else if(cmdbuf == "DATAFILE") - { - const char *binoffset = NULL; - const char *length = NULL; - - if(args[1].c_str()[0] == '#') - { - binoffset = args[1].c_str() + 1; - length = args[2].c_str(); - } - else - length = args[1].c_str(); - - ParseTOCFileLineInfo(&TmpTrack, active_track, args[0], binoffset, NULL, length, image_memcache, toc_streamcache); - } - else if(cmdbuf == "INDEX") - { - - } - else if(cmdbuf == "PREGAP") - { - if(active_track < 0) - { - throw(MDFN_Error(0, _("Command %s is outside of a TRACK definition!\n"), cmdbuf.c_str())); - } - - unsigned int m,s,f; - - StringToMSF(args[0].c_str(), &m, &s, &f); - - TmpTrack.pregap = (m * 60 + s) * 75 + f; - } // end to PREGAP - else if(cmdbuf == "START") - { - if(active_track < 0) - { - throw(MDFN_Error(0, _("Command %s is outside of a TRACK definition!\n"), cmdbuf.c_str())); - } - - unsigned int m,s,f; - - StringToMSF(args[0].c_str(), &m, &s, &f); - - TmpTrack.pregap = (m * 60 + s) * 75 + f; - } - else if(cmdbuf == "TWO_CHANNEL_AUDIO") - { - TmpTrack.subq_control &= ~SUBQ_CTRLF_4CH; - } - else if(cmdbuf == "FOUR_CHANNEL_AUDIO") - { - TmpTrack.subq_control |= SUBQ_CTRLF_4CH; - } - else if(cmdbuf == "NO") - { - MDFN_strtoupper(args[0]); - - if(args[0] == "COPY") - { - TmpTrack.subq_control &= ~SUBQ_CTRLF_DCP; - } - else if(args[0] == "PRE_EMPHASIS") - { - TmpTrack.subq_control &= ~SUBQ_CTRLF_PRE; - } - else - { - throw MDFN_Error(0, _("Unsupported argument to \"NO\" directive: %s"), args[0].c_str()); - } - } - else if(cmdbuf == "COPY") - { - TmpTrack.subq_control |= SUBQ_CTRLF_DCP; - } - else if(cmdbuf == "PRE_EMPHASIS") - { - TmpTrack.subq_control |= SUBQ_CTRLF_PRE; - } - // TODO: Confirm that these are taken from the TOC of the disc, and not synthesized by cdrdao. - else if(cmdbuf == "CD_DA") - disc_type = DISC_TYPE_CDDA_OR_M1; - else if(cmdbuf == "CD_ROM") - disc_type = DISC_TYPE_CDDA_OR_M1; - else if(cmdbuf == "CD_ROM_XA") - disc_type = DISC_TYPE_CD_XA; - else - { - //throw MDFN_Error(0, _("Unsupported directive: %s"), cmdbuf.c_str()); - } - // TODO: CATALOG - - } /*********** END TOC HANDLING ************/ - else // now for CUE sheet handling - { - if(cmdbuf == "FILE") - { - if(active_track >= 0) - { - memcpy(&Tracks[active_track], &TmpTrack, sizeof(TmpTrack)); - memset(&TmpTrack, 0, sizeof(TmpTrack)); - active_track = -1; - } - - std::string efn = MDFN_EvalFIP(base_dir, args[0]); - TmpTrack.fp = new FileStream(efn, FileStream::MODE_READ); - TmpTrack.FirstFileInstance = 1; - - if(image_memcache) - TmpTrack.fp = new MemoryStream(TmpTrack.fp); - - if(!strcasecmp(args[1].c_str(), "BINARY")) - { - //TmpTrack.Format = TRACK_FORMAT_DATA; - //struct stat stat_buf; - //fstat(fileno(TmpTrack.fp), &stat_buf); - //TmpTrack.sectors = stat_buf.st_size; // / 2048; - } - else if(!strcasecmp(args[1].c_str(), "OGG") || !strcasecmp(args[1].c_str(), "VORBIS") || !strcasecmp(args[1].c_str(), "WAVE") || !strcasecmp(args[1].c_str(), "WAV") || !strcasecmp(args[1].c_str(), "PCM") - || !strcasecmp(args[1].c_str(), "MPC") || !strcasecmp(args[1].c_str(), "MP+")) - { - TmpTrack.AReader = CDAFR_Open(TmpTrack.fp); - if(!TmpTrack.AReader) - { - throw(MDFN_Error(0, _("Unsupported audio track file format: %s\n"), args[0].c_str())); - } - } - else - { - throw(MDFN_Error(0, _("Unsupported track format: %s\n"), args[1].c_str())); - } - } - else if(cmdbuf == "TRACK") - { - if(active_track >= 0) - { - memcpy(&Tracks[active_track], &TmpTrack, sizeof(TmpTrack)); - TmpTrack.FirstFileInstance = 0; - TmpTrack.pregap = 0; - TmpTrack.pregap_dv = 0; - TmpTrack.postgap = 0; - TmpTrack.index[0] = -1; - TmpTrack.index[1] = 0; - } - active_track = atoi(args[0].c_str()); - - if(active_track < 1 || active_track > 99) - { - throw(MDFN_Error(0, _("Invalid track number: %d\n"), active_track)); - } - - if(active_track < FirstTrack) - FirstTrack = active_track; - if(active_track > LastTrack) - LastTrack = active_track; - - int format_lookup; - for(format_lookup = 0; format_lookup < _DI_FORMAT_COUNT; format_lookup++) - { - if(!strcasecmp(args[1].c_str(), DI_CUE_Strings[format_lookup])) - { - TmpTrack.DIFormat = format_lookup; - break; - } - } - - if(format_lookup == _DI_FORMAT_COUNT) - { - throw(MDFN_Error(0, _("Invalid track format: %s\n"), args[1].c_str())); - } - } - else if(cmdbuf == "INDEX") - { - if(active_track >= 0) - { - unsigned int m,s,f; - - StringToMSF(args[1].c_str(), &m, &s, &f); - - if(!strcasecmp(args[0].c_str(), "01") || !strcasecmp(args[0].c_str(), "1")) - TmpTrack.index[1] = (m * 60 + s) * 75 + f; - else if(!strcasecmp(args[0].c_str(), "00") || !strcasecmp(args[0].c_str(), "0")) - TmpTrack.index[0] = (m * 60 + s) * 75 + f; - } - } - else if(cmdbuf == "PREGAP") - { - if(active_track >= 0) - { - unsigned int m,s,f; - - StringToMSF(args[0].c_str(), &m, &s, &f); - - TmpTrack.pregap = (m * 60 + s) * 75 + f; - } - } - else if(cmdbuf == "POSTGAP") - { - if(active_track >= 0) - { - unsigned int m,s,f; - - StringToMSF(args[0].c_str(), &m, &s, &f); - - TmpTrack.postgap = (m * 60 + s) * 75 + f; - } - } - else if(cmdbuf == "REM") - { - - } - else if(cmdbuf == "FLAGS") - { - TmpTrack.subq_control &= ~(SUBQ_CTRLF_PRE | SUBQ_CTRLF_DCP | SUBQ_CTRLF_4CH); - for(unsigned i = 0; i < argcount; i++) - { - if(args[i] == "DCP") - { - TmpTrack.subq_control |= SUBQ_CTRLF_DCP; - } - else if(args[i] == "4CH") - { - TmpTrack.subq_control |= SUBQ_CTRLF_4CH; - } - else if(args[i] == "PRE") - { - TmpTrack.subq_control |= SUBQ_CTRLF_PRE; - } - else if(args[i] == "SCMS") - { - // Not implemented, likely pointless. PROBABLY indicates that the copy bit of the subchannel Q control field is supposed to - // alternate between 1 and 0 at 9.375 Hz(four 1, four 0, four 1, four 0, etc.). - } - else - { - throw MDFN_Error(0, _("Unknown CUE sheet \"FLAGS\" directive flag \"%s\".\n"), args[i].c_str()); - } - } - } - else if(cmdbuf == "CDTEXTFILE" || cmdbuf == "CATALOG" || cmdbuf == "ISRC" || - cmdbuf == "TITLE" || cmdbuf == "PERFORMER" || cmdbuf == "SONGWRITER") - { - printf(_("Unsupported CUE sheet directive: \"%s\".\n"), cmdbuf.c_str()); // FIXME, generic logger passed by pointer to constructor - } - else - { - throw MDFN_Error(0, _("Unknown CUE sheet directive \"%s\".\n"), cmdbuf.c_str()); - } - } // end of CUE sheet handling - } // end of fgets() loop - - if(active_track >= 0) - memcpy(&Tracks[active_track], &TmpTrack, sizeof(TmpTrack)); - - if(FirstTrack > LastTrack) - { - throw(MDFN_Error(0, _("No tracks found!\n"))); - } - - FirstTrack = FirstTrack; - NumTracks = 1 + LastTrack - FirstTrack; - - int32 RunningLBA = 0; - int32 LastIndex = 0; - long FileOffset = 0; - - RunningLBA -= 150; - Tracks[FirstTrack].pregap += 150; - - for(int x = FirstTrack; x < (FirstTrack + NumTracks); x++) - { - if(!Tracks[x].fp && !Tracks[x].AReader) - throw MDFN_Error(0, _("Missing track %u."), x); - - if(Tracks[x].DIFormat == DI_FORMAT_AUDIO) - Tracks[x].subq_control &= ~SUBQ_CTRLF_DATA; - else - Tracks[x].subq_control |= SUBQ_CTRLF_DATA; - - if(!IsTOC) // TOC-format disc_type calculation is handled differently. - { - if(disc_type != DISC_TYPE_CD_I) - { - switch(Tracks[x].DIFormat) - { - default: break; - - case DI_FORMAT_MODE2: - case DI_FORMAT_MODE2_FORM1: - case DI_FORMAT_MODE2_FORM2: - case DI_FORMAT_MODE2_RAW: - disc_type = DISC_TYPE_CD_XA; - break; - - case DI_FORMAT_CDI_RAW: - disc_type = DISC_TYPE_CD_I; - break; - } - } - } - - if(IsTOC) - { - RunningLBA += Tracks[x].pregap; - Tracks[x].LBA = RunningLBA; - RunningLBA += Tracks[x].sectors; - RunningLBA += Tracks[x].postgap; - } - else // else handle CUE sheet... - { - if(Tracks[x].FirstFileInstance) - { - LastIndex = 0; - FileOffset = 0; - } - - RunningLBA += Tracks[x].pregap; - - Tracks[x].pregap_dv = 0; - - if(Tracks[x].index[0] != -1) - Tracks[x].pregap_dv = Tracks[x].index[1] - Tracks[x].index[0]; - - FileOffset += Tracks[x].pregap_dv * DI_Size_Table[Tracks[x].DIFormat]; - - RunningLBA += Tracks[x].pregap_dv; - - Tracks[x].LBA = RunningLBA; - - // Make sure FileOffset this is set before the call to GetSectorCount() - Tracks[x].FileOffset = FileOffset; - Tracks[x].sectors = GetSectorCount(&Tracks[x]); - - if((x + 1) >= (FirstTrack + NumTracks) || Tracks[x+1].FirstFileInstance) - { - - } - else - { - // Fix the sector count if we have multiple tracks per one binary image file. - if(Tracks[x + 1].index[0] == -1) - Tracks[x].sectors = Tracks[x + 1].index[1] - Tracks[x].index[1]; - else - Tracks[x].sectors = Tracks[x + 1].index[0] - Tracks[x].index[1]; //Tracks[x + 1].index - Tracks[x].index; - } - - //printf("Poo: %d %d\n", x, Tracks[x].sectors); - RunningLBA += Tracks[x].sectors; - RunningLBA += Tracks[x].postgap; - - //printf("%d, %ld %d %d %d %d\n", x, FileOffset, Tracks[x].index, Tracks[x].pregap, Tracks[x].sectors, Tracks[x].LBA); - - FileOffset += Tracks[x].sectors * DI_Size_Table[Tracks[x].DIFormat]; - } // end to cue sheet handling - } // end to track loop - - total_sectors = RunningLBA; - - // - // Load SBI file, if present - // - if(!IsTOC) - { - char sbi_ext[4] = { 's', 'b', 'i', 0 }; - - if(file_ext.length() == 4 && file_ext[0] == '.') - { - for(unsigned i = 0; i < 3; i++) - { - if(file_ext[1 + i] >= 'A' && file_ext[1 + i] <= 'Z') - sbi_ext[i] += 'A' - 'a'; - } - } - - LoadSBI(MDFN_EvalFIP(base_dir, file_base + std::string(".") + std::string(sbi_ext), true).c_str()); - } - - GenerateTOC(); -} - -void CDAccess_Image::Cleanup(void) -{ - for(int32 track = 0; track < 100; track++) - { - CDRFILE_TRACK_INFO *this_track = &Tracks[track]; - - if(this_track->FirstFileInstance) - { - if(Tracks[track].AReader) - { - delete Tracks[track].AReader; - Tracks[track].AReader = NULL; - } - - if(this_track->fp) - { - delete this_track->fp; - this_track->fp = NULL; - } - } - } -} - -CDAccess_Image::CDAccess_Image(const std::string& path, bool image_memcache) : NumTracks(0), FirstTrack(0), LastTrack(0), total_sectors(0) -{ - memset(Tracks, 0, sizeof(Tracks)); - - try - { - ImageOpen(path, image_memcache); - } - catch(...) - { - Cleanup(); - throw; - } -} - -CDAccess_Image::~CDAccess_Image() -{ - Cleanup(); -} - -void CDAccess_Image::Read_Raw_Sector(uint8 *buf, int32 lba) -{ - uint8 SimuQ[0xC]; - int32 track; - CDRFILE_TRACK_INFO *ct; - - // - // Leadout synthesis - // - if(lba >= total_sectors) - { - uint8 data_synth_mode = (disc_type == DISC_TYPE_CD_XA ? 0x02 : 0x01); - - switch(Tracks[LastTrack].DIFormat) - { - case DI_FORMAT_AUDIO: - break; - - case DI_FORMAT_MODE1_RAW: - case DI_FORMAT_MODE1: - data_synth_mode = 0x01; - break; - - case DI_FORMAT_MODE2_RAW: - case DI_FORMAT_MODE2_FORM1: - case DI_FORMAT_MODE2_FORM2: - case DI_FORMAT_MODE2: - case DI_FORMAT_CDI_RAW: - data_synth_mode = 0x02; - break; - } - - synth_leadout_sector_lba(data_synth_mode, toc, lba, buf); - return; - } - // - // - // - - memset(buf + 2352, 0, 96); - track = MakeSubPQ(lba, buf + 2352); - subq_deinterleave(buf + 2352, SimuQ); - - ct = &Tracks[track]; - - // - // Handle pregap and postgap reading - // - if(lba < (ct->LBA - ct->pregap_dv) || lba >= (ct->LBA + ct->sectors)) - { - int32 pg_offset = lba - ct->LBA; - CDRFILE_TRACK_INFO* et = ct; - - if(pg_offset < -150) - { - if((Tracks[track].subq_control & SUBQ_CTRLF_DATA) && (FirstTrack < track) && !(Tracks[track - 1].subq_control & SUBQ_CTRLF_DATA)) - et = &Tracks[track - 1]; - } - - memset(buf, 0, 2352); - switch(et->DIFormat) - { - case DI_FORMAT_AUDIO: - break; - - case DI_FORMAT_MODE1_RAW: - case DI_FORMAT_MODE1: - encode_mode1_sector(lba + 150, buf); - break; - - case DI_FORMAT_MODE2_RAW: - case DI_FORMAT_MODE2_FORM1: - case DI_FORMAT_MODE2_FORM2: - case DI_FORMAT_MODE2: - case DI_FORMAT_CDI_RAW: - buf[12 + 6] = 0x20; - buf[12 + 10] = 0x20; - encode_mode2_form2_sector(lba + 150, buf); - // TODO: Zero out optional(?) checksum bytes? - break; - } - //printf("Pre/post-gap read, LBA=%d(LBA-track_start_LBA=%d)\n", lba, lba - ct->LBA); - } - else - { - if(ct->AReader) - { - int16 AudioBuf[588 * 2]; - uint64 frames_read = ct->AReader->Read((ct->FileOffset / 4) + (lba - ct->LBA) * 588, AudioBuf, 588); - - ct->LastSamplePos += frames_read; - - if(frames_read > 588) // This shouldn't happen. - { - printf("Error: frames_read out of range: %llu\n", (unsigned long long)frames_read); - frames_read = 0; - } - - if(frames_read < 588) - memset((uint8 *)AudioBuf + frames_read * 2 * sizeof(int16), 0, (588 - frames_read) * 2 * sizeof(int16)); - - for(int i = 0; i < 588 * 2; i++) - MDFN_en16lsb(buf + i * 2, AudioBuf[i]); - } - else // Binary, woo. - { - long SeekPos = ct->FileOffset; - long LBARelPos = lba - ct->LBA; - - SeekPos += LBARelPos * DI_Size_Table[ct->DIFormat]; - - if(ct->SubchannelMode) - SeekPos += 96 * (lba - ct->LBA); - - ct->fp->seek(SeekPos, SEEK_SET); - - switch(ct->DIFormat) - { - case DI_FORMAT_AUDIO: - ct->fp->read(buf, 2352); - - if(ct->RawAudioMSBFirst) - Endian_A16_Swap(buf, 588 * 2); - break; - - case DI_FORMAT_MODE1: - ct->fp->read(buf + 12 + 3 + 1, 2048); - encode_mode1_sector(lba + 150, buf); - break; - - case DI_FORMAT_MODE1_RAW: - case DI_FORMAT_MODE2_RAW: - case DI_FORMAT_CDI_RAW: - ct->fp->read(buf, 2352); - break; - - case DI_FORMAT_MODE2: - ct->fp->read(buf + 16, 2336); - encode_mode2_sector(lba + 150, buf); - break; - - - // FIXME: M2F1, M2F2, does sub-header come before or after user data(standards say before, but I wonder - // about cdrdao...). - case DI_FORMAT_MODE2_FORM1: - ct->fp->read(buf + 24, 2048); - //encode_mode2_form1_sector(lba + 150, buf); - break; - - case DI_FORMAT_MODE2_FORM2: - ct->fp->read(buf + 24, 2324); - //encode_mode2_form2_sector(lba + 150, buf); - break; - - } - - if(ct->SubchannelMode) - ct->fp->read(buf + 2352, 96); - } - } // end if audible part of audio track read. -} - -bool CDAccess_Image::Fast_Read_Raw_PW_TSRE(uint8* pwbuf, int32 lba) const noexcept -{ - int32 track; - - if(lba >= total_sectors) - { - subpw_synth_leadout_lba(toc, lba, pwbuf); - return(true); - } - - memset(pwbuf, 0, 96); - try - { - track = MakeSubPQ(lba, pwbuf); - } - catch(...) - { - return(false); - } - - // - // If TOC+BIN has embedded subchannel data, we can't fast-read(synthesize) it... - // - if(Tracks[track].SubchannelMode && lba >= (Tracks[track].LBA - Tracks[track].pregap_dv) && (lba < Tracks[track].LBA + Tracks[track].sectors)) - return(false); - - return(true); -} - -// -// Note: this function makes use of the current contents(as in |=) in SubPWBuf. -// -int32 CDAccess_Image::MakeSubPQ(int32 lba, uint8 *SubPWBuf) const -{ - uint8 buf[0xC]; - int32 track; - uint32 lba_relative; - uint32 ma, sa, fa; - uint32 m, s, f; - uint8 pause_or = 0x00; - bool track_found = false; - - for(track = FirstTrack; track < (FirstTrack + NumTracks); track++) - { - if(lba >= (Tracks[track].LBA - Tracks[track].pregap_dv - Tracks[track].pregap) && lba < (Tracks[track].LBA + Tracks[track].sectors + Tracks[track].postgap)) - { - track_found = true; - break; - } - } - - if(!track_found) - throw(MDFN_Error(0, _("Could not find track for sector %u!"), lba)); - - if(lba < Tracks[track].LBA) - lba_relative = Tracks[track].LBA - 1 - lba; - else - lba_relative = lba - Tracks[track].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 = Tracks[track].subq_control; - - // Handle pause(D7 of interleaved subchannel byte) bit, should be set to 1 when in pregap or postgap. - if((lba < Tracks[track].LBA) || (lba >= Tracks[track].LBA + Tracks[track].sectors)) - { - //printf("pause_or = 0x80 --- %d\n", lba); - pause_or = 0x80; - } - - // Handle pregap between audio->data track - { - int32 pg_offset = (int32)lba - Tracks[track].LBA; - - // If we're more than 2 seconds(150 sectors) from the real "start" of the track/INDEX 01, and the track is a data track, - // and the preceding track is an audio track, encode it as audio(by taking the SubQ control field from the preceding track). - // - // TODO: Look into how we're supposed to handle subq control field in the four combinations of track types(data/audio). - // - if(pg_offset < -150) - { - if((Tracks[track].subq_control & SUBQ_CTRLF_DATA) && (FirstTrack < track) && !(Tracks[track - 1].subq_control & SUBQ_CTRLF_DATA)) - { - //printf("Pregap part 1 audio->data: lba=%d track_lba=%d\n", lba, Tracks[track].LBA); - control = Tracks[track - 1].subq_control; - } - } - } - - - memset(buf, 0, 0xC); - buf[0] = (adr << 0) | (control << 4); - buf[1] = U8_to_BCD(track); - - if(lba < Tracks[track].LBA) // Index is 00 in pregap - buf[2] = U8_to_BCD(0x00); - else - buf[2] = U8_to_BCD(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); - - if(!SubQReplaceMap.empty()) - { - //printf("%d\n", lba); - auto it = SubQReplaceMap.find(LBA_to_ABA(lba)); - - if(it != SubQReplaceMap.end()) - { - //printf("Replace: %d\n", lba); - memcpy(buf, it->second.data(), 12); - } - } - - for(int i = 0; i < 96; i++) - SubPWBuf[i] |= (((buf[i >> 3] >> (7 - (i & 0x7))) & 1) ? 0x40 : 0x00) | pause_or; - - return track; -} - -void CDAccess_Image::Read_TOC(TOC *rtoc) -{ - *rtoc = toc; -} - -void CDAccess_Image::GenerateTOC(void) -{ - toc.Clear(); - - toc.first_track = FirstTrack; - toc.last_track = FirstTrack + NumTracks - 1; - toc.disc_type = disc_type; - - for(int i = FirstTrack; i < FirstTrack + NumTracks; i++) - { - if(Tracks[i].DIFormat == DI_FORMAT_CDI_RAW) - { - toc.first_track = std::min(99, i + 1); - toc.last_track = std::max(toc.first_track, toc.last_track); - } - - toc.tracks[i].lba = Tracks[i].LBA; - toc.tracks[i].adr = ADR_CURPOS; - toc.tracks[i].control = Tracks[i].subq_control; - toc.tracks[i].valid = true; - } - - toc.tracks[100].lba = total_sectors; - toc.tracks[100].adr = ADR_CURPOS; - toc.tracks[100].control = Tracks[FirstTrack + NumTracks - 1].subq_control & 0x4; - toc.tracks[100].valid = true; -} - - diff --git a/psx/mednadisc/cdrom/CDAccess_Image.h b/psx/mednadisc/cdrom/CDAccess_Image.h deleted file mode 100644 index 659032164a9..00000000000 --- a/psx/mednadisc/cdrom/CDAccess_Image.h +++ /dev/null @@ -1,103 +0,0 @@ -#ifndef __MDFN_CDACCESS_IMAGE_H -#define __MDFN_CDACCESS_IMAGE_H - -#include -#include - -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 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> 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 &toc_streamcache); - uint32 GetSectorCount(CDRFILE_TRACK_INFO *track); -}; - - -#endif diff --git a/psx/mednadisc/cdrom/CDAccess_Physical.cpp b/psx/mednadisc/cdrom/CDAccess_Physical.cpp deleted file mode 100644 index b8af20bac91..00000000000 --- a/psx/mednadisc/cdrom/CDAccess_Physical.cpp +++ /dev/null @@ -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 -#include -#include -#include - -#include -#include -#include - -#if LIBCDIO_VERSION_NUM >= 83 -#include -#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 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; - } - } -} - diff --git a/psx/mednadisc/cdrom/CDAccess_Physical.h b/psx/mednadisc/cdrom/CDAccess_Physical.h deleted file mode 100644 index 562b79f4794..00000000000 --- a/psx/mednadisc/cdrom/CDAccess_Physical.h +++ /dev/null @@ -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 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 diff --git a/psx/mednadisc/cdrom/CDUtility.cpp b/psx/mednadisc/cdrom/CDUtility.cpp deleted file mode 100644 index f1f6fd9ef46..00000000000 --- a/psx/mednadisc/cdrom/CDUtility.cpp +++ /dev/null @@ -1,435 +0,0 @@ -/* Mednafen - Multi-system Emulator - * - * Subchannel Q CRC Code: Copyright (C) 1998 Andreas Mueller - * - * 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 -#include - -#include "emuware/emuware.h" -#include "CDUtility.h" -#include "dvdisaster.h" -#include "lec.h" - -#include -// 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]; -} - -} diff --git a/psx/mednadisc/cdrom/CDUtility.h b/psx/mednadisc/cdrom/CDUtility.h deleted file mode 100644 index b796acfaaf6..00000000000 --- a/psx/mednadisc/cdrom/CDUtility.h +++ /dev/null @@ -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 diff --git a/psx/mednadisc/cdrom/Makefile.am.inc b/psx/mednadisc/cdrom/Makefile.am.inc deleted file mode 100644 index b06d158c124..00000000000 --- a/psx/mednadisc/cdrom/Makefile.am.inc +++ /dev/null @@ -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 diff --git a/psx/mednadisc/cdrom/SimpleFIFO.h b/psx/mednadisc/cdrom/SimpleFIFO.h deleted file mode 100644 index edc8f03e36f..00000000000 --- a/psx/mednadisc/cdrom/SimpleFIFO.h +++ /dev/null @@ -1,140 +0,0 @@ -#ifndef __MDFN_SIMPLEFIFO_H -#define __MDFN_SIMPLEFIFO_H - -#include -#include - -#include "../math_ops.h" - -template -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 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 data; - uint32 size; - uint32 read_pos; // Read position - uint32 write_pos; // Write position - uint32 in_count; // Number of units in the FIFO -}; - - -#endif diff --git a/psx/mednadisc/cdrom/cdromif.cpp b/psx/mednadisc/cdrom/cdromif.cpp deleted file mode 100644 index ca09dc74aa5..00000000000 --- a/psx/mednadisc/cdrom/cdromif.cpp +++ /dev/null @@ -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 -#include -#include -#include "emuware/emuware.h" -#include "cdromif.h" -#include "CDAccess.h" -#include "general.h" -#include "error.h" - -//undo gettext stuff -#define _(X) X -#include - -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 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(2048 - (rp & 2047), count - (rp - position))); - memcpy((uint8*)data + (rp - position), buf + (rp & 2047), std::min(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); -} diff --git a/psx/mednadisc/cdrom/cdromif.h b/psx/mednadisc/cdrom/cdromif.h deleted file mode 100644 index 728f2e6c663..00000000000 --- a/psx/mednadisc/cdrom/cdromif.h +++ /dev/null @@ -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 - -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 diff --git a/psx/mednadisc/cdrom/crc32.cpp b/psx/mednadisc/cdrom/crc32.cpp deleted file mode 100644 index 08268ae8dc2..00000000000 --- a/psx/mednadisc/cdrom/crc32.cpp +++ /dev/null @@ -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; -} diff --git a/psx/mednadisc/cdrom/dvdisaster.h b/psx/mednadisc/cdrom/dvdisaster.h deleted file mode 100644 index 7d963c535c9..00000000000 --- a/psx/mednadisc/cdrom/dvdisaster.h +++ /dev/null @@ -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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -//#include - -/*** - *** 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_FIELDMAX) - { - x -= GF_FIELDMAX; - x = (x >> GF_SYMBOLSIZE) + (x & GF_FIELDMAX); - } - - return x; -} diff --git a/psx/mednadisc/cdrom/galois.cpp b/psx/mednadisc/cdrom/galois.cpp deleted file mode 100644 index 5c48f4f793a..00000000000 --- a/psx/mednadisc/cdrom/galois.cpp +++ /dev/null @@ -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; logindexOf[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; inroots; 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); -} diff --git a/psx/mednadisc/cdrom/l-ec.cpp b/psx/mednadisc/cdrom/l-ec.cpp deleted file mode 100644 index 39b4cbdd9fa..00000000000 --- a/psx/mednadisc/cdrom/l-ec.cpp +++ /dev/null @@ -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; ialphaTo[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; iindexOf[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; i0; j--) - { int tmp = gt->indexOf[lambda[j-1]]; - - if(tmp != GF_ALPHA0) - lambda[j] ^= gt->alphaTo[mod_fieldmax(u + tmp)]; - } - } - } - - for(i=0; iindexOf[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; ialphaTo[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; ialphaTo[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; iindexOf[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; ialphaTo[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 - * - * 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 -#endif - -#include -#include - -#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 -#include -#include -#include - -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 diff --git a/psx/mednadisc/cdrom/lec.h b/psx/mednadisc/cdrom/lec.h deleted file mode 100644 index b41c06b8fa6..00000000000 --- a/psx/mednadisc/cdrom/lec.h +++ /dev/null @@ -1,77 +0,0 @@ -/* cdrdao - write audio CD-Rs in disc-at-once mode - * - * Copyright (C) 1998-2002 Andreas Mueller - * - * 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 -#endif - -#include -#include - -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 diff --git a/psx/mednadisc/cdrom/recover-raw.cpp b/psx/mednadisc/cdrom/recover-raw.cpp deleted file mode 100644 index 78be2e2a549..00000000000 --- a/psx/mednadisc/cdrom/recover-raw.cpp +++ /dev/null @@ -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 2) - { GetPVector(byte_state, p_state, p); - erasure_count = 0; - - for(i=0; i 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; -} - diff --git a/psx/mednadisc/cdrom/scsicd-pce-commands.inc b/psx/mednadisc/cdrom/scsicd-pce-commands.inc deleted file mode 100644 index 4441e9304be..00000000000 --- a/psx/mednadisc/cdrom/scsicd-pce-commands.inc +++ /dev/null @@ -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); -} - diff --git a/psx/mednadisc/cdrom/scsicd.cpp b/psx/mednadisc/cdrom/scsicd.cpp deleted file mode 100644 index 21d81e2d1ee..00000000000 --- a/psx/mednadisc/cdrom/scsicd.cpp +++ /dev/null @@ -1,3246 +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 -#include -#include -#include -#include "scsicd.h" -#include "cdromif.h" -#include "SimpleFIFO.h" - -#if defined(__SSE2__) -#include -#include -#endif - -//#define SCSIDBG(format, ...) { printf("[SCSICD] " format "\n", ## __VA_ARGS__); } -//#define SCSIDBG(format, ...) { } - -using namespace CDUtility; - -static uint32 CD_DATA_TRANSFER_RATE; -static uint32 System_Clock; -static void (*CDIRQCallback)(int); -static void (*CDStuffSubchannels)(uint8, int); -static int32* HRBufs[2]; -static int WhichSystem; - -static CDIF *Cur_CDIF; -static bool TrayOpen; - -// Internal operation to the SCSI CD unit. Only pass 1 or 0 to these macros! -#define SetIOP(mask, set) { cd_bus.signals &= ~mask; if(set) cd_bus.signals |= mask; } - -#define SetBSY(set) SetIOP(SCSICD_BSY_mask, set) -#define SetIO(set) SetIOP(SCSICD_IO_mask, set) -#define SetCD(set) SetIOP(SCSICD_CD_mask, set) -#define SetMSG(set) SetIOP(SCSICD_MSG_mask, set) - -static INLINE void SetREQ(bool set) -{ - if(set && !REQ_signal) - CDIRQCallback(SCSICD_IRQ_MAGICAL_REQ); - - SetIOP(SCSICD_REQ_mask, set); -} - -#define SetkingACK(set) SetIOP(SCSICD_kingACK_mask, set) -#define SetkingRST(set) SetIOP(SCSICD_kingRST_mask, set) -#define SetkingSEL(set) SetIOP(SCSICD_kingSEL_mask, set) -#define SetkingATN(set) SetIOP(SCSICD_kingATN_mask, set) - - -enum -{ - QMode_Zero = 0, - QMode_Time = 1, - QMode_MCN = 2, // Media Catalog Number - QMode_ISRC = 3 // International Standard Recording Code -}; - -typedef struct -{ - bool last_RST_signal; - - // The pending message to send(in the message phase) - uint8 message_pending; - - bool status_sent, message_sent; - - // Pending error codes - uint8 key_pending, asc_pending, ascq_pending, fru_pending; - - uint8 command_buffer[256]; - uint8 command_buffer_pos; - uint8 command_size_left; - - // FALSE if not all pending data is in the FIFO, TRUE if it is. - // Used for multiple sector CD reads. - bool data_transfer_done; - - // To target(the cd unit); for "MODE SELECT". - uint8 data_out[256]; // Technically it only needs to be 255, but powers of 2 are better than those degenerate powers of 2 minus one goons. - uint8 data_out_pos; // Current index for writing into data_out. - uint8 data_out_want; // Total number of bytes to buffer into data_out. - - bool DiscChanged; - - uint8 SubQBuf[4][0xC]; // One for each of the 4 most recent q-Modes. - uint8 SubQBuf_Last[0xC]; // The most recent q subchannel data, regardless of q-mode. - - uint8 SubPWBuf[96]; - -} scsicd_t; - -enum -{ - CDDASTATUS_PAUSED = -1, - CDDASTATUS_STOPPED = 0, - CDDASTATUS_PLAYING = 1, - CDDASTATUS_SCANNING = 2, -}; - -enum -{ - PLAYMODE_SILENT = 0x00, - PLAYMODE_NORMAL, - PLAYMODE_INTERRUPT, - PLAYMODE_LOOP, -}; - -typedef struct -{ - uint32 CDDADivAcc; - uint8 CDDADivAccVolFudge; // For PC-FX CD-DA rate control RE impulses and resampling; 100 = 1.0. - uint32 scan_sec_end; - - uint8 PlayMode; - int32 CDDAVolume[2]; // 65536 = 1.0, the maximum. - int16 CDDASectorBuffer[1176]; - uint32 CDDAReadPos; - - int8 CDDAStatus; - uint8 ScanMode; - int64 CDDADiv; - int CDDATimeDiv; - - int16 OversampleBuffer[2][0x10 * 2]; // *2 so our MAC loop can blast through without masking the index. - unsigned OversamplePos; - - int16 sr[2]; - - uint8 OutPortChSelect[2]; - uint32 OutPortChSelectCache[2]; - int32 OutPortVolumeCache[2]; - - float DeemphState[2][2]; -} cdda_t; - -void MakeSense(uint8 * target, uint8 key, uint8 asc, uint8 ascq, uint8 fru) -{ - memset(target, 0, 18); - - target[0] = 0x70; // Current errors and sense data is not SCSI compliant - target[2] = key; - target[7] = 0x0A; - target[12] = asc; // Additional Sense Code - target[13] = ascq; // Additional Sense Code Qualifier - target[14] = fru; // Field Replaceable Unit code -} - -static void (*SCSILog)(const char *, const char *format, ...); -static void InitModePages(void); - -static scsicd_timestamp_t lastts; -static int64 monotonic_timestamp; -static int64 pce_lastsapsp_timestamp; - -scsicd_t cd; -scsicd_bus_t cd_bus; -static cdda_t cdda; - -static SimpleFIFO *din = NULL; - -static CDUtility::TOC toc; - -static uint32 read_sec_start; -static uint32 read_sec; -static uint32 read_sec_end; - -static int32 CDReadTimer; -static uint32 SectorAddr; -static uint32 SectorCount; - - -enum -{ - PHASE_BUS_FREE = 0, - PHASE_COMMAND, - PHASE_DATA_IN, - PHASE_DATA_OUT, - PHASE_STATUS, - PHASE_MESSAGE_IN, - PHASE_MESSAGE_OUT -}; -static unsigned int CurrentPhase; -static void ChangePhase(const unsigned int new_phase); - - -static void FixOPV(void) -{ - for(int port = 0; port < 2; port++) - { - int32 tmpvol = cdda.CDDAVolume[port] * 100 / (2 * cdda.CDDADivAccVolFudge); - - //printf("TV: %d\n", tmpvol); - - cdda.OutPortVolumeCache[port] = tmpvol; - - if(cdda.OutPortChSelect[port] & 0x01) - cdda.OutPortChSelectCache[port] = 0; - else if(cdda.OutPortChSelect[port] & 0x02) - cdda.OutPortChSelectCache[port] = 1; - else - { - cdda.OutPortChSelectCache[port] = 0; - cdda.OutPortVolumeCache[port] = 0; - } - } -} - -static void VirtualReset(void) -{ - InitModePages(); - - din->Flush(); - - CDReadTimer = 0; - - pce_lastsapsp_timestamp = monotonic_timestamp; - - SectorAddr = SectorCount = 0; - read_sec_start = read_sec = 0; - read_sec_end = ~0; - - cdda.PlayMode = PLAYMODE_SILENT; - cdda.CDDAReadPos = 0; - cdda.CDDAStatus = CDDASTATUS_STOPPED; - cdda.CDDADiv = 0; - - cdda.ScanMode = 0; - cdda.scan_sec_end = 0; - - cdda.OversamplePos = 0; - memset(cdda.sr, 0, sizeof(cdda.sr)); - memset(cdda.OversampleBuffer, 0, sizeof(cdda.OversampleBuffer)); - memset(cdda.DeemphState, 0, sizeof(cdda.DeemphState)); - - memset(cd.data_out, 0, sizeof(cd.data_out)); - cd.data_out_pos = 0; - cd.data_out_want = 0; - - - FixOPV(); - - ChangePhase(PHASE_BUS_FREE); -} - -void SCSICD_Power(scsicd_timestamp_t system_timestamp) -{ - memset(&cd, 0, sizeof(scsicd_t)); - memset(&cd_bus, 0, sizeof(scsicd_bus_t)); - - monotonic_timestamp = system_timestamp; - - cd.DiscChanged = false; - - if(Cur_CDIF && !TrayOpen) - Cur_CDIF->ReadTOC(&toc); - - CurrentPhase = PHASE_BUS_FREE; - - VirtualReset(); -} - - -void SCSICD_SetDB(uint8 data) -{ - cd_bus.DB = data; - //printf("Set DB: %02x\n", data); -} - -void SCSICD_SetACK(bool set) -{ - SetkingACK(set); - //printf("Set ACK: %d\n", set); -} - -void SCSICD_SetSEL(bool set) -{ - SetkingSEL(set); - //printf("Set SEL: %d\n", set); -} - -void SCSICD_SetRST(bool set) -{ - SetkingRST(set); - //printf("Set RST: %d\n", set); -} - -void SCSICD_SetATN(bool set) -{ - SetkingATN(set); - //printf("Set ATN: %d\n", set); -} - -static void GenSubQFromSubPW(void) -{ - uint8 SubQBuf[0xC]; - - memset(SubQBuf, 0, 0xC); - - for(int i = 0; i < 96; i++) - SubQBuf[i >> 3] |= ((cd.SubPWBuf[i] & 0x40) >> 6) << (7 - (i & 7)); - - //printf("Real %d/ SubQ %d - ", read_sec, BCD_to_U8(SubQBuf[7]) * 75 * 60 + BCD_to_U8(SubQBuf[8]) * 75 + BCD_to_U8(SubQBuf[9]) - 150); - // Debug code, remove me. - //for(int i = 0; i < 0xC; i++) - // printf("%02x ", SubQBuf[i]); - //printf("\n"); - - if(!subq_check_checksum(SubQBuf)) - { - //SCSIDBG("SubQ checksum error!"); - } - else - { - memcpy(cd.SubQBuf_Last, SubQBuf, 0xC); - - uint8 adr = SubQBuf[0] & 0xF; - - if(adr <= 0x3) - memcpy(cd.SubQBuf[adr], SubQBuf, 0xC); - - //if(adr == 0x02) - //for(int i = 0; i < 12; i++) - // printf("%02x\n", cd.SubQBuf[0x2][i]); - } -} - - -#define STATUS_GOOD 0 -#define STATUS_CHECK_CONDITION 1 -#define STATUS_CONDITION_MET 2 -#define STATUS_BUSY 4 -#define STATUS_INTERMEDIATE 8 - -#define SENSEKEY_NO_SENSE 0x0 -#define SENSEKEY_NOT_READY 0x2 -#define SENSEKEY_MEDIUM_ERROR 0x3 -#define SENSEKEY_HARDWARE_ERROR 0x4 -#define SENSEKEY_ILLEGAL_REQUEST 0x5 -#define SENSEKEY_UNIT_ATTENTION 0x6 -#define SENSEKEY_ABORTED_COMMAND 0xB - -#define ASC_MEDIUM_NOT_PRESENT 0x3A - - -// NEC sub-errors(ASC), no ASCQ. -#define NSE_NO_DISC 0x0B // Used with SENSEKEY_NOT_READY - This condition occurs when tray is closed with no disc present. -#define NSE_TRAY_OPEN 0x0D // Used with SENSEKEY_NOT_READY -#define NSE_SEEK_ERROR 0x15 -#define NSE_HEADER_READ_ERROR 0x16 // Used with SENSEKEY_MEDIUM_ERROR -#define NSE_NOT_AUDIO_TRACK 0x1C // Used with SENSEKEY_MEDIUM_ERROR -#define NSE_NOT_DATA_TRACK 0x1D // Used with SENSEKEY_MEDIUM_ERROR -#define NSE_INVALID_COMMAND 0x20 -#define NSE_INVALID_ADDRESS 0x21 -#define NSE_INVALID_PARAMETER 0x22 -#define NSE_END_OF_VOLUME 0x25 -#define NSE_INVALID_REQUEST_IN_CDB 0x27 -#define NSE_DISC_CHANGED 0x28 // Used with SENSEKEY_UNIT_ATTENTION -#define NSE_AUDIO_NOT_PLAYING 0x2C - -// ASC, ASCQ pair -#define AP_UNRECOVERED_READ_ERROR 0x11, 0x00 -#define AP_LEC_UNCORRECTABLE_ERROR 0x11, 0x05 -#define AP_CIRC_UNRECOVERED_ERROR 0x11, 0x06 - -#define AP_UNKNOWN_MEDIUM_FORMAT 0x30, 0x01 -#define AP_INCOMPAT_MEDIUM_FORMAT 0x30, 0x02 - -static void ChangePhase(const unsigned int new_phase) -{ - //printf("New phase: %d %lld\n", new_phase, monotonic_timestamp); - switch(new_phase) - { - case PHASE_BUS_FREE: - SetBSY(false); - SetMSG(false); - SetCD(false); - SetIO(false); - SetREQ(false); - - CDIRQCallback(0x8000 | SCSICD_IRQ_DATA_TRANSFER_DONE); - break; - - case PHASE_DATA_IN: // Us to them - SetBSY(true); - SetMSG(false); - SetCD(false); - SetIO(true); - //SetREQ(true); - SetREQ(false); - break; - - case PHASE_STATUS: // Us to them - SetBSY(true); - SetMSG(false); - SetCD(true); - SetIO(true); - SetREQ(true); - break; - - case PHASE_MESSAGE_IN: // Us to them - SetBSY(true); - SetMSG(true); - SetCD(true); - SetIO(true); - SetREQ(true); - break; - - - case PHASE_DATA_OUT: // Them to us - SetBSY(true); - SetMSG(false); - SetCD(false); - SetIO(false); - SetREQ(true); - break; - - case PHASE_COMMAND: // Them to us - SetBSY(true); - SetMSG(false); - SetCD(true); - SetIO(false); - SetREQ(true); - break; - - case PHASE_MESSAGE_OUT: // Them to us - SetBSY(true); - SetMSG(true); - SetCD(true); - SetIO(false); - SetREQ(true); - break; - } - CurrentPhase = new_phase; -} - -static void SendStatusAndMessage(uint8 status, uint8 message) -{ - // This should never ever happen, but that doesn't mean it won't. ;) - if(din->CanRead()) - { - //printf("[SCSICD] BUG: %d bytes still in SCSI CD FIFO\n", din->CanRead()); - din->Flush(); - } - - cd.message_pending = message; - - cd.status_sent = FALSE; - cd.message_sent = FALSE; - - if(WhichSystem == SCSICD_PCE) - { - if(status == STATUS_GOOD || status == STATUS_CONDITION_MET) - cd_bus.DB = 0x00; - else - cd_bus.DB = 0x01; - } - else - cd_bus.DB = status << 1; - - ChangePhase(PHASE_STATUS); -} - -static void DoSimpleDataIn(const uint8 *data_in, uint32 len) -{ - din->Write(data_in, len); - - cd.data_transfer_done = true; - - ChangePhase(PHASE_DATA_IN); -} - -void SCSICD_SetDisc(bool new_tray_open, CDIF *cdif, bool no_emu_side_effects) -{ - Cur_CDIF = cdif; - - // Closing the tray. - if(TrayOpen && !new_tray_open) - { - TrayOpen = false; - - if(cdif) - { - cdif->ReadTOC(&toc); - - if(!no_emu_side_effects) - { - memset(cd.SubQBuf, 0, sizeof(cd.SubQBuf)); - memset(cd.SubQBuf_Last, 0, sizeof(cd.SubQBuf_Last)); - cd.DiscChanged = true; - } - } - } - else if(!TrayOpen && new_tray_open) // Opening the tray - { - TrayOpen = true; - } -} - -static void CommandCCError(int key, int asc = 0, int ascq = 0) -{ - //printf("[SCSICD] CC Error: %02x %02x %02x\n", key, asc, ascq); - - cd.key_pending = key; - cd.asc_pending = asc; - cd.ascq_pending = ascq; - cd.fru_pending = 0x00; - - SendStatusAndMessage(STATUS_CHECK_CONDITION, 0x00); -} - -static bool ValidateRawDataSector(uint8 *data, const uint32 lba) -{ - if(!Cur_CDIF->ValidateRawSector(data)) - { - MDFN_DispMessage(_("Uncorrectable data at sector %d"), lba); - MDFN_PrintError(_("Uncorrectable data at sector %d"), lba); - - din->Flush(); - cd.data_transfer_done = false; - - CommandCCError(SENSEKEY_MEDIUM_ERROR, AP_LEC_UNCORRECTABLE_ERROR); - return(false); - } - - return(true); -} - -static void DoMODESELECT6(const uint8 *cdb) -{ - if(cdb[4]) - { - cd.data_out_pos = 0; - cd.data_out_want = cdb[4]; - //printf("Switch to DATA OUT phase, len: %d\n", cd.data_out_want); - - ChangePhase(PHASE_DATA_OUT); - } - else - SendStatusAndMessage(STATUS_GOOD, 0x00); -} - -/* - All Japan Female Pro Wrestle: - Datumama: 10, 00 00 00 00 00 00 00 00 00 0a - - Kokuu Hyouryuu Nirgends: - Datumama: 10, 00 00 00 00 00 00 00 00 00 0f - Datumama: 10, 00 00 00 00 00 00 00 00 00 0f - - Last Imperial Prince: - Datumama: 10, 00 00 00 00 00 00 00 00 00 0f - Datumama: 10, 00 00 00 00 00 00 00 00 00 0f - - Megami Paradise II: - Datumama: 10, 00 00 00 00 00 00 00 00 00 0a - - Miraculum: - Datumama: 7, 00 00 00 00 29 01 00 - Datumama: 10, 00 00 00 00 00 00 00 00 00 0f - Datumama: 7, 00 00 00 00 29 01 00 - Datumama: 10, 00 00 00 00 00 00 00 00 00 00 - Datumama: 7, 00 00 00 00 29 01 00 - - Pachio Kun FX: - Datumama: 10, 00 00 00 00 00 00 00 00 00 14 - - Return to Zork: - Datumama: 10, 00 00 00 00 00 00 00 00 00 00 - - Sotsugyou II: - Datumama: 10, 00 00 00 00 01 00 00 00 00 01 - - Tokimeki Card Paradise: - Datumama: 10, 00 00 00 00 00 00 00 00 00 14 - Datumama: 10, 00 00 00 00 00 00 00 00 00 07 - - Tonari no Princess Rolfee: - Datumama: 10, 00 00 00 00 00 00 00 00 00 00 - - Zoku Hakutoi Monogatari: - Datumama: 10, 00 00 00 00 00 00 00 00 00 14 -*/ - - // Page 151: MODE SENSE(6) - // PC = 0 current - // PC = 1 Changeable - // PC = 2 Default - // PC = 3 Saved - // Page 183: Mode parameter header. - // Page 363: CD-ROM density codes. - // Page 364: CD-ROM mode page codes. - // Page 469: ASC and ASCQ table - - -struct ModePageParam -{ - uint8 default_value; - uint8 alterable_mask; // Alterable mask reported when PC == 1 - uint8 real_mask; // Real alterable mask. -}; - -struct ModePage -{ - const uint8 code; - const uint8 param_length; - const ModePageParam params[64]; // 64 should be more than enough - uint8 current_value[64]; -}; - -/* - Mode pages present: - 0x00: - 0x0E: - 0x28: - 0x29: - 0x2A: - 0x2B: - 0x3F(Yes, not really a mode page but a fetch method) -*/ -// Remember to update the code in StateAction() if we change the number or layout of modepages here. -static const int NumModePages = 5; -static ModePage ModePages[NumModePages] = -{ - // Unknown - { 0x28, - 0x04, - { - { 0x00, 0x00, 0xFF }, - { 0x00, 0x00, 0xFF }, - { 0x00, 0x00, 0xFF }, - { 0x00, 0x00, 0xFF }, - } - }, - - // Unknown - { 0x29, - 0x01, - { - { 0x00, 0x00, 0xFF }, - } - }, - - // Unknown - { 0x2a, - 0x02, - { - { 0x00, 0x00, 0xFF }, - { 0x11, 0x00, 0xFF }, - } - }, - - // CD-DA playback speed modifier - { 0x2B, - 0x01, - { - { 0x00, 0x00, 0xFF }, - } - }, - - // 0x0E goes last, for correct order of return data when page code == 0x3F - // Real mask values are probably not right; some functionality not emulated yet. - // CD-ROM audio control parameters - { 0x0E, - 0x0E, - { - { 0x04, 0x04, 0x04 }, // Immed - { 0x00, 0x00, 0x00 }, // Reserved - { 0x00, 0x00, 0x00 }, // Reserved - { 0x00, 0x01, 0x01 }, // Reserved? - { 0x00, 0x00, 0x00 }, // MSB of LBA per second. - { 0x00, 0x00, 0x00 }, // LSB of LBA per second. - { 0x01, 0x01, 0x03 }, // Outport port 0 channel selection. - { 0xFF, 0x00, 0x00 }, // Outport port 0 volume. - { 0x02, 0x02, 0x03 }, // Outport port 1 channel selection. - { 0xFF, 0x00, 0x00 }, // Outport port 1 volume. - { 0x00, 0x00, 0x00 }, // Outport port 2 channel selection. - { 0x00, 0x00, 0x00 }, // Outport port 2 volume. - { 0x00, 0x00, 0x00 }, // Outport port 3 channel selection. - { 0x00, 0x00, 0x00 }, // Outport port 3 volume. - } - }, -}; - -static void UpdateMPCacheP(const ModePage* mp) -{ - switch(mp->code) - { - case 0x0E: - { - const uint8 *pd = &mp->current_value[0]; - - for(int i = 0; i < 2; i++) - cdda.OutPortChSelect[i] = pd[6 + i * 2]; - FixOPV(); - } - break; - - case 0x28: - break; - - case 0x29: - break; - - case 0x2A: - break; - - case 0x2B: - { - int speed; - int rate; - - // - // Not sure what the actual limits are, or what happens when exceeding them, but these will at least keep the - // CD-DA playback system from imploding in on itself. - // - // The range of speed values accessible via the BIOS CD-DA player is apparently -10 to 10. - // - // No game is known to use the CD-DA playback speed control. It may be useful in homebrew to lower the rate for fitting more CD-DA onto the disc, - // is implemented on the PC-FX in such a way that it degrades audio quality, so it wouldn't really make sense to increase the rate in homebrew. - // - // Due to performance considerations, we only partially emulate the CD-DA oversampling filters used on the PC Engine and PC-FX, and instead - // blast impulses into the 1.78MHz buffer, relying on the final sound resampler to kill spectrum mirrors. This is less than ideal, but generally - // works well in practice, except when lowering CD-DA playback rate...which causes the spectrum mirrors to enter the non-murder zone, causing - // the sound output amplitude to approach overflow levels. - // But, until there's a killer PC-FX homebrew game that necessitates more computationally-expensive CD-DA handling, - // I don't see a good reason to change how CD-DA resampling is currently implemented. - // - speed = std::max(-32, std::min(32, (int8)mp->current_value[0])); - rate = 44100 + 441 * speed; - - //printf("[SCSICD] Speed: %d(pre-clamped=%d) %d\n", speed, (int8)mp->current_value[0], rate); - cdda.CDDADivAcc = ((int64)System_Clock * (1024 * 1024) / (2 * rate)); - cdda.CDDADivAccVolFudge = 100 + speed; - FixOPV(); // Resampler impulse amplitude volume adjustment(call after setting cdda.CDDADivAccVolFudge) - } - break; - } -} - -static void UpdateMPCache(uint8 code) -{ - for(int pi = 0; pi < NumModePages; pi++) - { - const ModePage* mp = &ModePages[pi]; - - if(mp->code == code) - { - UpdateMPCacheP(mp); - break; - } - } -} - -static void InitModePages(void) -{ - for(int pi = 0; pi < NumModePages; pi++) - { - ModePage *mp = &ModePages[pi]; - const ModePageParam *params = &ModePages[pi].params[0]; - - for(int parami = 0; parami < mp->param_length; parami++) - mp->current_value[parami] = params[parami].default_value; - - UpdateMPCacheP(mp); - } -} - -static void FinishMODESELECT6(const uint8 *data, const uint8 data_len) -{ - uint8 mode_data_length, medium_type, device_specific, block_descriptor_length; - uint32 offset = 0; - - //printf("[SCSICD] Mode Select (6) Data: Length=0x%02x, ", data_len); - //for(uint32 i = 0; i < data_len; i++) - // printf("0x%02x ", data[i]); - //printf("\n"); - - if(data_len < 4) - { - CommandCCError(SENSEKEY_ILLEGAL_REQUEST, NSE_INVALID_PARAMETER); - return; - } - - mode_data_length = data[offset++]; - medium_type = data[offset++]; - device_specific = data[offset++]; - block_descriptor_length = data[offset++]; - - // For now, shut up gcc. - (void)mode_data_length; - (void)medium_type; - (void)device_specific; - - if(block_descriptor_length & 0x7) - { - CommandCCError(SENSEKEY_ILLEGAL_REQUEST, NSE_INVALID_PARAMETER); - return; - } - - if((offset + block_descriptor_length) > data_len) - { - CommandCCError(SENSEKEY_ILLEGAL_REQUEST, NSE_INVALID_PARAMETER); - return; - } - - // TODO: block descriptors. - offset += block_descriptor_length; - - // Now handle mode pages - while(offset < data_len) - { - const uint8 code = data[offset++]; - uint8 param_len = 0; - bool page_found = false; - - if(code == 0x00) - { - if((offset + 0x5) > data_len) - { - CommandCCError(SENSEKEY_ILLEGAL_REQUEST, NSE_INVALID_PARAMETER); - return; - } - - UpdateMPCache(0x00); - - offset += 0x5; - continue; - } - - if(offset >= data_len) - { - CommandCCError(SENSEKEY_ILLEGAL_REQUEST, NSE_INVALID_PARAMETER); - return; - } - - param_len = data[offset++]; - - for(int pi = 0; pi < NumModePages; pi++) - { - ModePage *mp = &ModePages[pi]; - - if(code == mp->code) - { - page_found = true; - - if(param_len != mp->param_length) - { - CommandCCError(SENSEKEY_ILLEGAL_REQUEST, NSE_INVALID_PARAMETER); - return; - } - - if((param_len + offset) > data_len) - { - CommandCCError(SENSEKEY_ILLEGAL_REQUEST, NSE_INVALID_PARAMETER); - return; - } - - for(int parami = 0; parami < mp->param_length; parami++) - { - mp->current_value[parami] &= ~mp->params[parami].real_mask; - mp->current_value[parami] |= (data[offset++]) & mp->params[parami].real_mask; - } - - UpdateMPCacheP(mp); - break; - } - } - - if(!page_found) - { - CommandCCError(SENSEKEY_ILLEGAL_REQUEST, NSE_INVALID_PARAMETER); - return; - } - } - - SendStatusAndMessage(STATUS_GOOD, 0x00); -} - -static void DoMODESENSE6(const uint8 *cdb) -{ - unsigned int PC = (cdb[2] >> 6) & 0x3; - unsigned int PageCode = cdb[2] & 0x3F; - bool DBD = cdb[1] & 0x08; - int AllocSize = cdb[4]; - int index = 0; - uint8 data_in[8192]; - uint8 PageMatchOR = 0x00; - bool AnyPageMatch = false; - - //SCSIDBG("Mode sense 6: %02x %d %d %d", PageCode, PC, DBD, AllocSize); - - if(!AllocSize) - { - SendStatusAndMessage(STATUS_GOOD, 0x00); - return; - } - - if(PC == 3) - { - CommandCCError(SENSEKEY_ILLEGAL_REQUEST, NSE_INVALID_PARAMETER); - return; - } - - if(PageCode == 0x00) // Special weird case. - { - if(DBD || PC) - { - CommandCCError(SENSEKEY_ILLEGAL_REQUEST, NSE_INVALID_PARAMETER); - return; - } - - memset(data_in, 0, 0xA); - data_in[0] = 0x09; - data_in[2] = 0x80; - data_in[9] = 0x0F; - - if(AllocSize > 0xA) - AllocSize = 0xA; - - DoSimpleDataIn(data_in, AllocSize); - return; - } - - data_in[0] = 0x00; // Fill this in later. - data_in[1] = 0x00; // Medium type - data_in[2] = 0x00; // Device-specific parameter. - data_in[3] = DBD ? 0x00 : 0x08; // Block descriptor length. - index += 4; - - if(!DBD) - { - data_in[index++] = 0x00; // Density code. - MDFN_en24msb(&data_in[index], 0x6E); // Number of blocks? - index += 3; - - data_in[index++] = 0x00; // Reserved - MDFN_en24msb(&data_in[index], 0x800); // Block length; - index += 3; - } - - PageMatchOR = 0x00; - if(PageCode == 0x3F) - PageMatchOR = 0x3F; - - for(int pi = 0; pi < NumModePages; pi++) - { - const ModePage *mp = &ModePages[pi]; - const ModePageParam *params = &ModePages[pi].params[0]; - - if((mp->code | PageMatchOR) != PageCode) - continue; - - AnyPageMatch = true; - - data_in[index++] = mp->code; - data_in[index++] = mp->param_length; - - for(int parami = 0; parami < mp->param_length; parami++) - { - uint8 data; - - if(PC == 0x02) - data = params[parami].default_value; - else if(PC == 0x01) - data = params[parami].alterable_mask; - else - data = mp->current_value[parami]; - - data_in[index++] = data; - } - } - - if(!AnyPageMatch) - { - CommandCCError(SENSEKEY_ILLEGAL_REQUEST, NSE_INVALID_PARAMETER); - return; - } - - if(AllocSize > index) - AllocSize = index; - - data_in[0] = AllocSize - 1; - - DoSimpleDataIn(data_in, AllocSize); -} - -static void DoSTARTSTOPUNIT6(const uint8 *cdb) -{ - //bool Immed = cdb[1] & 0x01; - //bool LoEj = cdb[4] & 0x02; - //bool Start = cdb[4] & 0x01; - - //SCSIDBG("Do start stop unit 6: %d %d %d\n", Immed, LoEj, Start); - - SendStatusAndMessage(STATUS_GOOD, 0x00); -} - -static void DoREZEROUNIT(const uint8 *cdb) -{ - //SCSIDBG("Rezero Unit: %02x\n", cdb[5]); - SendStatusAndMessage(STATUS_GOOD, 0x00); -} - -// This data was originally taken from a PC-FXGA software loader, but -// while it was mostly correct(maybe it is correct for the FXGA, but not for the PC-FX?), -// it was 3 bytes too long, and the last real byte was 0x45 instead of 0x20. -// TODO: Investigate this discrepancy by testing an FXGA with the official loader software. -#if 0 -static const uint8 InqData[0x24] = -{ - // Standard - 0x05, 0x80, 0x02, 0x00, - - // Additional Length - 0x1F, - - // Vendor Specific - 0x00, 0x00, 0x00, 0x4E, 0x45, 0x43, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x43, 0x44, 0x2D, 0x52, 0x4F, - 0x4D, 0x20, 0x44, 0x52, 0x49, 0x56, 0x45, 0x3A, - 0x46, 0x58, 0x20, 0x31, 0x2E, 0x30, 0x20 -}; -#endif - -// Miraculum behaves differently if the last byte(offset 0x23) of the inquiry data is 0x45(ASCII character 'E'). Relavent code is at PC=0x3E382 -// If it's = 0x45, it will run MODE SELECT, and transfer this data to the CD unit: 00 00 00 00 29 01 00 -static const uint8 InqData[0x24] = -{ - // Peripheral device-type: CD-ROM/read-only direct access device - 0x05, - - // Removable media: yes - // Device-type qualifier: 0 - 0x80, - - // ISO version: 0 - // ECMA version: 0 - // ANSI version: 2 (SCSI-2? ORLY?) - 0x02, - - // Supports asynchronous event notification: no - // Supports the terminate I/O process message: no - // Response data format: 0 (not exactly correct, not exactly incorrect, meh. :b) - 0x00, - - // Additional Length - 0x1F, - - // Reserved - 0x00, 0x00, - - // Yay, no special funky features. - 0x00, - - // 8-15, vendor ID - // NEC - 0x4E, 0x45, 0x43, 0x20, 0x20, 0x20, 0x20, 0x20, - - // 16-31, product ID - // CD-ROM DRIVE:FX - 0x43, 0x44, 0x2D, 0x52, 0x4F, 0x4D, 0x20, 0x44, 0x52, 0x49, 0x56, 0x45, 0x3A, 0x46, 0x58, 0x20, - - // 32-35, product revision level - // 1.0 - 0x31, 0x2E, 0x30, 0x20 -}; - -static void DoINQUIRY(const uint8 *cdb) -{ - unsigned int AllocSize = (cdb[4] < sizeof(InqData)) ? cdb[4] : sizeof(InqData); - - if(AllocSize) - DoSimpleDataIn(InqData, AllocSize); - else - SendStatusAndMessage(STATUS_GOOD, 0x00); -} - -static void DoNEC_NOP(const uint8 *cdb) -{ - SendStatusAndMessage(STATUS_GOOD, 0x00); -} - - - -/******************************************************** -* * -* PC-FX CD Command 0xDC - EJECT * -* * -********************************************************/ -static void DoNEC_EJECT(const uint8 *cdb) -{ - CommandCCError(SENSEKEY_ILLEGAL_REQUEST, NSE_INVALID_REQUEST_IN_CDB); -} - -static void DoREQUESTSENSE(const uint8 *cdb) -{ - uint8 data_in[8192]; - - MakeSense(data_in, cd.key_pending, cd.asc_pending, cd.ascq_pending, cd.fru_pending); - - DoSimpleDataIn(data_in, 18); - - cd.key_pending = 0; - cd.asc_pending = 0; - cd.ascq_pending = 0; - cd.fru_pending = 0; -} - -static void EncodeM3TOC(uint8 *buf, uint8 POINTER_RAW, int32 LBA, uint32 PLBA, uint8 control) -{ - uint8 MIN, SEC, FRAC; - uint8 PMIN, PSEC, PFRAC; - - LBA_to_AMSF(LBA, &MIN, &SEC, &FRAC); - LBA_to_AMSF(PLBA, &PMIN, &PSEC, &PFRAC); - - buf[0x0] = control << 4; - buf[0x1] = 0x00; // TNO - buf[0x2] = POINTER_RAW; - buf[0x3] = U8_to_BCD(MIN); - buf[0x4] = U8_to_BCD(SEC); - buf[0x5] = U8_to_BCD(FRAC); - buf[0x6] = 0x00; // Zero - buf[0x7] = U8_to_BCD(PMIN); - buf[0x8] = U8_to_BCD(PSEC); - buf[0x9] = U8_to_BCD(PFRAC); -} - -/******************************************************** -* * -* PC-FX CD Command 0xDE - Get Directory Info * -* * -********************************************************/ -static void DoNEC_GETDIRINFO(const uint8 *cdb) -{ - // Problems: - // Mode 0x03 has a few semi-indeterminate(but within a range, and they only change when the disc is reloaded) fields on a real PC-FX, that correspond to where in the lead-in area the data - // was read, that we don't bother to handle here. - // Mode 0x03 returns weird/wrong control field data for the "last track" and "leadout" entries in the "Blue Breaker" TOC. - // A bug in the PC-FX CD firmware, or an oddity of the disc(maybe other PC-FX discs are similar)? Or maybe it's an undefined field in that context? - // "Match" value of 0xB0 is probably not handled properly. Is it to return the catalog number, or something else? - - uint8 data_in[2048]; - uint32 data_in_size = 0; - - memset(data_in, 0, sizeof(data_in)); - - switch(cdb[1] & 0x03) - { - // This commands returns relevant raw TOC data as encoded in the Q subchannel(sans the CRC bytes). - case 0x3: - { - int offset = 0; - int32 lilba = -150; - uint8 match = cdb[2]; - - if(match != 0x00 && match != 0xA0 && match != 0xA1 && match != 0xA2 && match != 0xB0) - { - CommandCCError(SENSEKEY_ILLEGAL_REQUEST, NSE_INVALID_ADDRESS); - return; - } - memset(data_in, 0, sizeof(data_in)); - - data_in[0] = 0x00; // Size MSB??? - data_in[1] = 0x00; // Total Size - 2(we'll fill it in later). - offset = 2; - - if(!match || match == 0xA0) - { - EncodeM3TOC(&data_in[offset], 0xA0, lilba, toc.first_track * 75 * 60 - 150, toc.tracks[toc.first_track].control); - lilba++; - offset += 0xA; - } - - if(!match || match == 0xA1) - { - EncodeM3TOC(&data_in[offset], 0xA1, lilba, toc.last_track * 75 * 60 - 150, toc.tracks[toc.last_track].control); - lilba++; - offset += 0xA; - } - - if(!match || match == 0xA2) - { - EncodeM3TOC(&data_in[offset], 0xA2, lilba, toc.tracks[100].lba, toc.tracks[100].control); - lilba++; - offset += 0xA; - } - - if(!match) - for(int track = toc.first_track; track <= toc.last_track; track++) - { - EncodeM3TOC(&data_in[offset], U8_to_BCD(track), lilba, toc.tracks[track].lba, toc.tracks[track].control); - lilba++; - offset += 0xA; - } - - if(match == 0xB0) - { - memset(&data_in[offset], 0, 0x14); - offset += 0x14; - } - - assert((unsigned int)offset <= sizeof(data_in)); - data_in_size = offset; - MDFN_en16msb(&data_in[0], offset - 2); - } - break; - - case 0x0: - data_in[0] = U8_to_BCD(toc.first_track); - data_in[1] = U8_to_BCD(toc.last_track); - - data_in_size = 4; - 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 = 4; - } - break; - - case 0x2: - { - uint8 m, s, f; - int track = BCD_to_U8(cdb[2]); - - if(track < toc.first_track || track > toc.last_track) - { - CommandCCError(SENSEKEY_ILLEGAL_REQUEST, NSE_INVALID_ADDRESS); - 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); -} - -static void DoREADTOC(const uint8 *cdb) -{ - uint8 data_in[8192]; - int FirstTrack = toc.first_track; - int LastTrack = toc.last_track; - int StartingTrack = cdb[6]; - unsigned int AllocSize = (cdb[7] << 8) | cdb[8]; - unsigned int RealSize = 0; - const bool WantInMSF = cdb[1] & 0x2; - - if(!AllocSize) - { - SendStatusAndMessage(STATUS_GOOD, 0x00); - return; - } - - if((cdb[1] & ~0x2) || cdb[2] || cdb[3] || cdb[4] || cdb[5] || cdb[9]) - { - CommandCCError(SENSEKEY_ILLEGAL_REQUEST, NSE_INVALID_PARAMETER); - return; - } - - if(!StartingTrack) - StartingTrack = 1; - else if(StartingTrack == 0xAA) - { - StartingTrack = LastTrack + 1; - } - else if(StartingTrack > toc.last_track) - { - CommandCCError(SENSEKEY_ILLEGAL_REQUEST, NSE_INVALID_PARAMETER); - return; - } - - data_in[2] = FirstTrack; - data_in[3] = LastTrack; - - RealSize += 4; - - // Read leadout track too LastTrack + 1 ??? - for(int track = StartingTrack; track <= (LastTrack + 1); track++) - { - uint8 *subptr = &data_in[RealSize]; - uint32 lba; - uint8 m, s, f; - uint32 eff_track; - - if(track == (LastTrack + 1)) - eff_track = 100; - else - eff_track = track; - - lba = toc.tracks[eff_track].lba; - LBA_to_AMSF(lba, &m, &s, &f); - - subptr[0] = 0; - subptr[1] = toc.tracks[eff_track].control | (toc.tracks[eff_track].adr << 4); - - if(eff_track == 100) - subptr[2] = 0xAA; - else - subptr[2] = track; - - subptr[3] = 0; - - if(WantInMSF) - { - subptr[4] = 0; - subptr[5] = m; // Min - subptr[6] = s; // Sec - subptr[7] = f; // Frames - } - else - { - subptr[4] = lba >> 24; - subptr[5] = lba >> 16; - subptr[6] = lba >> 8; - subptr[7] = lba >> 0; - } - RealSize += 8; - } - - // PC-FX: AllocSize too small doesn't reflect in this. - data_in[0] = (RealSize - 2) >> 8; - data_in[1] = (RealSize - 2) >> 0; - - DoSimpleDataIn(data_in, (AllocSize < RealSize) ? AllocSize : RealSize); -} - - - -/******************************************************** -* * -* SCSI-2 CD Command 0x25 - READ CD-ROM CAPACITY * -* * -********************************************************/ -static void DoREADCDCAP10(const uint8 *cdb) -{ - bool pmi = cdb[8] & 0x1; - uint32 lba = MDFN_de32msb(cdb + 0x2); - uint32 ret_lba; - uint32 ret_bl; - uint8 data_in[8]; - - memset(data_in, 0, sizeof(data_in)); - - if(lba > 0x05FF69) - { - CommandCCError(SENSEKEY_ILLEGAL_REQUEST, NSE_END_OF_VOLUME); - return; - } - - ret_lba = toc.tracks[100].lba - 1; - - if(pmi) - { - // Look for the track containing the LBA specified, then search for the first track afterwards that has a different track type(audio, data), - // and set the returned LBA to the sector preceding that track. - // - // If the specified LBA is >= leadout track, return the LBA of the sector immediately before the leadout track. - // - // If the specified LBA is < than the LBA of the first track, then return the LBA of sector preceding the first track. (I don't know if PC-FX can even handle discs like this, though) - if(lba >= toc.tracks[100].lba) - ret_lba = toc.tracks[100].lba - 1; - else if(lba < toc.tracks[toc.first_track].lba) - ret_lba = toc.tracks[toc.first_track].lba - 1; - else - { - const int track = toc.FindTrackByLBA(lba); - - for(int st = track + 1; st <= toc.last_track; st++) - { - if((toc.tracks[st].control ^ toc.tracks[track].control) & 0x4) - { - ret_lba = toc.tracks[st].lba - 1; - break; - } - } - } - } - - ret_bl = 2048; - - MDFN_en32msb(&data_in[0], ret_lba); - MDFN_en32msb(&data_in[4], ret_bl); - - cdda.CDDAStatus = CDDASTATUS_STOPPED; - - DoSimpleDataIn(data_in, 8); -} - -static void DoREADHEADER10(const uint8 *cdb) -{ - uint8 data_in[8192]; - bool WantInMSF = cdb[1] & 0x2; - uint32 HeaderLBA = MDFN_de32msb(cdb + 0x2); - int AllocSize = MDFN_de16msb(cdb + 0x7); - uint8 raw_buf[2352 + 96]; - uint8 mode; - int m, s, f; - uint32 lba; - - // Don't run command at all if AllocSize == 0(FIXME: On a real PC-FX, this command will return success - // if there's no CD when AllocSize == 0, implement this here, might require refactoring). - if(!AllocSize) - { - SendStatusAndMessage(STATUS_GOOD, 0x00); - return; - } - - if(HeaderLBA >= toc.tracks[100].lba) - { - CommandCCError(SENSEKEY_ILLEGAL_REQUEST, NSE_INVALID_PARAMETER); - return; - } - - if(HeaderLBA < toc.tracks[toc.first_track].lba) - { - CommandCCError(SENSEKEY_ILLEGAL_REQUEST, NSE_INVALID_PARAMETER); - return; - } - - Cur_CDIF->ReadRawSector(raw_buf, HeaderLBA); //, HeaderLBA + 1); - if(!ValidateRawDataSector(raw_buf, HeaderLBA)) - return; - - m = BCD_to_U8(raw_buf[12 + 0]); - s = BCD_to_U8(raw_buf[12 + 1]); - f = BCD_to_U8(raw_buf[12 + 2]); - mode = raw_buf[12 + 3]; - lba = AMSF_to_LBA(m, s, f); - - //printf("%d:%d:%d(LBA=%08x) %02x\n", m, s, f, lba, mode); - - data_in[0] = mode; - data_in[1] = 0; - data_in[2] = 0; - data_in[3] = 0; - - if(WantInMSF) - { - data_in[4] = 0; - data_in[5] = m; // Min - data_in[6] = s; // Sec - data_in[7] = f; // Frames - } - else - { - data_in[4] = lba >> 24; - data_in[5] = lba >> 16; - data_in[6] = lba >> 8; - data_in[7] = lba >> 0; - } - - cdda.CDDAStatus = CDDASTATUS_STOPPED; - - DoSimpleDataIn(data_in, 8); -} - -static void DoNEC_SST(const uint8 *cdb) // Command 0xDB, Set Stop Time -{ - SendStatusAndMessage(STATUS_GOOD, 0x00); -} - -static void DoPABase(const uint32 lba, const uint32 length, unsigned int status = CDDASTATUS_PLAYING, unsigned int mode = PLAYMODE_NORMAL) -{ - if(lba > toc.tracks[100].lba) // > is not a typo, it's a PC-FX bug apparently. - { - CommandCCError(SENSEKEY_ILLEGAL_REQUEST, NSE_INVALID_PARAMETER); - return; - } - - if(lba < toc.tracks[toc.first_track].lba) - { - CommandCCError(SENSEKEY_ILLEGAL_REQUEST, NSE_INVALID_PARAMETER); - return; - } - - if(!length) // FIXME to return good status in this case even if no CD is present - { - SendStatusAndMessage(STATUS_GOOD, 0x00); - return; - } - else - { - if(toc.tracks[toc.FindTrackByLBA(lba)].control & 0x04) - { - CommandCCError(SENSEKEY_MEDIUM_ERROR, NSE_NOT_AUDIO_TRACK); - return; - } - - cdda.CDDAReadPos = 588; - read_sec = read_sec_start = lba; - read_sec_end = read_sec_start + length; - - cdda.CDDAStatus = status; - cdda.PlayMode = mode; - - if(read_sec < toc.tracks[100].lba) - { - Cur_CDIF->HintReadSector(read_sec); //, read_sec_end, read_sec_start); - } - } - - SendStatusAndMessage(STATUS_GOOD, 0x00); -} - - - -/******************************************************** -* * -* PC-FX CD Command 0xD8 - SAPSP * -* * -********************************************************/ -static void DoNEC_SAPSP(const uint8 *cdb) -{ - uint32 lba; - - switch (cdb[9] & 0xc0) - { - default: - CommandCCError(SENSEKEY_ILLEGAL_REQUEST, NSE_INVALID_PARAMETER); - return; - break; - - case 0x00: - lba = MDFN_de24msb(&cdb[3]); - break; - - case 0x40: - { - uint8 m, s, f; - - if(!BCD_to_U8_check(cdb[2], &m) || !BCD_to_U8_check(cdb[3], &s) || !BCD_to_U8_check(cdb[4], &f)) - { - CommandCCError(SENSEKEY_ILLEGAL_REQUEST, NSE_INVALID_PARAMETER); - return; - } - - lba = AMSF_to_LBA(m, s, f); - } - break; - - case 0x80: - { - uint8 track; - - if(!cdb[2] || !BCD_to_U8_check(cdb[2], &track)) - { - CommandCCError(SENSEKEY_ILLEGAL_REQUEST, NSE_INVALID_PARAMETER); - return; - } - - if(track == toc.last_track + 1) - track = 100; - else if(track > toc.last_track) - { - CommandCCError(SENSEKEY_ILLEGAL_REQUEST, NSE_END_OF_VOLUME); - return; - } - lba = toc.tracks[track].lba; - } - break; - } - - if(cdb[1] & 0x01) - DoPABase(lba, toc.tracks[100].lba - lba, CDDASTATUS_PLAYING, PLAYMODE_NORMAL); - else - DoPABase(lba, toc.tracks[100].lba - lba, CDDASTATUS_PAUSED, PLAYMODE_SILENT); -} - - - -/******************************************************** -* * -* PC-FX CD Command 0xD9 - SAPEP * -* * -********************************************************/ -static void DoNEC_SAPEP(const uint8 *cdb) -{ - uint32 lba; - - if(cdda.CDDAStatus == CDDASTATUS_STOPPED) - { - CommandCCError(SENSEKEY_ILLEGAL_REQUEST, NSE_AUDIO_NOT_PLAYING); - return; - } - - switch (cdb[9] & 0xc0) - { - default: - CommandCCError(SENSEKEY_ILLEGAL_REQUEST, NSE_INVALID_PARAMETER); - return; - break; - - case 0x00: - lba = MDFN_de24msb(&cdb[3]); - break; - - case 0x40: - { - uint8 m, s, f; - - if(!BCD_to_U8_check(cdb[2], &m) || !BCD_to_U8_check(cdb[3], &s) || !BCD_to_U8_check(cdb[4], &f)) - { - CommandCCError(SENSEKEY_ILLEGAL_REQUEST, NSE_INVALID_PARAMETER); - return; - } - - lba = AMSF_to_LBA(m, s, f); - } - break; - - case 0x80: - { - uint8 track; - - if(!cdb[2] || !BCD_to_U8_check(cdb[2], &track)) - { - CommandCCError(SENSEKEY_ILLEGAL_REQUEST, NSE_INVALID_PARAMETER); - return; - } - - if(track == toc.last_track + 1) - track = 100; - else if(track > toc.last_track) - { - CommandCCError(SENSEKEY_ILLEGAL_REQUEST, NSE_END_OF_VOLUME); - return; - } - lba = toc.tracks[track].lba; - } - break; - } - - switch(cdb[1] & 0x7) - { - case 0x00: cdda.PlayMode = PLAYMODE_SILENT; - break; - - case 0x04: cdda.PlayMode = PLAYMODE_LOOP; - break; - - default: cdda.PlayMode = PLAYMODE_NORMAL; - break; - } - cdda.CDDAStatus = CDDASTATUS_PLAYING; - - read_sec_end = lba; - - SendStatusAndMessage(STATUS_GOOD, 0x00); -} - - - -/******************************************************** -* * -* SCSI-2 CD Command 0x45 - PLAY AUDIO(10) * -* * -********************************************************/ -static void DoPA10(const uint8 *cdb) -{ - // Real PC-FX Bug: Error out on LBA >(not >=) leadout sector number - const uint32 lba = MDFN_de32msb(cdb + 0x2); - const uint16 length = MDFN_de16msb(cdb + 0x7); - - DoPABase(lba, length); -} - - - -/******************************************************** -* * -* SCSI-2 CD Command 0xA5 - PLAY AUDIO(12) * -* * -********************************************************/ -static void DoPA12(const uint8 *cdb) -{ - // Real PC-FX Bug: Error out on LBA >(not >=) leadout sector number - const uint32 lba = MDFN_de32msb(cdb + 0x2); - const uint32 length = MDFN_de32msb(cdb + 0x6); - - DoPABase(lba, length); -} - - - -/******************************************************** -* * -* SCSI-2 CD Command 0x47 - PLAY AUDIO MSF * -* * -********************************************************/ -static void DoPAMSF(const uint8 *cdb) -{ - int32 lba_start, lba_end; - - lba_start = AMSF_to_LBA(cdb[3], cdb[4], cdb[5]); - lba_end = AMSF_to_LBA(cdb[6], cdb[7], cdb[8]); - - if(lba_start < 0 || lba_end < 0 || lba_start >= (int32)toc.tracks[100].lba) - { - CommandCCError(SENSEKEY_ILLEGAL_REQUEST, NSE_END_OF_VOLUME); - return; - } - - if(lba_start == lba_end) - { - SendStatusAndMessage(STATUS_GOOD, 0x00); - return; - } - else if(lba_start > lba_end) - { - CommandCCError(SENSEKEY_ILLEGAL_REQUEST, NSE_INVALID_ADDRESS); - return; - } - - cdda.CDDAReadPos = 588; - read_sec = read_sec_start = lba_start; - read_sec_end = lba_end; - - cdda.CDDAStatus = CDDASTATUS_PLAYING; - cdda.PlayMode = PLAYMODE_NORMAL; - - SendStatusAndMessage(STATUS_GOOD, 0x00); -} - - - -static void DoPATI(const uint8 *cdb) -{ - // "Boundary Gate" uses this command. - // Problems: - // The index fields aren't handled. The ending index wouldn't be too bad, but the starting index would require a bit of work and code uglyfying(to scan for the index), and may be highly - // problematic when Mednafen is used with a physical CD. - int StartTrack = cdb[4]; - int EndTrack = cdb[7]; - //int StartIndex = cdb[5]; - //int EndIndex = cdb[8]; - - if(!StartTrack || StartTrack < toc.first_track || StartTrack > toc.last_track) - { - CommandCCError(SENSEKEY_ILLEGAL_REQUEST, NSE_INVALID_PARAMETER); - return; - } - - //printf("PATI: %d %d %d SI: %d, EI: %d\n", StartTrack, EndTrack, Cur_CDIF->GetTrackStartPositionLBA(StartTrack), StartIndex, EndIndex); - - DoPABase(toc.tracks[StartTrack].lba, toc.tracks[EndTrack].lba - toc.tracks[StartTrack].lba); -} - - -static void DoPATRBase(const uint32 lba, const uint32 length) -{ - if(lba >= toc.tracks[100].lba) - { - CommandCCError(SENSEKEY_ILLEGAL_REQUEST, NSE_INVALID_PARAMETER); - return; - } - - if(lba < toc.tracks[toc.first_track].lba) - { - CommandCCError(SENSEKEY_ILLEGAL_REQUEST, NSE_INVALID_PARAMETER); - return; - } - - if(!length) // FIXME to return good status in this case even if no CD is present - { - SendStatusAndMessage(STATUS_GOOD, 0x00); - return; - } - else - { - if(toc.tracks[toc.FindTrackByLBA(lba)].control & 0x04) - { - CommandCCError(SENSEKEY_MEDIUM_ERROR, NSE_NOT_AUDIO_TRACK); - return; - } - - cdda.CDDAReadPos = 588; - read_sec = read_sec_start = lba; - read_sec_end = read_sec_start + length; - - cdda.CDDAStatus = CDDASTATUS_PLAYING; - cdda.PlayMode = PLAYMODE_NORMAL; - } - - SendStatusAndMessage(STATUS_GOOD, 0x00); -} - - -/******************************************************** -* * -* SCSI-2 CD Command 0x49 - PLAY AUDIO TRACK * -* RELATIVE(10) * -********************************************************/ -static void DoPATR10(const uint8 *cdb) -{ - const int32 rel_lba = MDFN_de32msb(cdb + 0x2); - const int StartTrack = cdb[6]; - const uint16 length = MDFN_de16msb(cdb + 0x7); - - if(!StartTrack || StartTrack < toc.first_track || StartTrack > toc.last_track) - { - CommandCCError(SENSEKEY_ILLEGAL_REQUEST, NSE_INVALID_PARAMETER); - return; - } - - DoPATRBase(toc.tracks[StartTrack].lba + rel_lba, length); -} - - - -/******************************************************** -* * -* SCSI-2 CD Command 0xA9 - PLAY AUDIO TRACK * -* RELATIVE(12) * -********************************************************/ -static void DoPATR12(const uint8 *cdb) -{ - const int32 rel_lba = MDFN_de32msb(cdb + 0x2); - const int StartTrack = cdb[10]; - const uint32 length = MDFN_de32msb(cdb + 0x6); - - if(!StartTrack || StartTrack < toc.first_track || StartTrack > toc.last_track) - { - CommandCCError(SENSEKEY_ILLEGAL_REQUEST, NSE_INVALID_PARAMETER); - return; - } - - DoPATRBase(toc.tracks[StartTrack].lba + rel_lba, length); -} - -static void DoPAUSERESUME(const uint8 *cdb) -{ - // Pause/resume - // "It shall not be considered an error to request a pause when a pause is already in effect, - // or to request a resume when a play operation is in progress." - - if(cdda.CDDAStatus == CDDASTATUS_STOPPED) - { - CommandCCError(SENSEKEY_ILLEGAL_REQUEST, NSE_AUDIO_NOT_PLAYING); - return; - } - - if(cdb[8] & 1) // Resume - cdda.CDDAStatus = CDDASTATUS_PLAYING; - else - cdda.CDDAStatus = CDDASTATUS_PAUSED; - - SendStatusAndMessage(STATUS_GOOD, 0x00); -} - - - - - -static void DoREADBase(uint32 sa, uint32 sc) -{ - int track; - - if(sa > toc.tracks[100].lba) // Another one of those off-by-one PC-FX CD bugs. - { - CommandCCError(SENSEKEY_ILLEGAL_REQUEST, NSE_END_OF_VOLUME); - return; - } - - if((track = toc.FindTrackByLBA(sa)) == 0) - { - CommandCCError(SENSEKEY_ILLEGAL_REQUEST, NSE_END_OF_VOLUME); - return; - } - - if(!(toc.tracks[track].control) & 0x4) - { - CommandCCError(SENSEKEY_MEDIUM_ERROR, NSE_NOT_DATA_TRACK); - return; - } - - // Case for READ(10) and READ(12) where sc == 0, and sa == toc.tracks[100].lba - if(!sc && sa == toc.tracks[100].lba) - { - CommandCCError(SENSEKEY_MEDIUM_ERROR, NSE_HEADER_READ_ERROR); - return; - } - - if(SCSILog) - { - int Track = toc.FindTrackByLBA(sa); - uint32 Offset = sa - toc.tracks[Track].lba; //Cur_CDIF->GetTrackStartPositionLBA(Track); - SCSILog("SCSI", "Read: start=0x%08x(track=%d, offs=0x%08x), cnt=0x%08x", sa, Track, Offset, sc); - } - - SectorAddr = sa; - SectorCount = sc; - if(SectorCount) - { - Cur_CDIF->HintReadSector(sa); //, sa + sc); - - CDReadTimer = (uint64)1 * 2048 * System_Clock / CD_DATA_TRANSFER_RATE; - } - else - { - CDReadTimer = 0; - SendStatusAndMessage(STATUS_GOOD, 0x00); - } - cdda.CDDAStatus = CDDASTATUS_STOPPED; -} - - - -/******************************************************** -* * -* SCSI-2 CD Command 0x08 - READ(6) * -* * -********************************************************/ -static void DoREAD6(const uint8 *cdb) -{ - uint32 sa = ((cdb[1] & 0x1F) << 16) | (cdb[2] << 8) | (cdb[3] << 0); - uint32 sc = cdb[4]; - - // TODO: confirm real PCE does this(PC-FX does at least). - if(!sc) - { - //SCSIDBG("READ(6) with count == 0.\n"); - sc = 256; - } - - DoREADBase(sa, sc); -} - - - -/******************************************************** -* * -* SCSI-2 CD Command 0x28 - READ(10) * -* * -********************************************************/ -static void DoREAD10(const uint8 *cdb) -{ - uint32 sa = MDFN_de32msb(cdb + 0x2); - uint32 sc = MDFN_de16msb(cdb + 0x7); - - DoREADBase(sa, sc); -} - - - -/******************************************************** -* * -* SCSI-2 CD Command 0xA8 - READ(12) * -* * -********************************************************/ -static void DoREAD12(const uint8 *cdb) -{ - uint32 sa = MDFN_de32msb(cdb + 0x2); - uint32 sc = MDFN_de32msb(cdb + 0x6); - - DoREADBase(sa, sc); -} - - - -/******************************************************** -* * -* SCSI-2 CD Command 0x34 - PREFETCH(10) * -* * -********************************************************/ -static void DoPREFETCH(const uint8 *cdb) -{ - uint32 lba = MDFN_de32msb(cdb + 0x2); - //uint32 len = MDFN_de16msb(cdb + 0x7); - //bool reladdr = cdb[1] & 0x1; - //bool immed = cdb[1] & 0x2; - - // Note: This command appears to lock up the CD unit to some degree on a real PC-FX if the (lba + len) >= leadout_track_lba, - // more testing is needed if we ever try to fully emulate this command. - if(lba >= toc.tracks[100].lba) - { - CommandCCError(SENSEKEY_ILLEGAL_REQUEST, NSE_END_OF_VOLUME); - return; - } - - //printf("Prefetch: %08x %08x %d %d %d %d\n", lba, len, link, flag, reladdr, immed); - //SendStatusAndMessage(STATUS_GOOD, 0x00); - SendStatusAndMessage(STATUS_CONDITION_MET, 0x00); -} - - - - -// SEEK functions are mostly just stubs for now, until(if) we emulate seek delays. -static void DoSEEKBase(uint32 lba) -{ - if(lba >= toc.tracks[100].lba) - { - CommandCCError(SENSEKEY_ILLEGAL_REQUEST, NSE_END_OF_VOLUME); - return; - } - - cdda.CDDAStatus = CDDASTATUS_STOPPED; - SendStatusAndMessage(STATUS_GOOD, 0x00); -} - - - -/******************************************************** -* * -* SCSI-2 CD Command 0x0B - SEEK(6) * -* * -********************************************************/ -static void DoSEEK6(const uint8 *cdb) -{ - uint32 lba = ((cdb[1] & 0x1F) << 16) | (cdb[2] << 8) | cdb[3]; - - DoSEEKBase(lba); -} - - - -/******************************************************** -* * -* SCSI-2 CD Command 0x2B - SEEK(10) * -* * -********************************************************/ -static void DoSEEK10(const uint8 *cdb) -{ - uint32 lba = MDFN_de32msb(cdb + 0x2); - - DoSEEKBase(lba); -} - -// 353 -/******************************************************** -* * -* SCSI-2 CD Command 0x42 - READ SUB-CHANNEL(10) * -* * -********************************************************/ -static void DoREADSUBCHANNEL(const uint8 *cdb) -{ - uint8 data_in[8192]; - int DataFormat = cdb[3]; - int TrackNum = cdb[6]; - unsigned AllocSize = (cdb[7] << 8) | cdb[8]; - bool WantQ = cdb[2] & 0x40; - bool WantMSF = cdb[1] & 0x02; - uint32 offset = 0; - - if(!AllocSize) - { - SendStatusAndMessage(STATUS_GOOD, 0x00); - return; - } - - if(DataFormat > 0x3) - { - CommandCCError(SENSEKEY_ILLEGAL_REQUEST, NSE_INVALID_PARAMETER); - return; - } - - if(DataFormat == 0x3 && (TrackNum < toc.first_track || TrackNum > toc.last_track)) - { - CommandCCError(SENSEKEY_ILLEGAL_REQUEST, NSE_INVALID_PARAMETER); - return; - } - - data_in[offset++] = 0; - - // FIXME: Is this audio status code correct for scanning playback?? - if(cdda.CDDAStatus == CDDASTATUS_PLAYING || cdda.CDDAStatus == CDDASTATUS_SCANNING) - data_in[offset++] = 0x11; // Audio play operation in progress - else if(cdda.CDDAStatus == CDDASTATUS_PAUSED) - data_in[offset++] = 0x12; // Audio play operation paused - else - data_in[offset++] = 0x13; // 0x13(audio play operation completed successfully) or 0x15(no current audio status to return)? :( - - - // Subchannel data length(at data_in[0x2], filled out at the end of the function) - data_in[offset++] = 0x00; - data_in[offset++] = 0x00; - - //printf("42Read SubChannel: %02x %02x %d %d %d\n", DataFormat, TrackNum, AllocSize, WantQ, WantMSF); - if(WantQ) - { - // Sub-channel format code - data_in[offset++] = DataFormat; - if(!DataFormat || DataFormat == 0x01) - { - uint8 *SubQBuf = cd.SubQBuf[QMode_Time]; - - data_in[offset++] = ((SubQBuf[0] & 0x0F) << 4) | ((SubQBuf[0] & 0xF0) >> 4); // Control/adr - data_in[offset++] = SubQBuf[1]; // Track - data_in[offset++] = SubQBuf[2]; // Index - - // Absolute CD-ROM address - if(WantMSF) - { - data_in[offset++] = 0; - data_in[offset++] = BCD_to_U8(SubQBuf[7]); // M - data_in[offset++] = BCD_to_U8(SubQBuf[8]); // S - data_in[offset++] = BCD_to_U8(SubQBuf[9]); // F - } - else - { - uint32 tmp_lba = BCD_to_U8(SubQBuf[7]) * 60 * 75 + BCD_to_U8(SubQBuf[8]) * 75 + BCD_to_U8(SubQBuf[9]) - 150; - - data_in[offset++] = tmp_lba >> 24; - data_in[offset++] = tmp_lba >> 16; - data_in[offset++] = tmp_lba >> 8; - data_in[offset++] = tmp_lba >> 0; - } - - // Relative CD-ROM address - if(WantMSF) - { - data_in[offset++] = 0; - data_in[offset++] = BCD_to_U8(SubQBuf[3]); // M - data_in[offset++] = BCD_to_U8(SubQBuf[4]); // S - data_in[offset++] = BCD_to_U8(SubQBuf[5]); // F - } - else - { - uint32 tmp_lba = BCD_to_U8(SubQBuf[3]) * 60 * 75 + BCD_to_U8(SubQBuf[4]) * 75 + BCD_to_U8(SubQBuf[5]); // Don't subtract 150 in the conversion! - - data_in[offset++] = tmp_lba >> 24; - data_in[offset++] = tmp_lba >> 16; - data_in[offset++] = tmp_lba >> 8; - data_in[offset++] = tmp_lba >> 0; - } - } - - if(!DataFormat || DataFormat == 0x02) - { - if(DataFormat == 0x02) - { - data_in[offset++] = 0x00; - data_in[offset++] = 0x00; - data_in[offset++] = 0x00; - } - data_in[offset++] = 0x00; // MCVal and reserved. - for(int i = 0; i < 15; i++) - data_in[offset++] = 0x00; - } - - // Track ISRC - if(!DataFormat || DataFormat == 0x03) - { - if(DataFormat == 0x03) - { - uint8 *SubQBuf = cd.SubQBuf[QMode_Time]; // FIXME - data_in[offset++] = ((SubQBuf[0] & 0x0F) << 4) | ((SubQBuf[0] & 0xF0) >> 4); // Control/adr - data_in[offset++] = TrackNum; // From sub Q or from parameter? - data_in[offset++] = 0x00; // Reserved. - } - data_in[offset++] = 0x00; // TCVal and reserved - for(int i = 0; i < 15; i++) - data_in[offset++] = 0x00; - } - } - - MDFN_en16msb(&data_in[0x2], offset - 0x4); - - DoSimpleDataIn(data_in, (AllocSize > offset) ? offset : AllocSize); -} - - - -/******************************************************** -* * -* PC-FX CD Command 0xDD - READ SUB Q * -* * -********************************************************/ -static void DoNEC_READSUBQ(const uint8 *cdb) -{ - uint8 *SubQBuf = cd.SubQBuf[QMode_Time]; - uint8 data_in[10]; - const uint8 alloc_size = (cdb[1] < 10) ? cdb[1] : 10; - - memset(data_in, 0x00, 10); - - 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 - - data_in[1] = SubQBuf[0]; // Control/adr - 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) - - DoSimpleDataIn(data_in, alloc_size); -} - -static void DoTESTUNITREADY(const uint8 *cdb) -{ - SendStatusAndMessage(STATUS_GOOD, 0x00); -} - -static void DoNEC_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); - } -} - -static void DoNEC_SCAN(const uint8 *cdb) -{ - uint32 sector_tmp = 0; - - // 0: 0xD2 - // 1: 0x03 = reverse scan, 0x02 = forward scan - // 2: End M - // 3: End S - // 4: End F - - switch (cdb[9] & 0xc0) - { - default: - //SCSIDBG("Unknown NECSCAN format"); - break; - - case 0x00: - sector_tmp = (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; - break; - - case 0x40: - sector_tmp = AMSF_to_LBA(BCD_to_U8(cdb[2]), BCD_to_U8(cdb[3]), BCD_to_U8(cdb[4])); - break; - - case 0x80: // FIXME: error on invalid track number??? - sector_tmp = toc.tracks[BCD_to_U8(cdb[2])].lba; - break; - } - - cdda.ScanMode = cdb[1] & 0x3; - cdda.scan_sec_end = sector_tmp; - - if(cdda.CDDAStatus != CDDASTATUS_STOPPED) - { - if(cdda.ScanMode) - { - cdda.CDDAStatus = CDDASTATUS_SCANNING; - } - } - SendStatusAndMessage(STATUS_GOOD, 0x00); -} - - - -/******************************************************** -* * -* SCSI-2 CD Command 0x1E - PREVENT/ALLOW MEDIUM * -* REMOVAL * -********************************************************/ -static void DoPREVENTALLOWREMOVAL(const uint8 *cdb) -{ - //bool prevent = cdb[4] & 0x01; - //const int logical_unit = cdb[1] >> 5; - //SCSIDBG("PREVENT ALLOW MEDIUM REMOVAL: %d for %d\n", cdb[4] & 0x1, logical_unit); - //SendStatusAndMessage(STATUS_GOOD, 0x00); - - CommandCCError(SENSEKEY_ILLEGAL_REQUEST, NSE_INVALID_REQUEST_IN_CDB); -} - -// -// -// -#include "scsicd-pce-commands.inc" - - -#define SCF_REQUIRES_MEDIUM 0x0001 -#define SCF_INCOMPLETE 0x4000 -#define SCF_UNTESTED 0x8000 - -typedef struct -{ - uint8 cmd; - uint32 flags; - void (*func)(const uint8 *cdb); - const char *pretty_name; - const char *format_string; -} SCSICH; - -static const int32 RequiredCDBLen[16] = -{ - 6, // 0x0n - 6, // 0x1n - 10, // 0x2n - 10, // 0x3n - 10, // 0x4n - 10, // 0x5n - 10, // 0x6n - 10, // 0x7n - 10, // 0x8n - 10, // 0x9n - 12, // 0xAn - 12, // 0xBn - 10, // 0xCn - 10, // 0xDn - 10, // 0xEn - 10, // 0xFn -}; - -static SCSICH PCFXCommandDefs[] = -{ - { 0x00, SCF_REQUIRES_MEDIUM, DoTESTUNITREADY, "Test Unit Ready" }, - { 0x01, 0/* ? */, DoREZEROUNIT, "Rezero Unit" }, - { 0x03, 0, DoREQUESTSENSE, "Request Sense" }, - { 0x08, SCF_REQUIRES_MEDIUM, DoREAD6, "Read(6)" }, - { 0x0B, SCF_REQUIRES_MEDIUM, DoSEEK6, "Seek(6)" }, - { 0x0D, 0, DoNEC_NOP, "No Operation" }, - { 0x12, 0, DoINQUIRY, "Inquiry" }, - { 0x15, 0, DoMODESELECT6, "Mode Select(6)" }, - // TODO: { 0x16, 0 /* ? */, DoRESERVE, "Reserve" }, // 9.2.12 - // TODO: { 0x17, 0 /* ? */, DoRELEASE, "Release" }, // 9.2.11 - { 0x1A, 0, DoMODESENSE6, "Mode Sense(6)" }, - { 0x1B, SCF_REQUIRES_MEDIUM, DoSTARTSTOPUNIT6, "Start/Stop Unit" }, // 9.2.17 - // TODO: { 0x1D, , DoSENDDIAG, "Send Diagnostic" }, // 8.2.15 - { 0x1E, 0, DoPREVENTALLOWREMOVAL, "Prevent/Allow Media Removal" }, - - { 0x25, SCF_REQUIRES_MEDIUM, DoREADCDCAP10, "Read CD-ROM Capacity" }, // 14.2.8 - { 0x28, SCF_REQUIRES_MEDIUM, DoREAD10, "Read(10)" }, - { 0x2B, SCF_REQUIRES_MEDIUM, DoSEEK10, "Seek(10)" }, - - // TODO: { 0x2F, SCF_REQUIRES_MEDIUM, DoVERIFY10, "Verify(10)" }, // 16.2.11 - - { 0x34, SCF_REQUIRES_MEDIUM, DoPREFETCH, "Prefetch" }, - // TODO: { 0x3B, 0, 10, DoWRITEBUFFER, "Write Buffer" }, // 8.2.17 - // TODO: { 0x3C, 0, 10, DoREADBUFFER, "Read Buffer" }, // 8.2.12 - - { 0x42, SCF_REQUIRES_MEDIUM, DoREADSUBCHANNEL, "Read Subchannel" }, - { 0x43, SCF_REQUIRES_MEDIUM, DoREADTOC, "Read TOC" }, - { 0x44, SCF_REQUIRES_MEDIUM, DoREADHEADER10, "Read Header" }, - - { 0x45, SCF_REQUIRES_MEDIUM, DoPA10, "Play Audio(10)" }, - { 0x47, SCF_REQUIRES_MEDIUM, DoPAMSF, "Play Audio MSF" }, - { 0x48, SCF_REQUIRES_MEDIUM, DoPATI, "Play Audio Track Index" }, - { 0x49, SCF_REQUIRES_MEDIUM, DoPATR10, "Play Audio Track Relative(10)" }, - { 0x4B, SCF_REQUIRES_MEDIUM, DoPAUSERESUME, "Pause/Resume" }, - - { 0xA5, SCF_REQUIRES_MEDIUM, DoPA12, "Play Audio(12)" }, - { 0xA8, SCF_REQUIRES_MEDIUM, DoREAD12, "Read(12)" }, - { 0xA9, SCF_REQUIRES_MEDIUM, DoPATR12, "Play Audio Track Relative(12)" }, - - // TODO: { 0xAF, SCF_REQUIRES_MEDIUM, DoVERIFY12, "Verify(12)" }, // 16.2.12 - - { 0xD2, SCF_REQUIRES_MEDIUM, DoNEC_SCAN, "Scan" }, - { 0xD8, SCF_REQUIRES_MEDIUM, DoNEC_SAPSP, "Set Audio Playback Start Position" }, // "Audio track search" - { 0xD9, SCF_REQUIRES_MEDIUM, DoNEC_SAPEP, "Set Audio Playback End Position" }, // "Play" - { 0xDA, SCF_REQUIRES_MEDIUM, DoNEC_PAUSE, "Pause" }, // "Still" - { 0xDB, SCF_REQUIRES_MEDIUM | SCF_UNTESTED, DoNEC_SST, "Set Stop Time" }, - { 0xDC, SCF_REQUIRES_MEDIUM, DoNEC_EJECT, "Eject" }, - { 0xDD, SCF_REQUIRES_MEDIUM, DoNEC_READSUBQ, "Read Subchannel Q" }, - { 0xDE, SCF_REQUIRES_MEDIUM, DoNEC_GETDIRINFO, "Get Dir Info" }, - - { 0xFF, 0, 0, NULL, NULL }, -}; - -static SCSICH PCECommandDefs[] = -{ - { 0x00, SCF_REQUIRES_MEDIUM, DoTESTUNITREADY, "Test Unit Ready" }, - { 0x03, 0, DoREQUESTSENSE, "Request Sense" }, - { 0x08, SCF_REQUIRES_MEDIUM, DoREAD6, "Read(6)" }, - //{ 0x15, DoMODESELECT6, "Mode Select(6)" }, - { 0xD8, SCF_REQUIRES_MEDIUM, DoNEC_PCE_SAPSP, "Set Audio Playback Start Position" }, - { 0xD9, SCF_REQUIRES_MEDIUM, DoNEC_PCE_SAPEP, "Set Audio Playback End Position" }, - { 0xDA, SCF_REQUIRES_MEDIUM, DoNEC_PCE_PAUSE, "Pause" }, - { 0xDD, SCF_REQUIRES_MEDIUM, DoNEC_PCE_READSUBQ, "Read Subchannel Q" }, - { 0xDE, SCF_REQUIRES_MEDIUM, DoNEC_PCE_GETDIRINFO, "Get Dir Info" }, - - { 0xFF, 0, 0, NULL, NULL }, -}; - -void SCSICD_ResetTS(uint32 ts_base) -{ - lastts = ts_base; -} - -void SCSICD_GetCDDAValues(int16 &left, int16 &right) -{ - if(cdda.CDDAStatus) - { - left = cdda.sr[0]; - right = cdda.sr[1]; - } - else - left = right = 0; -} - -#define CDDA_FILTER_NUMCONVOLUTIONS 7 -#define CDDA_FILTER_NUMCONVOLUTIONS_PADDED 8 - -#define CDDA_FILTER_NUMPHASES_SHIFT 6 -#define CDDA_FILTER_NUMPHASES (1 << CDDA_FILTER_NUMPHASES_SHIFT) - -alignas(16) static const int16 CDDA_Filter[1 + CDDA_FILTER_NUMPHASES + 1][CDDA_FILTER_NUMCONVOLUTIONS_PADDED] = -{ - #include "scsicd_cdda_filter.inc" -}; - -alignas(16) static const int16 OversampleFilter[2][0x10] = -{ - { -82, 217, -463, 877, -1562, 2783, -5661, 29464, 9724, -3844, 2074, -1176, 645, -323, 138, -43, }, /* sum=32768, sum_abs=59076 */ - { -43, 138, -323, 645, -1176, 2074, -3844, 9724, 29464, -5661, 2783, -1562, 877, -463, 217, -82, }, /* sum=32768, sum_abs=59076 */ -}; - -static INLINE void RunCDDA(uint32 system_timestamp, int32 run_time) -{ - if(cdda.CDDAStatus == CDDASTATUS_PLAYING || cdda.CDDAStatus == CDDASTATUS_SCANNING) - { - cdda.CDDADiv -= (int64)run_time << 20; - - while(cdda.CDDADiv <= 0) - { - const uint32 synthtime_ex = (((uint64)system_timestamp << 20) + (int64)cdda.CDDADiv) / cdda.CDDATimeDiv; - const int synthtime = (synthtime_ex >> 16) & 0xFFFF; // & 0xFFFF(or equivalent) to prevent overflowing HRBufs[] - const int synthtime_phase = (int)(synthtime_ex & 0xFFFF) - 0x80; - const int synthtime_phase_int = synthtime_phase >> (16 - CDDA_FILTER_NUMPHASES_SHIFT); - const int synthtime_phase_fract = synthtime_phase & ((1 << (16 - CDDA_FILTER_NUMPHASES_SHIFT)) - 1); - int32 sample_va[2]; - - cdda.CDDADiv += cdda.CDDADivAcc; - - if(!(cdda.OversamplePos & 1)) - { - if(cdda.CDDAReadPos == 588) - { - if(read_sec >= read_sec_end || (cdda.CDDAStatus == CDDASTATUS_SCANNING && read_sec == cdda.scan_sec_end)) - { - switch(cdda.PlayMode) - { - case PLAYMODE_SILENT: - case PLAYMODE_NORMAL: - cdda.CDDAStatus = CDDASTATUS_STOPPED; - break; - - case PLAYMODE_INTERRUPT: - cdda.CDDAStatus = CDDASTATUS_STOPPED; - CDIRQCallback(SCSICD_IRQ_DATA_TRANSFER_DONE); - break; - - case PLAYMODE_LOOP: - read_sec = read_sec_start; - break; - } - - // If CDDA playback is stopped, break out of our while(CDDADiv ...) loop and don't play any more sound! - if(cdda.CDDAStatus == CDDASTATUS_STOPPED) - break; - } - - // Don't play past the user area of the disc. - if(read_sec >= toc.tracks[100].lba) - { - cdda.CDDAStatus = CDDASTATUS_STOPPED; - break; - } - - if(TrayOpen || !Cur_CDIF) - { - cdda.CDDAStatus = CDDASTATUS_STOPPED; - - #if 0 - cd.data_transfer_done = FALSE; - cd.key_pending = SENSEKEY_NOT_READY; - cd.asc_pending = ASC_MEDIUM_NOT_PRESENT; - cd.ascq_pending = 0x00; - cd.fru_pending = 0x00; - SendStatusAndMessage(STATUS_CHECK_CONDITION, 0x00); - #endif - - break; - } - - - cdda.CDDAReadPos = 0; - - { - uint8 tmpbuf[2352 + 96]; - - Cur_CDIF->ReadRawSector(tmpbuf, read_sec); //, read_sec_end, read_sec_start); - - for(int i = 0; i < 588 * 2; i++) - cdda.CDDASectorBuffer[i] = MDFN_de16lsb(&tmpbuf[i * 2]); - - memcpy(cd.SubPWBuf, tmpbuf + 2352, 96); - } - GenSubQFromSubPW(); - - if(!(cd.SubQBuf_Last[0] & 0x10)) - { - // Not using de-emphasis, so clear the de-emphasis filter state. - memset(cdda.DeemphState, 0, sizeof(cdda.DeemphState)); - } - - if(cdda.CDDAStatus == CDDASTATUS_SCANNING) - { - int64 tmp_read_sec = read_sec; - - if(cdda.ScanMode & 1) - { - tmp_read_sec -= 24; - if(tmp_read_sec < cdda.scan_sec_end) - tmp_read_sec = cdda.scan_sec_end; - } - else - { - tmp_read_sec += 24; - if(tmp_read_sec > cdda.scan_sec_end) - tmp_read_sec = cdda.scan_sec_end; - } - read_sec = tmp_read_sec; - } - else - read_sec++; - } // End if(CDDAReadPos == 588) - - if(!(cdda.CDDAReadPos % 6)) - { - int subindex = cdda.CDDAReadPos / 6 - 2; - - if(subindex >= 0) - CDStuffSubchannels(cd.SubPWBuf[subindex], subindex); - else // The system-specific emulation code should handle what value the sync bytes are. - CDStuffSubchannels(0x00, subindex); - } - - // If the last valid sub-Q data decoded indicate that the corresponding sector is a data sector, don't output the - // current sector as audio. - if(!(cd.SubQBuf_Last[0] & 0x40) && cdda.PlayMode != PLAYMODE_SILENT) - { - cdda.sr[0] = cdda.CDDASectorBuffer[cdda.CDDAReadPos * 2 + cdda.OutPortChSelectCache[0]]; - cdda.sr[1] = cdda.CDDASectorBuffer[cdda.CDDAReadPos * 2 + cdda.OutPortChSelectCache[1]]; - } - -#if 0 - { - static int16 wv = 0x7FFF; //0x5000; - static unsigned counter = 0; - static double phase = 0; - static double phase_inc = 0; - static const double phase_inc_inc = 0.000003 / 2; - - cdda.sr[0] = 32767 * sin(phase); - cdda.sr[1] = 32767 * sin(phase); - - //cdda.sr[0] = wv; - //cdda.sr[1] = wv; - - if(counter == 0) - wv = -wv; - counter = (counter + 1) & 1; - phase += phase_inc; - phase_inc += phase_inc_inc; - } -#endif - - { - const unsigned obwp = cdda.OversamplePos >> 1; - cdda.OversampleBuffer[0][obwp] = cdda.OversampleBuffer[0][0x10 + obwp] = cdda.sr[0]; - cdda.OversampleBuffer[1][obwp] = cdda.OversampleBuffer[1][0x10 + obwp] = cdda.sr[1]; - } - - cdda.CDDAReadPos++; - } // End if(!(cdda.OversamplePos & 1)) - - { - const int16* f = OversampleFilter[cdda.OversamplePos & 1]; -#if defined(__SSE2__) - __m128i f0 = _mm_load_si128((__m128i *)&f[0]); - __m128i f1 = _mm_load_si128((__m128i *)&f[8]); -#endif - - for(unsigned lr = 0; lr < 2; lr++) - { - const int16* b = &cdda.OversampleBuffer[lr][((cdda.OversamplePos >> 1) + 1) & 0xF]; -#if defined(__SSE2__) - union - { - int32 accum; - float accum_f; - //__m128i accum_m128; - }; - - { - __m128i b0; - __m128i b1; - __m128i sum; - - b0 = _mm_loadu_si128((__m128i *)&b[0]); - b1 = _mm_loadu_si128((__m128i *)&b[8]); - - sum = _mm_add_epi32(_mm_madd_epi16(f0, b0), _mm_madd_epi16(f1, b1)); - sum = _mm_add_epi32(sum, _mm_shuffle_epi32(sum, (3 << 0) | (2 << 2) | (1 << 4) | (0 << 6))); - sum = _mm_add_epi32(sum, _mm_shuffle_epi32(sum, (1 << 0) | (0 << 2) | (3 << 4) | (2 << 6))); - _mm_store_ss(&accum_f, (__m128)sum); - //_mm_store_si128(&accum_m128, sum); - } -#else - int32 accum = 0; - - for(unsigned i = 0; i < 0x10; i++) - accum += f[i] * b[i]; -#endif - // sum_abs * cdda_min = - // 59076 * -32768 = -1935802368 - // OPVC can have a maximum value of 65536. - // -1935802368 * 65536 = -126864743989248 - // - // -126864743989248 / 65536 = -1935802368 - sample_va[lr] = ((int64)accum * cdda.OutPortVolumeCache[lr]) >> 16; - // Output of this stage will be (approximate max ranges) -2147450880 through 2147385345. - } - } - - // - // This de-emphasis filter's frequency response isn't totally correct, but it's much better than nothing(and it's not like any known PCE CD/TG16 CD/PC-FX games - // utilize pre-emphasis anyway). - // - if(MDFN_UNLIKELY(cd.SubQBuf_Last[0] & 0x10)) - { - //puts("Deemph"); - for(unsigned lr = 0; lr < 2; lr++) - { - float inv = sample_va[lr] * 0.35971507338824012f; - - cdda.DeemphState[lr][1] = (cdda.DeemphState[lr][0] - 0.4316395666f * inv) + (0.7955522347f * cdda.DeemphState[lr][1]); - cdda.DeemphState[lr][0] = inv; - - sample_va[lr] = std::max(-2147483648.0, std::min(2147483647.0, cdda.DeemphState[lr][1])); - //printf("%u: %f, %d\n", lr, cdda.DeemphState[lr][1], sample_va[lr]); - } - } - - - if(HRBufs[0] && HRBufs[1]) - { - // - // FINAL_OUT_SHIFT should be 32 so we can take advantage of 32x32->64 multipliers on 32-bit CPUs. - // - #define FINAL_OUT_SHIFT 32 - #define MULT_SHIFT_ADJ (32 - (26 + (8 - CDDA_FILTER_NUMPHASES_SHIFT))) - - #if (((1 << (16 - CDDA_FILTER_NUMPHASES_SHIFT)) - 0) << MULT_SHIFT_ADJ) > 32767 - #error "COEFF MULT OVERFLOW" - #endif - - const int16 mult_a = ((1 << (16 - CDDA_FILTER_NUMPHASES_SHIFT)) - synthtime_phase_fract) << MULT_SHIFT_ADJ; - const int16 mult_b = synthtime_phase_fract << MULT_SHIFT_ADJ; - int32 coeff[CDDA_FILTER_NUMCONVOLUTIONS]; - - //if(synthtime_phase_fract == 0) - // printf("%5d: %d %d\n", synthtime_phase_fract, mult_a, mult_b); - - for(unsigned c = 0; c < CDDA_FILTER_NUMCONVOLUTIONS; c++) - { - coeff[c] = (CDDA_Filter[1 + synthtime_phase_int + 0][c] * mult_a + - CDDA_Filter[1 + synthtime_phase_int + 1][c] * mult_b); - } - - int32* tb0 = &HRBufs[0][synthtime]; - int32* tb1 = &HRBufs[1][synthtime]; - - for(unsigned c = 0; c < CDDA_FILTER_NUMCONVOLUTIONS; c++) - { - tb0[c] += ((int64)coeff[c] * sample_va[0]) >> FINAL_OUT_SHIFT; - tb1[c] += ((int64)coeff[c] * sample_va[1]) >> FINAL_OUT_SHIFT; - } - #undef FINAL_OUT_SHIFT - #undef MULT_SHIFT_ADJ - } - - cdda.OversamplePos = (cdda.OversamplePos + 1) & 0x1F; - } // end while(cdda.CDDADiv <= 0) - } -} - -static INLINE void RunCDRead(uint32 system_timestamp, int32 run_time) -{ - if(CDReadTimer > 0) - { - CDReadTimer -= run_time; - - if(CDReadTimer <= 0) - { - if(din->CanWrite() < ((WhichSystem == SCSICD_PCFX) ? 2352 : 2048)) // +96 if we find out the PC-FX can read subchannel data along with raw data too. ;) - { - //printf("Carp: %d %d %d\n", din->CanWrite(), SectorCount, CDReadTimer); - //CDReadTimer = (cd.data_in_size - cd.data_in_pos) * 10; - - CDReadTimer += (uint64) 1 * 2048 * System_Clock / CD_DATA_TRANSFER_RATE; - - //CDReadTimer += (uint64) 1 * 128 * System_Clock / CD_DATA_TRANSFER_RATE; - } - else - { - uint8 tmp_read_buf[2352 + 96]; - - if(TrayOpen) - { - din->Flush(); - cd.data_transfer_done = FALSE; - - CommandCCError(SENSEKEY_NOT_READY, NSE_TRAY_OPEN); - } - else if(!Cur_CDIF) - { - CommandCCError(SENSEKEY_NOT_READY, NSE_NO_DISC); - } - else if(SectorAddr >= toc.tracks[100].lba) - { - CommandCCError(SENSEKEY_ILLEGAL_REQUEST, NSE_END_OF_VOLUME); - } - else if(!Cur_CDIF->ReadRawSector(tmp_read_buf, SectorAddr)) //, SectorAddr + SectorCount)) - { - cd.data_transfer_done = FALSE; - - CommandCCError(SENSEKEY_ILLEGAL_REQUEST); - } - else if(ValidateRawDataSector(tmp_read_buf, SectorAddr)) - { - memcpy(cd.SubPWBuf, tmp_read_buf + 2352, 96); - - if(tmp_read_buf[12 + 3] == 0x2) - din->Write(tmp_read_buf + 24, 2048); - else - din->Write(tmp_read_buf + 16, 2048); - - GenSubQFromSubPW(); - - CDIRQCallback(SCSICD_IRQ_DATA_TRANSFER_READY); - - SectorAddr++; - SectorCount--; - - if(CurrentPhase != PHASE_DATA_IN) - ChangePhase(PHASE_DATA_IN); - - if(SectorCount) - { - cd.data_transfer_done = FALSE; - CDReadTimer += (uint64) 1 * 2048 * System_Clock / CD_DATA_TRANSFER_RATE; - } - else - { - cd.data_transfer_done = TRUE; - } - } - } // end else to if(!Cur_CDIF->ReadSector - - } - } -} - - -uint32 SCSICD_Run(scsicd_timestamp_t system_timestamp) -{ - int32 run_time = system_timestamp - lastts; - - if(system_timestamp < lastts) - { - fprintf(stderr, "Meow: %d %d\n", system_timestamp, lastts); - assert(system_timestamp >= lastts); - } - - monotonic_timestamp += run_time; - - lastts = system_timestamp; - - RunCDRead(system_timestamp, run_time); - RunCDDA(system_timestamp, run_time); - - bool ResetNeeded = false; - - if(RST_signal && !cd.last_RST_signal) - ResetNeeded = true; - - cd.last_RST_signal = RST_signal; - - if(ResetNeeded) - { - //puts("RST"); - VirtualReset(); - } - else if(CurrentPhase == PHASE_BUS_FREE) - { - if(SEL_signal) - { - if(WhichSystem == SCSICD_PCFX) - { - //if(cd_bus.DB == 0x84) - { - ChangePhase(PHASE_COMMAND); - } - } - else // PCE - { - ChangePhase(PHASE_COMMAND); - } - } - } - else if(ATN_signal && !REQ_signal && !ACK_signal) - { - //printf("Yay: %d %d\n", REQ_signal, ACK_signal); - ChangePhase(PHASE_MESSAGE_OUT); - } - else switch(CurrentPhase) - { - case PHASE_COMMAND: - if(REQ_signal && ACK_signal) // Data bus is valid nowww - { - //printf("Command Phase Byte I->T: %02x, %d\n", cd_bus.DB, cd.command_buffer_pos); - cd.command_buffer[cd.command_buffer_pos++] = cd_bus.DB; - SetREQ(FALSE); - } - - if(!REQ_signal && !ACK_signal && cd.command_buffer_pos) // Received at least one byte, what should we do? - { - if(cd.command_buffer_pos == RequiredCDBLen[cd.command_buffer[0] >> 4]) - { - const SCSICH *cmd_info_ptr; - - if(WhichSystem == SCSICD_PCFX) - cmd_info_ptr = PCFXCommandDefs; - else - cmd_info_ptr = PCECommandDefs; - - while(cmd_info_ptr->pretty_name && cmd_info_ptr->cmd != cd.command_buffer[0]) - cmd_info_ptr++; - - if(SCSILog) - { - char log_buffer[1024]; - int lb_pos; - - log_buffer[0] = 0; - - lb_pos = trio_snprintf(log_buffer, 1024, "Command: %02x, %s%s ", cd.command_buffer[0], cmd_info_ptr->pretty_name ? cmd_info_ptr->pretty_name : "!!BAD COMMAND!!", - (cmd_info_ptr->flags & SCF_UNTESTED) ? "(UNTESTED)" : ""); - - for(int i = 0; i < RequiredCDBLen[cd.command_buffer[0] >> 4]; i++) - lb_pos += trio_snprintf(log_buffer + lb_pos, 1024 - lb_pos, "%02x ", cd.command_buffer[i]); - - SCSILog("SCSI", "%s", log_buffer); - //puts(log_buffer); - } - - - if(cmd_info_ptr->pretty_name == NULL) // Command not found! - { - CommandCCError(SENSEKEY_ILLEGAL_REQUEST, NSE_INVALID_COMMAND); - - //SCSIDBG("Bad Command: %02x\n", cd.command_buffer[0]); - - if(SCSILog) - SCSILog("SCSI", "Bad Command: %02x", cd.command_buffer[0]); - - cd.command_buffer_pos = 0; - } - else - { - if(cmd_info_ptr->flags & SCF_UNTESTED) - { - //SCSIDBG("Untested SCSI command: %02x, %s", cd.command_buffer[0], cmd_info_ptr->pretty_name); - } - - if(TrayOpen && (cmd_info_ptr->flags & SCF_REQUIRES_MEDIUM)) - { - CommandCCError(SENSEKEY_NOT_READY, NSE_TRAY_OPEN); - } - else if(!Cur_CDIF && (cmd_info_ptr->flags & SCF_REQUIRES_MEDIUM)) - { - CommandCCError(SENSEKEY_NOT_READY, NSE_NO_DISC); - } - else if(cd.DiscChanged && (cmd_info_ptr->flags & SCF_REQUIRES_MEDIUM)) - { - CommandCCError(SENSEKEY_UNIT_ATTENTION, NSE_DISC_CHANGED); - cd.DiscChanged = false; - } - else - { - bool prev_ps = (cdda.CDDAStatus == CDDASTATUS_PLAYING || cdda.CDDAStatus == CDDASTATUS_SCANNING); - - cmd_info_ptr->func(cd.command_buffer); - - bool new_ps = (cdda.CDDAStatus == CDDASTATUS_PLAYING || cdda.CDDAStatus == CDDASTATUS_SCANNING); - - // A bit kludgey, but ehhhh. - if(!prev_ps && new_ps) - { - memset(cdda.sr, 0, sizeof(cdda.sr)); - memset(cdda.OversampleBuffer, 0, sizeof(cdda.OversampleBuffer)); - memset(cdda.DeemphState, 0, sizeof(cdda.DeemphState)); - //printf("CLEAR BUFFERS LALALA\n"); - } - } - - cd.command_buffer_pos = 0; - } - } // end if(cd.command_buffer_pos == RequiredCDBLen[cd.command_buffer[0] >> 4]) - else // Otherwise, get more data for the command! - SetREQ(TRUE); - } - break; - - case PHASE_DATA_OUT: - if(REQ_signal && ACK_signal) // Data bus is valid nowww - { - //printf("DATAOUT-SCSIIN: %d %02x\n", cd.data_out_pos, cd_bus.DB); - cd.data_out[cd.data_out_pos++] = cd_bus.DB; - SetREQ(FALSE); - } - else if(!REQ_signal && !ACK_signal && cd.data_out_pos) - { - if(cd.data_out_pos == cd.data_out_want) - { - cd.data_out_pos = 0; - - if(cd.command_buffer[0] == 0x15) - FinishMODESELECT6(cd.data_out, cd.data_out_want); - else // Error out here? It shouldn't be reached: - SendStatusAndMessage(STATUS_GOOD, 0x00); - } - else - SetREQ(TRUE); - } - break; - - - case PHASE_MESSAGE_OUT: - //printf("%d %d, %02x\n", REQ_signal, ACK_signal, cd_bus.DB); - if(REQ_signal && ACK_signal) - { - SetREQ(FALSE); - - // ABORT message is 0x06, but the code isn't set up to be able to recover from a MESSAGE OUT phase back to the previous phase, so we treat any message as an ABORT. - // Real tests are needed on the PC-FX to determine its behavior. - // (Previously, ATN emulation was a bit broken, which resulted in the wrong data on the data bus in this code path in at least "Battle Heat", but it's fixed now and 0x06 is on the data bus). - //if(cd_bus.DB == 0x6) // ABORT message! - if(1) - { - //printf("[SCSICD] Abort Received(DB=0x%02x)\n", cd_bus.DB); - din->Flush(); - cd.data_out_pos = cd.data_out_want = 0; - - CDReadTimer = 0; - cdda.CDDAStatus = CDDASTATUS_STOPPED; - ChangePhase(PHASE_BUS_FREE); - } - //else - // printf("[SCSICD] Message to target: 0x%02x\n", cd_bus.DB); - } - break; - - - case PHASE_STATUS: - if(REQ_signal && ACK_signal) - { - SetREQ(FALSE); - cd.status_sent = TRUE; - } - - if(!REQ_signal && !ACK_signal && cd.status_sent) - { - // Status sent, so get ready to send the message! - cd.status_sent = FALSE; - cd_bus.DB = cd.message_pending; - - ChangePhase(PHASE_MESSAGE_IN); - } - break; - - case PHASE_DATA_IN: - if(!REQ_signal && !ACK_signal) - { - //puts("REQ and ACK false"); - if(din->CanRead() == 0) // aaand we're done! - { - CDIRQCallback(0x8000 | SCSICD_IRQ_DATA_TRANSFER_READY); - - if(cd.data_transfer_done) - { - SendStatusAndMessage(STATUS_GOOD, 0x00); - cd.data_transfer_done = FALSE; - CDIRQCallback(SCSICD_IRQ_DATA_TRANSFER_DONE); - } - } - else - { - cd_bus.DB = din->ReadByte(); - SetREQ(TRUE); - } - } - if(REQ_signal && ACK_signal) - { - //puts("REQ and ACK true"); - SetREQ(FALSE); - } - break; - - case PHASE_MESSAGE_IN: - if(REQ_signal && ACK_signal) - { - SetREQ(FALSE); - cd.message_sent = TRUE; - } - - if(!REQ_signal && !ACK_signal && cd.message_sent) - { - cd.message_sent = FALSE; - ChangePhase(PHASE_BUS_FREE); - } - break; - } - - int32 next_time = 0x7fffffff; - - if(CDReadTimer > 0 && CDReadTimer < next_time) - next_time = CDReadTimer; - - if(cdda.CDDAStatus == CDDASTATUS_PLAYING || cdda.CDDAStatus == CDDASTATUS_SCANNING) - { - int32 cdda_div_sexytime = (cdda.CDDADiv + (cdda.CDDADivAcc * (cdda.OversamplePos & 1)) + ((1 << 20) - 1)) >> 20; - if(cdda_div_sexytime > 0 && cdda_div_sexytime < next_time) - next_time = cdda_div_sexytime; - } - - assert(next_time >= 0); - - return(next_time); -} - -void SCSICD_SetLog(void (*logfunc)(const char *, const char *, ...)) -{ - SCSILog = logfunc; -} - -void SCSICD_SetTransferRate(uint32 TransferRate) -{ - CD_DATA_TRANSFER_RATE = TransferRate; -} - -void SCSICD_Close(void) -{ - if(din) - { - delete din; - din = NULL; - } -} - -void SCSICD_Init(int type, int cdda_time_div, int32* left_hrbuf, int32* right_hrbuf, uint32 TransferRate, uint32 SystemClock, void (*IRQFunc)(int), void (*SSCFunc)(uint8, int)) -{ - Cur_CDIF = NULL; - TrayOpen = true; - - assert(SystemClock < 30000000); // 30 million, sanity check. - - monotonic_timestamp = 0; - lastts = 0; - - SCSILog = NULL; - - if(type == SCSICD_PCFX) - din = new SimpleFIFO(65536); //4096); - else - din = new SimpleFIFO(2048); //8192); //1024); /2048); - - WhichSystem = type; - - cdda.CDDADivAcc = (int64)System_Clock * (1024 * 1024) / 88200; - cdda.CDDADivAccVolFudge = 100; - cdda.CDDATimeDiv = cdda_time_div * (1 << (4 + 2)); - - cdda.CDDAVolume[0] = 65536; - cdda.CDDAVolume[1] = 65536; - - FixOPV(); - - HRBufs[0] = left_hrbuf; - HRBufs[1] = right_hrbuf; - - CD_DATA_TRANSFER_RATE = TransferRate; - System_Clock = SystemClock; - CDIRQCallback = IRQFunc; - CDStuffSubchannels = SSCFunc; -} - -void SCSICD_SetCDDAVolume(double left, double right) -{ - cdda.CDDAVolume[0] = 65536 * left; - cdda.CDDAVolume[1] = 65536 * right; - - for(int i = 0; i < 2; i++) - { - if(cdda.CDDAVolume[i] > 65536) - { - printf("[SCSICD] Debug Warning: CD-DA volume %d too large: %d\n", i, cdda.CDDAVolume[i]); - cdda.CDDAVolume[i] = 65536; - } - } - - FixOPV(); -} - -void SCSICD_StateAction(StateMem* sm, const unsigned load, const bool data_only, const char *sname) -{ - SFORMAT StateRegs[] = - { - SFVARN(cd_bus.DB, "DB"), - SFVARN(cd_bus.signals, "Signals"), - SFVAR(CurrentPhase), - - SFVARN(cd.last_RST_signal, "last_RST"), - SFVARN(cd.message_pending, "message_pending"), - SFVARN(cd.status_sent, "status_sent"), - SFVARN(cd.message_sent, "message_sent"), - SFVARN(cd.key_pending, "key_pending"), - SFVARN(cd.asc_pending, "asc_pending"), - SFVARN(cd.ascq_pending, "ascq_pending"), - SFVARN(cd.fru_pending, "fru_pending"), - - SFARRAYN(cd.command_buffer, 256, "command_buffer"), - SFVARN(cd.command_buffer_pos, "command_buffer_pos"), - SFVARN(cd.command_size_left, "command_size_left"), - - // Don't save the FIFO's write position, it will be reconstructed from read_pos and in_count - SFARRAYN(&din->data[0], din->data.size(), "din_fifo"), - SFVARN(din->read_pos, "din_read_pos"), - SFVARN(din->in_count, "din_in_count"), - SFVARN(cd.data_transfer_done, "data_transfer_done"), - - SFARRAYN(cd.data_out, sizeof(cd.data_out), "data_out"), - SFVARN(cd.data_out_pos, "data_out_pos"), - SFVARN(cd.data_out_want, "data_out_want"), - - SFVARN(cd.DiscChanged, "DiscChanged"), - - SFVAR(cdda.PlayMode), - SFARRAY16(cdda.CDDASectorBuffer, 1176), - SFVAR(cdda.CDDAReadPos), - SFVAR(cdda.CDDAStatus), - SFVAR(cdda.CDDADiv), - SFVAR(read_sec_start), - SFVAR(read_sec), - SFVAR(read_sec_end), - - SFVAR(CDReadTimer), - SFVAR(SectorAddr), - SFVAR(SectorCount), - - SFVAR(cdda.ScanMode), - SFVAR(cdda.scan_sec_end), - - SFVAR(cdda.OversamplePos), - SFARRAY16(&cdda.sr[0], sizeof(cdda.sr) / sizeof(cdda.sr[0])), - SFARRAY16(&cdda.OversampleBuffer[0][0], sizeof(cdda.OversampleBuffer) / sizeof(cdda.OversampleBuffer[0][0])), - - SFVAR(cdda.DeemphState[0][0]), - SFVAR(cdda.DeemphState[0][1]), - SFVAR(cdda.DeemphState[1][0]), - SFVAR(cdda.DeemphState[1][1]), - - SFARRAYN(&cd.SubQBuf[0][0], sizeof(cd.SubQBuf), "SubQBufs"), - SFARRAYN(cd.SubQBuf_Last, sizeof(cd.SubQBuf_Last), "SubQBufLast"), - SFARRAYN(cd.SubPWBuf, sizeof(cd.SubPWBuf), "SubPWBuf"), - - SFVAR(monotonic_timestamp), - SFVAR(pce_lastsapsp_timestamp), - - // - // - // - SFARRAY(ModePages[0].current_value, ModePages[0].param_length), - SFARRAY(ModePages[1].current_value, ModePages[1].param_length), - SFARRAY(ModePages[2].current_value, ModePages[2].param_length), - SFARRAY(ModePages[3].current_value, ModePages[3].param_length), - SFARRAY(ModePages[4].current_value, ModePages[4].param_length), - SFEND - }; - - MDFNSS_StateAction(sm, load, data_only, StateRegs, sname); - - if(load) - { - din->in_count &= din->size - 1; - din->read_pos &= din->size - 1; - din->write_pos = (din->read_pos + din->in_count) & (din->size - 1); - //printf("%d %d %d\n", din->in_count, din->read_pos, din->write_pos); - - if(load < 0x0935) - cdda.CDDADiv /= 2; - - if(cdda.CDDADiv <= 0) - cdda.CDDADiv = 1; - - cdda.OversamplePos &= 0x1F; - - for(int i = 0; i < NumModePages; i++) - UpdateMPCacheP(&ModePages[i]); - } -} diff --git a/psx/mednadisc/cdrom/scsicd.h b/psx/mednadisc/cdrom/scsicd.h deleted file mode 100644 index 8fc7496bd39..00000000000 --- a/psx/mednadisc/cdrom/scsicd.h +++ /dev/null @@ -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 diff --git a/psx/mednadisc/cdrom/scsicd_cdda_filter.inc b/psx/mednadisc/cdrom/scsicd_cdda_filter.inc deleted file mode 100644 index f80b20a5243..00000000000 --- a/psx/mednadisc/cdrom/scsicd_cdda_filter.inc +++ /dev/null @@ -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) - diff --git a/psx/mednadisc/emuware/EW_state.cpp b/psx/mednadisc/emuware/EW_state.cpp deleted file mode 100644 index 9b408d844e1..00000000000 --- a/psx/mednadisc/emuware/EW_state.cpp +++ /dev/null @@ -1,96 +0,0 @@ -#include "EW_state.h" -#include -#include -#include -#include -#include - -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(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); -} - - -} diff --git a/psx/mednadisc/emuware/EW_state.h b/psx/mednadisc/emuware/EW_state.h deleted file mode 100644 index acd3c1396af..00000000000 --- a/psx/mednadisc/emuware/EW_state.h +++ /dev/null @@ -1,105 +0,0 @@ -#ifndef NEWSTATE_H -#define NEWSTATE_H - -#include -#include - -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(EW::NewState *ns);\ - template void x::SyncState(EW::NewState *ns);\ - templatevoid 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(ns); ns->ExitSection(#x); } while (0) - - #define TSS(x) do { ns->EnterSection(#x); (x)->SyncState(ns); ns->ExitSection(#x); } while (0) - - } - - - -#endif //NEWSTATE_H \ No newline at end of file diff --git a/psx/mednadisc/emuware/PACKED.h b/psx/mednadisc/emuware/PACKED.h deleted file mode 100644 index eaef0c7a405..00000000000 --- a/psx/mednadisc/emuware/PACKED.h +++ /dev/null @@ -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 diff --git a/psx/mednadisc/emuware/PACKED_END.h b/psx/mednadisc/emuware/PACKED_END.h deleted file mode 100644 index 6eb7bd7c157..00000000000 --- a/psx/mednadisc/emuware/PACKED_END.h +++ /dev/null @@ -1,3 +0,0 @@ -#ifndef __GNUC__ -#pragma pack(pop) -#endif diff --git a/psx/mednadisc/emuware/emuware.cpp b/psx/mednadisc/emuware/emuware.cpp deleted file mode 100644 index 02119e1d593..00000000000 --- a/psx/mednadisc/emuware/emuware.cpp +++ /dev/null @@ -1,3 +0,0 @@ -#include "emuware.h" - -//this file intentionally empty \ No newline at end of file diff --git a/psx/mednadisc/emuware/emuware.h b/psx/mednadisc/emuware/emuware.h deleted file mode 100644 index ae009141288..00000000000 --- a/psx/mednadisc/emuware/emuware.h +++ /dev/null @@ -1,160 +0,0 @@ -#pragma once - -#include -#include -#include - -#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 -//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 -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 \ No newline at end of file diff --git a/psx/mednadisc/emuware/msvc/changelog.txt b/psx/mednadisc/emuware/msvc/changelog.txt deleted file mode 100644 index cf0539c2533..00000000000 --- a/psx/mednadisc/emuware/msvc/changelog.txt +++ /dev/null @@ -1,138 +0,0 @@ ------------------------------------------------------------------------- -r26 | 2009-10-02 13:36:47 +0400 | 2 lines - -[Issue 5] Change 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 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 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 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 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. ------------------------------------------------------------------------- diff --git a/psx/mednadisc/emuware/msvc/inttypes.h b/psx/mednadisc/emuware/msvc/inttypes.h deleted file mode 100644 index 25542771f59..00000000000 --- a/psx/mednadisc/emuware/msvc/inttypes.h +++ /dev/null @@ -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_ ] diff --git a/psx/mednadisc/emuware/msvc/stdint.h b/psx/mednadisc/emuware/msvc/stdint.h deleted file mode 100644 index 59d067302fc..00000000000 --- a/psx/mednadisc/emuware/msvc/stdint.h +++ /dev/null @@ -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 - -// For Visual Studio 6 in C++ mode and for many Visual Studio versions when -// compiling for ARM we should wrap 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 -#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 -#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_ ] diff --git a/psx/mednadisc/endian.cpp b/psx/mednadisc/endian.cpp deleted file mode 100644 index 05e8745fc35..00000000000 --- a/psx/mednadisc/endian.cpp +++ /dev/null @@ -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 -#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 -} diff --git a/psx/mednadisc/endian.h b/psx/mednadisc/endian.h deleted file mode 100644 index f0128cdb572..00000000000 --- a/psx/mednadisc/endian.h +++ /dev/null @@ -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 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 -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 -static INLINE T MDFN_densb(const void* ptr) -{ - return MDFN_deXsb<-1, T, aligned>(ptr); -} - -// -// Little endian. -// -template -static INLINE T MDFN_delsb(const void* ptr) -{ - return MDFN_deXsb<0, T, aligned>(ptr); -} - -template -static INLINE uint16 MDFN_de16lsb(const void* ptr) -{ - return MDFN_delsb(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 -static INLINE uint32 MDFN_de32lsb(const void* ptr) -{ - return MDFN_delsb(ptr); -} - -template -static INLINE uint64 MDFN_de64lsb(const void* ptr) -{ - return MDFN_delsb(ptr); -} - -// -// Big endian. -// -template -static INLINE T MDFN_demsb(const void* ptr) -{ - return MDFN_deXsb<1, T, aligned>(ptr); -} - -template -static INLINE uint16 MDFN_de16msb(const void* ptr) -{ - return MDFN_demsb(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 -static INLINE uint32 MDFN_de32msb(const void* ptr) -{ - return MDFN_demsb(ptr); -} - -template -static INLINE uint64 MDFN_de64msb(const void* ptr) -{ - return MDFN_demsb(ptr); -} - -// -// -// -// -// -// -// -// - -// -// X endian. -// -template -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 -static INLINE void MDFN_ennsb(void* ptr, T value) -{ - MDFN_enXsb<-1, T, aligned>(ptr, value); -} - -// -// Little endian. -// -template -static INLINE void MDFN_enlsb(void* ptr, T value) -{ - MDFN_enXsb<0, T, aligned>(ptr, value); -} - -template -static INLINE void MDFN_en16lsb(void* ptr, uint16 value) -{ - MDFN_enlsb(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 -static INLINE void MDFN_en32lsb(void* ptr, uint32 value) -{ - MDFN_enlsb(ptr, value); -} - -template -static INLINE void MDFN_en64lsb(void* ptr, uint64 value) -{ - MDFN_enlsb(ptr, value); -} - - -// -// Big endian. -// -template -static INLINE void MDFN_enmsb(void* ptr, T value) -{ - MDFN_enXsb<1, T, aligned>(ptr, value); -} - -template -static INLINE void MDFN_en16msb(void* ptr, uint16 value) -{ - MDFN_enmsb(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 -static INLINE void MDFN_en32msb(void* ptr, uint32 value) -{ - MDFN_enmsb(ptr, value); -} - -template -static INLINE void MDFN_en64msb(void* ptr, uint64 value) -{ - MDFN_enmsb(ptr, value); -} - -#endif diff --git a/psx/mednadisc/error.cpp b/psx/mednadisc/error.cpp deleted file mode 100644 index 4229a5c8bc9..00000000000 --- a/psx/mednadisc/error.cpp +++ /dev/null @@ -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 -#include -#include - -#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; - } -} - diff --git a/psx/mednadisc/error.h b/psx/mednadisc/error.h deleted file mode 100644 index ac55bb7823c..00000000000 --- a/psx/mednadisc/error.h +++ /dev/null @@ -1,75 +0,0 @@ -#ifndef __MDFN_ERROR_H -#define __MDFN_ERROR_H - -#include -#include -#include - -#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 diff --git a/psx/mednadisc/general.cpp b/psx/mednadisc/general.cpp deleted file mode 100644 index 3a7a2fc04bf..00000000000 --- a/psx/mednadisc/general.cpp +++ /dev/null @@ -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 -#include - -#include -#include - -#include -#include - -#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 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(tp1tp1)) - { - 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 = ""; - } -} - diff --git a/psx/mednadisc/general.h b/psx/mednadisc/general.h deleted file mode 100644 index be305838ecb..00000000000 --- a/psx/mednadisc/general.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef _GENERAL_H -#define _GENERAL_H - -#include - -#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 diff --git a/psx/mednadisc/math_ops.h b/psx/mednadisc/math_ops.h deleted file mode 100644 index 656abf6738f..00000000000 --- a/psx/mednadisc/math_ops.h +++ /dev/null @@ -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 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 diff --git a/psx/mednadisc/string/ConvertUTF.cpp b/psx/mednadisc/string/ConvertUTF.cpp deleted file mode 100644 index ee02e25c3a6..00000000000 --- a/psx/mednadisc/string/ConvertUTF.cpp +++ /dev/null @@ -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 -#endif - -#include -#include - -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. - - --------------------------------------------------------------------- */ diff --git a/psx/mednadisc/string/ConvertUTF.h b/psx/mednadisc/string/ConvertUTF.h deleted file mode 100644 index a4d64d6b321..00000000000 --- a/psx/mednadisc/string/ConvertUTF.h +++ /dev/null @@ -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: , , - or 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 - -/* --------------------------------------------------------------------- */ diff --git a/psx/mednadisc/string/Makefile.am.inc b/psx/mednadisc/string/Makefile.am.inc deleted file mode 100644 index ae18bc946d1..00000000000 --- a/psx/mednadisc/string/Makefile.am.inc +++ /dev/null @@ -1,2 +0,0 @@ -mednafen_SOURCES += string/escape.cpp string/trim.cpp string/ConvertUTF.cpp - diff --git a/psx/mednadisc/string/escape.cpp b/psx/mednadisc/string/escape.cpp deleted file mode 100644 index 8aed2b324dc..00000000000 --- a/psx/mednadisc/string/escape.cpp +++ /dev/null @@ -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); -} diff --git a/psx/mednadisc/string/escape.h b/psx/mednadisc/string/escape.h deleted file mode 100644 index a1ed431a2f6..00000000000 --- a/psx/mednadisc/string/escape.h +++ /dev/null @@ -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 diff --git a/psx/mednadisc/string/trim.cpp b/psx/mednadisc/string/trim.cpp deleted file mode 100644 index b810ccd3394..00000000000 --- a/psx/mednadisc/string/trim.cpp +++ /dev/null @@ -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 -#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); -} - diff --git a/psx/mednadisc/string/trim.h b/psx/mednadisc/string/trim.h deleted file mode 100644 index 691de8e9cd0..00000000000 --- a/psx/mednadisc/string/trim.h +++ /dev/null @@ -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 diff --git a/psx/mednadisc/trio/trio.c b/psx/mednadisc/trio/trio.c deleted file mode 100644 index 28b5e4e80d1..00000000000 --- a/psx/mednadisc/trio/trio.c +++ /dev/null @@ -1,7907 +0,0 @@ -/************************************************************************* - * - * $Id$ - * - * Copyright (C) 1998, 2009 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. - * - ************************************************************************* - * - * A note to trio contributors: - * - * Avoid heap allocation at all costs to ensure that the trio functions - * are async-safe. The exceptions are the printf/fprintf functions, which - * uses fputc, and the asprintf functions and the modifier, which - * by design are required to allocate form the heap. - * - ************************************************************************/ - -/* - * TODO: - * - Scan is probably too permissive about its modifiers. - * - C escapes in %#[] ? - * - Multibyte characters (done for format parsing, except scan groups) - * - Complex numbers? (C99 _Complex) - * - Boolean values? (C99 _Bool) - * - C99 NaN(n-char-sequence) missing. The n-char-sequence can be used - * to print the mantissa, e.g. NaN(0xc000000000000000) - * - Should we support the GNU %a alloc modifier? GNU has an ugly hack - * for %a, because C99 used %a for other purposes. If specified as - * %as or %a[ it is interpreted as the alloc modifier, otherwise as - * the C99 hex-float. This means that you cannot scan %as as a hex-float - * immediately followed by an 's'. - * - Scanning of collating symbols. - */ - -/************************************************************************* - * Trio include files - */ -#include "triodef.h" -#include "trio.h" -#include "triop.h" - -#if defined(TRIO_EMBED_NAN) -# define TRIO_PUBLIC_NAN static -# if TRIO_FEATURE_FLOAT -# define TRIO_FUNC_NAN -# define TRIO_FUNC_NINF -# define TRIO_FUNC_PINF -# define TRIO_FUNC_FPCLASSIFY_AND_SIGNBIT -# define TRIO_FUNC_ISINF -# endif -#endif -#include "trionan.h" - -#if defined(TRIO_EMBED_STRING) -# define TRIO_PUBLIC_STRING static -# define TRIO_FUNC_LENGTH -# define TRIO_FUNC_LENGTH_MAX -# define TRIO_FUNC_TO_LONG -# if TRIO_FEATURE_LOCALE -# define TRIO_FUNC_COPY_MAX -# endif -# if TRIO_FEATURE_DYNAMICSTRING -# define TRIO_FUNC_XSTRING_DUPLICATE -# endif -# if TRIO_EXTENSION && TRIO_FEATURE_SCANF -# define TRIO_FUNC_EQUAL_LOCALE -# endif -# if TRIO_FEATURE_ERRNO -# define TRIO_FUNC_ERROR -# endif -# if TRIO_FEATURE_FLOAT && TRIO_FEATURE_SCANF -# define TRIO_FUNC_TO_DOUBLE -# endif -# if TRIO_FEATURE_DYNAMICSTRING -# define TRIO_FUNC_STRING_EXTRACT -# endif -# if TRIO_FEATURE_DYNAMICSTRING -# define TRIO_FUNC_STRING_TERMINATE -# endif -# if TRIO_FEATURE_USER_DEFINED -# define TRIO_FUNC_DUPLICATE -# endif -# if TRIO_FEATURE_DYNAMICSTRING -# define TRIO_FUNC_STRING_DESTROY -# endif -# if TRIO_FEATURE_USER_DEFINED -# define TRIO_FUNC_DESTROY -# endif -# if TRIO_FEATURE_USER_DEFINED || (TRIO_FEATURE_FLOAT && TRIO_FEATURE_SCANF) -# define TRIO_FUNC_EQUAL -# endif -# if TRIO_FEATURE_USER_DEFINED || TRIO_FEATURE_SCANF -# define TRIO_FUNC_EQUAL_CASE -# endif -# if (TRIO_EXTENSION && TRIO_FEATURE_SCANF) -# define TRIO_FUNC_EQUAL_MAX -# endif -# if TRIO_FEATURE_SCANF -# define TRIO_FUNC_TO_UPPER -# endif -# if TRIO_FEATURE_DYNAMICSTRING -# define TRIO_FUNC_XSTRING_APPEND_CHAR -# endif -#endif -#include "triostr.h" - -/************************************************************************** - * - * Definitions - * - *************************************************************************/ - -#include -#if TRIO_FEATURE_FLOAT -# include -# include -#endif - -#if defined(__STDC_ISO_10646__) || defined(MB_LEN_MAX) || defined(USE_MULTIBYTE) || TRIO_FEATURE_WIDECHAR -# if !defined(TRIO_PLATFORM_WINCE) -# define TRIO_COMPILER_SUPPORTS_MULTIBYTE -# if !defined(MB_LEN_MAX) -# define MB_LEN_MAX 6 -# endif -# endif -#endif - -#if (defined(TRIO_COMPILER_VISUALC) && (TRIO_COMPILER_VISUALC >= 1100)) || defined(TRIO_COMPILER_BORLAND) -# define TRIO_COMPILER_SUPPORTS_VISUALC_INT -#endif - -#if TRIO_FEATURE_FLOAT -# if defined(PREDEF_STANDARD_C99) \ - || defined(PREDEF_STANDARD_UNIX03) -# if !defined(HAVE_FLOORL) && !defined(TRIO_NO_FLOORL) -# define HAVE_FLOORL -# endif -# if !defined(HAVE_CEILL) && !defined(TRIO_NO_CEILL) -# define HAVE_CEILL -# endif -# if !defined(HAVE_POWL) && !defined(TRIO_NO_POWL) -# define HAVE_POWL -# endif -# if !defined(HAVE_FMODL) && !defined(TRIO_NO_FMODL) -# define HAVE_FMODL -# endif -# if !defined(HAVE_LOG10L) && !defined(TRIO_NO_LOG10L) -# define HAVE_LOG10L -# endif -# endif -# if defined(TRIO_COMPILER_VISUALC) -# if defined(floorl) -# define HAVE_FLOORL -# endif -# if defined(ceill) -# define HAVE_CEILL -# endif -# if defined(powl) -# define HAVE_POWL -# endif -# if defined(fmodl) -# define HAVE_FMODL -# endif -# if defined(log10l) -# define HAVE_LOG10L -# endif -# endif -#endif - -/************************************************************************* - * Generic definitions - */ - -#if !(defined(DEBUG) || defined(NDEBUG)) -# define NDEBUG -#endif - -#include -#include -#if defined(PREDEF_STANDARD_C99) && !defined(isascii) -# define isascii(x) ((x) & 0x7F) -#endif -#if defined(TRIO_COMPILER_ANCIENT) -# include -#else -# include -#endif -#include -#if defined(TRIO_PLATFORM_WINCE) -extern int errno; -#else -# include -#endif - -#ifndef NULL -# define NULL 0 -#endif -#define NIL ((char)0) -#ifndef FALSE -# define FALSE (1 == 0) -# define TRUE (! FALSE) -#endif -#define BOOLEAN_T int - -/* mincore() can be used for debugging purposes */ -#define VALID(x) (NULL != (x)) - -#if TRIO_FEATURE_ERRORCODE - /* - * Encode the error code and the position. This is decoded - * with TRIO_ERROR_CODE and TRIO_ERROR_POSITION. - */ -# define TRIO_ERROR_RETURN(x,y) (- ((x) + ((y) << 8))) -#else -# define TRIO_ERROR_RETURN(x,y) (-1) -#endif - -typedef unsigned long trio_flags_t; - - -/************************************************************************* - * Platform specific definitions - */ -#if defined(TRIO_PLATFORM_UNIX) -# include -# include -# include -# if !defined(TRIO_FEATURE_LOCALE) -# define USE_LOCALE -# endif -#endif /* TRIO_PLATFORM_UNIX */ -#if defined(TRIO_PLATFORM_VMS) -# include -#endif -#if defined(TRIO_PLATFORM_WIN32) -# if defined(TRIO_PLATFORM_WINCE) -int read(int handle, char *buffer, unsigned int length); -int write(int handle, const char *buffer, unsigned int length); -# else -# include -# define read _read -# define write _write -# endif -#endif /* TRIO_PLATFORM_WIN32 */ - -#if TRIO_FEATURE_WIDECHAR -# if defined(PREDEF_STANDARD_C94) -# include -# include -typedef wchar_t trio_wchar_t; -typedef wint_t trio_wint_t; -# else -typedef char trio_wchar_t; -typedef int trio_wint_t; -# define WCONST(x) L ## x -# define WEOF EOF -# define iswalnum(x) isalnum(x) -# define iswalpha(x) isalpha(x) -# define iswcntrl(x) iscntrl(x) -# define iswdigit(x) isdigit(x) -# define iswgraph(x) isgraph(x) -# define iswlower(x) islower(x) -# define iswprint(x) isprint(x) -# define iswpunct(x) ispunct(x) -# define iswspace(x) isspace(x) -# define iswupper(x) isupper(x) -# define iswxdigit(x) isxdigit(x) -# endif -#endif - - -/************************************************************************* - * Compiler dependent definitions - */ - -/* Support for long long */ -#ifndef __cplusplus -# if !defined(USE_LONGLONG) -# if defined(TRIO_COMPILER_GCC) && !defined(__STRICT_ANSI__) -# define USE_LONGLONG -# else -# if defined(TRIO_COMPILER_SUNPRO) -# define USE_LONGLONG -# else -# if defined(TRIO_COMPILER_MSVC) && (_MSC_VER >= 1400) -# define USE_LONGLONG -# else -# if defined(_LONG_LONG) || defined(_LONGLONG) -# define USE_LONGLONG -# endif -# endif -# endif -# endif -# endif -#endif - -/* The extra long numbers */ -#if defined(USE_LONGLONG) -typedef signed long long int trio_longlong_t; -typedef unsigned long long int trio_ulonglong_t; -#else -# if defined(TRIO_COMPILER_SUPPORTS_VISUALC_INT) -typedef signed __int64 trio_longlong_t; -typedef unsigned __int64 trio_ulonglong_t; -# else -typedef TRIO_SIGNED long int trio_longlong_t; -typedef unsigned long int trio_ulonglong_t; -# endif -#endif - -/* Maximal and fixed integer types */ -#if defined(PREDEF_STANDARD_C99) -# include -typedef intmax_t trio_intmax_t; -typedef uintmax_t trio_uintmax_t; -typedef int8_t trio_int8_t; -typedef int16_t trio_int16_t; -typedef int32_t trio_int32_t; -typedef int64_t trio_int64_t; -#else -# if defined(PREDEF_STANDARD_UNIX98) -# include -typedef intmax_t trio_intmax_t; -typedef uintmax_t trio_uintmax_t; -typedef int8_t trio_int8_t; -typedef int16_t trio_int16_t; -typedef int32_t trio_int32_t; -typedef int64_t trio_int64_t; -# else -# if defined(TRIO_COMPILER_SUPPORTS_VISUALC_INT) -typedef trio_longlong_t trio_intmax_t; -typedef trio_ulonglong_t trio_uintmax_t; -typedef __int8 trio_int8_t; -typedef __int16 trio_int16_t; -typedef __int32 trio_int32_t; -typedef __int64 trio_int64_t; -# else -typedef trio_longlong_t trio_intmax_t; -typedef trio_ulonglong_t trio_uintmax_t; -# if defined(TRIO_INT8_T) -typedef TRIO_INT8_T trio_int8_t; -# else -typedef TRIO_SIGNED char trio_int8_t; -# endif -# if defined(TRIO_INT16_T) -typedef TRIO_INT16_T trio_int16_t; -# else -typedef TRIO_SIGNED short trio_int16_t; -# endif -# if defined(TRIO_INT32_T) -typedef TRIO_INT32_T trio_int32_t; -# else -typedef TRIO_SIGNED int trio_int32_t; -# endif -# if defined(TRIO_INT64_T) -typedef TRIO_INT64_T trio_int64_t; -# else -typedef trio_longlong_t trio_int64_t; -# endif -# endif -# endif -#endif - -#if defined(HAVE_FLOORL) -# define trio_floor(x) floorl((x)) -#else -# define trio_floor(x) floor((double)(x)) -#endif - -#if defined(HAVE_CEILL) -# define trio_ceil(x) ceill((x)) -#else -# define trio_ceil(x) ceil((double)(x)) -#endif - -#if defined(HAVE_FMODL) -# define trio_fmod(x,y) fmodl((x),(y)) -#else -# define trio_fmod(x,y) fmod((double)(x),(double)(y)) -#endif - -#if defined(HAVE_POWL) -# define trio_pow(x,y) powl((x),(y)) -#else -# define trio_pow(x,y) pow((double)(x),(double)(y)) -#endif - -#if defined(HAVE_LOG10L) -# define trio_log10(x) log10l((x)) -#else -# define trio_log10(x) log10((double)(x)) -#endif - -#if TRIO_FEATURE_FLOAT -# define TRIO_FABS(x) (((x) < 0.0) ? -(x) : (x)) -#endif - -/************************************************************************* - * Internal Definitions - */ - -#if TRIO_FEATURE_FLOAT - -# if !defined(DECIMAL_DIG) -# define DECIMAL_DIG DBL_DIG -# endif - -/* Long double sizes */ -# ifdef LDBL_DIG -# define MAX_MANTISSA_DIGITS LDBL_DIG -# define MAX_EXPONENT_DIGITS 4 -# define MAX_DOUBLE_DIGITS LDBL_MAX_10_EXP -# else -# define MAX_MANTISSA_DIGITS DECIMAL_DIG -# define MAX_EXPONENT_DIGITS 3 -# define MAX_DOUBLE_DIGITS DBL_MAX_10_EXP -# endif - -# if defined(TRIO_COMPILER_ANCIENT) || !defined(LDBL_DIG) -# undef LDBL_DIG -# undef LDBL_MANT_DIG -# undef LDBL_EPSILON -# define LDBL_DIG DBL_DIG -# define LDBL_MANT_DIG DBL_MANT_DIG -# define LDBL_EPSILON DBL_EPSILON -# endif - -#endif /* TRIO_FEATURE_FLOAT */ - -/* The maximal number of digits is for base 2 */ -#define MAX_CHARS_IN(x) (sizeof(x) * CHAR_BIT) -/* The width of a pointer. The number of bits in a hex digit is 4 */ -#define POINTER_WIDTH ((sizeof("0x") - 1) + sizeof(trio_pointer_t) * CHAR_BIT / 4) - -#if TRIO_FEATURE_FLOAT -/* Infinite and Not-A-Number for floating-point */ -# define INFINITE_LOWER "inf" -# define INFINITE_UPPER "INF" -# define LONG_INFINITE_LOWER "infinite" -# define LONG_INFINITE_UPPER "INFINITE" -# define NAN_LOWER "nan" -# define NAN_UPPER "NAN" -#endif - -/* Various constants */ -enum { - TYPE_PRINT = 1, -#if TRIO_FEATURE_SCANF - TYPE_SCAN = 2, -#endif - - /* Flags. FLAGS_LAST must be less than ULONG_MAX */ - FLAGS_NEW = 0, - FLAGS_STICKY = 1, - FLAGS_SPACE = 2 * FLAGS_STICKY, - FLAGS_SHOWSIGN = 2 * FLAGS_SPACE, - FLAGS_LEFTADJUST = 2 * FLAGS_SHOWSIGN, - FLAGS_ALTERNATIVE = 2 * FLAGS_LEFTADJUST, - FLAGS_SHORT = 2 * FLAGS_ALTERNATIVE, - FLAGS_SHORTSHORT = 2 * FLAGS_SHORT, - FLAGS_LONG = 2 * FLAGS_SHORTSHORT, - FLAGS_QUAD = 2 * FLAGS_LONG, - FLAGS_LONGDOUBLE = 2 * FLAGS_QUAD, - FLAGS_SIZE_T = 2 * FLAGS_LONGDOUBLE, - FLAGS_PTRDIFF_T = 2 * FLAGS_SIZE_T, - FLAGS_INTMAX_T = 2 * FLAGS_PTRDIFF_T, - FLAGS_NILPADDING = 2 * FLAGS_INTMAX_T, - FLAGS_UNSIGNED = 2 * FLAGS_NILPADDING, - FLAGS_UPPER = 2 * FLAGS_UNSIGNED, - FLAGS_WIDTH = 2 * FLAGS_UPPER, - FLAGS_WIDTH_PARAMETER = 2 * FLAGS_WIDTH, - FLAGS_PRECISION = 2 * FLAGS_WIDTH_PARAMETER, - FLAGS_PRECISION_PARAMETER = 2 * FLAGS_PRECISION, - FLAGS_BASE = 2 * FLAGS_PRECISION_PARAMETER, - FLAGS_BASE_PARAMETER = 2 * FLAGS_BASE, - FLAGS_FLOAT_E = 2 * FLAGS_BASE_PARAMETER, - FLAGS_FLOAT_G = 2 * FLAGS_FLOAT_E, - FLAGS_QUOTE = 2 * FLAGS_FLOAT_G, - FLAGS_WIDECHAR = 2 * FLAGS_QUOTE, - FLAGS_IGNORE = 2 * FLAGS_WIDECHAR, - FLAGS_IGNORE_PARAMETER = 2 * FLAGS_IGNORE, - FLAGS_VARSIZE_PARAMETER = 2 * FLAGS_IGNORE_PARAMETER, - FLAGS_FIXED_SIZE = 2 * FLAGS_VARSIZE_PARAMETER, - FLAGS_LAST = FLAGS_FIXED_SIZE, - /* Reused flags */ - FLAGS_EXCLUDE = FLAGS_SHORT, - FLAGS_USER_DEFINED = FLAGS_IGNORE, - FLAGS_USER_DEFINED_PARAMETER = FLAGS_IGNORE_PARAMETER, - FLAGS_ROUNDING = FLAGS_INTMAX_T, - /* Compounded flags */ - FLAGS_ALL_VARSIZES = FLAGS_LONG | FLAGS_QUAD | FLAGS_INTMAX_T | FLAGS_PTRDIFF_T | FLAGS_SIZE_T, - FLAGS_ALL_SIZES = FLAGS_ALL_VARSIZES | FLAGS_SHORTSHORT | FLAGS_SHORT, - - NO_POSITION = -1, - NO_WIDTH = 0, - NO_PRECISION = -1, - NO_SIZE = -1, - - /* Do not change these */ - NO_BASE = -1, - MIN_BASE = 2, - MAX_BASE = 36, - BASE_BINARY = 2, - BASE_OCTAL = 8, - BASE_DECIMAL = 10, - BASE_HEX = 16, - - /* Maximal number of allowed parameters */ - MAX_PARAMETERS = 64, - /* Maximal number of characters in class */ - MAX_CHARACTER_CLASS = UCHAR_MAX + 1, - -#if TRIO_FEATURE_USER_DEFINED - /* Maximal string lengths for user-defined specifiers */ - MAX_USER_NAME = 64, - MAX_USER_DATA = 256, -#endif - - /* Maximal length of locale separator strings */ - MAX_LOCALE_SEPARATOR_LENGTH = MB_LEN_MAX, - /* Maximal number of integers in grouping */ - MAX_LOCALE_GROUPS = 64 -}; - -#define NO_GROUPING ((int)CHAR_MAX) - -/* Fundamental formatting parameter types */ -#define FORMAT_SENTINEL -1 /* marks end of parameters array */ -#define FORMAT_UNKNOWN 0 -#define FORMAT_INT 1 -#define FORMAT_DOUBLE 2 -#define FORMAT_CHAR 3 -#define FORMAT_STRING 4 -#define FORMAT_POINTER 5 -#define FORMAT_COUNT 6 -#define FORMAT_PARAMETER 7 -#define FORMAT_GROUP 8 -#define FORMAT_ERRNO 9 -#define FORMAT_USER_DEFINED 10 - -/* Character constants */ -#define CHAR_IDENTIFIER '%' -#define CHAR_ALT_IDENTIFIER '$' -#define CHAR_BACKSLASH '\\' -#define CHAR_QUOTE '\"' -#define CHAR_ADJUST ' ' - -#if TRIO_EXTENSION -/* Character class expressions */ -# define CLASS_ALNUM "[:alnum:]" -# define CLASS_ALPHA "[:alpha:]" -# define CLASS_BLANK "[:blank:]" -# define CLASS_CNTRL "[:cntrl:]" -# define CLASS_DIGIT "[:digit:]" -# define CLASS_GRAPH "[:graph:]" -# define CLASS_LOWER "[:lower:]" -# define CLASS_PRINT "[:print:]" -# define CLASS_PUNCT "[:punct:]" -# define CLASS_SPACE "[:space:]" -# define CLASS_UPPER "[:upper:]" -# define CLASS_XDIGIT "[:xdigit:]" -#endif - -/* - * SPECIFIERS: - * - * - * a Hex-float - * A Hex-float - * c Character - * C Widechar character (wint_t) - * d Decimal - * e Float - * E Float - * F Float - * F Float - * g Float - * G Float - * i Integer - * m Error message - * n Count - * o Octal - * p Pointer - * s String - * S Widechar string (wchar_t *) - * u Unsigned - * x Hex - * X Hex - * [] Group - * <> User-defined - * - * Reserved: - * - * D Binary Coded Decimal %D(length,precision) (OS/390) - */ -#define SPECIFIER_CHAR 'c' -#define SPECIFIER_STRING 's' -#define SPECIFIER_DECIMAL 'd' -#define SPECIFIER_INTEGER 'i' -#define SPECIFIER_UNSIGNED 'u' -#define SPECIFIER_OCTAL 'o' -#define SPECIFIER_HEX 'x' -#define SPECIFIER_HEX_UPPER 'X' -#if TRIO_FEATURE_FLOAT -# define SPECIFIER_FLOAT_E 'e' -# define SPECIFIER_FLOAT_E_UPPER 'E' -# define SPECIFIER_FLOAT_F 'f' -# define SPECIFIER_FLOAT_F_UPPER 'F' -# define SPECIFIER_FLOAT_G 'g' -# define SPECIFIER_FLOAT_G_UPPER 'G' -#endif -#define SPECIFIER_POINTER 'p' -#if TRIO_FEATURE_SCANF -# define SPECIFIER_GROUP '[' -# define SPECIFIER_UNGROUP ']' -#endif -#define SPECIFIER_COUNT 'n' -#if TRIO_UNIX98 -# define SPECIFIER_CHAR_UPPER 'C' -# define SPECIFIER_STRING_UPPER 'S' -#endif -#define SPECIFIER_HEXFLOAT 'a' -#define SPECIFIER_HEXFLOAT_UPPER 'A' -#define SPECIFIER_ERRNO 'm' -#if TRIO_FEATURE_BINARY -# define SPECIFIER_BINARY 'b' -# define SPECIFIER_BINARY_UPPER 'B' -#endif -#if TRIO_FEATURE_USER_DEFINED -# define SPECIFIER_USER_DEFINED_BEGIN '<' -# define SPECIFIER_USER_DEFINED_END '>' -# define SPECIFIER_USER_DEFINED_SEPARATOR ':' -# define SPECIFIER_USER_DEFINED_EXTRA '|' -#endif - -/* - * QUALIFIERS: - * - * - * Numbers = d,i,o,u,x,X - * Float = a,A,e,E,f,F,g,G - * String = s - * Char = c - * - * - * 9$ Position - * Use the 9th parameter. 9 can be any number between 1 and - * the maximal argument - * - * 9 Width - * Set width to 9. 9 can be any number, but must not be postfixed - * by '$' - * - * h Short - * Numbers: - * (unsigned) short int - * - * hh Short short - * Numbers: - * (unsigned) char - * - * l Long - * Numbers: - * (unsigned) long int - * String: - * as the S specifier - * Char: - * as the C specifier - * - * ll Long Long - * Numbers: - * (unsigned) long long int - * - * L Long Double - * Float - * long double - * - * # Alternative - * Float: - * Decimal-point is always present - * String: - * non-printable characters are handled as \number - * - * Spacing - * - * + Sign - * - * - Alignment - * - * . Precision - * - * * Parameter - * print: use parameter - * scan: no parameter (ignore) - * - * q Quad - * - * Z size_t - * - * w Widechar - * - * ' Thousands/quote - * Numbers: - * Integer part grouped in thousands - * Binary numbers: - * Number grouped in nibbles (4 bits) - * String: - * Quoted string - * - * j intmax_t - * t prtdiff_t - * z size_t - * - * ! Sticky - * @ Parameter (for both print and scan) - * - * I n-bit Integer - * Numbers: - * The following options exists - * I8 = 8-bit integer - * I16 = 16-bit integer - * I32 = 32-bit integer - * I64 = 64-bit integer - */ -#define QUALIFIER_POSITION '$' -#define QUALIFIER_SHORT 'h' -#define QUALIFIER_LONG 'l' -#define QUALIFIER_LONG_UPPER 'L' -#define QUALIFIER_ALTERNATIVE '#' -#define QUALIFIER_SPACE ' ' -#define QUALIFIER_PLUS '+' -#define QUALIFIER_MINUS '-' -#define QUALIFIER_DOT '.' -#define QUALIFIER_STAR '*' -#define QUALIFIER_CIRCUMFLEX '^' /* For scanlists */ -#define QUALIFIER_SIZE_T 'z' -#define QUALIFIER_PTRDIFF_T 't' -#define QUALIFIER_INTMAX_T 'j' -#define QUALIFIER_QUAD 'q' -#define QUALIFIER_SIZE_T_UPPER 'Z' -#if TRIO_MISC -# define QUALIFIER_WIDECHAR 'w' -#endif -#define QUALIFIER_FIXED_SIZE 'I' -#define QUALIFIER_QUOTE '\'' -#define QUALIFIER_STICKY '!' -#define QUALIFIER_VARSIZE '&' /* This should remain undocumented */ -#define QUALIFIER_ROUNDING_UPPER 'R' -#if TRIO_EXTENSION -# define QUALIFIER_PARAM '@' /* Experimental */ -# define QUALIFIER_COLON ':' /* For scanlists */ -# define QUALIFIER_EQUAL '=' /* For scanlists */ -#endif - - -/************************************************************************* - * - * Internal Structures - * - *************************************************************************/ - -/* Parameters */ -typedef struct { - /* An indication of which entry in the data union is used */ - int type; - /* The flags */ - trio_flags_t flags; - /* The width qualifier */ - int width; - /* The precision qualifier */ - int precision; - /* The base qualifier */ - int base; - /* Base from specifier */ - int baseSpecifier; - /* The size for the variable size qualifier */ - int varsize; - /* Offset of the first character of the specifier */ - int beginOffset; - /* Offset of the first character after the specifier */ - int endOffset; - /* Position in the argument list that this parameter refers to */ - int position; - /* The data from the argument list */ - union { - char *string; -#if TRIO_FEATURE_WIDECHAR - trio_wchar_t *wstring; -#endif - trio_pointer_t pointer; - union { - trio_intmax_t as_signed; - trio_uintmax_t as_unsigned; - } number; -#if TRIO_FEATURE_FLOAT - double doubleNumber; - double *doublePointer; - trio_long_double_t longdoubleNumber; - trio_long_double_t *longdoublePointer; -#endif - int errorNumber; - } data; -#if TRIO_FEATURE_USER_DEFINED - /* For the user-defined specifier */ - union { - char namespace[MAX_USER_NAME]; - int handler; /* if flags & FLAGS_USER_DEFINED_PARAMETER */ - } user_defined; - char user_data[MAX_USER_DATA]; -#endif -} trio_parameter_t; - -/* Container for customized functions */ -typedef struct { - union { - trio_outstream_t out; - trio_instream_t in; - } stream; - trio_pointer_t closure; -} trio_custom_t; - -/* General trio "class" */ -typedef struct _trio_class_t { - /* - * The function to write characters to a stream. - */ - void (*OutStream) TRIO_PROTO((struct _trio_class_t *, int)); - /* - * The function to read characters from a stream. - */ - void (*InStream) TRIO_PROTO((struct _trio_class_t *, int *)); - /* - * The function to undo read characters from a stream. - */ - void (*UndoStream) TRIO_PROTO((struct _trio_class_t *)); - /* - * The current location in the stream. - */ - trio_pointer_t location; - /* - * The character currently being processed. - */ - int current; - /* - * The number of characters that would have been written/read - * if there had been sufficient space. - */ - int processed; - union { - /* - * The number of characters that are actually written. Processed and - * committed will only differ for the *nprintf functions. - */ - int committed; - /* - * The number of look-ahead characters read. - */ - int cached; - } actually; - /* - * The upper limit of characters that may be written/read. - */ - int max; - /* - * The last output error that was detected. - */ - int error; -} trio_class_t; - -/* References (for user-defined callbacks) */ -typedef struct _trio_reference_t { - trio_class_t *data; - trio_parameter_t *parameter; -} trio_reference_t; - -#if TRIO_FEATURE_USER_DEFINED -/* Registered entries (for user-defined callbacks) */ -typedef struct _trio_userdef_t { - struct _trio_userdef_t *next; - trio_callback_t callback; - char *name; -} trio_userdef_t; -#endif - -/************************************************************************* - * - * Internal Variables - * - *************************************************************************/ - -static TRIO_CONST char rcsid[] = "@(#)$Id$"; - -#if TRIO_FEATURE_FLOAT -/* - * Need this to workaround a parser bug in HP C/iX compiler that fails - * to resolves macro definitions that includes type 'long double', - * e.g: va_arg(arg_ptr, long double) - */ -# if defined(TRIO_PLATFORM_MPEIX) -static TRIO_CONST trio_long_double_t ___dummy_long_double = 0; -# endif -#endif - -static TRIO_CONST char internalNullString[] = "(nil)"; - -#if defined(USE_LOCALE) -static struct lconv *internalLocaleValues = NULL; -#endif - -/* - * UNIX98 says "in a locale where the radix character is not defined, - * the radix character defaults to a period (.)" - */ -#if TRIO_FEATURE_FLOAT || TRIO_FEATURE_LOCALE || defined(USE_LOCALE) -static int internalDecimalPointLength = 1; -static char internalDecimalPoint = '.'; -static char internalDecimalPointString[MAX_LOCALE_SEPARATOR_LENGTH + 1] = "."; -#endif -#if TRIO_FEATURE_QUOTE || TRIO_FEATURE_LOCALE || TRIO_EXTENSION -static int internalThousandSeparatorLength = 1; -static char internalThousandSeparator[MAX_LOCALE_SEPARATOR_LENGTH + 1] = ","; -static char internalGrouping[MAX_LOCALE_GROUPS] = { (char)NO_GROUPING }; -#endif - -static TRIO_CONST char internalDigitsLower[] = "0123456789abcdefghijklmnopqrstuvwxyz"; -static TRIO_CONST char internalDigitsUpper[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; -#if TRIO_FEATURE_SCANF -static BOOLEAN_T internalDigitsUnconverted = TRUE; -static int internalDigitArray[128]; -# if TRIO_EXTENSION -static BOOLEAN_T internalCollationUnconverted = TRUE; -static char internalCollationArray[MAX_CHARACTER_CLASS][MAX_CHARACTER_CLASS]; -# endif -#endif - -#if TRIO_FEATURE_USER_DEFINED -static TRIO_VOLATILE trio_callback_t internalEnterCriticalRegion = NULL; -static TRIO_VOLATILE trio_callback_t internalLeaveCriticalRegion = NULL; -static trio_userdef_t *internalUserDef = NULL; -#endif - - -/************************************************************************* - * - * Internal Functions - * - ************************************************************************/ - -#if defined(TRIO_EMBED_NAN) -# include "trionan.c" -#endif - -#if defined(TRIO_EMBED_STRING) -# include "triostr.c" -#endif - -/************************************************************************* - * TrioInitializeParameter - * - * Description: - * Initialize a trio_parameter_t struct. - */ -TRIO_PRIVATE void -TrioInitializeParameter -TRIO_ARGS1((parameter), - trio_parameter_t *parameter) -{ - parameter->type = FORMAT_UNKNOWN; - parameter->flags = 0; - parameter->width = 0; - parameter->precision = 0; - parameter->base = 0; - parameter->baseSpecifier = 0; - parameter->varsize = 0; - parameter->beginOffset = 0; - parameter->endOffset = 0; - parameter->position = 0; - parameter->data.pointer = 0; -#if TRIO_FEATURE_USER_DEFINED - parameter->user_defined.handler = 0; - parameter->user_data[0] = 0; -#endif -} - -/************************************************************************* - * TrioCopyParameter - * - * Description: - * Copies one trio_parameter_t struct to another. - */ -TRIO_PRIVATE void -TrioCopyParameter -TRIO_ARGS2((target, source), - trio_parameter_t *target, - TRIO_CONST trio_parameter_t *source) -{ -#if TRIO_FEATURE_USER_DEFINED - size_t i; -#endif - - target->type = source->type; - target->flags = source->flags; - target->width = source->width; - target->precision = source->precision; - target->base = source->base; - target->baseSpecifier = source->baseSpecifier; - target->varsize = source->varsize; - target->beginOffset = source->beginOffset; - target->endOffset = source->endOffset; - target->position = source->position; - target->data = source->data; - -#if TRIO_FEATURE_USER_DEFINED - target->user_defined = source->user_defined; - - for (i = 0U; i < sizeof(target->user_data); ++i) - { - if ((target->user_data[i] = source->user_data[i]) == NIL) - break; - } -#endif -} - -/************************************************************************* - * TrioIsQualifier - * - * Description: - * Remember to add all new qualifiers to this function. - * QUALIFIER_POSITION must not be added. - */ -TRIO_PRIVATE BOOLEAN_T -TrioIsQualifier -TRIO_ARGS1((character), - TRIO_CONST char character) -{ - /* QUALIFIER_POSITION is not included */ - switch (character) - { - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - case QUALIFIER_PLUS: - case QUALIFIER_MINUS: - case QUALIFIER_SPACE: - case QUALIFIER_DOT: - case QUALIFIER_STAR: - case QUALIFIER_ALTERNATIVE: - case QUALIFIER_SHORT: - case QUALIFIER_LONG: - case QUALIFIER_CIRCUMFLEX: - case QUALIFIER_LONG_UPPER: - case QUALIFIER_SIZE_T: - case QUALIFIER_PTRDIFF_T: - case QUALIFIER_INTMAX_T: - case QUALIFIER_QUAD: - case QUALIFIER_SIZE_T_UPPER: -#if defined(QUALIFIER_WIDECHAR) - case QUALIFIER_WIDECHAR: -#endif - case QUALIFIER_QUOTE: - case QUALIFIER_STICKY: - case QUALIFIER_VARSIZE: -#if defined(QUALIFIER_PARAM) - case QUALIFIER_PARAM: -#endif - case QUALIFIER_FIXED_SIZE: - case QUALIFIER_ROUNDING_UPPER: - return TRUE; - default: - return FALSE; - } -} - -/************************************************************************* - * TrioSetLocale - */ -#if defined(USE_LOCALE) -TRIO_PRIVATE void -TrioSetLocale(TRIO_NOARGS) -{ - internalLocaleValues = (struct lconv *)localeconv(); - if (internalLocaleValues) - { - if ((internalLocaleValues->decimal_point) && - (internalLocaleValues->decimal_point[0] != NIL)) - { - internalDecimalPointLength = trio_length(internalLocaleValues->decimal_point); - if (internalDecimalPointLength == 1) - { - internalDecimalPoint = internalLocaleValues->decimal_point[0]; - } - else - { - internalDecimalPoint = NIL; - trio_copy_max(internalDecimalPointString, - sizeof(internalDecimalPointString), - internalLocaleValues->decimal_point); - } - } -# if TRIO_EXTENSION - if ((internalLocaleValues->thousands_sep) && - (internalLocaleValues->thousands_sep[0] != NIL)) - { - trio_copy_max(internalThousandSeparator, - sizeof(internalThousandSeparator), - internalLocaleValues->thousands_sep); - internalThousandSeparatorLength = trio_length(internalThousandSeparator); - } -# endif -# if TRIO_EXTENSION - if ((internalLocaleValues->grouping) && - (internalLocaleValues->grouping[0] != NIL)) - { - trio_copy_max(internalGrouping, - sizeof(internalGrouping), - internalLocaleValues->grouping); - } -# endif - } -} -#endif /* defined(USE_LOCALE) */ - -#if TRIO_FEATURE_FLOAT && TRIO_FEATURE_QUOTE -TRIO_PRIVATE int -TrioCalcThousandSeparatorLength -TRIO_ARGS1((digits), - int digits) -{ - int count = 0; - int step = NO_GROUPING; - char *groupingPointer = internalGrouping; - - while (digits > 0) - { - if (*groupingPointer == CHAR_MAX) - { - /* Disable grouping */ - break; /* while */ - } - else if (*groupingPointer == 0) - { - /* Repeat last group */ - if (step == NO_GROUPING) - { - /* Error in locale */ - break; /* while */ - } - } - else - { - step = *groupingPointer++; - } - if (digits > step) - count += internalThousandSeparatorLength; - digits -= step; - } - return count; -} -#endif /* TRIO_FEATURE_FLOAT && TRIO_FEATURE_QUOTE */ - -#if TRIO_FEATURE_QUOTE -TRIO_PRIVATE BOOLEAN_T -TrioFollowedBySeparator -TRIO_ARGS1((position), - int position) -{ - int step = 0; - char *groupingPointer = internalGrouping; - - position--; - if (position == 0) - return FALSE; - while (position > 0) - { - if (*groupingPointer == CHAR_MAX) - { - /* Disable grouping */ - break; /* while */ - } - else if (*groupingPointer != 0) - { - step = *groupingPointer++; - } - if (step == 0) - break; - position -= step; - } - return (position == 0); -} -#endif /* TRIO_FEATURE_QUOTE */ - -/************************************************************************* - * TrioGetPosition - * - * Get the %n$ position. - */ -TRIO_PRIVATE int -TrioGetPosition -TRIO_ARGS2((format, offsetPointer), - TRIO_CONST char *format, - int *offsetPointer) -{ -#if TRIO_FEATURE_POSITIONAL - char *tmpformat; - int number = 0; - int offset = *offsetPointer; - - number = (int)trio_to_long(&format[offset], &tmpformat, BASE_DECIMAL); - offset = (int)(tmpformat - format); - if ((number != 0) && (QUALIFIER_POSITION == format[offset++])) - { - *offsetPointer = offset; - /* - * number is decreased by 1, because n$ starts from 1, whereas - * the array it is indexing starts from 0. - */ - return number - 1; - } -#endif - return NO_POSITION; -} - -/************************************************************************* - * TrioFindNamespace - * - * Find registered user-defined specifier. - * The prev argument is used for optimization only. - */ -#if TRIO_FEATURE_USER_DEFINED -TRIO_PRIVATE trio_userdef_t * -TrioFindNamespace -TRIO_ARGS2((name, prev), - TRIO_CONST char *name, - trio_userdef_t **prev) -{ - trio_userdef_t *def; - - if (internalEnterCriticalRegion) - (void)internalEnterCriticalRegion(NULL); - - for (def = internalUserDef; def; def = def->next) - { - /* Case-sensitive string comparison */ - if (trio_equal_case(def->name, name)) - break; - - if (prev) - *prev = def; - } - - if (internalLeaveCriticalRegion) - (void)internalLeaveCriticalRegion(NULL); - - return def; -} -#endif - -/************************************************************************* - * TrioPower - * - * Description: - * Calculate pow(base, exponent), where number and exponent are integers. - */ -#if TRIO_FEATURE_FLOAT -TRIO_PRIVATE trio_long_double_t -TrioPower -TRIO_ARGS2((number, exponent), - int number, - int exponent) -{ - trio_long_double_t result; - - if (number == 10) - { - switch (exponent) - { - /* Speed up calculation of common cases */ - case 0: - result = (trio_long_double_t)number * TRIO_SUFFIX_LONG(1E-1); - break; - case 1: - result = (trio_long_double_t)number * TRIO_SUFFIX_LONG(1E+0); - break; - case 2: - result = (trio_long_double_t)number * TRIO_SUFFIX_LONG(1E+1); - break; - case 3: - result = (trio_long_double_t)number * TRIO_SUFFIX_LONG(1E+2); - break; - case 4: - result = (trio_long_double_t)number * TRIO_SUFFIX_LONG(1E+3); - break; - case 5: - result = (trio_long_double_t)number * TRIO_SUFFIX_LONG(1E+4); - break; - case 6: - result = (trio_long_double_t)number * TRIO_SUFFIX_LONG(1E+5); - break; - case 7: - result = (trio_long_double_t)number * TRIO_SUFFIX_LONG(1E+6); - break; - case 8: - result = (trio_long_double_t)number * TRIO_SUFFIX_LONG(1E+7); - break; - case 9: - result = (trio_long_double_t)number * TRIO_SUFFIX_LONG(1E+8); - break; - default: - result = trio_pow((trio_long_double_t)number, - (trio_long_double_t)exponent); - break; - } - } - else - { - return trio_pow((trio_long_double_t)number, - (trio_long_double_t)exponent); - } - return result; -} -#endif /* TRIO_FEATURE_FLOAT */ - -/************************************************************************* - * TrioLogarithm - */ -#if TRIO_FEATURE_FLOAT -TRIO_PRIVATE trio_long_double_t -TrioLogarithm -TRIO_ARGS2((number, base), - trio_long_double_t number, - int base) -{ - trio_long_double_t result; - - if (number <= 0.0) - { - /* xlC crashes on log(0) */ - result = (number == 0.0) ? trio_ninf() : trio_nan(); - } - else - { - if (base == 10) - { - result = trio_log10(number); - } - else - { - result = trio_log10(number) / trio_log10((double)base); - } - } - return result; -} -#endif /* TRIO_FEATURE_FLOAT */ - -/************************************************************************* - * TrioLogarithmBase - */ -#if TRIO_FEATURE_FLOAT -TRIO_PRIVATE double -TrioLogarithmBase -TRIO_ARGS1((base), - int base) -{ - switch (base) - { - case BASE_BINARY : return 1.0; - case BASE_OCTAL : return 3.0; - case BASE_DECIMAL: return 3.321928094887362345; - case BASE_HEX : return 4.0; - default : return TrioLogarithm((double)base, 2); - } -} -#endif /* TRIO_FEATURE_FLOAT */ - -/************************************************************************* - * TrioParseQualifiers - * - * Description: - * Parse the qualifiers of a potential conversion specifier - */ -TRIO_PRIVATE int -TrioParseQualifiers -TRIO_ARGS4((type, format, offset, parameter), - int type, - TRIO_CONST char *format, - int offset, - trio_parameter_t *parameter) -{ - char ch; - int dots = 0; /* Count number of dots in modifier part */ - char *tmpformat; - - parameter->beginOffset = offset - 1; - parameter->flags = FLAGS_NEW; - parameter->position = TrioGetPosition(format, &offset); - - /* Default values */ - parameter->width = NO_WIDTH; - parameter->precision = NO_PRECISION; - parameter->base = NO_BASE; - parameter->varsize = NO_SIZE; - - while (TrioIsQualifier(format[offset])) - { - ch = format[offset++]; - - switch (ch) - { - case QUALIFIER_SPACE: - parameter->flags |= FLAGS_SPACE; - break; - - case QUALIFIER_PLUS: - parameter->flags |= FLAGS_SHOWSIGN; - break; - - case QUALIFIER_MINUS: - parameter->flags |= FLAGS_LEFTADJUST; - parameter->flags &= ~FLAGS_NILPADDING; - break; - - case QUALIFIER_ALTERNATIVE: - parameter->flags |= FLAGS_ALTERNATIVE; - break; - - case QUALIFIER_DOT: - if (dots == 0) /* Precision */ - { - dots++; - - /* Skip if no precision */ - if (QUALIFIER_DOT == format[offset]) - break; - - /* After the first dot we have the precision */ - parameter->flags |= FLAGS_PRECISION; - if ((QUALIFIER_STAR == format[offset]) -#if defined(QUALIFIER_PARAM) - || (QUALIFIER_PARAM == format[offset]) -#endif - ) - { - offset++; - parameter->flags |= FLAGS_PRECISION_PARAMETER; - parameter->precision = TrioGetPosition(format, &offset); - } - else - { - parameter->precision = trio_to_long(&format[offset], - &tmpformat, - BASE_DECIMAL); - offset = (int)(tmpformat - format); - } - } - else if (dots == 1) /* Base */ - { - dots++; - - /* After the second dot we have the base */ - parameter->flags |= FLAGS_BASE; - if ((QUALIFIER_STAR == format[offset]) -#if defined(QUALIFIER_PARAM) - || (QUALIFIER_PARAM == format[offset]) -#endif - ) - { - offset++; - parameter->flags |= FLAGS_BASE_PARAMETER; - parameter->base = TrioGetPosition(format, &offset); - } - else - { - parameter->base = trio_to_long(&format[offset], - &tmpformat, - BASE_DECIMAL); - if (parameter->base > MAX_BASE) - return TRIO_ERROR_RETURN(TRIO_EINVAL, offset); - offset = (int)(tmpformat - format); - } - } - else - { - return TRIO_ERROR_RETURN(TRIO_EINVAL, offset); - } - break; /* QUALIFIER_DOT */ - -#if defined(QUALIFIER_PARAM) - case QUALIFIER_PARAM: - parameter->type = TYPE_PRINT; - /* FALLTHROUGH */ -#endif - case QUALIFIER_STAR: - /* This has different meanings for print and scan */ - if (TYPE_PRINT == type) - { - /* Read with from parameter */ - int width = TrioGetPosition(format, &offset); - parameter->flags |= (FLAGS_WIDTH | FLAGS_WIDTH_PARAMETER); - if (NO_POSITION != width) - parameter->width = width; - /* else keep parameter->width = NO_WIDTH which != NO_POSITION */ - } -#if TRIO_FEATURE_SCANF - else - { - /* Scan, but do not store result */ - parameter->flags |= FLAGS_IGNORE; - } -#endif - break; /* QUALIFIER_STAR */ - - case '0': - if (! (parameter->flags & FLAGS_LEFTADJUST)) - parameter->flags |= FLAGS_NILPADDING; - /* FALLTHROUGH */ - case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - parameter->flags |= FLAGS_WIDTH; - /* - * &format[offset - 1] is used to "rewind" the read - * character from format - */ - parameter->width = trio_to_long(&format[offset - 1], - &tmpformat, - BASE_DECIMAL); - offset = (int)(tmpformat - format); - break; - - case QUALIFIER_SHORT: - if (parameter->flags & FLAGS_SHORTSHORT) - return TRIO_ERROR_RETURN(TRIO_EINVAL, offset); - else if (parameter->flags & FLAGS_SHORT) - parameter->flags |= FLAGS_SHORTSHORT; - else - parameter->flags |= FLAGS_SHORT; - break; - - case QUALIFIER_LONG: - if (parameter->flags & FLAGS_QUAD) - return TRIO_ERROR_RETURN(TRIO_EINVAL, offset); - else if (parameter->flags & FLAGS_LONG) - parameter->flags |= FLAGS_QUAD; - else - parameter->flags |= FLAGS_LONG; - break; - -#if TRIO_FEATURE_LONGDOUBLE - case QUALIFIER_LONG_UPPER: - parameter->flags |= FLAGS_LONGDOUBLE; - break; -#endif - -#if TRIO_FEATURE_SIZE_T - case QUALIFIER_SIZE_T: - parameter->flags |= FLAGS_SIZE_T; - /* Modify flags for later truncation of number */ - if (sizeof(size_t) == sizeof(trio_ulonglong_t)) - parameter->flags |= FLAGS_QUAD; - else if (sizeof(size_t) == sizeof(long)) - parameter->flags |= FLAGS_LONG; - break; -#endif - -#if TRIO_FEATURE_PTRDIFF_T - case QUALIFIER_PTRDIFF_T: - parameter->flags |= FLAGS_PTRDIFF_T; - if (sizeof(ptrdiff_t) == sizeof(trio_ulonglong_t)) - parameter->flags |= FLAGS_QUAD; - else if (sizeof(ptrdiff_t) == sizeof(long)) - parameter->flags |= FLAGS_LONG; - break; -#endif - -#if TRIO_FEATURE_INTMAX_T - case QUALIFIER_INTMAX_T: - parameter->flags |= FLAGS_INTMAX_T; - if (sizeof(trio_intmax_t) == sizeof(trio_ulonglong_t)) - parameter->flags |= FLAGS_QUAD; - else if (sizeof(trio_intmax_t) == sizeof(long)) - parameter->flags |= FLAGS_LONG; - break; -#endif - -#if TRIO_FEATURE_QUAD - case QUALIFIER_QUAD: - parameter->flags |= FLAGS_QUAD; - break; -#endif - -#if TRIO_FEATURE_FIXED_SIZE - case QUALIFIER_FIXED_SIZE: - if (parameter->flags & FLAGS_FIXED_SIZE) - return TRIO_ERROR_RETURN(TRIO_EINVAL, offset); - - if (parameter->flags & (FLAGS_ALL_SIZES | - FLAGS_LONGDOUBLE | - FLAGS_WIDECHAR | - FLAGS_VARSIZE_PARAMETER)) - return TRIO_ERROR_RETURN(TRIO_EINVAL, offset); - - if ((format[offset] == '6') && - (format[offset + 1] == '4')) - { - parameter->varsize = sizeof(trio_int64_t); - offset += 2; - } - else if ((format[offset] == '3') && - (format[offset + 1] == '2')) - { - parameter->varsize = sizeof(trio_int32_t); - offset += 2; - } - else if ((format[offset] == '1') && - (format[offset + 1] == '6')) - { - parameter->varsize = sizeof(trio_int16_t); - offset += 2; - } - else if (format[offset] == '8') - { - parameter->varsize = sizeof(trio_int8_t); - offset++; - } - else - return TRIO_ERROR_RETURN(TRIO_EINVAL, offset); - - parameter->flags |= FLAGS_FIXED_SIZE; - break; -#endif /* TRIO_FEATURE_FIXED_SIZE */ - -#if defined(QUALIFIER_WIDECHAR) - case QUALIFIER_WIDECHAR: - parameter->flags |= FLAGS_WIDECHAR; - break; -#endif - -#if TRIO_FEATURE_SIZE_T_UPPER - case QUALIFIER_SIZE_T_UPPER: - break; -#endif - -#if TRIO_FEATURE_QUOTE - case QUALIFIER_QUOTE: - parameter->flags |= FLAGS_QUOTE; - break; -#endif - -#if TRIO_FEATURE_STICKY - case QUALIFIER_STICKY: - parameter->flags |= FLAGS_STICKY; - break; -#endif - -#if TRIO_FEATURE_VARSIZE - case QUALIFIER_VARSIZE: - parameter->flags |= FLAGS_VARSIZE_PARAMETER; - break; -#endif - -#if TRIO_FEATURE_ROUNDING - case QUALIFIER_ROUNDING_UPPER: - parameter->flags |= FLAGS_ROUNDING; - break; -#endif - - default: - /* Bail out completely to make the error more obvious */ - return TRIO_ERROR_RETURN(TRIO_EINVAL, offset); - } - } /* while qualifier */ - - parameter->endOffset = offset; - - return 0; -} - -/************************************************************************* - * TrioParseSpecifier - * - * Description: - * Parse the specifier part of a potential conversion specifier - */ -TRIO_PRIVATE int -TrioParseSpecifier -TRIO_ARGS4((type, format, offset, parameter), - int type, - TRIO_CONST char *format, - int offset, - trio_parameter_t *parameter) -{ - parameter->baseSpecifier = NO_BASE; - - switch (format[offset++]) - { -#if defined(SPECIFIER_CHAR_UPPER) - case SPECIFIER_CHAR_UPPER: - parameter->flags |= FLAGS_WIDECHAR; - /* FALLTHROUGH */ -#endif - case SPECIFIER_CHAR: - if (parameter->flags & FLAGS_LONG) - parameter->flags |= FLAGS_WIDECHAR; - else if (parameter->flags & FLAGS_SHORT) - parameter->flags &= ~FLAGS_WIDECHAR; - parameter->type = FORMAT_CHAR; - break; - -#if defined(SPECIFIER_STRING_UPPER) - case SPECIFIER_STRING_UPPER: - parameter->flags |= FLAGS_WIDECHAR; - /* FALLTHROUGH */ -#endif - case SPECIFIER_STRING: - if (parameter->flags & FLAGS_LONG) - parameter->flags |= FLAGS_WIDECHAR; - else if (parameter->flags & FLAGS_SHORT) - parameter->flags &= ~FLAGS_WIDECHAR; - parameter->type = FORMAT_STRING; - break; - -#if defined(SPECIFIER_GROUP) - case SPECIFIER_GROUP: - if (TYPE_SCAN == type) - { - int depth = 1; - parameter->type = FORMAT_GROUP; - if (format[offset] == QUALIFIER_CIRCUMFLEX) - offset++; - if (format[offset] == SPECIFIER_UNGROUP) - offset++; - if (format[offset] == QUALIFIER_MINUS) - offset++; - /* Skip nested brackets */ - while (format[offset] != NIL) - { - if (format[offset] == SPECIFIER_GROUP) - { - depth++; - } - else if (format[offset] == SPECIFIER_UNGROUP) - { - if (--depth <= 0) - { - offset++; - break; - } - } - offset++; - } - } - break; -#endif /* defined(SPECIFIER_GROUP) */ - - case SPECIFIER_INTEGER: - parameter->type = FORMAT_INT; - break; - - case SPECIFIER_UNSIGNED: - parameter->flags |= FLAGS_UNSIGNED; - parameter->type = FORMAT_INT; - break; - - case SPECIFIER_DECIMAL: - parameter->baseSpecifier = BASE_DECIMAL; - parameter->type = FORMAT_INT; - break; - - case SPECIFIER_OCTAL: - parameter->flags |= FLAGS_UNSIGNED; - parameter->baseSpecifier = BASE_OCTAL; - parameter->type = FORMAT_INT; - break; - -#if TRIO_FEATURE_BINARY - case SPECIFIER_BINARY_UPPER: - parameter->flags |= FLAGS_UPPER; - /* FALLTHROUGH */ - case SPECIFIER_BINARY: - parameter->flags |= FLAGS_NILPADDING; - parameter->baseSpecifier = BASE_BINARY; - parameter->type = FORMAT_INT; - break; -#endif - - case SPECIFIER_HEX_UPPER: - parameter->flags |= FLAGS_UPPER; - /* FALLTHROUGH */ - case SPECIFIER_HEX: - parameter->flags |= FLAGS_UNSIGNED; - parameter->baseSpecifier = BASE_HEX; - parameter->type = FORMAT_INT; - break; - -#if defined(SPECIFIER_FLOAT_E) -# if defined(SPECIFIER_FLOAT_E_UPPER) - case SPECIFIER_FLOAT_E_UPPER: - parameter->flags |= FLAGS_UPPER; - /* FALLTHROUGH */ -# endif - case SPECIFIER_FLOAT_E: - parameter->flags |= FLAGS_FLOAT_E; - parameter->type = FORMAT_DOUBLE; - break; -#endif - -#if defined(SPECIFIER_FLOAT_G) -# if defined(SPECIFIER_FLOAT_G_UPPER) - case SPECIFIER_FLOAT_G_UPPER: - parameter->flags |= FLAGS_UPPER; - /* FALLTHROUGH */ -# endif - case SPECIFIER_FLOAT_G: - parameter->flags |= FLAGS_FLOAT_G; - parameter->type = FORMAT_DOUBLE; - break; -#endif - -#if defined(SPECIFIER_FLOAT_F) -# if defined(SPECIFIER_FLOAT_F_UPPER) - case SPECIFIER_FLOAT_F_UPPER: - parameter->flags |= FLAGS_UPPER; - /* FALLTHROUGH */ -# endif - case SPECIFIER_FLOAT_F: - parameter->type = FORMAT_DOUBLE; - break; -#endif - -#if defined(TRIO_COMPILER_VISUALC) -# pragma warning( push ) -# pragma warning( disable : 4127 ) /* Conditional expression is constant */ -#endif - case SPECIFIER_POINTER: - if (sizeof(trio_pointer_t) == sizeof(trio_ulonglong_t)) - parameter->flags |= FLAGS_QUAD; - else if (sizeof(trio_pointer_t) == sizeof(long)) - parameter->flags |= FLAGS_LONG; - parameter->type = FORMAT_POINTER; - break; -#if defined(TRIO_COMPILER_VISUALC) -# pragma warning( pop ) -#endif - - case SPECIFIER_COUNT: - parameter->type = FORMAT_COUNT; - break; - -#if TRIO_FEATURE_HEXFLOAT - case SPECIFIER_HEXFLOAT_UPPER: - parameter->flags |= FLAGS_UPPER; - /* FALLTHROUGH */ - case SPECIFIER_HEXFLOAT: - parameter->baseSpecifier = BASE_HEX; - parameter->type = FORMAT_DOUBLE; - break; -#endif - -#if TRIO_FEATURE_ERRNO - case SPECIFIER_ERRNO: - parameter->type = FORMAT_ERRNO; - break; -#endif - -#if TRIO_FEATURE_USER_DEFINED - case SPECIFIER_USER_DEFINED_BEGIN: - { - unsigned int max; - int without_namespace = TRUE; - char* tmpformat = (char *)&format[offset]; - int ch; - - parameter->type = FORMAT_USER_DEFINED; - parameter->user_defined.namespace[0] = NIL; - - while ((ch = format[offset]) != NIL) - { - offset++; - if ((ch == SPECIFIER_USER_DEFINED_END) || (ch == SPECIFIER_USER_DEFINED_EXTRA)) - { - if (without_namespace) - /* No namespace, handler will be passed as an argument */ - parameter->flags |= FLAGS_USER_DEFINED_PARAMETER; - - /* Copy the user data */ - max = (unsigned int)(&format[offset] - tmpformat); - if (max > MAX_USER_DATA) - max = MAX_USER_DATA; - trio_copy_max(parameter->user_data, max, tmpformat); - - /* Skip extra data (which is only there to keep the compiler happy) */ - while ((ch != NIL) && (ch != SPECIFIER_USER_DEFINED_END)) - ch = format[offset++]; - - break; /* while */ - } - - if (ch == SPECIFIER_USER_DEFINED_SEPARATOR) - { - without_namespace = FALSE; - /* Copy the namespace for later looking-up */ - max = (int)(&format[offset] - tmpformat); - if (max > MAX_USER_NAME) - max = MAX_USER_NAME; - trio_copy_max(parameter->user_defined.namespace, max, tmpformat); - tmpformat = (char *)&format[offset]; - } - } - - if (ch != SPECIFIER_USER_DEFINED_END) - return TRIO_ERROR_RETURN(TRIO_EINVAL, offset); - } - break; -#endif /* TRIO_FEATURE_USER_DEFINED */ - - default: - /* Bail out completely to make the error more obvious */ - return TRIO_ERROR_RETURN(TRIO_EINVAL, offset); - } - - parameter->endOffset = offset; - - return 0; -} - -/************************************************************************* - * TrioParse - * - * Description: - * Parse the format string - */ -TRIO_PRIVATE int -TrioParse -TRIO_ARGS6((type, format, parameters, arglist, argfunc, argarray), - int type, - TRIO_CONST char *format, - trio_parameter_t *parameters, - va_list arglist, - trio_argfunc_t argfunc, - trio_pointer_t *argarray) -{ - /* Count the number of times a parameter is referenced */ - unsigned short usedEntries[MAX_PARAMETERS]; - /* Parameter counters */ - int parameterPosition; - int maxParam = -1; - /* Utility variables */ - int offset; /* Offset into formatting string */ - BOOLEAN_T positional; /* Does the specifier have a positional? */ -#if TRIO_FEATURE_STICKY - BOOLEAN_T gotSticky = FALSE; /* Are there any sticky modifiers at all? */ -#endif - /* - * indices specifies the order in which the parameters must be - * read from the va_args (this is necessary to handle positionals) - */ - int indices[MAX_PARAMETERS]; - int pos = 0; - /* Various variables */ -#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE) - int charlen; -#endif - int save_errno; - int i = -1; - int num; - trio_parameter_t workParameter; - int status; - - /* Both must be set or none must be set */ - assert(((argfunc == NULL) && (argarray == NULL)) || - ((argfunc != NULL) && (argarray != NULL))); - - /* - * The 'parameters' array is not initialized, but we need to - * know which entries we have used. - */ - memset(usedEntries, 0, sizeof(usedEntries)); - - save_errno = errno; - offset = 0; - parameterPosition = 0; -#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE) - charlen = mblen(NULL, 0); -#endif - - while (format[offset]) - { - TrioInitializeParameter(&workParameter); - -#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE) - if (! isascii(format[offset])) - { - /* - * Multibyte characters cannot be legal specifiers or - * modifiers, so we skip over them. - */ - charlen = mblen(&format[offset], MB_LEN_MAX); - offset += (charlen > 0) ? charlen : 1; - continue; /* while */ - } -#endif /* TRIO_COMPILER_SUPPORTS_MULTIBYTE */ - - switch(format[offset++]) { - - case CHAR_IDENTIFIER: - { - if (CHAR_IDENTIFIER == format[offset]) - { - /* skip double "%" */ - offset++; - continue; /* while */ - } - - status = TrioParseQualifiers(type, format, offset, &workParameter); - if (status < 0) - return status; /* Return qualifier syntax error */ - - status = TrioParseSpecifier(type, format, workParameter.endOffset, &workParameter); - if (status < 0) - return status; /* Return specifier syntax error */ - } - break; - -#if TRIO_EXTENSION - case CHAR_ALT_IDENTIFIER: - { - status = TrioParseQualifiers(type, format, offset, &workParameter); - if (status < 0) - continue; /* False alert, not a user defined specifier */ - - status = TrioParseSpecifier(type, format, workParameter.endOffset, &workParameter); - if ((status < 0) || (FORMAT_USER_DEFINED != workParameter.type)) - continue; /* False alert, not a user defined specifier */ - } - break; -#endif - - default: - continue; /* while */ - } - - /* now handle the parsed conversion specification */ - positional = (NO_POSITION != workParameter.position); - - /* - * Parameters only need the type and value. The value is - * read later. - */ - if (workParameter.flags & FLAGS_WIDTH_PARAMETER) - { - if (workParameter.width == NO_WIDTH) - { - workParameter.width = parameterPosition++; - } - else - { - if (! positional) - workParameter.position = workParameter.width + 1; - } - - usedEntries[workParameter.width] += 1; - if (workParameter.width > maxParam) - maxParam = workParameter.width; - parameters[pos].type = FORMAT_PARAMETER; - parameters[pos].flags = 0; - indices[workParameter.width] = pos; - workParameter.width = pos++; - } - if (workParameter.flags & FLAGS_PRECISION_PARAMETER) - { - if (workParameter.precision == NO_PRECISION) - { - workParameter.precision = parameterPosition++; - } - else - { - if (! positional) - workParameter.position = workParameter.precision + 1; - } - - usedEntries[workParameter.precision] += 1; - if (workParameter.precision > maxParam) - maxParam = workParameter.precision; - parameters[pos].type = FORMAT_PARAMETER; - parameters[pos].flags = 0; - indices[workParameter.precision] = pos; - workParameter.precision = pos++; - } - if (workParameter.flags & FLAGS_BASE_PARAMETER) - { - if (workParameter.base == NO_BASE) - { - workParameter.base = parameterPosition++; - } - else - { - if (! positional) - workParameter.position = workParameter.base + 1; - } - - usedEntries[workParameter.base] += 1; - if (workParameter.base > maxParam) - maxParam = workParameter.base; - parameters[pos].type = FORMAT_PARAMETER; - parameters[pos].flags = 0; - indices[workParameter.base] = pos; - workParameter.base = pos++; - } -#if TRIO_FEATURE_VARSIZE - if (workParameter.flags & FLAGS_VARSIZE_PARAMETER) - { - workParameter.varsize = parameterPosition++; - - usedEntries[workParameter.varsize] += 1; - if (workParameter.varsize > maxParam) - maxParam = workParameter.varsize; - parameters[pos].type = FORMAT_PARAMETER; - parameters[pos].flags = 0; - indices[workParameter.varsize] = pos; - workParameter.varsize = pos++; - } -#endif -#if TRIO_FEATURE_USER_DEFINED - if (workParameter.flags & FLAGS_USER_DEFINED_PARAMETER) - { - workParameter.user_defined.handler = parameterPosition++; - - usedEntries[workParameter.user_defined.handler] += 1; - if (workParameter.user_defined.handler > maxParam) - maxParam = workParameter.user_defined.handler; - parameters[pos].type = FORMAT_PARAMETER; - parameters[pos].flags = FLAGS_USER_DEFINED; - indices[workParameter.user_defined.handler] = pos; - workParameter.user_defined.handler = pos++; - } -#endif - - if (NO_POSITION == workParameter.position) - { - workParameter.position = parameterPosition++; - } - - if (workParameter.position > maxParam) - maxParam = workParameter.position; - - if (workParameter.position >= MAX_PARAMETERS) - { - /* Bail out completely to make the error more obvious */ - return TRIO_ERROR_RETURN(TRIO_ETOOMANY, offset); - } - - indices[workParameter.position] = pos; - - /* Count the number of times this entry has been used */ - usedEntries[workParameter.position] += 1; - - /* Find last sticky parameters */ -#if TRIO_FEATURE_STICKY - if (workParameter.flags & FLAGS_STICKY) - { - gotSticky = TRUE; - } - else if (gotSticky) - { - for (i = pos - 1; i >= 0; i--) - { - if (parameters[i].type == FORMAT_PARAMETER) - continue; - if ((parameters[i].flags & FLAGS_STICKY) && - (parameters[i].type == workParameter.type)) - { - /* Do not overwrite current qualifiers */ - workParameter.flags |= (parameters[i].flags & (unsigned long)~FLAGS_STICKY); - if (workParameter.width == NO_WIDTH) - workParameter.width = parameters[i].width; - if (workParameter.precision == NO_PRECISION) - workParameter.precision = parameters[i].precision; - if (workParameter.base == NO_BASE) - workParameter.base = parameters[i].base; - break; - } - } - } -#endif - - if (workParameter.base == NO_BASE) - workParameter.base = BASE_DECIMAL; - - offset = workParameter.endOffset; - - TrioCopyParameter(¶meters[pos++], &workParameter); - } /* while format characters left */ - - parameters[pos].type = FORMAT_SENTINEL; /* end parameter array with sentinel */ - parameters[pos].beginOffset = offset; - - for (num = 0; num <= maxParam; num++) - { - if (usedEntries[num] != 1) - { - if (usedEntries[num] == 0) /* gap detected */ - return TRIO_ERROR_RETURN(TRIO_EGAP, num); - else /* double references detected */ - return TRIO_ERROR_RETURN(TRIO_EDBLREF, num); - } - - i = indices[num]; - - /* - * FORMAT_PARAMETERS are only present if they must be read, - * so it makes no sense to check the ignore flag (besides, - * the flags variable is not set for that particular type) - */ - if ((parameters[i].type != FORMAT_PARAMETER) && - (parameters[i].flags & FLAGS_IGNORE)) - continue; /* for all arguments */ - - /* - * The stack arguments are read according to ANSI C89 - * default argument promotions: - * - * char = int - * short = int - * unsigned char = unsigned int - * unsigned short = unsigned int - * float = double - * - * In addition to the ANSI C89 these types are read (the - * default argument promotions of C99 has not been - * considered yet) - * - * long long - * long double - * size_t - * ptrdiff_t - * intmax_t - */ - switch (parameters[i].type) - { - case FORMAT_GROUP: - case FORMAT_STRING: -#if TRIO_FEATURE_WIDECHAR - if (parameters[i].flags & FLAGS_WIDECHAR) - { - parameters[i].data.wstring = (argfunc == NULL) - ? va_arg(arglist, trio_wchar_t *) - : (trio_wchar_t *)(argfunc(argarray, num, TRIO_TYPE_PWCHAR)); - } - else -#endif - { - parameters[i].data.string = (argfunc == NULL) - ? va_arg(arglist, char *) - : (char *)(argfunc(argarray, num, TRIO_TYPE_PCHAR)); - } - break; - -#if TRIO_FEATURE_USER_DEFINED - case FORMAT_USER_DEFINED: -#endif - case FORMAT_POINTER: - case FORMAT_COUNT: - case FORMAT_UNKNOWN: - parameters[i].data.pointer = (argfunc == NULL) - ? va_arg(arglist, trio_pointer_t ) - : argfunc(argarray, num, TRIO_TYPE_POINTER); - break; - - case FORMAT_CHAR: - case FORMAT_INT: -#if TRIO_FEATURE_SCANF - if (TYPE_SCAN == type) - { - if (argfunc == NULL) - parameters[i].data.pointer = - (trio_pointer_t)va_arg(arglist, trio_pointer_t); - else - { - if (parameters[i].type == FORMAT_CHAR) - parameters[i].data.pointer = - (trio_pointer_t)((char *)argfunc(argarray, num, TRIO_TYPE_CHAR)); - else if (parameters[i].flags & FLAGS_SHORT) - parameters[i].data.pointer = - (trio_pointer_t)((short *)argfunc(argarray, num, TRIO_TYPE_SHORT)); - else - parameters[i].data.pointer = - (trio_pointer_t)((int *)argfunc(argarray, num, TRIO_TYPE_INT)); - } - } - else -#endif /* TRIO_FEATURE_SCANF */ - { -#if TRIO_FEATURE_VARSIZE || TRIO_FEATURE_FIXED_SIZE - if (parameters[i].flags - & (FLAGS_VARSIZE_PARAMETER | FLAGS_FIXED_SIZE)) - { - int varsize; - if (parameters[i].flags & FLAGS_VARSIZE_PARAMETER) - { - /* - * Variable sizes are mapped onto the fixed sizes, in - * accordance with integer promotion. - * - * Please note that this may not be portable, as we - * only guess the size, not the layout of the numbers. - * For example, if int is little-endian, and long is - * big-endian, then this will fail. - */ - varsize = (int)parameters[parameters[i].varsize].data.number.as_unsigned; - } - else - { - /* Used for the I modifiers */ - varsize = parameters[i].varsize; - } - parameters[i].flags &= ~FLAGS_ALL_VARSIZES; - - if (varsize <= (int)sizeof(int)) - ; - else if (varsize <= (int)sizeof(long)) - parameters[i].flags |= FLAGS_LONG; -#if TRIO_FEATURE_INTMAX_T - else if (varsize <= (int)sizeof(trio_longlong_t)) - parameters[i].flags |= FLAGS_QUAD; - else - parameters[i].flags |= FLAGS_INTMAX_T; -#else - else - parameters[i].flags |= FLAGS_QUAD; -#endif - } -#endif /* TRIO_FEATURE_VARSIZE */ -#if TRIO_FEATURE_SIZE_T || TRIO_FEATURE_SIZE_T_UPPER - if (parameters[i].flags & FLAGS_SIZE_T) - parameters[i].data.number.as_unsigned = (argfunc == NULL) - ? (trio_uintmax_t)va_arg(arglist, size_t) - : (trio_uintmax_t)(*((size_t *)argfunc(argarray, num, TRIO_TYPE_SIZE))); - else -#endif -#if TRIO_FEATURE_PTRDIFF_T - if (parameters[i].flags & FLAGS_PTRDIFF_T) - parameters[i].data.number.as_unsigned = (argfunc == NULL) - ? (trio_uintmax_t)va_arg(arglist, ptrdiff_t) - : (trio_uintmax_t)(*((ptrdiff_t *)argfunc(argarray, num, TRIO_TYPE_PTRDIFF))); - else -#endif -#if TRIO_FEATURE_INTMAX_T - if (parameters[i].flags & FLAGS_INTMAX_T) - parameters[i].data.number.as_unsigned = (argfunc == NULL) - ? (trio_uintmax_t)va_arg(arglist, trio_intmax_t) - : (trio_uintmax_t)(*((trio_intmax_t *)argfunc(argarray, num, TRIO_TYPE_UINTMAX))); - else -#endif - if (parameters[i].flags & FLAGS_QUAD) - parameters[i].data.number.as_unsigned = (argfunc == NULL) - ? (trio_uintmax_t)va_arg(arglist, trio_ulonglong_t) - : (trio_uintmax_t)(*((trio_ulonglong_t *)argfunc(argarray, num, TRIO_TYPE_ULONGLONG))); - else if (parameters[i].flags & FLAGS_LONG) - parameters[i].data.number.as_unsigned = (argfunc == NULL) - ? (trio_uintmax_t)va_arg(arglist, long) - : (trio_uintmax_t)(*((long *)argfunc(argarray, num, TRIO_TYPE_LONG))); - else - { - if (argfunc == NULL) - parameters[i].data.number.as_unsigned = (trio_uintmax_t)va_arg(arglist, int); - else - { - if (parameters[i].type == FORMAT_CHAR) - parameters[i].data.number.as_unsigned = - (trio_uintmax_t)(*((char *)argfunc(argarray, num, TRIO_TYPE_CHAR))); - else if (parameters[i].flags & FLAGS_SHORT) - parameters[i].data.number.as_unsigned = - (trio_uintmax_t)(*((short *)argfunc(argarray, num, TRIO_TYPE_SHORT))); - else - parameters[i].data.number.as_unsigned = - (trio_uintmax_t)(*((int *)argfunc(argarray, num, TRIO_TYPE_INT))); - } - } - } - break; - - case FORMAT_PARAMETER: - /* - * The parameter for the user-defined specifier is a pointer, - * whereas the rest (width, precision, base) uses an integer. - */ - if (parameters[i].flags & FLAGS_USER_DEFINED) - parameters[i].data.pointer = (argfunc == NULL) - ? va_arg(arglist, trio_pointer_t ) - : argfunc(argarray, num, TRIO_TYPE_POINTER); - else - parameters[i].data.number.as_unsigned = (argfunc == NULL) - ? (trio_uintmax_t)va_arg(arglist, int) - : (trio_uintmax_t)(*((int *)argfunc(argarray, num, TRIO_TYPE_INT))); - break; - -#if TRIO_FEATURE_FLOAT - case FORMAT_DOUBLE: -# if TRIO_FEATURE_SCANF - if (TYPE_SCAN == type) - { - if (parameters[i].flags & FLAGS_LONGDOUBLE) - parameters[i].data.longdoublePointer = (argfunc == NULL) - ? va_arg(arglist, trio_long_double_t *) - : (trio_long_double_t *)argfunc(argarray, num, TRIO_TYPE_LONGDOUBLE); - else - { - if (parameters[i].flags & FLAGS_LONG) - parameters[i].data.doublePointer = (argfunc == NULL) - ? va_arg(arglist, double *) - : (double *)argfunc(argarray, num, TRIO_TYPE_DOUBLE); - else - parameters[i].data.doublePointer = (argfunc == NULL) - ? (double *)va_arg(arglist, float *) - : (double *)argfunc(argarray, num, TRIO_TYPE_DOUBLE); - } - } - else -# endif /* TRIO_FEATURE_SCANF */ - { - if (parameters[i].flags & FLAGS_LONGDOUBLE) - parameters[i].data.longdoubleNumber = (argfunc == NULL) - ? va_arg(arglist, trio_long_double_t) - : (trio_long_double_t)(*((trio_long_double_t *)argfunc(argarray, num, TRIO_TYPE_LONGDOUBLE))); - else - { - if (argfunc == NULL) - parameters[i].data.longdoubleNumber = - (trio_long_double_t)va_arg(arglist, double); - else - { - if (parameters[i].flags & FLAGS_SHORT) - parameters[i].data.longdoubleNumber = - (trio_long_double_t)(*((float *)argfunc(argarray, num, TRIO_TYPE_FLOAT))); - else - parameters[i].data.longdoubleNumber = - (trio_long_double_t)(*((double *)argfunc(argarray, num, TRIO_TYPE_DOUBLE))); - } - } - } - break; -#endif /* TRIO_FEATURE_FLOAT */ - -#if TRIO_FEATURE_ERRNO - case FORMAT_ERRNO: - parameters[i].data.errorNumber = save_errno; - break; -#endif - - default: - break; - } - } /* for all specifiers */ - return num; -} - - -/************************************************************************* - * - * FORMATTING - * - ************************************************************************/ - - -/************************************************************************* - * TrioWriteNumber - * - * Description: - * Output a number. - * The complexity of this function is a result of the complexity - * of the dependencies of the flags. - */ -TRIO_PRIVATE void -TrioWriteNumber -TRIO_ARGS6((self, number, flags, width, precision, base), - trio_class_t *self, - trio_uintmax_t number, - trio_flags_t flags, - int width, - int precision, - int base) -{ - BOOLEAN_T isNegative; - BOOLEAN_T isNumberZero; - BOOLEAN_T isPrecisionZero; - BOOLEAN_T ignoreNumber; - char buffer[MAX_CHARS_IN(trio_uintmax_t) * (1 + MAX_LOCALE_SEPARATOR_LENGTH) + 1]; - char *bufferend; - char *pointer; - TRIO_CONST char *digits; - int i; -#if TRIO_FEATURE_QUOTE - int length; - char *p; -#endif - int count; - int digitOffset; - - assert(VALID(self)); - assert(VALID(self->OutStream)); - assert(((base >= MIN_BASE) && (base <= MAX_BASE)) || (base == NO_BASE)); - - digits = (flags & FLAGS_UPPER) ? internalDigitsUpper : internalDigitsLower; - if (base == NO_BASE) - base = BASE_DECIMAL; - - isNumberZero = (number == 0); - isPrecisionZero = (precision == 0); - ignoreNumber = (isNumberZero - && isPrecisionZero - && !((flags & FLAGS_ALTERNATIVE) && (base == BASE_OCTAL))); - - if (flags & FLAGS_UNSIGNED) - { - isNegative = FALSE; - flags &= ~FLAGS_SHOWSIGN; - } - else - { - isNegative = ((trio_intmax_t)number < 0); - if (isNegative) - number = -((trio_intmax_t)number); - } - - if (flags & FLAGS_QUAD) - number &= (trio_ulonglong_t)-1; - else if (flags & FLAGS_LONG) - number &= (unsigned long)-1; - else - number &= (unsigned int)-1; - - /* Build number */ - pointer = bufferend = &buffer[sizeof(buffer) - 1]; - *pointer-- = NIL; - for (i = 1; i < (int)sizeof(buffer); i++) - { - digitOffset = number % base; - *pointer-- = digits[digitOffset]; - number /= base; - if (number == 0) - break; - -#if TRIO_FEATURE_QUOTE - if ((flags & FLAGS_QUOTE) && TrioFollowedBySeparator(i + 1)) - { - /* - * We are building the number from the least significant - * to the most significant digit, so we have to copy the - * thousand separator backwards - */ - length = internalThousandSeparatorLength; - if (((int)(pointer - buffer) - length) > 0) - { - p = &internalThousandSeparator[length - 1]; - while (length-- > 0) - *pointer-- = *p--; - } - } -#endif - } - - if (! ignoreNumber) - { - /* Adjust width */ - width -= (bufferend - pointer) - 1; - } - - /* Adjust precision */ - if (NO_PRECISION != precision) - { - precision -= (bufferend - pointer) - 1; - if (precision < 0) - precision = 0; - flags |= FLAGS_NILPADDING; - } - - /* Calculate padding */ - count = (! ((flags & FLAGS_LEFTADJUST) || (precision == NO_PRECISION))) - ? precision - : 0; - - /* Adjust width further */ - if (isNegative || (flags & FLAGS_SHOWSIGN) || (flags & FLAGS_SPACE)) - width--; - if ((flags & FLAGS_ALTERNATIVE) && !isNumberZero) - { - switch (base) - { - case BASE_BINARY: - case BASE_HEX: - width -= 2; - break; - case BASE_OCTAL: - if (!(flags & FLAGS_NILPADDING) || (count == 0)) - width--; - break; - default: - break; - } - } - - /* Output prefixes spaces if needed */ - if (! ((flags & FLAGS_LEFTADJUST) || - ((flags & FLAGS_NILPADDING) && (precision == NO_PRECISION)))) - { - while (width-- > count) - self->OutStream(self, CHAR_ADJUST); - } - - /* width has been adjusted for signs and alternatives */ - if (isNegative) - self->OutStream(self, '-'); - else if (flags & FLAGS_SHOWSIGN) - self->OutStream(self, '+'); - else if (flags & FLAGS_SPACE) - self->OutStream(self, ' '); - - /* Prefix is not written when the value is zero */ - if ((flags & FLAGS_ALTERNATIVE) && !isNumberZero) - { - switch (base) - { - case BASE_BINARY: - self->OutStream(self, '0'); - self->OutStream(self, (flags & FLAGS_UPPER) ? 'B' : 'b'); - break; - - case BASE_OCTAL: - if (!(flags & FLAGS_NILPADDING) || (count == 0)) - self->OutStream(self, '0'); - break; - - case BASE_HEX: - self->OutStream(self, '0'); - self->OutStream(self, (flags & FLAGS_UPPER) ? 'X' : 'x'); - break; - - default: - break; - } /* switch base */ - } - - /* Output prefixed zero padding if needed */ - if (flags & FLAGS_NILPADDING) - { - if (precision == NO_PRECISION) - precision = width; - while (precision-- > 0) - { - self->OutStream(self, '0'); - width--; - } - } - - if (! ignoreNumber) - { - /* Output the number itself */ - while (*(++pointer)) - { - self->OutStream(self, *pointer); - } - } - - /* Output trailing spaces if needed */ - if (flags & FLAGS_LEFTADJUST) - { - while (width-- > 0) - self->OutStream(self, CHAR_ADJUST); - } -} - -/************************************************************************* - * TrioWriteStringCharacter - * - * Description: - * Output a single character of a string - */ -TRIO_PRIVATE void -TrioWriteStringCharacter -TRIO_ARGS3((self, ch, flags), - trio_class_t *self, - int ch, - trio_flags_t flags) -{ - if (flags & FLAGS_ALTERNATIVE) - { - if (! isprint(ch)) - { - /* - * Non-printable characters are converted to C escapes or - * \number, if no C escape exists. - */ - self->OutStream(self, CHAR_BACKSLASH); - switch (ch) - { - case '\007': self->OutStream(self, 'a'); break; - case '\b': self->OutStream(self, 'b'); break; - case '\f': self->OutStream(self, 'f'); break; - case '\n': self->OutStream(self, 'n'); break; - case '\r': self->OutStream(self, 'r'); break; - case '\t': self->OutStream(self, 't'); break; - case '\v': self->OutStream(self, 'v'); break; - case '\\': self->OutStream(self, '\\'); break; - default: - self->OutStream(self, 'x'); - TrioWriteNumber(self, (trio_uintmax_t)ch, - FLAGS_UNSIGNED | FLAGS_NILPADDING, - 2, 2, BASE_HEX); - break; - } - } - else if (ch == CHAR_BACKSLASH) - { - self->OutStream(self, CHAR_BACKSLASH); - self->OutStream(self, CHAR_BACKSLASH); - } - else - { - self->OutStream(self, ch); - } - } - else - { - self->OutStream(self, ch); - } -} - -/************************************************************************* - * TrioWriteString - * - * Description: - * Output a string - */ -TRIO_PRIVATE void -TrioWriteString -TRIO_ARGS5((self, string, flags, width, precision), - trio_class_t *self, - TRIO_CONST char *string, - trio_flags_t flags, - int width, - int precision) -{ - int length; - int ch; - - assert(VALID(self)); - assert(VALID(self->OutStream)); - - if (string == NULL) - { - string = internalNullString; - length = sizeof(internalNullString) - 1; -#if TRIO_FEATURE_QUOTE - /* Disable quoting for the null pointer */ - flags &= (~FLAGS_QUOTE); -#endif - width = 0; - } - else - { - if (precision == 0) - { - length = trio_length(string); - } - else - { - length = trio_length_max(string, precision); - } - } - if ((NO_PRECISION != precision) && - (precision < length)) - { - length = precision; - } - width -= length; - -#if TRIO_FEATURE_QUOTE - if (flags & FLAGS_QUOTE) - self->OutStream(self, CHAR_QUOTE); -#endif - - if (! (flags & FLAGS_LEFTADJUST)) - { - while (width-- > 0) - self->OutStream(self, CHAR_ADJUST); - } - - while (length-- > 0) - { - /* The ctype parameters must be an unsigned char (or EOF) */ - ch = (int)((unsigned char)(*string++)); - TrioWriteStringCharacter(self, ch, flags); - } - - if (flags & FLAGS_LEFTADJUST) - { - while (width-- > 0) - self->OutStream(self, CHAR_ADJUST); - } -#if TRIO_FEATURE_QUOTE - if (flags & FLAGS_QUOTE) - self->OutStream(self, CHAR_QUOTE); -#endif -} - -/************************************************************************* - * TrioWriteWideStringCharacter - * - * Description: - * Output a wide string as a multi-byte sequence - */ -#if TRIO_FEATURE_WIDECHAR -TRIO_PRIVATE int -TrioWriteWideStringCharacter -TRIO_ARGS4((self, wch, flags, width), - trio_class_t *self, - trio_wchar_t wch, - trio_flags_t flags, - int width) -{ - int size; - int i; - int ch; - char *string; - char buffer[MB_LEN_MAX + 1]; - - if (width == NO_WIDTH) - width = sizeof(buffer); - - size = wctomb(buffer, wch); - if ((size <= 0) || (size > width) || (buffer[0] == NIL)) - return 0; - - string = buffer; - i = size; - while ((width >= i) && (width-- > 0) && (i-- > 0)) - { - /* The ctype parameters must be an unsigned char (or EOF) */ - ch = (int)((unsigned char)(*string++)); - TrioWriteStringCharacter(self, ch, flags); - } - return size; -} -#endif /* TRIO_FEATURE_WIDECHAR */ - -/************************************************************************* - * TrioWriteWideString - * - * Description: - * Output a wide character string as a multi-byte string - */ -#if TRIO_FEATURE_WIDECHAR -TRIO_PRIVATE void -TrioWriteWideString -TRIO_ARGS5((self, wstring, flags, width, precision), - trio_class_t *self, - TRIO_CONST trio_wchar_t *wstring, - trio_flags_t flags, - int width, - int precision) -{ - int length; - int size; - - assert(VALID(self)); - assert(VALID(self->OutStream)); - -#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE) - /* Required by TrioWriteWideStringCharacter */ - (void)mblen(NULL, 0); -#endif - - if (wstring == NULL) - { - TrioWriteString(self, NULL, flags, width, precision); - return; - } - - if (NO_PRECISION == precision) - { - length = INT_MAX; - } - else - { - length = precision; - width -= length; - } - -#if TRIO_FEATURE_QUOTE - if (flags & FLAGS_QUOTE) - self->OutStream(self, CHAR_QUOTE); -#endif - - if (! (flags & FLAGS_LEFTADJUST)) - { - while (width-- > 0) - self->OutStream(self, CHAR_ADJUST); - } - - while (length > 0) - { - size = TrioWriteWideStringCharacter(self, *wstring++, flags, length); - if (size == 0) - break; /* while */ - length -= size; - } - - if (flags & FLAGS_LEFTADJUST) - { - while (width-- > 0) - self->OutStream(self, CHAR_ADJUST); - } -#if TRIO_FEATURE_QUOTE - if (flags & FLAGS_QUOTE) - self->OutStream(self, CHAR_QUOTE); -#endif -} -#endif /* TRIO_FEATURE_WIDECHAR */ - -/************************************************************************* - * TrioWriteDouble - * - * http://wwwold.dkuug.dk/JTC1/SC22/WG14/www/docs/dr_211.htm - * - * "5.2.4.2.2 paragraph #4 - * - * The accuracy [...] is implementation defined, as is the accuracy - * of the conversion between floating-point internal representations - * and string representations performed by the libray routine in - * " - */ -/* FIXME: handle all instances of constant long-double number (L) - * and *l() math functions. - */ -#if TRIO_FEATURE_FLOAT -TRIO_PRIVATE void -TrioWriteDouble -TRIO_ARGS6((self, number, flags, width, precision, base), - trio_class_t *self, - trio_long_double_t number, - trio_flags_t flags, - int width, - int precision, - int base) -{ - trio_long_double_t integerNumber; - trio_long_double_t fractionNumber; - trio_long_double_t workNumber; - int integerDigits; - int fractionDigits; - int exponentDigits; - int workDigits; - int baseDigits; - int integerThreshold; - int fractionThreshold; - int expectedWidth; - int exponent = 0; - unsigned int uExponent = 0; - int exponentBase; - trio_long_double_t dblBase; - trio_long_double_t dblFractionBase; - trio_long_double_t integerAdjust; - trio_long_double_t fractionAdjust; - trio_long_double_t workFractionNumber; - trio_long_double_t workFractionAdjust; - int fractionDigitsInspect; - BOOLEAN_T isNegative; - BOOLEAN_T isExponentNegative = FALSE; - BOOLEAN_T requireTwoDigitExponent; - BOOLEAN_T isHex; - TRIO_CONST char *digits; -# if TRIO_FEATURE_QUOTE - char *groupingPointer; -# endif - int i; - int offset; - BOOLEAN_T hasOnlyZeroes; - int leadingFractionZeroes = -1; - register int trailingZeroes; - BOOLEAN_T keepTrailingZeroes; - BOOLEAN_T keepDecimalPoint; - trio_long_double_t epsilon; - trio_long_double_t epsilonCorrection; - BOOLEAN_T adjustNumber = FALSE; - - assert(VALID(self)); - assert(VALID(self->OutStream)); - assert(((base >= MIN_BASE) && (base <= MAX_BASE)) || (base == NO_BASE)); - - /* Determine sign and look for special quantities */ - switch (trio_fpclassify_and_signbit(number, &isNegative)) - { - case TRIO_FP_NAN: - TrioWriteString(self, - (flags & FLAGS_UPPER) - ? NAN_UPPER - : NAN_LOWER, - flags, width, precision); - return; - - case TRIO_FP_INFINITE: - if (isNegative) - { - /* Negative infinity */ - TrioWriteString(self, - (flags & FLAGS_UPPER) - ? "-" INFINITE_UPPER - : "-" INFINITE_LOWER, - flags, width, precision); - return; - } - else - { - /* Positive infinity */ - TrioWriteString(self, - (flags & FLAGS_UPPER) - ? INFINITE_UPPER - : INFINITE_LOWER, - flags, width, precision); - return; - } - - default: - /* Finitude */ - break; - } - - /* Normal numbers */ - if (flags & FLAGS_LONGDOUBLE) - { - baseDigits = (base == 10) - ? LDBL_DIG - : (int)trio_floor(LDBL_MANT_DIG / TrioLogarithmBase(base)); - epsilon = LDBL_EPSILON; - } - else if (flags & FLAGS_SHORT) - { - baseDigits = (base == BASE_DECIMAL) - ? FLT_DIG - : (int)trio_floor(FLT_MANT_DIG / TrioLogarithmBase(base)); - epsilon = FLT_EPSILON; - } - else - { - baseDigits = (base == BASE_DECIMAL) - ? DBL_DIG - : (int)trio_floor(DBL_MANT_DIG / TrioLogarithmBase(base)); - epsilon = DBL_EPSILON; - } - - digits = (flags & FLAGS_UPPER) ? internalDigitsUpper : internalDigitsLower; - isHex = (base == BASE_HEX); - if (base == NO_BASE) - base = BASE_DECIMAL; - dblBase = (trio_long_double_t)base; - /* - * Some log10() functions can "err by almost 3 ulps" according to - * http://www.cs.berkeley.edu/~wkahan/LOG10HAF.TXT - */ - epsilonCorrection = 3 * epsilon; - keepTrailingZeroes = !( (flags & FLAGS_ROUNDING) || - ( (flags & FLAGS_FLOAT_G) && - !(flags & FLAGS_ALTERNATIVE) ) ); - -# if TRIO_FEATURE_ROUNDING - if (flags & FLAGS_ROUNDING) - { - precision = baseDigits; - } -# endif - - if (precision == NO_PRECISION) - { - if (isHex) - { - keepTrailingZeroes = FALSE; - precision = FLT_MANT_DIG; - } - else - { - precision = FLT_DIG; - } - } - - if (isNegative) - { - number = -number; - } - - if (isHex) - { - flags |= FLAGS_FLOAT_E; - } - - reprocess: - - if (flags & FLAGS_FLOAT_G) - { - if (precision == 0) - precision = 1; - - if ( (number < TRIO_SUFFIX_LONG(1.0E-4)) || - (number >= TrioPower(base, (trio_long_double_t)precision)) ) - { - /* Use scientific notation */ - flags |= FLAGS_FLOAT_E; - } - else if (number < 1.0) - { - /* - * Use normal notation. If the integer part of the number is - * zero, then adjust the precision to include leading fractional - * zeros. - */ - workNumber = TrioLogarithm(number, base); - workNumber = TRIO_FABS(workNumber); - if (workNumber - trio_floor(workNumber) < epsilon) - workNumber--; - leadingFractionZeroes = (int)trio_floor(workNumber); - } - } - - if (flags & FLAGS_FLOAT_E) - { - /* Scale the number */ - workNumber = TrioLogarithm(number, base); - if (trio_isinf(workNumber) == -1) - { - exponent = 0; - /* Undo setting */ - if (flags & FLAGS_FLOAT_G) - flags &= ~FLAGS_FLOAT_E; - } - else - { - exponent = (int)trio_floor(workNumber + epsilonCorrection); - workNumber = number; - /* - * We want to apply A / 10^B but the equivalent A * 10^-B gives better - * accuracy on platforms with true long double support. - */ -#if defined(TRIO_DOUBLE_DOUBLE) - workNumber /= TrioPower(dblBase, (trio_long_double_t)exponent); -#else - workNumber *= TrioPower(dblBase, (trio_long_double_t)-exponent); -#endif - if (trio_isinf(workNumber)) { - /* - * Scaling is done it two steps to avoid problems with subnormal - * numbers. - */ - workNumber /= TrioPower(dblBase, (trio_long_double_t)(exponent / 2)); - workNumber /= TrioPower(dblBase, (trio_long_double_t)(exponent - (exponent / 2))); - } - number = workNumber; - isExponentNegative = (exponent < 0); - uExponent = (isExponentNegative) ? -exponent : exponent; - if (isHex) - uExponent *= 4; /* log16(2) */ -#if TRIO_FEATURE_QUOTE - /* No thousand separators */ - flags &= ~FLAGS_QUOTE; -#endif - } - } - - integerNumber = trio_floor(number); - fractionNumber = number - integerNumber; - - /* - * Truncated number. - * - * Precision is number of significant digits for FLOAT_G and number of - * fractional digits for others. - */ - integerDigits = 1; - if (integerNumber > epsilon) - { - integerDigits += (int)(TrioLogarithm(integerNumber, base) + epsilonCorrection); - } - - fractionDigits = precision; - if (flags & FLAGS_FLOAT_G) - { - if (leadingFractionZeroes > 0) - { - fractionDigits += leadingFractionZeroes; - } - if ((integerNumber > epsilon) || (number <= epsilon)) - { - fractionDigits -= integerDigits; - } - } - - dblFractionBase = TrioPower(base, fractionDigits); - - if (integerNumber < 1.0) - { - workNumber = number * dblFractionBase + TRIO_SUFFIX_LONG(0.5); - if (trio_floor(number * dblFractionBase) != trio_floor(workNumber)) - { - adjustNumber = TRUE; - /* Remove a leading fraction zero if fraction is rounded up */ - if ((int)(TrioLogarithm(number * dblFractionBase, base) + epsilonCorrection) != - (int)(TrioLogarithm(workNumber, base) + epsilonCorrection)) - { - --leadingFractionZeroes; - } - } - workNumber /= dblFractionBase; - } - else - { - workNumber = number + TRIO_SUFFIX_LONG(0.5) / dblFractionBase; - adjustNumber = (trio_floor(number) != trio_floor(workNumber)); - } - if (adjustNumber) - { - if ((flags & FLAGS_FLOAT_G) && !(flags & FLAGS_FLOAT_E)) - { - /* The adjustment may require a change to scientific notation */ - if ( (workNumber < TRIO_SUFFIX_LONG(1.0E-4)) || - (workNumber >= TrioPower(base, (trio_long_double_t)precision)) ) - { - /* Use scientific notation */ - flags |= FLAGS_FLOAT_E; - goto reprocess; - } - } - - if (flags & FLAGS_FLOAT_E) - { - workDigits = 1 + (TrioLogarithm(trio_floor(workNumber), base) + epsilonCorrection); - if (integerDigits == workDigits) - { - /* Adjust if the same number of digits are used */ - number += TRIO_SUFFIX_LONG(0.5) / dblFractionBase; - integerNumber = trio_floor(number); - fractionNumber = number - integerNumber; - } - else - { - /* Adjust if number was rounded up one digit (ie. 0.99 to 1.00) */ - exponent++; - isExponentNegative = (exponent < 0); - uExponent = (isExponentNegative) ? -exponent : exponent; - if (isHex) - uExponent *= 4; /* log16(2) */ - workNumber = (number + TRIO_SUFFIX_LONG(0.5) / dblFractionBase) / dblBase; - integerNumber = trio_floor(workNumber); - fractionNumber = workNumber - integerNumber; - } - } - else - { - if (workNumber > 1.0) - { - /* Adjust if number was rounded up one digit (ie. 99 to 100) */ - integerNumber = trio_floor(workNumber); - fractionNumber = 0.0; - integerDigits = (integerNumber > epsilon) - ? 1 + (int)(TrioLogarithm(integerNumber, base) + epsilonCorrection) - : 1; - if (flags & FLAGS_FLOAT_G) - { - if (flags & FLAGS_ALTERNATIVE) - { - fractionDigits = precision; - if ((integerNumber > epsilon) || (number <= epsilon)) - { - fractionDigits -= integerDigits; - } - } - else - { - fractionDigits = 0; - } - } - } - else - { - integerNumber = trio_floor(workNumber); - fractionNumber = workNumber - integerNumber; - if (flags & FLAGS_FLOAT_G) - { - if (flags & FLAGS_ALTERNATIVE) - { - fractionDigits = precision; - if (leadingFractionZeroes > 0) - { - fractionDigits += leadingFractionZeroes; - } - if ((integerNumber > epsilon) || (number <= epsilon)) - { - fractionDigits -= integerDigits; - } - } - } - } - } - } - - /* Estimate accuracy */ - integerAdjust = fractionAdjust = TRIO_SUFFIX_LONG(0.5); -# if TRIO_FEATURE_ROUNDING - if (flags & FLAGS_ROUNDING) - { - if (integerDigits > baseDigits) - { - integerThreshold = baseDigits; - fractionDigits = 0; - dblFractionBase = 1.0; - fractionThreshold = 0; - precision = 0; /* Disable decimal-point */ - integerAdjust = TrioPower(base, integerDigits - integerThreshold - 1); - fractionAdjust = 0.0; - } - else - { - integerThreshold = integerDigits; - fractionThreshold = fractionDigits - integerThreshold; - fractionAdjust = 1.0; - } - } - else -# endif - { - integerThreshold = INT_MAX; - fractionThreshold = INT_MAX; - } - - /* - * Calculate expected width. - * sign + integer part + thousands separators + decimal point - * + fraction + exponent - */ - fractionAdjust /= dblFractionBase; - hasOnlyZeroes = (trio_floor((fractionNumber + fractionAdjust) * - dblFractionBase) < epsilon); - keepDecimalPoint = ( (flags & FLAGS_ALTERNATIVE) || - !((precision == 0) || - (!keepTrailingZeroes && hasOnlyZeroes)) ); - - expectedWidth = integerDigits + fractionDigits; - - if (!keepTrailingZeroes) - { - trailingZeroes = 0; - workFractionNumber = fractionNumber; - workFractionAdjust = fractionAdjust; - fractionDigitsInspect = fractionDigits; - - if (integerDigits > integerThreshold) - { - fractionDigitsInspect = 0; - } - else if (fractionThreshold <= fractionDigits) - { - fractionDigitsInspect = fractionThreshold + 1; - } - - trailingZeroes = fractionDigits - fractionDigitsInspect; - for (i = 0; i < fractionDigitsInspect; i++) - { - workFractionNumber *= dblBase; - workFractionAdjust *= dblBase; - workNumber = trio_floor(workFractionNumber + workFractionAdjust); - workFractionNumber -= workNumber; - offset = (int)trio_fmod(workNumber, dblBase); - if (offset == 0) - { - trailingZeroes++; - } - else - { - trailingZeroes = 0; - } - } - expectedWidth -= trailingZeroes; - } - - if (keepDecimalPoint) - { - expectedWidth += internalDecimalPointLength; - } - -#if TRIO_FEATURE_QUOTE - if (flags & FLAGS_QUOTE) - { - expectedWidth += TrioCalcThousandSeparatorLength(integerDigits); - } -#endif - - if (isNegative || (flags & FLAGS_SHOWSIGN) || (flags & FLAGS_SPACE)) - { - expectedWidth += sizeof("-") - 1; - } - - exponentDigits = 0; - if (flags & FLAGS_FLOAT_E) - { - exponentDigits = (uExponent == 0) - ? 1 - : (int)trio_ceil(TrioLogarithm((double)(uExponent + 1), - (isHex) ? 10 : base)); - } - requireTwoDigitExponent = ((base == BASE_DECIMAL) && (exponentDigits == 1)); - if (exponentDigits > 0) - { - expectedWidth += exponentDigits; - expectedWidth += (requireTwoDigitExponent - ? sizeof("E+0") - 1 - : sizeof("E+") - 1); - } - - if (isHex) - { - expectedWidth += sizeof("0X") - 1; - } - - /* Output prefixing */ - if (flags & FLAGS_NILPADDING) - { - /* Leading zeros must be after sign */ - if (isNegative) - self->OutStream(self, '-'); - else if (flags & FLAGS_SHOWSIGN) - self->OutStream(self, '+'); - else if (flags & FLAGS_SPACE) - self->OutStream(self, ' '); - if (isHex) - { - self->OutStream(self, '0'); - self->OutStream(self, (flags & FLAGS_UPPER) ? 'X' : 'x'); - } - if (!(flags & FLAGS_LEFTADJUST)) - { - for (i = expectedWidth; i < width; i++) - { - self->OutStream(self, '0'); - } - } - } - else - { - /* Leading spaces must be before sign */ - if (!(flags & FLAGS_LEFTADJUST)) - { - for (i = expectedWidth; i < width; i++) - { - self->OutStream(self, CHAR_ADJUST); - } - } - if (isNegative) - self->OutStream(self, '-'); - else if (flags & FLAGS_SHOWSIGN) - self->OutStream(self, '+'); - else if (flags & FLAGS_SPACE) - self->OutStream(self, ' '); - if (isHex) - { - self->OutStream(self, '0'); - self->OutStream(self, (flags & FLAGS_UPPER) ? 'X' : 'x'); - } - } - - /* Output the integer part and thousand separators */ - for (i = 0; i < integerDigits; i++) - { - workNumber = trio_floor(((integerNumber + integerAdjust) - / TrioPower(base, integerDigits - i - 1))); - if (i > integerThreshold) - { - /* Beyond accuracy */ - self->OutStream(self, digits[0]); - } - else - { - self->OutStream(self, digits[(int)trio_fmod(workNumber, dblBase)]); - } - -#if TRIO_FEATURE_QUOTE - if (((flags & (FLAGS_FLOAT_E | FLAGS_QUOTE)) == FLAGS_QUOTE) - && TrioFollowedBySeparator(integerDigits - i)) - { - for (groupingPointer = internalThousandSeparator; - *groupingPointer != NIL; - groupingPointer++) - { - self->OutStream(self, *groupingPointer); - } - } -#endif - } - - /* Insert decimal point and build the fraction part */ - trailingZeroes = 0; - - if (keepDecimalPoint) - { - if (internalDecimalPoint) - { - self->OutStream(self, internalDecimalPoint); - } - else - { - for (i = 0; i < internalDecimalPointLength; i++) - { - self->OutStream(self, internalDecimalPointString[i]); - } - } - } - - for (i = 0; i < fractionDigits; i++) - { - if ((integerDigits > integerThreshold) || (i > fractionThreshold)) - { - /* Beyond accuracy */ - trailingZeroes++; - } - else - { - fractionNumber *= dblBase; - fractionAdjust *= dblBase; - workNumber = trio_floor(fractionNumber + fractionAdjust); - if (workNumber > fractionNumber) - { - /* fractionNumber should never become negative */ - fractionNumber = 0.0; - fractionAdjust = 0.0; - } - else - { - fractionNumber -= workNumber; - } - offset = (int)trio_fmod(workNumber, dblBase); - if (offset == 0) - { - trailingZeroes++; - } - else - { - while (trailingZeroes > 0) - { - /* Not trailing zeroes after all */ - self->OutStream(self, digits[0]); - trailingZeroes--; - } - self->OutStream(self, digits[offset]); - } - } - } - - if (keepTrailingZeroes) - { - while (trailingZeroes > 0) - { - self->OutStream(self, digits[0]); - trailingZeroes--; - } - } - - /* Output exponent */ - if (exponentDigits > 0) - { - self->OutStream(self, - isHex - ? ((flags & FLAGS_UPPER) ? 'P' : 'p') - : ((flags & FLAGS_UPPER) ? 'E' : 'e')); - self->OutStream(self, (isExponentNegative) ? '-' : '+'); - - /* The exponent must contain at least two digits */ - if (requireTwoDigitExponent) - self->OutStream(self, '0'); - - if (isHex) - base = 10; - exponentBase = (int)TrioPower(base, exponentDigits - 1); - for (i = 0; i < exponentDigits; i++) - { - self->OutStream(self, digits[(uExponent / exponentBase) % base]); - exponentBase /= base; - } - } - /* Output trailing spaces */ - if (flags & FLAGS_LEFTADJUST) - { - for (i = expectedWidth; i < width; i++) - { - self->OutStream(self, CHAR_ADJUST); - } - } -} -#endif /* TRIO_FEATURE_FLOAT */ - -/************************************************************************* - * TrioFormatProcess - * - * Description: - * This is the main engine for formatting output - */ -TRIO_PRIVATE int -TrioFormatProcess -TRIO_ARGS3((data, format, parameters), - trio_class_t *data, - TRIO_CONST char *format, - trio_parameter_t *parameters) -{ - int i; -#if TRIO_FEATURE_ERRNO - TRIO_CONST char *string; -#endif - trio_pointer_t pointer; - trio_flags_t flags; - int width; - int precision; - int base; - int offset; - - offset = 0; - i = 0; - - for (;;) - { - /* Skip the parameter entries */ - while (parameters[i].type == FORMAT_PARAMETER) - i++; - - /* Copy non conversion-specifier part of format string */ - while (offset < parameters[i].beginOffset) - { - if (CHAR_IDENTIFIER == format[offset] && CHAR_IDENTIFIER == format[offset + 1]) - { - data->OutStream(data, CHAR_IDENTIFIER); - offset += 2; - } - else - { - data->OutStream(data, format[offset++]); - } - } - - /* Abort if we reached end of format string */ - if (parameters[i].type == FORMAT_SENTINEL) - break; - - /* Ouput parameter */ - flags = parameters[i].flags; - - /* Find width */ - width = parameters[i].width; - if (flags & FLAGS_WIDTH_PARAMETER) - { - /* Get width from parameter list */ - width = (int)parameters[width].data.number.as_signed; - if (width < 0) - { - /* - * A negative width is the same as the - flag and - * a positive width. - */ - flags |= FLAGS_LEFTADJUST; - flags &= ~FLAGS_NILPADDING; - width = -width; - } - } - - /* Find precision */ - if (flags & FLAGS_PRECISION) - { - precision = parameters[i].precision; - if (flags & FLAGS_PRECISION_PARAMETER) - { - /* Get precision from parameter list */ - precision = (int)parameters[precision].data.number.as_signed; - if (precision < 0) - { - /* - * A negative precision is the same as no - * precision - */ - precision = NO_PRECISION; - } - } - } - else - { - precision = NO_PRECISION; - } - - /* Find base */ - if (NO_BASE != parameters[i].baseSpecifier) - { - /* Base from specifier has priority */ - base = parameters[i].baseSpecifier; - } - else if (flags & FLAGS_BASE_PARAMETER) - { - /* Get base from parameter list */ - base = parameters[i].base; - base = (int)parameters[base].data.number.as_signed; - } - else - { - /* Use base from format string */ - base = parameters[i].base; - } - - switch (parameters[i].type) - { - case FORMAT_CHAR: -#if TRIO_FEATURE_QUOTE - if (flags & FLAGS_QUOTE) - data->OutStream(data, CHAR_QUOTE); -#endif - if (! (flags & FLAGS_LEFTADJUST)) - { - while (--width > 0) - data->OutStream(data, CHAR_ADJUST); - } -#if TRIO_FEATURE_WIDECHAR - if (flags & FLAGS_WIDECHAR) - { - TrioWriteWideStringCharacter(data, - (trio_wchar_t)parameters[i].data.number.as_signed, - flags, - NO_WIDTH); - } - else -#endif - { - TrioWriteStringCharacter(data, - (int)parameters[i].data.number.as_signed, - flags); - } - - if (flags & FLAGS_LEFTADJUST) - { - while(--width > 0) - data->OutStream(data, CHAR_ADJUST); - } -#if TRIO_FEATURE_QUOTE - if (flags & FLAGS_QUOTE) - data->OutStream(data, CHAR_QUOTE); -#endif - - break; /* FORMAT_CHAR */ - - case FORMAT_INT: - TrioWriteNumber(data, - parameters[i].data.number.as_unsigned, - flags, - width, - precision, - base); - - break; /* FORMAT_INT */ - -#if TRIO_FEATURE_FLOAT - case FORMAT_DOUBLE: - TrioWriteDouble(data, - parameters[i].data.longdoubleNumber, - flags, - width, - precision, - base); - break; /* FORMAT_DOUBLE */ -#endif - - case FORMAT_STRING: -#if TRIO_FEATURE_WIDECHAR - if (flags & FLAGS_WIDECHAR) - { - TrioWriteWideString(data, - parameters[i].data.wstring, - flags, - width, - precision); - } - else -#endif - { - TrioWriteString(data, - parameters[i].data.string, - flags, - width, - precision); - } - break; /* FORMAT_STRING */ - - case FORMAT_POINTER: - { - trio_reference_t reference; - - reference.data = data; - reference.parameter = ¶meters[i]; - trio_print_pointer(&reference, parameters[i].data.pointer); - } - break; /* FORMAT_POINTER */ - - case FORMAT_COUNT: - pointer = parameters[i].data.pointer; - if (NULL != pointer) - { - /* - * C99 paragraph 7.19.6.1.8 says "the number of - * characters written to the output stream so far by - * this call", which is data->actually.committed - */ -#if TRIO_FEATURE_SIZE_T || TRIO_FEATURE_SIZE_T_UPPER - if (flags & FLAGS_SIZE_T) - *(size_t *)pointer = (size_t)data->actually.committed; - else -#endif -#if TRIO_FEATURE_PTRDIFF_T - if (flags & FLAGS_PTRDIFF_T) - *(ptrdiff_t *)pointer = (ptrdiff_t)data->actually.committed; - else -#endif -#if TRIO_FEATURE_INTMAX_T - if (flags & FLAGS_INTMAX_T) - *(trio_intmax_t *)pointer = (trio_intmax_t)data->actually.committed; - else -#endif - if (flags & FLAGS_QUAD) - { - *(trio_ulonglong_t *)pointer = (trio_ulonglong_t)data->actually.committed; - } - else if (flags & FLAGS_LONG) - { - *(long int *)pointer = (long int)data->actually.committed; - } - else if (flags & FLAGS_SHORT) - { - *(short int *)pointer = (short int)data->actually.committed; - } - else - { - *(int *)pointer = (int)data->actually.committed; - } - } - break; /* FORMAT_COUNT */ - - case FORMAT_PARAMETER: - break; /* FORMAT_PARAMETER */ - -#if TRIO_FEATURE_ERRNO - case FORMAT_ERRNO: - string = trio_error(parameters[i].data.errorNumber); - if (string) - { - TrioWriteString(data, - string, - flags, - width, - precision); - } - else - { - data->OutStream(data, '#'); - TrioWriteNumber(data, - (trio_uintmax_t)parameters[i].data.errorNumber, - flags, - width, - precision, - BASE_DECIMAL); - } - break; /* FORMAT_ERRNO */ -#endif /* TRIO_FEATURE_ERRNO */ - -#if TRIO_FEATURE_USER_DEFINED - case FORMAT_USER_DEFINED: - { - trio_reference_t reference; - trio_userdef_t *def = NULL; - - if (parameters[i].flags & FLAGS_USER_DEFINED_PARAMETER) - { - /* Use handle */ - if ((i > 0) || - (parameters[i - 1].type == FORMAT_PARAMETER)) - def = (trio_userdef_t *)parameters[i - 1].data.pointer; - } - else - { - /* Look up namespace */ - def = TrioFindNamespace(parameters[i].user_defined.namespace, NULL); - } - if (def) - { - reference.data = data; - reference.parameter = ¶meters[i]; - def->callback(&reference); - } - } - break; -#endif /* TRIO_FEATURE_USER_DEFINED */ - - default: - break; - } /* switch parameter type */ - - /* Prepare for next */ - offset = parameters[i].endOffset; - i++; - } - - return data->processed; -} - -/************************************************************************* - * TrioFormatRef - */ -#if TRIO_EXTENSION -TRIO_PRIVATE int -TrioFormatRef -TRIO_ARGS5((reference, format, arglist, argfunc, argarray), - trio_reference_t *reference, - TRIO_CONST char *format, - va_list arglist, - trio_argfunc_t argfunc, - trio_pointer_t *argarray) -{ - int status; - trio_parameter_t parameters[MAX_PARAMETERS]; - - status = TrioParse(TYPE_PRINT, format, parameters, arglist, argfunc, argarray); - if (status < 0) - return status; - - status = TrioFormatProcess(reference->data, format, parameters); - if (reference->data->error != 0) - { - status = reference->data->error; - } - return status; -} -#endif /* TRIO_EXTENSION */ - -/************************************************************************* - * TrioFormat - */ -TRIO_PRIVATE int -TrioFormat -TRIO_ARGS7((destination, destinationSize, OutStream, format, arglist, argfunc, argarray), - trio_pointer_t destination, - size_t destinationSize, - void (*OutStream) TRIO_PROTO((trio_class_t *, int)), - TRIO_CONST char *format, - va_list arglist, - trio_argfunc_t argfunc, - trio_pointer_t *argarray) -{ - int status; - trio_class_t data; - trio_parameter_t parameters[MAX_PARAMETERS]; - - assert(VALID(OutStream)); - assert(VALID(format)); - - memset(&data, 0, sizeof(data)); - data.OutStream = OutStream; - data.location = destination; - data.max = destinationSize; - data.error = 0; - -#if defined(USE_LOCALE) - if (NULL == internalLocaleValues) - { - TrioSetLocale(); - } -#endif - - status = TrioParse(TYPE_PRINT, format, parameters, arglist, argfunc, argarray); - if (status < 0) - return status; - - status = TrioFormatProcess(&data, format, parameters); - if (data.error != 0) - { - status = data.error; - } - return status; -} - -/************************************************************************* - * TrioOutStreamFile - */ -#if TRIO_FEATURE_FILE || TRIO_FEATURE_STDIO -TRIO_PRIVATE void -TrioOutStreamFile -TRIO_ARGS2((self, output), - trio_class_t *self, - int output) -{ - FILE *file; - - assert(VALID(self)); - assert(VALID(self->location)); - - file = (FILE *)self->location; - self->processed++; - if (fputc(output, file) == EOF) - { - self->error = TRIO_ERROR_RETURN(TRIO_EOF, 0); - } - else - { - self->actually.committed++; - } -} -#endif /* TRIO_FEATURE_FILE || TRIO_FEATURE_STDIO */ - -/************************************************************************* - * TrioOutStreamFileDescriptor - */ -#if TRIO_FEATURE_FD -TRIO_PRIVATE void -TrioOutStreamFileDescriptor -TRIO_ARGS2((self, output), - trio_class_t *self, - int output) -{ - int fd; - char ch; - - assert(VALID(self)); - - fd = *((int *)self->location); - ch = (char)output; - self->processed++; - if (write(fd, &ch, sizeof(char)) == -1) - { - self->error = TRIO_ERROR_RETURN(TRIO_ERRNO, 0); - } - else - { - self->actually.committed++; - } -} -#endif /* TRIO_FEATURE_FD */ - -/************************************************************************* - * TrioOutStreamCustom - */ -#if TRIO_FEATURE_CLOSURE -TRIO_PRIVATE void -TrioOutStreamCustom -TRIO_ARGS2((self, output), - trio_class_t *self, - int output) -{ - int status; - trio_custom_t *data; - - assert(VALID(self)); - assert(VALID(self->location)); - - data = (trio_custom_t *)self->location; - if (data->stream.out) - { - status = (data->stream.out)(data->closure, output); - if (status >= 0) - { - self->actually.committed++; - } - else - { - if (self->error == 0) - { - self->error = TRIO_ERROR_RETURN(TRIO_ECUSTOM, -status); - } - } - } - self->processed++; -} -#endif /* TRIO_FEATURE_CLOSURE */ - -/************************************************************************* - * TrioOutStreamString - */ -TRIO_PRIVATE void -TrioOutStreamString -TRIO_ARGS2((self, output), - trio_class_t *self, - int output) -{ - char **buffer; - - assert(VALID(self)); - assert(VALID(self->location)); - - buffer = (char **)self->location; - **buffer = (char)output; - (*buffer)++; - self->processed++; - self->actually.committed++; -} - -/************************************************************************* - * TrioOutStreamStringMax - */ -TRIO_PRIVATE void -TrioOutStreamStringMax -TRIO_ARGS2((self, output), - trio_class_t *self, - int output) -{ - char **buffer; - - assert(VALID(self)); - assert(VALID(self->location)); - - buffer = (char **)self->location; - - if (self->processed < self->max) - { - **buffer = (char)output; - (*buffer)++; - self->actually.committed++; - } - self->processed++; -} - -/************************************************************************* - * TrioOutStreamStringDynamic - */ -#if TRIO_FEATURE_DYNAMICSTRING -TRIO_PRIVATE void -TrioOutStreamStringDynamic -TRIO_ARGS2((self, output), - trio_class_t *self, - int output) -{ - assert(VALID(self)); - assert(VALID(self->location)); - - if (self->error == 0) - { - trio_xstring_append_char((trio_string_t *)self->location, - (char)output); - self->actually.committed++; - } - /* The processed variable must always be increased */ - self->processed++; -} -#endif /* TRIO_FEATURE_DYNAMICSTRING */ - -/************************************************************************* - * TrioArrayGetter - */ -TRIO_PRIVATE -trio_pointer_t TrioArrayGetter(trio_pointer_t context, int index, int type) -{ - /* Utility function for the printfv family */ - trio_pointer_t *argarray = (trio_pointer_t *)context; - return argarray[index]; -} - -/************************************************************************* - * - * Formatted printing functions - * - ************************************************************************/ - -/** @addtogroup Printf - @{ -*/ - -/************************************************************************* - * printf - */ - -/** - Print to standard output stream. - - @param format Formatting string. - @param ... Arguments. - @return Number of printed characters. - */ -#if TRIO_FEATURE_STDIO -TRIO_PUBLIC int -trio_printf -TRIO_VARGS2((format, va_alist), - TRIO_CONST char *format, - TRIO_VA_DECL) -{ - int status; - va_list args; - - assert(VALID(format)); - - TRIO_VA_START(args, format); - status = TrioFormat(stdout, 0, TrioOutStreamFile, format, args, NULL, NULL); - TRIO_VA_END(args); - return status; -} -#endif /* TRIO_FEATURE_STDIO */ - -/** - Print to standard output stream. - - @param format Formatting string. - @param args Arguments. - @return Number of printed characters. - */ -#if TRIO_FEATURE_STDIO -TRIO_PUBLIC int -trio_vprintf -TRIO_ARGS2((format, args), - TRIO_CONST char *format, - va_list args) -{ - assert(VALID(format)); - - return TrioFormat(stdout, 0, TrioOutStreamFile, format, args, NULL, NULL); -} -#endif /* TRIO_FEATURE_STDIO */ - -/** - Print to standard output stream. - - @param format Formatting string. - @param args Arguments. - @return Number of printed characters. - */ -#if TRIO_FEATURE_STDIO -TRIO_PUBLIC int -trio_printfv -TRIO_ARGS2((format, args), - TRIO_CONST char *format, - trio_pointer_t * args) -{ - static va_list unused; - - assert(VALID(format)); - - return TrioFormat(stdout, 0, TrioOutStreamFile, format, - unused, TrioArrayGetter, args); -} -#endif /* TRIO_FEATURE_STDIO */ - -/************************************************************************* - * fprintf - */ - -/** - Print to file. - - @param file File pointer. - @param format Formatting string. - @param ... Arguments. - @return Number of printed characters. - */ -#if TRIO_FEATURE_FILE -TRIO_PUBLIC int -trio_fprintf -TRIO_VARGS3((file, format, va_alist), - FILE *file, - TRIO_CONST char *format, - TRIO_VA_DECL) -{ - int status; - va_list args; - - assert(VALID(file)); - assert(VALID(format)); - - TRIO_VA_START(args, format); - status = TrioFormat(file, 0, TrioOutStreamFile, format, args, NULL, NULL); - TRIO_VA_END(args); - return status; -} -#endif /* TRIO_FEATURE_FILE */ - -/** - Print to file. - - @param file File pointer. - @param format Formatting string. - @param args Arguments. - @return Number of printed characters. - */ -#if TRIO_FEATURE_FILE -TRIO_PUBLIC int -trio_vfprintf -TRIO_ARGS3((file, format, args), - FILE *file, - TRIO_CONST char *format, - va_list args) -{ - assert(VALID(file)); - assert(VALID(format)); - - return TrioFormat(file, 0, TrioOutStreamFile, format, args, NULL, NULL); -} -#endif /* TRIO_FEATURE_FILE */ - -/** - Print to file. - - @param file File pointer. - @param format Formatting string. - @param args Arguments. - @return Number of printed characters. - */ -#if TRIO_FEATURE_FILE -TRIO_PUBLIC int -trio_fprintfv -TRIO_ARGS3((file, format, args), - FILE *file, - TRIO_CONST char *format, - trio_pointer_t * args) -{ - static va_list unused; - - assert(VALID(file)); - assert(VALID(format)); - - return TrioFormat(file, 0, TrioOutStreamFile, format, - unused, TrioArrayGetter, args); -} -#endif /* TRIO_FEATURE_FILE */ - -/************************************************************************* - * dprintf - */ - -/** - Print to file descriptor. - - @param fd File descriptor. - @param format Formatting string. - @param ... Arguments. - @return Number of printed characters. - */ -#if TRIO_FEATURE_FD -TRIO_PUBLIC int -trio_dprintf -TRIO_VARGS3((fd, format, va_alist), - int fd, - TRIO_CONST char *format, - TRIO_VA_DECL) -{ - int status; - va_list args; - - assert(VALID(format)); - - TRIO_VA_START(args, format); - status = TrioFormat(&fd, 0, TrioOutStreamFileDescriptor, format, args, NULL, NULL); - TRIO_VA_END(args); - return status; -} -#endif /* TRIO_FEATURE_FD */ - -/** - Print to file descriptor. - - @param fd File descriptor. - @param format Formatting string. - @param args Arguments. - @return Number of printed characters. - */ -#if TRIO_FEATURE_FD -TRIO_PUBLIC int -trio_vdprintf -TRIO_ARGS3((fd, format, args), - int fd, - TRIO_CONST char *format, - va_list args) -{ - assert(VALID(format)); - - return TrioFormat(&fd, 0, TrioOutStreamFileDescriptor, format, args, NULL, NULL); -} -#endif /* TRIO_FEATURE_FD */ - -/** - Print to file descriptor. - - @param fd File descriptor. - @param format Formatting string. - @param args Arguments. - @return Number of printed characters. - */ -#if TRIO_FEATURE_FD -TRIO_PUBLIC int -trio_dprintfv -TRIO_ARGS3((fd, format, args), - int fd, - TRIO_CONST char *format, - trio_pointer_t *args) -{ - static va_list unused; - - assert(VALID(format)); - - return TrioFormat(&fd, 0, TrioOutStreamFileDescriptor, format, - unused, TrioArrayGetter, args); -} -#endif /* TRIO_FEATURE_FD */ - -/************************************************************************* - * cprintf - */ -#if TRIO_FEATURE_CLOSURE -TRIO_PUBLIC int -trio_cprintf -TRIO_VARGS4((stream, closure, format, va_alist), - trio_outstream_t stream, - trio_pointer_t closure, - TRIO_CONST char *format, - TRIO_VA_DECL) -{ - int status; - va_list args; - trio_custom_t data; - - assert(VALID(stream)); - assert(VALID(format)); - - TRIO_VA_START(args, format); - data.stream.out = stream; - data.closure = closure; - status = TrioFormat(&data, 0, TrioOutStreamCustom, format, args, NULL, NULL); - TRIO_VA_END(args); - return status; -} -#endif /* TRIO_FEATURE_CLOSURE */ - -#if TRIO_FEATURE_CLOSURE -TRIO_PUBLIC int -trio_vcprintf -TRIO_ARGS4((stream, closure, format, args), - trio_outstream_t stream, - trio_pointer_t closure, - TRIO_CONST char *format, - va_list args) -{ - trio_custom_t data; - - assert(VALID(stream)); - assert(VALID(format)); - - data.stream.out = stream; - data.closure = closure; - return TrioFormat(&data, 0, TrioOutStreamCustom, format, args, NULL, NULL); -} -#endif /* TRIO_FEATURE_CLOSURE */ - -#if TRIO_FEATURE_CLOSURE -TRIO_PUBLIC int -trio_cprintfv -TRIO_ARGS4((stream, closure, format, args), - trio_outstream_t stream, - trio_pointer_t closure, - TRIO_CONST char *format, - trio_pointer_t *args) -{ - static va_list unused; - trio_custom_t data; - - assert(VALID(stream)); - assert(VALID(format)); - - data.stream.out = stream; - data.closure = closure; - return TrioFormat(&data, 0, TrioOutStreamCustom, format, - unused, TrioArrayGetter, args); -} -#endif /* TRIO_FEATURE_CLOSURE */ - -#if TRIO_FEATURE_CLOSURE && TRIO_FEATURE_ARGFUNC -TRIO_PUBLIC int -trio_cprintff -TRIO_ARGS5((stream, closure, format, argfunc, context), - trio_outstream_t stream, - trio_pointer_t closure, - TRIO_CONST char *format, - trio_argfunc_t argfunc, - trio_pointer_t context) -{ - static va_list unused; - trio_custom_t data; - - assert(VALID(stream)); - assert(VALID(format)); - assert(VALID(argfunc)); - - data.stream.out = stream; - data.closure = closure; - return TrioFormat(&data, 0, TrioOutStreamCustom, format, - unused, argfunc, (trio_pointer_t *)context); -} -#endif /* TRIO_FEATURE_CLOSURE && TRIO_FEATURE_ARGFUNC */ - -/************************************************************************* - * sprintf - */ - -/** - Print to string. - - @param buffer Output string. - @param format Formatting string. - @param ... Arguments. - @return Number of printed characters. - */ -TRIO_PUBLIC int -trio_sprintf -TRIO_VARGS3((buffer, format, va_alist), - char *buffer, - TRIO_CONST char *format, - TRIO_VA_DECL) -{ - int status; - va_list args; - - assert(VALID(buffer)); - assert(VALID(format)); - - TRIO_VA_START(args, format); - status = TrioFormat(&buffer, 0, TrioOutStreamString, format, args, NULL, NULL); - *buffer = NIL; /* Terminate with NIL character */ - TRIO_VA_END(args); - return status; -} - -/** - Print to string. - - @param buffer Output string. - @param format Formatting string. - @param args Arguments. - @return Number of printed characters. - */ -TRIO_PUBLIC int -trio_vsprintf -TRIO_ARGS3((buffer, format, args), - char *buffer, - TRIO_CONST char *format, - va_list args) -{ - int status; - - assert(VALID(buffer)); - assert(VALID(format)); - - status = TrioFormat(&buffer, 0, TrioOutStreamString, format, args, NULL, NULL); - *buffer = NIL; - return status; -} - -/** - Print to string. - - @param buffer Output string. - @param format Formatting string. - @param args Arguments. - @return Number of printed characters. - */ -TRIO_PUBLIC int -trio_sprintfv -TRIO_ARGS3((buffer, format, args), - char *buffer, - TRIO_CONST char *format, - trio_pointer_t *args) -{ - static va_list unused; - int status; - - assert(VALID(buffer)); - assert(VALID(format)); - - status = TrioFormat(&buffer, 0, TrioOutStreamString, format, - unused, TrioArrayGetter, args); - *buffer = NIL; - return status; -} - -/************************************************************************* - * snprintf - */ - -/** - Print at most @p max characters to string. - - @param buffer Output string. - @param max Maximum number of characters to print. - @param format Formatting string. - @param ... Arguments. - @return Number of printed characters. - */ -TRIO_PUBLIC int -trio_snprintf -TRIO_VARGS4((buffer, max, format, va_alist), - char *buffer, - size_t max, - TRIO_CONST char *format, - TRIO_VA_DECL) -{ - int status; - va_list args; - - assert(VALID(buffer) || (max == 0)); - assert(VALID(format)); - - TRIO_VA_START(args, format); - status = TrioFormat(&buffer, max > 0 ? max - 1 : 0, - TrioOutStreamStringMax, format, args, NULL, NULL); - if (max > 0) - *buffer = NIL; - TRIO_VA_END(args); - return status; -} - -/** - Print at most @p max characters to string. - - @param buffer Output string. - @param max Maximum number of characters to print. - @param format Formatting string. - @param args Arguments. - @return Number of printed characters. - */ -TRIO_PUBLIC int -trio_vsnprintf -TRIO_ARGS4((buffer, max, format, args), - char *buffer, - size_t max, - TRIO_CONST char *format, - va_list args) -{ - int status; - - assert(VALID(buffer) || (max == 0)); - assert(VALID(format)); - - status = TrioFormat(&buffer, max > 0 ? max - 1 : 0, - TrioOutStreamStringMax, format, args, NULL, NULL); - if (max > 0) - *buffer = NIL; - return status; -} - -/** - Print at most @p max characters to string. - - @param buffer Output string. - @param max Maximum number of characters to print. - @param format Formatting string. - @param args Arguments. - @return Number of printed characters. - */ -TRIO_PUBLIC int -trio_snprintfv -TRIO_ARGS4((buffer, max, format, args), - char *buffer, - size_t max, - TRIO_CONST char *format, - trio_pointer_t *args) -{ - static va_list unused; - int status; - - assert(VALID(buffer) || (max == 0)); - assert(VALID(format)); - - status = TrioFormat(&buffer, max > 0 ? max - 1 : 0, - TrioOutStreamStringMax, format, - unused, TrioArrayGetter, args); - if (max > 0) - *buffer = NIL; - return status; -} - -/************************************************************************* - * snprintfcat - * Appends the new string to the buffer string overwriting the '\0' - * character at the end of buffer. - */ -#if TRIO_EXTENSION -TRIO_PUBLIC int -trio_snprintfcat -TRIO_VARGS4((buffer, max, format, va_alist), - char *buffer, - size_t max, - TRIO_CONST char *format, - TRIO_VA_DECL) -{ - int status; - va_list args; - size_t buf_len; - - TRIO_VA_START(args, format); - - assert(VALID(buffer)); - assert(VALID(format)); - - buf_len = trio_length(buffer); - buffer = &buffer[buf_len]; - - status = TrioFormat(&buffer, max - 1 - buf_len, - TrioOutStreamStringMax, format, args, NULL, NULL); - TRIO_VA_END(args); - *buffer = NIL; - return status; -} -#endif - -#if TRIO_EXTENSION -TRIO_PUBLIC int -trio_vsnprintfcat -TRIO_ARGS4((buffer, max, format, args), - char *buffer, - size_t max, - TRIO_CONST char *format, - va_list args) -{ - int status; - size_t buf_len; - - assert(VALID(buffer)); - assert(VALID(format)); - - buf_len = trio_length(buffer); - buffer = &buffer[buf_len]; - status = TrioFormat(&buffer, max - 1 - buf_len, - TrioOutStreamStringMax, format, args, NULL, NULL); - *buffer = NIL; - return status; -} -#endif - -/************************************************************************* - * trio_aprintf - */ - -#if TRIO_DEPRECATED && TRIO_FEATURE_DYNAMICSTRING -TRIO_PUBLIC char * -trio_aprintf -TRIO_VARGS2((format, va_alist), - TRIO_CONST char *format, - TRIO_VA_DECL) -{ - va_list args; - trio_string_t *info; - char *result = NULL; - - assert(VALID(format)); - - info = trio_xstring_duplicate(""); - if (info) - { - TRIO_VA_START(args, format); - (void)TrioFormat(info, 0, TrioOutStreamStringDynamic, - format, args, NULL, NULL); - TRIO_VA_END(args); - - trio_string_terminate(info); - result = trio_string_extract(info); - trio_string_destroy(info); - } - return result; -} -#endif /* TRIO_DEPRECATED && TRIO_FEATURE_DYNAMICSTRING */ - -#if TRIO_DEPRECATED && TRIO_FEATURE_DYNAMICSTRING -TRIO_PUBLIC char * -trio_vaprintf -TRIO_ARGS2((format, args), - TRIO_CONST char *format, - va_list args) -{ - trio_string_t *info; - char *result = NULL; - - assert(VALID(format)); - - info = trio_xstring_duplicate(""); - if (info) - { - (void)TrioFormat(info, 0, TrioOutStreamStringDynamic, - format, args, NULL, NULL); - trio_string_terminate(info); - result = trio_string_extract(info); - trio_string_destroy(info); - } - return result; -} -#endif /* TRIO_DEPRECATED && TRIO_FEATURE_DYNAMICSTRING */ - -/** - Allocate and print to string. - The memory allocated and returned by @p result must be freed by the - calling application. - - @param result Output string. - @param format Formatting string. - @param ... Arguments. - @return Number of printed characters. - */ -#if TRIO_FEATURE_DYNAMICSTRING -TRIO_PUBLIC int -trio_asprintf -TRIO_VARGS3((result, format, va_alist), - char **result, - TRIO_CONST char *format, - TRIO_VA_DECL) -{ - va_list args; - int status; - trio_string_t *info; - - assert(VALID(format)); - - *result = NULL; - - info = trio_xstring_duplicate(""); - if (info == NULL) - { - status = TRIO_ERROR_RETURN(TRIO_ENOMEM, 0); - } - else - { - TRIO_VA_START(args, format); - status = TrioFormat(info, 0, TrioOutStreamStringDynamic, - format, args, NULL, NULL); - TRIO_VA_END(args); - if (status >= 0) - { - trio_string_terminate(info); - *result = trio_string_extract(info); - } - trio_string_destroy(info); - } - return status; -} -#endif /* TRIO_FEATURE_DYNAMICSTRING */ - -/** - Allocate and print to string. - The memory allocated and returned by @p result must be freed by the - calling application. - - @param result Output string. - @param format Formatting string. - @param args Arguments. - @return Number of printed characters. - */ -#if TRIO_FEATURE_DYNAMICSTRING -TRIO_PUBLIC int -trio_vasprintf -TRIO_ARGS3((result, format, args), - char **result, - TRIO_CONST char *format, - va_list args) -{ - int status; - trio_string_t *info; - - assert(VALID(format)); - - *result = NULL; - - info = trio_xstring_duplicate(""); - if (info == NULL) - { - status = TRIO_ERROR_RETURN(TRIO_ENOMEM, 0); - } - else - { - status = TrioFormat(info, 0, TrioOutStreamStringDynamic, - format, args, NULL, NULL); - if (status >= 0) - { - trio_string_terminate(info); - *result = trio_string_extract(info); - } - trio_string_destroy(info); - } - return status; -} -#endif /* TRIO_FEATURE_DYNAMICSTRING */ - -/** - Allocate and print to string. - The memory allocated and returned by @p result must be freed by the - calling application. - - @param result Output string. - @param format Formatting string. - @param args Arguments. - @return Number of printed characters. - */ -#if TRIO_FEATURE_DYNAMICSTRING -TRIO_PUBLIC int -trio_asprintfv -TRIO_ARGS3((result, format, args), - char **result, - TRIO_CONST char *format, - trio_pointer_t * args) -{ - static va_list unused; - int status; - trio_string_t *info; - - assert(VALID(format)); - - *result = NULL; - - info = trio_xstring_duplicate(""); - if (info == NULL) - { - status = TRIO_ERROR_RETURN(TRIO_ENOMEM, 0); - } - else - { - status = TrioFormat(info, 0, TrioOutStreamStringDynamic, format, - unused, TrioArrayGetter, args); - if (status >= 0) - { - trio_string_terminate(info); - *result = trio_string_extract(info); - } - trio_string_destroy(info); - } - return status; -} -#endif /* TRIO_FEATURE_DYNAMICSTRING */ - -#if defined(TRIO_DOCUMENTATION) -# include "doc/doc_printf.h" -#endif - -/** @} End of Printf documentation module */ - -/************************************************************************* - * - * CALLBACK - * - ************************************************************************/ - -#if defined(TRIO_DOCUMENTATION) -# include "doc/doc_register.h" -#endif -/** - @addtogroup UserDefined - @{ -*/ - -#if TRIO_FEATURE_USER_DEFINED - -/************************************************************************* - * trio_register - */ - -/** - Register new user-defined specifier. - - @param callback - @param name - @return Handle. - */ -TRIO_PUBLIC trio_pointer_t -trio_register -TRIO_ARGS2((callback, name), - trio_callback_t callback, - TRIO_CONST char *name) -{ - trio_userdef_t *def; - trio_userdef_t *prev = NULL; - - if (callback == NULL) - return NULL; - - if (name) - { - /* Handle built-in namespaces */ - if (name[0] == ':') - { - if (trio_equal(name, ":enter")) - { - internalEnterCriticalRegion = callback; - } - else if (trio_equal(name, ":leave")) - { - internalLeaveCriticalRegion = callback; - } - return NULL; - } - - /* Bail out if namespace is too long */ - if (trio_length(name) >= MAX_USER_NAME) - return NULL; - - /* Bail out if namespace already is registered */ - def = TrioFindNamespace(name, &prev); - if (def) - return NULL; - } - - def = (trio_userdef_t *)TRIO_MALLOC(sizeof(trio_userdef_t)); - if (def) - { - if (internalEnterCriticalRegion) - (void)internalEnterCriticalRegion(NULL); - - if (name) - { - /* Link into internal list */ - if (prev == NULL) - internalUserDef = def; - else - prev->next = def; - } - /* Initialize */ - def->callback = callback; - def->name = (name == NULL) - ? NULL - : trio_duplicate(name); - def->next = NULL; - - if (internalLeaveCriticalRegion) - (void)internalLeaveCriticalRegion(NULL); - } - return (trio_pointer_t)def; -} - -/** - Unregister an existing user-defined specifier. - - @param handle - */ -TRIO_PUBLIC -void -trio_unregister -TRIO_ARGS1((handle), - trio_pointer_t handle) -{ - trio_userdef_t *self = (trio_userdef_t *)handle; - trio_userdef_t *def; - trio_userdef_t *prev = NULL; - - assert(VALID(self)); - - if (self->name) - { - def = TrioFindNamespace(self->name, &prev); - if (def) - { - if (internalEnterCriticalRegion) - (void)internalEnterCriticalRegion(NULL); - - if (prev == NULL) - internalUserDef = internalUserDef->next; - else - prev->next = def->next; - - if (internalLeaveCriticalRegion) - (void)internalLeaveCriticalRegion(NULL); - } - trio_destroy(self->name); - } - TRIO_FREE(self); -} - -/************************************************************************* - * trio_get_format - */ -TRIO_PUBLIC -TRIO_CONST char * -trio_get_format -TRIO_ARGS1((ref), - trio_pointer_t ref) -{ -#if TRIO_FEATURE_USER_DEFINED - assert(((trio_reference_t *)ref)->parameter->type == FORMAT_USER_DEFINED); -#endif - - return (((trio_reference_t *)ref)->parameter->user_data); -} - -/************************************************************************* - * trio_get_argument - */ -TRIO_PUBLIC -TRIO_CONST trio_pointer_t -trio_get_argument -TRIO_ARGS1((ref), - trio_pointer_t ref) -{ -#if TRIO_FEATURE_USER_DEFINED - assert(((trio_reference_t *)ref)->parameter->type == FORMAT_USER_DEFINED); -#endif - - return ((trio_reference_t *)ref)->parameter->data.pointer; -} - -/************************************************************************* - * trio_get_width / trio_set_width - */ -TRIO_PUBLIC -int -trio_get_width -TRIO_ARGS1((ref), - trio_pointer_t ref) -{ - return ((trio_reference_t *)ref)->parameter->width; -} - -TRIO_PUBLIC -void -trio_set_width -TRIO_ARGS2((ref, width), - trio_pointer_t ref, - int width) -{ - ((trio_reference_t *)ref)->parameter->width = width; -} - -/************************************************************************* - * trio_get_precision / trio_set_precision - */ -TRIO_PUBLIC -int -trio_get_precision -TRIO_ARGS1((ref), - trio_pointer_t ref) -{ - return (((trio_reference_t *)ref)->parameter->precision); -} - -TRIO_PUBLIC -void -trio_set_precision -TRIO_ARGS2((ref, precision), - trio_pointer_t ref, - int precision) -{ - ((trio_reference_t *)ref)->parameter->precision = precision; -} - -/************************************************************************* - * trio_get_base / trio_set_base - */ -TRIO_PUBLIC -int -trio_get_base -TRIO_ARGS1((ref), - trio_pointer_t ref) -{ - return (((trio_reference_t *)ref)->parameter->base); -} - -TRIO_PUBLIC -void -trio_set_base -TRIO_ARGS2((ref, base), - trio_pointer_t ref, - int base) -{ - ((trio_reference_t *)ref)->parameter->base = base; -} - -/************************************************************************* - * trio_get_long / trio_set_long - */ -TRIO_PUBLIC -int -trio_get_long -TRIO_ARGS1((ref), - trio_pointer_t ref) -{ - return (((trio_reference_t *)ref)->parameter->flags & FLAGS_LONG) - ? TRUE - : FALSE; -} - -TRIO_PUBLIC -void -trio_set_long -TRIO_ARGS2((ref, is_long), - trio_pointer_t ref, - int is_long) -{ - if (is_long) - ((trio_reference_t *)ref)->parameter->flags |= FLAGS_LONG; - else - ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_LONG; -} - -/************************************************************************* - * trio_get_longlong / trio_set_longlong - */ -TRIO_PUBLIC -int -trio_get_longlong -TRIO_ARGS1((ref), - trio_pointer_t ref) -{ - return (((trio_reference_t *)ref)->parameter->flags & FLAGS_QUAD) - ? TRUE - : FALSE; -} - -TRIO_PUBLIC -void -trio_set_longlong -TRIO_ARGS2((ref, is_longlong), - trio_pointer_t ref, - int is_longlong) -{ - if (is_longlong) - ((trio_reference_t *)ref)->parameter->flags |= FLAGS_QUAD; - else - ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_QUAD; -} - -/************************************************************************* - * trio_get_longdouble / trio_set_longdouble - */ -# if TRIO_FEATURE_FLOAT -TRIO_PUBLIC -int -trio_get_longdouble -TRIO_ARGS1((ref), - trio_pointer_t ref) -{ - return (((trio_reference_t *)ref)->parameter->flags & FLAGS_LONGDOUBLE) - ? TRUE - : FALSE; -} - -TRIO_PUBLIC -void -trio_set_longdouble -TRIO_ARGS2((ref, is_longdouble), - trio_pointer_t ref, - int is_longdouble) -{ - if (is_longdouble) - ((trio_reference_t *)ref)->parameter->flags |= FLAGS_LONGDOUBLE; - else - ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_LONGDOUBLE; -} -# endif /* TRIO_FEATURE_FLOAT */ - -/************************************************************************* - * trio_get_short / trio_set_short - */ -TRIO_PUBLIC -int -trio_get_short -TRIO_ARGS1((ref), - trio_pointer_t ref) -{ - return (((trio_reference_t *)ref)->parameter->flags & FLAGS_SHORT) - ? TRUE - : FALSE; -} - -TRIO_PUBLIC -void -trio_set_short -TRIO_ARGS2((ref, is_short), - trio_pointer_t ref, - int is_short) -{ - if (is_short) - ((trio_reference_t *)ref)->parameter->flags |= FLAGS_SHORT; - else - ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_SHORT; -} - -/************************************************************************* - * trio_get_shortshort / trio_set_shortshort - */ -TRIO_PUBLIC -int -trio_get_shortshort -TRIO_ARGS1((ref), - trio_pointer_t ref) -{ - return (((trio_reference_t *)ref)->parameter->flags & FLAGS_SHORTSHORT) - ? TRUE - : FALSE; -} - -TRIO_PUBLIC -void -trio_set_shortshort -TRIO_ARGS2((ref, is_shortshort), - trio_pointer_t ref, - int is_shortshort) -{ - if (is_shortshort) - ((trio_reference_t *)ref)->parameter->flags |= FLAGS_SHORTSHORT; - else - ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_SHORTSHORT; -} - -/************************************************************************* - * trio_get_alternative / trio_set_alternative - */ -TRIO_PUBLIC -int -trio_get_alternative -TRIO_ARGS1((ref), - trio_pointer_t ref) -{ - return (((trio_reference_t *)ref)->parameter->flags & FLAGS_ALTERNATIVE) - ? TRUE - : FALSE; -} - -TRIO_PUBLIC -void -trio_set_alternative -TRIO_ARGS2((ref, is_alternative), - trio_pointer_t ref, - int is_alternative) -{ - if (is_alternative) - ((trio_reference_t *)ref)->parameter->flags |= FLAGS_ALTERNATIVE; - else - ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_ALTERNATIVE; -} - -/************************************************************************* - * trio_get_alignment / trio_set_alignment - */ -TRIO_PUBLIC -int -trio_get_alignment -TRIO_ARGS1((ref), - trio_pointer_t ref) -{ - return (((trio_reference_t *)ref)->parameter->flags & FLAGS_LEFTADJUST) - ? TRUE - : FALSE; -} - -TRIO_PUBLIC -void -trio_set_alignment -TRIO_ARGS2((ref, is_leftaligned), - trio_pointer_t ref, - int is_leftaligned) -{ - if (is_leftaligned) - ((trio_reference_t *)ref)->parameter->flags |= FLAGS_LEFTADJUST; - else - ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_LEFTADJUST; -} - -/************************************************************************* - * trio_get_spacing /trio_set_spacing - */ -TRIO_PUBLIC -int -trio_get_spacing -TRIO_ARGS1((ref), - trio_pointer_t ref) -{ - return (((trio_reference_t *)ref)->parameter->flags & FLAGS_SPACE) - ? TRUE - : FALSE; -} - -TRIO_PUBLIC -void -trio_set_spacing -TRIO_ARGS2((ref, is_space), - trio_pointer_t ref, - int is_space) -{ - if (is_space) - ((trio_reference_t *)ref)->parameter->flags |= FLAGS_SPACE; - else - ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_SPACE; -} - -/************************************************************************* - * trio_get_sign / trio_set_sign - */ -TRIO_PUBLIC -int -trio_get_sign -TRIO_ARGS1((ref), - trio_pointer_t ref) -{ - return (((trio_reference_t *)ref)->parameter->flags & FLAGS_SHOWSIGN) - ? TRUE - : FALSE; -} - -TRIO_PUBLIC -void -trio_set_sign -TRIO_ARGS2((ref, is_sign), - trio_pointer_t ref, - int is_sign) -{ - if (is_sign) - ((trio_reference_t *)ref)->parameter->flags |= FLAGS_SHOWSIGN; - else - ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_SHOWSIGN; -} - -/************************************************************************* - * trio_get_padding / trio_set_padding - */ -TRIO_PUBLIC -int -trio_get_padding -TRIO_ARGS1((ref), - trio_pointer_t ref) -{ - return (((trio_reference_t *)ref)->parameter->flags & FLAGS_NILPADDING) - ? TRUE - : FALSE; -} - -TRIO_PUBLIC -void -trio_set_padding -TRIO_ARGS2((ref, is_padding), - trio_pointer_t ref, - int is_padding) -{ - if (is_padding) - ((trio_reference_t *)ref)->parameter->flags |= FLAGS_NILPADDING; - else - ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_NILPADDING; -} - -/************************************************************************* - * trio_get_quote / trio_set_quote - */ -# if TRIO_FEATURE_QUOTE -TRIO_PUBLIC -int -trio_get_quote -TRIO_ARGS1((ref), - trio_pointer_t ref) -{ - return (((trio_reference_t *)ref)->parameter->flags & FLAGS_QUOTE) - ? TRUE - : FALSE; -} - -TRIO_PUBLIC -void -trio_set_quote -TRIO_ARGS2((ref, is_quote), - trio_pointer_t ref, - int is_quote) -{ - if (is_quote) - ((trio_reference_t *)ref)->parameter->flags |= FLAGS_QUOTE; - else - ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_QUOTE; -} -#endif /* TRIO_FEATURE_QUOTE */ - -/************************************************************************* - * trio_get_upper / trio_set_upper - */ -TRIO_PUBLIC -int -trio_get_upper -TRIO_ARGS1((ref), - trio_pointer_t ref) -{ - return (((trio_reference_t *)ref)->parameter->flags & FLAGS_UPPER) - ? TRUE - : FALSE; -} - -TRIO_PUBLIC -void -trio_set_upper -TRIO_ARGS2((ref, is_upper), - trio_pointer_t ref, - int is_upper) -{ - if (is_upper) - ((trio_reference_t *)ref)->parameter->flags |= FLAGS_UPPER; - else - ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_UPPER; -} - -/************************************************************************* - * trio_get_largest / trio_set_largest - */ -#if TRIO_FEATURE_INTMAX_T -TRIO_PUBLIC -int -trio_get_largest -TRIO_ARGS1((ref), - trio_pointer_t ref) -{ - return (((trio_reference_t *)ref)->parameter->flags & FLAGS_INTMAX_T) - ? TRUE - : FALSE; -} - -TRIO_PUBLIC -void -trio_set_largest -TRIO_ARGS2((ref, is_largest), - trio_pointer_t ref, - int is_largest) -{ - if (is_largest) - ((trio_reference_t *)ref)->parameter->flags |= FLAGS_INTMAX_T; - else - ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_INTMAX_T; -} -#endif /* TRIO_FEATURE_INTMAX_T */ - -/************************************************************************* - * trio_get_ptrdiff / trio_set_ptrdiff - */ -#if TRIO_FEATURE_PTRDIFF_T -TRIO_PUBLIC -int -trio_get_ptrdiff -TRIO_ARGS1((ref), - trio_pointer_t ref) -{ - return (((trio_reference_t *)ref)->parameter->flags & FLAGS_PTRDIFF_T) - ? TRUE - : FALSE; -} - -TRIO_PUBLIC -void -trio_set_ptrdiff -TRIO_ARGS2((ref, is_ptrdiff), - trio_pointer_t ref, - int is_ptrdiff) -{ - if (is_ptrdiff) - ((trio_reference_t *)ref)->parameter->flags |= FLAGS_PTRDIFF_T; - else - ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_PTRDIFF_T; -} -#endif /* TRIO_FEATURE_PTRDIFF_T */ - -/************************************************************************* - * trio_get_size / trio_set_size - */ -#if TRIO_FEATURE_SIZE_T -TRIO_PUBLIC -int -trio_get_size -TRIO_ARGS1((ref), - trio_pointer_t ref) -{ - return (((trio_reference_t *)ref)->parameter->flags & FLAGS_SIZE_T) - ? TRUE - : FALSE; -} - -TRIO_PUBLIC -void -trio_set_size -TRIO_ARGS2((ref, is_size), - trio_pointer_t ref, - int is_size) -{ - if (is_size) - ((trio_reference_t *)ref)->parameter->flags |= FLAGS_SIZE_T; - else - ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_SIZE_T; -} -#endif /* TRIO_FEATURE_SIZE_T */ - -/************************************************************************* - * trio_print_int - */ -TRIO_PUBLIC -void -trio_print_int -TRIO_ARGS2((ref, number), - trio_pointer_t ref, - int number) -{ - trio_reference_t *self = (trio_reference_t *)ref; - - TrioWriteNumber(self->data, - (trio_uintmax_t)number, - self->parameter->flags, - self->parameter->width, - self->parameter->precision, - self->parameter->base); -} - -/************************************************************************* - * trio_print_uint - */ -TRIO_PUBLIC -void -trio_print_uint -TRIO_ARGS2((ref, number), - trio_pointer_t ref, - unsigned int number) -{ - trio_reference_t *self = (trio_reference_t *)ref; - - TrioWriteNumber(self->data, - (trio_uintmax_t)number, - self->parameter->flags | FLAGS_UNSIGNED, - self->parameter->width, - self->parameter->precision, - self->parameter->base); -} - -/************************************************************************* - * trio_print_double - */ -#if TRIO_FEATURE_FLOAT -TRIO_PUBLIC -void -trio_print_double -TRIO_ARGS2((ref, number), - trio_pointer_t ref, - double number) -{ - trio_reference_t *self = (trio_reference_t *)ref; - - TrioWriteDouble(self->data, - number, - self->parameter->flags, - self->parameter->width, - self->parameter->precision, - self->parameter->base); -} -#endif /* TRIO_FEATURE_FLOAT */ - -/************************************************************************* - * trio_print_string - */ -TRIO_PUBLIC -void -trio_print_string -TRIO_ARGS2((ref, string), - trio_pointer_t ref, - TRIO_CONST char *string) -{ - trio_reference_t *self = (trio_reference_t *)ref; - - TrioWriteString(self->data, - string, - self->parameter->flags, - self->parameter->width, - self->parameter->precision); -} - -/************************************************************************* - * trio_print_ref - */ -TRIO_PUBLIC -int -trio_print_ref -TRIO_VARGS3((ref, format, va_alist), - trio_pointer_t ref, - TRIO_CONST char *format, - TRIO_VA_DECL) -{ - int status; - va_list arglist; - - assert(VALID(format)); - - TRIO_VA_START(arglist, format); - status = TrioFormatRef((trio_reference_t *)ref, format, arglist, NULL, NULL); - TRIO_VA_END(arglist); - return status; -} - -/************************************************************************* - * trio_vprint_ref - */ -TRIO_PUBLIC -int -trio_vprint_ref -TRIO_ARGS3((ref, format, arglist), - trio_pointer_t ref, - TRIO_CONST char *format, - va_list arglist) -{ - assert(VALID(format)); - - return TrioFormatRef((trio_reference_t *)ref, format, arglist, NULL, NULL); -} - -/************************************************************************* - * trio_printv_ref - */ -TRIO_PUBLIC -int -trio_printv_ref -TRIO_ARGS3((ref, format, argarray), - trio_pointer_t ref, - TRIO_CONST char *format, - trio_pointer_t *argarray) -{ - static va_list unused; - - assert(VALID(format)); - - return TrioFormatRef((trio_reference_t *)ref, format, - unused, TrioArrayGetter, argarray); -} - -#endif - -/************************************************************************* - * trio_print_pointer - */ -TRIO_PUBLIC -void -trio_print_pointer -TRIO_ARGS2((ref, pointer), - trio_pointer_t ref, - trio_pointer_t pointer) -{ - trio_reference_t *self = (trio_reference_t *)ref; - trio_flags_t flags; - trio_uintmax_t number; - - if (NULL == pointer) - { - TRIO_CONST char *string = internalNullString; - while (*string) - self->data->OutStream(self->data, *string++); - } - else - { - /* - * The subtraction of the null pointer is a workaround - * to avoid a compiler warning. The performance overhead - * is negligible (and likely to be removed by an - * optimizing compiler). The (char *) casting is done - * to please ANSI C++. - */ - number = (trio_uintmax_t)((char *)pointer - (char *)0); - /* Shrink to size of pointer */ - number &= (trio_uintmax_t)-1; - flags = self->parameter->flags; - flags |= (FLAGS_UNSIGNED | FLAGS_ALTERNATIVE | - FLAGS_NILPADDING); - TrioWriteNumber(self->data, - number, - flags, - POINTER_WIDTH, - NO_PRECISION, - BASE_HEX); - } -} - -/** @} End of UserDefined documentation module */ - -/************************************************************************* - * - * LOCALES - * - ************************************************************************/ - -/************************************************************************* - * trio_locale_set_decimal_point - * - * Decimal point can only be one character. The input argument is a - * string to enable multibyte characters. At most MB_LEN_MAX characters - * will be used. - */ -#if TRIO_FEATURE_LOCALE -TRIO_PUBLIC void -trio_locale_set_decimal_point -TRIO_ARGS1((decimalPoint), - char *decimalPoint) -{ -#if defined(USE_LOCALE) - if (NULL == internalLocaleValues) - { - TrioSetLocale(); - } -#endif - internalDecimalPointLength = trio_length(decimalPoint); - if (internalDecimalPointLength == 1) - { - internalDecimalPoint = *decimalPoint; - } - else - { - internalDecimalPoint = NIL; - trio_copy_max(internalDecimalPointString, - sizeof(internalDecimalPointString), - decimalPoint); - } -} -#endif - -/************************************************************************* - * trio_locale_set_thousand_separator - * - * See trio_locale_set_decimal_point - */ -#if TRIO_FEATURE_LOCALE || TRIO_EXTENSION -TRIO_PUBLIC void -trio_locale_set_thousand_separator -TRIO_ARGS1((thousandSeparator), - char *thousandSeparator) -{ -# if defined(USE_LOCALE) - if (NULL == internalLocaleValues) - { - TrioSetLocale(); - } -# endif - trio_copy_max(internalThousandSeparator, - sizeof(internalThousandSeparator), - thousandSeparator); - internalThousandSeparatorLength = trio_length(internalThousandSeparator); -} -#endif - -/************************************************************************* - * trio_locale_set_grouping - * - * Array of bytes. Reversed order. - * - * CHAR_MAX : No further grouping - * 0 : Repeat last group for the remaining digits (not necessary - * as C strings are zero-terminated) - * n : Set current group to n - * - * Same order as the grouping attribute in LC_NUMERIC. - */ -#if TRIO_FEATURE_LOCALE || TRIO_EXTENSION -TRIO_PUBLIC void -trio_locale_set_grouping -TRIO_ARGS1((grouping), - char *grouping) -{ -# if defined(USE_LOCALE) - if (NULL == internalLocaleValues) - { - TrioSetLocale(); - } -# endif - trio_copy_max(internalGrouping, - sizeof(internalGrouping), - grouping); -} -#endif - - -/************************************************************************* - * - * SCANNING - * - ************************************************************************/ - -#if TRIO_FEATURE_SCANF - -/************************************************************************* - * TrioSkipWhitespaces - */ -TRIO_PRIVATE int -TrioSkipWhitespaces -TRIO_ARGS1((self), - trio_class_t *self) -{ - int ch; - - ch = self->current; - while (isspace(ch)) - { - self->InStream(self, &ch); - } - return ch; -} - -/************************************************************************* - * TrioGetCollation - */ -#if TRIO_EXTENSION -TRIO_PRIVATE void -TrioGetCollation(TRIO_NOARGS) -{ - int i; - int j; - int k; - char first[2]; - char second[2]; - - /* This is computationally expensive */ - first[1] = NIL; - second[1] = NIL; - for (i = 0; i < MAX_CHARACTER_CLASS; i++) - { - k = 0; - first[0] = (char)i; - for (j = 0; j < MAX_CHARACTER_CLASS; j++) - { - second[0] = (char)j; - if (trio_equal_locale(first, second)) - internalCollationArray[i][k++] = (char)j; - } - internalCollationArray[i][k] = NIL; - } -} -#endif - -/************************************************************************* - * TrioGetCharacterClass - * - * FIXME: - * multibyte - */ -TRIO_PRIVATE int -TrioGetCharacterClass -TRIO_ARGS4((format, offsetPointer, flagsPointer, characterclass), - TRIO_CONST char *format, - int *offsetPointer, - trio_flags_t *flagsPointer, - int *characterclass) -{ - int offset = *offsetPointer; - int i; - char ch; - char range_begin; - char range_end; - - *flagsPointer &= ~FLAGS_EXCLUDE; - - if (format[offset] == QUALIFIER_CIRCUMFLEX) - { - *flagsPointer |= FLAGS_EXCLUDE; - offset++; - } - /* - * If the ungroup character is at the beginning of the scanlist, - * it will be part of the class, and a second ungroup character - * must follow to end the group. - */ - if (format[offset] == SPECIFIER_UNGROUP) - { - characterclass[(int)SPECIFIER_UNGROUP]++; - offset++; - } - /* - * Minus is used to specify ranges. To include minus in the class, - * it must be at the beginning of the list - */ - if (format[offset] == QUALIFIER_MINUS) - { - characterclass[(int)QUALIFIER_MINUS]++; - offset++; - } - /* Collect characters */ - for (ch = format[offset]; - (ch != SPECIFIER_UNGROUP) && (ch != NIL); - ch = format[++offset]) - { - switch (ch) - { - case QUALIFIER_MINUS: /* Scanlist ranges */ - - /* - * Both C99 and UNIX98 describes ranges as implementation- - * defined. - * - * We support the following behaviour (although this may - * change as we become wiser) - * - only increasing ranges, ie. [a-b] but not [b-a] - * - transitive ranges, ie. [a-b-c] == [a-c] - * - trailing minus, ie. [a-] is interpreted as an 'a' - * and a '-' - * - duplicates (although we can easily convert these - * into errors) - */ - range_begin = format[offset - 1]; - range_end = format[++offset]; - if (range_end == SPECIFIER_UNGROUP) - { - /* Trailing minus is included */ - characterclass[(int)ch]++; - ch = range_end; - break; /* for */ - } - if (range_end == NIL) - return TRIO_ERROR_RETURN(TRIO_EINVAL, offset); - if (range_begin > range_end) - return TRIO_ERROR_RETURN(TRIO_ERANGE, offset); - - for (i = (int)range_begin; i <= (int)range_end; i++) - characterclass[i]++; - - ch = range_end; - break; - -#if TRIO_EXTENSION - - case SPECIFIER_GROUP: - - switch (format[offset + 1]) - { - case QUALIFIER_DOT: /* Collating symbol */ - /* - * FIXME: This will be easier to implement when multibyte - * characters have been implemented. Until now, we ignore - * this feature. - */ - for (i = offset + 2; ; i++) - { - if (format[i] == NIL) - /* Error in syntax */ - return -1; - else if (format[i] == QUALIFIER_DOT) - break; /* for */ - } - if (format[++i] != SPECIFIER_UNGROUP) - return -1; - - offset = i; - break; - - case QUALIFIER_EQUAL: /* Equivalence class expressions */ - { - unsigned int j; - unsigned int k; - - if (internalCollationUnconverted) - { - /* Lazy evaluation of collation array */ - TrioGetCollation(); - internalCollationUnconverted = FALSE; - } - for (i = offset + 2; ; i++) - { - if (format[i] == NIL) - /* Error in syntax */ - return -1; - else if (format[i] == QUALIFIER_EQUAL) - break; /* for */ - else - { - /* Mark any equivalent character */ - k = (unsigned int)format[i]; - for (j = 0; internalCollationArray[k][j] != NIL; j++) - characterclass[(int)internalCollationArray[k][j]]++; - } - } - if (format[++i] != SPECIFIER_UNGROUP) - return -1; - - offset = i; - } - break; - - case QUALIFIER_COLON: /* Character class expressions */ - - if (trio_equal_max(CLASS_ALNUM, sizeof(CLASS_ALNUM) - 1, - &format[offset])) - { - for (i = 0; i < MAX_CHARACTER_CLASS; i++) - if (isalnum(i)) - characterclass[i]++; - offset += sizeof(CLASS_ALNUM) - 1; - } - else if (trio_equal_max(CLASS_ALPHA, sizeof(CLASS_ALPHA) - 1, - &format[offset])) - { - for (i = 0; i < MAX_CHARACTER_CLASS; i++) - if (isalpha(i)) - characterclass[i]++; - offset += sizeof(CLASS_ALPHA) - 1; - } - else if (trio_equal_max(CLASS_CNTRL, sizeof(CLASS_CNTRL) - 1, - &format[offset])) - { - for (i = 0; i < MAX_CHARACTER_CLASS; i++) - if (iscntrl(i)) - characterclass[i]++; - offset += sizeof(CLASS_CNTRL) - 1; - } - else if (trio_equal_max(CLASS_DIGIT, sizeof(CLASS_DIGIT) - 1, - &format[offset])) - { - for (i = 0; i < MAX_CHARACTER_CLASS; i++) - if (isdigit(i)) - characterclass[i]++; - offset += sizeof(CLASS_DIGIT) - 1; - } - else if (trio_equal_max(CLASS_GRAPH, sizeof(CLASS_GRAPH) - 1, - &format[offset])) - { - for (i = 0; i < MAX_CHARACTER_CLASS; i++) - if (isgraph(i)) - characterclass[i]++; - offset += sizeof(CLASS_GRAPH) - 1; - } - else if (trio_equal_max(CLASS_LOWER, sizeof(CLASS_LOWER) - 1, - &format[offset])) - { - for (i = 0; i < MAX_CHARACTER_CLASS; i++) - if (islower(i)) - characterclass[i]++; - offset += sizeof(CLASS_LOWER) - 1; - } - else if (trio_equal_max(CLASS_PRINT, sizeof(CLASS_PRINT) - 1, - &format[offset])) - { - for (i = 0; i < MAX_CHARACTER_CLASS; i++) - if (isprint(i)) - characterclass[i]++; - offset += sizeof(CLASS_PRINT) - 1; - } - else if (trio_equal_max(CLASS_PUNCT, sizeof(CLASS_PUNCT) - 1, - &format[offset])) - { - for (i = 0; i < MAX_CHARACTER_CLASS; i++) - if (ispunct(i)) - characterclass[i]++; - offset += sizeof(CLASS_PUNCT) - 1; - } - else if (trio_equal_max(CLASS_SPACE, sizeof(CLASS_SPACE) - 1, - &format[offset])) - { - for (i = 0; i < MAX_CHARACTER_CLASS; i++) - if (isspace(i)) - characterclass[i]++; - offset += sizeof(CLASS_SPACE) - 1; - } - else if (trio_equal_max(CLASS_UPPER, sizeof(CLASS_UPPER) - 1, - &format[offset])) - { - for (i = 0; i < MAX_CHARACTER_CLASS; i++) - if (isupper(i)) - characterclass[i]++; - offset += sizeof(CLASS_UPPER) - 1; - } - else if (trio_equal_max(CLASS_XDIGIT, sizeof(CLASS_XDIGIT) - 1, - &format[offset])) - { - for (i = 0; i < MAX_CHARACTER_CLASS; i++) - if (isxdigit(i)) - characterclass[i]++; - offset += sizeof(CLASS_XDIGIT) - 1; - } - else - { - characterclass[(int)ch]++; - } - break; - - default: - characterclass[(int)ch]++; - break; - } - break; - -#endif /* TRIO_EXTENSION */ - - default: - characterclass[(int)ch]++; - break; - } - } - return 0; -} - -/************************************************************************* - * TrioReadNumber - * - * We implement our own number conversion in preference of strtol and - * strtoul, because we must handle 'long long' and thousand separators. - */ -TRIO_PRIVATE BOOLEAN_T -TrioReadNumber -TRIO_ARGS5((self, target, flags, width, base), - trio_class_t *self, - trio_uintmax_t *target, - trio_flags_t flags, - int width, - int base) -{ - trio_uintmax_t number = 0; - int digit; - int count; - BOOLEAN_T isNegative = FALSE; - BOOLEAN_T gotNumber = FALSE; - int j; - - assert(VALID(self)); - assert(VALID(self->InStream)); - assert((base >= MIN_BASE && base <= MAX_BASE) || (base == NO_BASE)); - - if (internalDigitsUnconverted) - { - /* Lazy evaluation of digits array */ - memset(internalDigitArray, -1, sizeof(internalDigitArray)); - for (j = 0; j < (int)sizeof(internalDigitsLower) - 1; j++) - { - internalDigitArray[(int)internalDigitsLower[j]] = j; - internalDigitArray[(int)internalDigitsUpper[j]] = j; - } - internalDigitsUnconverted = FALSE; - } - - TrioSkipWhitespaces(self); - - /* Leading sign */ - if (self->current == '+') - { - self->InStream(self, NULL); - } - else if (self->current == '-') - { - self->InStream(self, NULL); - isNegative = TRUE; - } - - count = self->processed; - - if (flags & FLAGS_ALTERNATIVE) - { - switch (base) - { - case NO_BASE: - case BASE_OCTAL: - case BASE_HEX: - case BASE_BINARY: - if (self->current == '0') - { - self->InStream(self, NULL); - if (self->current) - { - if ((base == BASE_HEX) && - (trio_to_upper(self->current) == 'X')) - { - self->InStream(self, NULL); - } - else if ((base == BASE_BINARY) && - (trio_to_upper(self->current) == 'B')) - { - self->InStream(self, NULL); - } - } - } - else - return FALSE; - break; - default: - break; - } - } - - while (((width == NO_WIDTH) || (self->processed - count < width)) && - (! ((self->current == EOF) || isspace(self->current)))) - { - if (isascii(self->current)) - { - digit = internalDigitArray[self->current]; - /* Abort if digit is not allowed in the specified base */ - if ((digit == -1) || (digit >= base)) - break; - } -#if TRIO_FEATURE_QUOTE - else if (flags & FLAGS_QUOTE) - { - /* Compare with thousands separator */ - for (j = 0; internalThousandSeparator[j] && self->current; j++) - { - if (internalThousandSeparator[j] != self->current) - break; - - self->InStream(self, NULL); - } - if (internalThousandSeparator[j]) - break; /* Mismatch */ - else - continue; /* Match */ - } -#endif - else - break; - - number *= base; - number += digit; - gotNumber = TRUE; /* we need at least one digit */ - - self->InStream(self, NULL); - } - - /* Was anything read at all? */ - if (!gotNumber) - return FALSE; - - if (target) - *target = (isNegative) ? (trio_uintmax_t)(-((trio_intmax_t)number)) : number; - return TRUE; -} - -/************************************************************************* - * TrioReadChar - */ -TRIO_PRIVATE int -TrioReadChar -TRIO_ARGS4((self, target, flags, width), - trio_class_t *self, - char *target, - trio_flags_t flags, - int width) -{ - int i; - char ch; - trio_uintmax_t number; - - assert(VALID(self)); - assert(VALID(self->InStream)); - - for (i = 0; - (self->current != EOF) && (i < width); - i++) - { - ch = (char)self->current; - self->InStream(self, NULL); - if ((flags & FLAGS_ALTERNATIVE) && (ch == CHAR_BACKSLASH)) - { - switch (self->current) - { - case '\\': ch = '\\'; break; - case 'a': ch = '\007'; break; - case 'b': ch = '\b'; break; - case 'f': ch = '\f'; break; - case 'n': ch = '\n'; break; - case 'r': ch = '\r'; break; - case 't': ch = '\t'; break; - case 'v': ch = '\v'; break; - default: - if (isdigit(self->current)) - { - /* Read octal number */ - if (!TrioReadNumber(self, &number, 0, 3, BASE_OCTAL)) - return 0; - ch = (char)number; - } - else if (trio_to_upper(self->current) == 'X') - { - /* Read hexadecimal number */ - self->InStream(self, NULL); - if (!TrioReadNumber(self, &number, 0, 2, BASE_HEX)) - return 0; - ch = (char)number; - } - else - { - ch = (char)self->current; - } - break; - } - } - - if (target) - target[i] = ch; - } - return i + 1; -} - -/************************************************************************* - * TrioReadString - */ -TRIO_PRIVATE BOOLEAN_T -TrioReadString -TRIO_ARGS4((self, target, flags, width), - trio_class_t *self, - char *target, - trio_flags_t flags, - int width) -{ - int i; - - assert(VALID(self)); - assert(VALID(self->InStream)); - - TrioSkipWhitespaces(self); - - /* - * Continue until end of string is reached, a whitespace is encountered, - * or width is exceeded - */ - for (i = 0; - ((width == NO_WIDTH) || (i < width)) && - (! ((self->current == EOF) || isspace(self->current))); - i++) - { - if (TrioReadChar(self, (target ? &target[i] : 0), flags, 1) == 0) - break; /* for */ - } - if (target) - target[i] = NIL; - return TRUE; -} - -/************************************************************************* - * TrioReadWideChar - */ -#if TRIO_FEATURE_WIDECHAR -TRIO_PRIVATE int -TrioReadWideChar -TRIO_ARGS4((self, target, flags, width), - trio_class_t *self, - trio_wchar_t *target, - trio_flags_t flags, - int width) -{ - int i; - int j; - int size; - int amount = 0; - trio_wchar_t wch; - char buffer[MB_LEN_MAX + 1]; - - assert(VALID(self)); - assert(VALID(self->InStream)); - - for (i = 0; - (self->current != EOF) && (i < width); - i++) - { - if (isascii(self->current)) - { - if (TrioReadChar(self, buffer, flags, 1) == 0) - return 0; - buffer[1] = NIL; - } - else - { - /* - * Collect a multibyte character, by enlarging buffer until - * it contains a fully legal multibyte character, or the - * buffer is full. - */ - j = 0; - do - { - buffer[j++] = (char)self->current; - buffer[j] = NIL; - self->InStream(self, NULL); - } - while ((j < (int)sizeof(buffer)) && (mblen(buffer, (size_t)j) != j)); - } - if (target) - { - size = mbtowc(&wch, buffer, sizeof(buffer)); - if (size > 0) - target[i] = wch; - } - amount += size; - self->InStream(self, NULL); - } - return amount; -} -#endif /* TRIO_FEATURE_WIDECHAR */ - -/************************************************************************* - * TrioReadWideString - */ -#if TRIO_FEATURE_WIDECHAR -TRIO_PRIVATE BOOLEAN_T -TrioReadWideString -TRIO_ARGS4((self, target, flags, width), - trio_class_t *self, - trio_wchar_t *target, - trio_flags_t flags, - int width) -{ - int i; - int size; - - assert(VALID(self)); - assert(VALID(self->InStream)); - - TrioSkipWhitespaces(self); - -#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE) - /* Required by TrioReadWideChar */ - (void)mblen(NULL, 0); -#endif - - /* - * Continue until end of string is reached, a whitespace is encountered, - * or width is exceeded - */ - for (i = 0; - ((width == NO_WIDTH) || (i < width)) && - (! ((self->current == EOF) || isspace(self->current))); - ) - { - size = TrioReadWideChar(self, &target[i], flags, 1); - if (size == 0) - break; /* for */ - - i += size; - } - if (target) - target[i] = WCONST('\0'); - return TRUE; -} -#endif /* TRIO_FEATURE_WIDECHAR */ - -/************************************************************************* - * TrioReadGroup - * - * Reads non-empty character groups. - * - * FIXME: characterclass does not work with multibyte characters - */ -TRIO_PRIVATE BOOLEAN_T -TrioReadGroup -TRIO_ARGS5((self, target, characterclass, flags, width), - trio_class_t *self, - char *target, - int *characterclass, - trio_flags_t flags, - int width) -{ - int ch; - int i; - - assert(VALID(self)); - assert(VALID(self->InStream)); - - ch = self->current; - for (i = 0; - ((width == NO_WIDTH) || (i < width)) && - (! ((ch == EOF) || - (((flags & FLAGS_EXCLUDE) != 0) ^ (characterclass[ch] == 0)))); - i++) - { - if (target) - target[i] = (char)ch; - self->InStream(self, &ch); - } - - if (i == 0) - return FALSE; - - /* Terminate the string if input saved */ - if (target) - target[i] = NIL; - return TRUE; -} - -/************************************************************************* - * TrioReadDouble - * - * FIXME: - * add long double - * handle base - */ -#if TRIO_FEATURE_FLOAT -TRIO_PRIVATE BOOLEAN_T -TrioReadDouble -TRIO_ARGS4((self, target, flags, width), - trio_class_t *self, - trio_pointer_t target, - trio_flags_t flags, - int width) -{ - int ch; - char doubleString[512]; - int offset = 0; - int start; -# if TRIO_FEATURE_QUOTE - int j; -# endif - BOOLEAN_T isHex = FALSE; - trio_long_double_t infinity; - - doubleString[0] = 0; - - if ((width == NO_WIDTH) || (width > (int)sizeof(doubleString) - 1)) - width = sizeof(doubleString) - 1; - - TrioSkipWhitespaces(self); - - /* - * Read entire double number from stream. trio_to_double requires - * a string as input, but InStream can be anything, so we have to - * collect all characters. - */ - ch = self->current; - if ((ch == '+') || (ch == '-')) - { - doubleString[offset++] = (char)ch; - self->InStream(self, &ch); - width--; - } - - start = offset; - switch (ch) - { - case 'n': - case 'N': - /* Not-a-number */ - if (offset != 0) - break; - /* FALLTHROUGH */ - case 'i': - case 'I': - /* Infinity */ - while (isalpha(ch) && (offset - start < width)) - { - doubleString[offset++] = (char)ch; - self->InStream(self, &ch); - } - doubleString[offset] = NIL; - - /* Case insensitive string comparison */ - if (trio_equal(&doubleString[start], INFINITE_UPPER) || - trio_equal(&doubleString[start], LONG_INFINITE_UPPER)) - { - infinity = ((start == 1) && (doubleString[0] == '-')) - ? trio_ninf() - : trio_pinf(); - if (flags & FLAGS_LONGDOUBLE) - { - *((trio_long_double_t *)target) = infinity; - } - else if (flags & FLAGS_LONG) - { - *((double *)target) = infinity; - } - else - { - *((float *)target) = infinity; - } - return TRUE; - } - if (trio_equal(doubleString, NAN_UPPER)) - { - /* NaN must not have a preceeding + nor - */ - if (flags & FLAGS_LONGDOUBLE) - { - *((trio_long_double_t *)target) = trio_nan(); - } - else if (flags & FLAGS_LONG) - { - *((double *)target) = trio_nan(); - } - else - { - *((float *)target) = trio_nan(); - } - return TRUE; - } - return FALSE; - - case '0': - doubleString[offset++] = (char)ch; - self->InStream(self, &ch); - if (trio_to_upper(ch) == 'X') - { - isHex = TRUE; - doubleString[offset++] = (char)ch; - self->InStream(self, &ch); - } - break; - - default: - break; - } - - while ((ch != EOF) && (offset - start < width)) - { - /* Integer part */ - if (isHex ? isxdigit(ch) : isdigit(ch)) - { - doubleString[offset++] = (char)ch; - self->InStream(self, &ch); - } -# if TRIO_FEATURE_QUOTE - else if (flags & FLAGS_QUOTE) - { - /* Compare with thousands separator */ - for (j = 0; internalThousandSeparator[j] && self->current; j++) - { - if (internalThousandSeparator[j] != self->current) - break; - - self->InStream(self, &ch); - } - if (internalThousandSeparator[j]) - break; /* Mismatch */ - else - continue; /* Match */ - } -# endif - else - break; /* while */ - } - if (ch == '.') - { - /* Decimal part */ - doubleString[offset++] = (char)ch; - self->InStream(self, &ch); - while ((isHex ? isxdigit(ch) : isdigit(ch)) && - (offset - start < width)) - { - doubleString[offset++] = (char)ch; - self->InStream(self, &ch); - } - } - if (isHex ? (trio_to_upper(ch) == 'P') : (trio_to_upper(ch) == 'E')) - { - /* Exponent */ - doubleString[offset++] = (char)ch; - self->InStream(self, &ch); - if ((ch == '+') || (ch == '-')) - { - doubleString[offset++] = (char)ch; - self->InStream(self, &ch); - } - while (isdigit(ch) && (offset - start < width)) - { - doubleString[offset++] = (char)ch; - self->InStream(self, &ch); - } - } - - if ((offset == start) || (*doubleString == NIL)) - return FALSE; - - doubleString[offset] = 0; - - if (flags & FLAGS_LONGDOUBLE) - { - *((trio_long_double_t *)target) = trio_to_long_double(doubleString, NULL); - } - else if (flags & FLAGS_LONG) - { - *((double *)target) = trio_to_double(doubleString, NULL); - } - else - { - *((float *)target) = trio_to_float(doubleString, NULL); - } - return TRUE; -} -#endif /* TRIO_FEATURE_FLOAT */ - -/************************************************************************* - * TrioReadPointer - */ -TRIO_PRIVATE BOOLEAN_T -TrioReadPointer -TRIO_ARGS3((self, target, flags), - trio_class_t *self, - trio_pointer_t *target, - trio_flags_t flags) -{ - trio_uintmax_t number; - char buffer[sizeof(internalNullString)]; - - flags |= (FLAGS_UNSIGNED | FLAGS_ALTERNATIVE | FLAGS_NILPADDING); - - if (TrioReadNumber(self, - &number, - flags, - POINTER_WIDTH, - BASE_HEX)) - { - if (target) - { -#if defined(TRIO_COMPILER_GCC) || defined(TRIO_COMPILER_MIPSPRO) - /* - * The strange assignment of number is a workaround for a compiler - * warning - */ - *target = &((char *)0)[number]; -#else - *target = (trio_pointer_t)number; -#endif - } - return TRUE; - } - else if (TrioReadString(self, - (flags & FLAGS_IGNORE) - ? NULL - : buffer, - 0, - sizeof(internalNullString) - 1)) - { - if (trio_equal_case(buffer, internalNullString)) - { - if (target) - *target = NULL; - return TRUE; - } - } - return FALSE; -} - -/************************************************************************* - * TrioScanProcess - */ -TRIO_PRIVATE int -TrioScanProcess -TRIO_ARGS3((data, format, parameters), - trio_class_t *data, - TRIO_CONST char *format, - trio_parameter_t *parameters) -{ - int status; - int assignment; - int ch; - int offset; /* Offset of format string */ - int i; /* Offset of current parameter */ - trio_flags_t flags; - int width; - int base; - trio_pointer_t pointer; - - /* Return on empty format string */ - if (format[0] == NIL) - return 0; - - status = 0; - assignment = 0; - i = 0; - offset = 0; - data->InStream(data, &ch); - - for (;;) - { - /* Skip the parameter entries */ - while (parameters[i].type == FORMAT_PARAMETER) - { - assert(i <= MAX_PARAMETERS); - i++; - } - - /* Compare non conversion-specifier part of format string */ - while (offset < parameters[i].beginOffset) - { - if ((CHAR_IDENTIFIER == format[offset]) && - (CHAR_IDENTIFIER == format[offset + 1])) - { - /* Two % in format matches one % in input stream */ - if (CHAR_IDENTIFIER == ch) - { - data->InStream(data, &ch); - offset += 2; - continue; /* while format chars left */ - } - else - { - status = TRIO_ERROR_RETURN(TRIO_EINVAL, offset); - goto end; - } - } - else /* Not an % identifier */ - { - if (isspace((int)format[offset])) - { - /* Whitespaces may match any amount of whitespaces */ - ch = TrioSkipWhitespaces(data); - } - else if (ch == format[offset]) - { - data->InStream(data, &ch); - } - else - { - status = assignment; - goto end; - } - - offset++; - } - } - - if (parameters[i].type == FORMAT_SENTINEL) - break; - - if ((EOF == ch) && (parameters[i].type != FORMAT_COUNT)) - { - status = (assignment > 0) ? assignment : EOF; - goto end; - } - - flags = parameters[i].flags; - - /* Find width */ - width = parameters[i].width; - if (flags & FLAGS_WIDTH_PARAMETER) - { - /* Get width from parameter list */ - width = (int)parameters[width].data.number.as_signed; - } - - /* Find base */ - if (NO_BASE != parameters[i].baseSpecifier) - { - /* Base from specifier has priority */ - base = parameters[i].baseSpecifier; - } - else if (flags & FLAGS_BASE_PARAMETER) - { - /* Get base from parameter list */ - base = parameters[i].base; - base = (int)parameters[base].data.number.as_signed; - } - else - { - /* Use base from format string */ - base = parameters[i].base; - } - - switch (parameters[i].type) - { - case FORMAT_INT: - { - trio_uintmax_t number; - - if (0 == base) - base = BASE_DECIMAL; - - if (!TrioReadNumber(data, - &number, - flags, - width, - base)) - { - status = assignment; - goto end; - } - - if (!(flags & FLAGS_IGNORE)) - { - assignment++; - - pointer = parameters[i].data.pointer; -#if TRIO_FEATURE_SIZE_T || TRIO_FEATURE_SIZE_T_UPPER - if (flags & FLAGS_SIZE_T) - *(size_t *)pointer = (size_t)number; - else -#endif -#if TRIO_FEATURE_PTRDIFF_T - if (flags & FLAGS_PTRDIFF_T) - *(ptrdiff_t *)pointer = (ptrdiff_t)number; - else -#endif -#if TRIO_FEATURE_INTMAX_T - if (flags & FLAGS_INTMAX_T) - *(trio_intmax_t *)pointer = (trio_intmax_t)number; - else -#endif - if (flags & FLAGS_QUAD) - *(trio_ulonglong_t *)pointer = (trio_ulonglong_t)number; - else if (flags & FLAGS_LONG) - *(long int *)pointer = (long int)number; - else if (flags & FLAGS_SHORT) - *(short int *)pointer = (short int)number; - else - *(int *)pointer = (int)number; - } - } - break; /* FORMAT_INT */ - - case FORMAT_STRING: -#if TRIO_FEATURE_WIDECHAR - if (flags & FLAGS_WIDECHAR) - { - if (!TrioReadWideString(data, - (flags & FLAGS_IGNORE) - ? NULL - : parameters[i].data.wstring, - flags, - width)) - { - status = assignment; - goto end; - } - } - else -#endif - { - if (!TrioReadString(data, - (flags & FLAGS_IGNORE) - ? NULL - : parameters[i].data.string, - flags, - width)) - { - status = assignment; - goto end; - } - } - if (!(flags & FLAGS_IGNORE)) - assignment++; - break; /* FORMAT_STRING */ - -#if TRIO_FEATURE_FLOAT - case FORMAT_DOUBLE: - { - if (flags & FLAGS_IGNORE) - { - pointer = NULL; - } - else - { - pointer = (flags & FLAGS_LONGDOUBLE) - ? (trio_pointer_t)parameters[i].data.longdoublePointer - : (trio_pointer_t)parameters[i].data.doublePointer; - } - if (!TrioReadDouble(data, pointer, flags, width)) - { - status = assignment; - goto end; - } - if (!(flags & FLAGS_IGNORE)) - { - assignment++; - } - break; /* FORMAT_DOUBLE */ - } -#endif - - case FORMAT_GROUP: - { - int characterclass[MAX_CHARACTER_CLASS + 1]; - - /* Skip over modifiers */ - while (format[offset] != SPECIFIER_GROUP) - { - offset++; - } - /* Skip over group specifier */ - offset++; - - memset(characterclass, 0, sizeof(characterclass)); - status = TrioGetCharacterClass(format, - &offset, - &flags, - characterclass); - if (status < 0) - goto end; - - if (!TrioReadGroup(data, - (flags & FLAGS_IGNORE) - ? NULL - : parameters[i].data.string, - characterclass, - flags, - parameters[i].width)) - { - status = assignment; - goto end; - } - if (!(flags & FLAGS_IGNORE)) - assignment++; - } - break; /* FORMAT_GROUP */ - - case FORMAT_COUNT: - pointer = parameters[i].data.pointer; - if (NULL != pointer) - { - int count = data->processed; - if (ch != EOF) - count--; /* a character is read, but is not consumed yet */ -#if TRIO_FEATURE_SIZE_T || TRIO_FEATURE_SIZE_T_UPPER - if (flags & FLAGS_SIZE_T) - *(size_t *)pointer = (size_t)count; - else -#endif -#if TRIO_FEATURE_PTRDIFF_T - if (flags & FLAGS_PTRDIFF_T) - *(ptrdiff_t *)pointer = (ptrdiff_t)count; - else -#endif -#if TRIO_FEATURE_INTMAX_T - if (flags & FLAGS_INTMAX_T) - *(trio_intmax_t *)pointer = (trio_intmax_t)count; - else -#endif - if (flags & FLAGS_QUAD) - { - *(trio_ulonglong_t *)pointer = (trio_ulonglong_t)count; - } - else if (flags & FLAGS_LONG) - { - *(long int *)pointer = (long int)count; - } - else if (flags & FLAGS_SHORT) - { - *(short int *)pointer = (short int)count; - } - else - { - *(int *)pointer = (int)count; - } - } - break; /* FORMAT_COUNT */ - - case FORMAT_CHAR: -#if TRIO_FEATURE_WIDECHAR - if (flags & FLAGS_WIDECHAR) - { - if (TrioReadWideChar(data, - (flags & FLAGS_IGNORE) - ? NULL - : parameters[i].data.wstring, - flags, - (width == NO_WIDTH) ? 1 : width) == 0) - { - status = assignment; - goto end; - } - } - else -#endif - { - if (TrioReadChar(data, - (flags & FLAGS_IGNORE) - ? NULL - : parameters[i].data.string, - flags, - (width == NO_WIDTH) ? 1 : width) == 0) - { - status = assignment; - goto end; - } - } - if (!(flags & FLAGS_IGNORE)) - assignment++; - break; /* FORMAT_CHAR */ - - case FORMAT_POINTER: - if (!TrioReadPointer(data, - (flags & FLAGS_IGNORE) - ? NULL - : (trio_pointer_t *)parameters[i].data.pointer, - flags)) - { - status = assignment; - goto end; - } - if (!(flags & FLAGS_IGNORE)) - assignment++; - break; /* FORMAT_POINTER */ - - case FORMAT_PARAMETER: - break; /* FORMAT_PARAMETER */ - - default: - status = TRIO_ERROR_RETURN(TRIO_EINVAL, offset); - goto end; - } - - ch = data->current; - offset = parameters[i].endOffset; - i++; - } - - status = assignment; - end: - if (data->UndoStream) - data->UndoStream(data); - return status; -} - -/************************************************************************* - * TrioScan - */ -TRIO_PRIVATE int -TrioScan -TRIO_ARGS8((source, sourceSize, InStream, UndoStream, format, arglist, argfunc, argarray), - trio_pointer_t source, - size_t sourceSize, - void (*InStream) TRIO_PROTO((trio_class_t *, int *)), - void (*UndoStream) TRIO_PROTO((trio_class_t *)), - TRIO_CONST char *format, - va_list arglist, - trio_argfunc_t argfunc, - trio_pointer_t *argarray) -{ - int status; - trio_parameter_t parameters[MAX_PARAMETERS]; - trio_class_t data; - - assert(VALID(InStream)); - assert(VALID(format)); - - memset(&data, 0, sizeof(data)); - data.InStream = InStream; - data.UndoStream = UndoStream; - data.location = (trio_pointer_t)source; - data.max = sourceSize; - data.error = 0; - -#if defined(USE_LOCALE) - if (NULL == internalLocaleValues) - { - TrioSetLocale(); - } -#endif - - status = TrioParse(TYPE_SCAN, format, parameters, arglist, argfunc, argarray); - if (status < 0) - return status; - - status = TrioScanProcess(&data, format, parameters); - if (data.error != 0) - { - status = data.error; - } - return status; -} - -/************************************************************************* - * TrioInStreamFile - */ -#if TRIO_FEATURE_FILE || TRIO_FEATURE_STDIO -TRIO_PRIVATE void -TrioInStreamFile -TRIO_ARGS2((self, intPointer), - trio_class_t *self, - int *intPointer) -{ - FILE *file = (FILE *)self->location; - - assert(VALID(self)); - assert(VALID(file)); - - self->actually.cached = 0; - - /* The initial value of self->current is zero */ - if (self->current == EOF) - { - self->error = (ferror(file)) - ? TRIO_ERROR_RETURN(TRIO_ERRNO, 0) - : TRIO_ERROR_RETURN(TRIO_EOF, 0); - } - else - { - self->processed++; - self->actually.cached++; - } - - self->current = fgetc(file); - - if (VALID(intPointer)) - { - *intPointer = self->current; - } -} -#endif /* TRIO_FEATURE_FILE || TRIO_FEATURE_STDIO */ - -/************************************************************************* - * TrioUndoStreamFile - */ -#if TRIO_FEATURE_FILE || TRIO_FEATURE_STDIO -TRIO_PRIVATE void -TrioUndoStreamFile -TRIO_ARGS1((self), - trio_class_t *self) -{ - FILE *file = (FILE *)self->location; - - assert(VALID(self)); - assert(VALID(file)); - - if (self->actually.cached > 0) - { - assert(self->actually.cached == 1); - - self->current = ungetc(self->current, file); - self->actually.cached = 0; - } -} -#endif /* TRIO_FEATURE_FILE || TRIO_FEATURE_STDIO */ - -/************************************************************************* - * TrioInStreamFileDescriptor - */ -#if TRIO_FEATURE_FD -TRIO_PRIVATE void -TrioInStreamFileDescriptor -TRIO_ARGS2((self, intPointer), - trio_class_t *self, - int *intPointer) -{ - int fd = *((int *)self->location); - int size; - unsigned char input; - - assert(VALID(self)); - - self->actually.cached = 0; - - size = read(fd, &input, sizeof(char)); - if (size == -1) - { - self->error = TRIO_ERROR_RETURN(TRIO_ERRNO, 0); - self->current = EOF; - } - else - { - self->current = (size == 0) ? EOF : input; - } - if (self->current != EOF) - { - self->actually.cached++; - self->processed++; - } - - if (VALID(intPointer)) - { - *intPointer = self->current; - } -} -#endif /* TRIO_FEATURE_FD */ - -/************************************************************************* - * TrioInStreamCustom - */ -#if TRIO_FEATURE_CLOSURE -TRIO_PRIVATE void -TrioInStreamCustom -TRIO_ARGS2((self, intPointer), - trio_class_t *self, - int *intPointer) -{ - trio_custom_t *data; - - assert(VALID(self)); - assert(VALID(self->location)); - - self->actually.cached = 0; - - data = (trio_custom_t *)self->location; - - self->current = (data->stream.in == NULL) - ? NIL - : (data->stream.in)(data->closure); - - if (self->current == NIL) - { - self->current = EOF; - } - else - { - self->processed++; - self->actually.cached++; - } - - if (VALID(intPointer)) - { - *intPointer = self->current; - } -} -#endif /* TRIO_FEATURE_CLOSURE */ - -/************************************************************************* - * TrioInStreamString - */ -TRIO_PRIVATE void -TrioInStreamString -TRIO_ARGS2((self, intPointer), - trio_class_t *self, - int *intPointer) -{ - unsigned char **buffer; - - assert(VALID(self)); - assert(VALID(self->location)); - - self->actually.cached = 0; - - buffer = (unsigned char **)self->location; - self->current = (*buffer)[0]; - if (self->current == NIL) - { - self->current = EOF; - } - else - { - (*buffer)++; - self->processed++; - self->actually.cached++; - } - - if (VALID(intPointer)) - { - *intPointer = self->current; - } -} - -/************************************************************************* - * - * Formatted scanning functions - * - ************************************************************************/ - -#if defined(TRIO_DOCUMENTATION) -# include "doc/doc_scanf.h" -#endif -/** @addtogroup Scanf - @{ -*/ - -/************************************************************************* - * scanf - */ - -/** - Scan characters from standard input stream. - - @param format Formatting string. - @param ... Arguments. - @return Number of scanned characters. - */ -#if TRIO_FEATURE_STDIO -TRIO_PUBLIC int -trio_scanf -TRIO_VARGS2((format, va_alist), - TRIO_CONST char *format, - TRIO_VA_DECL) -{ - int status; - va_list args; - - assert(VALID(format)); - - TRIO_VA_START(args, format); - status = TrioScan((trio_pointer_t)stdin, 0, - TrioInStreamFile, - TrioUndoStreamFile, - format, args, NULL, NULL); - TRIO_VA_END(args); - return status; -} -#endif /* TRIO_FEATURE_STDIO */ - -/** - Scan characters from standard input stream. - - @param format Formatting string. - @param args Arguments. - @return Number of scanned characters. - */ -#if TRIO_FEATURE_STDIO -TRIO_PUBLIC int -trio_vscanf -TRIO_ARGS2((format, args), - TRIO_CONST char *format, - va_list args) -{ - assert(VALID(format)); - - return TrioScan((trio_pointer_t)stdin, 0, - TrioInStreamFile, - TrioUndoStreamFile, - format, args, NULL, NULL); -} -#endif /* TRIO_FEATURE_STDIO */ - -/** - Scan characters from standard input stream. - - @param format Formatting string. - @param args Arguments. - @return Number of scanned characters. - */ -#if TRIO_FEATURE_STDIO -TRIO_PUBLIC int -trio_scanfv -TRIO_ARGS2((format, args), - TRIO_CONST char *format, - trio_pointer_t *args) -{ - static va_list unused; - - assert(VALID(format)); - - return TrioScan((trio_pointer_t)stdin, 0, - TrioInStreamFile, - TrioUndoStreamFile, - format, - unused, TrioArrayGetter, args); -} -#endif /* TRIO_FEATURE_STDIO */ - -/************************************************************************* - * fscanf - */ - -/** - Scan characters from file. - - @param file File pointer. - @param format Formatting string. - @param ... Arguments. - @return Number of scanned characters. - */ -#if TRIO_FEATURE_FILE -TRIO_PUBLIC int -trio_fscanf -TRIO_VARGS3((file, format, va_alist), - FILE *file, - TRIO_CONST char *format, - TRIO_VA_DECL) -{ - int status; - va_list args; - - assert(VALID(file)); - assert(VALID(format)); - - TRIO_VA_START(args, format); - status = TrioScan((trio_pointer_t)file, 0, - TrioInStreamFile, - TrioUndoStreamFile, - format, args, NULL, NULL); - TRIO_VA_END(args); - return status; -} -#endif /* TRIO_FEATURE_FILE */ - -/** - Scan characters from file. - - @param file File pointer. - @param format Formatting string. - @param args Arguments. - @return Number of scanned characters. - */ -#if TRIO_FEATURE_FILE -TRIO_PUBLIC int -trio_vfscanf -TRIO_ARGS3((file, format, args), - FILE *file, - TRIO_CONST char *format, - va_list args) -{ - assert(VALID(file)); - assert(VALID(format)); - - return TrioScan((trio_pointer_t)file, 0, - TrioInStreamFile, - TrioUndoStreamFile, - format, args, NULL, NULL); -} -#endif /* TRIO_FEATURE_FILE */ - -/** - Scan characters from file. - - @param file File pointer. - @param format Formatting string. - @param args Arguments. - @return Number of scanned characters. - */ -#if TRIO_FEATURE_FILE -TRIO_PUBLIC int -trio_fscanfv -TRIO_ARGS3((file, format, args), - FILE *file, - TRIO_CONST char *format, - trio_pointer_t *args) -{ - static va_list unused; - - assert(VALID(file)); - assert(VALID(format)); - - return TrioScan((trio_pointer_t)file, 0, - TrioInStreamFile, - TrioUndoStreamFile, - format, - unused, TrioArrayGetter, args); -} -#endif /* TRIO_FEATURE_FILE */ - -/************************************************************************* - * dscanf - */ - -/** - Scan characters from file descriptor. - - @param fd File descriptor. - @param format Formatting string. - @param ... Arguments. - @return Number of scanned characters. - */ -#if TRIO_FEATURE_FD -TRIO_PUBLIC int -trio_dscanf -TRIO_VARGS3((fd, format, va_alist), - int fd, - TRIO_CONST char *format, - TRIO_VA_DECL) -{ - int status; - va_list args; - - assert(VALID(format)); - - TRIO_VA_START(args, format); - status = TrioScan((trio_pointer_t)&fd, 0, - TrioInStreamFileDescriptor, - NULL, - format, args, NULL, NULL); - TRIO_VA_END(args); - return status; -} -#endif /* TRIO_FEATURE_FD */ - -/** - Scan characters from file descriptor. - - @param fd File descriptor. - @param format Formatting string. - @param args Arguments. - @return Number of scanned characters. - */ -#if TRIO_FEATURE_FD -TRIO_PUBLIC int -trio_vdscanf -TRIO_ARGS3((fd, format, args), - int fd, - TRIO_CONST char *format, - va_list args) -{ - assert(VALID(format)); - - return TrioScan((trio_pointer_t)&fd, 0, - TrioInStreamFileDescriptor, - NULL, - format, args, NULL, NULL); -} -#endif /* TRIO_FEATURE_FD */ - -/** - Scan characters from file descriptor. - - @param fd File descriptor. - @param format Formatting string. - @param args Arguments. - @return Number of scanned characters. - */ -#if TRIO_FEATURE_FD -TRIO_PUBLIC int -trio_dscanfv -TRIO_ARGS3((fd, format, args), - int fd, - TRIO_CONST char *format, - trio_pointer_t *args) -{ - static va_list unused; - - assert(VALID(format)); - - return TrioScan((trio_pointer_t)&fd, 0, - TrioInStreamFileDescriptor, - NULL, - format, - unused, TrioArrayGetter, args); -} -#endif /* TRIO_FEATURE_FD */ - -/************************************************************************* - * cscanf - */ -#if TRIO_FEATURE_CLOSURE -TRIO_PUBLIC int -trio_cscanf -TRIO_VARGS4((stream, closure, format, va_alist), - trio_instream_t stream, - trio_pointer_t closure, - TRIO_CONST char *format, - TRIO_VA_DECL) -{ - int status; - va_list args; - trio_custom_t data; - - assert(VALID(stream)); - assert(VALID(format)); - - TRIO_VA_START(args, format); - data.stream.in = stream; - data.closure = closure; - status = TrioScan(&data, 0, TrioInStreamCustom, NULL, format, args, NULL, NULL); - TRIO_VA_END(args); - return status; -} -#endif /* TRIO_FEATURE_CLOSURE */ - -#if TRIO_FEATURE_CLOSURE -TRIO_PUBLIC int -trio_vcscanf -TRIO_ARGS4((stream, closure, format, args), - trio_instream_t stream, - trio_pointer_t closure, - TRIO_CONST char *format, - va_list args) -{ - trio_custom_t data; - - assert(VALID(stream)); - assert(VALID(format)); - - data.stream.in = stream; - data.closure = closure; - return TrioScan(&data, 0, TrioInStreamCustom, NULL, format, args, NULL, NULL); -} -#endif /* TRIO_FEATURE_CLOSURE */ - -#if TRIO_FEATURE_CLOSURE -TRIO_PUBLIC int -trio_cscanfv -TRIO_ARGS4((stream, closure, format, args), - trio_instream_t stream, - trio_pointer_t closure, - TRIO_CONST char *format, - trio_pointer_t *args) -{ - static va_list unused; - trio_custom_t data; - - assert(VALID(stream)); - assert(VALID(format)); - - data.stream.in = stream; - data.closure = closure; - return TrioScan(&data, 0, TrioInStreamCustom, NULL, format, - unused, TrioArrayGetter, args); -} -#endif /* TRIO_FEATURE_CLOSURE */ - -#if TRIO_FEATURE_CLOSURE && TRIO_FEATURE_ARGFUNC -TRIO_PUBLIC int -trio_cscanff -TRIO_ARGS5((stream, closure, format, argfunc, context), - trio_instream_t stream, - trio_pointer_t closure, - TRIO_CONST char *format, - trio_argfunc_t argfunc, - trio_pointer_t context) -{ - static va_list unused; - trio_custom_t data; - - assert(VALID(stream)); - assert(VALID(format)); - assert(VALID(argfunc)); - - data.stream.in = stream; - data.closure = closure; - return TrioScan(&data, 0, TrioInStreamCustom, NULL, format, - unused, argfunc, (trio_pointer_t *)context); -} -#endif /* TRIO_FEATURE_CLOSURE && TRIO_FEATURE_ARGFUNC */ - -/************************************************************************* - * sscanf - */ - -/** - Scan characters from string. - - @param buffer Input string. - @param format Formatting string. - @param ... Arguments. - @return Number of scanned characters. - */ -TRIO_PUBLIC int -trio_sscanf -TRIO_VARGS3((buffer, format, va_alist), - TRIO_CONST char *buffer, - TRIO_CONST char *format, - TRIO_VA_DECL) -{ - int status; - va_list args; - - assert(VALID(buffer)); - assert(VALID(format)); - - TRIO_VA_START(args, format); - status = TrioScan((trio_pointer_t)&buffer, 0, - TrioInStreamString, - NULL, - format, args, NULL, NULL); - TRIO_VA_END(args); - return status; -} - -/** - Scan characters from string. - - @param buffer Input string. - @param format Formatting string. - @param args Arguments. - @return Number of scanned characters. - */ -TRIO_PUBLIC int -trio_vsscanf -TRIO_ARGS3((buffer, format, args), - TRIO_CONST char *buffer, - TRIO_CONST char *format, - va_list args) -{ - assert(VALID(buffer)); - assert(VALID(format)); - - return TrioScan((trio_pointer_t)&buffer, 0, - TrioInStreamString, - NULL, - format, args, NULL, NULL); -} - -/** - Scan characters from string. - - @param buffer Input string. - @param format Formatting string. - @param args Arguments. - @return Number of scanned characters. - */ -TRIO_PUBLIC int -trio_sscanfv -TRIO_ARGS3((buffer, format, args), - TRIO_CONST char *buffer, - TRIO_CONST char *format, - trio_pointer_t *args) -{ - static va_list unused; - - assert(VALID(buffer)); - assert(VALID(format)); - - return TrioScan((trio_pointer_t)&buffer, 0, - TrioInStreamString, - NULL, - format, - unused, TrioArrayGetter, args); -} - -#endif /* TRIO_FEATURE_SCANF */ - -/** @} End of Scanf documentation module */ - -/************************************************************************* - * trio_strerror - */ -TRIO_PUBLIC TRIO_CONST char * -trio_strerror -TRIO_ARGS1((errorcode), - int errorcode) -{ -#if TRIO_FEATURE_STRERR - /* Textual versions of the error codes */ - switch (TRIO_ERROR_CODE(errorcode)) - { - case TRIO_EOF: - return "End of file"; - case TRIO_EINVAL: - return "Invalid argument"; - case TRIO_ETOOMANY: - return "Too many arguments"; - case TRIO_EDBLREF: - return "Double reference"; - case TRIO_EGAP: - return "Reference gap"; - case TRIO_ENOMEM: - return "Out of memory"; - case TRIO_ERANGE: - return "Invalid range"; - case TRIO_ECUSTOM: - return "Custom error"; - default: - return "Unknown"; - } -#else - return "Unknown"; -#endif -} diff --git a/psx/mednadisc/trio/trio.h b/psx/mednadisc/trio/trio.h deleted file mode 100644 index 6bb74b1d4ce..00000000000 --- a/psx/mednadisc/trio/trio.h +++ /dev/null @@ -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 -#endif - -#include "triop.h" - -#include - -#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 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 */ diff --git a/psx/mednadisc/trio/triodef.h b/psx/mednadisc/trio/triodef.h deleted file mode 100644 index 7a77b4a8b9b..00000000000 --- a/psx/mednadisc/trio/triodef.h +++ /dev/null @@ -1,375 +0,0 @@ -/************************************************************************* - * - * $Id$ - * - * Copyright (C) 2001 Bjorn Reese - * - * 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 -#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 -# 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 */ diff --git a/psx/mednadisc/trio/trionan.c b/psx/mednadisc/trio/trionan.c deleted file mode 100644 index e3bae34816c..00000000000 --- a/psx/mednadisc/trio/trionan.c +++ /dev/null @@ -1,1318 +0,0 @@ -/************************************************************************* - * - * $Id$ - * - * Copyright (C) 2001 Bjorn Reese - * - * 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. - * - ************************************************************************ - * - * Functions to handle special quantities in floating-point numbers - * (that is, NaNs and infinity). They provide the capability to detect - * and fabricate special quantities. - * - * Although written to be as portable as possible, it can never be - * guaranteed to work on all platforms, as not all hardware supports - * special quantities. - * - * The approach used here (approximately) is to: - * - * 1. Use C99 functionality when available. - * 2. Use IEEE 754 bit-patterns if possible. - * 3. Use platform-specific techniques. - * - ************************************************************************/ - -/************************************************************************* - * Include files - */ -#include "triodef.h" -#include "trionan.h" - -#include -#include -#include -#if !defined(TRIO_PLATFORM_SYMBIAN) -# include -#endif -#if defined(TRIO_PLATFORM_UNIX) -# include -#endif -#if defined(TRIO_COMPILER_DECC) -# include -#endif -#include - -#if defined(TRIO_DOCUMENTATION) -# include "doc/doc_nan.h" -#endif -/** @addtogroup SpecialQuantities - @{ -*/ - -/************************************************************************* - * Definitions - */ - -#if !defined(TRIO_PUBLIC_NAN) -# define TRIO_PUBLIC_NAN TRIO_PUBLIC -#endif -#if !defined(TRIO_PRIVATE_NAN) -# define TRIO_PRIVATE_NAN TRIO_PRIVATE -#endif - -#define TRIO_TRUE (1 == 1) -#define TRIO_FALSE (0 == 1) - -/* - * We must enable IEEE floating-point on Alpha - */ -#if defined(__alpha) && !defined(_IEEE_FP) -# if defined(TRIO_COMPILER_DECC) -# if defined(TRIO_PLATFORM_VMS) -# error "Must be compiled with option /IEEE_MODE=UNDERFLOW_TO_ZERO/FLOAT=IEEE" -# else -# if !defined(_CFE) -# error "Must be compiled with option -ieee" -# endif -# endif -# else -# if defined(TRIO_COMPILER_GCC) -# error "Must be compiled with option -mieee" -# endif -# endif -#endif /* __alpha && ! _IEEE_FP */ - -/* - * In ANSI/IEEE 754-1985 64-bits double format numbers have the - * following properties (amoungst others) - * - * o FLT_RADIX == 2: binary encoding - * o DBL_MAX_EXP == 1024: 11 bits exponent, where one bit is used - * to indicate special numbers (e.g. NaN and Infinity), so the - * maximum exponent is 10 bits wide (2^10 == 1024). - * o DBL_MANT_DIG == 53: The mantissa is 52 bits wide, but because - * numbers are normalized the initial binary 1 is represented - * implicitly (the so-called "hidden bit"), which leaves us with - * the ability to represent 53 bits wide mantissa. - */ -#if defined(__STDC_IEC_559__) -# define TRIO_IEEE_754 -#else -# if (FLT_RADIX - 0 == 2) && (DBL_MAX_EXP - 0 == 1024) && (DBL_MANT_DIG - 0 == 53) -# define TRIO_IEEE_754 -# endif -#endif - -/* - * Determine which fpclassify_and_sign() function to use. - */ -#if defined(TRIO_FUNC_FPCLASSIFY_AND_SIGNBIT) -# if defined(PREDEF_STANDARD_C99) && defined(fpclassify) -# define TRIO_FUNC_C99_FPCLASSIFY_AND_SIGNBIT -# else -# if defined(TRIO_COMPILER_DECC) -# define TRIO_FUNC_DECC_FPCLASSIFY_AND_SIGNBIT -# else -# if defined(TRIO_COMPILER_VISUALC) || defined(TRIO_COMPILER_BORLAND) -# define TRIO_FUNC_MS_FPCLASSIFY_AND_SIGNBIT -# else -# if defined(TRIO_COMPILER_HP) && defined(FP_PLUS_NORM) -# define TRIO_FUNC_HP_FPCLASSIFY_AND_SIGNBIT -# else -# if defined(TRIO_COMPILER_XLC) && defined(FP_PLUS_NORM) -# define TRIO_FUNC_XLC_FPCLASSIFY_AND_SIGNBIT -# else -# define TRIO_FUNC_INTERNAL_FPCLASSIFY_AND_SIGNBIT -# endif -# endif -# endif -# endif -# endif -#endif - -/* - * Determine how to generate negative zero. - */ -#if defined(TRIO_FUNC_NZERO) -# if defined(TRIO_IEEE_754) -# define TRIO_NZERO_IEEE_754 -# else -# define TRIO_NZERO_FALLBACK -# endif -#endif - -/* - * Determine how to generate positive infinity. - */ -#if defined(TRIO_FUNC_PINF) -# if defined(INFINITY) && defined(__STDC_IEC_559__) -# define TRIO_PINF_C99_MACRO -# else -# if defined(TRIO_IEEE_754) -# define TRIO_PINF_IEEE_754 -# else -# define TRIO_PINF_FALLBACK -# endif -# endif -#endif - -/* - * Determine how to generate NaN. - */ -#if defined(TRIO_FUNC_NAN) -# if defined(PREDEF_STANDARD_C99) && !defined(TRIO_COMPILER_DECC) -# define TRIO_NAN_C99_FUNCTION -# else -# if defined(NAN) && defined(__STDC_IEC_559__) -# define TRIO_NAN_C99_MACRO -# else -# if defined(TRIO_IEEE_754) -# define TRIO_NAN_IEEE_754 -# else -# define TRIO_NAN_FALLBACK -# endif -# endif -# endif -#endif - -/* - * Resolve internal dependencies. - */ -#if defined(TRIO_FUNC_INTERNAL_FPCLASSIFY_AND_SIGNBIT) -# define TRIO_FUNC_INTERNAL_ISNAN -# define TRIO_FUNC_INTERNAL_ISINF -# if defined(TRIO_IEEE_754) -# define TRIO_FUNC_INTERNAL_IS_SPECIAL_QUANTITY -# define TRIO_FUNC_INTERNAL_IS_NEGATIVE -# endif -#endif - -#if defined(TRIO_NZERO_IEEE_754) \ - || defined(TRIO_PINF_IEEE_754) \ - || defined(TRIO_NAN_IEEE_754) -# define TRIO_FUNC_INTERNAL_MAKE_DOUBLE -#endif - -#if defined(TRIO_FUNC_INTERNAL_ISNAN) -# if defined(PREDEF_STANDARD_XPG3) -# define TRIO_INTERNAL_ISNAN_XPG3 -# else -# if defined(TRIO_IEEE_754) -# define TRIO_INTERNAL_ISNAN_IEEE_754 -# else -# define TRIO_INTERNAL_ISNAN_FALLBACK -# endif -# endif -#endif - -#if defined(TRIO_FUNC_INTERNAL_ISINF) -# if defined(TRIO_IEEE_754) -# define TRIO_INTERNAL_ISINF_IEEE_754 -# else -# define TRIO_INTERNAL_ISINF_FALLBACK -# endif -#endif - -/************************************************************************* - * Constants - */ - -#if !defined(TRIO_EMBED_NAN) -static TRIO_CONST char rcsid[] = "@(#)$Id$"; -#endif - -#if defined(TRIO_FUNC_INTERNAL_MAKE_DOUBLE) \ - || defined(TRIO_FUNC_INTERNAL_IS_SPECIAL_QUANTITY) \ - || defined(TRIO_FUNC_INTERNAL_IS_NEGATIVE) -/* - * Endian-agnostic indexing macro. - * - * The value of internalEndianMagic, when converted into a 64-bit - * integer, becomes 0x0706050403020100 (we could have used a 64-bit - * integer value instead of a double, but not all platforms supports - * that type). The value is automatically encoded with the correct - * endianess by the compiler, which means that we can support any - * kind of endianess. The individual bytes are then used as an index - * for the IEEE 754 bit-patterns and masks. - */ -#define TRIO_DOUBLE_INDEX(x) (((unsigned char *)&internalEndianMagic)[7-(x)]) -static TRIO_CONST double internalEndianMagic = 7.949928895127363e-275; -#endif - -#if defined(TRIO_FUNC_INTERNAL_IS_SPECIAL_QUANTITY) -/* Mask for the exponent */ -static TRIO_CONST unsigned char ieee_754_exponent_mask[] = { - 0x7F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - -/* Mask for the mantissa */ -static TRIO_CONST unsigned char ieee_754_mantissa_mask[] = { - 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF -}; -#endif - -#if defined(TRIO_FUNC_INTERNAL_IS_NEGATIVE) -/* Mask for the sign bit */ -static TRIO_CONST unsigned char ieee_754_sign_mask[] = { - 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; -#endif - -#if defined(TRIO_NZERO_IEEE_754) -/* Bit-pattern for negative zero */ -static TRIO_CONST unsigned char ieee_754_negzero_array[] = { - 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; -#endif - -#if defined(TRIO_PINF_IEEE_754) -/* Bit-pattern for infinity */ -static TRIO_CONST unsigned char ieee_754_infinity_array[] = { - 0x7F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; -#endif - -#if defined(TRIO_NAN_IEEE_754) -/* Bit-pattern for quiet NaN */ -static TRIO_CONST unsigned char ieee_754_qnan_array[] = { - 0x7F, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; -#endif - - -/************************************************************************* - * Internal functions - */ - -/* - * - */ -#if defined(TRIO_PLATFORM_UNIX) && defined(TRIO_INTERNAL_ISNAN_FALLBACK) - -/* Assume that if SA_SIGINFO is defined, then sigaction() and - * 'struct sigaction' are also properly defined on this platform. - */ -#ifndef TRIO_USE_SIGACTION -# ifdef SA_SIGINFO -# define TRIO_USE_SIGACTION 1 -# else -# define TRIO_USE_SIGACTION 0 -# endif -#endif - -# if TRIO_USE_SIGACTION -typedef struct sigaction signal_handler_t; -# else -typedef void (*signal_handler_t) TRIO_PROTO((int)); -# endif - -/* - * internal_ignore_signal_handler - */ - -TRIO_PRIVATE_NAN signal_handler_t -internal_ignore_signal_handler -TRIO_ARGS1((signum), - int signum) -{ -# if TRIO_USE_SIGACTION - signal_handler_t old_handler, new_handler; - memset(&new_handler, '\0', sizeof(new_handler)); - new_handler.sa_handler = SIG_IGN; - new_handler.sa_flags = SA_RESTART; - sigaction(signum, &new_handler, &old_handler); - return old_handler; -# else - return signal(signum, SIG_IGN); -# endif -} - -/* - * internal_restore_signal_handler - */ -TRIO_PRIVATE_NAN void -internal_restore_signal_handler -TRIO_ARGS2((signum, handler), - int signum, - signal_handler_t handler) -{ -# if TRIO_USE_SIGACTION - sigaction(signum, &handler, NULL); -# else - signal(signum, handler); -# endif -} - -#endif - -/* - * internal_make_double - */ -#if defined(TRIO_FUNC_INTERNAL_MAKE_DOUBLE) - -TRIO_PRIVATE_NAN double -internal_make_double -TRIO_ARGS1((values), - TRIO_CONST unsigned char *values) -{ - TRIO_VOLATILE double result; - int i; - - for (i = 0; i < (int)sizeof(double); i++) { - ((TRIO_VOLATILE unsigned char *)&result)[TRIO_DOUBLE_INDEX(i)] = values[i]; - } - return result; -} - -#endif - -/* - * internal_is_special_quantity - */ -#if defined(TRIO_FUNC_INTERNAL_IS_SPECIAL_QUANTITY) - -TRIO_PRIVATE_NAN int -internal_is_special_quantity -TRIO_ARGS2((number, has_mantissa), - double number, - int *has_mantissa) -{ - unsigned int i; - unsigned char current; - int is_special_quantity = TRIO_TRUE; - - *has_mantissa = 0; - - for (i = 0; i < (unsigned int)sizeof(double); i++) { - current = ((unsigned char *)&number)[TRIO_DOUBLE_INDEX(i)]; - is_special_quantity - &= ((current & ieee_754_exponent_mask[i]) == ieee_754_exponent_mask[i]); - *has_mantissa |= (current & ieee_754_mantissa_mask[i]); - } - return is_special_quantity; -} - -#endif - -/* - * internal_is_negative - */ -#if defined(TRIO_FUNC_INTERNAL_IS_NEGATIVE) - -TRIO_PRIVATE_NAN int -internal_is_negative -TRIO_ARGS1((number), - double number) -{ - unsigned int i; - int is_negative = TRIO_FALSE; - - for (i = 0; i < (unsigned int)sizeof(double); i++) { - is_negative |= (((unsigned char *)&number)[TRIO_DOUBLE_INDEX(i)] - & ieee_754_sign_mask[i]); - } - return is_negative; -} - -#endif - -#if defined(TRIO_FUNC_C99_FPCLASSIFY_AND_SIGNBIT) - -TRIO_PRIVATE_NAN TRIO_INLINE int -c99_fpclassify_and_signbit -TRIO_ARGS2((number, is_negative), - double number, - int *is_negative) -{ - *is_negative = signbit(number); - switch (fpclassify(number)) { - case FP_NAN: - return TRIO_FP_NAN; - case FP_INFINITE: - return TRIO_FP_INFINITE; - case FP_SUBNORMAL: - return TRIO_FP_SUBNORMAL; - case FP_ZERO: - return TRIO_FP_ZERO; - default: - return TRIO_FP_NORMAL; - } -} - -#endif /* TRIO_FUNC_C99_FPCLASSIFY_AND_SIGNBIT */ - -#if defined(TRIO_FUNC_DECC_FPCLASSIFY_AND_SIGNBIT) - -TRIO_PRIVATE_NAN TRIO_INLINE int -decc_fpclassify_and_signbit -TRIO_ARGS2((number, is_negative), - double number, - int *is_negative) -{ - switch (fp_class(number)) { - case FP_QNAN: - case FP_SNAN: - *is_negative = TRIO_FALSE; /* NaN has no sign */ - return TRIO_FP_NAN; - case FP_POS_INF: - *is_negative = TRIO_FALSE; - return TRIO_FP_INFINITE; - case FP_NEG_INF: - *is_negative = TRIO_TRUE; - return TRIO_FP_INFINITE; - case FP_POS_DENORM: - *is_negative = TRIO_FALSE; - return TRIO_FP_SUBNORMAL; - case FP_NEG_DENORM: - *is_negative = TRIO_TRUE; - return TRIO_FP_SUBNORMAL; - case FP_POS_ZERO: - *is_negative = TRIO_FALSE; - return TRIO_FP_ZERO; - case FP_NEG_ZERO: - *is_negative = TRIO_TRUE; - return TRIO_FP_ZERO; - case FP_POS_NORM: - *is_negative = TRIO_FALSE; - return TRIO_FP_NORMAL; - case FP_NEG_NORM: - *is_negative = TRIO_TRUE; - return TRIO_FP_NORMAL; - default: - *is_negative = (number < 0.0); - return TRIO_FP_NORMAL; - } -} - -#endif /* TRIO_FUNC_DECC_FPCLASSIFY_AND_SIGNBIT */ - -#if defined(TRIO_FUNC_MS_FPCLASSIFY_AND_SIGNBIT) - -TRIO_PRIVATE_NAN int -ms_fpclassify_and_signbit -TRIO_ARGS2((number, is_negative), - double number, - int *is_negative) -{ - int result; -# if defined(TRIO_COMPILER_BORLAND) - /* - * The floating-point precision may be changed by the Borland _fpclass() - * function, so we have to save and restore the floating-point control mask. - */ - unsigned int mask; - /* Remember the old mask */ - mask = _control87(0, 0); -# endif - - switch (_fpclass(number)) { - case _FPCLASS_QNAN: - case _FPCLASS_SNAN: - *is_negative = TRIO_FALSE; /* NaN has no sign */ - result = TRIO_FP_NAN; - break; - case _FPCLASS_PINF: - *is_negative = TRIO_FALSE; - result = TRIO_FP_INFINITE; - break; - case _FPCLASS_NINF: - *is_negative = TRIO_TRUE; - result = TRIO_FP_INFINITE; - break; - case _FPCLASS_PD: - *is_negative = TRIO_FALSE; - result = TRIO_FP_SUBNORMAL; - break; - case _FPCLASS_ND: - *is_negative = TRIO_TRUE; - result = TRIO_FP_SUBNORMAL; - break; - case _FPCLASS_PZ: - *is_negative = TRIO_FALSE; - result = TRIO_FP_ZERO; - break; - case _FPCLASS_NZ: - *is_negative = TRIO_TRUE; - result = TRIO_FP_ZERO; - break; - case _FPCLASS_PN: - *is_negative = TRIO_FALSE; - result = TRIO_FP_NORMAL; - break; - case _FPCLASS_NN: - *is_negative = TRIO_TRUE; - result = TRIO_FP_NORMAL; - break; - default: - *is_negative = (number < 0.0); - result = TRIO_FP_NORMAL; - break; - } - -# if defined(TRIO_COMPILER_BORLAND) - /* Restore the old precision */ - (void)_control87(mask, MCW_PC); -# endif - - return result; -} - -#endif /* TRIO_FUNC_MS_FPCLASSIFY_AND_SIGNBIT */ - -#if defined(TRIO_FUNC_HP_FPCLASSIFY_AND_SIGNBIT) - -TRIO_PRIVATE_NAN TRIO_INLINE int -hp_fpclassify_and_signbit -TRIO_ARGS2((number, is_negative), - double number, - int *is_negative) -{ - /* - * HP-UX 9.x and 10.x have an fpclassify() function, that is different - * from the C99 fpclassify() macro supported on HP-UX 11.x. - */ - switch (fpclassify(number)) { - case FP_QNAN: - case FP_SNAN: - *is_negative = TRIO_FALSE; /* NaN has no sign */ - return TRIO_FP_NAN; - case FP_PLUS_INF: - *is_negative = TRIO_FALSE; - return TRIO_FP_INFINITE; - case FP_MINUS_INF: - *is_negative = TRIO_TRUE; - return TRIO_FP_INFINITE; - case FP_PLUS_DENORM: - *is_negative = TRIO_FALSE; - return TRIO_FP_SUBNORMAL; - case FP_MINUS_DENORM: - *is_negative = TRIO_TRUE; - return TRIO_FP_SUBNORMAL; - case FP_PLUS_ZERO: - *is_negative = TRIO_FALSE; - return TRIO_FP_ZERO; - case FP_MINUS_ZERO: - *is_negative = TRIO_TRUE; - return TRIO_FP_ZERO; - case FP_PLUS_NORM: - *is_negative = TRIO_FALSE; - return TRIO_FP_NORMAL; - case FP_MINUS_NORM: - *is_negative = TRIO_TRUE; - return TRIO_FP_NORMAL; - default: - *is_negative = (number < 0.0); - return TRIO_FP_NORMAL; - } -} - -#endif /* TRIO_FUNC_HP_FPCLASSIFY_AND_SIGNBIT */ - -#if defined(TRIO_FUNC_XLC_FPCLASSIFY_AND_SIGNBIT) - -TRIO_PRIVATE_NAN TRIO_INLINE int -xlc_fpclassify_and_signbit -TRIO_ARGS2((number, is_negative), - double number, - int *is_negative) -{ - /* - * AIX has class() for C, and _class() for C++ - */ -# if defined(__cplusplus) -# define AIX_CLASS(n) _class(n) -# else -# define AIX_CLASS(n) class(n) -# endif - - switch (AIX_CLASS(number)) { - case FP_QNAN: - case FP_SNAN: - *is_negative = TRIO_FALSE; /* NaN has no sign */ - return TRIO_FP_NAN; - case FP_PLUS_INF: - *is_negative = TRIO_FALSE; - return TRIO_FP_INFINITE; - case FP_MINUS_INF: - *is_negative = TRIO_TRUE; - return TRIO_FP_INFINITE; - case FP_PLUS_DENORM: - *is_negative = TRIO_FALSE; - return TRIO_FP_SUBNORMAL; - case FP_MINUS_DENORM: - *is_negative = TRIO_TRUE; - return TRIO_FP_SUBNORMAL; - case FP_PLUS_ZERO: - *is_negative = TRIO_FALSE; - return TRIO_FP_ZERO; - case FP_MINUS_ZERO: - *is_negative = TRIO_TRUE; - return TRIO_FP_ZERO; - case FP_PLUS_NORM: - *is_negative = TRIO_FALSE; - return TRIO_FP_NORMAL; - case FP_MINUS_NORM: - *is_negative = TRIO_TRUE; - return TRIO_FP_NORMAL; - default: - *is_negative = (number < 0.0); - return TRIO_FP_NORMAL; - } -} - -#endif /* TRIO_FUNC_XLC_FPCLASSIFY_AND_SIGNBIT */ - -#if defined(TRIO_FUNC_INTERNAL_ISNAN) - -TRIO_PRIVATE_NAN TRIO_INLINE int -internal_isnan -TRIO_ARGS1((number), - double number) -{ -# if defined(TRIO_INTERNAL_ISNAN_XPG3) || defined(TRIO_PLATFORM_SYMBIAN) - /* - * XPG3 defines isnan() as a function. - */ - return isnan(number); - -# endif - -# if defined(TRIO_INTERNAL_ISNAN_IEEE_754) - - /* - * Examine IEEE 754 bit-pattern. A NaN must have a special exponent - * pattern, and a non-empty mantissa. - */ - int has_mantissa; - int is_special_quantity; - - is_special_quantity = internal_is_special_quantity(number, &has_mantissa); - - return (is_special_quantity && has_mantissa); - -# endif - -# if defined(TRIO_INTERNAL_ISNAN_FALLBACK) - - /* - * Fallback solution - */ - int status; - double integral, fraction; - -# if defined(TRIO_PLATFORM_UNIX) - signal_handler_t sigfpe_handler = internal_ignore_signal_handler(SIGFPE); -# endif - - status = (/* - * NaN is the only number which does not compare to itself - */ - ((TRIO_VOLATILE double)number != (TRIO_VOLATILE double)number) || - /* - * Fallback solution if NaN compares to NaN - */ - ((number != 0.0) && - (fraction = modf(number, &integral), - integral == fraction))); - -# if defined(TRIO_PLATFORM_UNIX) - internal_restore_signal_handler(SIGFPR, sigfpe_handler); -# endif - - return status; - -# endif -} - -#endif /* TRIO_FUNC_INTERNAL_ISNAN */ - -#if defined(TRIO_FUNC_INTERNAL_ISINF) - -TRIO_PRIVATE_NAN TRIO_INLINE int -internal_isinf -TRIO_ARGS1((number), - double number) -{ -# if defined(TRIO_PLATFORM_SYMBIAN) - - return isinf(number); - -# endif - -# if defined(TRIO_INTERNAL_ISINF_IEEE_754) - /* - * Examine IEEE 754 bit-pattern. Infinity must have a special exponent - * pattern, and an empty mantissa. - */ - int has_mantissa; - int is_special_quantity; - - is_special_quantity = internal_is_special_quantity(number, &has_mantissa); - - return (is_special_quantity && !has_mantissa) - ? ((number < 0.0) ? -1 : 1) - : 0; - -# endif - -# if defined(TRIO_INTERNAL_ISINF_FALLBACK) - - /* - * Fallback solution. - */ - int status; - -# if defined(TRIO_PLATFORM_UNIX) - signal_handler_t sigfpe_handler = internal_ignore_signal_handler(SIGFPE); -# endif - - double infinity = trio_pinf(); - - status = ((number == infinity) - ? 1 - : ((number == -infinity) ? -1 : 0)); - -# if defined(TRIO_PLATFORM_UNIX) - internal_restore_signal_handler(SIGFPE, sigfpe_handler); -# endif - - return status; - -# endif -} - -#endif /* TRIO_FUNC_INTERNAL_ISINF */ - -/************************************************************************* - * Public functions - */ - -#if defined(TRIO_FUNC_FPCLASSIFY_AND_SIGNBIT) - -TRIO_PUBLIC_NAN int -trio_fpclassify_and_signbit -TRIO_ARGS2((number, is_negative), - double number, - int *is_negative) -{ - /* The TRIO_FUNC_xxx_FPCLASSIFY_AND_SIGNBIT macros are mutually exclusive */ - -#if defined(TRIO_FUNC_C99_FPCLASSIFY_AND_SIGNBIT) - - return c99_fpclassify_and_signbit(number, is_negative); - -#endif - -#if defined(TRIO_FUNC_DECC_FPCLASSIFY_AND_SIGNBIT) - - return decc_fpclassify_and_signbit(number, is_negative); - -#endif - -#if defined(TRIO_FUNC_MS_FPCLASSIFY_AND_SIGNBIT) - - return ms_fpclassify_and_signbit(number, is_negative); - -#endif - -#if defined(TRIO_FUNC_HP_FPCLASSIFY_AND_SIGNBIT) - - return hp_fpclassify_and_signbit(number, is_negative); - -#endif - -#if defined(TRIO_FUNC_XLC_FPCLASSIFY_AND_SIGNBIT) - - return xlc_fpclassify_and_signbit(number, is_negative); - -#endif - -#if defined(TRIO_FUNC_INTERNAL_FPCLASSIFY_AND_SIGNBIT) - - /* - * Fallback solution. - */ - int rc; - - if (number == 0.0) { - /* - * In IEEE 754 the sign of zero is ignored in comparisons, so we - * have to handle this as a special case by examining the sign bit - * directly. - */ -# if defined(TRIO_IEEE_754) - *is_negative = internal_is_negative(number); -# else - *is_negative = TRIO_FALSE; /* FIXME */ -# endif - return TRIO_FP_ZERO; - } - if (internal_isnan(number)) { - *is_negative = TRIO_FALSE; - return TRIO_FP_NAN; - } - rc = internal_isinf(number); - if (rc != 0) { - *is_negative = (rc == -1); - return TRIO_FP_INFINITE; - } - if ((number > 0.0) && (number < DBL_MIN)) { - *is_negative = TRIO_FALSE; - return TRIO_FP_SUBNORMAL; - } - if ((number < 0.0) && (number > -DBL_MIN)) { - *is_negative = TRIO_TRUE; - return TRIO_FP_SUBNORMAL; - } - *is_negative = (number < 0.0); - return TRIO_FP_NORMAL; - -#endif -} - -#endif - -/** - Check for NaN. - - @param number An arbitrary floating-point number. - @return Boolean value indicating whether or not the number is a NaN. -*/ -#if defined(TRIO_FUNC_ISNAN) - -TRIO_PUBLIC_NAN int -trio_isnan -TRIO_ARGS1((number), - double number) -{ - int dummy; - - return (trio_fpclassify_and_signbit(number, &dummy) == TRIO_FP_NAN); -} - -#endif - -/** - Check for infinity. - - @param number An arbitrary floating-point number. - @return 1 if positive infinity, -1 if negative infinity, 0 otherwise. -*/ -#if defined(TRIO_FUNC_ISINF) - -TRIO_PUBLIC_NAN int -trio_isinf -TRIO_ARGS1((number), - double number) -{ - int is_negative; - - if (trio_fpclassify_and_signbit(number, &is_negative) == TRIO_FP_INFINITE) - { - return (is_negative) ? -1 : 1; - } - else - { - return 0; - } -} - -#endif - -/** - Check for finity. - - @param number An arbitrary floating-point number. - @return Boolean value indicating whether or not the number is a finite. -*/ -#if defined(TRIO_FUNC_ISFINITE) - -TRIO_PUBLIC_NAN int -trio_isfinite -TRIO_ARGS1((number), - double number) -{ - int dummy; - - switch (trio_fpclassify_and_signbit(number, &dummy)) - { - case TRIO_FP_INFINITE: - case TRIO_FP_NAN: - return 0; - default: - return 1; - } -} - -#endif - -/** - Examine the sign of a number. - - @param number An arbitrary floating-point number. - @return Boolean value indicating whether or not the number has the - sign bit set (i.e. is negative). -*/ -#if defined(TRIO_FUNC_SIGNBIT) - -TRIO_PUBLIC_NAN int -trio_signbit -TRIO_ARGS1((number), - double number) -{ - int is_negative; - - (void)trio_fpclassify_and_signbit(number, &is_negative); - return is_negative; -} - -#endif - -/** - Examine the class of a number. - - @param number An arbitrary floating-point number. - @return Enumerable value indicating the class of @p number -*/ -#if defined(TRIO_FUNC_FPCLASSIFY) - -TRIO_PUBLIC_NAN int -trio_fpclassify -TRIO_ARGS1((number), - double number) -{ - int dummy; - - return trio_fpclassify_and_signbit(number, &dummy); -} - -#endif - -/** - Generate negative zero. - - @return Floating-point representation of negative zero. -*/ -#if defined(TRIO_FUNC_NZERO) - -TRIO_PUBLIC_NAN double -trio_nzero(TRIO_NOARGS) -{ -# if defined(TRIO_NZERO_IEEE_754) - - return internal_make_double(ieee_754_negzero_array); - -# endif - -# if defined(TRIO_NZERO_FALLBACK) - - TRIO_VOLATILE double zero = 0.0; - - return -zero; - -# endif -} - -#endif - -/** - Generate positive infinity. - - @return Floating-point representation of positive infinity. -*/ -#if defined(TRIO_FUNC_PINF) - -TRIO_PUBLIC_NAN double -trio_pinf(TRIO_NOARGS) -{ - /* Cache the result */ - static double pinf_value = 0.0; - - if (pinf_value == 0.0) { - -# if defined(TRIO_PINF_C99_MACRO) - - pinf_value = (double)INFINITY; - -# endif - -# if defined(TRIO_PINF_IEEE_754) - - pinf_value = internal_make_double(ieee_754_infinity_array); - -# endif - -# if defined(TRIO_PINF_FALLBACK) - /* - * If HUGE_VAL is different from DBL_MAX, then HUGE_VAL is used - * as infinity. Otherwise we have to resort to an overflow - * operation to generate infinity. - */ -# if defined(TRIO_PLATFORM_UNIX) - signal_handler_t sigfpe_handler = internal_ignore_signal_handler(SIGFPE); -# endif - - pinf_value = HUGE_VAL; - if (HUGE_VAL == DBL_MAX) { - /* Force overflow */ - pinf_value += HUGE_VAL; - } - -# if defined(TRIO_PLATFORM_UNIX) - internal_restore_signal_handler(SIGFPE, sigfpe_handler); -# endif - -# endif - } - return pinf_value; -} - -#endif - -/** - Generate negative infinity. - - @return Floating-point value of negative infinity. -*/ -#if defined(TRIO_FUNC_NINF) - -TRIO_PUBLIC_NAN double -trio_ninf(TRIO_NOARGS) -{ - static double ninf_value = 0.0; - - if (ninf_value == 0.0) { - /* - * Negative infinity is calculated by negating positive infinity, - * which can be done because it is legal to do calculations on - * infinity (for example, 1 / infinity == 0). - */ - ninf_value = -trio_pinf(); - } - return ninf_value; -} - -#endif - -/** - Generate NaN. - - @return Floating-point representation of NaN. -*/ -#if defined(TRIO_FUNC_NAN) - -TRIO_PUBLIC_NAN double -trio_nan(TRIO_NOARGS) -{ - /* Cache the result */ - static double nan_value = 0.0; - - if (nan_value == 0.0) { - -# if defined(TRIO_NAN_C99_FUNCTION) || defined(TRIO_PLATFORM_SYMBIAN) - - nan_value = nan(""); - -# endif - -# if defined(TRIO_NAN_C99_MACRO) - - nan_value = (double)NAN; - -# endif - -# if defined(TRIO_NAN_IEEE_754) - - nan_value = internal_make_double(ieee_754_qnan_array); - -# endif - -# if defined(TRIO_NAN_FALLBACK) - /* - * There are several ways to generate NaN. The one used here is - * to divide infinity by infinity. I would have preferred to add - * negative infinity to positive infinity, but that yields wrong - * result (infinity) on FreeBSD. - * - * This may fail if the hardware does not support NaN, or if - * the Invalid Operation floating-point exception is unmasked. - */ -# if defined(TRIO_PLATFORM_UNIX) - signal_handle_t sigfpe_handler = internal_ignore_signal_handler(SIGFPE); -# endif - - nan_value = trio_pinf() / trio_pinf(); - -# if defined(TRIO_PLATFORM_UNIX) - internal_restore_signal_handler(SIGFPE, sigfpe_handler); -# endif - -# endif - } - return nan_value; -} - -#endif - -/** @} SpecialQuantities */ - -/************************************************************************* - * For test purposes. - * - * Add the following compiler option to include this test code. - * - * Unix : -DSTANDALONE - * VMS : /DEFINE=(STANDALONE) - */ -#if defined(STANDALONE) -# include - -static TRIO_CONST char * -getClassification -TRIO_ARGS1((type), - int type) -{ - switch (type) { - case TRIO_FP_INFINITE: - return "FP_INFINITE"; - case TRIO_FP_NAN: - return "FP_NAN"; - case TRIO_FP_NORMAL: - return "FP_NORMAL"; - case TRIO_FP_SUBNORMAL: - return "FP_SUBNORMAL"; - case TRIO_FP_ZERO: - return "FP_ZERO"; - default: - return "FP_UNKNOWN"; - } -} - -static void -print_class -TRIO_ARGS2((prefix, number), - TRIO_CONST char *prefix, - double number) -{ - printf("%-6s: %s %-15s %g\n", - prefix, - trio_signbit(number) ? "-" : "+", - getClassification(trio_fpclassify(number)), - number); -} - -int main(TRIO_NOARGS) -{ - double my_nan; - double my_pinf; - double my_ninf; -# if defined(TRIO_PLATFORM_UNIX) - signal_handler_t signal_handler; -# endif - - my_nan = trio_nan(); - my_pinf = trio_pinf(); - my_ninf = trio_ninf(); - - print_class("Nan", my_nan); - print_class("PInf", my_pinf); - print_class("NInf", my_ninf); - print_class("PZero", 0.0); - print_class("NZero", -0.0); - print_class("PNorm", 1.0); - print_class("NNorm", -1.0); - print_class("PSub", 1.01e-307 - 1.00e-307); - print_class("NSub", 1.00e-307 - 1.01e-307); - - printf("NaN : %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d, %2d)\n", - my_nan, - ((unsigned char *)&my_nan)[0], - ((unsigned char *)&my_nan)[1], - ((unsigned char *)&my_nan)[2], - ((unsigned char *)&my_nan)[3], - ((unsigned char *)&my_nan)[4], - ((unsigned char *)&my_nan)[5], - ((unsigned char *)&my_nan)[6], - ((unsigned char *)&my_nan)[7], - trio_isnan(my_nan), trio_isinf(my_nan), trio_isfinite(my_nan)); - printf("PInf: %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d, %2d)\n", - my_pinf, - ((unsigned char *)&my_pinf)[0], - ((unsigned char *)&my_pinf)[1], - ((unsigned char *)&my_pinf)[2], - ((unsigned char *)&my_pinf)[3], - ((unsigned char *)&my_pinf)[4], - ((unsigned char *)&my_pinf)[5], - ((unsigned char *)&my_pinf)[6], - ((unsigned char *)&my_pinf)[7], - trio_isnan(my_pinf), trio_isinf(my_pinf), trio_isfinite(my_pinf)); - printf("NInf: %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d, %2d)\n", - my_ninf, - ((unsigned char *)&my_ninf)[0], - ((unsigned char *)&my_ninf)[1], - ((unsigned char *)&my_ninf)[2], - ((unsigned char *)&my_ninf)[3], - ((unsigned char *)&my_ninf)[4], - ((unsigned char *)&my_ninf)[5], - ((unsigned char *)&my_ninf)[6], - ((unsigned char *)&my_ninf)[7], - trio_isnan(my_ninf), trio_isinf(my_ninf), trio_isfinite(my_ninf)); - -# if defined(TRIO_PLATFORM_UNIX) - signal_handler = internal_ignore_signal_handler(SIGFPE); -# endif - - my_pinf = DBL_MAX + DBL_MAX; - my_ninf = -my_pinf; - my_nan = my_pinf / my_pinf; - -# if defined(TRIO_PLATFORM_UNIX) - internal_restore_signal_handler(SIGFPE, signal_handler); -# endif - - printf("NaN : %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d, %2d)\n", - my_nan, - ((unsigned char *)&my_nan)[0], - ((unsigned char *)&my_nan)[1], - ((unsigned char *)&my_nan)[2], - ((unsigned char *)&my_nan)[3], - ((unsigned char *)&my_nan)[4], - ((unsigned char *)&my_nan)[5], - ((unsigned char *)&my_nan)[6], - ((unsigned char *)&my_nan)[7], - trio_isnan(my_nan), trio_isinf(my_nan), trio_isfinite(my_nan)); - printf("PInf: %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d, %2d)\n", - my_pinf, - ((unsigned char *)&my_pinf)[0], - ((unsigned char *)&my_pinf)[1], - ((unsigned char *)&my_pinf)[2], - ((unsigned char *)&my_pinf)[3], - ((unsigned char *)&my_pinf)[4], - ((unsigned char *)&my_pinf)[5], - ((unsigned char *)&my_pinf)[6], - ((unsigned char *)&my_pinf)[7], - trio_isnan(my_pinf), trio_isinf(my_pinf), trio_isfinite(my_pinf)); - printf("NInf: %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d, %2d)\n", - my_ninf, - ((unsigned char *)&my_ninf)[0], - ((unsigned char *)&my_ninf)[1], - ((unsigned char *)&my_ninf)[2], - ((unsigned char *)&my_ninf)[3], - ((unsigned char *)&my_ninf)[4], - ((unsigned char *)&my_ninf)[5], - ((unsigned char *)&my_ninf)[6], - ((unsigned char *)&my_ninf)[7], - trio_isnan(my_ninf), trio_isinf(my_ninf), trio_isfinite(my_ninf)); - - return 0; -} -#endif diff --git a/psx/mednadisc/trio/trionan.h b/psx/mednadisc/trio/trionan.h deleted file mode 100644 index b441b4ae219..00000000000 --- a/psx/mednadisc/trio/trionan.h +++ /dev/null @@ -1,183 +0,0 @@ -/************************************************************************* - * - * $Id$ - * - * Copyright (C) 2001 Bjorn Reese - * - * 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 */ diff --git a/psx/mednadisc/trio/triop.h b/psx/mednadisc/trio/triop.h deleted file mode 100644 index 352754ea2c5..00000000000 --- a/psx/mednadisc/trio/triop.h +++ /dev/null @@ -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 -#if defined(TRIO_COMPILER_ANCIENT) -# include -#else -# include -#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 */ diff --git a/psx/mednadisc/trio/triostr.c b/psx/mednadisc/trio/triostr.c deleted file mode 100644 index d43e622c722..00000000000 --- a/psx/mednadisc/trio/triostr.c +++ /dev/null @@ -1,2385 +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. - * - ************************************************************************/ - -/************************************************************************* - * Include files - */ - -#if defined(HAVE_CONFIG_H) -# include -#endif -#include -#include -#include -#include -#include "triodef.h" -#include "triostr.h" -#if defined(TRIO_FUNC_TO_LONG_DOUBLE) -# define USE_MATH -#endif -#if defined(USE_MATH) -# include -#endif - -/************************************************************************* - * Definitions - */ - -#if !defined(TRIO_PUBLIC_STRING) -# define TRIO_PUBLIC_STRING TRIO_PUBLIC -#endif -#if !defined(TRIO_PRIVATE_STRING) -# define TRIO_PRIVATE_STRING TRIO_PRIVATE -#endif - -#if !defined(NULL) -# define NULL 0 -#endif -#if !defined(NIL) -# define NIL ((char)0) -#endif -#if !defined(FALSE) -# define FALSE (1 == 0) -# define TRUE (! FALSE) -#endif -#if !defined(BOOLEAN_T) -# define BOOLEAN_T int -#endif - -#if defined(USE_MATH) -# if defined(PREDEF_STANDARD_C99) -# if defined(TRIO_COMPILER_DECC) -# if (TRIO_COMPILER_DECC - 0 > 80000000) -/* - * The OSF/1 runtime that comes with the DECC compiler does not support - * hexfloats conversion. - */ -# define USE_STRTOD -# define USE_STRTOF -# endif -# else -# define USE_STRTOD -# define USE_STRTOF -# endif -# else -# if defined(TRIO_COMPILER_VISUALC) -# define USE_STRTOD -# endif -#endif -#endif - -#if defined(TRIO_PLATFORM_UNIX) -# if defined(PREDEF_STANDARD_UNIX95) -# define USE_STRCASECMP -# define USE_STRNCASECMP -# endif -# if defined(TRIO_PLATFORM_SUNOS) -# define USE_SYS_ERRLIST -# else -# define USE_STRERROR -# endif -# if defined(TRIO_PLATFORM_QNX) -# define strcasecmp(x,y) stricmp(x,y) -# define strncasecmp(x,y,n) strnicmp(x,y,n) -# endif -#endif - -#if defined(TRIO_PLATFORM_WIN32) -# define USE_STRCASECMP -# if defined(TRIO_PLATFORM_WINCE) -# define strcasecmp(x,y) _stricmp(x,y) -# else -# define strcasecmp(x,y) strcmpi(x,y) -# endif -#endif - -#if !defined(HAVE_CONFIG_H) -# if !(defined(TRIO_PLATFORM_SUNOS)) -# define HAVE_TOLOWER -# define HAVE_TOUPPER -# endif -#endif - -#if defined(USE_MATH) && !defined(TRIO_NO_POWL) -# if !defined(HAVE_POWL) -# if defined(PREDEF_STANDARD_C99) \ - || defined(PREDEF_STANDARD_UNIX03) -# define HAVE_POWL -# else -# if defined(TRIO_COMPILER_VISUALC) -# if defined(powl) -# define HAVE_POWL -# endif -# endif -# endif -# endif -#endif - -#if defined(HAVE_POWL) -# define trio_powl(x,y) powl((x),(y)) -#else -# define trio_powl(x,y) pow((double)(x),(double)(y)) -#endif - -#if defined(TRIO_FUNC_TO_UPPER) \ - || (defined(TRIO_FUNC_EQUAL) && !defined(USE_STRCASECMP)) \ - || (defined(TRIO_FUNC_EQUAL_MAX) && !defined(USE_STRNCASECMP)) \ - || defined(TRIO_FUNC_MATCH) \ - || defined(TRIO_FUNC_TO_LONG_DOUBLE) \ - || defined(TRIO_FUNC_UPPER) -# define TRIO_FUNC_INTERNAL_TO_UPPER -#endif - -/************************************************************************* - * Structures - */ - -struct _trio_string_t -{ - char *content; - size_t length; - size_t allocated; -}; - -/************************************************************************* - * Constants - */ - -#if !defined(TRIO_EMBED_STRING) -static TRIO_CONST char rcsid[] = "@(#)$Id$"; -#endif - -/************************************************************************* - * Static String Functions - */ - -#if defined(TRIO_DOCUMENTATION) -# include "doc/doc_static.h" -#endif -/** @addtogroup StaticStrings - @{ -*/ - -/* - * internal_duplicate_max - */ -#if defined(TRIO_FUNC_DUPLICATE) \ - || defined(TRIO_FUNC_DUPLICATE_MAX) \ - || defined(TRIO_FUNC_STRING_DUPLICATE) \ - || defined(TRIO_FUNC_XSTRING_DUPLICATE) - -TRIO_PRIVATE_STRING char * -internal_duplicate_max -TRIO_ARGS2((source, size), - TRIO_CONST char *source, - size_t size) -{ - char *target; - - assert(source); - - /* Make room for string plus a terminating zero */ - size++; - target = trio_create(size); - if (target) - { - trio_copy_max(target, size, source); - } - return target; -} - -#endif - -/* - * internal_string_alloc - */ -#if defined(TRIO_FUNC_STRING_CREATE) \ - || defined(TRIO_FUNC_STRING_DUPLICATE) \ - || defined(TRIO_FUNC_XSTRING_DUPLICATE) - -TRIO_PRIVATE_STRING trio_string_t * -internal_string_alloc(TRIO_NOARGS) -{ - trio_string_t *self; - - self = (trio_string_t *)TRIO_MALLOC(sizeof(trio_string_t)); - if (self) - { - self->content = NULL; - self->length = 0; - self->allocated = 0; - } - return self; -} - -#endif - -/* - * internal_string_grow - * - * The size of the string will be increased by 'delta' characters. If - * 'delta' is zero, the size will be doubled. - */ -#if defined(TRIO_FUNC_STRING_CREATE) \ - || defined(TRIO_FUNC_STRING_APPEND) \ - || defined(TRIO_FUNC_XSTRING_APPEND) \ - || defined(TRIO_FUNC_XSTRING_APPEND_CHAR) - -TRIO_PRIVATE_STRING BOOLEAN_T -internal_string_grow -TRIO_ARGS2((self, delta), - trio_string_t *self, - size_t delta) -{ - BOOLEAN_T status = FALSE; - char *new_content; - size_t new_size; - - new_size = (delta == 0) - ? ( (self->allocated == 0) ? 1 : self->allocated * 2 ) - : self->allocated + delta; - - new_content = (char *)TRIO_REALLOC(self->content, new_size); - if (new_content) - { - self->content = new_content; - self->allocated = new_size; - status = TRUE; - } - return status; -} - -#endif - -/* - * internal_string_grow_to - * - * The size of the string will be increased to 'length' plus one characters. - * If 'length' is less than the original size, the original size will be - * used (that is, the size of the string is never decreased). - */ -#if defined(TRIO_FUNC_STRING_APPEND) \ - || defined(TRIO_FUNC_XSTRING_APPEND) \ - || defined(TRIO_FUNC_XSTRING_APPEND_MAX) - -TRIO_PRIVATE_STRING BOOLEAN_T -internal_string_grow_to -TRIO_ARGS2((self, length), - trio_string_t *self, - size_t length) -{ - length++; /* Room for terminating zero */ - return (self->allocated < length) - ? internal_string_grow(self, length - self->allocated) - : TRUE; -} - -#endif - -#if defined(TRIO_FUNC_INTERNAL_TO_UPPER) - -TRIO_PRIVATE_STRING int -internal_to_upper -TRIO_ARGS1((source), - int source) -{ -# if defined(HAVE_TOUPPER) - - return toupper(source); - -# else - - /* Does not handle locales or non-contiguous alphabetic characters */ - return ((source >= (int)'a') && (source <= (int)'z')) - ? source - 'a' + 'A' - : source; - -# endif -} - -#endif - - -/** - Create new string. - - @param size Size of new string. - @return Pointer to string, or NULL if allocation failed. -*/ -#if defined(TRIO_FUNC_CREATE) - -TRIO_PUBLIC_STRING char * -trio_create -TRIO_ARGS1((size), - size_t size) -{ - return (char *)TRIO_MALLOC(size); -} - -#endif - -/** - Destroy string. - - @param string String to be freed. -*/ -#if defined(TRIO_FUNC_DESTROY) - -TRIO_PUBLIC_STRING void -trio_destroy -TRIO_ARGS1((string), - char *string) -{ - if (string) - { - TRIO_FREE(string); - } -} - -#endif - -/** - Count the number of characters in a string. - - @param string String to measure. - @return Number of characters in @p string. -*/ -#if defined(TRIO_FUNC_LENGTH) - -TRIO_PUBLIC_STRING size_t -trio_length -TRIO_ARGS1((string), - TRIO_CONST char *string) -{ - return strlen(string); -} - -#endif - -/** - Count at most @p max characters in a string. - - @param string String to measure. - @param max Maximum number of characters to count. - @return The maximum value of @p max and number of characters in @p string. -*/ -#if defined(TRIO_FUNC_LENGTH_MAX) - -TRIO_PUBLIC_STRING size_t -trio_length_max -TRIO_ARGS2((string, max), - TRIO_CONST char *string, - size_t max) -{ - size_t i; - - for (i = 0; i < max; ++i) - { - if (string[i] == 0) - break; - } - return i; -} - -#endif - -/** - Append @p source at the end of @p target. - - @param target Target string. - @param source Source string. - @return Boolean value indicating success or failure. - - @pre @p target must point to a memory chunk with sufficient room to - contain the @p target string and @p source string. - @pre No boundary checking is performed, so insufficient memory will - result in a buffer overrun. - @post @p target will be zero terminated. -*/ -#if defined(TRIO_FUNC_APPEND) - -TRIO_PUBLIC_STRING int -trio_append -TRIO_ARGS2((target, source), - char *target, - TRIO_CONST char *source) -{ - assert(target); - assert(source); - - return (strcat(target, source) != NULL); -} - -#endif - -/** - Append at most @p max characters from @p source to @p target. - - @param target Target string. - @param max Maximum number of characters to append. - @param source Source string. - @return Boolean value indicating success or failure. - - @pre @p target must point to a memory chuck with sufficient room to - contain the @p target string and the @p source string (at most @p max - characters). - @pre No boundary checking is performed, so insufficient memory will - result in a buffer overrun. - @post @p target will be zero terminated. -*/ -#if defined(TRIO_FUNC_APPEND_MAX) - -TRIO_PUBLIC_STRING int -trio_append_max -TRIO_ARGS3((target, max, source), - char *target, - size_t max, - TRIO_CONST char *source) -{ - size_t length; - - assert(target); - assert(source); - - length = trio_length(target); - - if (max > length) - { - strncat(target, source, max - length - 1); - } - return TRUE; -} - -#endif - -/** - Determine if a string contains a substring. - - @param string String to be searched. - @param substring String to be found. - @return Boolean value indicating success or failure. -*/ -#if defined(TRIO_FUNC_CONTAINS) - -TRIO_PUBLIC_STRING int -trio_contains -TRIO_ARGS2((string, substring), - TRIO_CONST char *string, - TRIO_CONST char *substring) -{ - assert(string); - assert(substring); - - return (0 != strstr(string, substring)); -} - -#endif - -/** - Copy @p source to @p target. - - @param target Target string. - @param source Source string. - @return Boolean value indicating success or failure. - - @pre @p target must point to a memory chunk with sufficient room to - contain the @p source string. - @pre No boundary checking is performed, so insufficient memory will - result in a buffer overrun. - @post @p target will be zero terminated. -*/ -#if defined(TRIO_FUNC_COPY) - -TRIO_PUBLIC_STRING int -trio_copy -TRIO_ARGS2((target, source), - char *target, - TRIO_CONST char *source) -{ - assert(target); - assert(source); - - (void)strcpy(target, source); - return TRUE; -} - -#endif - -/** - Copy at most @p max - 1 characters from @p source to @p target. - - @param target Target string. - @param max Maximum number of characters to append (one of which is - a NUL terminator). In other words @p source must point to at least - @p max - 1 bytes, but @p target must point to at least @p max - bytes. - @param source Source string. - @return Boolean value indicating success or failure. - - @pre @p target must point to a memory chunk with sufficient room to - contain the @p source string and a NUL terminator (at most @p max - bytes total). - @pre No boundary checking is performed, so insufficient memory will - result in a buffer overrun. - @post @p target will be zero terminated. -*/ -#if defined(TRIO_FUNC_COPY_MAX) - -TRIO_PUBLIC_STRING int -trio_copy_max -TRIO_ARGS3((target, max, source), - char *target, - size_t max, - TRIO_CONST char *source) -{ - assert(target); - assert(source); - assert(max > 0); /* Includes != 0 */ - - (void)strncpy(target, source, max - 1); - target[max - 1] = (char)0; - return TRUE; -} - -#endif - -/** - Duplicate @p source. - - @param source Source string. - @return A copy of the @p source string. - - @post @p target will be zero terminated. -*/ -#if defined(TRIO_FUNC_DUPLICATE) - -TRIO_PUBLIC_STRING char * -trio_duplicate -TRIO_ARGS1((source), - TRIO_CONST char *source) -{ - return internal_duplicate_max(source, trio_length(source)); -} - -#endif - -/** - Duplicate at most @p max characters of @p source. - - @param source Source string. - @param max Maximum number of characters to duplicate. - @return A copy of the @p source string. - - @post @p target will be zero terminated. -*/ -#if defined(TRIO_FUNC_DUPLICATE_MAX) - -TRIO_PUBLIC_STRING char * -trio_duplicate_max -TRIO_ARGS2((source, max), - TRIO_CONST char *source, - size_t max) -{ - size_t length; - - assert(source); - assert(max > 0); - - length = trio_length(source); - if (length > max) - { - length = max; - } - return internal_duplicate_max(source, length); -} - -#endif - -/** - Compare if two strings are equal. - - @param first First string. - @param second Second string. - @return Boolean indicating whether the two strings are equal or not. - - Case-insensitive comparison. -*/ -#if defined(TRIO_FUNC_EQUAL) - -TRIO_PUBLIC_STRING int -trio_equal -TRIO_ARGS2((first, second), - TRIO_CONST char *first, - TRIO_CONST char *second) -{ - assert(first); - assert(second); - - if ((first != NULL) && (second != NULL)) - { -# if defined(USE_STRCASECMP) - return (0 == strcasecmp(first, second)); -# else - while ((*first != NIL) && (*second != NIL)) - { - if (internal_to_upper(*first) != internal_to_upper(*second)) - { - break; - } - first++; - second++; - } - return ((*first == NIL) && (*second == NIL)); -# endif - } - return FALSE; -} - -#endif - -/** - Compare if two strings are equal. - - @param first First string. - @param second Second string. - @return Boolean indicating whether the two strings are equal or not. - - Case-sensitive comparison. -*/ -#if defined(TRIO_FUNC_EQUAL_CASE) - -TRIO_PUBLIC_STRING int -trio_equal_case -TRIO_ARGS2((first, second), - TRIO_CONST char *first, - TRIO_CONST char *second) -{ - assert(first); - assert(second); - - if ((first != NULL) && (second != NULL)) - { - return (0 == strcmp(first, second)); - } - return FALSE; -} - -#endif - -/** - Compare if two strings up until the first @p max characters are equal. - - @param first First string. - @param max Maximum number of characters to compare. - @param second Second string. - @return Boolean indicating whether the two strings are equal or not. - - Case-sensitive comparison. -*/ -#if defined(TRIO_FUNC_EQUAL_CASE_MAX) - -TRIO_PUBLIC_STRING int -trio_equal_case_max -TRIO_ARGS3((first, max, second), - TRIO_CONST char *first, - size_t max, - TRIO_CONST char *second) -{ - assert(first); - assert(second); - - if ((first != NULL) && (second != NULL)) - { - return (0 == strncmp(first, second, max)); - } - return FALSE; -} - -#endif - -/** - Compare if two strings are equal. - - @param first First string. - @param second Second string. - @return Boolean indicating whether the two strings are equal or not. - - Collating characters are considered equal. -*/ -#if defined(TRIO_FUNC_EQUAL_LOCALE) - -TRIO_PUBLIC_STRING int -trio_equal_locale -TRIO_ARGS2((first, second), - TRIO_CONST char *first, - TRIO_CONST char *second) -{ - assert(first); - assert(second); - -# if defined(LC_COLLATE) - return (strcoll(first, second) == 0); -# else - return trio_equal(first, second); -# endif -} - -#endif - -/** - Compare if two strings up until the first @p max characters are equal. - - @param first First string. - @param max Maximum number of characters to compare. - @param second Second string. - @return Boolean indicating whether the two strings are equal or not. - - Case-insensitive comparison. -*/ -#if defined(TRIO_FUNC_EQUAL_MAX) - -TRIO_PUBLIC_STRING int -trio_equal_max -TRIO_ARGS3((first, max, second), - TRIO_CONST char *first, - size_t max, - TRIO_CONST char *second) -{ - assert(first); - assert(second); - - if ((first != NULL) && (second != NULL)) - { -# if defined(USE_STRNCASECMP) - return (0 == strncasecmp(first, second, max)); -# else - /* Not adequately tested yet */ - size_t cnt = 0; - while ((*first != NIL) && (*second != NIL) && (cnt <= max)) - { - if (internal_to_upper(*first) != internal_to_upper(*second)) - { - break; - } - first++; - second++; - cnt++; - } - return ((cnt == max) || ((*first == NIL) && (*second == NIL))); -# endif - } - return FALSE; -} - -#endif - -/** - Provide a textual description of an error code (errno). - - @param error_number Error number. - @return Textual description of @p error_number. -*/ -#if defined(TRIO_FUNC_ERROR) - -TRIO_PUBLIC_STRING TRIO_CONST char * -trio_error -TRIO_ARGS1((error_number), - int error_number) -{ -# if defined(USE_STRERROR) - - return strerror(error_number); - -# else -# if defined(USE_SYS_ERRLIST) - - extern char *sys_errlist[]; - extern int sys_nerr; - - return ((error_number < 0) || (error_number >= sys_nerr)) - ? "unknown" - : sys_errlist[error_number]; - -# else - - return "unknown"; - -# endif -# endif -} - -#endif - -/** - Format the date/time according to @p format. - - @param target Target string. - @param max Maximum number of characters to format. - @param format Formatting string. - @param datetime Date/time structure. - @return Number of formatted characters. - - The formatting string accepts the same specifiers as the standard C - function strftime. -*/ -#if defined(TRIO_FUNC_FORMAT_DATE_MAX) - -TRIO_PUBLIC_STRING size_t -trio_format_date_max -TRIO_ARGS4((target, max, format, datetime), - char *target, - size_t max, - TRIO_CONST char *format, - TRIO_CONST struct tm *datetime) -{ - assert(target); - assert(format); - assert(datetime); - assert(max > 0); - - return strftime(target, max, format, datetime); -} - -#endif - -/** - Calculate a hash value for a string. - - @param string String to be calculated on. - @param type Hash function. - @return Calculated hash value. - - @p type can be one of the following - @li @c TRIO_HASH_PLAIN Plain hash function. -*/ -#if defined(TRIO_FUNC_HASH) - -TRIO_PUBLIC_STRING unsigned long -trio_hash -TRIO_ARGS2((string, type), - TRIO_CONST char *string, - int type) -{ - unsigned long value = 0L; - char ch; - - assert(string); - - switch (type) - { - case TRIO_HASH_PLAIN: - while ( (ch = *string++) != NIL ) - { - value *= 31; - value += (unsigned long)ch; - } - break; - default: - assert(FALSE); - break; - } - return value; -} - -#endif - -/** - Find first occurrence of a character in a string. - - @param string String to be searched. - @param character Character to be found. - @return A pointer to the found character, or NULL if character was not found. - */ -#if defined(TRIO_FUNC_INDEX) - -TRIO_PUBLIC_STRING char * -trio_index -TRIO_ARGS2((string, character), - TRIO_CONST char *string, - int character) -{ - assert(string); - - return strchr(string, character); -} - -#endif - -/** - Find last occurrence of a character in a string. - - @param string String to be searched. - @param character Character to be found. - @return A pointer to the found character, or NULL if character was not found. - */ -#if defined(TRIO_FUNC_INDEX_LAST) - -TRIO_PUBLIC_STRING char * -trio_index_last -TRIO_ARGS2((string, character), - TRIO_CONST char *string, - int character) -{ - assert(string); - - return strchr(string, character); -} - -#endif - -/** - Convert the alphabetic letters in the string to lower-case. - - @param target String to be converted. - @return Number of processed characters (converted or not). -*/ -#if defined(TRIO_FUNC_LOWER) - -TRIO_PUBLIC_STRING int -trio_lower -TRIO_ARGS1((target), - char *target) -{ - assert(target); - - return trio_span_function(target, target, trio_to_lower); -} - -#endif - -/** - Compare two strings using wildcards. - - @param string String to be searched. - @param pattern Pattern, including wildcards, to search for. - @return Boolean value indicating success or failure. - - Case-insensitive comparison. - - The following wildcards can be used - @li @c * Match any number of characters. - @li @c ? Match a single character. -*/ -#if defined(TRIO_FUNC_MATCH) - -TRIO_PUBLIC_STRING int -trio_match -TRIO_ARGS2((string, pattern), - TRIO_CONST char *string, - TRIO_CONST char *pattern) -{ - assert(string); - assert(pattern); - - for (; ('*' != *pattern); ++pattern, ++string) - { - if (NIL == *string) - { - return (NIL == *pattern); - } - if ((internal_to_upper((int)*string) != internal_to_upper((int)*pattern)) - && ('?' != *pattern)) - { - return FALSE; - } - } - /* two-line patch to prevent *too* much recursiveness: */ - while ('*' == pattern[1]) - pattern++; - - do - { - if ( trio_match(string, &pattern[1]) ) - { - return TRUE; - } - } - while (*string++); - - return FALSE; -} - -#endif - -/** - Compare two strings using wildcards. - - @param string String to be searched. - @param pattern Pattern, including wildcards, to search for. - @return Boolean value indicating success or failure. - - Case-sensitive comparison. - - The following wildcards can be used - @li @c * Match any number of characters. - @li @c ? Match a single character. -*/ -#if defined(TRIO_FUNC_MATCH_CASE) - -TRIO_PUBLIC_STRING int -trio_match_case -TRIO_ARGS2((string, pattern), - TRIO_CONST char *string, - TRIO_CONST char *pattern) -{ - assert(string); - assert(pattern); - - for (; ('*' != *pattern); ++pattern, ++string) - { - if (NIL == *string) - { - return (NIL == *pattern); - } - if ((*string != *pattern) - && ('?' != *pattern)) - { - return FALSE; - } - } - /* two-line patch to prevent *too* much recursiveness: */ - while ('*' == pattern[1]) - pattern++; - - do - { - if ( trio_match_case(string, &pattern[1]) ) - { - return TRUE; - } - } - while (*string++); - - return FALSE; -} - -#endif - -/** - Execute a function on each character in string. - - @param target Target string. - @param source Source string. - @param Function Function to be executed. - @return Number of processed characters. -*/ -#if defined(TRIO_FUNC_SPAN_FUNCTION) - -TRIO_PUBLIC_STRING size_t -trio_span_function -TRIO_ARGS3((target, source, Function), - char *target, - TRIO_CONST char *source, - int (*Function) TRIO_PROTO((int))) -{ - size_t count = 0; - - assert(target); - assert(source); - assert(Function); - - while (*source != NIL) - { - *target++ = Function(*source++); - count++; - } - return count; -} - -#endif - -/** - Search for a substring in a string. - - @param string String to be searched. - @param substring String to be found. - @return Pointer to first occurrence of @p substring in @p string, or NULL - if no match was found. -*/ -#if defined(TRIO_FUNC_SUBSTRING) - -TRIO_PUBLIC_STRING char * -trio_substring -TRIO_ARGS2((string, substring), - TRIO_CONST char *string, - TRIO_CONST char *substring) -{ - assert(string); - assert(substring); - - return strstr(string, substring); -} - -#endif - -/** - Search for a substring in the first @p max characters of a string. - - @param string String to be searched. - @param max Maximum characters to be searched. - @param substring String to be found. - @return Pointer to first occurrence of @p substring in @p string, or NULL - if no match was found. -*/ -#if defined(TRIO_FUNC_SUBSTRING_MAX) - -TRIO_PUBLIC_STRING char * -trio_substring_max -TRIO_ARGS3((string, max, substring), - TRIO_CONST char *string, - size_t max, - TRIO_CONST char *substring) -{ - size_t count; - size_t size; - char *result = NULL; - - assert(string); - assert(substring); - - size = trio_length(substring); - if (size <= max) - { - for (count = 0; count <= max - size; count++) - { - if (trio_equal_max(substring, size, &string[count])) - { - result = (char *)&string[count]; - break; - } - } - } - return result; -} - -#endif - -/** - Tokenize string. - - @param string String to be tokenized. - @param delimiters String containing list of delimiting characters. - @return Start of new token. - - @warning @p string will be destroyed. -*/ -#if defined(TRIO_FUNC_TOKENIZE) - -TRIO_PUBLIC_STRING char * -trio_tokenize -TRIO_ARGS2((string, delimiters), - char *string, - TRIO_CONST char *delimiters) -{ - assert(delimiters); - - return strtok(string, delimiters); -} - -#endif - -/** - Convert string to floating-point number. - - @param source String to be converted. - @param endp Pointer to end of the converted string. - @return A floating-point number. - - The following Extended Backus-Naur form is used - @verbatim - double ::= [ ] - ( | - | - ) - [ [ ] ] - number ::= 1*( ) - digit ::= ( '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' ) - exponential ::= ( 'e' | 'E' ) - sign ::= ( '-' | '+' ) - decimal_point ::= '.' - @endverbatim -*/ -#if defined(TRIO_FUNC_TO_LONG_DOUBLE) - -/* FIXME: Add EBNF for hex-floats */ -TRIO_PUBLIC_STRING trio_long_double_t -trio_to_long_double -TRIO_ARGS2((source, endp), - TRIO_CONST char *source, - char **endp) -{ -# if defined(USE_STRTOLD) - return strtold(source, endp); -# else - int isNegative = FALSE; - int isExponentNegative = FALSE; - trio_long_double_t integer = 0.0; - trio_long_double_t fraction = 0.0; - unsigned long exponent = 0; - trio_long_double_t base; - trio_long_double_t fracdiv = 1.0; - trio_long_double_t value = 0.0; - - /* First try hex-floats */ - if ((source[0] == '0') && ((source[1] == 'x') || (source[1] == 'X'))) - { - base = 16.0; - source += 2; - while (isxdigit((int)*source)) - { - integer *= base; - integer += (isdigit((int)*source) - ? (*source - '0') - : 10 + (internal_to_upper((int)*source) - 'A')); - source++; - } - if (*source == '.') - { - source++; - while (isxdigit((int)*source)) - { - fracdiv /= base; - fraction += fracdiv * (isdigit((int)*source) - ? (*source - '0') - : 10 + (internal_to_upper((int)*source) - 'A')); - source++; - } - if ((*source == 'p') || (*source == 'P')) - { - source++; - if ((*source == '+') || (*source == '-')) - { - isExponentNegative = (*source == '-'); - source++; - } - while (isdigit((int)*source)) - { - exponent *= 10; - exponent += (*source - '0'); - source++; - } - } - } - /* For later use with exponent */ - base = 2.0; - } - else /* Then try normal decimal floats */ - { - base = 10.0; - isNegative = (*source == '-'); - /* Skip sign */ - if ((*source == '+') || (*source == '-')) - source++; - - /* Integer part */ - while (isdigit((int)*source)) - { - integer *= base; - integer += (*source - '0'); - source++; - } - - if (*source == '.') - { - source++; /* skip decimal point */ - while (isdigit((int)*source)) - { - fracdiv /= base; - fraction += (*source - '0') * fracdiv; - source++; - } - } - if ((*source == 'e') - || (*source == 'E') -# if TRIO_MICROSOFT - || (*source == 'd') - || (*source == 'D') -# endif - ) - { - source++; /* Skip exponential indicator */ - isExponentNegative = (*source == '-'); - if ((*source == '+') || (*source == '-')) - source++; - while (isdigit((int)*source)) - { - exponent *= (int)base; - exponent += (*source - '0'); - source++; - } - } - } - - value = integer + fraction; - if (exponent != 0) - { - if (isExponentNegative) - value /= trio_powl(base, (trio_long_double_t)exponent); - else - value *= trio_powl(base, (trio_long_double_t)exponent); - } - if (isNegative) - value = -value; - - if (endp) - *endp = (char *)source; - return value; -# endif -} - -#endif - -/** - Convert string to floating-point number. - - @param source String to be converted. - @param endp Pointer to end of the converted string. - @return A floating-point number. - - See @ref trio_to_long_double. -*/ -#if defined(TRIO_FUNC_TO_DOUBLE) - -TRIO_PUBLIC_STRING double -trio_to_double -TRIO_ARGS2((source, endp), - TRIO_CONST char *source, - char **endp) -{ -#if defined(USE_STRTOD) - return strtod(source, endp); -#else - return (double)trio_to_long_double(source, endp); -#endif -} - -#endif - -/** - Convert string to floating-point number. - - @param source String to be converted. - @param endp Pointer to end of the converted string. - @return A floating-point number. - - See @ref trio_to_long_double. -*/ -#if defined(TRIO_FUNC_TO_FLOAT) - -TRIO_PUBLIC_STRING float -trio_to_float -TRIO_ARGS2((source, endp), - TRIO_CONST char *source, - char **endp) -{ -# if defined(USE_STRTOF) - return strtof(source, endp); -# else - return (float)trio_to_long_double(source, endp); -# endif -} - -#endif - -/** - Convert string to signed integer. - - @param string String to be converted. - @param endp Pointer to end of converted string. - @param base Radix number of number. -*/ -#if defined(TRIO_FUNC_TO_LONG) - -TRIO_PUBLIC_STRING long -trio_to_long -TRIO_ARGS3((string, endp, base), - TRIO_CONST char *string, - char **endp, - int base) -{ - assert(string); - assert((base >= 2) && (base <= 36)); - - return strtol(string, endp, base); -} - -#endif - -/** - Convert one alphabetic letter to lower-case. - - @param source The letter to be converted. - @return The converted letter. -*/ -#if defined(TRIO_FUNC_TO_LOWER) - -TRIO_PUBLIC_STRING int -trio_to_lower -TRIO_ARGS1((source), - int source) -{ -# if defined(HAVE_TOLOWER) - - return tolower(source); - -# else - - /* Does not handle locales or non-contiguous alphabetic characters */ - return ((source >= (int)'A') && (source <= (int)'Z')) - ? source - 'A' + 'a' - : source; - -# endif -} - -#endif - -/** - Convert string to unsigned integer. - - @param string String to be converted. - @param endp Pointer to end of converted string. - @param base Radix number of number. -*/ -#if defined(TRIO_FUNC_TO_UNSIGNED_LONG) - -TRIO_PUBLIC_STRING unsigned long -trio_to_unsigned_long -TRIO_ARGS3((string, endp, base), - TRIO_CONST char *string, - char **endp, - int base) -{ - assert(string); - assert((base >= 2) && (base <= 36)); - - return strtoul(string, endp, base); -} - -#endif - -/** - Convert one alphabetic letter to upper-case. - - @param source The letter to be converted. - @return The converted letter. -*/ -#if defined(TRIO_FUNC_TO_UPPER) - -TRIO_PUBLIC_STRING int -trio_to_upper -TRIO_ARGS1((source), - int source) -{ - return internal_to_upper(source); -} - -#endif - -/** - Convert the alphabetic letters in the string to upper-case. - - @param target The string to be converted. - @return The number of processed characters (converted or not). -*/ -#if defined(TRIO_FUNC_UPPER) - -TRIO_PUBLIC_STRING int -trio_upper -TRIO_ARGS1((target), - char *target) -{ - assert(target); - - return trio_span_function(target, target, internal_to_upper); -} - -#endif - -/** @} End of StaticStrings */ - - -/************************************************************************* - * Dynamic String Functions - */ - -#if defined(TRIO_DOCUMENTATION) -# include "doc/doc_dynamic.h" -#endif -/** @addtogroup DynamicStrings - @{ -*/ - -/** - Create a new dynamic string. - - @param initial_size Initial size of the buffer. - @return Newly allocated dynamic string, or NULL if memory allocation failed. -*/ -#if defined(TRIO_FUNC_STRING_CREATE) - -TRIO_PUBLIC_STRING trio_string_t * -trio_string_create -TRIO_ARGS1((initial_size), - int initial_size) -{ - trio_string_t *self; - - self = internal_string_alloc(); - if (self) - { - if (internal_string_grow(self, - (size_t)((initial_size > 0) ? initial_size : 1))) - { - self->content[0] = (char)0; - self->allocated = initial_size; - } - else - { - trio_string_destroy(self); - self = NULL; - } - } - return self; -} - -#endif - -/** - Deallocate the dynamic string and its contents. - - @param self Dynamic string -*/ -#if defined(TRIO_FUNC_STRING_DESTROY) - -TRIO_PUBLIC_STRING void -trio_string_destroy -TRIO_ARGS1((self), - trio_string_t *self) -{ - assert(self); - - if (self) - { - trio_destroy(self->content); - TRIO_FREE(self); - } -} - -#endif - -/** - Get a pointer to the content. - - @param self Dynamic string. - @param offset Offset into content. - @return Pointer to the content. - - @p Offset can be zero, positive, or negative. If @p offset is zero, - then the start of the content will be returned. If @p offset is positive, - then a pointer to @p offset number of characters from the beginning of the - content is returned. If @p offset is negative, then a pointer to @p offset - number of characters from the ending of the string, starting at the - terminating zero, is returned. -*/ -#if defined(TRIO_FUNC_STRING_GET) - -TRIO_PUBLIC_STRING char * -trio_string_get -TRIO_ARGS2((self, offset), - trio_string_t *self, - int offset) -{ - char *result = NULL; - - assert(self); - - if (self->content != NULL) - { - if (self->length == 0) - { - (void)trio_string_length(self); - } - if (offset >= 0) - { - if (offset > (int)self->length) - { - offset = self->length; - } - } - else - { - offset += self->length + 1; - if (offset < 0) - { - offset = 0; - } - } - result = &(self->content[offset]); - } - return result; -} - -#endif - -/** - Extract the content. - - @param self Dynamic String - @return Content of dynamic string. - - The content is removed from the dynamic string. This enables destruction - of the dynamic string without deallocation of the content. -*/ -#if defined(TRIO_FUNC_STRING_EXTRACT) - -TRIO_PUBLIC_STRING char * -trio_string_extract -TRIO_ARGS1((self), - trio_string_t *self) -{ - char *result; - - assert(self); - - result = self->content; - /* FIXME: Allocate new empty buffer? */ - self->content = NULL; - self->length = self->allocated = 0; - return result; -} - -#endif - -/** - Set the content of the dynamic string. - - @param self Dynamic String - @param buffer The new content. - - Sets the content of the dynamic string to a copy @p buffer. - An existing content will be deallocated first, if necessary. - - @remark - This function will make a copy of @p buffer. - You are responsible for deallocating @p buffer yourself. -*/ -#if defined(TRIO_FUNC_XSTRING_SET) - -TRIO_PUBLIC_STRING void -trio_xstring_set -TRIO_ARGS2((self, buffer), - trio_string_t *self, - char *buffer) -{ - assert(self); - - trio_destroy(self->content); - self->content = trio_duplicate(buffer); -} - -#endif - -/* - * trio_string_size - */ -#if defined(TRIO_FUNC_STRING_SIZE) - -TRIO_PUBLIC_STRING int -trio_string_size -TRIO_ARGS1((self), - trio_string_t *self) -{ - assert(self); - - return self->allocated; -} - -#endif - -/* - * trio_string_terminate - */ -#if defined(TRIO_FUNC_STRING_TERMINATE) - -TRIO_PUBLIC_STRING void -trio_string_terminate -TRIO_ARGS1((self), - trio_string_t *self) -{ - trio_xstring_append_char(self, 0); -} - -#endif - -/** - Append the second string to the first. - - @param self Dynamic string to be modified. - @param other Dynamic string to copy from. - @return Boolean value indicating success or failure. -*/ -#if defined(TRIO_FUNC_STRING_APPEND) - -TRIO_PUBLIC_STRING int -trio_string_append -TRIO_ARGS2((self, other), - trio_string_t *self, - trio_string_t *other) -{ - size_t length; - - assert(self); - assert(other); - - length = self->length + other->length; - if (!internal_string_grow_to(self, length)) - goto error; - trio_copy(&self->content[self->length], other->content); - self->length = length; - return TRUE; - - error: - return FALSE; -} - -#endif - - -/* - * trio_xstring_append - */ -#if defined(TRIO_FUNC_XSTRING_APPEND) - -TRIO_PUBLIC_STRING int -trio_xstring_append -TRIO_ARGS2((self, other), - trio_string_t *self, - TRIO_CONST char *other) -{ - size_t length; - - assert(self); - assert(other); - - length = self->length + trio_length(other); - if (!internal_string_grow_to(self, length)) - goto error; - trio_copy(&self->content[self->length], other); - self->length = length; - return TRUE; - - error: - return FALSE; -} - -#endif - -/* - * trio_xstring_append_char - */ -#if defined(TRIO_FUNC_XSTRING_APPEND_CHAR) - -TRIO_PUBLIC_STRING int -trio_xstring_append_char -TRIO_ARGS2((self, character), - trio_string_t *self, - char character) -{ - assert(self); - - if ((int)self->length >= trio_string_size(self)) - { - if (!internal_string_grow(self, 0)) - goto error; - } - self->content[self->length] = character; - self->length++; - return TRUE; - - error: - return FALSE; -} - -#endif - -/* - * trio_xstring_append_max - */ -#if defined(TRIO_FUNC_XSTRING_APPEND_MAX) - -TRIO_PUBLIC_STRING int -trio_xstring_append_max -TRIO_ARGS3((self, other, max), - trio_string_t *self, - TRIO_CONST char *other, - size_t max) -{ - size_t length; - - assert(self); - assert(other); - - length = self->length + trio_length_max(other, max); - if (!internal_string_grow_to(self, length)) - goto error; - - /* - * Pass max + 1 since trio_copy_max copies one character less than - * this from the source to make room for a terminating zero. - */ - trio_copy_max(&self->content[self->length], max + 1, other); - self->length = length; - return TRUE; - - error: - return FALSE; -} - -#endif - -/** - Search for the first occurrence of second parameter in the first. - - @param self Dynamic string to be modified. - @param other Dynamic string to copy from. - @return Boolean value indicating success or failure. -*/ -#if defined(TRIO_FUNC_STRING_CONTAINS) - -TRIO_PUBLIC_STRING int -trio_string_contains -TRIO_ARGS2((self, other), - trio_string_t *self, - trio_string_t *other) -{ - assert(self); - assert(other); - - return trio_contains(self->content, other->content); -} - -#endif - -/* - * trio_xstring_contains - */ -#if defined(TRIO_FUNC_XSTRING_CONTAINS) - -TRIO_PUBLIC_STRING int -trio_xstring_contains -TRIO_ARGS2((self, other), - trio_string_t *self, - TRIO_CONST char *other) -{ - assert(self); - assert(other); - - return trio_contains(self->content, other); -} - -#endif - -/* - * trio_string_copy - */ -#if defined(TRIO_FUNC_STRING_COPY) - -TRIO_PUBLIC_STRING int -trio_string_copy -TRIO_ARGS2((self, other), - trio_string_t *self, - trio_string_t *other) -{ - assert(self); - assert(other); - - self->length = 0; - return trio_string_append(self, other); -} - -#endif - - -/* - * trio_xstring_copy - */ -#if defined(TRIO_FUNC_XSTRING_COPY) - -TRIO_PUBLIC_STRING int -trio_xstring_copy -TRIO_ARGS2((self, other), - trio_string_t *self, - TRIO_CONST char *other) -{ - assert(self); - assert(other); - - self->length = 0; - return trio_xstring_append(self, other); -} - -#endif - -/* - * trio_string_duplicate - */ -#if defined(TRIO_FUNC_STRING_DUPLICATE) - -TRIO_PUBLIC_STRING trio_string_t * -trio_string_duplicate -TRIO_ARGS1((other), - trio_string_t *other) -{ - trio_string_t *self; - - assert(other); - - self = internal_string_alloc(); - if (self) - { - self->content = internal_duplicate_max(other->content, other->length); - if (self->content) - { - self->length = other->length; - self->allocated = self->length + 1; - } - else - { - self->length = self->allocated = 0; - } - } - return self; -} - -#endif - -/* - * trio_xstring_duplicate - */ -#if defined(TRIO_FUNC_XSTRING_DUPLICATE) - -TRIO_PUBLIC_STRING trio_string_t * -trio_xstring_duplicate -TRIO_ARGS1((other), - TRIO_CONST char *other) -{ - trio_string_t *self; - - assert(other); - - self = internal_string_alloc(); - if (self) - { - self->content = internal_duplicate_max(other, trio_length(other)); - if (self->content) - { - self->length = trio_length(self->content); - self->allocated = self->length + 1; - } - else - { - self->length = self->allocated = 0; - } - } - return self; -} - -#endif - -/* - * trio_string_equal - */ -#if defined(TRIO_FUNC_STRING_EQUAL) - -TRIO_PUBLIC_STRING int -trio_string_equal -TRIO_ARGS2((self, other), - trio_string_t *self, - trio_string_t *other) -{ - assert(self); - assert(other); - - return trio_equal(self->content, other->content); -} - -#endif - - -/* - * trio_xstring_equal - */ -#if defined(TRIO_FUNC_XSTRING_EQUAL) - -TRIO_PUBLIC_STRING int -trio_xstring_equal -TRIO_ARGS2((self, other), - trio_string_t *self, - TRIO_CONST char *other) -{ - assert(self); - assert(other); - - return trio_equal(self->content, other); -} - -#endif - -/* - * trio_string_equal_max - */ -#if defined(TRIO_FUNC_STRING_EQUAL_MAX) - -TRIO_PUBLIC_STRING int -trio_string_equal_max -TRIO_ARGS3((self, max, other), - trio_string_t *self, - size_t max, - trio_string_t *other) -{ - assert(self); - assert(other); - - return trio_equal_max(self->content, max, other->content); -} -#endif - -/* - * trio_xstring_equal_max - */ -#if defined(TRIO_FUNC_XSTRING_EQUAL_MAX) - -TRIO_PUBLIC_STRING int -trio_xstring_equal_max -TRIO_ARGS3((self, max, other), - trio_string_t *self, - size_t max, - TRIO_CONST char *other) -{ - assert(self); - assert(other); - - return trio_equal_max(self->content, max, other); -} - -#endif - -/* - * trio_string_equal_case - */ -#if defined(TRIO_FUNC_STRING_EQUAL_CASE) - -TRIO_PUBLIC_STRING int -trio_string_equal_case -TRIO_ARGS2((self, other), - trio_string_t *self, - trio_string_t *other) -{ - assert(self); - assert(other); - - return trio_equal_case(self->content, other->content); -} - -#endif - -/* - * trio_xstring_equal_case - */ -#if defined(TRIO_FUNC_XSTRING_EQUAL_CASE) - -TRIO_PUBLIC_STRING int -trio_xstring_equal_case -TRIO_ARGS2((self, other), - trio_string_t *self, - TRIO_CONST char *other) -{ - assert(self); - assert(other); - - return trio_equal_case(self->content, other); -} - -#endif - -/* - * trio_string_equal_case_max - */ -#if defined(TRIO_FUNC_STRING_EQUAL_CASE_MAX) - -TRIO_PUBLIC_STRING int -trio_string_equal_case_max -TRIO_ARGS3((self, max, other), - trio_string_t *self, - size_t max, - trio_string_t *other) -{ - assert(self); - assert(other); - - return trio_equal_case_max(self->content, max, other->content); -} - -#endif - -/* - * trio_xstring_equal_case_max - */ -#if defined(TRIO_FUNC_XSTRING_EQUAL_CASE_MAX) - -TRIO_PUBLIC_STRING int -trio_xstring_equal_case_max -TRIO_ARGS3((self, max, other), - trio_string_t *self, - size_t max, - TRIO_CONST char *other) -{ - assert(self); - assert(other); - - return trio_equal_case_max(self->content, max, other); -} - -#endif - -/* - * trio_string_format_data_max - */ -#if defined(TRIO_FUNC_STRING_FORMAT_DATE_MAX) - -TRIO_PUBLIC_STRING size_t -trio_string_format_date_max -TRIO_ARGS4((self, max, format, datetime), - trio_string_t *self, - size_t max, - TRIO_CONST char *format, - TRIO_CONST struct tm *datetime) -{ - assert(self); - - return trio_format_date_max(self->content, max, format, datetime); -} - -#endif - -/* - * trio_string_index - */ -#if defined(TRIO_FUNC_STRING_INDEX) - -TRIO_PUBLIC_STRING char * -trio_string_index -TRIO_ARGS2((self, character), - trio_string_t *self, - int character) -{ - assert(self); - - return trio_index(self->content, character); -} - -#endif - -/* - * trio_string_index_last - */ -#if defined(TRIO_FUNC_STRING_INDEX_LAST) - -TRIO_PUBLIC_STRING char * -trio_string_index_last -TRIO_ARGS2((self, character), - trio_string_t *self, - int character) -{ - assert(self); - - return trio_index_last(self->content, character); -} - -#endif - -/* - * trio_string_length - */ -#if defined(TRIO_FUNC_STRING_LENGTH) - -TRIO_PUBLIC_STRING int -trio_string_length -TRIO_ARGS1((self), - trio_string_t *self) -{ - assert(self); - - if (self->length == 0) - { - self->length = trio_length(self->content); - } - return self->length; -} - -#endif - -/* - * trio_string_lower - */ -#if defined(TRIO_FUNC_STRING_LOWER) - -TRIO_PUBLIC_STRING int -trio_string_lower -TRIO_ARGS1((self), - trio_string_t *self) -{ - assert(self); - - return trio_lower(self->content); -} - -#endif - -/* - * trio_string_match - */ -#if defined(TRIO_FUNC_STRING_MATCH) - -TRIO_PUBLIC_STRING int -trio_string_match -TRIO_ARGS2((self, other), - trio_string_t *self, - trio_string_t *other) -{ - assert(self); - assert(other); - - return trio_match(self->content, other->content); -} - -#endif - -/* - * trio_xstring_match - */ -#if defined(TRIO_FUNC_XSTRING_MATCH) - -TRIO_PUBLIC_STRING int -trio_xstring_match -TRIO_ARGS2((self, other), - trio_string_t *self, - TRIO_CONST char *other) -{ - assert(self); - assert(other); - - return trio_match(self->content, other); -} - -#endif - -/* - * trio_string_match_case - */ -#if defined(TRIO_FUNC_STRING_MATCH_CASE) - -TRIO_PUBLIC_STRING int -trio_string_match_case -TRIO_ARGS2((self, other), - trio_string_t *self, - trio_string_t *other) -{ - assert(self); - assert(other); - - return trio_match_case(self->content, other->content); -} - -#endif - -/* - * trio_xstring_match_case - */ -#if defined(TRIO_FUNC_XSTRING_MATCH_CASE) - -TRIO_PUBLIC_STRING int -trio_xstring_match_case -TRIO_ARGS2((self, other), - trio_string_t *self, - TRIO_CONST char *other) -{ - assert(self); - assert(other); - - return trio_match_case(self->content, other); -} - -#endif - -/* - * trio_string_substring - */ -#if defined(TRIO_FUNC_STRING_SUBSTRING) - -TRIO_PUBLIC_STRING char * -trio_string_substring -TRIO_ARGS2((self, other), - trio_string_t *self, - trio_string_t *other) -{ - assert(self); - assert(other); - - return trio_substring(self->content, other->content); -} - -#endif - -/* - * trio_xstring_substring - */ -#if defined(TRIO_FUNC_XSTRING_SUBSTRING) - -TRIO_PUBLIC_STRING char * -trio_xstring_substring -TRIO_ARGS2((self, other), - trio_string_t *self, - TRIO_CONST char *other) -{ - assert(self); - assert(other); - - return trio_substring(self->content, other); -} - -#endif - -/* - * trio_string_upper - */ -#if defined(TRIO_FUNC_STRING_UPPER) - -TRIO_PUBLIC_STRING int -trio_string_upper -TRIO_ARGS1((self), - trio_string_t *self) -{ - assert(self); - - return trio_upper(self->content); -} - -#endif - -/** @} End of DynamicStrings */ diff --git a/psx/mednadisc/trio/triostr.h b/psx/mednadisc/trio/triostr.h deleted file mode 100644 index 1e6939bc1f8..00000000000 --- a/psx/mednadisc/trio/triostr.h +++ /dev/null @@ -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 -#include -#include -#include -#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 */ diff --git a/psx/octoshock/FileStream.cpp b/psx/octoshock/FileStream.cpp deleted file mode 100644 index 1e7c1adf75e..00000000000 --- a/psx/octoshock/FileStream.cpp +++ /dev/null @@ -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 -#include "mednafen.h" -#include "Stream.h" -#include "FileStream.h" - -#include -#include -#include - -#ifdef _WIN32 -#include -#else -#include -#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); -} diff --git a/psx/octoshock/FileStream.h b/psx/octoshock/FileStream.h deleted file mode 100644 index 97ccd2a7478..00000000000 --- a/psx/octoshock/FileStream.h +++ /dev/null @@ -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 diff --git a/psx/octoshock/FileWrapper.cpp b/psx/octoshock/FileWrapper.cpp deleted file mode 100644 index 8e566451956..00000000000 --- a/psx/octoshock/FileWrapper.cpp +++ /dev/null @@ -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 -#include "mednafen.h" -#include "FileWrapper.h" - -#include -#include -#include - -#ifdef _WIN32 -#include -#else -#include -#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); -} diff --git a/psx/octoshock/FileWrapper.h b/psx/octoshock/FileWrapper.h deleted file mode 100644 index c4d11fd77b0..00000000000 --- a/psx/octoshock/FileWrapper.h +++ /dev/null @@ -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 diff --git a/psx/octoshock/Stream.cpp b/psx/octoshock/Stream.cpp deleted file mode 100644 index abe4f2bbd9e..00000000000 --- a/psx/octoshock/Stream.cpp +++ /dev/null @@ -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 - -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; -} diff --git a/psx/octoshock/Stream.h b/psx/octoshock/Stream.h deleted file mode 100644 index eecc10eea28..00000000000 --- a/psx/octoshock/Stream.h +++ /dev/null @@ -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 - -#include // For SEEK_* defines, which we will use in Stream out of FORCE OF HABIT. -#include - -#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 - INLINE T get_NE(void) - { - T ret; - - read(&ret, sizeof(ret)); - - return ret; - } - - template - INLINE void put_NE(T c) - { - write(&c, sizeof(c)); - } - - - template - 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 - 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 - INLINE T get_LE(void) - { - #ifdef LSB_FIRST - return get_NE(); - #else - return get_RE(); - #endif - } - - template - INLINE void put_LE(T c) - { - #ifdef LSB_FIRST - return put_NE(c); - #else - return put_RE(c); - #endif - } - - template - INLINE T get_BE(void) - { - #ifndef LSB_FIRST - return get_NE(); - #else - return get_RE(); - #endif - } - - template - INLINE void put_BE(T c) - { - #ifndef LSB_FIRST - return put_NE(c); - #else - return put_RE(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 diff --git a/psx/octoshock/bizhawk/octoshock.sln b/psx/octoshock/bizhawk/octoshock.sln deleted file mode 100644 index b673e808dec..00000000000 --- a/psx/octoshock/bizhawk/octoshock.sln +++ /dev/null @@ -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 diff --git a/psx/octoshock/bizhawk/octoshock.vcxproj b/psx/octoshock/bizhawk/octoshock.vcxproj deleted file mode 100644 index 1a9ad75f5c4..00000000000 --- a/psx/octoshock/bizhawk/octoshock.vcxproj +++ /dev/null @@ -1,169 +0,0 @@ - - - - - Debug - x64 - - - Release - x64 - - - - 17.0 - {8610A02C-7420-4237-89D3-31BBC9A459AD} - Win32Proj - 10.0 - - - - DynamicLibrary - true - v143 - Unicode - - - DynamicLibrary - false - v143 - Unicode - true - - - - - - - - - - - - - - - true - - - - ..;%(AdditionalIncludeDirectories) - EW_EXPORT;WANT_LEC_CHECK;%(PreprocessorDefinitions) - true - - - copy /Y "$(TargetDir)$(TargetName).dll" "$(SolutionDir)..\..\..\Assets\dll\$(TargetName).dll" -copy /Y "$(TargetDir)$(TargetName).dll" "$(SolutionDir)..\..\..\output\dll\$(TargetName).dll" - - - - - ..;%(AdditionalIncludeDirectories) - EW_EXPORT;WANT_LEC_CHECK;%(PreprocessorDefinitions) - true - true - - - copy /Y "$(TargetDir)$(TargetName).dll" "$(SolutionDir)..\..\..\Assets\dll\$(TargetName).dll" -copy /Y "$(TargetDir)$(TargetName).dll" "$(SolutionDir)..\..\..\output\dll\$(TargetName).dll" - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/psx/octoshock/bizhawk/octoshock.vcxproj.filters b/psx/octoshock/bizhawk/octoshock.vcxproj.filters deleted file mode 100644 index aa41fe79cde..00000000000 --- a/psx/octoshock/bizhawk/octoshock.vcxproj.filters +++ /dev/null @@ -1,269 +0,0 @@ - - - - - {00f73db4-1182-4bf7-b891-66bf860d3742} - - - {f69cc8f2-7480-44d6-9a32-9dca789d2bf6} - - - {57a8e6ec-9225-410d-b38f-ba209abae070} - - - {76abb796-5411-4d33-b3e0-f1f3873f138e} - - - {cb700979-4dce-4b10-8521-3ab71a313271} - - - {d1f71901-17a5-441a-8b4f-f7da34a057c1} - - - - - psx - - - psx - - - psx - - - psx - - - psx - - - - psx - - - psx - - - psx - - - psx - - - psx - - - psx - - - psx - - - - psx\input - - - psx\input - - - psx\input - - - psx\input - - - psx\input - - - psx\input - - - psx\input - - - psx\input - - - psx\input - - - - emuware - - - video - - - video - - - video - - - emuware - - - psx - - - psx - - - psx - - - psx - - - cdrom - - - - cdrom - - - cdrom - - - cdrom - - - cdrom - - - cdrom - - - - - psx - - - psx - - - emuware - - - psx - - - psx - - - - - - psx - - - - - - psx - - - psx - - - psx - - - psx - - - psx - - - psx - - - psx - - - psx\input - - - psx\input - - - psx\input - - - psx\input - - - psx\input - - - psx\input - - - psx\input - - - psx\input - - - psx\input - - - emuware\msvc - - - emuware\msvc - - - video - - - video - - - video - - - emuware - - - cdrom - - - psx - - - psx - - - cdrom - - - cdrom - - - cdrom - - - cdrom - - - psx - - - psx - - - - - - - psx - - - psx - - - psx - - - \ No newline at end of file diff --git a/psx/octoshock/bizhawk/octoshock.xcodeproj/project.pbxproj b/psx/octoshock/bizhawk/octoshock.xcodeproj/project.pbxproj deleted file mode 100644 index d35e803a417..00000000000 --- a/psx/octoshock/bizhawk/octoshock.xcodeproj/project.pbxproj +++ /dev/null @@ -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 = ""; }; - 9E11BDEC1A41204F00CC7F6B /* CDUtility.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDUtility.h; sourceTree = ""; }; - 9E11BDED1A41204F00CC7F6B /* crc32.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = crc32.cpp; sourceTree = ""; }; - 9E11BDF01A41204F00CC7F6B /* galois.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = galois.cpp; sourceTree = ""; }; - 9E11BDF11A41204F00CC7F6B /* l-ec.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "l-ec.cpp"; sourceTree = ""; }; - 9E11BDF21A41204F00CC7F6B /* lec.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = lec.cpp; sourceTree = ""; }; - 9E11BDF31A41204F00CC7F6B /* lec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = lec.h; sourceTree = ""; }; - 9E11BDF41A41204F00CC7F6B /* recover-raw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "recover-raw.cpp"; sourceTree = ""; }; - 9E11BDF81A41204F00CC7F6B /* emuware.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = emuware.cpp; sourceTree = ""; }; - 9E11BDF91A41204F00CC7F6B /* emuware.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = emuware.h; sourceTree = ""; }; - 9E11BDFA1A41204F00CC7F6B /* EW_state.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = EW_state.cpp; sourceTree = ""; }; - 9E11BDFB1A41204F00CC7F6B /* EW_state.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EW_state.h; sourceTree = ""; }; - 9E11BE001A41204F00CC7F6B /* PACKED.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PACKED.h; sourceTree = ""; }; - 9E11BE011A41204F00CC7F6B /* PACKED_END.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PACKED_END.h; sourceTree = ""; }; - 9E11BE021A41204F00CC7F6B /* endian.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = endian.cpp; path = ../endian.cpp; sourceTree = ""; }; - 9E11BE031A41204F00CC7F6B /* endian.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = endian.h; path = ../endian.h; sourceTree = ""; }; - 9E11BE041A41204F00CC7F6B /* error.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = error.h; path = ../error.h; sourceTree = ""; }; - 9E11BE0B1A41204F00CC7F6B /* git.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = git.h; path = ../git.h; sourceTree = ""; }; - 9E11BE0C1A41204F00CC7F6B /* math_ops.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = math_ops.h; path = ../math_ops.h; sourceTree = ""; }; - 9E11BE0D1A41204F00CC7F6B /* octoshock.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = octoshock.cpp; path = ../octoshock.cpp; sourceTree = ""; }; - 9E11BE0E1A41204F00CC7F6B /* octoshock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = octoshock.h; path = ../octoshock.h; sourceTree = ""; }; - 9E11BE101A41204F00CC7F6B /* cdc.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = cdc.cpp; sourceTree = ""; }; - 9E11BE111A41204F00CC7F6B /* cdc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cdc.h; sourceTree = ""; }; - 9E11BE121A41204F00CC7F6B /* cpu.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = cpu.cpp; sourceTree = ""; }; - 9E11BE131A41204F00CC7F6B /* cpu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cpu.h; sourceTree = ""; }; - 9E11BE141A41204F00CC7F6B /* cpu_bigswitch.inc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.pascal; path = cpu_bigswitch.inc; sourceTree = ""; }; - 9E11BE151A41204F00CC7F6B /* cpu_computedgoto.inc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.pascal; path = cpu_computedgoto.inc; sourceTree = ""; }; - 9E11BE181A41204F00CC7F6B /* dis.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = dis.cpp; sourceTree = ""; }; - 9E11BE191A41204F00CC7F6B /* dis.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dis.h; sourceTree = ""; }; - 9E11BE1A1A41204F00CC7F6B /* dma.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = dma.cpp; sourceTree = ""; }; - 9E11BE1B1A41204F00CC7F6B /* dma.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dma.h; sourceTree = ""; }; - 9E11BE1C1A41204F00CC7F6B /* frontio.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = frontio.cpp; sourceTree = ""; }; - 9E11BE1D1A41204F00CC7F6B /* frontio.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = frontio.h; sourceTree = ""; }; - 9E11BE1E1A41204F00CC7F6B /* gpu.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = gpu.cpp; sourceTree = ""; }; - 9E11BE1F1A41204F00CC7F6B /* gpu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = gpu.h; sourceTree = ""; }; - 9E11BE201A41204F00CC7F6B /* gpu_common.inc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.pascal; path = gpu_common.inc; sourceTree = ""; }; - 9E11BE211A41204F00CC7F6B /* gpu_line.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = gpu_line.cpp; sourceTree = ""; }; - 9E11BE221A41204F00CC7F6B /* gpu_polygon.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = gpu_polygon.cpp; sourceTree = ""; }; - 9E11BE231A41204F00CC7F6B /* gpu_sprite.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = gpu_sprite.cpp; sourceTree = ""; }; - 9E11BE241A41204F00CC7F6B /* gte.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = gte.cpp; sourceTree = ""; }; - 9E11BE251A41204F00CC7F6B /* gte.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = gte.h; sourceTree = ""; }; - 9E11BE271A41204F00CC7F6B /* dualanalog.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = dualanalog.cpp; sourceTree = ""; }; - 9E11BE281A41204F00CC7F6B /* dualanalog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dualanalog.h; sourceTree = ""; }; - 9E11BE291A41204F00CC7F6B /* dualshock.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = dualshock.cpp; sourceTree = ""; }; - 9E11BE2A1A41204F00CC7F6B /* dualshock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dualshock.h; sourceTree = ""; }; - 9E11BE2B1A41204F00CC7F6B /* gamepad.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = gamepad.cpp; sourceTree = ""; }; - 9E11BE2C1A41204F00CC7F6B /* gamepad.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = gamepad.h; sourceTree = ""; }; - 9E11BE2D1A41204F00CC7F6B /* guncon.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = guncon.cpp; sourceTree = ""; }; - 9E11BE2E1A41204F00CC7F6B /* guncon.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = guncon.h; sourceTree = ""; }; - 9E11BE2F1A41204F00CC7F6B /* justifier.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = justifier.cpp; sourceTree = ""; }; - 9E11BE301A41204F00CC7F6B /* justifier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = justifier.h; sourceTree = ""; }; - 9E11BE311A41204F00CC7F6B /* memcard.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = memcard.cpp; sourceTree = ""; }; - 9E11BE321A41204F00CC7F6B /* memcard.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = memcard.h; sourceTree = ""; }; - 9E11BE331A41204F00CC7F6B /* mouse.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = mouse.cpp; sourceTree = ""; }; - 9E11BE341A41204F00CC7F6B /* mouse.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mouse.h; sourceTree = ""; }; - 9E11BE351A41204F00CC7F6B /* multitap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = multitap.cpp; sourceTree = ""; }; - 9E11BE361A41204F00CC7F6B /* multitap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = multitap.h; sourceTree = ""; }; - 9E11BE371A41204F00CC7F6B /* negcon.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = negcon.cpp; sourceTree = ""; }; - 9E11BE381A41204F00CC7F6B /* negcon.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = negcon.h; sourceTree = ""; }; - 9E11BE391A41204F00CC7F6B /* irq.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = irq.cpp; sourceTree = ""; }; - 9E11BE3A1A41204F00CC7F6B /* irq.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = irq.h; sourceTree = ""; }; - 9E11BE3D1A41204F00CC7F6B /* masmem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = masmem.h; sourceTree = ""; }; - 9E11BE3E1A41204F00CC7F6B /* mdec.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = mdec.cpp; sourceTree = ""; }; - 9E11BE3F1A41204F00CC7F6B /* mdec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mdec.h; sourceTree = ""; }; - 9E11BE401A41204F00CC7F6B /* psx.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = psx.cpp; sourceTree = ""; }; - 9E11BE411A41204F00CC7F6B /* psx.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = psx.h; sourceTree = ""; }; - 9E11BE421A41204F00CC7F6B /* sio.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = sio.cpp; sourceTree = ""; }; - 9E11BE431A41204F00CC7F6B /* sio.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sio.h; sourceTree = ""; }; - 9E11BE441A41204F00CC7F6B /* spu.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = spu.cpp; sourceTree = ""; }; - 9E11BE451A41204F00CC7F6B /* spu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = spu.h; sourceTree = ""; }; - 9E11BE461A41204F00CC7F6B /* spu_fir_table.inc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.pascal; path = spu_fir_table.inc; sourceTree = ""; }; - 9E11BE471A41204F00CC7F6B /* spu_reverb.inc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.pascal; path = spu_reverb.inc; sourceTree = ""; }; - 9E11BE481A41204F00CC7F6B /* timer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = timer.cpp; sourceTree = ""; }; - 9E11BE491A41204F00CC7F6B /* timer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = timer.h; sourceTree = ""; }; - 9E11BE4A1A41204F00CC7F6B /* Stream.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Stream.cpp; path = ../Stream.cpp; sourceTree = ""; }; - 9E11BE4B1A41204F00CC7F6B /* Stream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Stream.h; path = ../Stream.h; sourceTree = ""; }; - 9E11BE4D1A41204F00CC7F6B /* Deinterlacer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Deinterlacer.cpp; sourceTree = ""; }; - 9E11BE4E1A41204F00CC7F6B /* Deinterlacer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Deinterlacer.h; sourceTree = ""; }; - 9E11BE4F1A41204F00CC7F6B /* surface.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = surface.cpp; sourceTree = ""; }; - 9E11BE501A41204F00CC7F6B /* surface.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = surface.h; sourceTree = ""; }; - 9E11BEB71A41213D00CC7F6B /* dvdisaster.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dvdisaster.h; sourceTree = ""; }; - 9E11BEB91A41215900CC7F6B /* SimpleFIFO.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SimpleFIFO.h; sourceTree = ""; }; -/* 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 = ""; - }; - 9E11BDE01A411DA300CC7F6B /* Products */ = { - isa = PBXGroup; - children = ( - 9E11BDDF1A411DA300CC7F6B /* liboctoshock.dylib */, - ); - name = Products; - sourceTree = ""; - }; - 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 = ""; - }; - 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 = ""; - }; - 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 = ""; - }; - 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 = ""; - }; - 9E11BE4C1A41204F00CC7F6B /* video */ = { - isa = PBXGroup; - children = ( - 9E11BE4D1A41204F00CC7F6B /* Deinterlacer.cpp */, - 9E11BE4E1A41204F00CC7F6B /* Deinterlacer.h */, - 9E11BE4F1A41204F00CC7F6B /* surface.cpp */, - 9E11BE501A41204F00CC7F6B /* surface.h */, - ); - name = video; - path = ../video; - sourceTree = ""; - }; -/* 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 */; -} diff --git a/psx/octoshock/bizhawk/octoshock.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/psx/octoshock/bizhawk/octoshock.xcodeproj/project.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index 45bf46d1088..00000000000 --- a/psx/octoshock/bizhawk/octoshock.xcodeproj/project.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/psx/octoshock/cdrom/CDUtility.cpp b/psx/octoshock/cdrom/CDUtility.cpp deleted file mode 100644 index 969eee916fe..00000000000 --- a/psx/octoshock/cdrom/CDUtility.cpp +++ /dev/null @@ -1,182 +0,0 @@ -/* Mednafen - Multi-system Emulator - * - * Subchannel Q CRC Code: Copyright (C) 1998 Andreas Mueller - * - * 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 -#include - -#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; - } - } -} - -} \ No newline at end of file diff --git a/psx/octoshock/cdrom/CDUtility.h b/psx/octoshock/cdrom/CDUtility.h deleted file mode 100644 index f87d0b63cb2..00000000000 --- a/psx/octoshock/cdrom/CDUtility.h +++ /dev/null @@ -1,176 +0,0 @@ -#ifndef __MDFN_CDROM_CDUTILITY_H -#define __MDFN_CDROM_CDUTILITY_H - -#include - -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 diff --git a/psx/octoshock/cdrom/SimpleFIFO.h b/psx/octoshock/cdrom/SimpleFIFO.h deleted file mode 100644 index 0afd4b2c56b..00000000000 --- a/psx/octoshock/cdrom/SimpleFIFO.h +++ /dev/null @@ -1,155 +0,0 @@ -#ifndef __MDFN_SIMPLEFIFO_H -#define __MDFN_SIMPLEFIFO_H - -#include -#include - -#include "../math_ops.h" - -template -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 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 data; - uint32 size; - uint32 read_pos; // Read position - uint32 write_pos; // Write position - uint32 in_count; // Number of units in the FIFO - - template 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 diff --git a/psx/octoshock/cdrom/crc32.cpp b/psx/octoshock/cdrom/crc32.cpp deleted file mode 100644 index 9b3b2c8e6b5..00000000000 --- a/psx/octoshock/cdrom/crc32.cpp +++ /dev/null @@ -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; -} diff --git a/psx/octoshock/cdrom/dvdisaster.h b/psx/octoshock/cdrom/dvdisaster.h deleted file mode 100644 index 66f55f0cf2f..00000000000 --- a/psx/octoshock/cdrom/dvdisaster.h +++ /dev/null @@ -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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/*** - *** 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_FIELDMAX) - { - x -= GF_FIELDMAX; - x = (x >> GF_SYMBOLSIZE) + (x & GF_FIELDMAX); - } - - return x; -} diff --git a/psx/octoshock/cdrom/galois.cpp b/psx/octoshock/cdrom/galois.cpp deleted file mode 100644 index 2792cfc3414..00000000000 --- a/psx/octoshock/cdrom/galois.cpp +++ /dev/null @@ -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; logindexOf[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; inroots; 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); -} diff --git a/psx/octoshock/cdrom/l-ec.cpp b/psx/octoshock/cdrom/l-ec.cpp deleted file mode 100644 index 5c035ce4ab3..00000000000 --- a/psx/octoshock/cdrom/l-ec.cpp +++ /dev/null @@ -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; ialphaTo[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; iindexOf[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; i0; j--) - { int tmp = gt->indexOf[lambda[j-1]]; - - if(tmp != GF_ALPHA0) - lambda[j] ^= gt->alphaTo[mod_fieldmax(u + tmp)]; - } - } - } - - for(i=0; iindexOf[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; ialphaTo[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; ialphaTo[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; iindexOf[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; ialphaTo[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 - * - * 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 -#endif - -#include -#include - -#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 -#include -#include -#include - -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 diff --git a/psx/octoshock/cdrom/lec.h b/psx/octoshock/cdrom/lec.h deleted file mode 100644 index c5e874c3f36..00000000000 --- a/psx/octoshock/cdrom/lec.h +++ /dev/null @@ -1,77 +0,0 @@ -/* cdrdao - write audio CD-Rs in disc-at-once mode - * - * Copyright (C) 1998-2002 Andreas Mueller - * - * 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 -#endif - -#include -#include - -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 diff --git a/psx/octoshock/cdrom/recover-raw.cpp b/psx/octoshock/cdrom/recover-raw.cpp deleted file mode 100644 index 78be2e2a549..00000000000 --- a/psx/octoshock/cdrom/recover-raw.cpp +++ /dev/null @@ -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 2) - { GetPVector(byte_state, p_state, p); - erasure_count = 0; - - for(i=0; i 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; -} - diff --git a/psx/octoshock/docs/upstreaminfo.txt b/psx/octoshock/docs/upstreaminfo.txt deleted file mode 100644 index 0a8e44f4903..00000000000 --- a/psx/octoshock/docs/upstreaminfo.txt +++ /dev/null @@ -1,233 +0,0 @@ -0.9.36.2 (approx) -> 0.9.36.5 -[NO] cdrom/CDAccess_Image : added support for SBI files (SBI will be handled in external disc system) -[OK] psx/CDC : removed stub for Command_Sync (WHY?) -[OK] psx/psx : fixed bug (SPU-related: clarified read order by turning into two statements) -[NO] psx/psx : StateAction bugfix - -0.9.36.5 -> 0.9.37-UNSTABLE -(General improvements and state fixups) -(bios hash check at loadstate time added) -(disc CDIF media changing infrastructure heavily revised) -[OK] psx/cdc : DMForceStop refactoring -[OK] psx/cpu : MULT_Tab24 changes -[OK] psx/cpu : AssertIRQ refinement -[OK] psx/cpu : BIOSPrintMode revisions -[OK] psx/cpu : Odd PC address handling -[OK] psx/cpu : Some int signedness tweaks, maybe to fix warnings or even bugs -[NO] psx/debugp : SPU register names changed (not using debug.cpp) -[OK] psx/dma : Cleanup and bugfixes, notably in RecalcIRQOut -[NO] psx/frontio : port configuration and organization changes; NV reading api changes -[OK] psx/frontio : FrontIO::Write and Read fixes -[OK] psx/frontio : FrontIO::Reset powering_up handling (independent of reset?) -[OK] psx/frontio : GPULineHook fixes maybe related to org changes -[OK] psx/GPU* : A lot of work and refactoring -[OK] psx/GTE : division refactors and improvement -[OK] psx/input/* : fio-related refactors (organization and Power-up logic) ( TODO - some of the powerup-related logic seems not to have made it?) -[OK] psx/input/dualshock : AM toggle changes -[OK] psx/irq : reorg -[NO] psx/psx : loader edits, firmware region list, disc ID stuff (TODO - update later when disc ID reintegrated into core as perk) (CalcRegion_By_SA, ConstrainRegion_By_SA, etc.) -[OK] psx/psx : fio-related powerup stuff -[NO] psx/psx : fio-related configuration stuff -[??] psx/psx : SCEE/SCEA/SCEI SCEx stuff changed (???) -[!!] psx/psx : LoadEXE/PSF1 changes (TODO - need these) -[OK] psx/spu* : register renames and misc bugfixes - -0.9.37-UNSTABLE -> 0.9.37.1 -[NO] psx/cpu : fix some savestate problem with ReadAbsorbDummy, seems alarming but maybe was just backwards compatibility -[OK] psx/spu : clamp some sound output presumably messed up by prior reverb changes - -0.9.37.1 -> 0.9.38-UNSTABLE -(major CDIF changes) -(simplefifo refactored) -[!!] psx/cdutility : substantial revisions to disc sector synthesis with respect to leadout, "UDAPP", and "TSRE" (thread-safe re-entrant) which I dont understand. Need to study for DiscSystem. -[OK] required math_ops changes -[OK] SimpleFifo changed to PSX-only FastFIFO -[OK] psx/cdc : set SoftReset Mode to 0x20 -[OK] psx/cdc : Edits to MakeStatus and BeginResults and ReadResult -[OK] psx/cdc : in HandlePlayRead, handling of leadout sector synth moved to CDIF -[OK] psx/cdc : in Update, Mode handling and reading of subcode changed -[OK] psx/cdc : in Update, reading of subcode changed. This isn't very important, it just saved reading the 2352 sector bytes when it wasn't needed. -[OK] psx/cdc : error handling in Command_Setloc -[OK] psx/cdc : PreSeekHack edits -[OK] psx/cdc : Command_GetTD improvements -[OK] psx/cdc : Command_SeekL timing changes -[OK] psx/cpu : helpful changes to case ranges and jump table. double check for savestate changes. -[OK] psx/dma : easy bugfixes -[??] psx/gpu : display timing changes ?? study more -[OK] psx/gpu : BlitterFifo changes, related to FBWrite/Read -[OK] psx/gpu : a bunch of bugfixes -[OK] psx/gpu : video standard mismatch warning suppressed during DisplayOff -[OK] psx/gpu : be aware of savestate changes -[OK] psx/gpu_line : easy bugfixes -[OK] psx/gte : division bugfixes -[OK] psx/memcard : refactors and maybe bugfixes easy to port -[OK] psx/multitap : general revisions, easy to port, note savestate changes -[OK] psx/mdec : easy fifo and timing related changes -[OK] psx/spu : reverb reg fixes or reorg -[OK] psx/psx : DMACycleSteal stuff -[NO] psx/psx : CalcRegion_By_SYSTEMCNF and TestMagicCD updated -[NO] psx/psx : DiscSanityChecks added (add feature later maybe) - -0.9.38-UNSTABLE -> 0.9.38.1 -[NO] psx/psx : DiscSanityChecks fix (OK if we used this feature) - -0.9.38.1 -> 0.9.38.2 -[OK] psx/gpu_polygon : Fixes to poly rasterizing - -0.9.38.2 -> 0.9.38.4 -[OK] psx/cdc : Change to fundamental sector reading for tomb raider -[OK] psx/cpu : Elaborate debug poke capabilities -[OK] psx/debug : Elaborate debug poke capabilities -[OK] psx/gpu : Alter mouse coordinate translation -[OK] psx/gpu : Alter texcache invalidation, TPage and DrawMode commands -[OK] psx/psx : Elaborate debug poke capabilities - -0.9.38.4 -> 0.9.38.5 -[OK] psx/cdc : substantial changes to disc swapping and seek retries -[OK] psx/gpu : change to comments -[OK] psx/memcard : change to debug output - -0.9.38.4 -> 0.9.38.6 -[OK] psx/gpu & gpu_sprite : Fixed GPU emulation timing bugs that caused graphical glitches in "Mr. Driller G". - -0.9.38.5 -> 0.9.38.7 -[OK] psx/cpu : Revisions to exception handling -[OK] psx/cpu : Many revisions and cleanups to branch and exception handling in opcode implementations -[OK] psx/dis : Just some basic disassembly changes -[OK] psx/gte : Cleanup -[OK] psx/psx : Cleanup -[OK] psx/timer : Major functional changes -[NO] psx/timer : Added loadstate sanity checks - -0.9.38.7 -> 0.9.39-unstable -[OK] psx/cdc : "Fantastic Pinball Kyutenkai" enable; add MDFN_COLD -[OK] psx/cpu : various improvements -[OK] psx/fastfifo : .h copyright header -[NO] psx/debug : (file not used) -[OK] psx/dis : rename opcode, copyright header -[OK] psx/dma : copyright header -[OK] psx/frontio : copyright header and minor stuff -[OK] psx/gpu : copyright, change ctor, member org changes, minor stuff -[OK] psx/gte : (c), CR 30 change, add inlines -[OK] psx/input/* : (c) -[OK] psx/irq : (c) -[OK] psx/masmem : (c) -[OK] psx/mdec : (c), opts, -[NO] psx/psx : cheats support -[OK] psx/psx : (c), cnf parse -[OK] psx/sio : (c) -[OK] psx/spu : (c), comments, inline -[OK] psx/timer : (c), comments - -0.9.39-unstable -> 0.9.39-1 -[NO] mednafen : just org stuff -[??] cdrom/ccd : something about track AA - -0.9.39-1 -> 0.9.39-2 -[NO] drivers/main : nothing useful -[NO] mednafen : nothing useful -[OK] psx/cdc : loadstate, type change -[OK] psx/cpu : type change, loadstate tweak. ignore GTE_StateAction. -[OK] psx/gpu : big update to loadstate, maybe missing things before -[NO] psx/input/* : loadstate buffer sanity, not used for us -[OK] psx/mdec : PixelBufferReadOffset fixes -[OK] psx/psx : event_time initial value -[OK] psx/spu : loadstate sanity, decided to accept it here - -0.9.39-2 -> 0.9.41 -[OK] math_ops : major revisions -[NO] mednafen : nothing useful, but check interlace init -[OK] psx/cpu : remove PS_CPU_EMULATE_ICACHE? ok.. -[NO] psx/frontio : AMCT stuff -[NO] psx/gpu : render parameters stuff -[NO] psx/input/dualshocK : AMCT stuff -[NO] psx/psx : render parameters stuff -[OK] tests : pasted over and whittled down - -0.9.41 -> 0.9.42 -[OK] tests : some 64bit casting tests - -0.9.42 -> 0.9.43 -[OK] psx/frontio : (c), UpdateOutput() [not needed] -[OK] psx/input/dualshock : (c), analog state change [TEST] -[OK] psx/psx : (c), UpdateOutput() [not needed] - -0.9.43 -> 0.9.44.1 -[OK] psx/cdc : add const -[NO] psx/debug : not used file -[OK] psx/dis : add const -[OK] psx/dma : update GPU api. NOTE: found biz bug here. -[OK] psx/frontio : add cold -[OK] psx/gpu : (big change to make GPU static) -[OK] psx/psx : associated with GPU, add cold; ignored PSF loader cold. NOTE: at smoe point we got RMD_Drive, which I'm not using -[NO] psx/input/* : not important cold and device specifications stuff -[OK] psx/mdec : fastcall -[OK] psx/irq : fastcall -[NO] types : extensive work to cold, hot, fastcall, etc. macros for compilers - -0.9.44.1 -> 0.9.45 -(misc #include changes all over) -[NO] psx/frontio : not important -[OK] psx/gte : FALSE->false, etc -[OK] psx/masmem : not important -[NO] psx/mdec : not important -[NO] psx/psx : not important - -0.9.45 -> 0.9.45.1 -(nothing) - -0.9.45.1 -> 0.9.48 -[OK] endian / many updates, probably for performance -[OK] psx/irq : tidy -[OK] psx/gpu : tidy -[OK] tests: add some gcc tests, and tests for various cpu archs - -0.9.48 -> 1.21.3 -[OK] psx/cdc : add static asserts (useless: change how variables are saved) -[NO] psx/cpu : change how variables are saved -[NO] psx/frontio : change how variables are saved -[OK] psx/gpu : odd fix to lightgun coords, maybe pointless; change how variables are saved; optimization to GetTexel -[OK] psx/gte : add static asserts (useless: change how variables are saved) -[NO] psx/input/* : variable saving, and change to input device setup -[NO] psx/input/mouse : input buffer format changed? must be due to input device changes in 1.x update -[OK] psx/input/multitap : MDAP ? weird -[ON] psx/mdec : MDAP? (ignored: variable saving) -[NO] psx/psx : frontend memcard error handling, changes from strncasecmp to MDFN_strazicmp and etc; change to ReadSector API? -[NO] psx/spu : ignored: variable saving - -1.21.3 -> 1.22.0-UNSTABLE -(mednafen namespaces added all over) -[NO] endian : nothing important -[OK] psx/cdc : many changes (described well in changelog). CAUTION: DMForceStop is removed, this may cause problems on multidisc games -[OK] psx/psx : remove register keyword, add NO_INLINE -[NO] psx/dis : minor change, we do it different -[OK] psx/gpu : silence warning -[OK] psx/mdec : change intrinsics macros; change inline keyword -[NO] psx/psx : change memcard flushing logic, change cd interface, PSF loading -[OK] psx/psx : change CNF parsing - -1.22.0-UNSTABLE -> 1.22.2 -[OK] psx/cdc : fix a bug - -1.22.2 -> 1.23.0 -[OK] psx/cdc : fix a bug -[NO] psx/psx : GIT change - -1.23.0 -> 1.24.0-UNSTABLE -(MDFN_HIDE litter all over) -[OK] psx/gpu : (c); ignored AR changes in GIT (TODO: reapply in bizhawk code). changed timing. -[OK] psx/input/guncon : TransformInput changes to use GPU_GetGunXTranslation... IGNORED? IMPORTANT? also: hook updates. -[OK] psx/input/justifier : TransformInput changes to use GPU_GetGunXTranslation... IGNORED? IMPORTANT? also: hook updates. -[OK] psx/mdec : intrinsic macros changes -[NO] psx/psx : "psx.correct_aspect". we're not really using this. -[OK] psx/spu : casts on volumes -[NO] types : nothing important -[NO] video/Deinterlacer : IGNORE. we may have weak deinterlacing, but so be it -[NO] tests : intrinsic macros changes, threading API changes, stream tests - -1.24.0-UNSTABLE -> 1.24.1 -[OK] psx/spu : some basic emulation fixes -[NO] tests : thread stuff - -1.24.1 -> 1.24.2 --nothing- \ No newline at end of file diff --git a/psx/octoshock/emuware/EW_state.cpp b/psx/octoshock/emuware/EW_state.cpp deleted file mode 100644 index 2991cb91281..00000000000 --- a/psx/octoshock/emuware/EW_state.cpp +++ /dev/null @@ -1,99 +0,0 @@ -#include "EW_state.h" -#include -#include -#include -#include -#include - -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(length <= 0x30a907 && length + size > 0x30a907) - { - } - 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(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); -} - - -} diff --git a/psx/octoshock/emuware/EW_state.h b/psx/octoshock/emuware/EW_state.h deleted file mode 100644 index acd3c1396af..00000000000 --- a/psx/octoshock/emuware/EW_state.h +++ /dev/null @@ -1,105 +0,0 @@ -#ifndef NEWSTATE_H -#define NEWSTATE_H - -#include -#include - -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(EW::NewState *ns);\ - template void x::SyncState(EW::NewState *ns);\ - templatevoid 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(ns); ns->ExitSection(#x); } while (0) - - #define TSS(x) do { ns->EnterSection(#x); (x)->SyncState(ns); ns->ExitSection(#x); } while (0) - - } - - - -#endif //NEWSTATE_H \ No newline at end of file diff --git a/psx/octoshock/emuware/emuware.cpp b/psx/octoshock/emuware/emuware.cpp deleted file mode 100644 index 02119e1d593..00000000000 --- a/psx/octoshock/emuware/emuware.cpp +++ /dev/null @@ -1,3 +0,0 @@ -#include "emuware.h" - -//this file intentionally empty \ No newline at end of file diff --git a/psx/octoshock/emuware/emuware.h b/psx/octoshock/emuware/emuware.h deleted file mode 100644 index 19e9fd12c91..00000000000 --- a/psx/octoshock/emuware/emuware.h +++ /dev/null @@ -1,143 +0,0 @@ -#pragma once - -#include -#include -#include - -#ifdef _MSC_VER -#define SIZEOF_CHAR sizeof(char) -#define SIZEOF_SHORT sizeof(short) -#define SIZEOF_INT sizeof(int) -#define SIZEOF_LONG sizeof(long) -#define SIZEOF_LONG_LONG sizeof(long long) -#define SIZEOF_OFF_T sizeof(off_t) -#define SIZEOF_PTRDIFF_T sizeof(void*) -#define SIZEOF_SIZE_T sizeof(size_t) -#define SIZEOF_VOID_P sizeof(void*) -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 MDFN_HIDE - - -//#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_FASTCALL - -//#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 - -#if defined(_MSC_VER) - #define strncasecmp _strnicmp - #define NO_CLONE -#endif - -#if defined(_MSC_VER) && _MSC_VER < 1900 - #define snprintf _snprintf - #define vsnprintf _vsnprintf - #define strcasecmp _stricmp - #define final - #define noexcept -#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 -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 - -//http://stackoverflow.com/questions/1537964/visual-c-equivalent-of-gccs-attribute-packed -#ifdef _MSC_VER -#define EW_PACKED( ... ) __pragma( pack(push, 1) ) __VA_ARGS__ __pragma( pack(pop) ) -#else -#define EW_PACKED( ... ) __VA_ARGS__ __attribute__((__packed__)) -#endif - -#define MDFN_IS_BIGENDIAN 0 \ No newline at end of file diff --git a/psx/octoshock/emuware/msvc/changelog.txt b/psx/octoshock/emuware/msvc/changelog.txt deleted file mode 100644 index cf0539c2533..00000000000 --- a/psx/octoshock/emuware/msvc/changelog.txt +++ /dev/null @@ -1,138 +0,0 @@ ------------------------------------------------------------------------- -r26 | 2009-10-02 13:36:47 +0400 | 2 lines - -[Issue 5] Change 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 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 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 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 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. ------------------------------------------------------------------------- diff --git a/psx/octoshock/emuware/msvc/inttypes.h b/psx/octoshock/emuware/msvc/inttypes.h deleted file mode 100644 index 25542771f59..00000000000 --- a/psx/octoshock/emuware/msvc/inttypes.h +++ /dev/null @@ -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_ ] diff --git a/psx/octoshock/emuware/msvc/stdint.h b/psx/octoshock/emuware/msvc/stdint.h deleted file mode 100644 index 59d067302fc..00000000000 --- a/psx/octoshock/emuware/msvc/stdint.h +++ /dev/null @@ -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 - -// For Visual Studio 6 in C++ mode and for many Visual Studio versions when -// compiling for ARM we should wrap 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 -#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 -#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_ ] diff --git a/psx/octoshock/endian.cpp b/psx/octoshock/endian.cpp deleted file mode 100644 index ce6edb46789..00000000000 --- a/psx/octoshock/endian.cpp +++ /dev/null @@ -1,135 +0,0 @@ -/******************************************************************************/ -/* Mednafen - Multi-system Emulator */ -/******************************************************************************/ -/* endian.cpp: -** Copyright (C) 2006-2016 Mednafen Team -** -** 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., -** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include -#include -#include "octoshock.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 -} - -void Endian_V_NE_LE(void* p, size_t len) -{ - #ifdef MSB_FIRST - std::reverse((uint8*)p, (uint8*)p + len); - #endif -} - -void Endian_V_NE_BE(void* p, size_t len) -{ - #ifdef LSB_FIRST - std::reverse((uint8*)p, (uint8*)p + len); - #endif -} diff --git a/psx/octoshock/endian.h b/psx/octoshock/endian.h deleted file mode 100644 index 56efd2306c7..00000000000 --- a/psx/octoshock/endian.h +++ /dev/null @@ -1,533 +0,0 @@ -/******************************************************************************/ -/* Mednafen - Multi-system Emulator */ -/******************************************************************************/ -/* endian.h: -** Copyright (C) 2006-2017 Mednafen Team -** -** 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., -** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef __MDFN_ENDIAN_H -#define __MDFN_ENDIAN_H - -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* p, size_t len); -void Endian_V_NE_BE(void* p, size_t len); - -// -// -// - -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 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). -*/ - -static INLINE uint16 MDFN_bswap16(uint16 v) -{ -#if defined(_MSC_VER) - return _byteswap_ushort(v); -#else - return (v << 8) | (v >> 8); -#endif -} - -static INLINE uint32 MDFN_bswap32(uint32 v) -{ -#if defined(_MSC_VER) - return _byteswap_ulong(v); -#else - return (v << 24) | ((v & 0xFF00) << 8) | ((v >> 8) & 0xFF00) | (v >> 24); -#endif -} - -static INLINE uint64 MDFN_bswap64(uint64 v) -{ -#if defined(_MSC_VER) - return _byteswap_uint64(v); -#else - return (v << 56) | (v >> 56) | ((v & 0xFF00) << 40) | ((v >> 40) & 0xFF00) | ((uint64)MDFN_bswap32(v >> 16) << 16); -#endif -} - -// -// X endian. -// -template -static INLINE T MDFN_deXsb(const void* ptr) -{ - T tmp; - - memcpy(&tmp, MDFN_ASSUME_ALIGNED(ptr, (aligned ? alignof(T) : 1)), sizeof(T)); - - if(isbigendian != -1 && isbigendian != (int)MDFN_IS_BIGENDIAN) - { - static_assert(sizeof(T) == 1 || sizeof(T) == 2 || sizeof(T) == 4 || sizeof(T) == 8, "Gummy penguins."); - - if(sizeof(T) == 8) - return MDFN_bswap64(tmp); - else if(sizeof(T) == 4) - return MDFN_bswap32(tmp); - else if(sizeof(T) == 2) - return MDFN_bswap16(tmp); - } - - return tmp; -} - -// -// Native endian. -// -template -static INLINE T MDFN_densb(const void* ptr) -{ - return MDFN_deXsb<-1, T, aligned>(ptr); -} - -// -// Little endian. -// -template -static INLINE T MDFN_delsb(const void* ptr) -{ - return MDFN_deXsb<0, T, aligned>(ptr); -} - -template -static INLINE uint16 MDFN_de16lsb(const void* ptr) -{ - return MDFN_delsb(ptr); -} - -static INLINE uint32 MDFN_de24lsb(const void* ptr) -{ - const uint8* ptr_u8 = (const uint8*)ptr; - - return (ptr_u8[0] << 0) | (ptr_u8[1] << 8) | (ptr_u8[2] << 16); -} - -template -static INLINE uint32 MDFN_de32lsb(const void* ptr) -{ - return MDFN_delsb(ptr); -} - -template -static INLINE uint64 MDFN_de64lsb(const void* ptr) -{ - return MDFN_delsb(ptr); -} - -// -// Big endian. -// -template -static INLINE T MDFN_demsb(const void* ptr) -{ - return MDFN_deXsb<1, T, aligned>(ptr); -} - -template -static INLINE uint16 MDFN_de16msb(const void* ptr) -{ - return MDFN_demsb(ptr); -} - -static INLINE uint32 MDFN_de24msb(const void* ptr) -{ - const uint8* ptr_u8 = (const uint8*)ptr; - - return (ptr_u8[0] << 16) | (ptr_u8[1] << 8) | (ptr_u8[2] << 0); -} - -template -static INLINE uint32 MDFN_de32msb(const void* ptr) -{ - return MDFN_demsb(ptr); -} - -template -static INLINE uint64 MDFN_de64msb(const void* ptr) -{ - return MDFN_demsb(ptr); -} - -// -// -// -// -// -// -// -// - -// -// X endian. -// -template -static INLINE void MDFN_enXsb(void* ptr, T value) -{ - T tmp = value; - - if(isbigendian != -1 && isbigendian != (int)MDFN_IS_BIGENDIAN) - { - static_assert(sizeof(T) == 1 || sizeof(T) == 2 || sizeof(T) == 4 || sizeof(T) == 8, "Gummy penguins."); - - if(sizeof(T) == 8) - tmp = MDFN_bswap64(value); - else if(sizeof(T) == 4) - tmp = MDFN_bswap32(value); - else if(sizeof(T) == 2) - tmp = MDFN_bswap16(value); - } - - memcpy(MDFN_ASSUME_ALIGNED(ptr, (aligned ? alignof(T) : 1)), &tmp, sizeof(T)); -} - -// -// Native endian. -// -template -static INLINE void MDFN_ennsb(void* ptr, T value) -{ - MDFN_enXsb<-1, T, aligned>(ptr, value); -} - -// -// Little endian. -// -template -static INLINE void MDFN_enlsb(void* ptr, T value) -{ - MDFN_enXsb<0, T, aligned>(ptr, value); -} - -template -static INLINE void MDFN_en16lsb(void* ptr, uint16 value) -{ - MDFN_enlsb(ptr, value); -} - -static INLINE void MDFN_en24lsb(void* ptr, uint32 value) -{ - uint8* ptr_u8 = (uint8*)ptr; - - ptr_u8[0] = value >> 0; - ptr_u8[1] = value >> 8; - ptr_u8[2] = value >> 16; -} - -template -static INLINE void MDFN_en32lsb(void* ptr, uint32 value) -{ - MDFN_enlsb(ptr, value); -} - -template -static INLINE void MDFN_en64lsb(void* ptr, uint64 value) -{ - MDFN_enlsb(ptr, value); -} - - -// -// Big endian. -// -template -static INLINE void MDFN_enmsb(void* ptr, T value) -{ - MDFN_enXsb<1, T, aligned>(ptr, value); -} - -template -static INLINE void MDFN_en16msb(void* ptr, uint16 value) -{ - MDFN_enmsb(ptr, value); -} - -static INLINE void MDFN_en24msb(void* ptr, uint32 value) -{ - uint8* ptr_u8 = (uint8*)ptr; - - ptr_u8[0] = value >> 16; - ptr_u8[1] = value >> 8; - ptr_u8[2] = value >> 0; -} - -template -static INLINE void MDFN_en32msb(void* ptr, uint32 value) -{ - MDFN_enmsb(ptr, value); -} - -template -static INLINE void MDFN_en64msb(void* ptr, uint64 value) -{ - MDFN_enmsb(ptr, value); -} - - -// -// -// -// -// -// - -template -static INLINE uintptr_t neX_ptr_be(uintptr_t const base, const size_t byte_offset) -{ -#ifdef MSB_FIRST - return base + (byte_offset &~ (sizeof(T) - 1)); -#else - return base + (((byte_offset &~ (sizeof(T) - 1)) ^ (sizeof(X) - std::min(sizeof(X), sizeof(T))))); -#endif -} - -template -static INLINE uintptr_t neX_ptr_le(uintptr_t const base, const size_t byte_offset) -{ -#ifdef LSB_FIRST - return base + (byte_offset &~ (sizeof(T) - 1)); -#else - return base + (((byte_offset &~ (sizeof(T) - 1)) ^ (sizeof(X) - std::min(sizeof(X), sizeof(T))))); -#endif -} - -template -static INLINE void ne16_wbo_be(BT base, const size_t byte_offset, const T value) -{ - static_assert(sizeof(T) == 1 || sizeof(T) == 2 || sizeof(T) == 4, "Unsupported type size"); - static_assert(std::is_same::value || std::is_convertible::value, "Wrong base type"); - - uintptr_t const ptr = neX_ptr_be((uintptr_t)base, byte_offset); - - if(sizeof(T) == 4) - { - uint16* const ptr16 = (uint16*)ptr; - - ptr16[0] = value >> 16; - ptr16[1] = value; - } - else - *(T*)ptr = value; -} - -template -static INLINE T ne16_rbo_be(BT base, const size_t byte_offset) -{ - static_assert(sizeof(T) == 1 || sizeof(T) == 2 || sizeof(T) == 4, "Unsupported type size"); - static_assert(std::is_same::value || std::is_convertible::value, "Wrong base type"); - - uintptr_t const ptr = neX_ptr_be((uintptr_t)base, byte_offset); - - if(sizeof(T) == 4) - { - uint16* const ptr16 = (uint16*)ptr; - T tmp; - - tmp = ptr16[0] << 16; - tmp |= ptr16[1]; - - return tmp; - } - else - return *(T*)ptr; -} - -template -static INLINE void ne16_rwbo_be(BT base, const size_t byte_offset, T* value) -{ - if(IsWrite) - ne16_wbo_be(base, byte_offset, *value); - else - *value = ne16_rbo_be(base, byte_offset); -} - -// -// -// - -template -static INLINE void ne16_wbo_le(BT base, const size_t byte_offset, const T value) -{ - static_assert(sizeof(T) == 1 || sizeof(T) == 2 || sizeof(T) == 4, "Unsupported type size"); - static_assert(std::is_same::value || std::is_convertible::value, "Wrong base type"); - - uintptr_t const ptr = neX_ptr_le((uintptr_t)base, byte_offset); - - if(sizeof(T) == 4) - { - uint16* const ptr16 = (uint16*)ptr; - - ptr16[0] = value; - ptr16[1] = value >> 16; - } - else - *(T*)ptr = value; -} - -template -static INLINE T ne16_rbo_le(BT base, const size_t byte_offset) -{ - static_assert(sizeof(T) == 1 || sizeof(T) == 2 || sizeof(T) == 4, "Unsupported type size"); - static_assert(std::is_same::value || std::is_convertible::value, "Wrong base type"); - - uintptr_t const ptr = neX_ptr_le((uintptr_t)base, byte_offset); - - if(sizeof(T) == 4) - { - uint16* const ptr16 = (uint16*)ptr; - T tmp; - - tmp = ptr16[0]; - tmp |= ptr16[1] << 16; - - return tmp; - } - else - return *(T*)ptr; -} - - -template -static INLINE void ne16_rwbo_le(BT base, const size_t byte_offset, T* value) -{ - if(IsWrite) - ne16_wbo_le(base, byte_offset, *value); - else - *value = ne16_rbo_le(base, byte_offset); -} - -// -// -// -template -static INLINE void ne64_wbo_be(BT base, const size_t byte_offset, const T value) -{ - static_assert(sizeof(T) == 1 || sizeof(T) == 2 || sizeof(T) == 4 || sizeof(T) == 8, "Unsupported type size"); - static_assert(std::is_same::value || std::is_convertible::value, "Wrong base type"); - - uintptr_t const ptr = neX_ptr_be((uintptr_t)base, byte_offset); - - memcpy(MDFN_ASSUME_ALIGNED((void*)ptr, alignof(T)), &value, sizeof(T)); -} - -template -static INLINE T ne64_rbo_be(BT base, const size_t byte_offset) -{ - static_assert(sizeof(T) == 1 || sizeof(T) == 2 || sizeof(T) == 4 || sizeof(T) == 8, "Unsupported type size"); - static_assert(std::is_same::value || std::is_convertible::value, "Wrong base type"); - - uintptr_t const ptr = neX_ptr_be((uintptr_t)base, byte_offset); - T ret; - - memcpy(&ret, MDFN_ASSUME_ALIGNED((void*)ptr, alignof(T)), sizeof(T)); - - return ret; -} - -template -static INLINE void ne64_rwbo_be(BT base, const size_t byte_offset, T* value) -{ - if(IsWrite) - ne64_wbo_be(base, byte_offset, *value); - else - *value = ne64_rbo_be(base, byte_offset); -} -// -// -// -template -static INLINE void ne64_wbo_le(BT base, const size_t byte_offset, const T value) -{ - static_assert(sizeof(T) == 1 || sizeof(T) == 2 || sizeof(T) == 4 || sizeof(T) == 8, "Unsupported type size"); - static_assert(std::is_same::value || std::is_convertible::value, "Wrong base type"); - - uintptr_t const ptr = neX_ptr_le((uintptr_t)base, byte_offset); - - memcpy(MDFN_ASSUME_ALIGNED((void*)ptr, alignof(T)), &value, sizeof(T)); -} - -template -static INLINE T ne64_rbo_le(BT base, const size_t byte_offset) -{ - static_assert(sizeof(T) == 1 || sizeof(T) == 2 || sizeof(T) == 4 || sizeof(T) == 8, "Unsupported type size"); - static_assert(std::is_same::value || std::is_convertible::value, "Wrong base type"); - - uintptr_t const ptr = neX_ptr_le((uintptr_t)base, byte_offset); - T ret; - - memcpy(&ret, MDFN_ASSUME_ALIGNED((void*)ptr, alignof(T)), sizeof(T)); - - return ret; -} - -template -static INLINE void ne64_rwbo_le(BT base, const size_t byte_offset, T* value) -{ - if(IsWrite) - ne64_wbo_le(base, byte_offset, *value); - else - *value = ne64_rbo_le(base, byte_offset); -} - - -#endif diff --git a/psx/octoshock/error.cpp b/psx/octoshock/error.cpp deleted file mode 100644 index d299584b370..00000000000 --- a/psx/octoshock/error.cpp +++ /dev/null @@ -1,144 +0,0 @@ -/******************************************************************************/ -/* Mednafen - Multi-system Emulator */ -/******************************************************************************/ -/* error.cpp: -** Copyright (C) 2007-2016 Mednafen Team -** -** 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., -** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "error.h" -#include -#include -#include - -MDFN_Error::MDFN_Error() noexcept -{ - abort(); -} - -MDFN_Error::MDFN_Error(int errno_code_new, const char *format, ...) noexcept -{ - errno_code = errno_code_new; - - va_list ap; - va_start(ap, format); - va_list ap_copy; - va_copy(ap_copy, ap); - std::vector buf(1+vsnprintf(nullptr, 0, format, ap)); - va_end(ap); - (void)vsnprintf(buf.data(), buf.size(),format, ap_copy); - va_end(ap_copy); - error_message = strdup(buf.data()); - va_end(ap); -} - - -MDFN_Error::MDFN_Error(const ErrnoHolder &enh) -{ - errno_code = enh.Errno(); - - error_message = strdup(enh.StrError()); -} - - -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 MDFN_NOWARN_UNUSED const char *srr_wrap(int ret, const char *local_strerror) -{ - if(ret == -1) - return("ERROR IN strerror_r()!!!"); - - return(local_strerror); -} - -static MDFN_NOWARN_UNUSED 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; - } -} diff --git a/psx/octoshock/error.h b/psx/octoshock/error.h deleted file mode 100644 index 0fcb68d3ed8..00000000000 --- a/psx/octoshock/error.h +++ /dev/null @@ -1,76 +0,0 @@ -#ifndef __MDFN_ERROR_H -#define __MDFN_ERROR_H - -#include -#include -#include -#include "emuware/emuware.h" - -#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 diff --git a/psx/octoshock/file.cpp b/psx/octoshock/file.cpp deleted file mode 100644 index f6cf1952698..00000000000 --- a/psx/octoshock/file.cpp +++ /dev/null @@ -1,562 +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 -//#include -//#include -//#include -//#include -// -//#include "octoshock.h" -//#include "FileStream.h" -// -// -//#ifdef HAVE_MMAP -//#include -//#include -//#include -//#include -//#endif -// -//#include "file.h" -// -//static const int64 MaxROMImageSize = (int64)1 << 26; // 2 ^ 26 = 64MiB -// -//enum -//{ -// MDFN_FILETYPE_PLAIN = 0, -// MDFN_FILETYPE_GZIP = 1, -// MDFN_FILETYPE_ZIP = 2, -//}; -// -//void MDFNFILE::MakeMemWrap(void *tz, int type) -//{ -// #ifdef HAVE_MMAP -// is_mmap = FALSE; -// #endif -// location = 0; -// -// if(type == MDFN_FILETYPE_PLAIN) -// { -// ::fseek((FILE *)tz, 0, SEEK_END); -// f_size = ::ftell((FILE *)tz); -// ::fseek((FILE *)tz, 0, SEEK_SET); -// -// -// #ifdef HAVE_MMAP -// if((void *)-1 != (f_data = (uint8 *)mmap(NULL, size, PROT_READ, MAP_SHARED, fileno((FILE *)tz), 0))) -// { -// //puts("mmap'ed"); -// is_mmap = TRUE; -// #ifdef HAVE_MADVISE -// madvise(f_data, size, MADV_SEQUENTIAL | MADV_WILLNEED); -// #endif -// } -// else -// #endif -// { -// f_data = (uint8 *)MDFN_malloc_T(size, _("file read buffer")); -// -// if((int64)::fread(f_data, 1, size, (FILE *)tz) != size) -// { -// ErrnoHolder ene(errno); -// -// throw MDFN_Error(ene.Errno(), _("Error reading file: %s"), ene.StrError()); -// } -// } -// } -// else if(type == MDFN_FILETYPE_GZIP) -// { -// uint32_t cur_size = 0; -// uint32_t cur_alloced = 65536; -// int howmany; -// -// f_data = (uint8 *)MDFN_malloc_T(cur_alloced, _("file read buffer")); -// -// while((howmany = gzread((gzFile)tz, f_data + cur_size, cur_alloced - cur_size)) > 0) -// { -// cur_size += howmany; -// cur_alloced <<= 1; -// -// if(cur_size > MaxROMImageSize) -// throw MDFN_Error(0, _("ROM image is too large; maximum size allowed is %llu bytes."), (unsigned long long)MaxROMImageSize); -// -// f_data = (uint8 *)MDFN_realloc_T(f_data, cur_alloced, _("file read buffer")); -// } -// -// f_data = (uint8 *)MDFN_realloc_T(f_data, cur_size, _("file read buffer")); -// f_size = cur_size; -// -// { -// int gzerrnum = 0; -// const char *gzerrstring; -// if((gzerrstring = gzerror((gzFile)tz, &gzerrnum)) && gzerrnum != Z_OK && gzerrnum != Z_STREAM_END) -// { -// if(gzerrnum != Z_ERRNO) -// { -// throw MDFN_Error(0, _("Error reading file: zlib error: %s"), gzerrstring); -// } -// else -// { -// ErrnoHolder ene(errno); -// throw MDFN_Error(ene.Errno(), _("Error reading file: %s"), ene.StrError()); -// } -// } -// } -// } -// else if(type == MDFN_FILETYPE_ZIP) -// { -// unz_file_info ufo; -// unzGetCurrentFileInfo((unzFile)tz, &ufo, 0, 0, 0, 0, 0, 0); -// -// f_size = ufo.uncompressed_size; -// -// if(size > MaxROMImageSize) -// throw MDFN_Error(0, _("ROM image is too large; maximum size allowed is %llu bytes."), (unsigned long long)MaxROMImageSize); -// -// f_data = (uint8 *)MDFN_malloc_T(ufo.uncompressed_size, _("file read buffer")); -// unzReadCurrentFile((unzFile)tz, f_data, ufo.uncompressed_size); -// } -//} -// -//MDFNFILE::MDFNFILE(const char *path, const FileExtensionSpecStruct *known_ext, const char *purpose) : size(f_size), data((const uint8* const &)f_data), ext((const char * const &)f_ext), fbase((const char * const &)f_fbase) -//{ -// f_data = NULL; -// f_size = 0; -// f_ext = NULL; -// f_fbase = NULL; -// -// location = 0; -// -// #ifdef HAVE_MMAP -// is_mmap = 0; -// #endif -// -// Open(path, known_ext, purpose); -//} -// -//MDFNFILE::~MDFNFILE() -//{ -// Close(); -//} -// -// -//void MDFNFILE::Open(const char *path, const FileExtensionSpecStruct *known_ext, const char *purpose) -//{ -// unzFile tz = NULL; -// FILE *fp = NULL; -// gzFile gzp = NULL; -// -// try -// { -// // -// // Try opening it as a zip file first -// // -// if((tz = unzOpen(path))) -// { -// char tempu[1024]; -// int errcode; -// -// if((errcode = unzGoToFirstFile(tz)) != UNZ_OK) -// { -// throw MDFN_Error(0, _("Could not seek to first file in ZIP archive: %s"), unzErrorString(errcode)); -// } -// -// if(known_ext) -// { -// bool FileFound = FALSE; -// while(!FileFound) -// { -// size_t tempu_strlen; -// const FileExtensionSpecStruct *ext_search = known_ext; -// -// if((errcode = unzGetCurrentFileInfo(tz, 0, tempu, 1024, 0, 0, 0, 0)) != UNZ_OK) -// { -// throw MDFN_Error(0, _("Could not get file information in ZIP archive: %s"), unzErrorString(errcode)); -// } -// -// tempu[1023] = 0; -// tempu_strlen = strlen(tempu); -// -// while(ext_search->extension && !FileFound) -// { -// size_t ttmeow = strlen(ext_search->extension); -// if(tempu_strlen >= ttmeow) -// { -// if(!strcasecmp(tempu + tempu_strlen - ttmeow, ext_search->extension)) -// FileFound = TRUE; -// } -// ext_search++; -// } -// -// if(FileFound) -// break; -// -// if((errcode = unzGoToNextFile(tz)) != UNZ_OK) -// { -// if(errcode != UNZ_END_OF_LIST_OF_FILE) -// { -// throw MDFN_Error(0, _("Error seeking to next file in ZIP archive: %s"), unzErrorString(errcode)); -// } -// -// if((errcode = unzGoToFirstFile(tz)) != UNZ_OK) -// { -// throw MDFN_Error(0, _("Could not seek to first file in ZIP archive: %s"), unzErrorString(errcode)); -// } -// break; -// } -// } // end to while(!FileFound) -// } // end to if(ext) -// -// if((errcode = unzOpenCurrentFile(tz)) != UNZ_OK) -// { -// throw MDFN_Error(0, _("Could not open file in ZIP archive: %s"), unzErrorString(errcode)); -// } -// -// MakeMemWrap(tz, MDFN_FILETYPE_ZIP); -// -// { -// char *ld = strrchr(tempu, '.'); -// -// f_ext = strdup(ld ? ld + 1 : ""); -// f_fbase = strdup(tempu); -// if(ld) -// f_fbase[ld - tempu] = 0; -// } -// } -// else // If it's not a zip file, handle it as...another type of file! -// { -// if(!(fp = fopen(path, "rb"))) -// { -// ErrnoHolder ene(errno); -// -// throw MDFN_Error(ene.Errno(), _("Error opening \"%s\": %s"), path, ene.StrError()); -// } -// -// const char *path_fnp = GetFNComponent(path); -// -// uint32 gzmagic; -// -// gzmagic = ::fgetc(fp); -// gzmagic |= ::fgetc(fp) << 8; -// gzmagic |= ::fgetc(fp) << 16; -// -// if(gzmagic != 0x088b1f) /* Not gzip... */ -// { -// ::fseek(fp, 0, SEEK_SET); -// -// MakeMemWrap(fp, MDFN_FILETYPE_PLAIN); -// -// { -// const char *ld = strrchr(path_fnp, '.'); -// f_ext = strdup(ld ? ld + 1 : ""); -// f_fbase = strdup(path_fnp); -// if(ld) -// f_fbase[ld - path_fnp] = 0; -// } -// } -// else /* Probably gzip */ -// { -// fclose(fp); -// fp = NULL; -// -// // Clear errno so we can see if the error occurred within zlib or the C lib -// errno = 0; -// if(!(gzp = gzopen(path, "rb"))) -// { -// if(errno != 0) -// { -// ErrnoHolder ene(errno); -// -// throw MDFN_Error(ene.Errno(), _("Error opening \"%s\": %s"), path, ene.StrError()); -// } -// else -// throw MDFN_Error(0, _("Error opening \"%s\": %s"), path, _("zlib error")); -// } -// -// MakeMemWrap(gzp, MDFN_FILETYPE_GZIP); -// -// char *tmp_path = strdup(path_fnp); -// char *ld = strrchr(tmp_path, '.'); -// -// if(ld && ld > tmp_path) -// { -// char *last_ld = ld; -// *ld = 0; -// ld = strrchr(tmp_path, '.'); -// if(!ld) { ld = last_ld; } -// else *ld = 0; -// } -// f_ext = strdup(ld ? ld + 1 : ""); -// f_fbase = tmp_path; -// } // End gzip handling -// } // End normal and gzip file handling else to zip -// } -// catch(...) -// { -// if(tz != NULL) -// { -// unzCloseCurrentFile(tz); -// unzClose(tz); -// } -// -// if(fp != NULL) -// { -// fclose(fp); -// fp = NULL; -// } -// -// if(gzp != NULL) -// { -// gzclose(gzp); -// gzp = NULL; -// } -// -// Close(); -// throw; -// } -// -// if(tz != NULL) -// { -// unzCloseCurrentFile(tz); -// unzClose(tz); -// } -// -// if(fp != NULL) -// { -// fclose(fp); -// fp = NULL; -// } -// -// if(gzp != NULL) -// { -// gzclose(gzp); -// gzp = NULL; -// } -//} -// -//void MDFNFILE::Close(void) throw() -//{ -// if(f_ext) -// { -// free(f_ext); -// f_ext = NULL; -// } -// -// if(f_fbase) -// { -// free(f_fbase); -// f_fbase = NULL; -// } -// -// if(f_data) -// { -// #if HAVE_MMAP -// if(is_mmap) -// munmap(f_data, size); -// else -// #endif -// free(f_data); -// f_data = NULL; -// } -//} -// -//uint64 MDFNFILE::fread(void *ptr, size_t element_size, size_t nmemb) -//{ -// uint32 total = element_size * nmemb; -// -// if(location >= f_size) -// return 0; -// -// if((location + total) > f_size) -// { -// int64 ak = f_size - location; -// -// memcpy((uint8*)ptr, f_data + location, ak); -// -// location = f_size; -// -// return(ak / element_size); -// } -// else -// { -// memcpy((uint8*)ptr, f_data + location, total); -// -// location += total; -// -// return nmemb; -// } -//} -// -//int MDFNFILE::fseek(int64 offset, int whence) -//{ -// switch(whence) -// { -// case SEEK_SET:if(offset >= f_size) -// return(-1); -// location = offset; -// break; -// -// case SEEK_CUR:if((offset + location) > f_size) -// return(-1); -// -// location += offset; -// break; -// } -// return 0; -//} -// -//int MDFNFILE::read16le(uint16 *val) -//{ -// if((location + 2) > size) -// return 0; -// -// *val = MDFN_de16lsb(data + location); -// -// location += 2; -// -// return(1); -//} -// -//int MDFNFILE::read32le(uint32 *val) -//{ -// if((location + 4) > size) -// return 0; -// -// *val = MDFN_de32lsb(data + location); -// -// location += 4; -// -// return(1); -//} -// -//char *MDFNFILE::fgets(char *s, int buffer_size) -//{ -// int pos = 0; -// -// if(!buffer_size) -// return(NULL); -// -// if(location >= buffer_size) -// return(NULL); -// -// while(pos < (buffer_size - 1) && location < buffer_size) -// { -// int v = data[location]; -// s[pos] = v; -// location++; -// pos++; -// if(v == '\n') break; -// } -// -// if(buffer_size) -// s[pos] = 0; -// -// return(s); -//} -// -//static INLINE bool MDFN_DumpToFileReal(const char *filename, int compress, const std::vector &pearpairs) -//{ -// if(MDFN_GetSettingB("filesys.disablesavegz")) -// compress = 0; -// -// if(compress) -// { -// char mode[64]; -// gzFile gp; -// -// trio_snprintf(mode, 64, "wb%d", compress); -// -// gp = gzopen(filename, mode); -// -// if(!gp) -// { -// ErrnoHolder ene(errno); -// -// MDFN_PrintError(_("Error opening \"%s\": %s"), filename, ene.StrError()); -// return(0); -// } -// -// for(unsigned int i = 0; i < pearpairs.size(); i++) -// { -// const void *data = pearpairs[i].GetData(); -// const int64 length = pearpairs[i].GetLength(); -// -// if(gzwrite(gp, data, length) != length) -// { -// int errnum; -// -// MDFN_PrintError(_("Error writing to \"%s\": %s"), filename, gzerror(gp, &errnum)); -// gzclose(gp); -// return(0); -// } -// } -// -// if(gzclose(gp) != Z_OK) // FIXME: Huhm, how should we handle this? -// { -// MDFN_PrintError(_("Error closing \"%s\""), filename); -// return(0); -// } -// } -// else -// { -// FILE *fp = fopen(filename, "wb"); -// if(!fp) -// { -// ErrnoHolder ene(errno); -// -// MDFN_PrintError(_("Error opening \"%s\": %s"), filename, ene.StrError()); -// return(0); -// } -// -// for(unsigned int i = 0; i < pearpairs.size(); i++) -// { -// const void *data = pearpairs[i].GetData(); -// const uint64 length = pearpairs[i].GetLength(); -// -// if(fwrite(data, 1, length, fp) != length) -// { -// ErrnoHolder ene(errno); -// -// MDFN_PrintError(_("Error writing to \"%s\": %s"), filename, ene.StrError()); -// fclose(fp); -// return(0); -// } -// } -// -// if(fclose(fp) == EOF) -// { -// ErrnoHolder ene(errno); -// -// MDFN_PrintError(_("Error closing \"%s\": %s"), filename, ene.StrError()); -// return(0); -// } -// } -// return(1); -//} -// -//bool MDFN_DumpToFile(const char *filename, int compress, const std::vector &pearpairs) -//{ -// return(MDFN_DumpToFileReal(filename, compress, pearpairs)); -//} -// -//bool MDFN_DumpToFile(const char *filename, int compress, const void *data, uint64 length) -//{ -// std::vector tmp_pairs; -// tmp_pairs.push_back(PtrLengthPair(data, length)); -// return(MDFN_DumpToFileReal(filename, compress, tmp_pairs)); -//} diff --git a/psx/octoshock/file.h b/psx/octoshock/file.h deleted file mode 100644 index 847a038de9d..00000000000 --- a/psx/octoshock/file.h +++ /dev/null @@ -1,122 +0,0 @@ -#pragma once - -#include - -class Stream; - -#define MDFNFILE_EC_NOTFOUND 1 -#define MDFNFILE_EC_OTHER 2 - -class MDFNFILE -{ - public: - - MDFNFILE(const char *path, const void *known_ext, const char *purpose = NULL); - ~MDFNFILE(); - - void ApplyIPS(Stream *); - void Close(void) throw(); - - const int64 &size; - const uint8 * const &data; - const char * const &ext; - const char * const &fbase; - - inline int64 Size(void) - { - return(f_size); - } - - inline const uint8 *Data(void) - { - return(f_data); - } - - uint64 fread(void *ptr, size_t size, size_t nmemb); - int fseek(int64 offset, int whence); - - inline uint64 ftell(void) - { - return(location); - } - - inline void rewind(void) - { - location = 0; - } - - int read32le(uint32 *Bufo); - int read16le(uint16 *Bufo); - - inline int fgetc(void) - { - if(location < f_size) - return f_data[location++]; - - return EOF; - } - - inline int fisarchive(void) - { - return(0); - } - - char *fgets(char *s, int size); - - private: - - uint8 *f_data; - int64 f_size; - char *f_ext; - char *f_fbase; - - int64 location; - - #ifdef HAVE_MMAP - bool is_mmap; - #endif - - void Open(const char *path, const void *known_ext, const char *purpose = NULL); - void MakeMemWrap(void *tz, int type); -}; - -class PtrLengthPair -{ - public: - - inline PtrLengthPair(const void *new_data, const uint64 new_length) - { - data = new_data; - length = new_length; - } - - ~PtrLengthPair() - { - - } - - INLINE const void *GetData(void) const - { - return(data); - } - - INLINE uint64 GetLength(void) const - { - return(length); - } - - private: - const void *data; - uint64 length; -}; - -#include - -// These functions should be used for data like save states and non-volatile backup memory. -// Until(if, even) we add LoadFromFile functions, for reading the files these functions generate, just use gzopen(), gzread(), etc. -// "compress" is set to the zlib compression level. 0 disables compression entirely, and dumps the file without a gzip header or footer. -// (Note: There is a setting that will force compress to 0 in the internal DumpToFile logic, for hackers who don't want to ungzip save files.) - -bool MDFN_DumpToFile(const char *filename, int compress, const void *data, const uint64 length); -bool MDFN_DumpToFile(const char *filename, int compress, const std::vector &pearpairs); - diff --git a/psx/octoshock/git.h b/psx/octoshock/git.h deleted file mode 100644 index c6ca94b4cb6..00000000000 --- a/psx/octoshock/git.h +++ /dev/null @@ -1,354 +0,0 @@ -#ifndef _GIT_H -#define _GIT_H - -#include - -#include "octoshock.h" - -#include "video.h" -#include "file.h" - -class CDIF; - -typedef struct -{ - const char *extension; // Example ".nes" - const char *description; // Example "iNES Format ROM Image" -} FileExtensionSpecStruct; - -#include "file.h" - -enum -{ - MDFN_ROTATE0 = 0, - MDFN_ROTATE90, - MDFN_ROTATE180, - MDFN_ROTATE270 -}; - -typedef enum -{ - VIDSYS_NONE, // Can be used internally in system emulation code, but it is an error condition to let it continue to be - // after the Load() or LoadCD() function returns! - VIDSYS_PAL, - VIDSYS_PAL_M, // Same timing as NTSC, but uses PAL-style colour encoding - VIDSYS_NTSC, - VIDSYS_SECAM -} VideoSystems; - -typedef enum -{ - GMT_CART, // Self-explanatory! - GMT_ARCADE, // VS Unisystem, PC-10... - GMT_DISK, // Famicom Disk System, mostly - GMT_CDROM, // PC Engine CD, PC-FX - GMT_PLAYER // Music player(NSF, HES, GSF) -} GameMediumTypes; - -#ifdef WANT_DEBUGGER -// #ifdef WANT_DEBUGGER -// typedef struct DebuggerInfoStruct; -// #else -#include "debug.h" - -#endif - -typedef enum -{ - IDIT_BUTTON, // 1-bit - IDIT_BUTTON_CAN_RAPID, // 1-bit - - IDIT_X_AXIS, // (mouse) 16-bits, signed - in-screen/window range: [0.0, nominal_width) - IDIT_Y_AXIS, // (mouse) 16-bits, signed - in-screen/window range: [0.0, nominal_height) - - IDIT_X_AXIS_REL, // (mouse) 32-bits, signed - IDIT_Y_AXIS_REL, // (mouse) 32-bits, signed - - IDIT_BYTE_SPECIAL, - - IDIT_BUTTON_ANALOG, // 16-bits, 0 - 32767 - - IDIT_RUMBLE, // 16-bits, lower 8 bits are weak rumble(0-255), next 8 bits are strong rumble(0-255), 0=no rumble, 255=max rumble. Somewhat subjective, too... - // It's a rather special case of game module->driver code communication. -} InputDeviceInputType; - - -#define IDIT_BUTTON_ANALOG_FLAG_SQLR 0x00000001 // Denotes analog data that may need to be scaled to ensure a more squareish logical range(for emulated - // analog sticks). - -typedef struct -{ - const char *SettingName; // No spaces, shouldbe all a-z0-9 and _. Definitely no ~! - const char *Name; - const int ConfigOrder; // Configuration order during in-game config process, -1 for no config. - const InputDeviceInputType Type; - const char *ExcludeName; // SettingName of a button that can't be pressed at the same time as this button - // due to physical limitations. - - const char *RotateName[3]; // 90, 180, 270 - unsigned Flags; -} InputDeviceInputInfoStruct; - -typedef struct -{ - const char *ShortName; - const char *FullName; - const char *Description; - - //struct InputPortInfoStruct *PortExpanderDeviceInfo; - const void *PortExpanderDeviceInfo; // DON'T USE, IT'S NOT IMPLEMENTED PROPERLY CURRENTLY. - int NumInputs; // Usually just the number of buttons....OR if PortExpanderDeviceInfo is non-NULL, it's the number of input - // ports this port expander device provides. - const InputDeviceInputInfoStruct *IDII; -} InputDeviceInfoStruct; - -typedef struct -{ - const char *ShortName; - const char *FullName; - int NumTypes; // Number of unique input devices available for this input port - InputDeviceInfoStruct *DeviceInfo; - const char *DefaultDevice; // Default device for this port. -} InputPortInfoStruct; - -typedef struct -{ - int InputPorts; - const InputPortInfoStruct *Types; -} InputInfoStruct; - -struct MemoryPatch; - -typedef struct -{ - // Pitch(32-bit) must be equal to width and >= the "fb_width" specified in the MDFNGI struct for the emulated system. - // Height must be >= to the "fb_height" specified in the MDFNGI struct for the emulated system. - // The framebuffer pointed to by surface->pixels is written to by the system emulation code. - MDFN_Surface *surface; - - // Will be set to TRUE if the video pixel format has changed since the last call to Emulate(), FALSE otherwise. - // Will be set to TRUE on the first call to the Emulate() function/method - bool VideoFormatChanged; - - // Set by the system emulation code every frame, to denote the horizontal and vertical offsets of the image, and the size - // of the image. If the emulated system sets the elements of LineWidths, then the width(w) of this structure - // is ignored while drawing the image. - MDFN_Rect DisplayRect; - - // Pointer to an array of int32, number of elements = fb_height, set by the driver code. Individual elements written - // to by system emulation code. If the emulated system doesn't support multiple screen widths per frame, or if you handle - // such a situation by outputting at a constant width-per-frame that is the least-common-multiple of the screen widths, then - // you can ignore this. If you do wish to use this, you must set all elements every frame. - int32 *LineWidths; - - // TODO - bool *IsFMV; - - // Set(optionally) by emulation code. If InterlaceOn is true, then assume field height is 1/2 DisplayRect.h, and - // only every other line in surface (with the start line defined by InterlacedField) has valid data - // (it's up to internal Mednafen code to deinterlace it). - bool InterlaceOn; - bool InterlaceField; - - // Skip rendering this frame if true. Set by the driver code. - int skip; - - // - // If sound is disabled, the driver code must set SoundRate to false, SoundBuf to NULL, SoundBufMaxSize to 0. - - // Will be set to TRUE if the sound format(only rate for now, at least) has changed since the last call to Emulate(), FALSE otherwise. - // Will be set to TRUE on the first call to the Emulate() function/method - bool SoundFormatChanged; - - // Sound rate. Set by driver side. - double SoundRate; - - // Pointer to sound buffer, set by the driver code, that the emulation code should render sound to. - // Guaranteed to be at least 500ms in length, but emulation code really shouldn't exceed 40ms or so. Additionally, if emulation code - // generates >= 100ms, - // DEPRECATED: Emulation code may set this pointer to a sound buffer internal to the emulation module. - int16 *SoundBuf; - - // Maximum size of the sound buffer, in frames. Set by the driver code. - int32 SoundBufMaxSize; - - // Number of frames currently in internal sound buffer. Set by the system emulation code, to be read by the driver code. - int32 SoundBufSize; - int32 SoundBufSizeALMS; // SoundBufSize value at last MidSync(), 0 - // if mid sync isn't implemented for the emulation module in use. - - // Number of cycles that this frame consumed, using MDFNGI::MasterClock as a time base. - // Set by emulation code. - int64 MasterCycles; - int64 MasterCyclesALMS; // MasterCycles value at last MidSync(), 0 - // if mid sync isn't implemented for the emulation module in use. - - // Current sound volume(0.000...<=volume<=1.000...). If, after calling Emulate(), it is still != 1, Mednafen will handle it internally. - // Emulation modules can handle volume themselves if they like, for speed reasons. If they do, afterwards, they should set its value to 1. - double SoundVolume; - - // Current sound speed multiplier. Set by the driver code. If, after calling Emulate(), it is still != 1, Mednafen will handle it internally - // by resampling the audio. This means that emulation modules can handle(and set the value to 1 after handling it) it if they want to get the most - // performance possible. HOWEVER, emulation modules must make sure the value is in a range(with minimum and maximum) that their code can handle - // before they try to handle it. - double soundmultiplier; - - // True if we want to rewind one frame. Set by the driver code. - bool NeedRewind; - - // Sound reversal during state rewinding is normally done in mednafen.cpp, but - // individual system emulation code can also do it if this is set, and clear it after it's done. - // (Also, the driver code shouldn't touch this variable) - bool NeedSoundReverse; - -} EmulateSpecStruct; - - - -typedef struct -{ - /* Private functions to Mednafen. Do not call directly - from the driver code, or else bad things shall happen. Maybe. Probably not, but don't - do it(yet)! - */ - // Short system name, lowercase a-z, 0-9, and _ are the only allowable characters! - const char *shortname; - - // Full system name. Preferably English letters, but can be UTF8 - const char *fullname; - - // Pointer to an array of FileExtensionSpecStruct, with the last entry being { NULL, NULL } to terminate the list. - // This list is used to make best-guess choices, when calling the TestMagic*() functions would be unreasonable, such - // as when scanning a ZIP archive for a file to load. The list may also be used in the future for GUI file open windows. - const FileExtensionSpecStruct *FileExtensions; - - #ifdef WANT_DEBUGGER - DebuggerInfoStruct *Debugger; - #else - void *Debugger; - #endif - InputInfoStruct *InputInfo; - - // - // Returns 1 on successful load. - // throws exception on fatal error. - // - // DEPRECATED: Return 0 on fatal error. - // DEPRECATED: Return -1 on unrecognized format. - // - // fp's stream position is guaranteed to be 0 when this function is called. - // - int (*Load)(MDFNFILE *fp); - - // - // Return true if the file is a recognized type, false if not. - // - // fp's stream position is guaranteed to be 0 when this function is called. - // - bool (*TestMagic)(MDFNFILE *fp); - - // - // (*CDInterfaces).size() is guaranteed to be >= 1. - void (*LoadCD)(std::vector *CDInterfaces); - bool (*TestMagicCD)(std::vector *CDInterfaces); - - void (*CloseGame)(void); - - void (*SetLayerEnableMask)(uint64 mask); // Video - const char *LayerNames; - - void (*SetChanEnableMask)(uint64 mask); // Audio(TODO, placeholder) - const char *ChanNames; - - // - // InstallReadPatch and RemoveReadPatches should be non-NULL(even if only pointing to dummy functions) if the emulator module supports - // read-substitution and read-substitution-with-compare style(IE Game Genie-style) cheats. - // - // See also "SubCheats" global stuff in mempatcher.h. - // - void (*InstallReadPatch)(uint32 address, uint8 value, int compare); // Compare is >= 0 when utilized. - void (*RemoveReadPatches)(void); - uint8 (*MemRead)(uint32 addr); - - bool SaveStateAltersState; // true for bsnes and some libco-style emulators, false otherwise. - // Main save state routine, called by the save state code in state.cpp. - // When saving, load is set to 0. When loading, load is set to the version field of the save state being loaded. - // data_only is true when the save state data is temporary, such as being saved into memory for state rewinding. - - void (*Emulate)(EmulateSpecStruct *espec); - void (*SetInput)(int port, const char *type, void *ptr); - - void (*DoSimpleCommand)(int cmd); - - // Time base for EmulateSpecStruct::MasterCycles - // MasterClock must be >= MDFN_MASTERCLOCK_FIXED(1.0) - // All or part of the fractional component may be ignored in some timekeeping operations in the emulator to prevent integer overflow, - // so it is unwise to have a fractional component when the integral component is very small(less than say, 10000). - #define MDFN_MASTERCLOCK_FIXED(n) ((int64)((double)(n) * (1LL << 32))) - int64 MasterClock; - - // Nominal frames per second * 65536 * 256, truncated. - // May be deprecated in the future due to many systems having slight frame rate programmability. - uint32 fps; - - // multires is a hint that, if set, indicates that the system has fairly programmable video modes(particularly, the ability - // to display multiple horizontal resolutions, such as the PCE, PC-FX, or Genesis). In practice, it will cause the driver - // code to set the linear interpolation on by default. - // - // lcm_width and lcm_height are the least common multiples of all possible - // resolutions in the frame buffer as specified by DisplayRect/LineWidths(Ex for PCE: widths of 256, 341.333333, 512, - // lcm = 1024) - // - // nominal_width and nominal_height specify the resolution that Mednafen should display - // the framebuffer image in at 1x scaling, scaled from the dimensions of DisplayRect, and optionally the LineWidths array - // passed through espec to the Emulate() function. - // - bool multires; - - int lcm_width; - int lcm_height; - - void *dummy_separator; // - - int nominal_width; - int nominal_height; - - int fb_width; // Width of the framebuffer(not necessarily width of the image). MDFN_Surface width should be >= this. - int fb_height; // Height of the framebuffer passed to the Emulate() function(not necessarily height of the image) - - int soundchan; // Number of output sound channels. Only values of 1 and 2 are currently supported. - - - int rotated; - - uint8 *name; /* Game name, UTF8 encoding */ - uint8 MD5[16]; - uint8 GameSetMD5[16]; /* A unique ID for the game set this CD belongs to, only used in PC-FX emulation. */ - bool GameSetMD5Valid; /* True if GameSetMD5 is valid. */ - - uint8 StateMD5[16]; // ID to use in save state naming and netplay session IDs, if - bool StateMD5Valid; // StateMD5Valid is true(useful for systems with multiple BIOS revisions, e.g. PS1). - - int soundrate; /* For Ogg Vorbis expansion sound wacky support. 0 for default. */ - - VideoSystems VideoSystem; - GameMediumTypes GameType; - - //int DiskLogicalCount; // A single double-sided disk would be 2 here. - //const char *DiskNames; // Null-terminated. - - const char *cspecial; /* Special cart expansion: DIP switches, barcode reader, etc. */ - - std::vectorDesiredInput; // Desired input device for the input ports, NULL for don't care - - // For mouse relative motion. - double mouse_sensitivity; - - - // - // For absolute coordinates(IDIT_X_AXIS and IDIT_Y_AXIS), usually mapped to a mouse(hence the naming). - // - float mouse_scale_x, mouse_scale_y; - float mouse_offs_x, mouse_offs_y; -} MDFNGI; -#endif diff --git a/psx/octoshock/math_ops.h b/psx/octoshock/math_ops.h deleted file mode 100644 index 4154f2d49b3..00000000000 --- a/psx/octoshock/math_ops.h +++ /dev/null @@ -1,278 +0,0 @@ -/******************************************************************************/ -/* Mednafen - Multi-system Emulator */ -/******************************************************************************/ -/* math_ops.h: -** Copyright (C) 2007-2016 Mednafen Team -** -** 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., -** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -/* -** Some ideas from: -** blargg -** http://graphics.stanford.edu/~seander/bithacks.html -*/ - -#ifndef __MDFN_MATH_OPS_H -#define __MDFN_MATH_OPS_H - -#if defined(_MSC_VER) - #include -#endif - -static INLINE unsigned MDFN_lzcount16_0UD(uint16 v) -{ - #if defined(__GNUC__) || defined(__clang__) || defined(__ICC) || defined(__INTEL_COMPILER) - return 15 ^ 31 ^ __builtin_clz(v); - #elif defined(_MSC_VER) - unsigned long idx; - - _BitScanReverse(&idx, v); - - return 15 ^ idx; - #else - unsigned ret = 0; - unsigned tmp; - - tmp = !(v & 0xFF00) << 3; v <<= tmp; ret += tmp; - tmp = !(v & 0xF000) << 2; v <<= tmp; ret += tmp; - tmp = !(v & 0xC000) << 1; v <<= tmp; ret += tmp; - tmp = !(v & 0x8000) << 0; ret += tmp; - - return(ret); - #endif -} - -static INLINE unsigned MDFN_lzcount32_0UD(uint32 v) -{ - #if defined(__GNUC__) || defined(__clang__) || defined(__ICC) || defined(__INTEL_COMPILER) - return __builtin_clz(v); - #elif defined(_MSC_VER) - unsigned long idx; - - _BitScanReverse(&idx, v); - - return 31 ^ idx; - #else - unsigned ret = 0; - unsigned tmp; - - tmp = !(v & 0xFFFF0000) << 4; v <<= tmp; ret += tmp; - tmp = !(v & 0xFF000000) << 3; v <<= tmp; ret += tmp; - tmp = !(v & 0xF0000000) << 2; v <<= tmp; ret += tmp; - tmp = !(v & 0xC0000000) << 1; v <<= tmp; ret += tmp; - tmp = !(v & 0x80000000) << 0; ret += tmp; - - return(ret); - #endif -} - -static INLINE unsigned MDFN_lzcount64_0UD(uint64 v) -{ - #if defined(__GNUC__) || defined(__clang__) || defined(__ICC) || defined(__INTEL_COMPILER) - return __builtin_clzll(v); - #elif defined(_MSC_VER) - #if defined(_WIN64) - unsigned long idx; - _BitScanReverse64(&idx, v); - return 63 ^ idx; - #else - unsigned long idx0; - unsigned long idx1; - - _BitScanReverse(&idx1, v >> 0); - idx1 -= 32; - if(!_BitScanReverse(&idx0, v >> 32)) - idx0 = idx1; - - idx0 += 32; - - return 63 ^ idx0; - #endif - #else - unsigned ret = 0; - unsigned tmp; - - tmp = !(v & 0xFFFFFFFF00000000ULL) << 5; v <<= tmp; ret += tmp; - tmp = !(v & 0xFFFF000000000000ULL) << 4; v <<= tmp; ret += tmp; - tmp = !(v & 0xFF00000000000000ULL) << 3; v <<= tmp; ret += tmp; - tmp = !(v & 0xF000000000000000ULL) << 2; v <<= tmp; ret += tmp; - tmp = !(v & 0xC000000000000000ULL) << 1; v <<= tmp; ret += tmp; - tmp = !(v & 0x8000000000000000ULL) << 0; ret += tmp; - - return(ret); - #endif -} - -static INLINE unsigned MDFN_tzcount16_0UD(uint16 v) -{ - #if defined(__GNUC__) || defined(__clang__) || defined(__ICC) || defined(__INTEL_COMPILER) - return __builtin_ctz(v); - #elif defined(_MSC_VER) - unsigned long idx; - - _BitScanForward(&idx, v); - - return idx; - #else - unsigned ret = 0; - unsigned tmp; - - tmp = !( (uint8)v) << 3; v >>= tmp; ret += tmp; - tmp = !(v & 0x000F) << 2; v >>= tmp; ret += tmp; - tmp = !(v & 0x0003) << 1; v >>= tmp; ret += tmp; - tmp = !(v & 0x0001) << 0; ret += tmp; - - return ret; - #endif -} - -static INLINE unsigned MDFN_tzcount32_0UD(uint32 v) -{ - #if defined(__GNUC__) || defined(__clang__) || defined(__ICC) || defined(__INTEL_COMPILER) - return __builtin_ctz(v); - #elif defined(_MSC_VER) - unsigned long idx; - - _BitScanForward(&idx, v); - - return idx; - #else - unsigned ret = 0; - unsigned tmp; - - tmp = !((uint16)v) << 4; v >>= tmp; ret += tmp; - tmp = !( (uint8)v) << 3; v >>= tmp; ret += tmp; - tmp = !(v & 0x000F) << 2; v >>= tmp; ret += tmp; - tmp = !(v & 0x0003) << 1; v >>= tmp; ret += tmp; - tmp = !(v & 0x0001) << 0; ret += tmp; - - return ret; - #endif -} - -static INLINE unsigned MDFN_tzcount64_0UD(uint64 v) -{ - #if defined(__GNUC__) || defined(__clang__) || defined(__ICC) || defined(__INTEL_COMPILER) - return __builtin_ctzll(v); - #elif defined(_MSC_VER) - #if defined(_WIN64) - unsigned long idx; - _BitScanForward64(&idx, v); - return idx; - #else - unsigned long idx0, idx1; - - _BitScanForward(&idx1, v >> 32); - idx1 += 32; - if(!_BitScanForward(&idx0, v)) - idx0 = idx1; - - return idx0; - #endif - #else - unsigned ret = 0; - unsigned tmp; - - tmp = !((uint32)v) << 5; v >>= tmp; ret += tmp; - tmp = !((uint16)v) << 4; v >>= tmp; ret += tmp; - tmp = !( (uint8)v) << 3; v >>= tmp; ret += tmp; - tmp = !(v & 0x000F) << 2; v >>= tmp; ret += tmp; - tmp = !(v & 0x0003) << 1; v >>= tmp; ret += tmp; - tmp = !(v & 0x0001) << 0; ret += tmp; - - return ret; - #endif -} - -// -// Result is defined for all possible inputs(including 0). -// -static INLINE unsigned MDFN_lzcount16(uint16 v) { return !v ? 16 : MDFN_lzcount16_0UD(v); } -static INLINE unsigned MDFN_lzcount32(uint32 v) { return !v ? 32 : MDFN_lzcount32_0UD(v); } -static INLINE unsigned MDFN_lzcount64(uint64 v) { return !v ? 64 : MDFN_lzcount64_0UD(v); } - -static INLINE unsigned MDFN_tzcount16(uint16 v) { return !v ? 16 : MDFN_tzcount16_0UD(v); } -static INLINE unsigned MDFN_tzcount32(uint32 v) { return !v ? 32 : MDFN_tzcount32_0UD(v); } -static INLINE unsigned MDFN_tzcount64(uint64 v) { return !v ? 64 : MDFN_tzcount64_0UD(v); } - -static INLINE unsigned MDFN_log2(uint32 v) { return 31 ^ MDFN_lzcount32_0UD(v | 1); } -static INLINE unsigned MDFN_log2(uint64 v) { return 63 ^ MDFN_lzcount64_0UD(v | 1); } - -static INLINE unsigned MDFN_log2(int32 v) { return MDFN_log2((uint32)v); } -static INLINE unsigned MDFN_log2(int64 v) { return MDFN_log2((uint64)v); } - -// Rounds up to the nearest power of 2(treats input as unsigned to a degree, but be aware of integer promotion rules). -// Returns 0 on overflow. -static INLINE uint64 round_up_pow2(uint32 v) { uint64 tmp = (uint64)1 << MDFN_log2(v); return tmp << (tmp < v); } -static INLINE uint64 round_up_pow2(uint64 v) { uint64 tmp = (uint64)1 << MDFN_log2(v); return tmp << (tmp < v); } - -static INLINE uint64 round_up_pow2(int32 v) { return round_up_pow2((uint32)v); } -static INLINE uint64 round_up_pow2(int64 v) { return round_up_pow2((uint64)v); } - -// Rounds to the nearest power of 2(treats input as unsigned to a degree, but be aware of integer promotion rules). -static INLINE uint64 round_nearest_pow2(uint32 v, bool round_half_up = true) { uint64 tmp = (uint64)1 << MDFN_log2(v); return tmp << (v && (((v - tmp) << 1) >= (tmp + !round_half_up))); } -static INLINE uint64 round_nearest_pow2(uint64 v, bool round_half_up = true) { uint64 tmp = (uint64)1 << MDFN_log2(v); return tmp << (v && (((v - tmp) << 1) >= (tmp + !round_half_up))); } - -static INLINE uint64 round_nearest_pow2(int32 v, bool round_half_up = true) { return round_nearest_pow2((uint32)v, round_half_up); } -static INLINE uint64 round_nearest_pow2(int64 v, bool round_half_up = true) { return round_nearest_pow2((uint64)v, round_half_up); } - -// 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 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 diff --git a/psx/octoshock/octoshock.cpp b/psx/octoshock/octoshock.cpp deleted file mode 100644 index c8842921bde..00000000000 --- a/psx/octoshock/octoshock.cpp +++ /dev/null @@ -1,3 +0,0 @@ -#include "octoshock.h" - -//this file intentionally empty \ No newline at end of file diff --git a/psx/octoshock/octoshock.h b/psx/octoshock/octoshock.h deleted file mode 100644 index bcff0b06d93..00000000000 --- a/psx/octoshock/octoshock.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -#include "emuware/emuware.h" - -#define SIZEOF_DOUBLE 8 - -#define LSB_FIRST - -EW_EXPORT int os_test(); - -#include - -template typename std::remove_all_extents::type* MDAP(T* v) { return (typename std::remove_all_extents::type*)v; } diff --git a/psx/octoshock/psx/FastFIFO.h b/psx/octoshock/psx/FastFIFO.h deleted file mode 100644 index e6c822eedae..00000000000 --- a/psx/octoshock/psx/FastFIFO.h +++ /dev/null @@ -1,111 +0,0 @@ -/******************************************************************************/ -/* Mednafen Sony PS1 Emulation Module */ -/******************************************************************************/ -/* FastFIFO.h: -** Copyright (C) 2014-2016 Mednafen Team -** -** 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., -** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef __MDFN_FASTFIFO_H -#define __MDFN_FASTFIFO_H - -#include "emuware/EW_state.h" - -// size should be a power of 2. -template -class FastFIFO -{ - public: - - FastFIFO() - { - memset(data, 0, sizeof(data)); - read_pos = 0; - write_pos = 0; - in_count = 0; - } - - INLINE ~FastFIFO() - { - - } - - INLINE void SaveStatePostLoad(void) - { - read_pos %= size; - write_pos %= size; - in_count %= (size + 1); - } - - INLINE uint32 CanRead(void) - { - return(in_count); - } - - INLINE uint32 CanWrite(void) - { - return(size - in_count); - } - - INLINE T Peek(void) - { - return data[read_pos]; - } - - INLINE T Read(void) - { - T ret = data[read_pos]; - - read_pos = (read_pos + 1) & (size - 1); - in_count--; - - return(ret); - } - - INLINE void Write(const T& wr_data) - { - data[write_pos] = wr_data; - write_pos = (write_pos + 1) & (size - 1); - in_count++; - } - - INLINE void Flush(void) - { - read_pos = 0; - write_pos = 0; - in_count = 0; - } - - T data[size]; - uint32 read_pos; // Read position - uint32 write_pos; // Write position - uint32 in_count; // Number of units in the FIFO - - template void SyncState(EW::NewState *ns) - { - //I dont like this class... - - NSS(data); - NSS(read_pos); - NSS(write_pos); - NSS(in_count); - - SaveStatePostLoad(); - } -}; - - -#endif diff --git a/psx/octoshock/psx/Makefile.am b/psx/octoshock/psx/Makefile.am deleted file mode 100644 index 8e816d778e4..00000000000 --- a/psx/octoshock/psx/Makefile.am +++ /dev/null @@ -1,12 +0,0 @@ -AUTOMAKE_OPTIONS = subdir-objects -DEFS = -DLOCALEDIR=\"$(datadir)/locale\" @DEFS@ @MMX_CFLAGS@ @SSE_CFLAGS@ @SSE2_CFLAGS@ -funroll-loops -DEFAULT_INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include -I$(top_srcdir)/intl - -noinst_LIBRARIES = libpsx.a -libpsx_a_SOURCES = psx.cpp irq.cpp timer.cpp dma.cpp frontio.cpp sio.cpp cpu.cpp gte.cpp dis.cpp cdc.cpp spu.cpp mdec.cpp -libpsx_a_SOURCES += gpu.cpp gpu_polygon.cpp gpu_line.cpp gpu_sprite.cpp -libpsx_a_SOURCES += input/gamepad.cpp input/dualanalog.cpp input/dualshock.cpp input/memcard.cpp input/multitap.cpp input/mouse.cpp input/negcon.cpp input/guncon.cpp input/justifier.cpp - -if WANT_DEBUGGER -libpsx_a_SOURCES += debug.cpp -endif diff --git a/psx/octoshock/psx/Makefile.in b/psx/octoshock/psx/Makefile.in deleted file mode 100644 index 02873f4b28d..00000000000 --- a/psx/octoshock/psx/Makefile.in +++ /dev/null @@ -1,706 +0,0 @@ -# Makefile.in generated by automake 1.11.6 from Makefile.am. -# @configure_input@ - -# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, -# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software -# Foundation, Inc. -# This Makefile.in is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY, to the extent permitted by law; without -# even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. - -@SET_MAKE@ - -VPATH = @srcdir@ -am__make_dryrun = \ - { \ - am__dry=no; \ - case $$MAKEFLAGS in \ - *\\[\ \ ]*) \ - echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ - | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ - *) \ - for am__flg in $$MAKEFLAGS; do \ - case $$am__flg in \ - *=*|--*) ;; \ - *n*) am__dry=yes; break;; \ - esac; \ - done;; \ - esac; \ - test $$am__dry = yes; \ - } -pkgdatadir = $(datadir)/@PACKAGE@ -pkgincludedir = $(includedir)/@PACKAGE@ -pkglibdir = $(libdir)/@PACKAGE@ -pkglibexecdir = $(libexecdir)/@PACKAGE@ -am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd -install_sh_DATA = $(install_sh) -c -m 644 -install_sh_PROGRAM = $(install_sh) -c -install_sh_SCRIPT = $(install_sh) -c -INSTALL_HEADER = $(INSTALL_DATA) -transform = $(program_transform_name) -NORMAL_INSTALL = : -PRE_INSTALL = : -POST_INSTALL = : -NORMAL_UNINSTALL = : -PRE_UNINSTALL = : -POST_UNINSTALL = : -build_triplet = @build@ -host_triplet = @host@ -target_triplet = @target@ -@WANT_DEBUGGER_TRUE@am__append_1 = debug.cpp -subdir = src/psx -DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in -ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/m4/ax_cflags_gcc_option.m4 \ - $(top_srcdir)/m4/ax_cxx_compile_stdcxx_11.m4 \ - $(top_srcdir)/m4/codeset.m4 $(top_srcdir)/m4/fcntl-o.m4 \ - $(top_srcdir)/m4/gettext.m4 $(top_srcdir)/m4/glibc2.m4 \ - $(top_srcdir)/m4/glibc21.m4 $(top_srcdir)/m4/iconv.m4 \ - $(top_srcdir)/m4/intdiv0.m4 $(top_srcdir)/m4/intl.m4 \ - $(top_srcdir)/m4/intlmacosx.m4 $(top_srcdir)/m4/intmax.m4 \ - $(top_srcdir)/m4/inttypes-pri.m4 \ - $(top_srcdir)/m4/inttypes_h.m4 $(top_srcdir)/m4/lcmessage.m4 \ - $(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \ - $(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/libtool.m4 \ - $(top_srcdir)/m4/lock.m4 $(top_srcdir)/m4/longlong.m4 \ - $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ - $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ - $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \ - $(top_srcdir)/m4/printf-posix.m4 $(top_srcdir)/m4/progtest.m4 \ - $(top_srcdir)/m4/size_max.m4 $(top_srcdir)/m4/stdint_h.m4 \ - $(top_srcdir)/m4/threadlib.m4 $(top_srcdir)/m4/uintmax_t.m4 \ - $(top_srcdir)/m4/visibility.m4 $(top_srcdir)/m4/wchar_t.m4 \ - $(top_srcdir)/m4/wint_t.m4 $(top_srcdir)/m4/xsize.m4 \ - $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac -am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ - $(ACLOCAL_M4) -mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs -CONFIG_HEADER = $(top_builddir)/include/config.h -CONFIG_CLEAN_FILES = -CONFIG_CLEAN_VPATH_FILES = -LIBRARIES = $(noinst_LIBRARIES) -ARFLAGS = cru -AM_V_AR = $(am__v_AR_@AM_V@) -am__v_AR_ = $(am__v_AR_@AM_DEFAULT_V@) -am__v_AR_0 = @echo " AR " $@; -AM_V_at = $(am__v_at_@AM_V@) -am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) -am__v_at_0 = @ -libpsx_a_AR = $(AR) $(ARFLAGS) -libpsx_a_LIBADD = -am__libpsx_a_SOURCES_DIST = psx.cpp irq.cpp timer.cpp dma.cpp \ - frontio.cpp sio.cpp cpu.cpp gte.cpp dis.cpp cdc.cpp spu.cpp \ - mdec.cpp gpu.cpp gpu_polygon.cpp gpu_line.cpp gpu_sprite.cpp \ - input/gamepad.cpp input/dualanalog.cpp input/dualshock.cpp \ - input/memcard.cpp input/multitap.cpp input/mouse.cpp \ - input/negcon.cpp input/guncon.cpp input/justifier.cpp \ - debug.cpp -am__dirstamp = $(am__leading_dot)dirstamp -@WANT_DEBUGGER_TRUE@am__objects_1 = debug.$(OBJEXT) -am_libpsx_a_OBJECTS = psx.$(OBJEXT) irq.$(OBJEXT) timer.$(OBJEXT) \ - dma.$(OBJEXT) frontio.$(OBJEXT) sio.$(OBJEXT) cpu.$(OBJEXT) \ - gte.$(OBJEXT) dis.$(OBJEXT) cdc.$(OBJEXT) spu.$(OBJEXT) \ - mdec.$(OBJEXT) gpu.$(OBJEXT) gpu_polygon.$(OBJEXT) \ - gpu_line.$(OBJEXT) gpu_sprite.$(OBJEXT) \ - input/gamepad.$(OBJEXT) input/dualanalog.$(OBJEXT) \ - input/dualshock.$(OBJEXT) input/memcard.$(OBJEXT) \ - input/multitap.$(OBJEXT) input/mouse.$(OBJEXT) \ - input/negcon.$(OBJEXT) input/guncon.$(OBJEXT) \ - input/justifier.$(OBJEXT) $(am__objects_1) -libpsx_a_OBJECTS = $(am_libpsx_a_OBJECTS) -depcomp = $(SHELL) $(top_srcdir)/depcomp -am__depfiles_maybe = depfiles -am__mv = mv -f -CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ - $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -AM_V_lt = $(am__v_lt_@AM_V@) -am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) -am__v_lt_0 = --silent -LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ - $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \ - $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ - $(AM_CXXFLAGS) $(CXXFLAGS) -AM_V_CXX = $(am__v_CXX_@AM_V@) -am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) -am__v_CXX_0 = @echo " CXX " $@; -CXXLD = $(CXX) -CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ - $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ - $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ -AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) -am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) -am__v_CXXLD_0 = @echo " CXXLD " $@; -AM_V_GEN = $(am__v_GEN_@AM_V@) -am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) -am__v_GEN_0 = @echo " GEN " $@; -SOURCES = $(libpsx_a_SOURCES) -DIST_SOURCES = $(am__libpsx_a_SOURCES_DIST) -am__can_run_installinfo = \ - case $$AM_UPDATE_INFO_DIR in \ - n|no|NO) false;; \ - *) (install-info --version) >/dev/null 2>&1;; \ - esac -ETAGS = etags -CTAGS = ctags -DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) -ACLOCAL = @ACLOCAL@ -ALLOCA = @ALLOCA@ -ALSA_CFLAGS = @ALSA_CFLAGS@ -ALSA_LIBS = @ALSA_LIBS@ -AMTAR = @AMTAR@ -AM_CFLAGS = @AM_CFLAGS@ -AM_CXXFLAGS = @AM_CXXFLAGS@ -AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ -AR = @AR@ -AUTOCONF = @AUTOCONF@ -AUTOHEADER = @AUTOHEADER@ -AUTOMAKE = @AUTOMAKE@ -AWK = @AWK@ -BUILD_INCLUDED_LIBINTL = @BUILD_INCLUDED_LIBINTL@ -CATOBJEXT = @CATOBJEXT@ -CC = @CC@ -CCAS = @CCAS@ -CCASDEPMODE = @CCASDEPMODE@ -CCASFLAGS = @CCASFLAGS@ -CCDEPMODE = @CCDEPMODE@ -CFLAGS = @CFLAGS@ -CFLAG_VISIBILITY = @CFLAG_VISIBILITY@ -CPP = @CPP@ -CPPFLAGS = @CPPFLAGS@ -CXX = @CXX@ -CXXCPP = @CXXCPP@ -CXXDEPMODE = @CXXDEPMODE@ -CXXFLAGS = @CXXFLAGS@ -CYGPATH_W = @CYGPATH_W@ -DATADIRNAME = @DATADIRNAME@ -DEFS = -DLOCALEDIR=\"$(datadir)/locale\" @DEFS@ @MMX_CFLAGS@ @SSE_CFLAGS@ @SSE2_CFLAGS@ -funroll-loops -DEPDIR = @DEPDIR@ -DLLTOOL = @DLLTOOL@ -DSYMUTIL = @DSYMUTIL@ -DUMPBIN = @DUMPBIN@ -ECHO_C = @ECHO_C@ -ECHO_N = @ECHO_N@ -ECHO_T = @ECHO_T@ -EGREP = @EGREP@ -EXEEXT = @EXEEXT@ -FGREP = @FGREP@ -GENCAT = @GENCAT@ -GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ -GLIBC2 = @GLIBC2@ -GLIBC21 = @GLIBC21@ -GMSGFMT = @GMSGFMT@ -GMSGFMT_015 = @GMSGFMT_015@ -GREP = @GREP@ -HAVE_ASPRINTF = @HAVE_ASPRINTF@ -HAVE_CXX11 = @HAVE_CXX11@ -HAVE_NEWLOCALE = @HAVE_NEWLOCALE@ -HAVE_POSIX_PRINTF = @HAVE_POSIX_PRINTF@ -HAVE_SNPRINTF = @HAVE_SNPRINTF@ -HAVE_VISIBILITY = @HAVE_VISIBILITY@ -HAVE_WPRINTF = @HAVE_WPRINTF@ -INSTALL = @INSTALL@ -INSTALL_DATA = @INSTALL_DATA@ -INSTALL_PROGRAM = @INSTALL_PROGRAM@ -INSTALL_SCRIPT = @INSTALL_SCRIPT@ -INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ -INSTOBJEXT = @INSTOBJEXT@ -INTLBISON = @INTLBISON@ -INTLLIBS = @INTLLIBS@ -INTLOBJS = @INTLOBJS@ -INTL_DEFAULT_VERBOSITY = @INTL_DEFAULT_VERBOSITY@ -INTL_LIBTOOL_SUFFIX_PREFIX = @INTL_LIBTOOL_SUFFIX_PREFIX@ -INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ -JACK_CFLAGS = @JACK_CFLAGS@ -JACK_LIBS = @JACK_LIBS@ -LD = @LD@ -LDFLAGS = @LDFLAGS@ -LIBCDIO_CFLAGS = @LIBCDIO_CFLAGS@ -LIBCDIO_LIBS = @LIBCDIO_LIBS@ -LIBICONV = @LIBICONV@ -LIBINTL = @LIBINTL@ -LIBMULTITHREAD = @LIBMULTITHREAD@ -LIBOBJS = @LIBOBJS@ -LIBPTH = @LIBPTH@ -LIBPTH_PREFIX = @LIBPTH_PREFIX@ -LIBS = @LIBS@ -LIBTHREAD = @LIBTHREAD@ -LIBTOOL = @LIBTOOL@ -LIPO = @LIPO@ -LN_S = @LN_S@ -LTLIBC = @LTLIBC@ -LTLIBICONV = @LTLIBICONV@ -LTLIBINTL = @LTLIBINTL@ -LTLIBMULTITHREAD = @LTLIBMULTITHREAD@ -LTLIBOBJS = @LTLIBOBJS@ -LTLIBPTH = @LTLIBPTH@ -LTLIBTHREAD = @LTLIBTHREAD@ -MAKEINFO = @MAKEINFO@ -MANIFEST_TOOL = @MANIFEST_TOOL@ -MKDIR_P = @MKDIR_P@ -MMX_CFLAGS = @MMX_CFLAGS@ -MSGFMT = @MSGFMT@ -MSGFMT_015 = @MSGFMT_015@ -MSGMERGE = @MSGMERGE@ -NM = @NM@ -NMEDIT = @NMEDIT@ -OBJDUMP = @OBJDUMP@ -OBJEXT = @OBJEXT@ -OTOOL = @OTOOL@ -OTOOL64 = @OTOOL64@ -PACKAGE = @PACKAGE@ -PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ -PACKAGE_NAME = @PACKAGE_NAME@ -PACKAGE_STRING = @PACKAGE_STRING@ -PACKAGE_TARNAME = @PACKAGE_TARNAME@ -PACKAGE_URL = @PACKAGE_URL@ -PACKAGE_VERSION = @PACKAGE_VERSION@ -PATH_SEPARATOR = @PATH_SEPARATOR@ -PKG_CONFIG = @PKG_CONFIG@ -PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ -PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ -POSUB = @POSUB@ -PRI_MACROS_BROKEN = @PRI_MACROS_BROKEN@ -RANLIB = @RANLIB@ -SDL_CFLAGS = @SDL_CFLAGS@ -SDL_CONFIG = @SDL_CONFIG@ -SDL_LIBS = @SDL_LIBS@ -SED = @SED@ -SET_MAKE = @SET_MAKE@ -SHELL = @SHELL@ -SNDFILE_CFLAGS = @SNDFILE_CFLAGS@ -SNDFILE_LIBS = @SNDFILE_LIBS@ -SNES_EXTRA_CXXFLAGS = @SNES_EXTRA_CXXFLAGS@ -SNES_EXTRA_FLAGS = @SNES_EXTRA_FLAGS@ -SSE2_CFLAGS = @SSE2_CFLAGS@ -SSE3_CFLAGS = @SSE3_CFLAGS@ -SSE_CFLAGS = @SSE_CFLAGS@ -STRIP = @STRIP@ -TRIO_CFLAGS = @TRIO_CFLAGS@ -USE_INCLUDED_LIBINTL = @USE_INCLUDED_LIBINTL@ -USE_NLS = @USE_NLS@ -VERSION = @VERSION@ -WARNING_FLAGS = @WARNING_FLAGS@ -WINDRES = @WINDRES@ -WOE32 = @WOE32@ -WOE32DLL = @WOE32DLL@ -XGETTEXT = @XGETTEXT@ -XGETTEXT_015 = @XGETTEXT_015@ -XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ -abs_builddir = @abs_builddir@ -abs_srcdir = @abs_srcdir@ -abs_top_builddir = @abs_top_builddir@ -abs_top_srcdir = @abs_top_srcdir@ -ac_ct_AR = @ac_ct_AR@ -ac_ct_CC = @ac_ct_CC@ -ac_ct_CXX = @ac_ct_CXX@ -ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ -am__include = @am__include@ -am__leading_dot = @am__leading_dot@ -am__quote = @am__quote@ -am__tar = @am__tar@ -am__untar = @am__untar@ -bindir = @bindir@ -build = @build@ -build_alias = @build_alias@ -build_cpu = @build_cpu@ -build_os = @build_os@ -build_vendor = @build_vendor@ -builddir = @builddir@ -datadir = @datadir@ -datarootdir = @datarootdir@ -docdir = @docdir@ -dvidir = @dvidir@ -exec_prefix = @exec_prefix@ -host = @host@ -host_alias = @host_alias@ -host_cpu = @host_cpu@ -host_os = @host_os@ -host_vendor = @host_vendor@ -htmldir = @htmldir@ -includedir = @includedir@ -infodir = @infodir@ -install_sh = @install_sh@ -libdir = @libdir@ -libexecdir = @libexecdir@ -localedir = @localedir@ -localstatedir = @localstatedir@ -mandir = @mandir@ -mkdir_p = @mkdir_p@ -oldincludedir = @oldincludedir@ -pdfdir = @pdfdir@ -prefix = @prefix@ -program_transform_name = @program_transform_name@ -psdir = @psdir@ -sbindir = @sbindir@ -sharedstatedir = @sharedstatedir@ -srcdir = @srcdir@ -sysconfdir = @sysconfdir@ -target = @target@ -target_alias = @target_alias@ -target_cpu = @target_cpu@ -target_os = @target_os@ -target_vendor = @target_vendor@ -top_build_prefix = @top_build_prefix@ -top_builddir = @top_builddir@ -top_srcdir = @top_srcdir@ -AUTOMAKE_OPTIONS = subdir-objects -DEFAULT_INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include -I$(top_srcdir)/intl -noinst_LIBRARIES = libpsx.a -libpsx_a_SOURCES = psx.cpp irq.cpp timer.cpp dma.cpp frontio.cpp \ - sio.cpp cpu.cpp gte.cpp dis.cpp cdc.cpp spu.cpp mdec.cpp \ - gpu.cpp gpu_polygon.cpp gpu_line.cpp gpu_sprite.cpp \ - input/gamepad.cpp input/dualanalog.cpp input/dualshock.cpp \ - input/memcard.cpp input/multitap.cpp input/mouse.cpp \ - input/negcon.cpp input/guncon.cpp input/justifier.cpp \ - $(am__append_1) -all: all-am - -.SUFFIXES: -.SUFFIXES: .cpp .lo .o .obj -$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) - @for dep in $?; do \ - case '$(am__configure_deps)' in \ - *$$dep*) \ - ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ - && { if test -f $@; then exit 0; else break; fi; }; \ - exit 1;; \ - esac; \ - done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/psx/Makefile'; \ - $(am__cd) $(top_srcdir) && \ - $(AUTOMAKE) --gnu src/psx/Makefile -.PRECIOUS: Makefile -Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status - @case '$?' in \ - *config.status*) \ - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ - *) \ - echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ - esac; - -$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh - -$(top_srcdir)/configure: $(am__configure_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(ACLOCAL_M4): $(am__aclocal_m4_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(am__aclocal_m4_deps): - -clean-noinstLIBRARIES: - -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) -input/$(am__dirstamp): - @$(MKDIR_P) input - @: > input/$(am__dirstamp) -input/$(DEPDIR)/$(am__dirstamp): - @$(MKDIR_P) input/$(DEPDIR) - @: > input/$(DEPDIR)/$(am__dirstamp) -input/gamepad.$(OBJEXT): input/$(am__dirstamp) \ - input/$(DEPDIR)/$(am__dirstamp) -input/dualanalog.$(OBJEXT): input/$(am__dirstamp) \ - input/$(DEPDIR)/$(am__dirstamp) -input/dualshock.$(OBJEXT): input/$(am__dirstamp) \ - input/$(DEPDIR)/$(am__dirstamp) -input/memcard.$(OBJEXT): input/$(am__dirstamp) \ - input/$(DEPDIR)/$(am__dirstamp) -input/multitap.$(OBJEXT): input/$(am__dirstamp) \ - input/$(DEPDIR)/$(am__dirstamp) -input/mouse.$(OBJEXT): input/$(am__dirstamp) \ - input/$(DEPDIR)/$(am__dirstamp) -input/negcon.$(OBJEXT): input/$(am__dirstamp) \ - input/$(DEPDIR)/$(am__dirstamp) -input/guncon.$(OBJEXT): input/$(am__dirstamp) \ - input/$(DEPDIR)/$(am__dirstamp) -input/justifier.$(OBJEXT): input/$(am__dirstamp) \ - input/$(DEPDIR)/$(am__dirstamp) -libpsx.a: $(libpsx_a_OBJECTS) $(libpsx_a_DEPENDENCIES) $(EXTRA_libpsx_a_DEPENDENCIES) - $(AM_V_at)-rm -f libpsx.a - $(AM_V_AR)$(libpsx_a_AR) libpsx.a $(libpsx_a_OBJECTS) $(libpsx_a_LIBADD) - $(AM_V_at)$(RANLIB) libpsx.a - -mostlyclean-compile: - -rm -f *.$(OBJEXT) - -rm -f input/dualanalog.$(OBJEXT) - -rm -f input/dualshock.$(OBJEXT) - -rm -f input/gamepad.$(OBJEXT) - -rm -f input/guncon.$(OBJEXT) - -rm -f input/justifier.$(OBJEXT) - -rm -f input/memcard.$(OBJEXT) - -rm -f input/mouse.$(OBJEXT) - -rm -f input/multitap.$(OBJEXT) - -rm -f input/negcon.$(OBJEXT) - -distclean-compile: - -rm -f *.tab.c - -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cdc.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/debug.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dis.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dma.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/frontio.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gpu.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gpu_line.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gpu_polygon.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gpu_sprite.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gte.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/irq.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mdec.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/psx.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sio.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/spu.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/timer.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@input/$(DEPDIR)/dualanalog.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@input/$(DEPDIR)/dualshock.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@input/$(DEPDIR)/gamepad.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@input/$(DEPDIR)/guncon.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@input/$(DEPDIR)/justifier.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@input/$(DEPDIR)/memcard.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@input/$(DEPDIR)/mouse.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@input/$(DEPDIR)/multitap.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@input/$(DEPDIR)/negcon.Po@am__quote@ - -.cpp.o: -@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ -@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ -@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< - -.cpp.obj: -@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ -@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ -@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` - -.cpp.lo: -@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ -@am__fastdepCXX_TRUE@ $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ -@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $< - -mostlyclean-libtool: - -rm -f *.lo - -clean-libtool: - -rm -rf .libs _libs - -ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) - list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | \ - $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ - END { if (nonempty) { for (i in files) print i; }; }'`; \ - mkid -fID $$unique -tags: TAGS - -TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ - $(TAGS_FILES) $(LISP) - set x; \ - here=`pwd`; \ - list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | \ - $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ - END { if (nonempty) { for (i in files) print i; }; }'`; \ - shift; \ - if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ - test -n "$$unique" || unique=$$empty_fix; \ - if test $$# -gt 0; then \ - $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - "$$@" $$unique; \ - else \ - $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - $$unique; \ - fi; \ - fi -ctags: CTAGS -CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ - $(TAGS_FILES) $(LISP) - list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | \ - $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ - END { if (nonempty) { for (i in files) print i; }; }'`; \ - test -z "$(CTAGS_ARGS)$$unique" \ - || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ - $$unique - -GTAGS: - here=`$(am__cd) $(top_builddir) && pwd` \ - && $(am__cd) $(top_srcdir) \ - && gtags -i $(GTAGS_ARGS) "$$here" - -distclean-tags: - -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags - -distdir: $(DISTFILES) - @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - list='$(DISTFILES)'; \ - dist_files=`for file in $$list; do echo $$file; done | \ - sed -e "s|^$$srcdirstrip/||;t" \ - -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ - case $$dist_files in \ - */*) $(MKDIR_P) `echo "$$dist_files" | \ - sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ - sort -u` ;; \ - esac; \ - for file in $$dist_files; do \ - if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ - if test -d $$d/$$file; then \ - dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ - if test -d "$(distdir)/$$file"; then \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ - cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ - else \ - test -f "$(distdir)/$$file" \ - || cp -p $$d/$$file "$(distdir)/$$file" \ - || exit 1; \ - fi; \ - done -check-am: all-am -check: check-am -all-am: Makefile $(LIBRARIES) -installdirs: -install: install-am -install-exec: install-exec-am -install-data: install-data-am -uninstall: uninstall-am - -install-am: all-am - @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am - -installcheck: installcheck-am -install-strip: - if test -z '$(STRIP)'; then \ - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - install; \ - else \ - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ - fi -mostlyclean-generic: - -clean-generic: - -distclean-generic: - -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) - -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) - -rm -f input/$(DEPDIR)/$(am__dirstamp) - -rm -f input/$(am__dirstamp) - -maintainer-clean-generic: - @echo "This command is intended for maintainers to use" - @echo "it deletes files that may require special tools to rebuild." -clean: clean-am - -clean-am: clean-generic clean-libtool clean-noinstLIBRARIES \ - mostlyclean-am - -distclean: distclean-am - -rm -rf ./$(DEPDIR) input/$(DEPDIR) - -rm -f Makefile -distclean-am: clean-am distclean-compile distclean-generic \ - distclean-tags - -dvi: dvi-am - -dvi-am: - -html: html-am - -html-am: - -info: info-am - -info-am: - -install-data-am: - -install-dvi: install-dvi-am - -install-dvi-am: - -install-exec-am: - -install-html: install-html-am - -install-html-am: - -install-info: install-info-am - -install-info-am: - -install-man: - -install-pdf: install-pdf-am - -install-pdf-am: - -install-ps: install-ps-am - -install-ps-am: - -installcheck-am: - -maintainer-clean: maintainer-clean-am - -rm -rf ./$(DEPDIR) input/$(DEPDIR) - -rm -f Makefile -maintainer-clean-am: distclean-am maintainer-clean-generic - -mostlyclean: mostlyclean-am - -mostlyclean-am: mostlyclean-compile mostlyclean-generic \ - mostlyclean-libtool - -pdf: pdf-am - -pdf-am: - -ps: ps-am - -ps-am: - -uninstall-am: - -.MAKE: install-am install-strip - -.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ - clean-libtool clean-noinstLIBRARIES ctags distclean \ - distclean-compile distclean-generic distclean-libtool \ - distclean-tags distdir dvi dvi-am html html-am info info-am \ - install install-am install-data install-data-am install-dvi \ - install-dvi-am install-exec install-exec-am install-html \ - install-html-am install-info install-info-am install-man \ - install-pdf install-pdf-am install-ps install-ps-am \ - install-strip installcheck installcheck-am installdirs \ - maintainer-clean maintainer-clean-generic mostlyclean \ - mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ - pdf pdf-am ps ps-am tags uninstall uninstall-am - - -# Tell versions [3.59,3.63) of GNU make to not export all variables. -# Otherwise a system limit (for SysV at least) may be exceeded. -.NOEXPORT: diff --git a/psx/octoshock/psx/cdc.cpp b/psx/octoshock/psx/cdc.cpp deleted file mode 100644 index a27003cde1e..00000000000 --- a/psx/octoshock/psx/cdc.cpp +++ /dev/null @@ -1,2603 +0,0 @@ -/******************************************************************************/ -/* Mednafen Sony PS1 Emulation Module */ -/******************************************************************************/ -/* cdc.cpp: -** Copyright (C) 2011-2018 Mednafen Team -** -** 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., -** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -// TODO: Test seekl to CD-DA, and seekl to beyond end of disc. - -// TODO: Rewrite command processing to use switch() state machine madness, to handle some commands(like 0x0A) whose timing -// characteristics cannot be handled well with the current way. Be sure to test interruptability(with a new command) of the commands, too. - -#pragma GCC optimize ("unroll-loops") - -/* - Games to test after changing code affecting CD reading and buffering: - Bedlam (massive graphics corruption) - Rise 2 (massive graphics corruption) - - Captain Commando (boss graphics corruption on first stage) - Gran Turismo (missing music; GetLocL must be valid and sector data must be ready simultaneous with clearing of status seek bit and setting of reading bit) - Harukanaru Toki no Naka de - Banjou Yuugi (needs GetLocL to reflect dancing around target seek position after seek completes; otherwise hangs on voice acting) - Incredible Crisis (needs GetLocL to be valid after a SeekL; otherwise hangs without music near start of "Etsuko and the Golden Pig") - Tomb Raider(needs GetLocP to reflect dancing around just before target seek position after seek completes; otherwise, CD-DA tracks at M:S:F=x:x:0 fail to play and game hangs) - Vib Ribbon, with extra audio CD - Mortal Kombat Trilogy, music resumption after pause. - - Nightmare Creatures hangs during startup for some CD timing alignments/windows, and it spams command 0x0A without properly waiting for it to complete. -*/ - -// TODO: async command counter and async command phase? -/* - - TODO: - Implement missing commands. - - SPU CD-DA and CD-XA streaming semantics. -*/ - -/* - After eject(doesn't appear to occur when drive is in STOP state): - * Does not appear to occur in STOP state. - * Does not appear to occur in PAUSE state. - * DOES appear to occur in STANDBY state. (TODO: retest) - -% Result 0: 16 -% Result 1: 08 -% IRQ Result: e5 -% 19 e0 - - Command abortion tests(NOP tested): - Does not appear to occur when in STOP or PAUSE states(STOP or PAUSE command just executed). - - DOES occur after a ReadTOC completes, if ReadTOC is not followed by a STOP or PAUSE. Odd. -*/ - -#include "psx.h" -#include "cdc.h" -#include "spu.h" -#include "endian.h" - -using namespace CDUtility; - -namespace MDFN_IEN_PSX -{ - -PS_CDC::PS_CDC() : DMABuffer(4096) -{ - IsPSXDisc = false; - Cur_disc = NULL; - Open_disc = NULL; - EnableLEC = false; - - DriveStatus = DS_STOPPED; - PendingCommandPhase = 0; -} - -PS_CDC::~PS_CDC() -{ - -} - -void PS_CDC::OpenTray() -{ - //track the tray state - TrayOpen = true; - - //REMOVED in 1.22.0-UNSTABLE. this may cause problems. - //DMForceStop(); - - //zero 31-jan-2015 - psxtech says that what this is used for is actually a 'was open' flag which gets cleared after the status gets polled. - //so lets set it here, and rename it later if we're sure. - Status_TrayOpenBit = true; - - //since Cur_disc tracks what the CDC sees mounted, it can't see anything now that it's open, so exchange these states - Open_disc = Cur_disc; - Cur_disc = NULL; -} - -void PS_CDC::CloseTray(bool poke) -{ - //track the tray state - TrayOpen = false; - - //switch pending (open) disc to current disc - Cur_disc = Open_disc; - Open_disc = NULL; - - //cache Open_DiscID and clear it out - char disc_id[5]; - strncpy(disc_id,(char*)Open_DiscID,4); - memset(Open_DiscID,0,sizeof(Open_DiscID)); - - //prepare analysis if disc: leave in empty state - IsPSXDisc = false; - memset(DiscID, 0, sizeof(DiscID)); - - //stuff to always happen, even when poking: - if(Cur_disc) - { - Cur_disc->ReadTOC((ShockTOC*)&toc,(ShockTOCTrack*)toc.tracks); - - //complete analysis. if we had a disc ID, then it's a PSX disc; copy it in - if(disc_id[0]) - { - strncpy((char *)DiscID, disc_id, 4); - IsPSXDisc = true; - } - } - - //stuff to happen when not poking (reset CDC state) - if(Cur_disc && !poke) - { - HeaderBufValid = false; - DiscStartupDelay = (int64)1000 * 33868800 / 1000; - } - -} - -void PS_CDC::SetDisc(ShockDiscRef *disc, const char *disc_id, bool poke) -{ - //BIZHAWK NOTES: this functoin is quite different. - - Open_disc = disc; - strncpy((char*)Open_DiscID,disc_id,4); - - if(poke) - CloseTray(true); -} - -int32 PS_CDC::CalcNextEvent(void) -{ - int32 next_event = SPUCounter; - - if(PSRCounter > 0 && next_event > PSRCounter) - next_event = PSRCounter; - - if(PendingCommandCounter > 0 && next_event > PendingCommandCounter) - next_event = PendingCommandCounter; - - if(!(IRQBuffer & 0xF)) - { - if(CDCReadyReceiveCounter > 0 && next_event > CDCReadyReceiveCounter) - next_event = CDCReadyReceiveCounter; - } - - if(DiscStartupDelay > 0 && next_event > DiscStartupDelay) - next_event = DiscStartupDelay; - - //fprintf(stderr, "%d %d %d %d --- %d\n", PSRCounter, PendingCommandCounter, CDCReadyReceiveCounter, DiscStartupDelay, next_event); - - return(next_event); -} - -void PS_CDC::SoftReset(void) -{ - ClearAudioBuffers(); - - ReportLastF = 0; - ReportStartupDelay = 0; - - // Not sure about initial volume state - Pending_DecodeVolume[0][0] = 0x80; - Pending_DecodeVolume[0][1] = 0x00; - Pending_DecodeVolume[1][0] = 0x00; - Pending_DecodeVolume[1][1] = 0x80; - memcpy(DecodeVolume, Pending_DecodeVolume, sizeof(DecodeVolume)); - - RegSelector = 0; - memset(ArgsBuf, 0, sizeof(ArgsBuf)); - ArgsWP = ArgsRP = 0; - - ArgsReceiveLatch = 0; - memset(ArgsReceiveBuf, 0, sizeof(ArgsReceiveBuf)); - ArgsReceiveIn = 0; - - memset(ResultsBuffer, 0, sizeof(ResultsBuffer)); - ResultsWP = 0; - ResultsRP = 0; - ResultsIn = 0; - - CDCReadyReceiveCounter = 0; - - IRQBuffer = 0; - IRQOutTestMask = 0; - RecalcIRQ(); - - DMABuffer.Flush(); - SB_In = 0; - SectorPipe_Pos = SectorPipe_In = 0; - SectorsRead = 0; - - memset(SubQBuf, 0, sizeof(SubQBuf)); - memset(SubQBuf_Safe, 0, sizeof(SubQBuf_Safe)); - SubQChecksumOK = false; - - memset(HeaderBuf, 0, sizeof(HeaderBuf)); - - - FilterFile = 0; - FilterChan = 0; - - PendingCommand = 0; - PendingCommandPhase = 0; - PendingCommandCounter = 0; - - Mode = 0x20; - - HeaderBufValid = false; - SeekFinished = -1; - DriveStatus = DS_STOPPED; - ClearAIP(); - StatusAfterSeek = DS_STOPPED; - SeekRetryCounter = 0; - - Forward = false; - Backward = false; - Muted = false; - - PlayTrackMatch = 0; - - PSRCounter = 0; - - CurSector = 0; - - ClearAIP(); - - SeekTarget = 0; - - CommandLoc = 0; - CommandLoc_Dirty = true; - - Status_TrayOpenBit = true; - TrayOpen = false; -} - -void PS_CDC::Power(void) -{ - SPU->Power(); - - memset(SectorPipe, 0, sizeof(SectorPipe)); - memset(SB, 0, sizeof(SB)); - memset(AsyncResultsPending, 0, sizeof(AsyncResultsPending)); - memset(&DMABuffer.data[0], 0, DMABuffer.data.size()); - SoftReset(); - - HoldLogicalPos = false; - - DiscStartupDelay = 0; - - SPUCounter = SPU->UpdateFromCDC(0); - lastts = 0; -} - -SYNCFUNC(PS_CDC) -{ - NSS(TrayOpen); - - NSS(Status_TrayOpenBit); - NSS(DiscStartupDelay); - - NSS(AudioBuffer); - - NSS(Pending_DecodeVolume); - NSS(DecodeVolume); - - NSS(ADPCM_ResampBuf); - NSS(ADPCM_ResampCurPhase); - NSS(ADPCM_ResampCurPos); - - NSS(RegSelector); - NSS(ArgsBuf); - NSS(ArgsWP); - NSS(ArgsRP); - - NSS(ArgsReceiveLatch); - NSS(ArgsReceiveBuf); - NSS(ArgsReceiveIn); - - NSS(ResultsBuffer); - NSS(ResultsIn); - NSS(ResultsWP); - NSS(ResultsRP); - - SSS(DMABuffer); - - NSS(SB); - NSS(SB_In); - - NSS(SectorPipe); - NSS(SectorPipe_Pos); - NSS(SectorPipe_In); - - NSS(SubQBuf); - NSS(SubQBuf_Safe); - - NSS(SubQChecksumOK); - - NSS(HeaderBufValid); - NSS(HeaderBuf); - - NSS(IRQBuffer); - NSS(IRQOutTestMask); - NSS(CDCReadyReceiveCounter); - - - NSS(FilterFile); - NSS(FilterChan); - - NSS(PendingCommand); - NSS(PendingCommandPhase); - NSS(PendingCommandCounter); - - NSS(SPUCounter); - - NSS(Mode); - NSS(DriveStatus); - NSS(StatusAfterSeek); - NSS(Forward); - NSS(Backward); - NSS(Muted); - - NSS(PlayTrackMatch); - - NSS(PSRCounter); - NSS(HoldLogicalPos); - - NSS(CurSector); - NSS(SectorsRead); - - NSS(AsyncIRQPending); - NSS(AsyncResultsPending); - NSS(AsyncResultsPendingCount); - - NSS(SeekTarget); - NSS(SeekRetryCounter); - NSS(SeekFinished); - - // FIXME: Save TOC stuff? -#if 0 - CDUtility::TOC toc; - bool IsPSXDisc; - uint8 DiscID[4]; -#endif - - NSS(CommandLoc); - NSS(CommandLoc_Dirty); - NSS(xa_previous); - - NSS(ReportLastF); - NSS(ReportStartupDelay); - - //(%= crap about file format recovery in case SectorPipe_Pos changes) - - if(isReader) - { - if(AudioBuffer.Size > sizeof(AudioBuffer.Samples[0]) / sizeof(AudioBuffer.Samples[0][0])) - AudioBuffer.Size = sizeof(AudioBuffer.Samples[0]) / sizeof(AudioBuffer.Samples[0][0]); - - if(AudioBuffer.ReadPos > AudioBuffer.Size) - AudioBuffer.ReadPos = AudioBuffer.Size; - - ResultsRP &= 0xF; - ResultsWP &= 0xF; - ResultsIn &= 0x1F; - - ADPCM_ResampCurPos &= 0x1F; - ADPCM_ResampCurPhase %= 7; - } -} - -void PS_CDC::ResetTS(void) -{ - lastts = 0; -} - -void PS_CDC::RecalcIRQ(void) -{ - IRQ_Assert(IRQ_CD, (bool)(IRQBuffer & (IRQOutTestMask & 0x1F))); -} - -//static int32 doom_ts; -void PS_CDC::WriteIRQ(uint8 V) -{ - assert(CDCReadyReceiveCounter <= 0); - assert(!(IRQBuffer & 0xF)); - - //PSX_WARNING("[CDC] ***IRQTHINGY: 0x%02x -- %u", V, doom_ts); - - CDCReadyReceiveCounter = 2000; //1024; - - IRQBuffer = (IRQBuffer & 0x10) | V; - RecalcIRQ(); -} - -void PS_CDC::BeginResults(void) -{ - //if(ResultsIn) - // { - // printf("Cleared %d results. IRQBuffer=0x%02x\n", ResultsIn, IRQBuffer); - //} - - ResultsIn = 0; - ResultsWP = 0; - ResultsRP = 0; - - memset(ResultsBuffer, 0x00, sizeof(ResultsBuffer)); -} - -void PS_CDC::WriteResult(uint8 V) -{ - ResultsBuffer[ResultsWP] = V; - ResultsWP = (ResultsWP + 1) & 0xF; - ResultsIn = (ResultsIn + 1) & 0x1F; - - if(!ResultsIn) - PSX_WARNING("[CDC] Results buffer overflow!"); -} - -uint8 PS_CDC::ReadResult(void) -{ - uint8 ret = ResultsBuffer[ResultsRP]; - - if(!ResultsIn) - PSX_WARNING("[CDC] Results buffer underflow!"); - - ResultsRP = (ResultsRP + 1) & 0xF; - ResultsIn = (ResultsIn - 1) & 0x1F; - - return ret; -} - -uint8 PS_CDC::MakeStatus(bool cmd_error) -{ - uint8 ret = 0; - - // Are these bit positions right? - - if(DriveStatus == DS_PLAYING) - ret |= 0x80; - - if(DriveStatus == DS_READING) - ret |= 0x20; - - if(DriveStatus == DS_SEEKING || DriveStatus == DS_SEEKING_LOGICAL || DriveStatus == DS_SEEKING_LOGICAL2) - ret |= 0x40; - - if(Status_TrayOpenBit) - ret |= 0x10; - - if(DriveStatus != DS_STOPPED) - ret |= 0x02; - - if(cmd_error) - ret |= 0x01; - - //DiscChanged = false; // FIXME: Only do it on NOP command execution? //comment added with 0.9.38.5 - code removed by octoshock at some unknown point - //maybe a good point for looking at disc swap related bugs - - return(ret); -} - -bool PS_CDC::DecodeSubQ(uint8 *subpw) -{ - uint8 tmp_q[0xC]; - - memset(tmp_q, 0, 0xC); - - for(int i = 0; i < 96; i++) - tmp_q[i >> 3] |= ((subpw[i] & 0x40) >> 6) << (7 - (i & 7)); - - if((tmp_q[0] & 0xF) == 1) - { - memcpy(SubQBuf, tmp_q, 0xC); - SubQChecksumOK = subq_check_checksum(tmp_q); - - if(SubQChecksumOK) - { - memcpy(SubQBuf_Safe, tmp_q, 0xC); - return(true); - } - } - - return(false); -} - -static const int16 CDADPCMImpulse[7][25] = -{ - { 0, -5, 17, -35, 70, -23, -68, 347, -839, 2062, -4681, 15367, 21472, -5882, 2810, -1352, 635, -235, 26, 43, -35, 16, -8, 2, 0, }, /* 0 */ - { 0, -2, 10, -34, 65, -84, 52, 9, -266, 1024, -2680, 9036, 26516, -6016, 3021, -1571, 848, -365, 107, 10, -16, 17, -8, 3, -1, }, /* 1 */ - { -2, 0, 3, -19, 60, -75, 162, -227, 306, -67, -615, 3229, 29883, -4532, 2488, -1471, 882, -424, 166, -27, 5, 6, -8, 3, -1, }, /* 2 */ - { -1, 3, -2, -5, 31, -74, 179, -402, 689, -926, 1272, -1446, 31033, -1446, 1272, -926, 689, -402, 179, -74, 31, -5, -2, 3, -1, }, /* 3 */ - { -1, 3, -8, 6, 5, -27, 166, -424, 882, -1471, 2488, -4532, 29883, 3229, -615, -67, 306, -227, 162, -75, 60, -19, 3, 0, -2, }, /* 4 */ - { -1, 3, -8, 17, -16, 10, 107, -365, 848, -1571, 3021, -6016, 26516, 9036, -2680, 1024, -266, 9, 52, -84, 65, -34, 10, -2, 0, }, /* 5 */ - { 0, 2, -8, 16, -35, 43, 26, -235, 635, -1352, 2810, -5882, 21472, 15367, -4681, 2062, -839, 347, -68, -23, 70, -35, 17, -5, 0, }, /* 6 */ -}; - -void PS_CDC::ReadAudioBuffer(int32 samples[2]) -{ - samples[0] = AudioBuffer.Samples[0][AudioBuffer.ReadPos]; - samples[1] = AudioBuffer.Samples[1][AudioBuffer.ReadPos]; - - AudioBuffer.ReadPos++; -} - -INLINE void PS_CDC::ApplyVolume(int32 samples[2]) -{ - // - // Take care not to alter samples[] before we're done calculating the new output samples! - // - int32 left_out = ((samples[0] * DecodeVolume[0][0]) >> 7) + ((samples[1] * DecodeVolume[1][0]) >> 7); - int32 right_out = ((samples[0] * DecodeVolume[0][1]) >> 7) + ((samples[1] * DecodeVolume[1][1]) >> 7); - - clamp(&left_out, -32768, 32767); - clamp(&right_out, -32768, 32767); - - if(Muted) - { - left_out = 0; - right_out = 0; - } - - samples[0] = left_out; - samples[1] = right_out; -} - -// -// This function must always set samples[0] and samples[1], even if just to 0; range of samples[n] shall be restricted to -32768 through 32767. -// -void PS_CDC::GetCDAudio(int32 samples[2]) -{ - const unsigned freq = (AudioBuffer.ReadPos < AudioBuffer.Size) ? AudioBuffer.Freq : 0; - - samples[0] = 0; - samples[1] = 0; - - if(!freq) - return; - - if(freq == 7 || freq == 14) - { - ReadAudioBuffer(samples); - if(freq == 14) - ReadAudioBuffer(samples); - } - else - { - int32 out_tmp[2] = { 0, 0 }; - - for(unsigned i = 0; i < 2; i++) - { - const int16* imp = CDADPCMImpulse[ADPCM_ResampCurPhase]; - int16* wf = &ADPCM_ResampBuf[i][(ADPCM_ResampCurPos + 32 - 25) & 0x1F]; - - for(unsigned s = 0; s < 25; s++) - { - out_tmp[i] += imp[s] * wf[s]; - } - - out_tmp[i] >>= 15; - clamp(&out_tmp[i], -32768, 32767); - samples[i] = out_tmp[i]; - } - - ADPCM_ResampCurPhase += freq; - - if(ADPCM_ResampCurPhase >= 7) - { - int32 raw[2] = { 0, 0 }; - - ADPCM_ResampCurPhase -= 7; - ReadAudioBuffer(raw); - - for(unsigned i = 0; i < 2; i++) - { - ADPCM_ResampBuf[i][ADPCM_ResampCurPos + 0] = - ADPCM_ResampBuf[i][ADPCM_ResampCurPos + 32] = raw[i]; - } - ADPCM_ResampCurPos = (ADPCM_ResampCurPos + 1) & 0x1F; - } - } - - // - // Algorithmically, volume is applied after resampling for CD-XA ADPCM playback, per PS1 tests(though when "mute" is applied wasn't tested). - // - ApplyVolume(samples); -} - -EW_PACKED( -struct XA_Subheader -{ - uint8 file; - uint8 channel; - uint8 submode; - uint8 coding; - - uint8 file_dup; - uint8 channel_dup; - uint8 submode_dup; - uint8 coding_dup; -}); -static_assert(sizeof(XA_Subheader) == 8, "XA_Subheader wrong size!"); - -EW_PACKED( -struct XA_SoundGroup -{ - uint8 params[16]; - uint8 samples[112]; -}); -static_assert(sizeof(XA_SoundGroup) == 128, "XA_SoundGroup wrong size!"); - -#define XA_SUBMODE_EOF 0x80 -#define XA_SUBMODE_REALTIME 0x40 -#define XA_SUBMODE_FORM 0x20 -#define XA_SUBMODE_TRIGGER 0x10 -#define XA_SUBMODE_DATA 0x08 -#define XA_SUBMODE_AUDIO 0x04 -#define XA_SUBMODE_VIDEO 0x02 -#define XA_SUBMODE_EOR 0x01 - -#define XA_CODING_EMPHASIS 0x40 - -//#define XA_CODING_BPS_MASK 0x30 -//#define XA_CODING_BPS_4BIT 0x00 -//#define XA_CODING_BPS_8BIT 0x10 -//#define XA_CODING_SR_MASK 0x0C -//#define XA_CODING_SR_378 0x00 -//#define XA_CODING_SR_ - -#define XA_CODING_8BIT 0x10 -#define XA_CODING_189 0x04 -#define XA_CODING_STEREO 0x01 - -// Special regression prevention test cases: -// Um Jammer Lammy (start doing poorly) -// Yarudora Series Vol.1 - Double Cast (non-FMV speech) - -bool PS_CDC::XA_Test(const uint8 *sdata) -{ - const XA_Subheader *sh = (const XA_Subheader *)&sdata[12 + 4]; - - if(!(Mode & MODE_STRSND)) - return false; - - if(!(sh->submode & XA_SUBMODE_AUDIO)) - return false; - - //printf("Test File: 0x%02x 0x%02x - Channel: 0x%02x 0x%02x - Submode: 0x%02x 0x%02x - Coding: 0x%02x 0x%02x - \n", sh->file, sh->file_dup, sh->channel, sh->channel_dup, sh->submode, sh->submode_dup, sh->coding, sh->coding_dup); - - if((Mode & MODE_SF) && (sh->file != FilterFile || sh->channel != FilterChan)) - return false; - - return true; -} - -void PS_CDC::ClearAudioBuffers(void) -{ - memset(&AudioBuffer, 0, sizeof(AudioBuffer)); - memset(xa_previous, 0, sizeof(xa_previous)); - - memset(ADPCM_ResampBuf, 0, sizeof(ADPCM_ResampBuf)); - ADPCM_ResampCurPhase = 0; - ADPCM_ResampCurPos = 0; -} - -// -// output should be readable at -2 and -1 -static void DecodeXAADPCM(const uint8 *input, int16 *output, const unsigned shift, const unsigned weight) -{ - // Weights copied over from SPU channel ADPCM playback code, may not be entirely the same for CD-XA ADPCM, we need to run tests. - static const int32 Weights[16][2] = - { - // s-1 s-2 - { 0, 0 }, - { 60, 0 }, - { 115, -52 }, - { 98, -55 }, - { 122, -60 }, - }; - - for(int i = 0; i < 28; i++) - { - int32 sample; - - sample = (int16)(input[i] << 8); - sample >>= shift; - - sample += ((output[i - 1] * Weights[weight][0]) >> 6) + ((output[i - 2] * Weights[weight][1]) >> 6); - - if(sample < -32768) - sample = -32768; - - if(sample > 32767) - sample = 32767; - - output[i] = sample; - } -} - -void PS_CDC::XA_ProcessSector(const uint8 *sdata, CD_Audio_Buffer *ab) -{ - const XA_Subheader *sh = (const XA_Subheader *)&sdata[12 + 4]; - const unsigned unit_index_shift = (sh->coding & XA_CODING_8BIT) ? 0 : 1; - - //printf("File: 0x%02x 0x%02x - Channel: 0x%02x 0x%02x - Submode: 0x%02x 0x%02x - Coding: 0x%02x 0x%02x - \n", sh->file, sh->file_dup, sh->channel, sh->channel_dup, sh->submode, sh->submode_dup, sh->coding, sh->coding_dup); - ab->ReadPos = 0; - ab->Size = 18 * (4 << unit_index_shift) * 28; - - if(sh->coding & XA_CODING_STEREO) - ab->Size >>= 1; - - ab->Freq = (sh->coding & XA_CODING_189) ? 3 : 6; - - //fprintf(stderr, "Coding: %02x %02x\n", sh->coding, sh->coding_dup); - - for(unsigned group = 0; group < 18; group++) - { - const XA_SoundGroup *sg = (const XA_SoundGroup *)&sdata[12 + 4 + 8 + group * 128]; - - for(unsigned unit = 0; unit < (4U << unit_index_shift); unit++) - { - const uint8 param = sg->params[(unit & 3) | ((unit & 4) << 1)]; - const uint8 param_copy = sg->params[4 | (unit & 3) | ((unit & 4) << 1)]; - uint8 ibuffer[28]; - int16 obuffer[2 + 28]; - - if(param != param_copy) - { - PSX_WARNING("[CDC] CD-XA param != param_copy --- %d %02x %02x\n", unit, param, param_copy); - } - - for(unsigned i = 0; i < 28; i++) - { - uint8 tmp = sg->samples[i * 4 + (unit >> unit_index_shift)]; - - if(unit_index_shift) - { - tmp <<= (unit & 1) ? 0 : 4; - tmp &= 0xf0; - } - - ibuffer[i] = tmp; - } - - const bool ocn = (bool)(unit & 1) && (sh->coding & XA_CODING_STEREO); - - obuffer[0] = xa_previous[ocn][0]; - obuffer[1] = xa_previous[ocn][1]; - - DecodeXAADPCM(ibuffer, &obuffer[2], param & 0x0F, param >> 4); - - xa_previous[ocn][0] = obuffer[28]; - xa_previous[ocn][1] = obuffer[29]; - - if(param != param_copy) - memset(obuffer, 0, sizeof(obuffer)); - - if(sh->coding & XA_CODING_STEREO) - { - for(unsigned s = 0; s < 28; s++) - { - ab->Samples[ocn][group * (2 << unit_index_shift) * 28 + (unit >> 1) * 28 + s] = obuffer[2 + s]; - } - } - else - { - for(unsigned s = 0; s < 28; s++) - { - ab->Samples[0][group * (4 << unit_index_shift) * 28 + unit * 28 + s] = obuffer[2 + s]; - ab->Samples[1][group * (4 << unit_index_shift) * 28 + unit * 28 + s] = obuffer[2 + s]; - } - } - } - } - -#if 0 - // Test - for(unsigned i = 0; i < ab->Size; i++) - { - static unsigned counter = 0; - - ab->Samples[0][i] = (counter & 2) ? -0x6000 : 0x6000; - ab->Samples[1][i] = rand(); - counter++; - } -#endif -} - -void PS_CDC::ClearAIP(void) -{ - AsyncResultsPendingCount = 0; - AsyncIRQPending = 0; -} - -void PS_CDC::CheckAIP(void) -{ - if(AsyncIRQPending && CDCReadyReceiveCounter <= 0) - { - BeginResults(); - - for(unsigned i = 0; i < AsyncResultsPendingCount; i++) - WriteResult(AsyncResultsPending[i]); - - WriteIRQ(AsyncIRQPending); - - ClearAIP(); - } -} - -void PS_CDC::SetAIP(unsigned irq, unsigned result_count, uint8 *r) -{ - if(AsyncIRQPending) - { - PSX_WARNING("***WARNING*** Previous notification skipped: CurSector=%d, old_notification=0x%02x", CurSector, AsyncIRQPending); - } - ClearAIP(); - - AsyncResultsPendingCount = result_count; - - for(unsigned i = 0; i < result_count; i++) - AsyncResultsPending[i] = r[i]; - - AsyncIRQPending = irq; - - CheckAIP(); -} - -void PS_CDC::SetAIP(unsigned irq, uint8 result0) -{ - uint8 tr[1] = { result0 }; - SetAIP(irq, 1, tr); -} - -void PS_CDC::SetAIP(unsigned irq, uint8 result0, uint8 result1) -{ - uint8 tr[2] = { result0, result1 }; - SetAIP(irq, 2, tr); -} - - -void PS_CDC::EnbufferizeCDDASector(const uint8 *buf) -{ - CD_Audio_Buffer *ab = &AudioBuffer; - - ab->Freq = 7 * ((Mode & MODE_SPEED) ? 2 : 1); - ab->Size = 588; - - if(SubQBuf_Safe[0] & 0x40) - { - for(int i = 0; i < 588; i++) - { - ab->Samples[0][i] = 0; - ab->Samples[1][i] = 0; - } - } - else - { - for(int i = 0; i < 588; i++) - { - ab->Samples[0][i] = (int16)MDFN_de16lsb(&buf[i * sizeof(int16) * 2 + 0]); - ab->Samples[1][i] = (int16)MDFN_de16lsb(&buf[i * sizeof(int16) * 2 + 2]); - } - } - - ab->ReadPos = 0; -} - -void PS_CDC::HandlePlayRead(void) -{ - uint8 read_buf[2352 + 96]; - - //PSX_WARNING("Read sector: %d", CurSector); - - if(CurSector >= ((int32)toc.tracks[100].lba + 300) && CurSector >= (75 * 60 * 75 - 150)) - { - PSX_WARNING("[CDC] Read/Play position waaay too far out(%u), forcing STOP", CurSector); - SeekFinished = -1; - DriveStatus = DS_STOPPED; - SectorPipe_Pos = SectorPipe_In = 0; - SectorsRead = 0; - return; - } - - if(CurSector >= (int32)toc.tracks[100].lba) - { - PSX_WARNING("[CDC] In leadout area: %u", CurSector); - } - - Cur_disc->ReadLBA2448(CurSector,read_buf); // FIXME: error out on error. - DecodeSubQ(read_buf + 2352); - - if(SubQBuf_Safe[1] == 0xAA && (DriveStatus == DS_PLAYING || (DriveStatus == DS_READING && !(SubQBuf_Safe[0] & 0x40) && (Mode & MODE_CDDA)))) - { - HeaderBufValid = false; - - PSX_WARNING("[CDC] CD-DA leadout reached: %u", CurSector); - - // Status in this end-of-disc context here should be generated after we're in the pause state. - SeekTarget = CurSector; - DriveStatus = DS_PAUSED; - SectorPipe_Pos = SectorPipe_In = 0; - SectorsRead = 0; - SetAIP(CDCIRQ_DATA_END, MakeStatus()); - - return; - } - - if(DriveStatus == DS_PLAYING) - { - if(Mode & MODE_AUTOPAUSE) - { - // Note: Some game(s) start playing in the pregap of a track(so don't replace this with a simple subq index == 0 check for autopause). - // Pitball enables autopause a while after playing starts. - // - if(PlayTrackMatch == -1 && SubQChecksumOK) - PlayTrackMatch = SubQBuf_Safe[0x1]; - - if(PlayTrackMatch != -1 && SubQBuf_Safe[0x1] != PlayTrackMatch) - { - // Status needs to be taken before we're paused(IE it should still report playing). - SetAIP(CDCIRQ_DATA_END, MakeStatus()); - - SeekTarget = CurSector; - DriveStatus = DS_PAUSED; - SectorPipe_Pos = SectorPipe_In = 0; - SectorsRead = 0; - PSRCounter = 0; - return; - } - } - - if((Mode & MODE_REPORT) && ReportStartupDelay <= 0 && (((SubQBuf_Safe[0x9] >> 4) != ReportLastF) || Forward || Backward) && SubQChecksumOK) - { - uint8 tr[8]; - uint16 abs_lev_max = 0; - bool abs_lev_chselect = SubQBuf_Safe[0x8] & 0x01; - - for(int i = 0; i < 588; i++) - abs_lev_max = std::max(abs_lev_max, std::min(abs((int16)MDFN_de16lsb(&read_buf[i * 4 + (abs_lev_chselect * 2)])), 32767)); - abs_lev_max |= abs_lev_chselect << 15; - - tr[0] = MakeStatus(); - tr[1] = SubQBuf_Safe[0x1]; // Track - tr[2] = SubQBuf_Safe[0x2]; // Index - - if(SubQBuf_Safe[0x9] & 0x10) - { - tr[3] = SubQBuf_Safe[0x3]; // R M - tr[4] = SubQBuf_Safe[0x4] | 0x80; // R S - tr[5] = SubQBuf_Safe[0x5]; // R F - } - else - { - tr[3] = SubQBuf_Safe[0x7]; // A M - tr[4] = SubQBuf_Safe[0x8]; // A S - tr[5] = SubQBuf_Safe[0x9]; // A F - } - - tr[6] = abs_lev_max >> 0; - tr[7] = abs_lev_max >> 8; - - SetAIP(CDCIRQ_DATA_READY, 8, tr); - } - ReportLastF = SubQBuf_Safe[0x9] >> 4; - } - - if(SectorPipe_In >= SectorPipe_Count) - { - uint8* buf = SectorPipe[SectorPipe_Pos]; - SectorPipe_In--; - - if(SubQBuf_Safe[0] & 0x40) // Data sector - { - if(DriveStatus == DS_SEEKING_LOGICAL2 || DriveStatus == DS_READING || (HoldLogicalPos && (DriveStatus == DS_PAUSED || DriveStatus == DS_STANDBY))) - { - memcpy(HeaderBuf, buf + 12, 12); - HeaderBufValid = true; - - if(DriveStatus == DS_SEEKING_LOGICAL2) - { - if(AMSF_to_LBA(BCD_to_U8(HeaderBuf[0]), BCD_to_U8(HeaderBuf[1]), BCD_to_U8(HeaderBuf[2])) == SeekTarget) - { - //puts("Logical2 seek finished"); - DriveStatus = StatusAfterSeek; - SeekFinished = true; - ReportStartupDelay = 24000000; - } - else - { - if(!SeekRetryCounter) - { - HoldLogicalPos = false; - DriveStatus = DS_STANDBY; - SeekFinished = -1; - } - else - SeekRetryCounter--; - } - } - } - // - // - // - //printf("%d, %02x:%02x:%02x --- %d %d\n", DriveStatus, HeaderBuf[0], HeaderBuf[1], HeaderBuf[2], SeekTarget, AMSF_to_LBA(BCD_to_U8(HeaderBuf[0]), BCD_to_U8(HeaderBuf[1]), BCD_to_U8(HeaderBuf[2]))); - - if(DriveStatus == DS_READING) - { - if((Mode & MODE_STRSND) && (buf[12 + 3] == 0x2) && ((buf[12 + 6] & 0x64) == 0x64)) - { - if(XA_Test(buf)) - { - if(AudioBuffer.ReadPos < AudioBuffer.Size) - { - PSX_WARNING("[CDC] CD-XA ADPCM sector skipped - readpos=0x%04x, size=0x%04x", AudioBuffer.ReadPos, AudioBuffer.Size); - } - else - { - XA_ProcessSector(buf, &AudioBuffer); - } - } - } - else - { - // maybe if(!(Mode & 0x30)) too? - if(!(buf[12 + 6] & 0x20)) - { - if(!edc_lec_check_and_correct(buf, true)) - { - printf(("Uncorrectable error(s) in sector %d."), CurSector); - } - } - - if(!(Mode & 0x30) && (buf[12 + 6] & 0x20)) - PSX_WARNING("[CDC] BORK: %d", CurSector); - - int32 offs = (Mode & 0x20) ? 0 : 12; - int32 size = (Mode & 0x20) ? 2340 : 2048; - - if(Mode & 0x10) - { - offs = 12; - size = 2328; - } - - memcpy(SB, buf + 12 + offs, size); - SB_In = size; - SetAIP(CDCIRQ_DATA_READY, MakeStatus()); - } - } - } - else // CD-DA sector - { - if(DriveStatus == DS_SEEKING_LOGICAL2) - { - if(Mode & MODE_CDDA) - { - DriveStatus = StatusAfterSeek; - SeekFinished = true; - ReportStartupDelay = 24000000; - } - else - { - if(!SeekRetryCounter) - { - HoldLogicalPos = false; - DriveStatus = DS_STANDBY; - SeekFinished = -1; - } - else - SeekRetryCounter--; - } - } - // - // - // - if((DriveStatus == DS_READING && (Mode & MODE_CDDA)) || DriveStatus == DS_PLAYING) - { - if(AudioBuffer.ReadPos < AudioBuffer.Size) - { - PSX_WARNING("[CDC] BUG CDDA buffer full"); - } - else - { - EnbufferizeCDDASector(buf); - } - } - } - } - - memcpy(SectorPipe[SectorPipe_Pos], read_buf, 2352); - SectorPipe_Pos = (SectorPipe_Pos + 1) % SectorPipe_Count; - SectorPipe_In++; - - PSRCounter += 33868800 / (75 * ((Mode & MODE_SPEED) ? 2 : 1)); - - if(DriveStatus == DS_PLAYING) - { - // FIXME: What's the real fast-forward and backward speed? - if(Forward) - CurSector += 12; - else if(Backward) - { - CurSector -= 12; - - if(CurSector < 0) // FIXME: How does a real PS handle this condition? - CurSector = 0; - } - else - CurSector++; - } - else - CurSector++; - - if(DriveStatus == DS_PAUSED || DriveStatus == DS_STANDBY) // || DriveStatus == DS_SEEKING_LOGICAL2) - { - if(CurSector >= (SeekTarget + (HoldLogicalPos ? 2 : 0))) - CurSector = std::max(-150, CurSector - 9); - } - else - SectorsRead++; -} - -pscpu_timestamp_t PS_CDC::Update(const pscpu_timestamp_t timestamp) -{ - int32 clocks = timestamp - lastts; - - if(!Cur_disc) - { - if(DriveStatus != DS_STOPPED || (PendingCommandCounter > 0 && PendingCommandPhase >= 2)) - { - SetAIP(CDCIRQ_DISC_ERROR, (MakeStatus() & ~0xE0) | 0x04, 0x08); - - SectorPipe_Pos = SectorPipe_In = 0; - SectorsRead = 0; - HeaderBufValid = false; - SeekFinished = -1; - - DriveStatus = DS_STOPPED; - PSRCounter = 0; - - if(PendingCommandPhase >= 2) - { - PendingCommand = 0x00; - PendingCommandCounter = 0; - PendingCommandPhase = 0; - } - } - - DiscStartupDelay = 0; - } - // - // - // - while(clocks > 0) - { - int32 chunk_clocks = clocks; - - if(PSRCounter > 0 && chunk_clocks > PSRCounter) - chunk_clocks = PSRCounter; - - if(PendingCommandCounter > 0 && chunk_clocks > PendingCommandCounter) - chunk_clocks = PendingCommandCounter; - - if(chunk_clocks > SPUCounter) - chunk_clocks = SPUCounter; - - if(DiscStartupDelay > 0) - { - if(chunk_clocks > DiscStartupDelay) - chunk_clocks = DiscStartupDelay; - - DiscStartupDelay -= chunk_clocks; - - if(DiscStartupDelay <= 0) - { - SeekTarget = CurSector; - HoldLogicalPos = false; - DriveStatus = DS_PAUSED; // or is it supposed to be DS_STANDBY? - } - } - - //MDFN_DispMessage("%02x %d -- %d %d -- %02x", IRQBuffer, CDCReadyReceiveCounter, PSRCounter, PendingCommandCounter, PendingCommand); - - if(!(IRQBuffer & 0xF)) - { - if(CDCReadyReceiveCounter > 0 && chunk_clocks > CDCReadyReceiveCounter) - chunk_clocks = CDCReadyReceiveCounter; - - if(CDCReadyReceiveCounter > 0) - CDCReadyReceiveCounter -= chunk_clocks; - } - - CheckAIP(); - - if(PSRCounter > 0) - { - PSRCounter -= chunk_clocks; - - if(ReportStartupDelay > 0) - ReportStartupDelay -= chunk_clocks; - - if(PSRCounter <= 0) - { - if(DriveStatus == DS_SEEKING) - { - CurSector = SeekTarget; - - HoldLogicalPos = false; - DriveStatus = StatusAfterSeek; - SeekFinished = true; - ReportStartupDelay = 24000000; - - if(DriveStatus == DS_PAUSED || DriveStatus == DS_STANDBY) - CurSector = std::max(-150, CurSector - 9); - - PSRCounter = 33868800 / (75 * ((Mode & MODE_SPEED) ? 2 : 1)); - } - else if(DriveStatus == DS_SEEKING_LOGICAL) - { - CurSector = SeekTarget; - - HoldLogicalPos = true; - DriveStatus = DS_SEEKING_LOGICAL2; - } - // - // - // - if(DriveStatus == DS_PAUSED || DriveStatus == DS_STANDBY || DriveStatus == DS_READING || DriveStatus == DS_PLAYING || DriveStatus == DS_SEEKING_LOGICAL2) - { - HandlePlayRead(); - } - } - } - - if(PendingCommandCounter > 0) - { - PendingCommandCounter -= chunk_clocks; - - if(PendingCommandCounter <= 0 && CDCReadyReceiveCounter > 0) - { - PendingCommandCounter = CDCReadyReceiveCounter; //256; - } - //else if(PendingCommandCounter <= 0 && PSRCounter > 0 && PSRCounter < 2000) - //{ - // PendingCommandCounter = PSRCounter + 1; - //} - else if(PendingCommandCounter <= 0) - { - int32 next_time = 0; - - if(PendingCommandPhase == -1) - { - if(ArgsRP != ArgsWP) - { - ArgsReceiveLatch = ArgsBuf[ArgsRP & 0x0F]; - ArgsRP = (ArgsRP + 1) & 0x1F; - PendingCommandPhase += 1; - next_time = 1815; - } - else - { - PendingCommandPhase += 2; - next_time = 8500; - } - } - else if(PendingCommandPhase == 0) // Command phase 0 - { - if(ArgsReceiveIn < 32) - ArgsReceiveBuf[ArgsReceiveIn++] = ArgsReceiveLatch; - - if(ArgsRP != ArgsWP) - { - ArgsReceiveLatch = ArgsBuf[ArgsRP & 0x0F]; - ArgsRP = (ArgsRP + 1) & 0x1F; - next_time = 1815; - } - else - { - PendingCommandPhase++; - next_time = 8500; - } - } - else if(PendingCommandPhase >= 2) // Command phase 2+ - { - BeginResults(); - - const CDC_CTEntry *command = &Commands[PendingCommand]; - - next_time = (this->*(command->func2))(); - } - else // Command phase 1 - { - if(PendingCommand >= 0x20 || !Commands[PendingCommand].func) - { - BeginResults(); - - PSX_WARNING("[CDC] Unknown command: 0x%02x", PendingCommand); - - WriteResult(MakeStatus(true)); - WriteResult(ERRCODE_BAD_COMMAND); - WriteIRQ(CDCIRQ_DISC_ERROR); - } - else if(ArgsReceiveIn < Commands[PendingCommand].args_min || ArgsReceiveIn > Commands[PendingCommand].args_max) - { - BeginResults(); - - PSX_DBG(PSX_DBG_WARNING, "[CDC] Bad number(%d) of args(first check) for command 0x%02x", ArgsReceiveIn, PendingCommand); - for(unsigned int i = 0; i < ArgsReceiveIn; i++) - PSX_DBG(PSX_DBG_WARNING, " 0x%02x", ArgsReceiveBuf[i]); - PSX_DBG(PSX_DBG_WARNING, "\n"); - - WriteResult(MakeStatus(true)); - WriteResult(ERRCODE_BAD_NUMARGS); - WriteIRQ(CDCIRQ_DISC_ERROR); - } - else - { - BeginResults(); - - const CDC_CTEntry *command = &Commands[PendingCommand]; - - PSX_DBG(PSX_DBG_SPARSE, "[CDC] Command: %s --- ", command->name); - for(unsigned int i = 0; i < ArgsReceiveIn; i++) - PSX_DBG(PSX_DBG_SPARSE, " 0x%02x", ArgsReceiveBuf[i]); - PSX_DBG(PSX_DBG_SPARSE, "\n"); - - next_time = (this->*(command->func))(ArgsReceiveIn, ArgsReceiveBuf); - PendingCommandPhase = 2; - } - ArgsReceiveIn = 0; - } // end command phase 1 - - if(!next_time) - PendingCommandCounter = 0; - else - PendingCommandCounter += next_time; - } - } - - SPUCounter = SPU->UpdateFromCDC(chunk_clocks); - - clocks -= chunk_clocks; - } // end while(clocks > 0) - - lastts = timestamp; - - return(timestamp + CalcNextEvent()); -} - -void PS_CDC::Write(const pscpu_timestamp_t timestamp, uint32 A, uint8 V) -{ - A &= 0x3; - - //printf("Write: %08x %02x\n", A, V); - - if(A == 0x00) - { - RegSelector = V & 0x3; - } - else - { - const unsigned reg_index = ((RegSelector & 0x3) * 3) + (A - 1); - - Update(timestamp); - //PSX_WARNING("[CDC] Write to register 0x%02x: 0x%02x @ %d --- 0x%02x 0x%02x\n", reg_index, V, timestamp, DMABuffer.CanRead(), IRQBuffer); - - switch(reg_index) - { - default: - PSX_WARNING("[CDC] Unknown write to register 0x%02x: 0x%02x\n", reg_index, V); - break; - - case 0x00: - if(PendingCommandCounter > 0) - { - PSX_WARNING("[CDC] WARNING: Interrupting command 0x%02x, phase=%d, timeleft=%d with command=0x%02x", PendingCommand, PendingCommandPhase, - PendingCommandCounter, V); - } - - if(IRQBuffer & 0xF) - { - PSX_WARNING("[CDC] Attempting to start command(0x%02x) while IRQBuffer(0x%02x) is not clear.", V, IRQBuffer); - } - - if(ResultsIn > 0) - { - PSX_WARNING("[CDC] Attempting to start command(0x%02x) while command results(count=%d) still in buffer.", V, ResultsIn); - } - - PendingCommandCounter = 10500 + PSX_GetRandU32(0, 3000) + 1815; - PendingCommand = V; - PendingCommandPhase = -1; - ArgsReceiveIn = 0; - break; - - case 0x01: - ArgsBuf[ArgsWP & 0xF] = V; - ArgsWP = (ArgsWP + 1) & 0x1F; - - if(!((ArgsWP - ArgsRP) & 0x0F)) - { - PSX_WARNING("[CDC] Argument buffer overflow"); - } - break; - - case 0x02: - if(V & 0x80) - { - if(!DMABuffer.CanRead()) - { - if(!SB_In) - { - PSX_WARNING("[CDC] Data read begin when no data to read!"); - - DMABuffer.Write(SB, 2340); - - while(DMABuffer.CanWrite()) - DMABuffer.WriteByte(0x00); - } - else - { - DMABuffer.Write(SB, SB_In); - SB_In = 0; - } - } - else - { - //PSX_WARNING("[CDC] Attempt to start data transfer via 0x80->1803 when %d bytes still in buffer", DMABuffer.CanRead()); - } - } - else if(V & 0x40) // Something CD-DA related(along with & 0x20 ???)? - { - for(unsigned i = 0; i < 4 && DMABuffer.CanRead(); i++) - DMABuffer.ReadByte(); - } - else - { - DMABuffer.Flush(); - } - - if(V & 0x20) - { - PSX_WARNING("[CDC] Mystery IRQ trigger bit set."); - IRQBuffer |= 0x10; - RecalcIRQ(); - } - break; - - case 0x04: - IRQOutTestMask = V; - RecalcIRQ(); - break; - - case 0x05: - if((IRQBuffer &~ V) != IRQBuffer && ResultsIn) - { - // To debug icky race-condition related problems in "Psychic Detective", and to see if any games suffer from the same potential issue - // (to know what to test when we emulate CPU more accurately in regards to pipeline stalls and timing, which could throw off our kludge - // for this issue) - PSX_WARNING("[CDC] Acknowledged IRQ(wrote 0x%02x, before_IRQBuffer=0x%02x) while %u bytes in results buffer.", V, IRQBuffer, ResultsIn); - } - - IRQBuffer &= ~V; - RecalcIRQ(); - - if(V & 0x80) // Forced CD hardware reset of some kind(interface, controller, and drive?) Seems to take a while(relatively speaking) to complete. - { - PSX_WARNING("[CDC] Soft Reset"); - SoftReset(); - } - - if(V & 0x40) // Does it clear more than arguments buffer? Doesn't appear to clear results buffer. - { - ArgsWP = ArgsRP = 0; - } - break; - - case 0x07: - Pending_DecodeVolume[0][0] = V; - break; - - case 0x08: - Pending_DecodeVolume[0][1] = V; - break; - - case 0x09: - Pending_DecodeVolume[1][1] = V; - break; - - case 0x0A: - Pending_DecodeVolume[1][0] = V; - break; - - case 0x0B: - if(V & 0x20) - { - memcpy(DecodeVolume, Pending_DecodeVolume, sizeof(DecodeVolume)); - - for(int i = 0; i < 2; i++) - { - for(int o = 0; o < 2; o++) - { - //fprintf(stderr, "Input Channel %d, Output Channel %d -- Volume=%d\n", i, o, DecodeVolume[i][o]); - } - } - } - break; - } - PSX_SetEventNT(PSX_EVENT_CDC, timestamp + CalcNextEvent()); - } -} - -uint8 PS_CDC::Read(const pscpu_timestamp_t timestamp, uint32 A) -{ - uint8 ret = 0; - - A &= 0x03; - - //printf("Read %08x\n", A); - - if(A == 0x00) - { - ret = RegSelector & 0x3; - - if(ArgsWP == ArgsRP) - ret |= 0x08; // Args FIFO empty. - - if(!((ArgsWP - ArgsRP) & 0x10)) - ret |= 0x10; // Args FIFO has room. - - if(ResultsIn) - ret |= 0x20; - - if(DMABuffer.CanRead()) - ret |= 0x40; - - if(PendingCommandCounter > 0 && PendingCommandPhase <= 1) - ret |= 0x80; - } - else - { - switch(A & 0x3) - { - case 0x01: - ret = ReadResult(); - break; - - case 0x02: - //PSX_WARNING("[CDC] DMA Buffer manual read"); - if(DMABuffer.CanRead()) - ret = DMABuffer.ReadByte(); - else - { - PSX_WARNING("[CDC] CD data transfer port read, but no data present!"); - } - break; - - case 0x03: - if(RegSelector & 0x1) - { - ret = 0xE0 | IRQBuffer; - } - else - { - ret = 0xFF; - } - break; - } - } - - return(ret); -} - - -bool PS_CDC::DMACanRead(void) -{ - return(DMABuffer.CanRead()); -} - -uint32 PS_CDC::DMARead(void) -{ - uint32 data = 0; - - for(int i = 0; i < 4; i++) - { - if(DMABuffer.CanRead()) - data |= DMABuffer.ReadByte() << (i * 8); - else - { - PSX_WARNING("[CDC] DMA read buffer underflow!"); - } - } - - return(data); -} - -bool PS_CDC::CommandCheckDiscPresent(void) -{ - if(!Cur_disc || DiscStartupDelay > 0) - { - WriteResult(MakeStatus(true)); - WriteResult(ERRCODE_NOT_READY); - - WriteIRQ(CDCIRQ_DISC_ERROR); - - return(false); - } - - return(true); -} - -int32 PS_CDC::Command_Nop(const int arg_count, const uint8 *args) -{ - WriteResult(MakeStatus()); - - //PSX-SPX: this command ACKs the TrayOpenBit if the shell is no longer open - //(mednafen does this differently) - if(!TrayOpen) - Status_TrayOpenBit = false; - - WriteIRQ(CDCIRQ_ACKNOWLEDGE); - - return(0); -} - -int32 PS_CDC::Command_Setloc(const int arg_count, const uint8 *args) -{ - uint8 m, s, f; - - if((args[0] & 0x0F) > 0x09 || args[0] > 0x99 || - (args[1] & 0x0F) > 0x09 || args[1] > 0x59 || - (args[2] & 0x0F) > 0x09 || args[2] > 0x74) - { - WriteResult(MakeStatus(true)); - WriteResult(ERRCODE_BAD_ARGVAL); - WriteIRQ(CDCIRQ_DISC_ERROR); - return(0); - } - - m = BCD_to_U8(args[0]); - s = BCD_to_U8(args[1]); - f = BCD_to_U8(args[2]); - - CommandLoc = f + 75 * s + 75 * 60 * m - 150; - CommandLoc_Dirty = true; - - WriteResult(MakeStatus()); - WriteIRQ(CDCIRQ_ACKNOWLEDGE); - - return(0); -} - -int32 PS_CDC::CalcSeekTime(int32 initial, int32 target, bool motor_on, bool paused) -{ - int32 ret = 0; - - if(!motor_on) - { - initial = 0; - ret += 33868800; - } - - const int32 abs_diff = abs(initial - target); - - ret += std::max((int64)abs_diff * 33868800 * 1000 / (72 * 60 * 75) / 1000, 20000); - - if(abs_diff >= 2250) - ret += (int64)33868800 * 300 / 1000; - else if(paused) - { - // The delay to restart from a Pause state is...very....WEIRD. The time it takes is related to the amount of time that has passed since the pause, and - // where on the disc the laser head is, with generally more time passed = longer to resume, except that there's a window of time where it takes a - // ridiculous amount of time when not much time has passed. - // - // What we have here will be EXTREMELY simplified. - - // - // - - //if(time_passed >= 67737) - //{ - //} - //else - { - // Take twice as long for 1x mode. - ret += 1237952 * ((Mode & MODE_SPEED) ? 1 : 2); - } - } - else if(abs_diff >= 3 && abs_diff < 12) - ret += 33868800 / (75 * ((Mode & MODE_SPEED) ? 2 : 1)) * 4; - - //else if(target < initial) - // ret += 1000000; - - ret += PSX_GetRandU32(0, 25000); - - PSX_DBG(PSX_DBG_SPARSE, "[CDC] CalcSeekTime() %d->%d = %d\n", initial, target, ret); - - return(ret); -} - -#if 0 -void PS_CDC::BeginSeek(uint32 target, int after_seek) -{ - SeekTarget = target; - StatusAfterSeek = after_seek; - - PSRCounter = CalcSeekTime(CurSector, SeekTarget, DriveStatus != DS_STOPPED, DriveStatus == DS_PAUSED); -} -#endif - -// Remove this function when we have better seek emulation; it's here because the Rockman complete works games(at least 2 and 4) apparently have finicky fubared CD -// access code. -void PS_CDC::PreSeekHack(int32 target) -{ - uint8 pwbuf[96]; - int max_try = 32; - - CurSector = target; // If removing/changing this, take into account how it will affect ReadN/ReadS/Play/etc command calls that interrupt a seek. - SeekRetryCounter = 128; - - // If removing this SubQ reading bit, think about how it will interact with a Read command of data(or audio :b) sectors when Mode bit0 is 1. - do - { - Cur_disc->ReadLBA_PW(pwbuf, target++, true); - } while(!DecodeSubQ(pwbuf) && --max_try > 0); -} - -/* - Play command with a track argument that's not a valid BCD quantity causes interesting half-buggy behavior on an actual PS1(unlike some of the other commands, - an error doesn't seem to be generated for a bad BCD argument). -*/ -int32 PS_CDC::Command_Play(const int arg_count, const uint8 *args) -{ - if(!CommandCheckDiscPresent()) - return(0); - - ClearAIP(); - - WriteResult(MakeStatus()); - WriteIRQ(CDCIRQ_ACKNOWLEDGE); - - Forward = Backward = false; - - if(arg_count && args[0]) - { - int track = BCD_to_U8(args[0]); - - if(track < toc.first_track) - { - PSX_WARNING("[CDC] Attempt to play track before first track."); - track = toc.first_track; - } - else if(track > toc.last_track) - { - PSX_WARNING("[CDC] Attempt to play track after last track."); - track = toc.last_track; - } - - ClearAudioBuffers(); - SectorPipe_Pos = SectorPipe_In = 0; - SectorsRead = 0; - - PlayTrackMatch = track; - - PSX_WARNING("[CDC] Play track: %d", track); - - SeekTarget = toc.tracks[track].lba; - PSRCounter = CalcSeekTime(CurSector, SeekTarget, DriveStatus != DS_STOPPED, DriveStatus == DS_PAUSED); - HeaderBufValid = false; - PreSeekHack(SeekTarget); - - SeekFinished = false; - DriveStatus = DS_SEEKING; - StatusAfterSeek = DS_PLAYING; - } - else if(CommandLoc_Dirty || DriveStatus != DS_PLAYING) - { - ClearAudioBuffers(); - SectorPipe_Pos = SectorPipe_In = 0; - SectorsRead = 0; - - if(CommandLoc_Dirty) - SeekTarget = CommandLoc; - else - SeekTarget = CurSector; - - PlayTrackMatch = -1; - - PSRCounter = CalcSeekTime(CurSector, SeekTarget, DriveStatus != DS_STOPPED, DriveStatus == DS_PAUSED); - HeaderBufValid = false; - PreSeekHack(SeekTarget); - - SeekFinished = false; - DriveStatus = DS_SEEKING; - StatusAfterSeek = DS_PLAYING; - } - - CommandLoc_Dirty = false; - return(0); -} - -int32 PS_CDC::Command_Forward(const int arg_count, const uint8 *args) -{ - if(!CommandCheckDiscPresent()) - return(0); - - WriteResult(MakeStatus()); - WriteIRQ(CDCIRQ_ACKNOWLEDGE); - - Backward = false; - Forward = true; - - return(0); -} - -int32 PS_CDC::Command_Backward(const int arg_count, const uint8 *args) -{ - if(!CommandCheckDiscPresent()) - return(0); - - WriteResult(MakeStatus()); - WriteIRQ(CDCIRQ_ACKNOWLEDGE); - - Backward = true; - Forward = false; - - return(0); -} - - -void PS_CDC::ReadBase(void) -{ - if(!CommandCheckDiscPresent()) - return; - - if(!IsPSXDisc) - { - WriteResult(MakeStatus(true)); - WriteResult(ERRCODE_BAD_COMMAND); - - WriteIRQ(CDCIRQ_DISC_ERROR); - return; - } - - WriteResult(MakeStatus()); - WriteIRQ(CDCIRQ_ACKNOWLEDGE); - - if((DriveStatus == DS_SEEKING_LOGICAL || DriveStatus == DS_SEEKING_LOGICAL2) && SeekTarget == CommandLoc && StatusAfterSeek == DS_READING) - { - CommandLoc_Dirty = false; - return; - } - - if(CommandLoc_Dirty || DriveStatus != DS_READING) - { - // Don't flush the DMABuffer here; see CTR course selection screen. - ClearAIP(); - ClearAudioBuffers(); - SB_In = 0; - SectorPipe_Pos = SectorPipe_In = 0; - SectorsRead = 0; - - // TODO: separate motor start from seek phase? - - if(CommandLoc_Dirty) - SeekTarget = CommandLoc; - else if(DriveStatus != DS_PAUSED && DriveStatus != DS_STANDBY) - SeekTarget = CurSector; - - PSRCounter = 33868800 / (75 * ((Mode & MODE_SPEED) ? 2 : 1)) + CalcSeekTime(CurSector, SeekTarget, DriveStatus != DS_STOPPED, DriveStatus == DS_PAUSED); - HeaderBufValid = false; - PreSeekHack(SeekTarget); - - SeekFinished = false; - DriveStatus = DS_SEEKING_LOGICAL; - StatusAfterSeek = DS_READING; - } - - CommandLoc_Dirty = false; -} - -int32 PS_CDC::Command_ReadN(const int arg_count, const uint8 *args) -{ - ReadBase(); - return 0; -} - -int32 PS_CDC::Command_ReadS(const int arg_count, const uint8 *args) -{ - ReadBase(); - return 0; -} - -int32 PS_CDC::Command_Stop(const int arg_count, const uint8 *args) -{ - if(!CommandCheckDiscPresent()) - return(0); - - WriteResult(MakeStatus()); - WriteIRQ(CDCIRQ_ACKNOWLEDGE); - - if(DriveStatus == DS_STOPPED) - { - return(5000); - } - else - { - ClearAudioBuffers(); - ClearAIP(); - SectorPipe_Pos = SectorPipe_In = 0; - SectorsRead = 0; - - DriveStatus = DS_STOPPED; - HeaderBufValid = false; - - return(33868); // FIXME, should be much higher. - } -} - -int32 PS_CDC::Command_Stop_Part2(void) -{ - PSRCounter = 0; - - WriteResult(MakeStatus()); - WriteIRQ(CDCIRQ_COMPLETE); - - return(0); -} - -int32 PS_CDC::Command_Standby(const int arg_count, const uint8 *args) -{ - if(!CommandCheckDiscPresent()) - return(0); - - if(DriveStatus != DS_STOPPED) - { - WriteResult(MakeStatus(true)); - WriteResult(0x20); - WriteIRQ(CDCIRQ_DISC_ERROR); - return(0); - } - - WriteResult(MakeStatus()); - WriteIRQ(CDCIRQ_ACKNOWLEDGE); - - ClearAudioBuffers(); - ClearAIP(); - SectorPipe_Pos = SectorPipe_In = 0; - SectorsRead = 0; - - SeekTarget = CurSector; // FIXME? CurSector = 0? - HoldLogicalPos = false; - DriveStatus = DS_STANDBY; - - return((int64)33868800 * 100 / 1000); // No idea, FIXME. -} - -int32 PS_CDC::Command_Standby_Part2(void) -{ - PSRCounter = 0; - - WriteResult(MakeStatus()); - WriteIRQ(CDCIRQ_COMPLETE); - - return(0); -} - -int32 PS_CDC::Command_Pause(const int arg_count, const uint8 *args) -{ - if(!CommandCheckDiscPresent()) - return 0; - - WriteResult(MakeStatus()); - WriteIRQ(CDCIRQ_ACKNOWLEDGE); - - if(DriveStatus == DS_PAUSED || DriveStatus == DS_STOPPED) - { - return 5000; - } - else - { - CurSector -= std::min(4, SectorsRead); // See: Bedlam, Rise 2 - SectorsRead = 0; - - // "Viewpoint" flips out and crashes if reading isn't stopped (almost?) immediately. - //ClearAudioBuffers(); - SectorPipe_Pos = SectorPipe_In = 0; - ClearAIP(); - SeekTarget = CurSector; - DriveStatus = DS_PAUSED; - PSRCounter = 33868800 / (75 * ((Mode & MODE_SPEED) ? 2 : 1)); - - // An approximation. - return (1124584 + ((int64)CurSector * 42596 / (75 * 60))) * ((Mode & MODE_SPEED) ? 1 : 2) + PSX_GetRandU32(0, 100000); - } -} - -int32 PS_CDC::Command_Pause_Part2(void) -{ - WriteResult(MakeStatus()); - WriteIRQ(CDCIRQ_COMPLETE); - - return 0; -} - -int32 PS_CDC::Command_Reset(const int arg_count, const uint8 *args) -{ - WriteResult(MakeStatus()); - WriteIRQ(CDCIRQ_ACKNOWLEDGE); - - Muted = false; // Does it get reset here? - Mode = 0x20; // Confirmed(and see "This Is Football 2"). - CommandLoc = 0; - // - // - // -// printf("DriveStatus: %d %d %d\n", DriveStatus, StatusAfterSeek, SeekTarget); - if(Cur_disc && DiscStartupDelay <= 0) - { - if((DriveStatus == DS_SEEKING_LOGICAL || DriveStatus == DS_SEEKING) && StatusAfterSeek == DS_PAUSED && SeekTarget == 0) - { - //puts("HRMPH"); - return 256; - } - else - { - ClearAudioBuffers(); - - SB_In = 0; - SectorPipe_Pos = SectorPipe_In = 0; - SectorsRead = 0; - - SeekTarget = 0; - PSRCounter = std::max(PSX_GetRandU32(0, 3250000), CalcSeekTime(CurSector, SeekTarget, DriveStatus != DS_STOPPED, DriveStatus == DS_PAUSED)); - PreSeekHack(SeekTarget); - SeekFinished = false; - DriveStatus = HoldLogicalPos ? DS_SEEKING_LOGICAL : DS_SEEKING; - StatusAfterSeek = DS_PAUSED; - ClearAIP(); - - return 4100000; - } - } - else - { - SeekFinished = true; - return 70000; - } -} - -int32 PS_CDC::Command_Mute(const int arg_count, const uint8 *args) -{ - Muted = true; - - WriteResult(MakeStatus()); - WriteIRQ(CDCIRQ_ACKNOWLEDGE); - - return(0); -} - -int32 PS_CDC::Command_Demute(const int arg_count, const uint8 *args) -{ - Muted = false; - - WriteResult(MakeStatus()); - WriteIRQ(CDCIRQ_ACKNOWLEDGE); - - return(0); -} - -int32 PS_CDC::Command_Setfilter(const int arg_count, const uint8 *args) -{ - FilterFile = args[0]; - FilterChan = args[1]; - - //PSX_WARNING("[CDC] Setfilter: %02x %02x", args[0], args[1]); - - WriteResult(MakeStatus()); - WriteIRQ(CDCIRQ_ACKNOWLEDGE); - - return(0); -} - -int32 PS_CDC::Command_Setmode(const int arg_count, const uint8 *args) -{ - Mode = args[0]; - - WriteResult(MakeStatus()); - WriteIRQ(CDCIRQ_ACKNOWLEDGE); - - return(0); -} - -int32 PS_CDC::Command_Getparam(const int arg_count, const uint8 *args) -{ - WriteResult(MakeStatus()); - WriteResult(Mode); - WriteResult(0x00); - WriteResult(FilterFile); - WriteResult(FilterChan); - - WriteIRQ(CDCIRQ_ACKNOWLEDGE); - - - return(0); -} - -int32 PS_CDC::Command_GetlocL(const int arg_count, const uint8 *args) -{ - if(!CommandCheckDiscPresent()) - return(0); - - if(!HeaderBufValid) - { - WriteResult(MakeStatus(true)); - WriteResult(0x80); - WriteIRQ(CDCIRQ_DISC_ERROR); - return(0); - } - - for(unsigned i = 0; i < 8; i++) - { - //printf("%d %d: %02x\n", DriveStatus, i, HeaderBuf[i]); - WriteResult(HeaderBuf[i]); - } - - WriteIRQ(CDCIRQ_ACKNOWLEDGE); - - return(0); -} - -int32 PS_CDC::Command_GetlocP(const int arg_count, const uint8 *args) -{ - if(!CommandCheckDiscPresent()) - return(0); - - //printf("%2x:%2x %2x:%2x:%2x %2x:%2x:%2x\n", SubQBuf_Safe[0x1], SubQBuf_Safe[0x2], SubQBuf_Safe[0x3], SubQBuf_Safe[0x4], SubQBuf_Safe[0x5], SubQBuf_Safe[0x7], SubQBuf_Safe[0x8], SubQBuf_Safe[0x9]); - - WriteResult(SubQBuf_Safe[0x1]); // Track - WriteResult(SubQBuf_Safe[0x2]); // Index - WriteResult(SubQBuf_Safe[0x3]); // R M - WriteResult(SubQBuf_Safe[0x4]); // R S - WriteResult(SubQBuf_Safe[0x5]); // R F - WriteResult(SubQBuf_Safe[0x7]); // A M - WriteResult(SubQBuf_Safe[0x8]); // A S - WriteResult(SubQBuf_Safe[0x9]); // A F - - WriteIRQ(CDCIRQ_ACKNOWLEDGE); - - return(0); -} - -int32 PS_CDC::Command_ReadT(const int arg_count, const uint8 *args) -{ - WriteResult(MakeStatus()); - WriteIRQ(CDCIRQ_ACKNOWLEDGE); - - return(44100 * 768 / 1000); -} - -int32 PS_CDC::Command_ReadT_Part2(void) -{ - WriteResult(MakeStatus()); - WriteIRQ(CDCIRQ_COMPLETE); - - return(0); -} - -int32 PS_CDC::Command_GetTN(const int arg_count, const uint8 *args) -{ - if(!CommandCheckDiscPresent()) - return(0); - - WriteResult(MakeStatus()); - WriteResult(U8_to_BCD(toc.first_track)); - WriteResult(U8_to_BCD(toc.last_track)); - - WriteIRQ(CDCIRQ_ACKNOWLEDGE); - - return(0); -} - -int32 PS_CDC::Command_GetTD(const int arg_count, const uint8 *args) -{ - if(!CommandCheckDiscPresent()) - return(0); - - int track; - uint8 m, s, f; - - if(!args[0]) - track = 100; - else - { - track = BCD_to_U8(args[0]); - - if(!BCD_is_valid(args[0]) || track < toc.first_track || track > toc.last_track) // Error - { - WriteResult(MakeStatus(true)); - WriteResult(ERRCODE_BAD_ARGVAL); - WriteIRQ(CDCIRQ_DISC_ERROR); - return(0); - } - } - - LBA_to_AMSF(toc.tracks[track].lba, &m, &s, &f); - - WriteResult(MakeStatus()); - WriteResult(U8_to_BCD(m)); - WriteResult(U8_to_BCD(s)); - //WriteResult(U8_to_BCD(f)); - - WriteIRQ(CDCIRQ_ACKNOWLEDGE); - - return(0); -} - -int32 PS_CDC::Command_SeekL(const int arg_count, const uint8 *args) -{ - if(!CommandCheckDiscPresent()) - return(0); - - WriteResult(MakeStatus()); - WriteIRQ(CDCIRQ_ACKNOWLEDGE); - - SeekTarget = CommandLoc; - -#if 1 - SectorsRead = 0; - SectorPipe_Pos = SectorPipe_In = 0; -#endif - PSRCounter = CalcSeekTime(CurSector, SeekTarget, DriveStatus != DS_STOPPED, DriveStatus == DS_PAUSED); - //HeaderBufValid = false; - PreSeekHack(SeekTarget); - SeekFinished = false; - DriveStatus = DS_SEEKING_LOGICAL; - StatusAfterSeek = DS_STANDBY; - ClearAIP(); - - return(PSRCounter); -} - -int32 PS_CDC::Command_SeekP(const int arg_count, const uint8 *args) -{ - if(!CommandCheckDiscPresent()) - return(0); - - WriteResult(MakeStatus()); - WriteIRQ(CDCIRQ_ACKNOWLEDGE); - - SeekTarget = CommandLoc; - - PSRCounter = CalcSeekTime(CurSector, SeekTarget, DriveStatus != DS_STOPPED, DriveStatus == DS_PAUSED); - HeaderBufValid = false; - PreSeekHack(SeekTarget); - SeekFinished = false; - DriveStatus = DS_SEEKING; - StatusAfterSeek = DS_STANDBY; - ClearAIP(); - - return(PSRCounter); -} - -// Used with Command_Reset(), too. -int32 PS_CDC::Command_Seek_PartN(void) -{ - if(DriveStatus != DS_SEEKING && DriveStatus != DS_SEEKING_LOGICAL && DriveStatus != DS_SEEKING_LOGICAL2) - { - if(SeekFinished) - { - BeginResults(); - - if(SeekFinished < 0) - { - WriteResult(MakeStatus() | 0x04); - WriteResult(0x04); - WriteIRQ(CDCIRQ_DISC_ERROR); - } - else - { - WriteResult(MakeStatus()); - WriteIRQ(CDCIRQ_COMPLETE); - } - } - else - { - PSX_WARNING("[CDC] DriveStatus no longer seeking, but SeekFinished is still 0."); - } - - return 0; - } - else - { - return std::max(PSRCounter, 256); - } -} - -int32 PS_CDC::Command_Test(const int arg_count, const uint8 *args) -{ - //PSX_WARNING("[CDC] Test command sub-operation: 0x%02x", args[0]); - - switch(args[0]) - { - default: - PSX_WARNING("[CDC] Unknown Test command sub-operation: 0x%02x", args[0]); - WriteResult(MakeStatus(true)); - WriteResult(0x10); - WriteIRQ(CDCIRQ_DISC_ERROR); - break; - - case 0x00: - case 0x01: - case 0x02: - case 0x03: - case 0x10: - case 0x11: - case 0x12: - case 0x13: - case 0x14: - case 0x15: - case 0x16: - case 0x17: - case 0x18: - case 0x19: - case 0x1A: - PSX_WARNING("[CDC] Unknown Test command sub-operation: 0x%02x", args[0]); - WriteResult(MakeStatus()); - WriteIRQ(CDCIRQ_ACKNOWLEDGE); - break; - -#if 0 - case 0x50: // *Need to retest this test command, it takes additional arguments??? Or in any case, it generates a different error code(0x20) than most other Test - // sub-commands that generate an error code(0x10). - break; - - // Same with 0x60, 0x71-0x76 - -#endif - - case 0x51: // *Need to retest this test command - PSX_WARNING("[CDC] Unknown Test command sub-operation: 0x%02x", args[0]); - WriteResult(0x01); - WriteResult(0x00); - WriteResult(0x00); - break; - - case 0x75: // *Need to retest this test command - PSX_WARNING("[CDC] Unknown Test command sub-operation: 0x%02x", args[0]); - WriteResult(0x00); - WriteResult(0xC0); - WriteResult(0x00); - WriteResult(0x00); - break; - - // - // SCEx counters not reset by command 0x0A. - // - - case 0x04: // Reset SCEx counters - WriteResult(MakeStatus()); - WriteIRQ(CDCIRQ_ACKNOWLEDGE); - break; - - case 0x05: // Read SCEx counters - WriteResult(0x00); // Number of TOC/leadin reads? (apparently increases by 1 or 2 per ReadTOC, even on non-PSX music CD) - WriteResult(0x00); // Number of SCEx strings received? (Stays at zero on music CD) - WriteIRQ(CDCIRQ_ACKNOWLEDGE); - break; - - case 0x20: - { - WriteResult(0x97); - WriteResult(0x01); - WriteResult(0x10); - WriteResult(0xC2); - - WriteIRQ(CDCIRQ_ACKNOWLEDGE); - } - break; - - case 0x21: // *Need to retest this test command. - { - WriteResult(0x01); - WriteIRQ(CDCIRQ_ACKNOWLEDGE); - } - break; - - case 0x22: - { - static const uint8 td[7] = { 0x66, 0x6f, 0x72, 0x20, 0x55, 0x2f, 0x43 }; - - for(unsigned i = 0; i < 7; i++) - WriteResult(td[i]); - - WriteIRQ(CDCIRQ_ACKNOWLEDGE); - } - break; - - case 0x23: - case 0x24: - { - static const uint8 td[8] = { 0x43, 0x58, 0x44, 0x32, 0x35, 0x34, 0x35, 0x51 }; - - for(unsigned i = 0; i < 8; i++) - WriteResult(td[i]); - - WriteIRQ(CDCIRQ_ACKNOWLEDGE); - } - break; - - case 0x25: - { - static const uint8 td[8] = { 0x43, 0x58, 0x44, 0x31, 0x38, 0x31, 0x35, 0x51 }; - - for(unsigned i = 0; i < 8; i++) - WriteResult(td[i]); - - WriteIRQ(CDCIRQ_ACKNOWLEDGE); - } - break; - } - return(0); -} - -int32 PS_CDC::Command_ID(const int arg_count, const uint8 *args) -{ - if(!CommandCheckDiscPresent()) - return(0); - - WriteResult(MakeStatus()); - WriteIRQ(CDCIRQ_ACKNOWLEDGE); - - return(33868); -} - -int32 PS_CDC::Command_ID_Part2(void) -{ - if(IsPSXDisc) - { - WriteResult(MakeStatus()); - WriteResult(0x00); - WriteResult(0x20); - WriteResult(0x00); - } - else - { - WriteResult(MakeStatus() | 0x08); - WriteResult(0x90); - WriteResult(toc.disc_type); - WriteResult(0x00); - } - - if(IsPSXDisc) - { - WriteResult(DiscID[0]); - WriteResult(DiscID[1]); - WriteResult(DiscID[2]); - WriteResult(DiscID[3]); - } - else - { - WriteResult(0xff); - WriteResult(0); - WriteResult(0); - WriteResult(0); - } - - if(IsPSXDisc) - WriteIRQ(CDCIRQ_COMPLETE); - else - WriteIRQ(CDCIRQ_DISC_ERROR); - - return(0); -} - -int32 PS_CDC::Command_Init(const int arg_count, const uint8 *args) -{ - return(0); -} - -int32 PS_CDC::Command_ReadTOC(const int arg_count, const uint8 *args) -{ - int32 ret_time; - - HeaderBufValid = false; - WriteResult(MakeStatus()); - WriteIRQ(CDCIRQ_ACKNOWLEDGE); - - // ReadTOC doesn't error out if the tray is open, and it completes rather quickly in that case. - // - if(!CommandCheckDiscPresent()) - return(26000); - - - - // A gross approximation. - // The penalty for the drive being stopped seems to be rather high(higher than what CalcSeekTime() currently introduces), although - // that should be investigated further. - // - // ...and not to mention the time taken varies from disc to disc even! - ret_time = 30000000 + CalcSeekTime(CurSector, 0, DriveStatus != DS_STOPPED, DriveStatus == DS_PAUSED); - - SeekTarget = 0; - HoldLogicalPos = false; - DriveStatus = DS_PAUSED; // Ends up in a pause state when the command is finished. Maybe we should add DS_READTOC or something... - ClearAIP(); - - return ret_time; -} - -int32 PS_CDC::Command_ReadTOC_Part2(void) -{ - //if(!CommandCheckDiscPresent()) - // DriveStatus = DS_PAUSED; - - WriteResult(MakeStatus()); - WriteIRQ(CDCIRQ_COMPLETE); - - return(0); -} - -int32 PS_CDC::Command_0x1d(const int arg_count, const uint8 *args) -{ - WriteResult(MakeStatus()); - WriteIRQ(CDCIRQ_ACKNOWLEDGE); - return(0); -} - -const PS_CDC::CDC_CTEntry PS_CDC::Commands[0x20] = -{ - { /* 0x00, */ 0, 0, NULL, NULL, NULL }, - { /* 0x01, */ 0, 0, "Nop", &PS_CDC::Command_Nop, NULL }, - { /* 0x02, */ 3, 3, "Setloc", &PS_CDC::Command_Setloc, NULL }, - { /* 0x03, */ 0, 1, "Play", &PS_CDC::Command_Play, NULL }, - { /* 0x04, */ 0, 0, "Forward", &PS_CDC::Command_Forward, NULL }, - { /* 0x05, */ 0, 0, "Backward", &PS_CDC::Command_Backward, NULL }, - { /* 0x06, */ 0, 0, "ReadN", &PS_CDC::Command_ReadN, NULL }, - { /* 0x07, */ 0, 0, "Standby", &PS_CDC::Command_Standby, &PS_CDC::Command_Standby_Part2 }, - { /* 0x08, */ 0, 0, "Stop", &PS_CDC::Command_Stop, &PS_CDC::Command_Stop_Part2 }, - { /* 0x09, */ 0, 0, "Pause", &PS_CDC::Command_Pause, &PS_CDC::Command_Pause_Part2 }, - { /* 0x0A, */ 0, 0, "Reset", &PS_CDC::Command_Reset, &PS_CDC::Command_Seek_PartN }, - { /* 0x0B, */ 0, 0, "Mute", &PS_CDC::Command_Mute, NULL }, - { /* 0x0C, */ 0, 0, "Demute", &PS_CDC::Command_Demute, NULL }, - { /* 0x0D, */ 2, 2, "Setfilter", &PS_CDC::Command_Setfilter, NULL }, - { /* 0x0E, */ 1, 1, "Setmode", &PS_CDC::Command_Setmode, NULL }, - { /* 0x0F, */ 0, 0, "Getparam", &PS_CDC::Command_Getparam, NULL }, - { /* 0x10, */ 0, 0, "GetlocL", &PS_CDC::Command_GetlocL, NULL }, - { /* 0x11, */ 0, 0, "GetlocP", &PS_CDC::Command_GetlocP, NULL }, - { /* 0x12, */ 1, 1, "ReadT", &PS_CDC::Command_ReadT, &PS_CDC::Command_ReadT_Part2 }, - { /* 0x13, */ 0, 0, "GetTN", &PS_CDC::Command_GetTN, NULL }, - { /* 0x14, */ 1, 1, "GetTD", &PS_CDC::Command_GetTD, NULL }, - { /* 0x15, */ 0, 0, "SeekL", &PS_CDC::Command_SeekL, &PS_CDC::Command_Seek_PartN }, - { /* 0x16, */ 0, 0, "SeekP", &PS_CDC::Command_SeekP, &PS_CDC::Command_Seek_PartN }, - - { /* 0x17, */ 0, 0, NULL, NULL, NULL }, - { /* 0x18, */ 0, 0, NULL, NULL, NULL }, - - { /* 0x19, */ 1, 1/* ??? */, "Test", &PS_CDC::Command_Test, NULL }, - { /* 0x1A, */ 0, 0, "ID", &PS_CDC::Command_ID, &PS_CDC::Command_ID_Part2 }, - { /* 0x1B, */ 0, 0, "ReadS", &PS_CDC::Command_ReadS, NULL }, - { /* 0x1C, */ 0, 0, "Init", &PS_CDC::Command_Init, NULL }, - { /* 0x1D, */ 2, 2, "Unknown 0x1D", &PS_CDC::Command_0x1d, NULL }, - { /* 0x1E, */ 0, 0, "ReadTOC", &PS_CDC::Command_ReadTOC, &PS_CDC::Command_ReadTOC_Part2 }, - { /* 0x1F, */ 0, 0, NULL, NULL, NULL }, -}; - - -} diff --git a/psx/octoshock/psx/cdc.h b/psx/octoshock/psx/cdc.h deleted file mode 100644 index 06057736bbd..00000000000 --- a/psx/octoshock/psx/cdc.h +++ /dev/null @@ -1,311 +0,0 @@ -/******************************************************************************/ -/* Mednafen Sony PS1 Emulation Module */ -/******************************************************************************/ -/* cdc.h: -** Copyright (C) 2011-2018 Mednafen Team -** -** 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., -** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef __MDFN_PSX_CDC_H -#define __MDFN_PSX_CDC_H - -#include "cdrom/CDUtility.h" -#include "cdrom/SimpleFIFO.h" - -class ShockDiscRef; - - -namespace MDFN_IEN_PSX -{ - -struct CD_Audio_Buffer -{ - int16 Samples[2][0x1000]; // [0][...] = l, [1][...] = r - uint32 Size; - uint32 Freq; - uint32 ReadPos; -}; - -class PS_CDC -{ - public: - - PS_CDC() MDFN_COLD; - ~PS_CDC() MDFN_COLD; - - templatevoid SyncState(EW::NewState *ns); - - void OpenTray(); - void SetDisc(ShockDiscRef *disc, const char disc_id[4], bool poke); - void CloseTray(bool poke); - - void Power(void) MDFN_COLD; - void ResetTS(void); - - int32 CalcNextEvent(void); // Returns in master cycles to next event. - - pscpu_timestamp_t Update(const pscpu_timestamp_t timestamp); - - void Write(const pscpu_timestamp_t timestamp, uint32 A, uint8 V); - uint8 Read(const pscpu_timestamp_t timestamp, uint32 A); - - bool DMACanRead(void); - uint32 DMARead(void); - void SoftReset(void); - - void GetCDAudio(int32 samples[2]); - void SetLEC(bool enable) { EnableLEC = enable; } - - private: - ShockDiscRef* Cur_disc; - bool EnableLEC; - bool TrayOpen; - - ShockDiscRef* Open_disc; //the disc that's in the tray, while the tray is open. pending, kind of. used because Cur_disc != NULL is used as a tray-closed marker in the CDC code - uint8 Open_DiscID[4]; //same thing - - bool Status_TrayOpenBit; //PSX-SPX calls it ShellOpen - int32 DiscStartupDelay; - - CD_Audio_Buffer AudioBuffer; - - uint8 Pending_DecodeVolume[2][2], DecodeVolume[2][2]; // [data_source][output_port] - - int16 ADPCM_ResampBuf[2][32 * 2]; - uint8 ADPCM_ResampCurPos; - uint8 ADPCM_ResampCurPhase; - - void ApplyVolume(int32 samples[2]); - void ReadAudioBuffer(int32 samples[2]); - - void ClearAudioBuffers(void); - - - // - // - // - - - uint8 RegSelector; - uint8 ArgsBuf[16]; - uint8 ArgsWP; // 5-bit(0 ... 31) - uint8 ArgsRP; // 5-bit(0 ... 31) - - uint8 ArgsReceiveLatch; - uint8 ArgsReceiveBuf[32]; - uint8 ArgsReceiveIn; - - uint8 ResultsBuffer[16]; - uint8 ResultsIn; // 5-bit(0 ... 31) - uint8 ResultsWP; // Write position, 4 bit(0 ... 15). - uint8 ResultsRP; // Read position, 4 bit(0 ... 15). - - SimpleFIFO DMABuffer; - uint8 SB[2340]; - uint32 SB_In; - - enum { SectorPipe_Count = 2 }; - uint8 SectorPipe[SectorPipe_Count][2352]; - uint8 SectorPipe_Pos; - uint8 SectorPipe_In; - - uint8 SubQBuf[0xC]; - uint8 SubQBuf_Safe[0xC]; - bool SubQChecksumOK; - - bool HeaderBufValid; - uint8 HeaderBuf[12]; - - void RecalcIRQ(void); - enum - { - CDCIRQ_NONE = 0, - CDCIRQ_DATA_READY = 1, - CDCIRQ_COMPLETE = 2, - CDCIRQ_ACKNOWLEDGE = 3, - CDCIRQ_DATA_END = 4, - CDCIRQ_DISC_ERROR = 5 - }; - - // Names are just guessed for these based on what conditions cause them: - enum - { - ERRCODE_BAD_ARGVAL = 0x10, - ERRCODE_BAD_NUMARGS = 0x20, - ERRCODE_BAD_COMMAND = 0x40, - ERRCODE_NOT_READY = 0x80, // 0x80 (happens with getlocl when drive isn't reading, pause when tray is open, and MAYBE when trying to run an async - // command while another async command is currently in its asynch phase being executed[pause when in readtoc, todo test more]) - }; - - uint8 IRQBuffer; - uint8 IRQOutTestMask; - int32 CDCReadyReceiveCounter; // IRQBuffer being non-zero prevents new results and new IRQ from coming in and erasing the current results, - // but apparently at least one CONFOUNDED game is clearing the IRQ state BEFORE reading the results, so we need to have a delay - // between IRQBuffer being cleared to when we allow new results to come in. (The real thing should be like this too, - // but the mechanism is probably more nuanced and complex and ugly and I like anchovy pizza) - - void BeginResults(void); - void WriteIRQ(uint8); - void WriteResult(uint8); - uint8 ReadResult(void); - - uint8 FilterFile; - uint8 FilterChan; - - - uint8 PendingCommand; - int PendingCommandPhase; - int32 PendingCommandCounter; - - int32 SPUCounter; - - enum { MODE_SPEED = 0x80 }; - enum { MODE_STRSND = 0x40 }; - enum { MODE_SIZE = 0x20 }; - enum { MODE_SIZE2 = 0x10 }; - enum { MODE_SF = 0x08 }; - enum { MODE_REPORT = 0x04 }; - enum { MODE_AUTOPAUSE = 0x02 }; - enum { MODE_CDDA = 0x01 }; - uint8 Mode; - - enum - { - DS_STANDBY = -2, - DS_PAUSED = -1, - DS_STOPPED = 0, - DS_SEEKING, - DS_SEEKING_LOGICAL, - DS_SEEKING_LOGICAL2, - DS_PLAYING, - DS_READING, - //DS_RESETTING - }; - int DriveStatus; - int StatusAfterSeek; - bool Forward; - bool Backward; - bool Muted; - - int32 PlayTrackMatch; - - int32 PSRCounter; - - bool HoldLogicalPos; - - int32 CurSector; - uint32 SectorsRead; // Reset to 0 on Read*/Play command start; used in the rough simulation of PS1 SetLoc->Read->Pause->Read behavior. - - unsigned AsyncIRQPending; - uint8 AsyncResultsPending[16]; - uint8 AsyncResultsPendingCount; - - int32 CalcSeekTime(int32 initial, int32 target, bool motor_on, bool paused); - - void ClearAIP(void); - void CheckAIP(void); - void SetAIP(unsigned irq, unsigned result_count, uint8 *r); - void SetAIP(unsigned irq, uint8 result0); - void SetAIP(unsigned irq, uint8 result0, uint8 result1); - - int32 SeekTarget; - uint32 SeekRetryCounter; - int SeekFinished; - - pscpu_timestamp_t lastts; - - CDUtility::TOC toc; - bool IsPSXDisc; - uint8 DiscID[4]; - - int32 CommandLoc; - bool CommandLoc_Dirty; - - uint8 MakeStatus(bool cmd_error = false); - bool DecodeSubQ(uint8 *subpw); - bool CommandCheckDiscPresent(void); - - void EnbufferizeCDDASector(const uint8 *buf); - bool XA_Test(const uint8 *sdata); - void XA_ProcessSector(const uint8 *sdata, CD_Audio_Buffer *ab); - int16 xa_previous[2][2]; - - uint8 ReportLastF; - int32 ReportStartupDelay; - - void HandlePlayRead(void); - - struct CDC_CTEntry - { - uint8 args_min; - uint8 args_max; - const char *name; - int32 (PS_CDC::*func)(const int arg_count, const uint8 *args); - int32 (PS_CDC::*func2)(void); - }; - - void PreSeekHack(int32 target); - void ReadBase(void); - - MDFN_HIDE static const CDC_CTEntry Commands[0x20]; - - int32 Command_Nop(const int arg_count, const uint8 *args); - int32 Command_Setloc(const int arg_count, const uint8 *args); - int32 Command_Play(const int arg_count, const uint8 *args); - int32 Command_Forward(const int arg_count, const uint8 *args); - int32 Command_Backward(const int arg_count, const uint8 *args); - int32 Command_ReadN(const int arg_count, const uint8 *args); - int32 Command_Standby(const int arg_count, const uint8 *args); - int32 Command_Standby_Part2(void); - int32 Command_Stop(const int arg_count, const uint8 *args); - int32 Command_Stop_Part2(void); - int32 Command_Pause(const int arg_count, const uint8 *args); - int32 Command_Pause_Part2(void); - int32 Command_Reset(const int arg_count, const uint8 *args); - int32 Command_Mute(const int arg_count, const uint8 *args); - int32 Command_Demute(const int arg_count, const uint8 *args); - int32 Command_Setfilter(const int arg_count, const uint8 *args); - int32 Command_Setmode(const int arg_count, const uint8 *args); - int32 Command_Getparam(const int arg_count, const uint8 *args); - int32 Command_GetlocL(const int arg_count, const uint8 *args); - int32 Command_GetlocP(const int arg_count, const uint8 *args); - - int32 Command_ReadT(const int arg_count, const uint8 *args); - int32 Command_ReadT_Part2(void); - - int32 Command_GetTN(const int arg_count, const uint8 *args); - int32 Command_GetTD(const int arg_count, const uint8 *args); - int32 Command_SeekL(const int arg_count, const uint8 *args); - int32 Command_SeekP(const int arg_count, const uint8 *args); - int32 Command_Seek_PartN(void); - - int32 Command_Test(const int arg_count, const uint8 *args); - - int32 Command_ID(const int arg_count, const uint8 *args); - int32 Command_ID_Part2(void); - - int32 Command_ReadS(const int arg_count, const uint8 *args); - int32 Command_Init(const int arg_count, const uint8 *args); - - int32 Command_ReadTOC(const int arg_count, const uint8 *args); - int32 Command_ReadTOC_Part2(void); - - int32 Command_0x1d(const int arg_count, const uint8 *args); -}; - -} - -#endif diff --git a/psx/octoshock/psx/cpu.cpp b/psx/octoshock/psx/cpu.cpp deleted file mode 100644 index 3df2334a543..00000000000 --- a/psx/octoshock/psx/cpu.cpp +++ /dev/null @@ -1,2825 +0,0 @@ -/******************************************************************************/ -/* Mednafen Sony PS1 Emulation Module */ -/******************************************************************************/ -/* cpu.cpp: -** Copyright (C) 2011-2016 Mednafen Team -** -** 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., -** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include -#include "psx.h" -#include "cpu.h" -#include "math_ops.h" - -#if 0 - #define EXP_ILL_CHECK(n) {n;} -#else - #define EXP_ILL_CHECK(n) {} -#endif - -//not very organized, is it -void* g_ShockTraceCallbackOpaque = NULL; -ShockCallback_Trace g_ShockTraceCallback = NULL; -ShockCallback_Mem g_ShockMemCallback; -eShockMemCb g_ShockMemCbType; -char disasm_buf[128]; - -/* TODO - Make sure load delays are correct. - - Consider preventing IRQs being taken while in a branch delay slot, to prevent potential problems with games that like to be too clever and perform - un-restartable sequences of instructions. -*/ - -#define BIU_ENABLE_ICACHE_S1 0x00000800 // Enable I-cache, set 1 -#define BIU_ICACHE_FSIZE_MASK 0x00000300 // I-cache fill size mask; 0x000 = 2 words, 0x100 = 4 words, 0x200 = 8 words, 0x300 = 16 words -#define BIU_ENABLE_DCACHE 0x00000080 // Enable D-cache -#define BIU_DCACHE_SCRATCHPAD 0x00000008 // Enable scratchpad RAM mode of D-cache -#define BIU_TAG_TEST_MODE 0x00000004 // Enable TAG test mode(IsC must be set to 1 as well presumably?) -#define BIU_INVALIDATE_MODE 0x00000002 // Enable Invalidate mode(IsC must be set to 1 as well presumably?) -#define BIU_LOCK_MODE 0x00000001 // Enable Lock mode(IsC must be set to 1 as well presumably?) - - - -namespace MDFN_IEN_PSX -{ - - -PS_CPU::PS_CPU() -{ - //printf("%zu\n", (size_t)((uintptr_t)ICache - (uintptr_t)this)); - - Halted = false; - - memset(FastMap, 0, sizeof(FastMap)); - memset(DummyPage, 0xFF, sizeof(DummyPage)); // 0xFF to trigger an illegal instruction exception, so we'll know what's up when debugging. - - for(uint64 a = 0x00000000; a < (1ULL << 32); a += FAST_MAP_PSIZE) - SetFastMap(DummyPage, a, FAST_MAP_PSIZE); - - CPUHook = NULL; - ADDBT = NULL; - - GTE_Init(); - - for(unsigned i = 0; i < 24; i++) - { - uint8 v = 7; - - if(i < 12) - v += 4; - - if(i < 21) - v += 3; - - MULT_Tab24[i] = v; - } -} - -PS_CPU::~PS_CPU() -{ - - -} - -void PS_CPU::SetFastMap(void *region_mem, uint32 region_address, uint32 region_size) -{ - // FAST_MAP_SHIFT - // FAST_MAP_PSIZE - - for(uint64 A = region_address; A < (uint64)region_address + region_size; A += FAST_MAP_PSIZE) - { - FastMap[A >> FAST_MAP_SHIFT] = ((uintptr_t)region_mem - region_address); - } -} - -INLINE void PS_CPU::RecalcIPCache(void) -{ - IPCache = 0; - - if((CP0.SR & CP0.CAUSE & 0xFF00) && (CP0.SR & 1)) - IPCache = 0x80; - - if(Halted) - IPCache = 0x80; -} - -void PS_CPU::SetHalt(bool status) -{ - Halted = status; - RecalcIPCache(); -} - -void PS_CPU::Power(void) -{ - assert(sizeof(ICache) == sizeof(ICache_Bulk)); - - memset(GPR, 0, sizeof(GPR)); - memset(&CP0, 0, sizeof(CP0)); - LO = 0; - HI = 0; - - gte_ts_done = 0; - muldiv_ts_done = 0; - - BACKED_PC = 0xBFC00000; - BACKED_new_PC = BACKED_PC + 4; - BDBT = 0; - - BACKED_LDWhich = 0x20; - BACKED_LDValue = 0; - LDAbsorb = 0; - memset(ReadAbsorb, 0, sizeof(ReadAbsorb)); - ReadAbsorbWhich = 0; - ReadFudge = 0; - - CP0.SR |= (1 << 22); // BEV - CP0.SR |= (1 << 21); // TS - - CP0.PRID = 0x2; - - RecalcIPCache(); - - - BIU = 0; - - memset(ScratchRAM.data8, 0, 1024); - - // Not quite sure about these poweron/reset values: - for(unsigned i = 0; i < 1024; i++) - { - ICache[i].TV = 0x2 | ((BIU & 0x800) ? 0x0 : 0x1); - ICache[i].Data = 0; - } - - GTE_Power(); -} - -void PS_CPU::AssertIRQ(unsigned which, bool asserted) -{ - assert(which <= 5); - - CP0.CAUSE &= ~(1 << (10 + which)); - - if(asserted) - CP0.CAUSE |= 1 << (10 + which); - - RecalcIPCache(); -} - -void PS_CPU::SetBIU(uint32 val) -{ - const uint32 old_BIU = BIU; - - BIU = val & ~(0x440); - - if((BIU ^ old_BIU) & 0x800) - { - if(BIU & 0x800) // ICache enabled - { - for(unsigned i = 0; i < 1024; i++) - ICache[i].TV &= ~0x1; - } - else // ICache disabled - { - for(unsigned i = 0; i < 1024; i++) - ICache[i].TV |= 0x1; - } - } - - PSX_DBG(PSX_DBG_SPARSE, "[CPU] Set BIU=0x%08x\n", BIU); -} - -uint32 PS_CPU::GetBIU(void) -{ - return BIU; -} - -template -INLINE T PS_CPU::PeekMemory(uint32 address) -{ - T ret; - address &= addr_mask[address >> 29]; - - if(address >= 0x1F800000 && address <= 0x1F8003FF) - return ScratchRAM.Read(address & 0x3FF); - - //assert(!(CP0.SR & 0x10000)); - - if(sizeof(T) == 1) - ret = PSX_MemPeek8(address); - else if(sizeof(T) == 2) - ret = PSX_MemPeek16(address); - else - ret = PSX_MemPeek32(address); - - return(ret); -} - -template -void PS_CPU::PokeMemory(uint32 address, T value) -{ - address &= addr_mask[address >> 29]; - - if(address >= 0x1F800000 && address <= 0x1F8003FF) - return ScratchRAM.Write(address & 0x3FF, value); - - if(sizeof(T) == 1) - PSX_MemPoke8(address, value); - else if(sizeof(T) == 2) - PSX_MemPoke16(address, value); - else - PSX_MemPoke32(address, value); -} - -template -INLINE T PS_CPU::ReadMemory(pscpu_timestamp_t ×tamp, uint32 address, bool DS24, bool LWC_timing) -{ - T ret; - - ReadAbsorb[ReadAbsorbWhich] = 0; - ReadAbsorbWhich = 0; - -#if 0 - if(MDFN_UNLIKELY(CP0.SR & 0x10000)) - { - uint32 tmp = 0; // TODO(someday): = open bus - - LDAbsorb = 0; - - if(BIU & (BIU_TAG_TEST_MODE | BIU_INVALIDATE_MODE | BIU_LOCK_MODE)) - { - if(BIU & BIU_TAG_TEST_MODE) - { - const __ICache* const ICI = &ICache[((address & 0xFF0) >> 2)]; - - tmp &= ~0x3F; // bits 0-3 validity, bit 4 tag compare match, bit 5 forced to 0(lock bit apparently unimplemented in the PS1). - - // - // Get validity bits. - // - for(unsigned i = 0; i < 4; i++) - tmp |= (!(ICI[i].TV & 0x02)) << i; - - // - // Tag compare. - // - if(!((address ^ ICI[0].TV) & 0xFFFFF000)) - tmp |= 0x10; - } - } - else - { - tmp = ICache[(address & 0xFFC) >> 2].Data; - } - - return tmp >> ((address & 0x3) * 8); - } -#endif - // - // - // - - address &= addr_mask[address >> 29]; - - if(address >= 0x1F800000 && address <= 0x1F8003FF) - { - LDAbsorb = 0; - - if(DS24) - ret = ScratchRAM.ReadU24(address & 0x3FF); - else - ret = ScratchRAM.Read(address & 0x3FF); - - if (g_ShockMemCallback && (g_ShockMemCbType & eShockMemCb_Read)) - g_ShockMemCallback(address, eShockMemCb_Read, DS24 ? 24 : sizeof(T) * 8, ret); - return(ret); - } - - timestamp += (ReadFudge >> 4) & 2; - - //assert(!(CP0.SR & 0x10000)); - - pscpu_timestamp_t lts = timestamp; - - if(sizeof(T) == 1) - ret = PSX_MemRead8(lts, address); - else if(sizeof(T) == 2) - ret = PSX_MemRead16(lts, address); - else - { - if(DS24) - ret = PSX_MemRead24(lts, address) & 0xFFFFFF; - else - ret = PSX_MemRead32(lts, address); - } - - if(LWC_timing) - lts += 1; - else - lts += 2; - - LDAbsorb = (lts - timestamp); - timestamp = lts; - - if (g_ShockMemCallback && (g_ShockMemCbType & eShockMemCb_Read)) - g_ShockMemCallback(address, eShockMemCb_Read, DS24 ? 24 : sizeof(T) * 8, ret); - return(ret); -} - -template -INLINE void PS_CPU::WriteMemory(pscpu_timestamp_t ×tamp, uint32 address, uint32 value, bool DS24) -{ - if (g_ShockMemCallback && (g_ShockMemCbType & eShockMemCb_Write)) - g_ShockMemCallback(address, eShockMemCb_Write, DS24 ? 24 : sizeof(T) * 8, value); - - if(MDFN_LIKELY(!(CP0.SR & 0x10000))) - { - address &= addr_mask[address >> 29]; - - if(address >= 0x1F800000 && address <= 0x1F8003FF) - { - if(DS24) - ScratchRAM.WriteU24(address & 0x3FF, value); - else - ScratchRAM.Write(address & 0x3FF, value); - - return; - } - - if(sizeof(T) == 1) - PSX_MemWrite8(timestamp, address, value); - else if(sizeof(T) == 2) - PSX_MemWrite16(timestamp, address, value); - else - { - if(DS24) - PSX_MemWrite24(timestamp, address, value); - else - PSX_MemWrite32(timestamp, address, value); - } - } - else - { - if(BIU & BIU_ENABLE_ICACHE_S1) // Instruction cache is enabled/active - { - if(BIU & (BIU_TAG_TEST_MODE | BIU_INVALIDATE_MODE | BIU_LOCK_MODE)) - { - const uint8 valid_bits = (BIU & BIU_TAG_TEST_MODE) ? ((value << ((address & 0x3) * 8)) & 0x0F) : 0x00; - __ICache* const ICI = &ICache[((address & 0xFF0) >> 2)]; - - // - // Set validity bits and tag. - // - for(unsigned i = 0; i < 4; i++) - ICI[i].TV = ((valid_bits & (1U << i)) ? 0x00 : 0x02) | (address & 0xFFFFFFF0) | (i << 2); - } - else - { - ICache[(address & 0xFFC) >> 2].Data = value << ((address & 0x3) * 8); - } - } - - if((BIU & 0x081) == 0x080) // Writes to the scratchpad(TODO test) - { - if(DS24) - ScratchRAM.WriteU24(address & 0x3FF, value); - else - ScratchRAM.Write(address & 0x3FF, value); - } - //printf("IsC WRITE%d 0x%08x 0x%08x -- CP0.SR=0x%08x\n", (int)sizeof(T), address, value, CP0.SR); - } -} - -// -// ICache emulation here is not very accurate. More accurate emulation had about a 6% performance penalty for simple -// code that just looped infinitely, with no tangible known benefit for commercially-released games. -// -// We do emulate the tag test mode functionality in regards to loading custom tag, valid bits, and instruction word data, as it could -// hypothetically be useful for homebrew. However, due to inaccuracies, it's possible to load a tag for an address in the non-cached -// 0xA0000000-0xBFFFFFFF range, jump to the address, and have it execute out of instruction cache, which is wrong and not possible on a PS1. -// -// The other major inaccuracy here is how the region 0x80000000-0x9FFFFFFF is handled. On a PS1, when fetching instruction word data -// from this region, the upper bit is forced to 0 before the tag compare(though the tag compare IS a full 20 bit compare), -// and this address with the upper bit set to 0 is also written to the tag on cache miss. We don't do the address masking here, -// so in addition to the tag test mode implications, a program that jumps from somewhere in 0x00000000-0x1FFFFFFF to the corresponding -// location in 0x80000000-0x9FFFFFFF will always cause a cache miss in Mednafen. -// -// On a PS1, icache miss fill size can be programmed to 2, 4, 8, or 16 words(though 4 words is the nominally-correct setting). We always emulate the cache -// miss fill size as 4-words. Fill size of 8-words and 16-words are buggy on a PS1, and will write the wrong instruction data values(or read from the wrong -// addresses?) to cache when a cache miss occurs on an address that isn't aligned to a 4-word boundary. -// Fill size of 2-words seems to work on a PS1, and even behaves as if the line size is 2 words in regards to clearing -// the valid bits(when the tag matches, of course), but is obviously not very efficient unless running code that's just endless branching. -// -INLINE uint32 PS_CPU::ReadInstruction(pscpu_timestamp_t ×tamp, uint32 address) -{ - uint32 instr; - - instr = ICache[(address & 0xFFC) >> 2].Data; - - if(ICache[(address & 0xFFC) >> 2].TV != address) - { - ReadAbsorb[ReadAbsorbWhich] = 0; - ReadAbsorbWhich = 0; - - if(address >= 0xA0000000 || !(BIU & 0x800)) - { - instr = MDFN_de32lsb((uint8*)(FastMap[address >> FAST_MAP_SHIFT] + address)); - timestamp += 4; // Approximate best-case cache-disabled time, per PS1 tests(executing out of 0xA0000000+); it can be 5 in *some* sequences of code(like a lot of sequential "nop"s, probably other simple instructions too). - } - else - { - __ICache *ICI = &ICache[((address & 0xFF0) >> 2)]; - const uint8 *FMP = (uint8*)(FastMap[(address & 0xFFFFFFF0) >> FAST_MAP_SHIFT] + (address & 0xFFFFFFF0)); - - // | 0x2 to simulate (in)validity bits. - ICI[0x00].TV = (address & 0xFFFFFFF0) | 0x0 | 0x2; - ICI[0x01].TV = (address & 0xFFFFFFF0) | 0x4 | 0x2; - ICI[0x02].TV = (address & 0xFFFFFFF0) | 0x8 | 0x2; - ICI[0x03].TV = (address & 0xFFFFFFF0) | 0xC | 0x2; - - timestamp += 3; - - switch(address & 0xC) - { - case 0x0: - timestamp++; - ICI[0x00].TV &= ~0x2; - ICI[0x00].Data = MDFN_de32lsb(&FMP[0x0]); - case 0x4: - timestamp++; - ICI[0x01].TV &= ~0x2; - ICI[0x01].Data = MDFN_de32lsb(&FMP[0x4]); - case 0x8: - timestamp++; - ICI[0x02].TV &= ~0x2; - ICI[0x02].Data = MDFN_de32lsb(&FMP[0x8]); - case 0xC: - timestamp++; - ICI[0x03].TV &= ~0x2; - ICI[0x03].Data = MDFN_de32lsb(&FMP[0xC]); - break; - } - instr = ICache[(address & 0xFFC) >> 2].Data; - } - } - - return instr; -} - -uint32 NO_INLINE PS_CPU::Exception(uint32 code, uint32 PC, const uint32 NP, const uint32 instr) -{ - uint32 handler = 0x80000080; - - assert(code < 16); - - if(code != EXCEPTION_INT && code != EXCEPTION_BP && code != EXCEPTION_SYSCALL) - { - static const char* exmne[16] = - { - "INT", "MOD", "TLBL", "TLBS", "ADEL", "ADES", "IBE", "DBE", "SYSCALL", "BP", "RI", "COPU", "OV", NULL, NULL, NULL - }; - - PSX_DBG(PSX_DBG_WARNING, "[CPU] Exception %s(0x%02x) @ PC=0x%08x(NP=0x%08x, BDBT=0x%02x), Instr=0x%08x, IPCache=0x%02x, CAUSE=0x%08x, SR=0x%08x, IRQC_Status=0x%04x, IRQC_Mask=0x%04x\n", - exmne[code], code, PC, NP, BDBT, instr, IPCache, CP0.CAUSE, CP0.SR, IRQ_GetRegister(IRQ_GSREG_STATUS, NULL, 0), IRQ_GetRegister(IRQ_GSREG_MASK, NULL, 0)); - } - - if(CP0.SR & (1 << 22)) // BEV - handler = 0xBFC00180; - - CP0.EPC = PC; - if(BDBT & 2) - { - CP0.EPC -= 4; - CP0.TAR = NP; - } - - if(ADDBT) - ADDBT(PC, handler, true); - - // "Push" IEc and KUc(so that the new IEc and KUc are 0) - CP0.SR = (CP0.SR & ~0x3F) | ((CP0.SR << 2) & 0x3F); - - // Setup cause register - CP0.CAUSE &= 0x0000FF00; - CP0.CAUSE |= code << 2; - - CP0.CAUSE |= BDBT << 30; - CP0.CAUSE |= (instr << 2) & (0x3 << 28); // CE - - // - // - // - RecalcIPCache(); - - BDBT = 0; - - return(handler); -} - -#define BACKING_TO_ACTIVE \ - PC = BACKED_PC; \ - new_PC = BACKED_new_PC; \ - LDWhich = BACKED_LDWhich; \ - LDValue = BACKED_LDValue; - -#define ACTIVE_TO_BACKING \ - BACKED_PC = PC; \ - BACKED_new_PC = new_PC; \ - BACKED_LDWhich = LDWhich; \ - BACKED_LDValue = LDValue; - -// -// Should come before DO_LDS() so the EXP_ILL_CHECK() emulator debugging macro in GPR_DEP() will work properly. -// -#define GPR_DEPRES_BEGIN { uint8 back = ReadAbsorb[0]; -#define GPR_DEP(n) { unsigned tn = (n); ReadAbsorb[tn] = 0; EXP_ILL_CHECK(if(LDWhich > 0 && LDWhich < 0x20 && LDWhich == tn) { PSX_DBG(PSX_DBG_WARNING, "[CPU] Instruction at PC=0x%08x in load delay slot has dependency on load target register(0x%02x): SR=0x%08x\n", PC, LDWhich, CP0.SR); }) } -#define GPR_RES(n) { unsigned tn = (n); ReadAbsorb[tn] = 0; } -#define GPR_DEPRES_END ReadAbsorb[0] = back; } - -template -pscpu_timestamp_t PS_CPU::RunReal(pscpu_timestamp_t timestamp_in) -{ - pscpu_timestamp_t timestamp = timestamp_in; - - uint32 PC; - uint32 new_PC; - uint32 LDWhich; - uint32 LDValue; - - //printf("%d %d\n", gte_ts_done, muldiv_ts_done); - - gte_ts_done += timestamp; - muldiv_ts_done += timestamp; - - BACKING_TO_ACTIVE; - - do - { - //printf("Running: %d %d\n", timestamp, next_event_ts); - while(MDFN_LIKELY(timestamp < next_event_ts)) - { - uint32 instr; - uint32 opf; - - // Zero must be zero...until the Master Plan is enacted. - GPR[0] = 0; - - if(DebugMode && CPUHook) - { - ACTIVE_TO_BACKING; - - // For save states in step mode. - gte_ts_done -= timestamp; - muldiv_ts_done -= timestamp; - - CPUHook(timestamp, PC); - - // For save states in step mode. - gte_ts_done += timestamp; - muldiv_ts_done += timestamp; - - BACKING_TO_ACTIVE; - } - - if(BIOSPrintMode) - { - if(PC == 0xB0) - { - if(MDFN_UNLIKELY(GPR[9] == 0x3D)) - { - PSX_DBG_BIOS_PUTC(GPR[4]); - } - } - } - - // - // Instruction fetch - // - if(MDFN_UNLIKELY(PC & 0x3)) - { - // This will block interrupt processing, but since we're going more for keeping broken homebrew/hacks from working - // than super-duper-accurate pipeline emulation, it shouldn't be a problem. - CP0.BADA = PC; - new_PC = Exception(EXCEPTION_ADEL, PC, new_PC, 0); - goto OpDone; - } - - instr = ReadInstruction(timestamp, PC); - - - // - // Instruction decode - // - //printf("PC=%08x, SP=%08x - op=0x%02x - funct=0x%02x - instr=0x%08x\n", PC, GPR[29], instr >> 26, instr & 0x3F, instr); - //for(int i = 0; i < 32; i++) - // printf("%02x : %08x\n", i, GPR[i]); - //printf("\n"); - if (g_ShockTraceCallback) - { - //_asm int 3; - shock_Util_DisassembleMIPS(PC, instr, disasm_buf, ARRAY_SIZE(disasm_buf)); - g_ShockTraceCallback(NULL, PC, instr, disasm_buf); - } - - if (g_ShockMemCallback && (g_ShockMemCbType & eShockMemCb_Execute)) - g_ShockMemCallback(PC, eShockMemCb_Execute, 32, instr); - - - opf = instr & 0x3F; - - if(instr & (0x3F << 26)) - opf = 0x40 | (instr >> 26); - - opf |= IPCache; - - if(ReadAbsorb[ReadAbsorbWhich]) - ReadAbsorb[ReadAbsorbWhich]--; - else - timestamp++; - - #define DO_LDS() { GPR[LDWhich] = LDValue; ReadAbsorb[LDWhich] = LDAbsorb; ReadFudge = LDWhich; ReadAbsorbWhich |= LDWhich & 0x1F; LDWhich = 0x20; } - #define BEGIN_OPF(name) { op_##name: - #define END_OPF goto OpDone; } - - #define DO_BRANCH(arg_cond, arg_offset, arg_mask, arg_dolink, arg_linkreg)\ - { \ - const bool cond = (arg_cond); \ - const uint32 offset = (arg_offset); \ - const uint32 mask = (arg_mask); \ - const uint32 old_PC = PC; \ - \ - EXP_ILL_CHECK(if(BDBT) { PSX_DBG(PSX_DBG_WARNING, "[CPU] Branch instruction at PC=0x%08x in branch delay slot: SR=0x%08x\n", PC, CP0.SR);}) \ - \ - PC = new_PC; \ - new_PC += 4; \ - BDBT = 2; \ - \ - if(arg_dolink) \ - GPR[(arg_linkreg)] = new_PC; \ - \ - if(cond) \ - { \ - if(ILHMode) \ - { \ - if(old_PC == (((new_PC - 4) & mask) + offset)) \ - { \ - if(MDFN_densb((uint8*)(FastMap[PC >> FAST_MAP_SHIFT] + PC)) == 0) \ - { \ - if(next_event_ts > timestamp) /* Necessary since next_event_ts might be set to something like "0" to force a call to the event handler. */ \ - { \ - timestamp = next_event_ts; \ - } \ - } \ - } \ - } \ - \ - new_PC = ((new_PC - 4) & mask) + offset; \ - BDBT = 3; \ - \ - if(DebugMode && ADDBT) \ - { \ - ADDBT(PC, new_PC, false); \ - } \ - } \ - \ - goto SkipNPCStuff; \ - } - - #define ITYPE uint32 rs MDFN_NOWARN_UNUSED = (instr >> 21) & 0x1F; uint32 rt MDFN_NOWARN_UNUSED = (instr >> 16) & 0x1F; uint32 immediate = (int32)(int16)(instr & 0xFFFF); /*printf(" rs=%02x(%08x), rt=%02x(%08x), immediate=(%08x) ", rs, GPR[rs], rt, GPR[rt], immediate);*/ - #define ITYPE_ZE uint32 rs MDFN_NOWARN_UNUSED = (instr >> 21) & 0x1F; uint32 rt MDFN_NOWARN_UNUSED = (instr >> 16) & 0x1F; uint32 immediate = instr & 0xFFFF; /*printf(" rs=%02x(%08x), rt=%02x(%08x), immediate=(%08x) ", rs, GPR[rs], rt, GPR[rt], immediate);*/ - #define JTYPE uint32 target = instr & ((1 << 26) - 1); /*printf(" target=(%08x) ", target);*/ - #define RTYPE uint32 rs MDFN_NOWARN_UNUSED = (instr >> 21) & 0x1F; uint32 rt MDFN_NOWARN_UNUSED = (instr >> 16) & 0x1F; uint32 rd MDFN_NOWARN_UNUSED = (instr >> 11) & 0x1F; uint32 shamt MDFN_NOWARN_UNUSED = (instr >> 6) & 0x1F; /*printf(" rs=%02x(%08x), rt=%02x(%08x), rd=%02x(%08x) ", rs, GPR[rs], rt, GPR[rt], rd, GPR[rd]);*/ - -#if HAVE_COMPUTED_GOTO - #if 0 - // - // These truncated 32-bit table values apparently can't be calculated at compile/link time by gcc on x86_64, so gcc inserts initialization code, but - // the compare for the initialization code path is placed sub-optimally(near where the table value is used instead of at the beginning of the function). - // - #define CGBEGIN static const uint32 const op_goto_table[256] = { - #define CGE(l) (uint32)(uintptr_t)&&l, - #define CGEND }; goto *(void*)(uintptr_t)op_goto_table[opf]; - #else - #define CGBEGIN static const void *const op_goto_table[256] = { - #define CGE(l) &&l, - #define CGEND }; goto *op_goto_table[opf]; - #endif -#else - /* (uint8) cast for cheaper alternative to generated branch+compare bounds check instructions, but still more - expensive than computed goto which needs no masking nor bounds checking. - */ - #define CGBEGIN { enum { CGESB = 1 + __COUNTER__ }; switch((uint8)opf) { - #define CGE(l) case __COUNTER__ - CGESB: goto l; - #define CGEND } } -#endif - - CGBEGIN - CGE(op_SLL) CGE(op_ILL) CGE(op_SRL) CGE(op_SRA) CGE(op_SLLV) CGE(op_ILL) CGE(op_SRLV) CGE(op_SRAV) - CGE(op_JR) CGE(op_JALR) CGE(op_ILL) CGE(op_ILL) CGE(op_SYSCALL) CGE(op_BREAK) CGE(op_ILL) CGE(op_ILL) - CGE(op_MFHI) CGE(op_MTHI) CGE(op_MFLO) CGE(op_MTLO) CGE(op_ILL) CGE(op_ILL) CGE(op_ILL) CGE(op_ILL) - CGE(op_MULT) CGE(op_MULTU) CGE(op_DIV) CGE(op_DIVU) CGE(op_ILL) CGE(op_ILL) CGE(op_ILL) CGE(op_ILL) - CGE(op_ADD) CGE(op_ADDU) CGE(op_SUB) CGE(op_SUBU) CGE(op_AND) CGE(op_OR) CGE(op_XOR) CGE(op_NOR) - CGE(op_ILL) CGE(op_ILL) CGE(op_SLT) CGE(op_SLTU) CGE(op_ILL) CGE(op_ILL) CGE(op_ILL) CGE(op_ILL) - CGE(op_ILL) CGE(op_ILL) CGE(op_ILL) CGE(op_ILL) CGE(op_ILL) CGE(op_ILL) CGE(op_ILL) CGE(op_ILL) - CGE(op_ILL) CGE(op_ILL) CGE(op_ILL) CGE(op_ILL) CGE(op_ILL) CGE(op_ILL) CGE(op_ILL) CGE(op_ILL) - - CGE(op_ILL) CGE(op_BCOND) CGE(op_J) CGE(op_JAL) CGE(op_BEQ) CGE(op_BNE) CGE(op_BLEZ) CGE(op_BGTZ) - CGE(op_ADDI) CGE(op_ADDIU) CGE(op_SLTI) CGE(op_SLTIU) CGE(op_ANDI) CGE(op_ORI) CGE(op_XORI) CGE(op_LUI) - CGE(op_COP0) CGE(op_COP13) CGE(op_COP2) CGE(op_COP13) CGE(op_ILL) CGE(op_ILL) CGE(op_ILL) CGE(op_ILL) - CGE(op_ILL) CGE(op_ILL) CGE(op_ILL) CGE(op_ILL) CGE(op_ILL) CGE(op_ILL) CGE(op_ILL) CGE(op_ILL) - CGE(op_LB) CGE(op_LH) CGE(op_LWL) CGE(op_LW) CGE(op_LBU) CGE(op_LHU) CGE(op_LWR) CGE(op_ILL) - CGE(op_SB) CGE(op_SH) CGE(op_SWL) CGE(op_SW) CGE(op_ILL) CGE(op_ILL) CGE(op_SWR) CGE(op_ILL) - CGE(op_LWC013) CGE(op_LWC013) CGE(op_LWC2) CGE(op_LWC013) CGE(op_ILL) CGE(op_ILL) CGE(op_ILL) CGE(op_ILL) - CGE(op_SWC013) CGE(op_SWC013) CGE(op_SWC2) CGE(op_SWC013) CGE(op_ILL) CGE(op_ILL) CGE(op_ILL) CGE(op_ILL) - - // Interrupt portion of this table is constructed so that an interrupt won't be taken when the PC is pointing to a GTE instruction, - // to avoid problems caused by pipeline vs coprocessor nuances that aren't emulated. - CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) - CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) - CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) - CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) - CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) - CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) - CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) - CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) - - CGE(op_ILL) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) - CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) - CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_COP2) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) - CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) - CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) - CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) - CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) - CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) - CGEND - - { - BEGIN_OPF(ILL); - DO_LDS(); - new_PC = Exception(EXCEPTION_RI, PC, new_PC, instr); - END_OPF; - - // - // ADD - Add Word - // - BEGIN_OPF(ADD); - RTYPE; - - GPR_DEPRES_BEGIN - GPR_DEP(rs); - GPR_DEP(rt); - GPR_RES(rd); - GPR_DEPRES_END - - uint32 result = GPR[rs] + GPR[rt]; - bool ep = ((~(GPR[rs] ^ GPR[rt])) & (GPR[rs] ^ result)) & 0x80000000; - - DO_LDS(); - - if(MDFN_UNLIKELY(ep)) - { - new_PC = Exception(EXCEPTION_OV, PC, new_PC, instr); - } - else - GPR[rd] = result; - - END_OPF; - - // - // ADDI - Add Immediate Word - // - BEGIN_OPF(ADDI); - ITYPE; - - GPR_DEPRES_BEGIN - GPR_DEP(rs); - GPR_RES(rt); - GPR_DEPRES_END - - uint32 result = GPR[rs] + immediate; - bool ep = ((~(GPR[rs] ^ immediate)) & (GPR[rs] ^ result)) & 0x80000000; - - DO_LDS(); - - if(MDFN_UNLIKELY(ep)) - { - new_PC = Exception(EXCEPTION_OV, PC, new_PC, instr); - } - else - GPR[rt] = result; - - END_OPF; - - // - // ADDIU - Add Immediate Unsigned Word - // - BEGIN_OPF(ADDIU); - ITYPE; - - GPR_DEPRES_BEGIN - GPR_DEP(rs); - GPR_RES(rt); - GPR_DEPRES_END - - uint32 result = GPR[rs] + immediate; - - DO_LDS(); - - GPR[rt] = result; - - END_OPF; - - // - // ADDU - Add Unsigned Word - // - BEGIN_OPF(ADDU); - RTYPE; - - GPR_DEPRES_BEGIN - GPR_DEP(rs); - GPR_DEP(rt); - GPR_RES(rd); - GPR_DEPRES_END - - uint32 result = GPR[rs] + GPR[rt]; - - DO_LDS(); - - GPR[rd] = result; - - END_OPF; - - // - // AND - And - // - BEGIN_OPF(AND); - RTYPE; - - GPR_DEPRES_BEGIN - GPR_DEP(rs); - GPR_DEP(rt); - GPR_RES(rd); - GPR_DEPRES_END - - uint32 result = GPR[rs] & GPR[rt]; - - DO_LDS(); - - GPR[rd] = result; - - END_OPF; - - // - // ANDI - And Immediate - // - BEGIN_OPF(ANDI); - ITYPE_ZE; - - GPR_DEPRES_BEGIN - GPR_DEP(rs); - GPR_RES(rt); - GPR_DEPRES_END - - uint32 result = GPR[rs] & immediate; - - DO_LDS(); - - GPR[rt] = result; - - END_OPF; - - // - // BEQ - Branch on Equal - // - BEGIN_OPF(BEQ); - ITYPE; - - GPR_DEPRES_BEGIN - GPR_DEP(rs); - GPR_DEP(rt); - GPR_DEPRES_END - - const bool result = (GPR[rs] == GPR[rt]); - - DO_LDS(); - - DO_BRANCH(result, (immediate << 2), ~0U, false, 0); - END_OPF; - - // Bah, why does MIPS encoding have to be funky like this. :( - // Handles BGEZ, BGEZAL, BLTZ, BLTZAL - BEGIN_OPF(BCOND); - const uint32 tv = GPR[(instr >> 21) & 0x1F]; - const uint32 riv = (instr >> 16) & 0x1F; - const uint32 immediate = (int32)(int16)(instr & 0xFFFF); - const bool result = (int32)(tv ^ (riv << 31)) < 0; - const uint32 link = ((riv & 0x1E) == 0x10) ? 31 : 0; - - GPR_DEPRES_BEGIN - GPR_DEP((instr >> 21) & 0x1F); - GPR_RES(link); - GPR_DEPRES_END - - DO_LDS(); - - DO_BRANCH(result, (immediate << 2), ~0U, true, link); - END_OPF; - - - // - // BGTZ - Branch on Greater than Zero - // - BEGIN_OPF(BGTZ); - ITYPE; - - GPR_DEPRES_BEGIN - GPR_DEP(rs); - GPR_DEPRES_END - - const bool result = (int32)GPR[rs] > 0; - - DO_LDS(); - - DO_BRANCH(result, (immediate << 2), ~0U, false, 0); - END_OPF; - - // - // BLEZ - Branch on Less Than or Equal to Zero - // - BEGIN_OPF(BLEZ); - ITYPE; - - GPR_DEPRES_BEGIN - GPR_DEP(rs); - GPR_DEPRES_END - - const bool result = (int32)GPR[rs] <= 0; - - DO_LDS(); - - DO_BRANCH(result, (immediate << 2), ~0U, false, 0); - END_OPF; - - // - // BNE - Branch on Not Equal - // - BEGIN_OPF(BNE); - ITYPE; - - GPR_DEPRES_BEGIN - GPR_DEP(rs); - GPR_DEP(rt); - GPR_DEPRES_END - - const bool result = GPR[rs] != GPR[rt]; - - DO_LDS(); - - DO_BRANCH(result, (immediate << 2), ~0U, false, 0); - END_OPF; - - // - // BREAK - Breakpoint - // - BEGIN_OPF(BREAK); - DO_LDS(); - new_PC = Exception(EXCEPTION_BP, PC, new_PC, instr); - END_OPF; - - // Cop "instructions": CFCz(no CP0), COPz, CTCz(no CP0), LWCz(no CP0), MFCz, MTCz, SWCz(no CP0) - // - // COP0 instructions - // - BEGIN_OPF(COP0); - const uint32 sub_op = (instr >> 21) & 0x1F; - const uint32 rt = (instr >> 16) & 0x1F; - const uint32 rd = (instr >> 11) & 0x1F; - const uint32 val = GPR[rt]; - - switch(sub_op) - { - default: - DO_LDS(); - break; - - case 0x02: - case 0x06: - DO_LDS(); - new_PC = Exception(EXCEPTION_RI, PC, new_PC, instr); - break; - - case 0x00: // MFC0 - Move from Coprocessor - switch(rd) - { - case 0x00: - case 0x01: - case 0x02: - case 0x04: - case 0x0A: - DO_LDS(); - new_PC = Exception(EXCEPTION_RI, PC, new_PC, instr); - break; - - case 0x03: - case 0x05: - case 0x06: - case 0x07: - case 0x08: - case 0x09: - case 0x0B: - case 0x0C: - case 0x0D: - case 0x0E: - case 0x0F: - if(MDFN_UNLIKELY(LDWhich == rt)) - LDWhich = 0; - - DO_LDS(); - - LDAbsorb = 0; - LDWhich = rt; - LDValue = CP0.Regs[rd]; - break; - - default: - // Tested to be rather NOPish - DO_LDS(); - PSX_DBG(PSX_DBG_WARNING, "[CPU] MFC0 from unmapped CP0 register %u.\n", rd); - break; - } - break; - - case 0x04: // MTC0 - Move to Coprocessor - DO_LDS(); - switch(rd) - { - case 0x00: - case 0x01: - case 0x02: - case 0x04: - case 0x0A: - new_PC = Exception(EXCEPTION_RI, PC, new_PC, instr); - break; - - case CP0REG_BPC: - CP0.BPC = val; - break; - - case CP0REG_BDA: - CP0.BDA = val; - break; - - case CP0REG_DCIC: - if(val) - { - PSX_DBG(PSX_DBG_WARNING, "[CPU] Non-zero write to DCIC: 0x%08x\n", val); - } - CP0.DCIC = val & 0xFF80003F; - break; - - case CP0REG_BDAM: - CP0.BDAM = val; - break; - - case CP0REG_BPCM: - CP0.BPCM = val; - break; - - case CP0REG_CAUSE: - CP0.CAUSE &= ~(0x3 << 8); - CP0.CAUSE |= val & (0x3 << 8); - RecalcIPCache(); - break; - - case CP0REG_SR: - CP0.SR = val & ~( (0x3 << 26) | (0x3 << 23) | (0x3 << 6)); - RecalcIPCache(); - break; - } - break; - - case 0x08: // BC - case 0x0C: - DO_LDS(); - { - const uint32 immediate = (int32)(int16)(instr & 0xFFFF); - const bool result = (false == (bool)(instr & (1U << 16))); - - PSX_DBG(PSX_DBG_WARNING, "[CPU] BC0x instruction(0x%08x) @ PC=0x%08x\n", instr, PC); - - DO_BRANCH(result, (immediate << 2), ~0U, false, 0); - } - break; - - case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17: - case 0x18: case 0x19: case 0x1A: case 0x1B: case 0x1C: case 0x1D: case 0x1E: case 0x1F: - DO_LDS(); - { - const uint32 cp0_op = instr & 0x1F; // Not 0x3F - - if(MDFN_LIKELY(cp0_op == 0x10)) // RFE - { - // "Pop" - CP0.SR = (CP0.SR & ~0x0F) | ((CP0.SR >> 2) & 0x0F); - RecalcIPCache(); - } - else if(cp0_op == 0x01 || cp0_op == 0x02 || cp0_op == 0x06 || cp0_op == 0x08) // TLBR, TLBWI, TLBWR, TLBP - { - new_PC = Exception(EXCEPTION_RI, PC, new_PC, instr); - } - } - break; - } - END_OPF; - - // - // COP2 - // - BEGIN_OPF(COP2); - const uint32 sub_op = (instr >> 21) & 0x1F; - const uint32 rt = (instr >> 16) & 0x1F; - const uint32 rd = (instr >> 11) & 0x1F; - const uint32 val = GPR[rt]; - - if(MDFN_UNLIKELY(!(CP0.SR & (1U << (28 + 2))))) - { - DO_LDS(); - new_PC = Exception(EXCEPTION_COPU, PC, new_PC, instr); - } - else switch(sub_op) - { - default: - DO_LDS(); - break; - - case 0x00: // MFC2 - Move from Coprocessor - if(MDFN_UNLIKELY(LDWhich == rt)) - LDWhich = 0; - - DO_LDS(); - - if(timestamp < gte_ts_done) - { - LDAbsorb = gte_ts_done - timestamp; - timestamp = gte_ts_done; - } - else - LDAbsorb = 0; - - LDWhich = rt; - LDValue = GTE_ReadDR(rd); - break; - - case 0x04: // MTC2 - Move to Coprocessor - DO_LDS(); - - if(timestamp < gte_ts_done) - timestamp = gte_ts_done; - - GTE_WriteDR(rd, val); - break; - - case 0x02: // CFC2 - if(MDFN_UNLIKELY(LDWhich == rt)) - LDWhich = 0; - - DO_LDS(); - - if(timestamp < gte_ts_done) - { - LDAbsorb = gte_ts_done - timestamp; - timestamp = gte_ts_done; - } - else - LDAbsorb = 0; - - LDWhich = rt; - LDValue = GTE_ReadCR(rd); - break; - - case 0x06: // CTC2 - DO_LDS(); - - if(timestamp < gte_ts_done) - timestamp = gte_ts_done; - - GTE_WriteCR(rd, val); - break; - - case 0x08: - case 0x0C: - DO_LDS(); - { - const uint32 immediate = (int32)(int16)(instr & 0xFFFF); - const bool result = (false == (bool)(instr & (1U << 16))); - - PSX_DBG(PSX_DBG_WARNING, "[CPU] BC2x instruction(0x%08x) @ PC=0x%08x\n", instr, PC); - - DO_BRANCH(result, (immediate << 2), ~0U, false, 0); - } - break; - - case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17: - case 0x18: case 0x19: case 0x1A: case 0x1B: case 0x1C: case 0x1D: case 0x1E: case 0x1F: - DO_LDS(); - - if(timestamp < gte_ts_done) - timestamp = gte_ts_done; - gte_ts_done = timestamp + GTE_Instruction(instr); - break; - } - END_OPF; - - // - // COP1, COP3 - // - BEGIN_OPF(COP13); - DO_LDS(); - - if(!(CP0.SR & (1U << (28 + ((instr >> 26) & 0x3))))) - { - new_PC = Exception(EXCEPTION_COPU, PC, new_PC, instr); - } - else - { - const uint32 sub_op = (instr >> 21) & 0x1F; - - PSX_DBG(PSX_DBG_WARNING, "[CPU] COP%u instruction(0x%08x) @ PC=0x%08x\n", (instr >> 26) & 0x3, instr, PC); - - if(sub_op == 0x08 || sub_op == 0x0C) - { - const uint32 immediate = (int32)(int16)(instr & 0xFFFF); - const bool result = (false == (bool)(instr & (1U << 16))); - - DO_BRANCH(result, (immediate << 2), ~0U, false, 0); - } - } - END_OPF; - - // - // LWC0, LWC1, LWC3 - // - BEGIN_OPF(LWC013); - ITYPE; - const uint32 address = GPR[rs] + immediate; - - DO_LDS(); - - if(!(CP0.SR & (1U << (28 + ((instr >> 26) & 0x3))))) - { - new_PC = Exception(EXCEPTION_COPU, PC, new_PC, instr); - } - else - { - if(MDFN_UNLIKELY(address & 3)) - { - CP0.BADA = address; - new_PC = Exception(EXCEPTION_ADEL, PC, new_PC, instr); - } - else - { - PSX_DBG(PSX_DBG_WARNING, "[CPU] LWC%u instruction(0x%08x) @ PC=0x%08x\n", (instr >> 26) & 0x3, instr, PC); - - ReadMemory(timestamp, address, false, true); - } - } - END_OPF; - - // - // LWC2 - // - BEGIN_OPF(LWC2); - ITYPE; - const uint32 address = GPR[rs] + immediate; - - DO_LDS(); - - if(MDFN_UNLIKELY(address & 3)) - { - CP0.BADA = address; - new_PC = Exception(EXCEPTION_ADEL, PC, new_PC, instr); - } - else - { - if(timestamp < gte_ts_done) - timestamp = gte_ts_done; - - GTE_WriteDR(rt, ReadMemory(timestamp, address, false, true)); - } - // GTE stuff here - END_OPF; - - // - // SWC0, SWC1, SCW3 - // - BEGIN_OPF(SWC013); - ITYPE; - const uint32 address = GPR[rs] + immediate; - - DO_LDS(); - - if(!(CP0.SR & (1U << (28 + ((instr >> 26) & 0x3))))) - { - new_PC = Exception(EXCEPTION_COPU, PC, new_PC, instr); - } - else - { - if(MDFN_UNLIKELY(address & 0x3)) - { - CP0.BADA = address; - new_PC = Exception(EXCEPTION_ADES, PC, new_PC, instr); - } - else - { - PSX_DBG(PSX_DBG_WARNING, "[CPU] SWC%u instruction(0x%08x) @ PC=0x%08x\n", (instr >> 26) & 0x3, instr, PC); - //WriteMemory(timestamp, address, SOMETHING); - } - } - END_OPF; - - // - // SWC2 - // - BEGIN_OPF(SWC2); - ITYPE; - const uint32 address = GPR[rs] + immediate; - - if(MDFN_UNLIKELY(address & 0x3)) - { - CP0.BADA = address; - new_PC = Exception(EXCEPTION_ADES, PC, new_PC, instr); - } - else - { - if(timestamp < gte_ts_done) - timestamp = gte_ts_done; - - WriteMemory(timestamp, address, GTE_ReadDR(rt)); - } - DO_LDS(); - END_OPF; - - // - // DIV - Divide Word - // - BEGIN_OPF(DIV); - RTYPE; - - GPR_DEPRES_BEGIN - GPR_DEP(rs); - GPR_DEP(rt); - GPR_DEPRES_END - - if(!GPR[rt]) - { - if(GPR[rs] & 0x80000000) - LO = 1; - else - LO = 0xFFFFFFFF; - - HI = GPR[rs]; - } - else if(GPR[rs] == 0x80000000 && GPR[rt] == 0xFFFFFFFF) - { - LO = 0x80000000; - HI = 0; - } - else - { - LO = (int32)GPR[rs] / (int32)GPR[rt]; - HI = (int32)GPR[rs] % (int32)GPR[rt]; - } - muldiv_ts_done = timestamp + 37; - - DO_LDS(); - - END_OPF; - - - // - // DIVU - Divide Unsigned Word - // - BEGIN_OPF(DIVU); - RTYPE; - - GPR_DEPRES_BEGIN - GPR_DEP(rs); - GPR_DEP(rt); - GPR_DEPRES_END - - if(!GPR[rt]) - { - LO = 0xFFFFFFFF; - HI = GPR[rs]; - } - else - { - LO = GPR[rs] / GPR[rt]; - HI = GPR[rs] % GPR[rt]; - } - muldiv_ts_done = timestamp + 37; - - DO_LDS(); - END_OPF; - - // - // J - Jump - // - BEGIN_OPF(J); - JTYPE; - - DO_LDS(); - - DO_BRANCH(true, target << 2, 0xF0000000, false, 0); - END_OPF; - - // - // JAL - Jump and Link - // - BEGIN_OPF(JAL); - JTYPE; - - //GPR_DEPRES_BEGIN - GPR_RES(31); - //GPR_DEPRES_END - - DO_LDS(); - - DO_BRANCH(true, target << 2, 0xF0000000, true, 31); - END_OPF; - - // - // JALR - Jump and Link Register - // - BEGIN_OPF(JALR); - RTYPE; - - GPR_DEPRES_BEGIN - GPR_DEP(rs); - GPR_RES(rd); - GPR_DEPRES_END - - uint32 tmp = GPR[rs]; - - DO_LDS(); - - DO_BRANCH(true, tmp, 0, true, rd); - END_OPF; - - // - // JR - Jump Register - // - BEGIN_OPF(JR); - RTYPE; - - GPR_DEPRES_BEGIN - GPR_DEP(rs); - GPR_RES(rd); - GPR_DEPRES_END - - uint32 bt = GPR[rs]; - - DO_LDS(); - - DO_BRANCH(true, bt, 0, false, 0); - END_OPF; - - // - // LUI - Load Upper Immediate - // - BEGIN_OPF(LUI); - ITYPE_ZE; // Actually, probably would be sign-extending...if we were emulating a 64-bit MIPS chip :b - - GPR_DEPRES_BEGIN - GPR_RES(rt); - GPR_DEPRES_END - - DO_LDS(); - - GPR[rt] = immediate << 16; - - END_OPF; - - // - // MFHI - Move from HI - // - BEGIN_OPF(MFHI); - RTYPE; - - GPR_DEPRES_BEGIN - GPR_RES(rd); - GPR_DEPRES_END - - DO_LDS(); - - if(timestamp < muldiv_ts_done) - { - if(timestamp == muldiv_ts_done - 1) - muldiv_ts_done--; - else - { - do - { - if(ReadAbsorb[ReadAbsorbWhich]) - ReadAbsorb[ReadAbsorbWhich]--; - timestamp++; - } while(timestamp < muldiv_ts_done); - } - } - - GPR[rd] = HI; - - END_OPF; - - - // - // MFLO - Move from LO - // - BEGIN_OPF(MFLO); - RTYPE; - - GPR_DEPRES_BEGIN - GPR_RES(rd); - GPR_DEPRES_END - - DO_LDS(); - - if(timestamp < muldiv_ts_done) - { - if(timestamp == muldiv_ts_done - 1) - muldiv_ts_done--; - else - { - do - { - if(ReadAbsorb[ReadAbsorbWhich]) - ReadAbsorb[ReadAbsorbWhich]--; - timestamp++; - } while(timestamp < muldiv_ts_done); - } - } - - GPR[rd] = LO; - - END_OPF; - - - // - // MTHI - Move to HI - // - BEGIN_OPF(MTHI); - RTYPE; - - GPR_DEPRES_BEGIN - GPR_DEP(rs); - GPR_DEPRES_END - - HI = GPR[rs]; - - DO_LDS(); - - END_OPF; - - // - // MTLO - Move to LO - // - BEGIN_OPF(MTLO); - RTYPE; - - GPR_DEPRES_BEGIN - GPR_DEP(rs); - GPR_DEPRES_END - - LO = GPR[rs]; - - DO_LDS(); - - END_OPF; - - - // - // MULT - Multiply Word - // - BEGIN_OPF(MULT); - RTYPE; - - GPR_DEPRES_BEGIN - GPR_DEP(rs); - GPR_DEP(rt); - GPR_DEPRES_END - - uint64 result; - - result = (int64)(int32)GPR[rs] * (int32)GPR[rt]; - muldiv_ts_done = timestamp + MULT_Tab24[MDFN_lzcount32((GPR[rs] ^ ((int32)GPR[rs] >> 31)) | 0x400)]; - DO_LDS(); - - LO = result; - HI = result >> 32; - - END_OPF; - - // - // MULTU - Multiply Unsigned Word - // - BEGIN_OPF(MULTU); - RTYPE; - - GPR_DEPRES_BEGIN - GPR_DEP(rs); - GPR_DEP(rt); - GPR_DEPRES_END - - uint64 result; - - result = (uint64)GPR[rs] * GPR[rt]; - muldiv_ts_done = timestamp + MULT_Tab24[MDFN_lzcount32(GPR[rs] | 0x400)]; - DO_LDS(); - - LO = result; - HI = result >> 32; - - END_OPF; - - - // - // NOR - NOR - // - BEGIN_OPF(NOR); - RTYPE; - - GPR_DEPRES_BEGIN - GPR_DEP(rs); - GPR_DEP(rt); - GPR_RES(rd); - GPR_DEPRES_END - - uint32 result = ~(GPR[rs] | GPR[rt]); - - DO_LDS(); - - GPR[rd] = result; - - END_OPF; - - // - // OR - OR - // - BEGIN_OPF(OR); - RTYPE; - - GPR_DEPRES_BEGIN - GPR_DEP(rs); - GPR_DEP(rt); - GPR_RES(rd); - GPR_DEPRES_END - - uint32 result = GPR[rs] | GPR[rt]; - - DO_LDS(); - - GPR[rd] = result; - - END_OPF; - - - // - // ORI - OR Immediate - // - BEGIN_OPF(ORI); - ITYPE_ZE; - - GPR_DEPRES_BEGIN - GPR_DEP(rs); - GPR_RES(rt); - GPR_DEPRES_END - - uint32 result = GPR[rs] | immediate; - - DO_LDS(); - - GPR[rt] = result; - - END_OPF; - - - // - // SLL - Shift Word Left Logical - // - BEGIN_OPF(SLL); // SLL - RTYPE; - - GPR_DEPRES_BEGIN - GPR_DEP(rt); - GPR_RES(rd); - GPR_DEPRES_END - - uint32 result = GPR[rt] << shamt; - - DO_LDS(); - - GPR[rd] = result; - - END_OPF; - - - // - // SLLV - Shift Word Left Logical Variable - // - BEGIN_OPF(SLLV); - RTYPE; - - GPR_DEPRES_BEGIN - GPR_DEP(rs); - GPR_DEP(rt); - GPR_RES(rd); - GPR_DEPRES_END - - uint32 result = GPR[rt] << (GPR[rs] & 0x1F); - - DO_LDS(); - - GPR[rd] = result; - - END_OPF; - - // - // SLT - Set on Less Than - // - BEGIN_OPF(SLT); - RTYPE; - - GPR_DEPRES_BEGIN - GPR_DEP(rs); - GPR_DEP(rt); - GPR_RES(rd); - GPR_DEPRES_END - - uint32 result = (bool)((int32)GPR[rs] < (int32)GPR[rt]); - - DO_LDS(); - - GPR[rd] = result; - - END_OPF; - - - // - // SLTI - Set on Less Than Immediate - // - BEGIN_OPF(SLTI); - ITYPE; - - GPR_DEPRES_BEGIN - GPR_DEP(rs); - GPR_RES(rt); - GPR_DEPRES_END - - uint32 result = (bool)((int32)GPR[rs] < (int32)immediate); - - DO_LDS(); - - GPR[rt] = result; - - END_OPF; - - - // - // SLTIU - Set on Less Than Immediate, Unsigned - // - BEGIN_OPF(SLTIU); - ITYPE; - - GPR_DEPRES_BEGIN - GPR_DEP(rs); - GPR_RES(rt); - GPR_DEPRES_END - - uint32 result = (bool)(GPR[rs] < (uint32)immediate); - - DO_LDS(); - - GPR[rt] = result; - - END_OPF; - - - // - // SLTU - Set on Less Than, Unsigned - // - BEGIN_OPF(SLTU); - RTYPE; - - GPR_DEPRES_BEGIN - GPR_DEP(rs); - GPR_DEP(rt); - GPR_RES(rd); - GPR_DEPRES_END - - uint32 result = (bool)(GPR[rs] < GPR[rt]); - - DO_LDS(); - - GPR[rd] = result; - - END_OPF; - - - // - // SRA - Shift Word Right Arithmetic - // - BEGIN_OPF(SRA); - RTYPE; - - GPR_DEPRES_BEGIN - GPR_DEP(rt); - GPR_RES(rd); - GPR_DEPRES_END - - uint32 result = ((int32)GPR[rt]) >> shamt; - - DO_LDS(); - - GPR[rd] = result; - - END_OPF; - - - // - // SRAV - Shift Word Right Arithmetic Variable - // - BEGIN_OPF(SRAV); - RTYPE; - - GPR_DEPRES_BEGIN - GPR_DEP(rs); - GPR_DEP(rt); - GPR_RES(rd); - GPR_DEPRES_END - - uint32 result = ((int32)GPR[rt]) >> (GPR[rs] & 0x1F); - - DO_LDS(); - - GPR[rd] = result; - - END_OPF; - - - // - // SRL - Shift Word Right Logical - // - BEGIN_OPF(SRL); - RTYPE; - - GPR_DEPRES_BEGIN - GPR_DEP(rt); - GPR_RES(rd); - GPR_DEPRES_END - - uint32 result = GPR[rt] >> shamt; - - DO_LDS(); - - GPR[rd] = result; - - END_OPF; - - // - // SRLV - Shift Word Right Logical Variable - // - BEGIN_OPF(SRLV); - RTYPE; - - GPR_DEPRES_BEGIN - GPR_DEP(rs); - GPR_DEP(rt); - GPR_RES(rd); - GPR_DEPRES_END - - uint32 result = GPR[rt] >> (GPR[rs] & 0x1F); - - DO_LDS(); - - GPR[rd] = result; - - END_OPF; - - - // - // SUB - Subtract Word - // - BEGIN_OPF(SUB); - RTYPE; - - GPR_DEPRES_BEGIN - GPR_DEP(rs); - GPR_DEP(rt); - GPR_RES(rd); - GPR_DEPRES_END - - uint32 result = GPR[rs] - GPR[rt]; - bool ep = (((GPR[rs] ^ GPR[rt])) & (GPR[rs] ^ result)) & 0x80000000; - - DO_LDS(); - - if(MDFN_UNLIKELY(ep)) - { - new_PC = Exception(EXCEPTION_OV, PC, new_PC, instr); - } - else - GPR[rd] = result; - - END_OPF; - - - // - // SUBU - Subtract Unsigned Word - // - BEGIN_OPF(SUBU); - RTYPE; - - GPR_DEPRES_BEGIN - GPR_DEP(rs); - GPR_DEP(rt); - GPR_RES(rd); - GPR_DEPRES_END - - uint32 result = GPR[rs] - GPR[rt]; - - DO_LDS(); - - GPR[rd] = result; - - END_OPF; - - - // - // SYSCALL - // - BEGIN_OPF(SYSCALL); - DO_LDS(); - - new_PC = Exception(EXCEPTION_SYSCALL, PC, new_PC, instr); - END_OPF; - - - // - // XOR - // - BEGIN_OPF(XOR); - RTYPE; - - GPR_DEPRES_BEGIN - GPR_DEP(rs); - GPR_DEP(rt); - GPR_RES(rd); - GPR_DEPRES_END - - uint32 result = GPR[rs] ^ GPR[rt]; - - DO_LDS(); - - GPR[rd] = result; - - END_OPF; - - // - // XORI - Exclusive OR Immediate - // - BEGIN_OPF(XORI); - ITYPE_ZE; - - GPR_DEPRES_BEGIN - GPR_DEP(rs); - GPR_RES(rt); - GPR_DEPRES_END - - uint32 result = GPR[rs] ^ immediate; - - DO_LDS(); - - GPR[rt] = result; - END_OPF; - - // - // Memory access instructions(besides the coprocessor ones) follow: - // - - // - // LB - Load Byte - // - BEGIN_OPF(LB); - ITYPE; - - GPR_DEPRES_BEGIN - GPR_DEP(rs); - GPR_DEPRES_END - - uint32 address = GPR[rs] + immediate; - - if(MDFN_UNLIKELY(LDWhich == rt)) - LDWhich = 0; - - DO_LDS(); - - LDWhich = rt; - LDValue = (int32)ReadMemory(timestamp, address); - END_OPF; - - // - // LBU - Load Byte Unsigned - // - BEGIN_OPF(LBU); - ITYPE; - - GPR_DEPRES_BEGIN - GPR_DEP(rs); - GPR_DEPRES_END - - uint32 address = GPR[rs] + immediate; - - if(MDFN_UNLIKELY(LDWhich == rt)) - LDWhich = 0; - - DO_LDS(); - - LDWhich = rt; - LDValue = ReadMemory(timestamp, address); - END_OPF; - - // - // LH - Load Halfword - // - BEGIN_OPF(LH); - ITYPE; - - GPR_DEPRES_BEGIN - GPR_DEP(rs); - GPR_DEPRES_END - - uint32 address = GPR[rs] + immediate; - - if(MDFN_UNLIKELY(address & 1)) - { - DO_LDS(); - - CP0.BADA = address; - new_PC = Exception(EXCEPTION_ADEL, PC, new_PC, instr); - } - else - { - if(MDFN_UNLIKELY(LDWhich == rt)) - LDWhich = 0; - - DO_LDS(); - - LDWhich = rt; - LDValue = (int32)ReadMemory(timestamp, address); - } - END_OPF; - - // - // LHU - Load Halfword Unsigned - // - BEGIN_OPF(LHU); - ITYPE; - - GPR_DEPRES_BEGIN - GPR_DEP(rs); - GPR_DEPRES_END - - uint32 address = GPR[rs] + immediate; - - if(MDFN_UNLIKELY(address & 1)) - { - DO_LDS(); - - CP0.BADA = address; - new_PC = Exception(EXCEPTION_ADEL, PC, new_PC, instr); - } - else - { - if(MDFN_UNLIKELY(LDWhich == rt)) - LDWhich = 0; - - DO_LDS(); - - LDWhich = rt; - LDValue = ReadMemory(timestamp, address); - } - END_OPF; - - - // - // LW - Load Word - // - BEGIN_OPF(LW); - ITYPE; - - GPR_DEPRES_BEGIN - GPR_DEP(rs); - GPR_DEPRES_END - - uint32 address = GPR[rs] + immediate; - - if(MDFN_UNLIKELY(address & 3)) - { - DO_LDS(); - - CP0.BADA = address; - new_PC = Exception(EXCEPTION_ADEL, PC, new_PC, instr); - } - else - { - if(MDFN_UNLIKELY(LDWhich == rt)) - LDWhich = 0; - - DO_LDS(); - - LDWhich = rt; - LDValue = ReadMemory(timestamp, address); - } - END_OPF; - - // - // SB - Store Byte - // - BEGIN_OPF(SB); - ITYPE; - - GPR_DEPRES_BEGIN - GPR_DEP(rs); - GPR_DEP(rt); - GPR_DEPRES_END - - uint32 address = GPR[rs] + immediate; - - WriteMemory(timestamp, address, GPR[rt]); - - DO_LDS(); - END_OPF; - - // - // SH - Store Halfword - // - BEGIN_OPF(SH); - ITYPE; - - GPR_DEPRES_BEGIN - GPR_DEP(rs); - GPR_DEP(rt); - GPR_DEPRES_END - - uint32 address = GPR[rs] + immediate; - - if(MDFN_UNLIKELY(address & 0x1)) - { - CP0.BADA = address; - new_PC = Exception(EXCEPTION_ADES, PC, new_PC, instr); - } - else - WriteMemory(timestamp, address, GPR[rt]); - - DO_LDS(); - END_OPF; - - // - // SW - Store Word - // - BEGIN_OPF(SW); - ITYPE; - - GPR_DEPRES_BEGIN - GPR_DEP(rs); - GPR_DEP(rt); - GPR_DEPRES_END - - uint32 address = GPR[rs] + immediate; - - if(MDFN_UNLIKELY(address & 0x3)) - { - CP0.BADA = address; - new_PC = Exception(EXCEPTION_ADES, PC, new_PC, instr); - } - else - WriteMemory(timestamp, address, GPR[rt]); - - DO_LDS(); - END_OPF; - - // LWL and LWR load delay slot tomfoolery appears to apply even to MFC0! (and probably MFCn and CFCn as well, though they weren't explicitly tested) - - // - // LWL - Load Word Left - // - BEGIN_OPF(LWL); - ITYPE; - - GPR_DEPRES_BEGIN - GPR_DEP(rs); - //GPR_DEP(rt); - GPR_DEPRES_END - - uint32 address = GPR[rs] + immediate; - uint32 v = GPR[rt]; - - if(LDWhich == rt) - { - v = LDValue; - ReadFudge = 0; - } - else - { - DO_LDS(); - } - - LDWhich = rt; - switch(address & 0x3) - { - case 0: LDValue = (v & ~(0xFF << 24)) | (ReadMemory(timestamp, address & ~3) << 24); - break; - - case 1: LDValue = (v & ~(0xFFFF << 16)) | (ReadMemory(timestamp, address & ~3) << 16); - break; - - case 2: LDValue = (v & ~(0xFFFFFF << 8)) | (ReadMemory(timestamp, address & ~3, true) << 8); - break; - - case 3: LDValue = (v & ~(0xFFFFFFFF << 0)) | (ReadMemory(timestamp, address & ~3) << 0); - break; - } - END_OPF; - - // - // SWL - Store Word Left - // - BEGIN_OPF(SWL); - ITYPE; - - GPR_DEPRES_BEGIN - GPR_DEP(rs); - GPR_DEP(rt); - GPR_DEPRES_END - - uint32 address = GPR[rs] + immediate; - - switch(address & 0x3) - { - case 0: WriteMemory(timestamp, address & ~3, GPR[rt] >> 24); - break; - - case 1: WriteMemory(timestamp, address & ~3, GPR[rt] >> 16); - break; - - case 2: WriteMemory(timestamp, address & ~3, GPR[rt] >> 8, true); - break; - - case 3: WriteMemory(timestamp, address & ~3, GPR[rt] >> 0); - break; - } - DO_LDS(); - - END_OPF; - - // - // LWR - Load Word Right - // - BEGIN_OPF(LWR); - ITYPE; - - GPR_DEPRES_BEGIN - GPR_DEP(rs); - //GPR_DEP(rt); - GPR_DEPRES_END - - uint32 address = GPR[rs] + immediate; - uint32 v = GPR[rt]; - - if(LDWhich == rt) - { - v = LDValue; - ReadFudge = 0; - } - else - { - DO_LDS(); - } - - LDWhich = rt; - switch(address & 0x3) - { - case 0: LDValue = (v & ~(0xFFFFFFFF)) | ReadMemory(timestamp, address); - break; - - case 1: LDValue = (v & ~(0xFFFFFF)) | ReadMemory(timestamp, address, true); - break; - - case 2: LDValue = (v & ~(0xFFFF)) | ReadMemory(timestamp, address); - break; - - case 3: LDValue = (v & ~(0xFF)) | ReadMemory(timestamp, address); - break; - } - END_OPF; - - // - // SWR - Store Word Right - // - BEGIN_OPF(SWR); - ITYPE; - - GPR_DEPRES_BEGIN - GPR_DEP(rs); - GPR_DEP(rt); - GPR_DEPRES_END - - uint32 address = GPR[rs] + immediate; - - switch(address & 0x3) - { - case 0: WriteMemory(timestamp, address, GPR[rt]); - break; - - case 1: WriteMemory(timestamp, address, GPR[rt], true); - break; - - case 2: WriteMemory(timestamp, address, GPR[rt]); - break; - - case 3: WriteMemory(timestamp, address, GPR[rt]); - break; - } - - DO_LDS(); - - END_OPF; - - // - // Mednafen special instruction - // - BEGIN_OPF(INTERRUPT); - if(Halted) - { - goto SkipNPCStuff; - } - else - { - DO_LDS(); - - new_PC = Exception(EXCEPTION_INT, PC, new_PC, instr); - } - END_OPF; - } - - OpDone: ; - PC = new_PC; - new_PC = new_PC + 4; - BDBT = 0; - - SkipNPCStuff: ; - - //printf("\n"); - } - } while(MDFN_LIKELY(PSX_EventHandler(timestamp))); - - if(gte_ts_done > 0) - gte_ts_done -= timestamp; - - if(muldiv_ts_done > 0) - muldiv_ts_done -= timestamp; - - ACTIVE_TO_BACKING; - - return(timestamp); -} - -pscpu_timestamp_t PS_CPU::Run(pscpu_timestamp_t timestamp_in, bool BIOSPrintMode, bool ILHMode) -{ - if(CPUHook || ADDBT) - return(RunReal(timestamp_in)); - else - { - if(ILHMode) - return(RunReal(timestamp_in)); - else - { - if(BIOSPrintMode) - return(RunReal(timestamp_in)); - else - return(RunReal(timestamp_in)); - } - } -} - -void PS_CPU::SetCPUHook(void (*cpuh)(const pscpu_timestamp_t timestamp, uint32 pc), void (*addbt)(uint32 from, uint32 to, bool exception)) -{ - ADDBT = addbt; - CPUHook = cpuh; -} - -uint32 PS_CPU::GetRegister(unsigned int which, char *special, const uint32 special_len) -{ - uint32 ret = 0; - - if(which >= GSREG_GPR && which < (GSREG_GPR + 32)) - ret = GPR[which]; - else switch(which) - { - case GSREG_PC: - ret = BACKED_PC; - break; - - case GSREG_PC_NEXT: - ret = BACKED_new_PC; - break; - - case GSREG_IN_BD_SLOT: - ret = BDBT; - break; - - case GSREG_LO: - ret = LO; - break; - - case GSREG_HI: - ret = HI; - break; - - case GSREG_BPC: - ret = CP0.BPC; - break; - - case GSREG_BDA: - ret = CP0.BDA; - break; - - case GSREG_TAR: - ret = CP0.TAR; - break; - - case GSREG_DCIC: - ret = CP0.DCIC; - break; - - case GSREG_BADA: - ret = CP0.BADA; - break; - - case GSREG_BDAM: - ret = CP0.BDAM; - break; - - case GSREG_BPCM: - ret = CP0.BPCM; - break; - - case GSREG_SR: - ret = CP0.SR; - break; - - case GSREG_CAUSE: - ret = CP0.CAUSE; - if(special) - { - snprintf(special, special_len, "BD: %u, BT: %u, CE: %u, IP: 0x%02x, Sw: %u, ExcCode: 0x%01x", - (ret >> 31) & 1, (ret >> 30) & 1, (ret >> 28) & 3, (ret >> 10) & 0x3F, (ret >> 8) & 3, (ret >> 2) & 0xF); - } - break; - - case GSREG_EPC: - ret = CP0.EPC; - break; - - } - - return(ret); -} - -void PS_CPU::SetRegister(unsigned int which, uint32 value) -{ - if(which >= GSREG_GPR && which < (GSREG_GPR + 32)) - { - if(which != (GSREG_GPR + 0)) - GPR[which] = value; - } - else switch(which) - { - case GSREG_PC: - BACKED_PC = value; - break; - - case GSREG_PC_NEXT: - BACKED_new_PC = value; - break; - - case GSREG_IN_BD_SLOT: - BDBT = value & 0x3; - break; - - case GSREG_LO: - LO = value; - break; - - case GSREG_HI: - HI = value; - break; - - case GSREG_SR: - CP0.SR = value; // TODO: mask - break; - - case GSREG_CAUSE: - CP0.CAUSE = value; - break; - - case GSREG_EPC: - CP0.EPC = value & ~0x3U; - break; - - - } -} - -bool PS_CPU::PeekCheckICache(uint32 PC, uint32 *iw) -{ - if(ICache[(PC & 0xFFC) >> 2].TV == PC) - { - *iw = ICache[(PC & 0xFFC) >> 2].Data; - return(true); - } - - return(false); -} - - -uint8 PS_CPU::PeekMem8(uint32 A) -{ - return PeekMemory(A); -} - -uint16 PS_CPU::PeekMem16(uint32 A) -{ - return PeekMemory(A); -} - -uint32 PS_CPU::PeekMem32(uint32 A) -{ - return PeekMemory(A); -} - -void PS_CPU::PokeMem8(uint32 A, uint8 V) -{ - PokeMemory(A, V); -} - -void PS_CPU::PokeMem16(uint32 A, uint16 V) -{ - PokeMemory(A, V); -} - -void PS_CPU::PokeMem32(uint32 A, uint32 V) -{ - PokeMemory(A, V); -} - -#undef BEGIN_OPF -#undef END_OPF -#undef MK_OPF - -#define MK_OPF(op, funct) ((op) ? (0x40 | (op)) : (funct)) -#define BEGIN_OPF(op, funct) case MK_OPF(op, funct): { -#define END_OPF } break; - -// FIXME: should we breakpoint on an illegal address? And with LWC2/SWC2 if CP2 isn't enabled? -void PS_CPU::CheckBreakpoints(void (*callback)(bool write, uint32 address, unsigned int len), uint32 instr) -{ - uint32 opf; - - opf = instr & 0x3F; - - if(instr & (0x3F << 26)) - opf = 0x40 | (instr >> 26); - - - switch(opf) - { - default: - break; - - // - // LB - Load Byte - // - BEGIN_OPF(0x20, 0); - ITYPE; - uint32 address = GPR[rs] + immediate; - - callback(false, address, 1); - END_OPF; - - // - // LBU - Load Byte Unsigned - // - BEGIN_OPF(0x24, 0); - ITYPE; - uint32 address = GPR[rs] + immediate; - - callback(false, address, 1); - END_OPF; - - // - // LH - Load Halfword - // - BEGIN_OPF(0x21, 0); - ITYPE; - uint32 address = GPR[rs] + immediate; - - callback(false, address, 2); - END_OPF; - - // - // LHU - Load Halfword Unsigned - // - BEGIN_OPF(0x25, 0); - ITYPE; - uint32 address = GPR[rs] + immediate; - - callback(false, address, 2); - END_OPF; - - - // - // LW - Load Word - // - BEGIN_OPF(0x23, 0); - ITYPE; - uint32 address = GPR[rs] + immediate; - - callback(false, address, 4); - END_OPF; - - // - // SB - Store Byte - // - BEGIN_OPF(0x28, 0); - ITYPE; - uint32 address = GPR[rs] + immediate; - - callback(true, address, 1); - END_OPF; - - // - // SH - Store Halfword - // - BEGIN_OPF(0x29, 0); - ITYPE; - uint32 address = GPR[rs] + immediate; - - callback(true, address, 2); - END_OPF; - - // - // SW - Store Word - // - BEGIN_OPF(0x2B, 0); - ITYPE; - uint32 address = GPR[rs] + immediate; - - callback(true, address, 4); - END_OPF; - - // - // LWL - Load Word Left - // - BEGIN_OPF(0x22, 0); - ITYPE; - uint32 address = GPR[rs] + immediate; - - do - { - callback(false, address, 1); - } while((address--) & 0x3); - - END_OPF; - - // - // SWL - Store Word Left - // - BEGIN_OPF(0x2A, 0); - ITYPE; - uint32 address = GPR[rs] + immediate; - - do - { - callback(true, address, 1); - } while((address--) & 0x3); - - END_OPF; - - // - // LWR - Load Word Right - // - BEGIN_OPF(0x26, 0); - ITYPE; - uint32 address = GPR[rs] + immediate; - - do - { - callback(false, address, 1); - } while((++address) & 0x3); - - END_OPF; - - // - // SWR - Store Word Right - // - BEGIN_OPF(0x2E, 0); - ITYPE; - uint32 address = GPR[rs] + immediate; - - do - { - callback(true, address, 1); - } while((++address) & 0x3); - - END_OPF; - - // - // LWC2 - // - BEGIN_OPF(0x32, 0); - ITYPE; - uint32 address = GPR[rs] + immediate; - - callback(false, address, 4); - END_OPF; - - // - // SWC2 - // - BEGIN_OPF(0x3A, 0); - ITYPE; - uint32 address = GPR[rs] + immediate; - - callback(true, address, 4); - END_OPF; - - } -} - - - -SYNCFUNC(PS_CPU) -{ - NSS(GPR); - NSS(LO); - NSS(HI); - NSS(BACKED_PC); - NSS(BACKED_new_PC); - NSS(BDBT); - - NSS(IPCache); - NSS(Halted); - - NSS(BACKED_LDWhich); - NSS(BACKED_LDValue); - NSS(LDAbsorb); - - NSS(next_event_ts); - NSS(gte_ts_done); - NSS(muldiv_ts_done); - - NSS(BIU); - NSS(ICache_Bulk); - - NSS(CP0.Regs); - - NSS(ReadAbsorb); - NSS(ReadAbsorbWhich); - NSS(ReadFudge); - - NSS(ScratchRAM.data8); - - if(isReader) - { - ReadAbsorbWhich &= 0x1F; - BACKED_LDWhich %= 0x21; - } - -} //SYNCFUNC(CPU) - -} //namespace MDFN_IEN_PSX diff --git a/psx/octoshock/psx/cpu.h b/psx/octoshock/psx/cpu.h deleted file mode 100644 index fc6cb5b3aca..00000000000 --- a/psx/octoshock/psx/cpu.h +++ /dev/null @@ -1,284 +0,0 @@ -/******************************************************************************/ -/* Mednafen Sony PS1 Emulation Module */ -/******************************************************************************/ -/* cpu.h: -** Copyright (C) 2011-2016 Mednafen Team -** -** 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., -** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef __MDFN_PSX_CPU_H -#define __MDFN_PSX_CPU_H - -/* - Load delay notes: - - // Takes 1 less - ".set noreorder\n\t" - ".set nomacro\n\t" - "lw %0, 0(%2)\n\t" - "nop\n\t" - "nop\n\t" - "or %0, %1, %1\n\t" - - // cycle than this: - ".set noreorder\n\t" - ".set nomacro\n\t" - "lw %0, 0(%2)\n\t" - "nop\n\t" - "or %0, %1, %1\n\t" - "nop\n\t" - - - // Both of these - ".set noreorder\n\t" - ".set nomacro\n\t" - "lw %0, 0(%2)\n\t" - "nop\n\t" - "nop\n\t" - "or %1, %0, %0\n\t" - - // take same...(which is kind of odd). - ".set noreorder\n\t" - ".set nomacro\n\t" - "lw %0, 0(%2)\n\t" - "nop\n\t" - "or %1, %0, %0\n\t" - "nop\n\t" -*/ - -#include "gte.h" - -namespace MDFN_IEN_PSX -{ - -class PS_CPU -{ - public: - - PS_CPU() MDFN_COLD; - ~PS_CPU() MDFN_COLD; - - templatevoid SyncState(EW::NewState *ns); - // FAST_MAP_* enums are in BYTES(8-bit), not in 32-bit units("words" in MIPS context), but the sizes - // will always be multiples of 4. - enum { FAST_MAP_SHIFT = 16 }; - enum { FAST_MAP_PSIZE = 1 << FAST_MAP_SHIFT }; - - void SetFastMap(void *region_mem, uint32 region_address, uint32 region_size); - - INLINE void SetEventNT(const pscpu_timestamp_t next_event_ts_arg) - { - next_event_ts = next_event_ts_arg; - } - - pscpu_timestamp_t Run(pscpu_timestamp_t timestamp_in, bool BIOSPrintMode, bool ILHMode); - - void Power(void) MDFN_COLD; - - // which ranges 0-5, inclusive - void AssertIRQ(unsigned which, bool asserted); - - void SetHalt(bool status); - - // TODO eventually: factor BIU address decoding directly in the CPU core somehow without hurting speed. - void SetBIU(uint32 val); - uint32 GetBIU(void); - - - - private: - - uint32 GPR[32 + 1]; // GPR[32] Used as dummy in load delay simulation(indexing past the end of real GPR) - - uint32 LO; - uint32 HI; - - - uint32 BACKED_PC; - uint32 BACKED_new_PC; - - uint32 IPCache; - uint8 BDBT; - - uint8 ReadAbsorb[0x20 + 1]; - uint8 ReadAbsorbWhich; - uint8 ReadFudge; - - void RecalcIPCache(void); - bool Halted; - - uint32 BACKED_LDWhich; - uint32 BACKED_LDValue; - uint32 LDAbsorb; - - pscpu_timestamp_t next_event_ts; - pscpu_timestamp_t gte_ts_done; - pscpu_timestamp_t muldiv_ts_done; - - uint32 BIU; - - const uint32 addr_mask[8] = { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x7FFFFFFF, 0x1FFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF }; - - enum - { - CP0REG_BPC = 3, // PC breakpoint address. - CP0REG_BDA = 5, // Data load/store breakpoint address. - CP0REG_TAR = 6, // Target address(???) - CP0REG_DCIC = 7, // Cache control - CP0REG_BADA = 8, - CP0REG_BDAM = 9, // Data load/store address mask. - CP0REG_BPCM = 11, // PC breakpoint address mask. - CP0REG_SR = 12, - CP0REG_CAUSE = 13, - CP0REG_EPC = 14, - CP0REG_PRID = 15 // Product ID - }; - - struct - { - union - { - uint32 Regs[32]; - struct - { - uint32 Unused00; - uint32 Unused01; - uint32 Unused02; - uint32 BPC; // RW - uint32 Unused04; - uint32 BDA; // RW - uint32 TAR; // R - uint32 DCIC; // RW - uint32 BADA; // R - uint32 BDAM; // R/W - uint32 Unused0A; - uint32 BPCM; // R/W - uint32 SR; // R/W - uint32 CAUSE; // R/W(partial) - uint32 EPC; // R - uint32 PRID; // R - }; - }; - } CP0; - - uint8 MULT_Tab24[24]; - - struct __ICache - { - /* - TV: - Mask 0x00000001: 0x0 = icache enabled((BIU & 0x800) == 0x800), 0x1 = icache disabled(changed in bulk on BIU value changes; preserve everywhere else!) - Mask 0x00000002: 0x0 = valid, 0x2 = invalid - Mask 0x00000FFC: Always 0 - Mask 0xFFFFF000: Tag. - */ - uint32 TV; - uint32 Data; - }; - - union - { - __ICache ICache[1024]; - uint32 ICache_Bulk[2048]; - }; - - MultiAccessSizeMem<1024, false> ScratchRAM; - - //PS_GTE GTE; - - uintptr_t FastMap[1 << (32 - FAST_MAP_SHIFT)]; - uint8 DummyPage[FAST_MAP_PSIZE]; - - enum - { - EXCEPTION_INT = 0, - EXCEPTION_MOD = 1, - EXCEPTION_TLBL = 2, - EXCEPTION_TLBS = 3, - EXCEPTION_ADEL = 4, // Address error on load - EXCEPTION_ADES = 5, // Address error on store - EXCEPTION_IBE = 6, // Instruction bus error - EXCEPTION_DBE = 7, // Data bus error - EXCEPTION_SYSCALL = 8, // System call - EXCEPTION_BP = 9, // Breakpoint - EXCEPTION_RI = 10, // Reserved instruction - EXCEPTION_COPU = 11, // Coprocessor unusable - EXCEPTION_OV = 12 // Arithmetic overflow - }; - - uint32 Exception(uint32 code, uint32 PC, const uint32 NP, const uint32 instr) MDFN_WARN_UNUSED_RESULT; - - template NO_INLINE pscpu_timestamp_t RunReal(pscpu_timestamp_t timestamp_in) NO_INLINE; - - template T PeekMemory(uint32 address) MDFN_COLD; - template void PokeMemory(uint32 address, T value) MDFN_COLD; - template T ReadMemory(pscpu_timestamp_t ×tamp, uint32 address, bool DS24 = false, bool LWC_timing = false); - template void WriteMemory(pscpu_timestamp_t ×tamp, uint32 address, uint32 value, bool DS24 = false); - - uint32 ReadInstruction(pscpu_timestamp_t ×tamp, uint32 address); - - // - // Mednafen debugger stuff follows: - // - public: - void SetCPUHook(void (*cpuh)(const pscpu_timestamp_t timestamp, uint32 pc), void (*addbt)(uint32 from, uint32 to, bool exception)); - void CheckBreakpoints(void (*callback)(bool write, uint32 address, unsigned int len), uint32 instr); - void* debug_GetScratchRAMPtr() { return ScratchRAM.data8; } - void* debug_GetGPRPtr() { return GPR; } - - enum - { - GSREG_GPR = 0, - GSREG_PC = 32, - GSREG_PC_NEXT, - GSREG_IN_BD_SLOT, - GSREG_LO, - GSREG_HI, - // - // - GSREG_BPC, - GSREG_BDA, - GSREG_TAR, - GSREG_DCIC, - GSREG_BADA, - GSREG_BDAM, - GSREG_BPCM, - GSREG_SR, - GSREG_CAUSE, - GSREG_EPC - }; - - uint32 GetRegister(unsigned int which, char *special, const uint32 special_len); - void SetRegister(unsigned int which, uint32 value); - bool PeekCheckICache(uint32 PC, uint32 *iw); - - - uint8 PeekMem8(uint32 A); - uint16 PeekMem16(uint32 A); - uint32 PeekMem32(uint32 A); - - void PokeMem8(uint32 A, uint8 V); - void PokeMem16(uint32 A, uint16 V); - void PokeMem32(uint32 A, uint32 V); - - private: - void (*CPUHook)(const pscpu_timestamp_t timestamp, uint32 pc); - void (*ADDBT)(uint32 from, uint32 to, bool exception); -}; - -} - -#endif diff --git a/psx/octoshock/psx/debug.h b/psx/octoshock/psx/debug.h deleted file mode 100644 index 9751a4d45ee..00000000000 --- a/psx/octoshock/psx/debug.h +++ /dev/null @@ -1,42 +0,0 @@ -/******************************************************************************/ -/* Mednafen Sony PS1 Emulation Module */ -/******************************************************************************/ -/* debug.h: -** Copyright (C) 2011-2016 Mednafen Team -** -** 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., -** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef __MDFN_PSX_DEBUG_H -#define __MDFN_PSX_DEBUG_H - -#ifdef WANT_DEBUGGER - -namespace MDFN_IEN_PSX -{ - -MDFN_HIDE extern DebuggerInfoStruct PSX_DBGInfo; - -bool DBG_Init(void) MDFN_COLD; - -void DBG_Break(void); - -void DBG_GPUScanlineHook(unsigned scanline); - -} - -#endif - -#endif diff --git a/psx/octoshock/psx/dis.cpp b/psx/octoshock/psx/dis.cpp deleted file mode 100644 index 77a8711b788..00000000000 --- a/psx/octoshock/psx/dis.cpp +++ /dev/null @@ -1,519 +0,0 @@ -/******************************************************************************/ -/* Mednafen Sony PS1 Emulation Module */ -/******************************************************************************/ -/* dis.cpp: -** Copyright (C) 2011-2017 Mednafen Team -** -** 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., -** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include -#include - -#include "psx.h" - -//NOTE - this class was hand-crafted for octoshock. it wasn't tested very well, but its a little more tricksy than i'd like -class BufferAppender -{ -public: - BufferAppender(void* _buf, size_t _buflen) - : buf((char*)_buf) - , buflen(_buflen) - , ofs(0) - , overflow(false) - { - } - - void append(const char* str) - { - for(;;) - { - char c = *str++; - if(c == 0) break; - append(1,c); - } - } - - void append(size_t n, char c) - { - size_t remain = buflen-ofs; - if(remain==0) return; - size_t todo = n; - if(todo > remain) - todo = remain; - for(size_t i=0; i0) - { - va_list ap; - va_start(ap,fmt); - int done = vsnprintf(buf,remain,fmt,ap); - va_end(ap); - - if(done>=0) - { - ofs += done; - } - } - //make sure we stay null terminated, because msvc _snprintf is a piece of shit and can fill our buffer completely, among other flaws - terminate(); - } - - size_t size() const - { - return ofs; - } - - void clear() - { - ofs = 0; - overflow = false; - } - - void print() const - { - printf(buf); - } - - bool isOverflow() const { return overflow; } - -private: - char* buf; - size_t buflen; - size_t ofs; - bool overflow; - - void terminate() - { - if(ofs> 21) & 0x1F; - unsigned int rt = (instr >> 16) & 0x1F; - unsigned int rd = (instr >> 11) & 0x1F; - unsigned int shamt = (instr >> 6) & 0x1F; - unsigned int immediate = (int32)(int16)(instr & 0xFFFF); - unsigned int immediate_ze = (instr & 0xFFFF); - unsigned int jt = instr & ((1 << 26) - 1); - - static const char *gpr_names[32] = - { - "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3", "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", - "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", "t8", "t9", "k0", "k1", "gp", "sp", "fp", "ra" - }; - - static const char *cop0_names[32] = - { - "CPR0", "CPR1", "CPR2", "BPC", "CPR4", "BDA", "TAR", "DCIC", "BADA", "BDAM", "CPR10", "BPCM", "SR", "CAUSE", "EPC", "PRID", - "CPR16", "CPR17", "CPR18", "CPR19", "CPR20", "CPR21", "CPR22", "CPR23", "CPR24", "CPR25", "CPR26", "CPR27", "CPR28", "CPR29", "CPR30", "CPR31" - }; - - static const char *gte_cr_names[32] = - { - "R11R12", "R13R21", "R22R23", "R31R32", "R33", "TRX", "TRY", "TRZ", "L11L12", "L13L21", "L22L23", "L31L32", "L33", "RBK", "GBK", "BBK", - "LR1LR2", "LR3LG1", "LG2LG3", "LB1LB2", "LB3", "RFC", "GFC", "BFC", "OFX", "OFY", "H", "DQA", "DQB", "ZSF3", "ZSF4", "FLAG" - }; - - static const char *gte_dr_names[32] = - { - "VXY0", "VZ0", "VXY1", "VZ1", "VXY2", "VZ2", "RGB", "OTZ", "IR0", "IR1", "IR2", "IR3", "SXY0", "SXY1", "SXY2", "SXYP", - "SZ0", "SZ1", "SZ2", "SZ3", "RGB0", "RGB1", "RGB2", "RES1", "MAC0", "MAC1", "MAC2", "MAC3", "IRGB", "ORGB", "LZCS", "LZCR" - }; - - const OpEntry *op = ops; - - while(op->mnemonic) - { - if((instr & op->mask) == op->value) - { - // a = shift amount - // s = rs - // t = rt - // d = rd - // i = immediate - // z = immediate, zero-extended - // p = PC + 4 + immediate - // P = ((PC + 4) & 0xF0000000) | (26bitval << 2) - // - // 0 = rd(cop0 registers) - // c = rd(copz data registers) - // C = rd(copz control registers) - // g = rd(GTE data registers) - // G = rd(GTE control registers) - // h = rt(GTE data registers) - - char s_a[16]; - char s_i[16]; - char s_z[16]; - char s_p[16]; - char s_P[16]; - char s_c[16]; - char s_C[16]; - - //--------------------- - //TODO - this section only as needed (mask in opcode?) - snprintf(s_a, sizeof(s_a), "%d", shamt); - - if(immediate < 0) - snprintf(s_i, sizeof(s_i), "%d", immediate); - else - snprintf(s_i, sizeof(s_i), "0x%04x", (uint32)immediate); - - snprintf(s_z, sizeof(s_z), "0x%04x", immediate_ze); - - snprintf(s_p, sizeof(s_p), "0x%08x", PC + 4 + (immediate << 2)); - - snprintf(s_P, sizeof(s_P), "0x%08x", ((PC + 4) & 0xF0000000) | (jt << 2)); - - snprintf(s_c, sizeof(s_c), "CPR%d", rd); - snprintf(s_C, sizeof(s_C), "CCR%d", rd); - //---------------------- - - ret.clear(); - ret.append(op->mnemonic); - ret.append(10 - ret.size(), ' '); - - for(unsigned int i = 0; i < strlen(op->format); i++) - { - switch(op->format[i]) - { - case '#': - // sf mx v cv lm - { - char as[16]; - - as[0] = 0; - if(!strncmp(&op->format[i], "#sf#", 4)) - { - i += 3; - snprintf(as, 16, "sf=%d", (int)(bool)(instr & (1 << 19))); - } - else if(!strncmp(&op->format[i], "#mx#", 4)) - { - i += 3; - snprintf(as, 16, "mx=%d", (instr >> 17) & 0x3); - } - else if(!strncmp(&op->format[i], "#v#", 3)) - { - i += 2; - snprintf(as, 16, "v=%d", (instr >> 15) & 0x3); - } - else if(!strncmp(&op->format[i], "#cv#", 4)) - { - i += 3; - snprintf(as, 16, "cv=%d", (instr >> 13) & 0x3); - } - else if(!strncmp(&op->format[i], "#lm#", 4)) - { - i += 3; - snprintf(as, 16, "lm=%d", (int)(bool)(instr & (1 << 10))); - } - ret.append(as); - } - break; - case 'F': - { - char s_F[16]; - - snprintf(s_F, 16, "0x%07x", instr & 0x1FFFFFF); - ret.append(s_F); - } - break; - - case 'h': - ret.append(gte_dr_names[rt]); - break; - - case 'g': - ret.append(gte_dr_names[rd]); - break; - - case 'G': - ret.append(gte_cr_names[rd]); - break; - - case '0': - ret.append(cop0_names[rd]); - break; - - case 'c': - ret.append(s_c); - break; - - case 'C': - ret.append(s_C); - break; - - case 'a': - ret.append(s_a); - break; - - case 'i': - ret.append(s_i); - break; - - case 'z': - ret.append(s_z); - break; - - case 'p': - ret.append(s_p); - break; - - case 'P': - ret.append(s_P); - break; - - case 's': - ret.append(gpr_names[rs]); - break; - - case 't': - ret.append(gpr_names[rt]); - break; - - case 'd': - ret.append(gpr_names[rd]); - break; - - default: - ret.append(1, op->format[i]); - break; - } - } - break; - } - op++; - } - - if(ret.isOverflow()) - return SHOCK_OVERFLOW; - else return SHOCK_OK; -} - - diff --git a/psx/octoshock/psx/dis.h b/psx/octoshock/psx/dis.h deleted file mode 100644 index 12670706f6e..00000000000 --- a/psx/octoshock/psx/dis.h +++ /dev/null @@ -1,24 +0,0 @@ -/******************************************************************************/ -/* Mednafen Sony PS1 Emulation Module */ -/******************************************************************************/ -/* dis.h: -** Copyright (C) 2011-2016 Mednafen Team -** -** 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., -** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#pragma once - -EW_EXPORT s32 shock_Util_DisassembleMIPS(u32 PC, u32 instr, void* outbuf, s32 buflen); diff --git a/psx/octoshock/psx/dma.cpp b/psx/octoshock/psx/dma.cpp deleted file mode 100644 index 13eb05cabbf..00000000000 --- a/psx/octoshock/psx/dma.cpp +++ /dev/null @@ -1,774 +0,0 @@ -/******************************************************************************/ -/* Mednafen Sony PS1 Emulation Module */ -/******************************************************************************/ -/* dma.cpp: -** Copyright (C) 2011-2016 Mednafen Team -** -** 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., -** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "psx.h" -#include "mdec.h" -#include "cdc.h" -#include "spu.h" - -/* Notes: - - Channel 4(SPU): - Write: - Doesn't seem to work properly with CHCR=0x01000001 - Hung when CHCR=0x11000601 - - Channel 6: - DMA hangs if D28 of CHCR is 0? - D1 did not have an apparent effect. - -*/ - -enum -{ - CH_MDEC_IN = 0, - CH_MDEC_OUT = 1, - CH_GPU = 2, - CH_CDC = 3, - CH_SPU = 4, - CH_FIVE = 5, - CH_OT = 6, -}; - -extern bool GpuFrameForLag; - -// RunChannels(128 - whatevercounter); -// -// GPU next event, std::max<128, wait_time>, or something similar, for handling FIFO. - -namespace MDFN_IEN_PSX -{ - -static int32 DMACycleCounter; - -static uint32 DMAControl; -static uint32 DMAIntControl; -static uint8 DMAIntStatus; -static bool IRQOut; - -struct Channel -{ - uint32 BaseAddr; - uint32 BlockControl; - uint32 ChanControl; - - // - // - // - uint32 CurAddr; - uint16 WordCounter; - - // - // - int32 ClockCounter; -}; - -static Channel DMACH[7]; -static pscpu_timestamp_t lastts; - - -// static const char *PrettyChannelNames[7] = { "MDEC IN", "MDEC OUT", "GPU", "CDC", "SPU", "PIO", "OTC" }; - -void DMA_Init(void) -{ - -} - -void DMA_Kill(void) -{ - -} - -static INLINE void RecalcIRQOut(void) -{ - bool irqo; - - irqo = (bool)DMAIntStatus; - irqo &= (DMAIntControl >> 23) & 1; - irqo |= (DMAIntControl >> 15) & 1; - - IRQOut = irqo; - IRQ_Assert(IRQ_DMA, irqo); -} - -void DMA_ResetTS(void) -{ - lastts = 0; -} - -void DMA_Power(void) -{ - lastts = 0; - - memset(DMACH, 0, sizeof(DMACH)); - - DMACycleCounter = 128; - - DMAControl = 0; - DMAIntControl = 0; - DMAIntStatus = 0; - RecalcIRQOut(); -} - -static INLINE bool ChCan(const unsigned ch, const uint32 CRModeCache) -{ - switch(ch) - { - default: - abort(); - - case CH_MDEC_IN: - return(MDEC_DMACanWrite()); - - case CH_MDEC_OUT: - return(MDEC_DMACanRead()); - - case CH_GPU: - if(CRModeCache & 0x1) - return(GPU_DMACanWrite()); - else - return(true); - - case CH_CDC: - return(true); - - case CH_SPU: - return(true); - - case CH_FIVE: - return(false); - - case CH_OT: - return((bool)(DMACH[ch].ChanControl & (1U << 28))); - } -} - -static void RecalcHalt(void) -{ - bool Halt = false; - unsigned ch = 0; - - for(ch = 0; ch < 7; ch++) - { - if(DMACH[ch].ChanControl & (1U << 24)) - { - if(!(DMACH[ch].ChanControl & (7U << 8))) - { - if(DMACH[ch].WordCounter > 0) - { - Halt = true; - break; - } - } - -#if 0 - if(DMACH[ch].ChanControl & 0x100) // DMA doesn't hog the bus when this bit is set, though the DMA takes longer. - continue; - - if(ch == 4 || ch == 5) // Not sure if these channels will typically hog the bus or not...investigate. - continue; - - if(!(DMACH[ch].ChanControl & (1U << 10))) // Not sure about HOGGERYNESS with linked-list mode, and it likely wouldn't work well either in regards - // to GPU commands due to the rather large DMA update granularity. - { - if((DMACH[ch].WordCounter > 0) || ChCan(ch, DMACH[ch].ChanControl & 0x1)) - { - Halt = true; - break; - } - } -#endif - } - } - -#if 0 - if((DMACH[0].WordCounter || (DMACH[0].ChanControl & (1 << 24))) && (DMACH[0].ChanControl & 0x200) /*&& MDEC_DMACanWrite()*/) - Halt = true; - - if((DMACH[1].WordCounter || (DMACH[1].ChanControl & (1 << 24))) && (DMACH[1].ChanControl & 0x200) && (DMACH[1].WordCounter || MDEC_DMACanRead())) - Halt = true; - - if((DMACH[2].WordCounter || (DMACH[2].ChanControl & (1 << 24))) && (DMACH[2].ChanControl & 0x200) && ((DMACH[2].ChanControl & 0x1) && (DMACH[2].WordCounter || GPU_DMACanWrite()))) - Halt = true; - - if((DMACH[3].WordCounter || (DMACH[3].ChanControl & (1 << 24))) && !(DMACH[3].ChanControl & 0x100)) - Halt = true; - - if(DMACH[6].WordCounter || (DMACH[6].ChanControl & (1 << 24))) - Halt = true; -#endif - - //printf("Halt: %d\n", Halt); - - if(!Halt && (DMACH[2].ChanControl & (1U << 24)) && ((DMACH[2].ChanControl & 0x700) == 0x200) && ChCan(2, DMACH[2].ChanControl)) - { - unsigned tmp = DMACH[2].BlockControl & 0xFFFF; - - if(tmp > 0) - tmp--; - - PSX_SetDMACycleSteal(tmp); - } - else - PSX_SetDMACycleSteal(0); - - CPU->SetHalt(Halt); -} - - -static INLINE void ChRW(const unsigned ch, const uint32 CRModeCache, uint32 *V, uint32 *offset) -{ - unsigned extra_cyc_overhead = 0; - - switch(ch) - { - default: - abort(); - break; - - case CH_MDEC_IN: - if(CRModeCache & 0x1) - MDEC_DMAWrite(*V); - else - *V = 0; - break; - - case CH_MDEC_OUT: - if(CRModeCache & 0x1) - { - } - else - *V = MDEC_DMARead(offset); - break; - - case CH_GPU: - if(CRModeCache & 0x1) - GPU_WriteDMA(*V); - else - *V = GPU_ReadDMA(); - break; - - case CH_CDC: - // 0x1f801018 affects CDC DMA timing. -#if 0 - if(CRModeCache & 0x100) // For CDC DMA(at least): When this bit is set, DMA controller doesn't appear to hog the (RAM?) bus. - { - if(CRModeCache & 0x00400000) // For CDC DMA(at least): When this bit is set, DMA controller appears to get even less bus time(or has a lower priority??) - { - DMACH[ch].ClockCounter -= 44 * 20 / 12; - } - else - { - DMACH[ch].ClockCounter -= 29 * 20 / 12; - } - } - else - { - DMACH[ch].ClockCounter -= 23 * 20 / 12; // (23 + 1) = 24. (Though closer to 24.5 or 24.4 on average per tests on a PS1) - } -#endif - if(CRModeCache & 0x1) - { - } - else - { - extra_cyc_overhead = 8; // FIXME: Test. - *V = CDC->DMARead(); // Note: Legend of Mana's opening movie is sensitive to DMA timing, including CDC. - } - break; - - case CH_SPU: - // 0x1f801014 affects SPU DMA timing. - // Wild conjecture about 0x1f801014: - // - // & 0x0000000F - // & 0x000001E0 --- Used if (& 0x20000000) == 0? - // & 0x00001000 --- Double total bus cycle time if value == 0? - // & 0x0f000000 --- (value << 1) 33MHz cycles, bus cycle extension(added to 4?)? - // & 0x20000000 --- - // - // - // TODO?: SPU DMA will "complete" much faster if there's a mismatch between the CHCR read/write mode bit and the SPU control register DMA mode. - // - // - // Investigate: SPU DMA doesn't seem to work right if the value written to 0x1F801DAA doesn't have the upper bit set to 1(0x8000) on a PS1. - - extra_cyc_overhead = 47; // Should be closer to 69, average, but actual timing is...complicated. - - if(CRModeCache & 0x1) - SPU->WriteDMA(*V); - else - *V = SPU->ReadDMA(); - break; - - case CH_FIVE: - if(CRModeCache & 0x1) - { - } - else - { - *V = 0; - } - break; - - case CH_OT: - if(DMACH[ch].WordCounter == 1) - *V = 0xFFFFFF; - else - *V = (DMACH[ch].CurAddr - 4) & 0x1FFFFF; - break; - } - - // GROSS APPROXIMATION, shoehorning multiple effects together, TODO separate(especially SPU and CDC) - DMACH[ch].ClockCounter -= std::max(extra_cyc_overhead, (CRModeCache & 0x100) ? 7 : 0); -} - -// -// Remember to handle an end condition on the same iteration of the while(DMACH[ch].ClockCounter > 0) loop that caused it, -// otherwise RecalcHalt() might take the CPU out of a halted state before the end-of-DMA is signaled(especially a problem considering our largeish -// DMA update timing granularity). -// -static INLINE void RunChannelI(const unsigned ch, const uint32 CRModeCache, int32 clocks) -{ - //const uint32 dc = (DMAControl >> (ch * 4)) & 0xF; - - DMACH[ch].ClockCounter += clocks; - - while(MDFN_LIKELY(DMACH[ch].ClockCounter > 0)) - { - if(DMACH[ch].WordCounter == 0) // Begin WordCounter reload. - { - if(!(DMACH[ch].ChanControl & (1 << 24))) // Needed for the forced-DMA-stop kludge(see DMA_Write()). - break; - - if(!ChCan(ch, CRModeCache)) - break; - - DMACH[ch].CurAddr = DMACH[ch].BaseAddr; - - if(CRModeCache & (1U << 10)) - { - uint32 header; - - if(MDFN_UNLIKELY(DMACH[ch].CurAddr & 0x800000)) - { - DMACH[ch].ChanControl &= ~(0x11 << 24); - DMAIntControl |= 0x8000; - RecalcIRQOut(); - break; - } - - header = MainRAM.ReadU32(DMACH[ch].CurAddr & 0x1FFFFC); - DMACH[ch].CurAddr = (DMACH[ch].CurAddr + 4) & 0xFFFFFF; - - DMACH[ch].WordCounter = header >> 24; - DMACH[ch].BaseAddr = header & 0xFFFFFF; - - // printf to debug Soul Reaver ;) - //if(DMACH[ch].WordCounter > 0x10) - // printf("What the lala? 0x%02x @ 0x%08x\n", DMACH[ch].WordCounter, DMACH[ch].CurAddr - 4); - - if(DMACH[ch].WordCounter) - DMACH[ch].ClockCounter -= 15; - else - DMACH[ch].ClockCounter -= 10; - - goto SkipPayloadStuff; // 3 cheers for gluten-free spaghetticode(necessary because the newly-loaded WordCounter might be 0, and we actually - // want 0 to mean 0 and not 65536 in this context)! - } - else - { - DMACH[ch].WordCounter = DMACH[ch].BlockControl & 0xFFFF; - - if(CRModeCache & (1U << 9)) - { - if(ch == 2) // Technically should apply to all channels, but since we don't implement CPU read penalties for channels other than 2 yet, it's like this to avoid making DMA longer than what games can handle. - DMACH[ch].ClockCounter -= 7; - - DMACH[ch].BlockControl = (DMACH[ch].BlockControl & 0xFFFF) | ((DMACH[ch].BlockControl - (1U << 16)) & 0xFFFF0000); - } - } - } // End WordCounter reload. - else if(CRModeCache & 0x100) // BLARGH BLARGH FISHWHALE - { - //printf("LoadWC: %u(oldWC=%u)\n", DMACH[ch].BlockControl & 0xFFFF, DMACH[ch].WordCounter); - //MDFN_DispMessage("SPOOOON\n"); - DMACH[ch].CurAddr = DMACH[ch].BaseAddr; - DMACH[ch].WordCounter = DMACH[ch].BlockControl & 0xFFFF; - } - - // - // Do the payload read/write - // - { - uint32 vtmp; - uint32 voffs = 0; - - if(MDFN_UNLIKELY(DMACH[ch].CurAddr & 0x800000)) - { - DMACH[ch].ChanControl &= ~(0x11 << 24); - DMAIntControl |= 0x8000; - RecalcIRQOut(); - break; - } - - if(CRModeCache & 0x1) - vtmp = MainRAM.ReadU32(DMACH[ch].CurAddr & 0x1FFFFC); - - ChRW(ch, CRModeCache, &vtmp, &voffs); - - if(!(CRModeCache & 0x1)) - MainRAM.WriteU32((DMACH[ch].CurAddr + (voffs << 2)) & 0x1FFFFC, vtmp); - } - - if(CRModeCache & 0x2) - DMACH[ch].CurAddr = (DMACH[ch].CurAddr - 4) & 0xFFFFFF; - else - DMACH[ch].CurAddr = (DMACH[ch].CurAddr + 4) & 0xFFFFFF; - - DMACH[ch].WordCounter--; - DMACH[ch].ClockCounter--; - - SkipPayloadStuff: ; - - if(CRModeCache & 0x100) // BLARGH BLARGH WHALEFISH - { - DMACH[ch].BaseAddr = DMACH[ch].CurAddr; - DMACH[ch].BlockControl = (DMACH[ch].BlockControl & 0xFFFF0000) | DMACH[ch].WordCounter; - //printf("SaveWC: %u\n", DMACH[ch].WordCounter); - } - - // - // Handle channel end condition: - // - if(DMACH[ch].WordCounter == 0) - { - bool ChannelEndTC = false; - - if(!(DMACH[ch].ChanControl & (1 << 24))) // Needed for the forced-DMA-stop kludge(see DMA_Write()). - break; - - switch((CRModeCache >> 9) & 0x3) - { - case 0x0: - ChannelEndTC = true; - break; - - case 0x1: - DMACH[ch].BaseAddr = DMACH[ch].CurAddr; - if((DMACH[ch].BlockControl >> 16) == 0) - ChannelEndTC = true; - break; - - case 0x2: - case 0x3: // Not sure about 0x3. - if(DMACH[ch].BaseAddr == 0xFFFFFF) - ChannelEndTC = true; - break; - } - - if(ChannelEndTC) - { - DMACH[ch].ChanControl &= ~(0x11 << 24); - if(DMAIntControl & (1U << (16 + ch))) - { - DMAIntStatus |= 1U << ch; - RecalcIRQOut(); - } - break; - } - } - } - - if(DMACH[ch].ClockCounter > 0) - DMACH[ch].ClockCounter = 0; -} - -static INLINE void RunChannel(pscpu_timestamp_t timestamp, int32 clocks, int ch) -{ - // Mask out the bits that the DMA controller will modify during the course of operation. - const uint32 CRModeCache = DMACH[ch].ChanControl &~(0x11 << 24); - - switch(ch) - { - default: abort(); - - case 0: - if(MDFN_LIKELY(CRModeCache == 0x00000201)) - RunChannelI(0, 0x00000201, clocks); - else - RunChannelI(0, CRModeCache, clocks); - break; - - case 1: - if(MDFN_LIKELY(CRModeCache == 0x00000200)) - RunChannelI(1, 0x00000200, clocks); - else - RunChannelI(1, CRModeCache, clocks); - break; - - case 2: - if(MDFN_LIKELY(CRModeCache == 0x00000401)) - RunChannelI(2, 0x00000401, clocks); - else if(MDFN_LIKELY(CRModeCache == 0x00000201)) - RunChannelI(2, 0x00000201, clocks); - else if(MDFN_LIKELY(CRModeCache == 0x00000200)) - RunChannelI(2, 0x00000200, clocks); - else - RunChannelI(2, CRModeCache, clocks); - break; - - case 3: - if(MDFN_LIKELY(CRModeCache == 0x00000000)) - RunChannelI(3, 0x00000000, clocks); - else if(MDFN_LIKELY(CRModeCache == 0x00000100)) - RunChannelI(3, 0x00000100, clocks); - else - RunChannelI(3, CRModeCache, clocks); - break; - - case 4: - if(MDFN_LIKELY(CRModeCache == 0x00000201)) - RunChannelI(4, 0x00000201, clocks); - else if(MDFN_LIKELY(CRModeCache == 0x00000200)) - RunChannelI(4, 0x00000200, clocks); - else - RunChannelI(4, CRModeCache, clocks); - break; - - case 5: - RunChannelI(5, CRModeCache, clocks); - break; - - case 6: - if(MDFN_LIKELY(CRModeCache == 0x00000002)) - RunChannelI(6, 0x00000002, clocks); - else - RunChannelI(6, CRModeCache, clocks); - break; - } -} - -static INLINE int32 CalcNextEvent(int32 next_event) -{ - if(DMACycleCounter < next_event) - next_event = DMACycleCounter; - - return(next_event); -} - -MDFN_FASTCALL pscpu_timestamp_t DMA_Update(const pscpu_timestamp_t timestamp) -{ -// uint32 dc = (DMAControl >> (ch * 4)) & 0xF; - int32 clocks = timestamp - lastts; - lastts = timestamp; - - GPU_Update(timestamp); - MDEC_Run(clocks); - - RunChannel(timestamp, clocks, 0); - RunChannel(timestamp, clocks, 1); - RunChannel(timestamp, clocks, 2); - RunChannel(timestamp, clocks, 3); - RunChannel(timestamp, clocks, 4); - RunChannel(timestamp, clocks, 6); - - DMACycleCounter -= clocks; - while(DMACycleCounter <= 0) - DMACycleCounter += 128; - - RecalcHalt(); - - return(timestamp + CalcNextEvent(0x10000000)); -} - -#if 0 -static void CheckLinkedList(uint32 addr) -{ - std::map zoom; - - do - { - if(zoom[addr]) - { - printf("Bad linked list: 0x%08x\n", addr); - break; - } - zoom[addr] = 1; - - uint32 header = MainRAM.ReadU32(addr & 0x1FFFFC); - - addr = header & 0xFFFFFF; - - } while(addr != 0xFFFFFF && !(addr & 0x800000)); -} -#endif - -MDFN_FASTCALL void DMA_Write(const pscpu_timestamp_t timestamp, uint32 A, uint32 V) -{ - int ch = (A & 0x7F) >> 4; - - //if(ch == 2 || ch == 7) - //PSX_WARNING("[DMA] Write: %08x %08x, DMAIntStatus=%08x", A, V, DMAIntStatus); - - // FIXME if we ever have "accurate" bus emulation - V <<= (A & 3) * 8; - - DMA_Update(timestamp); - - if(ch == 7) - { - switch(A & 0xC) - { - case 0x0: //fprintf(stderr, "Global DMA control: 0x%08x\n", V); - DMAControl = V; - RecalcHalt(); - break; - - case 0x4: - DMAIntControl = V & 0x00ff803f; - DMAIntStatus &= ~(V >> 24); - RecalcIRQOut(); - break; - - default: PSX_WARNING("[DMA] Unknown write: %08x %08x", A, V); - break; - } - return; - } - switch(A & 0xC) - { - case 0x0: DMACH[ch].BaseAddr = V & 0xFFFFFF; - break; - - case 0x4: DMACH[ch].BlockControl = V; - break; - - case 0xC: - case 0x8: - { - uint32 OldCC = DMACH[ch].ChanControl; - - //printf("CHCR: %u, %08x --- 0x%08x\n", ch, V, DMACH[ch].BlockControl); - // - // Kludge for DMA timing granularity and other issues. Needs to occur before setting all bits of ChanControl to the new value, to accommodate the - // case of a game cancelling DMA and changing the type of DMA(read/write, etc.) at the same time. - // - if((DMACH[ch].ChanControl & (1 << 24)) && !(V & (1 << 24))) - { - DMACH[ch].ChanControl &= ~(1 << 24); // Clear bit before RunChannel(), so it will only finish the block it's on at most. - RunChannel(timestamp, 128 * 16, ch); - DMACH[ch].WordCounter = 0; - -#if 0 // TODO(maybe, need to work out worst-case performance for abnormally/brokenly large block sizes) - DMACH[ch].ClockCounter = (1 << 30); - RunChannel(timestamp, 1, ch); - DMACH[ch].ClockCounter = 0; -#endif - PSX_WARNING("[DMA] Forced stop for channel %d -- scanline=%d", ch, GPU_GetScanlineNum()); - //MDFN_DispMessage("[DMA] Forced stop for channel %d", ch); - } - - if(ch == 6) - DMACH[ch].ChanControl = (V & 0x51000000) | 0x2; - else - DMACH[ch].ChanControl = V & 0x71770703; - - if(!(OldCC & (1 << 24)) && (V & (1 << 24))) - { - //if(ch == 0 || ch == 1) - // PSX_WARNING("[DMA] Started DMA for channel=%d --- CHCR=0x%08x --- BCR=0x%08x --- scanline=%d", ch, DMACH[ch].ChanControl, DMACH[ch].BlockControl, GPU_GetScanlineNum()); - - DMACH[ch].WordCounter = 0; - DMACH[ch].ClockCounter = 0; - - // - // Viewpoint starts a short MEM->GPU LL DMA and apparently has race conditions that can cause a crash if it doesn't finish almost immediately( - // or at least very quickly, which the current DMA granularity has issues with, so run the channel ahead a bit to take of this issue and potentially - // games with similar issues). - // - // Though, Viewpoint isn't exactly a good game, so maybe we shouldn't bother? ;) - // - // Also, it's needed for RecalcHalt() to work with some semblance of workiness. - // - RunChannel(timestamp, 64, ch); //std::max(128 - DMACycleCounter, 1)); //64); //1); //128 - DMACycleCounter); - } - - RecalcHalt(); - } - break; - } - PSX_SetEventNT(PSX_EVENT_DMA, timestamp + CalcNextEvent(0x10000000)); -} - -MDFN_FASTCALL uint32 DMA_Read(const pscpu_timestamp_t timestamp, uint32 A) -{ - int ch = (A & 0x7F) >> 4; - uint32 ret = 0; - - if(ch == 7) - { - switch(A & 0xC) - { - default: PSX_WARNING("[DMA] Unknown read: %08x", A); - break; - - case 0x0: ret = DMAControl; - break; - - case 0x4: ret = DMAIntControl | (DMAIntStatus << 24) | (IRQOut << 31); - break; - } - } - else switch(A & 0xC) - { - case 0x0: ret = DMACH[ch].BaseAddr; - break; - - case 0x4: ret = DMACH[ch].BlockControl; - break; - - case 0xC: - case 0x8: ret = DMACH[ch].ChanControl; - break; - - } - - ret >>= (A & 3) * 8; - - //PSX_WARNING("[DMA] Read: %08x %08x", A, ret); - - return(ret); -} - - -void DMA_SyncState(bool isReader, EW::NewState *ns) -{ - NSS(DMACycleCounter); - NSS(DMAControl); - NSS(DMAIntControl); - NSS(DMAIntStatus); - NSS(IRQOut); - NSS(DMACH); -} - - -} diff --git a/psx/octoshock/psx/dma.h b/psx/octoshock/psx/dma.h deleted file mode 100644 index 4a260f94676..00000000000 --- a/psx/octoshock/psx/dma.h +++ /dev/null @@ -1,43 +0,0 @@ -/******************************************************************************/ -/* Mednafen Sony PS1 Emulation Module */ -/******************************************************************************/ -/* dma.h: -** Copyright (C) 2011-2016 Mednafen Team -** -** 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., -** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef __MDFN_PSX_DMA_H -#define __MDFN_PSX_DMA_H - -namespace MDFN_IEN_PSX -{ - -MDFN_FASTCALL pscpu_timestamp_t DMA_Update(const pscpu_timestamp_t timestamp); -MDFN_FASTCALL void DMA_Write(const pscpu_timestamp_t timestamp, uint32 A, uint32 V); -MDFN_FASTCALL uint32 DMA_Read(const pscpu_timestamp_t timestamp, uint32 A); - -void DMA_ResetTS(void); - -void DMA_Power(void) MDFN_COLD; - -void DMA_Init(void) MDFN_COLD; -void DMA_Kill(void) MDFN_COLD; - - - -} - -#endif diff --git a/psx/octoshock/psx/frontio.cpp b/psx/octoshock/psx/frontio.cpp deleted file mode 100644 index 4557a035edc..00000000000 --- a/psx/octoshock/psx/frontio.cpp +++ /dev/null @@ -1,723 +0,0 @@ -/******************************************************************************/ -/* Mednafen Sony PS1 Emulation Module */ -/******************************************************************************/ -/* frontio.cpp: -** Copyright (C) 2011-2017 Mednafen Team -** -** 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., -** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include - -#include "psx.h" -#include "frontio.h" - -#include "input/gamepad.h" -#include "input/dualanalog.h" -#include "input/dualshock.h" -#include "input/mouse.h" -#include "input/negcon.h" -#include "input/guncon.h" -#include "input/justifier.h" - -#include "input/memcard.h" - -#include "input/multitap.h" - -#define PSX_FIODBGINFO(format, ...) { /* printf(format " -- timestamp=%d -- PAD temp\n", ## __VA_ARGS__, timestamp); */ } - -namespace MDFN_IEN_PSX -{ - -InputDevice::InputDevice() : chair_r(0), chair_g(0), chair_b(0), chair_x(-1000), chair_y(-1000) -{ -} - -InputDevice::~InputDevice() -{ -} - -void InputDevice::Power(void) -{ -} - -void InputDevice::Update(const pscpu_timestamp_t timestamp) -{ - -} - -void InputDevice::ResetTS(void) -{ - -} - - -bool InputDevice::RequireNoFrameskip(void) -{ - return(false); -} - -pscpu_timestamp_t InputDevice::GPULineHook(const pscpu_timestamp_t timestamp, bool vsync, uint32 *pixels, const MDFN_PixelFormat* const format, const unsigned width, const unsigned pix_clock_offset, const unsigned pix_clock, const unsigned pix_clock_divider) -{ - return(PSX_EVENT_MAXTS); -} - - -void InputDevice::UpdateInput(const void *data) -{ -} - - -void InputDevice::SetDTR(bool new_dtr) -{ - -} - -bool InputDevice::GetDSR(void) -{ - return(0); -} - -bool InputDevice::Clock(bool TxD, int32 &dsr_pulse_delay) -{ - dsr_pulse_delay = 0; - - return(1); -} - -uint32 InputDevice::GetNVSize(void) const -{ - return(0); -} - -const uint8* InputDevice::ReadNV(void) const -{ - return NULL; -} - -void InputDevice::WriteNV(const uint8 *buffer, uint32 offset, uint32 count) -{ - -} - -uint64 InputDevice::GetNVDirtyCount(void) const -{ - return(0); -} - -void InputDevice::ResetNVDirtyCount(void) -{ - -} - -//an old snippet tha showshow to set up a multitap device - //if(emulate_multitap[mp]) - // DevicesTap[mp]->SetSubDevice(EP_to_SP(emulate_multitap, i), Devices[i], emulate_memcards[i] ? DevicesMC[i] : DummyDevice); - //else - // DevicesTap[mp]->SetSubDevice(EP_to_SP(emulate_multitap, i), DummyDevice, DummyDevice); - - -FrontIO::FrontIO() -{ - //a dummy device used for memcards (please rename me) - DummyDevice = new InputDevice(); - - for(int i=0;i<2;i++) - { - Ports[i] = new InputDevice(); - PortData[i] = NULL; - MCPorts[i] = new InputDevice(); - emulate_multitap[i] = false; - DevicesTap[i] = new InputDevice_Multitap(); - } -} - - -FrontIO::~FrontIO() -{ - for(int i=0;i<2;i++) - { - delete Ports[i]; - delete MCPorts[i]; - delete DevicesTap[i]; - } - delete DummyDevice; -} - -pscpu_timestamp_t FrontIO::CalcNextEventTS(pscpu_timestamp_t timestamp, int32 next_event) -{ - pscpu_timestamp_t ret; - - if(ClockDivider > 0 && ClockDivider < next_event) - next_event = ClockDivider; - - for(int i = 0; i < 4; i++) - if(dsr_pulse_delay[i] > 0 && next_event > dsr_pulse_delay[i]) - next_event = dsr_pulse_delay[i]; - - ret = timestamp + next_event; - - if(irq10_pulse_ts[0] < ret) - ret = irq10_pulse_ts[0]; - - if(irq10_pulse_ts[1] < ret) - ret = irq10_pulse_ts[1]; - - return(ret); -} - -static const uint8 ScaleShift[4] = { 0, 0, 4, 6 }; - -void FrontIO::CheckStartStopPending(pscpu_timestamp_t timestamp, bool skip_event_set) -{ - //const bool prior_ReceiveInProgress = ReceiveInProgress; - //const bool prior_TransmitInProgress = TransmitInProgress; - bool trigger_condition = false; - - trigger_condition = (ReceivePending && (Control & 0x4)) || (TransmitPending && (Control & 0x1)); - - if(trigger_condition) - { - if(ReceivePending) - { - ReceivePending = false; - ReceiveInProgress = true; - ReceiveBufferAvail = false; - ReceiveBuffer = 0; - ReceiveBitCounter = 0; - } - - if(TransmitPending) - { - TransmitPending = false; - TransmitInProgress = true; - TransmitBitCounter = 0; - } - - ClockDivider = std::max(0x20, (Baudrate << ScaleShift[Mode & 0x3]) & ~1); // Minimum of 0x20 is an emulation sanity check to prevent severe performance degradation. - //printf("CD: 0x%02x\n", ClockDivider); - } - - if(!(Control & 0x5)) - { - ReceiveInProgress = false; - TransmitInProgress = false; - } - - if(!ReceiveInProgress && !TransmitInProgress) - ClockDivider = 0; - - if(!(skip_event_set)) - PSX_SetEventNT(PSX_EVENT_FIO, CalcNextEventTS(timestamp, 0x10000000)); -} - -// DSR IRQ bit setting appears(from indirect tests on real PS1) to be level-sensitive, not edge-sensitive -INLINE void FrontIO::DoDSRIRQ(void) -{ - if(Control & 0x1000) - { - PSX_FIODBGINFO("[DSR] IRQ"); - istatus = true; - IRQ_Assert(IRQ_SIO, true); - } -} - - - -void FrontIO::Write(pscpu_timestamp_t timestamp, uint32 A, uint32 V) -{ - PSX_FIODBGINFO("[FIO] Write: %08x %08x", A, V); - - V <<= (A & 1) * 8; - - Update(timestamp); - - switch(A & 0xE) - { - case 0x0: - case 0x2: - V <<= (A & 2) * 8; - TransmitBuffer = V; - TransmitPending = true; - TransmitInProgress = false; - break; - - case 0x8: - Mode = V & 0x013F; - break; - - case 0xa: - if(ClockDivider > 0 && ((V & 0x2000) != (Control & 0x2000)) && ((Control & 0x2) == (V & 0x2)) ) - PSX_DBG(PSX_DBG_WARNING, "FIO device selection changed during comm %04x->%04x\n", Control, V); - - //printf("Control: %d, %04x\n", timestamp, V); - Control = V & 0x3F2F; - - if(V & 0x10) - { - istatus = false; - IRQ_Assert(IRQ_SIO, false); - } - - if(V & 0x40) // Reset - { - istatus = false; - IRQ_Assert(IRQ_SIO, false); - - ClockDivider = 0; - ReceivePending = false; - TransmitPending = false; - - ReceiveInProgress = false; - TransmitInProgress = false; - - ReceiveBufferAvail = false; - - TransmitBuffer = 0; - ReceiveBuffer = 0; - - ReceiveBitCounter = 0; - TransmitBitCounter = 0; - - Mode = 0; - Control = 0; - Baudrate = 0; - } - - Ports[0]->SetDTR((Control & 0x2) && !(Control & 0x2000)); - MCPorts[0]->SetDTR((Control & 0x2) && !(Control & 0x2000)); - Ports[1]->SetDTR((Control & 0x2) && (Control & 0x2000)); - MCPorts[1]->SetDTR((Control & 0x2) && (Control & 0x2000)); - -#if 1 -if(!((Control & 0x2) && !(Control & 0x2000))) -{ - dsr_pulse_delay[0] = 0; - dsr_pulse_delay[2] = 0; - dsr_active_until_ts[0] = -1; - dsr_active_until_ts[2] = -1; -} - -if(!((Control & 0x2) && (Control & 0x2000))) -{ - dsr_pulse_delay[1] = 0; - dsr_pulse_delay[3] = 0; - dsr_active_until_ts[1] = -1; - dsr_active_until_ts[3] = -1; -} - -#endif - // TODO: Uncomment out in the future once our CPU emulation is a bit more accurate with timing, to prevent causing problems with games - // that may clear the IRQ in an unsafe pattern that only works because its execution was slow enough to allow DSR to go inactive. (Whether or not - // such games even exist though is unknown!) - //if(timestamp < dsr_active_until_ts[0] || timestamp < dsr_active_until_ts[1] || timestamp < dsr_active_until_ts[2] || timestamp < dsr_active_until_ts[3]) - // DoDSRIRQ(); - - break; - - case 0xe: - Baudrate = V; - //printf("%02x\n", V); - //MDFN_DispMessage("%02x\n", V); - break; - } - - CheckStartStopPending(timestamp, false); -} - -uint32 FrontIO::Read(pscpu_timestamp_t timestamp, uint32 A) -{ - uint32 ret = 0; - - Update(timestamp); - - switch(A & 0xE) - { - case 0x0: - case 0x2: - //printf("FIO Read: 0x%02x\n", ReceiveBuffer); - ret = ReceiveBuffer | (ReceiveBuffer << 8) | (ReceiveBuffer << 16) | (ReceiveBuffer << 24); - ReceiveBufferAvail = false; - ReceivePending = true; - ReceiveInProgress = false; - CheckStartStopPending(timestamp, false); - ret >>= (A & 2) * 8; - break; - - case 0x4: - ret = 0; - - if(!TransmitPending && !TransmitInProgress) - ret |= 0x1; - - if(ReceiveBufferAvail) - ret |= 0x2; - - if(timestamp < dsr_active_until_ts[0] || timestamp < dsr_active_until_ts[1] || timestamp < dsr_active_until_ts[2] || timestamp < dsr_active_until_ts[3]) - ret |= 0x80; - - if(istatus) - ret |= 0x200; - - break; - - case 0x8: - ret = Mode; - break; - - case 0xa: - ret = Control; - break; - - case 0xe: - ret = Baudrate; - break; - } - - ret >>= (A & 1) * 8; - - if((A & 0xF) != 0x4) - PSX_FIODBGINFO("[FIO] Read: %08x %08x", A, ret); - - return(ret); -} - -pscpu_timestamp_t FrontIO::Update(pscpu_timestamp_t timestamp) -{ - int32 clocks = timestamp - lastts; - bool need_start_stop_check = false; - - for(int i = 0; i < 4; i++) - if(dsr_pulse_delay[i] > 0) - { - dsr_pulse_delay[i] -= clocks; - if(dsr_pulse_delay[i] <= 0) - { - dsr_active_until_ts[i] = timestamp + 32 + dsr_pulse_delay[i]; - DoDSRIRQ(); - } - } - - for(int i = 0; i < 2; i++) - { - if(timestamp >= irq10_pulse_ts[i]) - { - //printf("Yay: %d %u\n", i, timestamp); - irq10_pulse_ts[i] = PSX_EVENT_MAXTS; - IRQ_Assert(IRQ_PIO, true); - IRQ_Assert(IRQ_PIO, false); - } - } - - if(ClockDivider > 0) - { - ClockDivider -= clocks; - - while(ClockDivider <= 0) - { - if(ReceiveInProgress || TransmitInProgress) - { - bool rxd = 0, txd = 0; - const uint32 BCMask = 0x07; - - if(TransmitInProgress) - { - txd = (TransmitBuffer >> TransmitBitCounter) & 1; - TransmitBitCounter = (TransmitBitCounter + 1) & BCMask; - if(!TransmitBitCounter) - { - need_start_stop_check = true; - PSX_FIODBGINFO("[FIO] Data transmitted: %08x", TransmitBuffer); - TransmitInProgress = false; - - if(Control & 0x400) - { - istatus = true; - IRQ_Assert(IRQ_SIO, true); - } - } - } - - rxd = Ports[0]->Clock(txd, dsr_pulse_delay[0]) & Ports[1]->Clock(txd, dsr_pulse_delay[1]) & - MCPorts[0]->Clock(txd, dsr_pulse_delay[2]) & MCPorts[1]->Clock(txd, dsr_pulse_delay[3]); - - if(ReceiveInProgress) - { - ReceiveBuffer &= ~(1 << ReceiveBitCounter); - ReceiveBuffer |= rxd << ReceiveBitCounter; - - ReceiveBitCounter = (ReceiveBitCounter + 1) & BCMask; - - if(!ReceiveBitCounter) - { - need_start_stop_check = true; - PSX_FIODBGINFO("[FIO] Data received: %08x", ReceiveBuffer); - - ReceiveInProgress = false; - ReceiveBufferAvail = true; - - if(Control & 0x800) - { - istatus = true; - IRQ_Assert(IRQ_SIO, true); - } - } - } - ClockDivider += std::max(0x20, (Baudrate << ScaleShift[Mode & 0x3]) & ~1); // Minimum of 0x20 is an emulation sanity check to prevent severe performance degradation. - } - else - break; - } - } - - - lastts = timestamp; - - - if(need_start_stop_check) - { - CheckStartStopPending(timestamp, true); - } - - return(CalcNextEventTS(timestamp, 0x10000000)); -} - -void FrontIO::ResetTS(void) -{ - for(int i=0;i<2;i++) - { - if(Ports[i] != NULL) - { - Ports[i]->Update(lastts); // Maybe eventually call Update() from FrontIO::Update() and remove this(but would hurt speed)? - Ports[i]->ResetTS(); - } - - if(MCPorts[i] != NULL) - { - MCPorts[i]->Update(lastts); // Maybe eventually call Update() from FrontIO::Update() and remove this(but would hurt speed)? - MCPorts[i]->ResetTS(); - } - } - - for(int i = 0; i < 2; i++) - { - if(irq10_pulse_ts[i] != PSX_EVENT_MAXTS) - irq10_pulse_ts[i] -= lastts; - } - - for(int i = 0; i < 4; i++) - { - if(dsr_active_until_ts[i] >= 0) - { - dsr_active_until_ts[i] -= lastts; - //printf("SPOOONY: %d %d\n", i, dsr_active_until_ts[i]); - } - } - lastts = 0; -} - - -void FrontIO::Reset(bool powering_up) -{ - for(int i = 0; i < 4; i++) - { - dsr_pulse_delay[i] = 0; - dsr_active_until_ts[i] = -1; - } - - for(int i = 0; i < 2; i++) - { - irq10_pulse_ts[i] = PSX_EVENT_MAXTS; - } - - lastts = 0; - - // - // - - ClockDivider = 0; - - ReceivePending = false; - TransmitPending = false; - - ReceiveInProgress = false; - TransmitInProgress = false; - - ReceiveBufferAvail = false; - - TransmitBuffer = 0; - ReceiveBuffer = 0; - - ReceiveBitCounter = 0; - TransmitBitCounter = 0; - - Mode = 0; - Control = 0; - Baudrate = 0; - - //power on all plugged devices (are we doing this when attaching them?) - if(powering_up) - { - for(int i=0;i<2;i++) - { - if(Ports[i] != NULL) Ports[i]->Power(); - if(MCPorts[i] != NULL) MCPorts[i]->Power(); - } - } - - istatus = false; -} - -// Take care to call ->Power() only if the device actually changed. -void FrontIO::SetInput(unsigned int port, unsigned int multiport, const char *type, void *ptr) -{ - //clean up the old device - delete Ports[port]; - Ports[port] = NULL; - - if(!strcmp(type, "gamepad") || !strcmp(type, "dancepad")) - Ports[port] = Device_Gamepad_Create(); - else if(!strcmp(type, "dualanalog")) - Ports[port] = Device_DualAnalog_Create(false); - else if(!strcmp(type, "analogjoy")) - Ports[port] = Device_DualAnalog_Create(true); - else if(!strcmp(type, "dualshock")) - Ports[port] = Device_DualShock_Create(); - else if(!strcmp(type, "mouse")) - Ports[port] = Device_Mouse_Create(); - else if(!strcmp(type, "negcon")) - Ports[port] = Device_neGcon_Create(); - else if(!strcmp(type, "guncon")) - Ports[port] = Device_GunCon_Create(); - else if(!strcmp(type, "justifier")) - Ports[port] = Device_Justifier_Create(); - else if (!strcmp(type, "multitap")) - Ports[port] = new InputDevice_Multitap(); - else - Ports[port] = new InputDevice(); - - // " Take care to call ->Power() only if the device actually changed. " - TO THINK ABOUT. maybe irrelevant in octoshock - //if(Devices[port] != nd) - - //OCTOSHOCK TODO - not sure I understand this - if(port < 2) - irq10_pulse_ts[port] = PSX_EVENT_MAXTS; - - Ports[port]->Power(); - PortData[port] = ptr; -} - -uint64 FrontIO::GetMemcardDirtyCount(unsigned int which) -{ - assert(which < 2); - - return(MCPorts[which]->GetNVDirtyCount()); -} - -//TODO - ok, savestating varying input devices. this is tricky. -//its like... what happens when the hardware unfreezes with different input attached? -//thats some kind of instantaneous change event which shouldnt/cant be properly emulated or likely even implemented -//so in that respect it's very much like (if not identical to) CDs. -//heres a discussion question. what are we doing here? savestating the CONSOLE or savestating the ENTIRE SYSTEM? -//well, what's being emulated? -//I dont know. lets save it for later. -//You know, this is one reason mednafen had a distinction between ports and devices. -//But I had to get rid of it, I just had to. At least they need to be organized into a pool differently somehow. - -//Anyway, think about this: We cant just savestate the entire system. The game will be depending on the input devices being in a certain state. -//If theyre in any other state, literally, any other state, then the game will fail. -//Therefore the entire system needs saving together and mismatches MUST NOT BE PERMITTED. - -SYNCFUNC(FrontIO) -{ - NSS(ClockDivider); - - NSS(ReceivePending); - NSS(TransmitPending); - - NSS(ReceiveInProgress); - NSS(TransmitInProgress); - - NSS(ReceiveBufferAvail); - - NSS(ReceiveBuffer); - NSS(TransmitBuffer); - - NSS(ReceiveBitCounter); - NSS(TransmitBitCounter); - - NSS(Mode); - NSS(Control); - NSS(Baudrate); - - NSS(istatus); - - // FIXME: Step mode save states. - NSS(irq10_pulse_ts); - NSS(dsr_pulse_delay); - NSS(dsr_active_until_ts); - - //state actions for ports and such - for(int i=0;i<2;i++) - { - ns->EnterSection("PORT%d",i); - Ports[i]->SyncState(isReader,ns); - ns->ExitSection("PORT%d",i); - ns->EnterSection("MCPORT%d",i); - MCPorts[i]->SyncState(isReader,ns); - ns->ExitSection("MCPORT%d",i); - } - - //more of this crap.... - if(isReader) - { - IRQ_Assert(IRQ_SIO, istatus); - } - -} - -bool FrontIO::RequireNoFrameskip(void) -{ - //this whole function is nonsense. frontend should know what it has attached - return(false); -} - - -void FrontIO::GPULineHook(const pscpu_timestamp_t timestamp, const pscpu_timestamp_t line_timestamp, bool vsync, uint32 *pixels, const MDFN_PixelFormat* const format, const unsigned width, const unsigned pix_clock_offset, const unsigned pix_clock, const unsigned pix_clock_divider) -{ - Update(timestamp); - - for(unsigned i = 0; i < 2; i++) - { - pscpu_timestamp_t plts = Ports[i]->GPULineHook(line_timestamp, vsync, pixels, format, width, pix_clock_offset, pix_clock, pix_clock_divider); - - irq10_pulse_ts[i] = plts; - - if(irq10_pulse_ts[i] <= timestamp) - { - irq10_pulse_ts[i] = PSX_EVENT_MAXTS; - IRQ_Assert(IRQ_PIO, true); - IRQ_Assert(IRQ_PIO, false); - } - } - - - PSX_SetEventNT(PSX_EVENT_FIO, CalcNextEventTS(timestamp, 0x10000000)); -} - - - - -} diff --git a/psx/octoshock/psx/frontio.h b/psx/octoshock/psx/frontio.h deleted file mode 100644 index c686ce9ff18..00000000000 --- a/psx/octoshock/psx/frontio.h +++ /dev/null @@ -1,170 +0,0 @@ -/******************************************************************************/ -/* Mednafen Sony PS1 Emulation Module */ -/******************************************************************************/ -/* frontio.h: -** Copyright (C) 2011-2017 Mednafen Team -** -** 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., -** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef __MDFN_PSX_FRONTIO_H -#define __MDFN_PSX_FRONTIO_H - -namespace MDFN_IEN_PSX -{ - -class InputDevice_Multitap; - -class InputDevice -{ - public: - - InputDevice() MDFN_COLD; - virtual ~InputDevice() MDFN_COLD; - - virtual void Power(void) MDFN_COLD; - virtual void UpdateInput(const void *data); - - virtual void SyncState(bool isReader, EW::NewState *ns) {} - - virtual bool RequireNoFrameskip(void); - - // Divide mouse X coordinate by pix_clock_divider in the lightgun code to get the coordinate in pixel(clocks). - virtual pscpu_timestamp_t GPULineHook(const pscpu_timestamp_t line_timestamp, bool vsync, uint32 *pixels, const MDFN_PixelFormat* const format, const unsigned width, const unsigned pix_clock_offset, const unsigned pix_clock, const unsigned pix_clock_divider); - - virtual void Update(const pscpu_timestamp_t timestamp); // Partially-implemented, don't rely on for timing any more fine-grained than a video frame for now. - virtual void ResetTS(void); - - virtual const char* GetName() const { return "InputDevice"; } - - - // - // - // - virtual void SetDTR(bool new_dtr); - virtual bool GetDSR(void); // Currently unused. - - virtual bool Clock(bool TxD, int32 &dsr_pulse_delay); - - // - // - virtual uint32 GetNVSize(void) const; - virtual const uint8* ReadNV(void) const; // Pointer returned should be considered temporary and assumed invalidated upon further calls to non-const functions on the object. - virtual void WriteNV(const uint8 *buffer, uint32 offset, uint32 count); - - // - // Dirty count should be incremented on each call to a method this class that causes at least 1 write to occur to the - // nonvolatile memory(IE Clock() in the correct command phase, and WriteNV()). - // - virtual uint64 GetNVDirtyCount(void) const; - virtual void ResetNVDirtyCount(void); - - - private: - unsigned chair_r, chair_g, chair_b; - protected: - int32 chair_x, chair_y; -}; - -class FrontIO -{ - public: - - FrontIO(); - ~FrontIO(); - - templatevoid SyncState(EW::NewState *ns); - - void Reset(bool powering_up); - void Write(pscpu_timestamp_t timestamp, uint32 A, uint32 V); - uint32 Read(pscpu_timestamp_t timestamp, uint32 A); - pscpu_timestamp_t CalcNextEventTS(pscpu_timestamp_t timestamp, int32 next_event); - pscpu_timestamp_t Update(pscpu_timestamp_t timestamp); - void ResetTS(void); - - bool RequireNoFrameskip(void); - void GPULineHook(const pscpu_timestamp_t timestamp, const pscpu_timestamp_t line_timestamp, bool vsync, uint32 *pixels, const MDFN_PixelFormat* const format, const unsigned width, const unsigned pix_clock_offset, const unsigned pix_clock, const unsigned pix_clock_divider); - - void UpdateInput(void); - void SetInput(unsigned int port, unsigned int multiport, const char *type, void *ptr); - void SetCrosshairsColor(unsigned port, uint32 color); - - uint64 GetMemcardDirtyCount(unsigned int which); - - - InputDevice *Ports[2]; - void *PortData[2]; - InputDevice *MCPorts[2]; - InputDevice *DummyDevice; - - //private: - - void DoDSRIRQ(void); - void CheckStartStopPending(pscpu_timestamp_t timestamp, bool skip_event_set = false); - - - - - //OLD - //bool emulate_memcards[8]; - //void MapDevicesToPorts(void); - bool emulate_multitap[2]; - InputDevice_Multitap *DevicesTap[2]; - //InputDevice *Devices[8]; - //void *DeviceData[8]; - //InputDevice *DevicesMC[8]; - - // - // - // - - int32 ClockDivider; - - bool ReceivePending; - bool TransmitPending; - - bool ReceiveInProgress; - bool TransmitInProgress; - - bool ReceiveBufferAvail; - - uint8 ReceiveBuffer; - uint8 TransmitBuffer; - - int32 ReceiveBitCounter; - int32 TransmitBitCounter; - - uint16 Mode; - uint16 Control; - uint16 Baudrate; - - - bool istatus; - // - // - pscpu_timestamp_t irq10_pulse_ts[2]; - - int32 dsr_pulse_delay[4]; - int32 dsr_active_until_ts[4]; - int32 lastts; - // - // - uint32 chair_colors[8]; -}; - -extern InputInfoStruct FIO_InputInfo; - -} -#endif diff --git a/psx/octoshock/psx/gpu.cpp b/psx/octoshock/psx/gpu.cpp deleted file mode 100644 index 7fb5356e30b..00000000000 --- a/psx/octoshock/psx/gpu.cpp +++ /dev/null @@ -1,1698 +0,0 @@ -/******************************************************************************/ -/* Mednafen Sony PS1 Emulation Module */ -/******************************************************************************/ -/* gpu.cpp: -** Copyright (C) 2011-2019 Mednafen Team -** -** 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., -** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#pragma GCC optimize ("unroll-loops") - -#include - -#include "psx.h" -#include "timer.h" -#include "math_ops.h" - -/* FIXME: Respect horizontal timing register values in relation to hsync/hblank/hretrace/whatever signal sent to the timers */ - -/* - GPU display timing master clock is nominally 53.693182 MHz for NTSC PlayStations, and 53.203425 MHz for PAL PlayStations. - - Non-interlaced NTSC mode line timing notes(real-world times calculated via PS1 timer and math with nominal CPU clock value): - - 263 lines per frame - - ~16714.85 us per frame, average. - ~63.55456 us per line, average. - - Multiplying the results of counter 0 in pixel clock mode by the clock divider of the current dot clock mode/width gives a result that's slightly less - than expected; the dot clock divider is probably being reset each scanline. - - Non-interlaced PAL mode(but with an NTSC source clock in an NTSC PS1; calculated same way as NTSC values): - - 314 lines per frame - - ~19912.27 us per frame, average. - ~63.41486 us per line, average. - - FB X and Y display positions can be changed during active display; and Y display position appears to be treated as an offset to the current Y readout - position that gets reset around vblank time. - -*/ - -/* - November 29, 2012 notes: - - PAL mode can be turned on, and then off again, mid-frame(creates a neat effect). - - Pixel clock can be changed mid-frame with effect(the effect is either instantaneous, or cached at some point in the scanline, not tested to see which); - interestingly, alignment is off on a PS1 when going 5MHz->10MHz>5MHz with a grid image. - - Vertical start and end can be changed during active display, with effect(though it needs to be vs0->ve0->vs1->ve1->..., vs0->vs1->ve0 doesn't apparently do anything - different from vs0->ve0. -*/ - -namespace MDFN_IEN_PSX -{ - -PS_GPU GPU; - -namespace PS_GPU_INTERNAL -{ - #include "gpu_common.inc" -} -using namespace PS_GPU_INTERNAL; - -void GPU_Init(bool pal_clock_and_tv) -{ - static const int8 dither_table[4][4] = - { - { -4, 0, -3, 1 }, - { 2, -2, 3, -1 }, - { -3, 1, -4, 0 }, - { 3, -1, 2, -2 }, - }; - - HardwarePALType = pal_clock_and_tv; - //printf("%zu\n", (size_t)((uintptr_t)DitherLUT - (uintptr_t)this)); - //printf("%zu\n", (size_t)((uintptr_t)GPURAM - (uintptr_t)this)); - // - - for(int y = 0; y < 4; y++) - for(int x = 0; x < 4; x++) - for(int v = 0; v < 512; v++) - { - int value = v + dither_table[y][x]; - - value >>= 3; - - if(value < 0) - value = 0; - - if(value > 0x1F) - value = 0x1F; - - DitherLUT[y][x][v] = value; - } - - if(HardwarePALType == false) // NTSC clock - { - GPUClockRatio = 103896; // 65536 * 53693181.818 / (44100 * 768) - hmc_to_visible = 520; - } - else // PAL clock - { - GPUClockRatio = 102948; // 65536 * 53203425 / (44100 * 768) - hmc_to_visible = 560; - } - - memcpy(&Commands[0x00], Commands_00_1F, sizeof(Commands_00_1F)); - memcpy(&Commands[0x20], Commands_20_3F, sizeof(Commands_20_3F)); - memcpy(&Commands[0x40], Commands_40_5F, sizeof(Commands_40_5F)); - memcpy(&Commands[0x60], Commands_60_7F, sizeof(Commands_60_7F)); - memcpy(&Commands[0x80], Commands_80_FF, sizeof(Commands_80_FF)); -} - -void GPU_Kill(void) -{ - -} - -/* -2640: 528.000000 660.000000 377.142853 --- 8.000000 10.000000 11.428572 -2720: 544.000000 680.000000 388.571442 --- 4.000000 5.000000 5.714286 -2800: 560.000000 700.000000 400.000000 --- 0.000000 0.000000 0.000000 -*/ -static const uint32 DotClockRatios[5] = { 10, 8, 5, 4, 7 }; -static const int32 HVisMax = 2800; -static const int32 HVisHideOS = 2640; -static const uint32 drxbo = 32; -static const int32 FBWidth = 768; -static const int32 FBWidthNCA = 896; - -void PS_GPU::SetRenderOptions(::ShockRenderOptions* opts) -{ - dump_framebuffer = opts->renderType == eShockRenderType_Framebuffer; - ShowHOverscan = !(opts->renderType == eShockRenderType_ClipOverscan); - CorrectAspect = true; - HVis = ShowHOverscan ? HVisMax : HVisHideOS; - HVisOffs = (HVisMax - HVis) / 2; - NCABaseW = (HVis + 6) / 7; - - LineVisFirst = opts->scanline_start; - LineVisLast = opts->scanline_end; - - int lcm_width = HVis; - int lcm_height = (LineVisLast + 1 - LineVisFirst) * 2; - int fb_height, nominal_width; - - // - // Nominal fps values are for interlaced mode(fps will be lower in progressive mode), and will be slightly higher than actual fps - // due to rounding error with GPUClockRatio. - // - if(HardwarePALType) - { - nominal_width = ((int64)lcm_width * 14750000 / 53203425 + 1) / 2; - fb_height = 576; - - //gi->fb_height = 576; - //gi->fps = 838865530; // 65536*256 * 53203425 / (3405 * 312.5) - //gi->VideoSystem = VIDSYS_PAL; - } - else - { - nominal_width = ((int64)lcm_width * 12272727 / 53693182 + 1) / 2; - fb_height = 480; - - //gi->fb_height = 480; - //gi->fps = 1005627336; // 65536*256 * 53693182 / (3412.5 * 262.5) - //gi->VideoSystem = VIDSYS_NTSC; - } - - //printf("RESOLUTION INFO: %d %d %d %d\n", lcm_width, lcm_height, nominal_width, fb_height); - - //SNIP: gi-> setup stuff INCLUDING guns (probably need to do this at some point) -} - - -//------- -//OUT OF DATE AND NOT USED -//------- -//void PS_GPU_FillVideoParams(MDFNGI* gi) -//{ -// if(HardwarePALType) -// { -// gi->lcm_width = hide_hoverscan ? 2640 : 2800; -// gi->lcm_height = (LineVisLast + 1 - LineVisFirst) * 2; //576; -// -// gi->nominal_width = hide_hoverscan ? 363 : 384; // More like 385.stuff according to calculations derived from BT.601, but 384 is a nicer number. :p -// gi->nominal_height = LineVisLast + 1 - LineVisFirst; //288; -// -// gi->fb_width = 768; -// gi->fb_height = 576; -// -// gi->fps = 836203078; -// -// gi->VideoSystem = VIDSYS_PAL; -// } -// else -// { -// gi->lcm_width = hide_hoverscan ? 2640 : 2800; -// gi->lcm_height = (LineVisLast + 1 - LineVisFirst) * 2; //480; -// -// gi->nominal_width = (hide_hoverscan ? 302 : 320); -// gi->nominal_height = LineVisLast + 1 - LineVisFirst; //240; -// -// gi->fb_width = 768; -// gi->fb_height = 480; -// -// gi->fps = 1005643085; -// -// gi->VideoSystem = VIDSYS_NTSC; -// } -// -// -// // -// // For Justifier and Guncon. -// // -// gi->mouse_scale_x = (float)gi->lcm_width; -// gi->mouse_offs_x = (float)(2800 - gi->lcm_width) / 2; -// -// gi->mouse_scale_y = gi->nominal_height; -// gi->mouse_offs_y = LineVisFirst; -//} - -static INLINE void InvalidateTexCache(void) -{ - for(auto& c : TexCache) - c.Tag = ~0U; -} - -static void InvalidateCache(void) -{ - CLUT_Cache_VB = ~0U; - - InvalidateTexCache(); -} - -static void SoftReset(void) // Control command 0x00 -{ - IRQPending = false; - IRQ_Assert(IRQ_GPU, IRQPending); - - InvalidateCache(); - - DMAControl = 0; - - if(DrawTimeAvail < 0) - DrawTimeAvail = 0; - - BlitterFIFO.Flush(); - DataReadBufferEx = 0; - InCmd = PS_GPU::INCMD_NONE; - - DisplayOff = 1; - DisplayFB_XStart = 0; - DisplayFB_YStart = 0; - - DisplayMode = 0; - - HorizStart = 0x200; - HorizEnd = 0xC00; - - VertStart = 0x10; - VertEnd = 0x100; - - // - TexPageX = 0; - TexPageY = 0; - - SpriteFlip = 0; - - abr = 0; - TexMode = 0; - - dtd = 0; - dfe = 0; - - // - tww = 0; - twh = 0; - twx = 0; - twy = 0; - - RecalcTexWindowStuff(); - - // - ClipX0 = 0; - ClipY0 = 0; - - // - ClipX1 = 0; - ClipY1 = 0; - - // - OffsX = 0; - OffsY = 0; - - // - MaskSetOR = 0; - MaskEvalAND = 0; - - TexDisable = false; - TexDisableAllowChange = false; -} - -void GPU_Power(void) -{ - memset(GPURAM, 0, sizeof(GPURAM)); - - memset(CLUT_Cache, 0, sizeof(CLUT_Cache)); - CLUT_Cache_VB = ~0U; - - memset(TexCache, 0xFF, sizeof(TexCache)); - - DMAControl = 0; - - ClipX0 = 0; - ClipY0 = 0; - ClipX1 = 0; - ClipY1 = 0; - - OffsX = 0; - OffsY = 0; - - dtd = false; - dfe = false; - - MaskSetOR = 0; - MaskEvalAND = 0; - - TexDisable = false; - TexDisableAllowChange = false; - - tww = 0; - twh = 0; - twx = 0; - twy = 0; - - TexPageX = 0; - TexPageY = 0; - SpriteFlip = 0; - - abr = 0; - TexMode = 0; - - RecalcTexWindowStuff(); - - BlitterFIFO.Flush(); - DataReadBuffer = 0; // Don't reset in SoftReset() - DataReadBufferEx = 0; - InCmd = PS_GPU::INCMD_NONE; - FBRW_X = 0; - FBRW_Y = 0; - FBRW_W = 0; - FBRW_H = 0; - FBRW_CurY = 0; - FBRW_CurX = 0; - - DisplayMode = 0; - DisplayOff = 1; - DisplayFB_XStart = 0; - DisplayFB_YStart = 0; - - HorizStart = 0; - HorizEnd = 0; - - VertStart = 0; - VertEnd = 0; - - // - // - // - DisplayFB_CurYOffset = 0; - DisplayFB_CurLineYReadout = 0; - InVBlank = true; - - // TODO: factor out in a separate function. - LinesPerField = 263; - - // - // - // - scanline = 0; - field = 0; - field_ram_readout = 0; - PhaseChange = 0; - - // - // - // - DotClockCounter = 0; - GPUClockCounter = 0; - LineClockCounter = 3412 - 200; - LinePhase = 0; - - DrawTimeAvail = 0; - - lastts = 0; - - SoftReset(); - - IRQ_Assert(IRQ_VBLANK, InVBlank); - TIMER_SetVBlank(InVBlank); -} - -void GPU_ResetTS(void) -{ - lastts = 0; -} - -// Special RAM write mode(16 pixels at a time), does *not* appear to use mask drawing environment settings. -static void Command_FBFill(const uint32 *cb) -{ - int32 r = cb[0] & 0xFF; - int32 g = (cb[0] >> 8) & 0xFF; - int32 b = (cb[0] >> 16) & 0xFF; - const uint16 fill_value = ((r >> 3) << 0) | ((g >> 3) << 5) | ((b >> 3) << 10); - - int32 destX = (cb[1] >> 0) & 0x3F0; - int32 destY = (cb[1] >> 16) & 0x3FF; - - int32 width = (((cb[2] >> 0) & 0x3FF) + 0xF) & ~0xF; - int32 height = (cb[2] >> 16) & 0x1FF; - - //printf("[GPU] FB Fill %d:%d w=%d, h=%d\n", destX, destY, width, height); - DrawTimeAvail -= 46; // Approximate - - for(int32 y = 0; y < height; y++) - { - const int32 d_y = (y + destY) & 511; - - if(LineSkipTest(d_y)) - continue; - - DrawTimeAvail -= (width >> 3) + 9; - - for(int32 x = 0; x < width; x++) - { - const int32 d_x = (x + destX) & 1023; - - GPURAM[d_y][d_x] = fill_value; - } - } -} - -static void Command_FBCopy(const uint32 *cb) -{ - int32 sourceX = (cb[1] >> 0) & 0x3FF; - int32 sourceY = (cb[1] >> 16) & 0x3FF; - int32 destX = (cb[2] >> 0) & 0x3FF; - int32 destY = (cb[2] >> 16) & 0x3FF; - - int32 width = (cb[3] >> 0) & 0x3FF; - int32 height = (cb[3] >> 16) & 0x1FF; - - if(!width) - width = 0x400; - - if(!height) - height = 0x200; - - InvalidateTexCache(); - //printf("FB Copy: %d %d %d %d %d %d\n", sourceX, sourceY, destX, destY, width, height); - - DrawTimeAvail -= (width * height) * 2; - - for(int32 y = 0; y < height; y++) - { - for(int32 x = 0; x < width; x += 128) - { - const int32 chunk_x_max = std::min(width - x, 128); - uint16 tmpbuf[128]; // TODO: Check and see if the GPU is actually (ab)using the texture cache(doesn't seem to be affecting CLUT cache...). - - for(int32 chunk_x = 0; chunk_x < chunk_x_max; chunk_x++) - { - int32 s_y = (y + sourceY) & 511; - int32 s_x = (x + chunk_x + sourceX) & 1023; - - tmpbuf[chunk_x] = GPURAM[s_y][s_x]; - } - - for(int32 chunk_x = 0; chunk_x < chunk_x_max; chunk_x++) - { - int32 d_y = (y + destY) & 511; - int32 d_x = (x + chunk_x + destX) & 1023; - - if(!(GPURAM[d_y][d_x] & MaskEvalAND)) - GPURAM[d_y][d_x] = tmpbuf[chunk_x] | MaskSetOR; - } - } - } -} - -static void Command_FBWrite(const uint32 *cb) -{ - assert(InCmd == PS_GPU::INCMD_NONE); - - FBRW_X = (cb[1] >> 0) & 0x3FF; - FBRW_Y = (cb[1] >> 16) & 0x3FF; - - FBRW_W = (cb[2] >> 0) & 0x3FF; - FBRW_H = (cb[2] >> 16) & 0x1FF; - - if(!FBRW_W) - FBRW_W = 0x400; - - if(!FBRW_H) - FBRW_H = 0x200; - - FBRW_CurX = FBRW_X; - FBRW_CurY = FBRW_Y; - - InvalidateTexCache(); - - if(FBRW_W != 0 && FBRW_H != 0) - InCmd = PS_GPU::INCMD_FBWRITE; -} - -// -// FBRead: PS1 GPU in SCPH-5501 gives odd, inconsistent results when raw_height == 0, or -// raw_height != 0x200 && (raw_height & 0x1FF) == 0 -// -static void Command_FBRead(const uint32 *cb) -{ - assert(InCmd == PS_GPU::INCMD_NONE); - - FBRW_X = (cb[1] >> 0) & 0x3FF; - FBRW_Y = (cb[1] >> 16) & 0x3FF; - - FBRW_W = (cb[2] >> 0) & 0x3FF; - FBRW_H = (cb[2] >> 16) & 0x3FF; - - if(!FBRW_W) - FBRW_W = 0x400; - - if(FBRW_H > 0x200) - FBRW_H &= 0x1FF; - - FBRW_CurX = FBRW_X; - FBRW_CurY = FBRW_Y; - - InvalidateTexCache(); - - if(FBRW_W != 0 && FBRW_H != 0) - InCmd = PS_GPU::INCMD_FBREAD; -} - -/* -INLINE void PS_GPU::RecalcTexPageStuff(uint32 tpage) -{ - - -} -*/ - -static void SetTPage(const uint32 cmdw) -{ - const unsigned NewTexPageX = (cmdw & 0xF) * 64; - const unsigned NewTexPageY = (cmdw & 0x10) * 16; - const unsigned NewTexMode = (cmdw >> 7) & 0x3; - - abr = (cmdw >> 5) & 0x3; - - if(!NewTexMode != !TexMode || NewTexPageX != TexPageX || NewTexPageY != TexPageY) - { - InvalidateTexCache(); - } - - if(TexDisableAllowChange) - { - bool NewTexDisable = (cmdw >> 11) & 1; - - if(NewTexDisable != TexDisable) - InvalidateTexCache(); - - TexDisable = NewTexDisable; - //printf("TexDisable: %02x\n", TexDisable); - } - - TexPageX = NewTexPageX; - TexPageY = NewTexPageY; - TexMode = NewTexMode; - - // - // - RecalcTexWindowStuff(); -} - -static void Command_DrawMode(const uint32 *cb) -{ - const uint32 cmdw = *cb; - - SetTPage(cmdw); - - SpriteFlip = cmdw & 0x3000; - dtd = (cmdw >> 9) & 1; - dfe = (cmdw >> 10) & 1; - - //printf("*******************DFE: %d -- scanline=%d\n", dfe, scanline); -} - -static void Command_TexWindow(const uint32 *cb) -{ - tww = (*cb & 0x1F); - twh = ((*cb >> 5) & 0x1F); - twx = ((*cb >> 10) & 0x1F); - twy = ((*cb >> 15) & 0x1F); - - RecalcTexWindowStuff(); -} - -static void Command_Clip0(const uint32 *cb) -{ - ClipX0 = *cb & 1023; - ClipY0 = (*cb >> 10) & 1023; - - //fprintf(stderr, "[GPU] Clip0: x=%d y=%d, raw=0x%08x --- %d\n", ClipX0, ClipY0, *cb, scanline); -} - -static void Command_Clip1(const uint32 *cb) -{ - ClipX1 = *cb & 1023; - ClipY1 = (*cb >> 10) & 1023; - - //fprintf(stderr, "[GPU] Clip1: x=%d y=%d, raw=0x%08x --- %d\n", ClipX1, ClipY1, *cb, scanline); -} - -static void Command_DrawingOffset(const uint32 *cb) -{ - OffsX = sign_x_to_s32(11, (*cb & 2047)); - OffsY = sign_x_to_s32(11, ((*cb >> 11) & 2047)); - - //fprintf(stderr, "[GPU] Drawing offset: x=%d y=%d, raw=0x%08x --- %d\n", OffsX, OffsY, *cb, scanline); -} - -static void Command_MaskSetting(const uint32 *cb) -{ - //printf("Mask setting: %08x\n", *cb); - MaskSetOR = (*cb & 1) ? 0x8000 : 0x0000; - MaskEvalAND = (*cb & 2) ? 0x8000 : 0x0000; -} - -static void Command_ClearCache(const uint32 *cb) -{ - InvalidateCache(); -} - -static void Command_IRQ(const uint32 *cb) -{ - IRQPending = true; - IRQ_Assert(IRQ_GPU, IRQPending); -} - -namespace PS_GPU_INTERNAL -{ -MDFN_HIDE extern const CTEntry Commands_00_1F[0x20] = -{ - /* 0x00 */ - NULLCMD(), - OTHER_HELPER(1, 2, false, Command_ClearCache), - OTHER_HELPER(3, 3, false, Command_FBFill), - - NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), - NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), - - /* 0x10 */ - NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), - NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), - - /* 0x1F */ - OTHER_HELPER(1, 1, false, Command_IRQ) -}; - -MDFN_HIDE extern const CTEntry Commands_80_FF[0x80] = -{ - /* 0x80 ... 0x9F */ - OTHER_HELPER_X32(4, 2, false, Command_FBCopy), - - /* 0xA0 ... 0xBF */ - OTHER_HELPER_X32(3, 2, false, Command_FBWrite), - - /* 0xC0 ... 0xDF */ - OTHER_HELPER_X32(3, 2, false, Command_FBRead), - - /* 0xE0 */ - - NULLCMD(), - OTHER_HELPER(1, 2, false, Command_DrawMode), - OTHER_HELPER(1, 2, false, Command_TexWindow), - OTHER_HELPER(1, 1, true, Command_Clip0), - OTHER_HELPER(1, 1, true, Command_Clip1), - OTHER_HELPER(1, 1, true, Command_DrawingOffset), - OTHER_HELPER(1, 2, false, Command_MaskSetting), - - NULLCMD(), - NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), - - /* 0xF0 */ - NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), - NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD() -}; -} - -static void ProcessFIFO(void) -{ - if(!BlitterFIFO.CanRead()) - return; - - switch(InCmd) - { - default: - abort(); - break; - - case PS_GPU::INCMD_NONE: - break; - - case PS_GPU::INCMD_FBREAD: - PSX_WARNING("[GPU] Command FIFO not empty while in FB Read?!"); - return; - - case PS_GPU::INCMD_FBWRITE: - { - uint32 InData = BlitterFIFO.Read(); - - for(int i = 0; i < 2; i++) - { - if(!(GPURAM[FBRW_CurY & 511][FBRW_CurX & 1023] & MaskEvalAND)) - GPURAM[FBRW_CurY & 511][FBRW_CurX & 1023] = InData | MaskSetOR; - - FBRW_CurX++; - if(FBRW_CurX == (FBRW_X + FBRW_W)) - { - FBRW_CurX = FBRW_X; - FBRW_CurY++; - if(FBRW_CurY == (FBRW_Y + FBRW_H)) - { - InCmd = PS_GPU::INCMD_NONE; - break; // Break out of the for() loop. - } - } - InData >>= 16; - } - return; - } - break; - - case PS_GPU::INCMD_QUAD: - { - if(DrawTimeAvail < 0) - return; - - const uint32 cc = InCmd_CC; - const CTEntry *command = &Commands[cc]; - unsigned vl = 1 + (bool)(cc & 0x4) + (bool)(cc & 0x10); - uint32 CB[3]; - - if(BlitterFIFO.CanRead() >= vl) - { - for(unsigned i = 0; i < vl; i++) - { - CB[i] = BlitterFIFO.Read(); - } - - command->func[abr][TexMode | (MaskEvalAND ? 0x4 : 0x0)](CB); - } - return; - } - break; - - case PS_GPU::INCMD_PLINE: - { - if(DrawTimeAvail < 0) - return; - - const uint32 cc = InCmd_CC; - const CTEntry *command = &Commands[cc]; - unsigned vl = 1 + (bool)(InCmd_CC & 0x10); - uint32 CB[2]; - - if((BlitterFIFO.Peek() & 0xF000F000) == 0x50005000) - { - BlitterFIFO.Read(); - InCmd = PS_GPU::INCMD_NONE; - return; - } - - if(BlitterFIFO.CanRead() >= vl) - { - for(unsigned i = 0; i < vl; i++) - { - CB[i] = BlitterFIFO.Read(); - } - - command->func[abr][TexMode | (MaskEvalAND ? 0x4 : 0x0)](CB); - } - return; - } - break; - } - - const uint32 cc = BlitterFIFO.Peek() >> 24; - const CTEntry *command = &Commands[cc]; - - if(DrawTimeAvail < 0 && !command->ss_cmd) - return; - - if(BlitterFIFO.CanRead() >= command->len) - { - uint32 CB[0x10]; - - for(unsigned i = 0; i < command->len; i++) - CB[i] = BlitterFIFO.Read(); - - if(!command->ss_cmd) - DrawTimeAvail -= 2; - -#if 0 - PSX_WARNING("[GPU] Command: %08x %s %d %d %d", CB[0], command->name, command->len, scanline, DrawTimeAvail); - if(1) - { - printf("[GPU] "); - for(unsigned i = 0; i < command->len; i++) - printf("0x%08x ", CB[i]); - printf("\n"); - } -#endif - // A very very ugly kludge to support texture mode specialization. fixme/cleanup/SOMETHING in the future. - if(cc >= 0x20 && cc <= 0x3F && (cc & 0x4)) - { - // - // Don't alter SpriteFlip here. - // - SetTPage(CB[4 + ((cc >> 4) & 0x1)] >> 16); - } - - if(!command->func[abr][TexMode]) - { - if(CB[0]) - PSX_WARNING("[GPU] Unknown command: %08x, %d", CB[0], scanline); - } - else - { - command->func[abr][TexMode | (MaskEvalAND ? 0x4 : 0x0)](CB); - } - } -} - -static void WriteCB(uint32 InData) -{ - if(BlitterFIFO.CanRead() >= 0x10 && (InCmd != PS_GPU::INCMD_NONE || (BlitterFIFO.CanRead() - 0x10) >= Commands[BlitterFIFO.Peek() >> 24].fifo_fb_len)) - { - PSX_DBG(PSX_DBG_WARNING, "GPU FIFO overflow!!!\n"); - return; - } - - BlitterFIFO.Write(InData); - ProcessFIFO(); -} - -MDFN_FASTCALL void GPU_Write(const pscpu_timestamp_t timestamp, uint32 A, uint32 V) -{ - V <<= (A & 3) * 8; - - if(A & 4) // GP1 ("Control") - { - uint32 command = V >> 24; - - V &= 0x00FFFFFF; - - //PSX_WARNING("[GPU] Control command: %02x %06x %d", command, V, scanline); - - switch(command) - { - /* - 0x40-0xFF do NOT appear to be mirrors, at least not on my PS1's GPU. - */ - default: PSX_WARNING("[GPU] Unknown control command %02x - %06x", command, V); - break; - - case 0x00: // Reset GPU - //printf("\n\n************ Soft Reset %u ********* \n\n", scanline); - SoftReset(); - break; - - case 0x01: // Reset command buffer - if(DrawTimeAvail < 0) - DrawTimeAvail = 0; - BlitterFIFO.Flush(); - InCmd = PS_GPU::INCMD_NONE; - break; - - case 0x02: // Acknowledge IRQ - IRQPending = false; - IRQ_Assert(IRQ_GPU, IRQPending); - break; - - case 0x03: // Display enable - DisplayOff = V & 1; - break; - - case 0x04: // DMA Setup - DMAControl = V & 0x3; - break; - - case 0x05: // Start of display area in framebuffer - DisplayFB_XStart = V & 0x3FE; // Lower bit is apparently ignored. - DisplayFB_YStart = (V >> 10) & 0x1FF; - break; - - case 0x06: // Horizontal display range - HorizStart = V & 0xFFF; - HorizEnd = (V >> 12) & 0xFFF; - break; - - case 0x07: - VertStart = V & 0x3FF; - VertEnd = (V >> 10) & 0x3FF; - break; - - case 0x08: - //printf("\n\nDISPLAYMODE SET: 0x%02x, %u *************************\n\n\n", V & 0xFF, scanline); - DisplayMode = V & 0xFF; - break; - - case 0x09: - TexDisableAllowChange = V & 1; - break; - - case 0x10: // GPU info(?) - switch(V & 0xF) - { - // DataReadBuffer must remain unchanged for any unhandled GPU info index. - default: break; - - case 0x2: DataReadBufferEx &= 0xFFF00000; - DataReadBufferEx |= (tww << 0) | (twh << 5) | (twx << 10) | (twy << 15); - DataReadBuffer = DataReadBufferEx; - break; - - case 0x3: DataReadBufferEx &= 0xFFF00000; - DataReadBufferEx |= (ClipY0 << 10) | ClipX0; - DataReadBuffer = DataReadBufferEx; - break; - - case 0x4: DataReadBufferEx &= 0xFFF00000; - DataReadBufferEx |= (ClipY1 << 10) | ClipX1; - DataReadBuffer = DataReadBufferEx; - break; - - case 0x5: DataReadBufferEx &= 0xFFC00000; - DataReadBufferEx |= (OffsX & 2047) | ((OffsY & 2047) << 11); - DataReadBuffer = DataReadBufferEx; - break; - - case 0x7: DataReadBufferEx = 2; - DataReadBuffer = DataReadBufferEx; - break; - - case 0x8: DataReadBufferEx = 0; - DataReadBuffer = DataReadBufferEx; - break; - } - //fprintf(stderr, "[GPU] CC 0x10:0x%02x, DRB=0x%02x\n", V & 0xF, DataReadBuffer); - break; - - } - } - else // GP0 ("Data") - { - //uint32 command = V >> 24; - //printf("Meow command: %02x\n", command); - //assert(!(DMAControl & 2)); - WriteCB(V); - } -} - - -MDFN_FASTCALL void GPU_WriteDMA(uint32 V) -{ - WriteCB(V); -} - -static INLINE uint32 ReadData(void) -{ - if(InCmd == PS_GPU::INCMD_FBREAD) - { - DataReadBufferEx = 0; - for(int i = 0; i < 2; i++) - { - DataReadBufferEx |= GPURAM[FBRW_CurY & 511][FBRW_CurX & 1023] << (i * 16); - - FBRW_CurX++; - if(FBRW_CurX == (FBRW_X + FBRW_W)) - { - if((FBRW_CurY + 1) == (FBRW_Y + FBRW_H)) - { - InCmd = PS_GPU::INCMD_NONE; - } - else - { - FBRW_CurY++; - FBRW_CurX = FBRW_X; - } - } - } - - return DataReadBufferEx; - } - - return DataReadBuffer; -} - -uint32 GPU_ReadDMA(void) -{ - return ReadData(); -} - -MDFN_FASTCALL uint32 GPU_Read(const pscpu_timestamp_t timestamp, uint32 A) -{ - uint32 ret = 0; - - if(A & 4) // Status - { - ret = (((DisplayMode << 1) & 0x7F) | ((DisplayMode >> 6) & 1)) << 16; - - ret |= (DisplayMode & 0x80) << 7; - - ret |= DMAControl << 29; - - ret |= (DisplayFB_CurLineYReadout & 1) << 31; - - ret |= (!field) << 13; - - if(DMAControl & 0x02) - ret |= 1 << 25; - - ret |= IRQPending << 24; - - ret |= DisplayOff << 23; - - if(InCmd == PS_GPU::INCMD_NONE && DrawTimeAvail >= 0 && BlitterFIFO.CanRead() == 0x00) // GPU idle bit. - ret |= 1 << 26; - - if(InCmd == PS_GPU::INCMD_FBREAD) // Might want to more accurately emulate this in the future? - ret |= (1 << 27); - - ret |= GPU_CalcFIFOReadyBit() << 28; // FIFO has room bit? (kinda). - - // - // - ret |= TexPageX >> 6; - ret |= TexPageY >> 4; - ret |= abr << 5; - ret |= TexMode << 7; - - ret |= dtd << 9; - ret |= dfe << 10; - - if(MaskSetOR) - ret |= 1 << 11; - - if(MaskEvalAND) - ret |= 1 << 12; - - ret |= TexDisable << 15; - } - else // "Data" - ret = ReadData(); - - if(DMAControl & 2) - { - //PSX_WARNING("[GPU READ WHEN (DMACONTROL&2)] 0x%08x - ret=0x%08x, scanline=%d", A, ret, scanline); - } - - return(ret >> ((A & 3) * 8)); -} - -#if 0 -static INLINE uint32 MDFN_NOWARN_UNUSED ShiftHelper(uint32 val, int shamt, uint32 mask) -{ - if(shamt < 0) - return((val >> (-shamt)) & mask); - else - return((val << shamt) & mask); -} -#endif - -#pragma GCC push_options -#pragma GCC optimize("no-unroll-loops,no-peel-loops,no-crossjumping") -static INLINE void ReorderRGB_Var(uint32 out_Rshift, uint32 out_Gshift, uint32 out_Bshift, bool bpp24, const uint16 *src, uint32 *dest, const int32 dx_start, const int32 dx_end, int32 fb_x) -{ - if(bpp24) // 24bpp - { - for(int32 x = dx_start; MDFN_LIKELY(x < dx_end); x++) - { - uint32 srcpix; - - srcpix = src[(fb_x >> 1) + 0] | (src[((fb_x >> 1) + 1) & 0x7FF] << 16); - srcpix >>= (fb_x & 1) * 8; - - dest[x] = (((srcpix >> 0) << out_Rshift) & (0xFF << out_Rshift)) | (((srcpix >> 8) << out_Gshift) & (0xFF << out_Gshift)) | - (((srcpix >> 16) << out_Bshift) & (0xFF << out_Bshift)); - - fb_x = (fb_x + 3) & 0x7FF; - } - } // 15bpp - else - { - for(int32 x = dx_start; MDFN_LIKELY(x < dx_end); x++) - { - uint32 srcpix = src[fb_x >> 1]; - -#if 1 - dest[x] = OutputLUT[(uint8)srcpix] | (OutputLUT + 256)[(srcpix >> 8) & 0x7F]; -#else - dest[x] = ShiftHelper(srcpix, out_Rshift + 3 - 0, (0xF8 << out_Rshift)) | - ShiftHelper(srcpix, out_Gshift + 3 - 5, (0xF8 << out_Gshift)) | - ShiftHelper(srcpix, out_Bshift + 3 - 10, (0xF8 << out_Bshift)); -#endif - fb_x = (fb_x + 2) & 0x7FF; - } - } - -} - -template -static NO_INLINE void ReorderRGB(bool bpp24, const uint16 *src, uint32 *dest, const int32 dx_start, const int32 dx_end, int32 fb_x) -{ - ReorderRGB_Var(out_Rshift, out_Gshift, out_Bshift, bpp24, src, dest, dx_start, dx_end, fb_x); -} -#pragma GCC pop_options - -MDFN_FASTCALL pscpu_timestamp_t GPU_Update(const pscpu_timestamp_t sys_timestamp) -{ - const uint32 dmc = (DisplayMode & 0x40) ? 4 : (DisplayMode & 0x3); - const uint32 dmw = HVisMax / DotClockRatios[dmc]; // Must be <= (768 - drxbo) - const uint32 dmpa = HVisOffs / DotClockRatios[dmc]; // Must be <= drxbo - - int32 sys_clocks = sys_timestamp - lastts; - int32 gpu_clocks; - - //printf("GPUISH: %d\n", sys_timestamp - lastts); - - if(!sys_clocks) - goto TheEnd; - - DrawTimeAvail += sys_clocks << 1; - - if(DrawTimeAvail > 256) - DrawTimeAvail = 256; - - ProcessFIFO(); - - //puts("GPU Update Start"); - - GPUClockCounter += (uint64)sys_clocks * GPUClockRatio; - - gpu_clocks = GPUClockCounter >> 16; - GPUClockCounter -= gpu_clocks << 16; - - while(gpu_clocks > 0) - { - int32 chunk_clocks = gpu_clocks; - int32 dot_clocks; - - if(chunk_clocks > LineClockCounter) - { - //printf("Chunk: %u, LCC: %u\n", chunk_clocks, LineClockCounter); - chunk_clocks = LineClockCounter; - } - - gpu_clocks -= chunk_clocks; - LineClockCounter -= chunk_clocks; - - DotClockCounter += chunk_clocks; - dot_clocks = DotClockCounter / DotClockRatios[DisplayMode & 0x3]; - DotClockCounter -= dot_clocks * DotClockRatios[DisplayMode & 0x3]; - - TIMER_AddDotClocks(dot_clocks); - - - if(!LineClockCounter) - { - PSX_SetEventNT(PSX_EVENT_TIMER, TIMER_Update(sys_timestamp)); // We could just call this at the top of GPU_Update(), but do it here for slightly less CPU usage(presumably). - - LinePhase = (LinePhase + 1) & 1; - - if(LinePhase) - { - TIMER_SetHRetrace(true); - LineClockCounter = 200; - TIMER_ClockHRetrace(); - } - else - { - const unsigned int FirstVisibleLine = LineVisFirst + (HardwarePALType ? 20 : 16); - const unsigned int VisibleLineCount = LineVisLast + 1 - LineVisFirst; //HardwarePALType ? 288 : 240; - - TIMER_SetHRetrace(false); - - if(DisplayMode & 0x08) - LineClockCounter = 3405 - 200; - else - LineClockCounter = 3412 + PhaseChange - 200; - - scanline = (scanline + 1) % LinesPerField; - PhaseChange = !PhaseChange; - -#ifdef WANT_DEBUGGER - DBG_GPUScanlineHook(scanline); -#endif - - // - // - // - if(scanline == (HardwarePALType ? 308 : 256)) // Will need to be redone if we ever allow for visible vertical overscan with NTSC. - { - if(sl_zero_reached) - { - //printf("Req Exit(visible fallthrough case): %u\n", scanline); - PSX_RequestMLExit(); - } - } - - if(scanline == (LinesPerField - 1)) - { - if(sl_zero_reached) - { - //printf("Req Exit(final fallthrough case): %u\n", scanline); - PSX_RequestMLExit(); - } - - if(DisplayMode & 0x20) - field = !field; - else - field = 0; - } - - if(scanline == 0) - { - assert(sl_zero_reached == false); - sl_zero_reached = true; - - if(DisplayMode & 0x20) - { - skip = false; - - if(DisplayMode & 0x08) // PAL - LinesPerField = 313 - field; - else // NTSC - LinesPerField = 263 - field; - } - else - { - field = 0; // May not be the correct place for this? - - if(DisplayMode & 0x08) // PAL - LinesPerField = 314; - else // NTSC - LinesPerField = 263; - } - - if(espec) - { - if((bool)(DisplayMode & 0x08) != HardwarePALType) - { - const uint32 black = surface->MakeColor(0, 0, 0); - - DisplayRect->x = 0; - DisplayRect->y = 0; - DisplayRect->w = 384; - DisplayRect->h = VisibleLineCount; - - for(int32 y = 0; y < DisplayRect->h; y++) - { - uint32 *dest = surface->pixels + y * surface->pitch32; - - LineWidths[y] = 384; - - for(int32 x = 0; x < 384; x++) - { - dest[x] = black; - } - } - - if(!DisplayOff) - { - char buffer[256]; - printf(("VIDEO STANDARD MISMATCH")); - // DrawText(surface, 0, (DisplayRect->h / 2) - (13 / 2), buffer, - //surface->MakeColor(0x00, 0xFF, 0x00), MDFN_FONT_6x13_12x13, DisplayRect->w); - } - } - else - { - const uint32 black = surface->MakeColor(0, 0, 0); - - espec->InterlaceOn = (bool)(DisplayMode & 0x20); - espec->InterlaceField = (bool)(DisplayMode & 0x20) && field; - - DisplayRect->x = drxbo; - DisplayRect->y = 0; - DisplayRect->w = 0; - DisplayRect->h = VisibleLineCount << (bool)(DisplayMode & 0x20); - - // Clear ~0 state. - LineWidths[0] = 0; - - for(int i = 0; i < (DisplayRect->y + DisplayRect->h); i++) - { - surface->pixels[i * surface->pitch32 + drxbo + 0] = - surface->pixels[i * surface->pitch32 + drxbo + 1] = black; - LineWidths[i] = 2; - } - } - } - } - - // - // Don't mess with the order of evaluation of these scanline == VertXXX && (InVblankwhatever) if statements and the following IRQ/timer vblank stuff - // unless you know what you're doing!!! (IE you've run further tests to refine the behavior) - // - if(scanline == VertEnd && !InVBlank) - { - if(sl_zero_reached) - { - // Gameplay in Descent(NTSC) has vblank at scanline 236 - // - // Mikagura Shoujo Tanteidan has vblank at scanline 192 during intro - // FMV(which we don't handle here because low-latency in that case is not so important). - // - if(scanline >= (HardwarePALType ? 260 : 232)) - { - //printf("Req Exit(vblank case): %u\n", scanline); - PSX_RequestMLExit(); - } - else - { - //printf("VBlank too early, chickening out early exit: %u!\n", scanline); - } - } - - //printf("VBLANK: %u\n", scanline); - InVBlank = true; - - DisplayFB_CurYOffset = 0; - - if((DisplayMode & 0x24) == 0x24) - field_ram_readout = !field; - else - field_ram_readout = 0; - } - - if(scanline == VertStart && InVBlank) - { - InVBlank = false; - - // Note to self: X-Men Mutant Academy relies on this being set on the proper scanline in 480i mode(otherwise it locks up on startup). - //if(HeightMode) - // DisplayFB_CurYOffset = field; - } - - IRQ_Assert(IRQ_VBLANK, InVBlank); - TIMER_SetVBlank(InVBlank); - // - // - // - - // Needs to occur even in vblank. - // Not particularly confident about the timing of this in regards to vblank and the upper bit(ODE) of the GPU status port, though the test that - // showed an oddity was pathological in that VertEnd < VertStart in it. - if((DisplayMode & 0x24) == 0x24) - DisplayFB_CurLineYReadout = (DisplayFB_YStart + (DisplayFB_CurYOffset << 1) + (InVBlank ? 0 : field_ram_readout)) & 0x1FF; - else - DisplayFB_CurLineYReadout = (DisplayFB_YStart + DisplayFB_CurYOffset) & 0x1FF; - - if((bool)(DisplayMode & 0x08) == HardwarePALType && scanline >= FirstVisibleLine && scanline < (FirstVisibleLine + VisibleLineCount) && !skip && espec) - { - const uint32 black = surface->MakeColor(0, 0, 0); - uint32 *dest; - int32 dest_line; - int32 fb_x = DisplayFB_XStart * 2; - int32 dx_start = HorizStart, dx_end = HorizEnd; - - dest_line = ((scanline - FirstVisibleLine) << espec->InterlaceOn) + espec->InterlaceField; - dest = surface->pixels + (drxbo - dmpa) + dest_line * surface->pitch32; - - if(dx_end < dx_start) - dx_end = dx_start; - - dx_start = dx_start / DotClockRatios[dmc]; - dx_end = dx_end / DotClockRatios[dmc]; - - dx_start -= hmc_to_visible / DotClockRatios[dmc]; - dx_end -= hmc_to_visible / DotClockRatios[dmc]; - dx_start += 7; - dx_end += 7; - - if(dx_start < 0) - { - fb_x -= dx_start * ((DisplayMode & 0x10) ? 3 : 2); - fb_x &= 0x7FF; //0x3FF; - dx_start = 0; - } - - if((uint32)dx_end > dmw) - dx_end = dmw; - - if(InVBlank || DisplayOff) - dx_start = dx_end = 0; - - LineWidths[dest_line] = dmw - dmpa * 2; - // - int32 nca_lw = 0, nca_dest_adj = 0; - - if(!CorrectAspect) - { - nca_lw = NCABaseW << (bool)(dmc & 0x2); - nca_dest_adj = (nca_lw - LineWidths[dest_line]) >> 1; - assert(nca_dest_adj >= 0); - dest += nca_dest_adj; - } - - { - const uint16 *src = GPURAM[DisplayFB_CurLineYReadout]; - - for(int32 x = 0; x < dx_start; x++) - dest[x] = black; - - //printf("%d %d %d - %d %d\n", scanline, dx_start, dx_end, HorizStart, HorizEnd); - if(surface->format.Rshift == 0 && surface->format.Gshift == 8 && surface->format.Bshift == 16) - ReorderRGB<0, 8, 16>(DisplayMode & 0x10, src, dest, dx_start, dx_end, fb_x); - else if(surface->format.Rshift == 8 && surface->format.Gshift == 16 && surface->format.Bshift == 24) - ReorderRGB<8, 16, 24>(DisplayMode & 0x10, src, dest, dx_start, dx_end, fb_x); - else if(surface->format.Rshift == 16 && surface->format.Gshift == 8 && surface->format.Bshift == 0) - ReorderRGB<16, 8, 0>(DisplayMode & 0x10, src, dest, dx_start, dx_end, fb_x); - else if(surface->format.Rshift == 24 && surface->format.Gshift == 16 && surface->format.Bshift == 8) - ReorderRGB<24, 16, 8>(DisplayMode & 0x10, src, dest, dx_start, dx_end, fb_x); - else - ReorderRGB_Var(surface->format.Rshift, surface->format.Gshift, surface->format.Bshift, DisplayMode & 0x10, src, dest, dx_start, dx_end, fb_x); - - for(uint32 x = dx_end; x < dmw; x++) - dest[x] = black; - } - - //if(scanline == 64) - // printf("%u\n", sys_timestamp - ((uint64)gpu_clocks * 65536) / GPUClockRatio); - - PSX_GPULineHook(sys_timestamp, sys_timestamp - ((uint64)gpu_clocks * 65536) / GPUClockRatio, scanline == 0, dest, &surface->format, dmw, (hmc_to_visible - 220) / DotClockRatios[dmc], (HardwarePALType ? 53203425 : 53693182) / DotClockRatios[dmc], DotClockRatios[dmc]); - - if(!CorrectAspect) - { - dest = surface->pixels + drxbo + dest_line * surface->pitch32; - - for(int32 x = 0; x < nca_dest_adj; x++) - dest[x] = black; //rand(); - - for(int32 x = nca_dest_adj + LineWidths[dest_line]; x < nca_lw; x++) - dest[x] = black; //rand(); - - LineWidths[dest_line] = nca_lw; - } - } - else - { - PSX_GPULineHook(sys_timestamp, sys_timestamp - ((uint64)gpu_clocks * 65536) / GPUClockRatio, scanline == 0, NULL, NULL, 0, 0, 0, 0); - } - - if(!InVBlank) - { - DisplayFB_CurYOffset = (DisplayFB_CurYOffset + 1) & 0x1FF; - } - } - PSX_SetEventNT(PSX_EVENT_TIMER, TIMER_Update(sys_timestamp)); // Mostly so the next event time gets recalculated properly in regards to our calls - // to TIMER_SetVBlank() and TIMER_SetHRetrace(). - } // end if(!LineClockCounter) - } // end while(gpu_clocks > 0) - - //puts("GPU Update End"); - - TheEnd: - lastts = sys_timestamp; - - { - int32 next_dt = LineClockCounter; - - next_dt = (((int64)next_dt << 16) - GPUClockCounter + GPUClockRatio - 1) / GPUClockRatio; - - next_dt = std::max(1, next_dt); - next_dt = std::min(128, next_dt); - - //printf("%d\n", next_dt); - - return(sys_timestamp + next_dt); - } -} - -void GPU_GetGunXTranslation(float* scale, float* offs) -{ - *scale = 1.0; - *offs = HVisOffs; - - if(!CorrectAspect) - { - const uint32 dmc = (DisplayMode & 0x40) ? 4 : (DisplayMode & 0x3); - const uint32 dmw = HVisMax / DotClockRatios[dmc]; // Must be <= (768 - drxbo) - const uint32 dmpa = HVisOffs / DotClockRatios[dmc]; // Must be <= drxbo - // - const int32 lw = dmw - dmpa * 2; - const int32 nca_lw = NCABaseW << (bool)(dmc & 0x2); - int32 nca_dest_adj = (nca_lw - lw) >> 1; - *scale = (float)nca_lw / lw; //(float)(DotClockRatios[dmc] << (bool)(dmc & 0x2)) / 7; - *offs -= nca_dest_adj * DotClockRatios[dmc]; - //printf("%f %d %d\n", *scale, lw, nca_lw); - } -} -void GPU_StartFrame(EmulateSpecStruct *espec_arg) -{ - sl_zero_reached = false; - - if(!espec_arg) - { - espec = NULL; - surface = NULL; - DisplayRect = NULL; - LineWidths = NULL; - skip = true; - return; - } - - espec = espec_arg; - - surface = espec->surface; - DisplayRect = &espec->DisplayRect; - LineWidths = espec->LineWidths; - skip = espec->skip; - - if(espec->VideoFormatChanged) - { - const auto& f = surface->format; - - for(int rc = 0; rc < 0x8000; rc++) - { - const uint8 a = rc; - const uint8 b = rc >> 8; - - (OutputLUT + 0)[a] = ((a & 0x1F) << (3 + f.Rshift)) | ((a >> 5) << (3 + f.Gshift)); - (OutputLUT + 256)[b] = ((b & 0x3) << (6 + f.Gshift)) | (((b >> 2) & 0x1F) << (3 + f.Bshift)); - } - } -} - -SYNCFUNC(PS_GPU) -{ - NSS(GPURAM); - - NSS(CLUT_Cache); - NSS(CLUT_Cache_VB); - NSS(TexCache); - - NSS(DMAControl); - - NSS(ClipX0); - NSS(ClipY0); - NSS(ClipX1); - NSS(ClipY1); - - NSS(OffsX); - NSS(OffsY); - - NSS(dtd); - NSS(dfe); - - NSS(MaskSetOR); - NSS(MaskEvalAND); - - NSS(TexDisable); - NSS(TexDisableAllowChange); - - NSS(tww); - NSS(twh); - NSS(twx); - NSS(twy); - - NSS(TexPageX); - NSS(TexPageY); - - NSS(SpriteFlip); - - NSS(abr); - NSS(TexMode); - - SSS(BlitterFIFO); - - NSS(DataReadBuffer); - NSS(DataReadBufferEx); - - NSS(IRQPending); - - NSS(InCmd); - NSS(InCmd_CC); - - NSS(InQuad_F3Vertices); - - NSS(InPLine_PrevPoint); - - NSS(FBRW_X); - NSS(FBRW_Y); - NSS(FBRW_W); - NSS(FBRW_H); - NSS(FBRW_CurY); - NSS(FBRW_CurX); - - NSS(DisplayMode); - NSS(DisplayOff); - NSS(DisplayFB_XStart); - NSS(DisplayFB_YStart); - - NSS(HorizStart); - NSS(HorizEnd); - - NSS(VertStart); - NSS(VertEnd); - - NSS(DisplayFB_CurYOffset); - NSS(DisplayFB_CurLineYReadout); - - NSS(InVBlank); - - NSS(LinesPerField); - NSS(scanline); - NSS(field); - NSS(field_ram_readout); - NSS(PhaseChange); - - NSS(DotClockCounter); - - NSS(GPUClockCounter); - NSS(LineClockCounter); - NSS(LinePhase); - - NSS(DrawTimeAvail); - - if(isReader) - { - //BIZHAWK: not needed, since we can sync TexCache directly - //for(unsigned i = 0; i < 256; i++) - //{ - // TexCache[i].Tag = TexCache_Tag[i]; - - // for(unsigned j = 0; j < 4; j++) - // TexCache[i].Data[j] = TexCache_Data[i][j]; - //} - - RecalcTexWindowStuff(); - BlitterFIFO.SaveStatePostLoad(); - - HorizStart &= 0xFFF; - HorizEnd &= 0xFFF; - - DisplayFB_CurYOffset &= 0x1FF; - DisplayFB_CurLineYReadout &= 0x1FF; - - TexPageX &= 0xF * 64; - TexPageY &= 0x10 * 16; - TexMode &= 0x3; - abr &= 0x3; - - ClipX0 &= 1023; - ClipY0 &= 1023; - ClipX1 &= 1023; - ClipY1 &= 1023; - - OffsX = sign_x_to_s32(11, OffsX); - OffsY = sign_x_to_s32(11, OffsY); - - IRQ_Assert(IRQ_GPU, IRQPending); - } - -} - -} - diff --git a/psx/octoshock/psx/gpu.h b/psx/octoshock/psx/gpu.h deleted file mode 100644 index bde7c17e3fc..00000000000 --- a/psx/octoshock/psx/gpu.h +++ /dev/null @@ -1,287 +0,0 @@ -/******************************************************************************/ -/* Mednafen Sony PS1 Emulation Module */ -/******************************************************************************/ -/* gpu.h: -** Copyright (C) 2011-2017 Mednafen Team -** -** 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., -** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -// WARNING WARNING WARNING: ONLY use CanRead() method of BlitterFIFO, and NOT CanWrite(), since the FIFO is larger than the actual PS1 GPU FIFO to accommodate -// our lack of fancy superscalarish command sequencer. - -#ifndef __MDFN_PSX_GPU_H -#define __MDFN_PSX_GPU_H - -#include "FastFIFO.h" -#include "git.h" -#include "psx.h" -#include "octoshock.h" -#include "emuware/emuware.h" - -struct ShockRenderOptions; -namespace MDFN_IEN_PSX -{ - -struct CTEntry -{ - void (*func[4][8])(const uint32 *cb); - uint8 len; - uint8 fifo_fb_len; - bool ss_cmd; -}; - -struct tri_vertex -{ - int32 x, y; - int32 u, v; - int32 r, g, b; -}; - -struct line_point -{ - int32 x, y; - uint8 r, g, b; -}; - -struct PS_GPU -{ - - void SetRenderOptions(ShockRenderOptions* opts); - templatevoid SyncState(EW::NewState *ns); - uint16 CLUT_Cache[256]; - uint32 CLUT_Cache_VB; // Don't try to be clever and reduce it to 16 bits... ~0U is value for invalidated state. - - struct // Speedup-cache variables, derived from other variables; shouldn't be saved in save states. - { - // TW*_* variables derived from tww, twh, twx, twy, TexPageX, TexPageY - uint32 TWX_AND; - uint32 TWX_ADD; - - uint32 TWY_AND; - uint32 TWY_ADD; - } SUCV; - - struct - { - uint16 Data[4]; - uint32 Tag; - } TexCache[256]; - - uint32 DMAControl; - - // - // Drawing stuff - // - //int32 TexPageX; // 0, 64, 128, 192, etc up to 960 - //int32 TexPageY; // 0 or 256 - //uint32 abr; // Semi-transparency mode(0~3) - //bool dtd; // Dithering enable - - int32 ClipX0; - int32 ClipY0; - int32 ClipX1; - int32 ClipY1; - - int32 OffsX; - int32 OffsY; - - uint32 MaskSetOR; - uint32 MaskEvalAND; - - bool dtd; - bool dfe; - - bool TexDisable; - bool TexDisableAllowChange; - - uint8 tww, twh, twx, twy; - - uint32 TexPageX; - uint32 TexPageY; - - uint32 SpriteFlip; - - uint32 abr; - uint32 TexMode; - - FastFIFO BlitterFIFO; // 0x10 on actual PS1 GPU, 0x20 here(see comment at top of gpu.h) - uint32 DataReadBuffer; - uint32 DataReadBufferEx; - - bool IRQPending; - // - // - // - // Powers of 2 for faster multiple equality testing(just for multi-testing; InCmd itself will only contain 0, or a power of 2). - enum - { - INCMD_NONE = 0, - INCMD_PLINE = (1 << 0), - INCMD_QUAD = (1 << 1), - INCMD_FBWRITE = (1 << 2), - INCMD_FBREAD = (1 << 3) - }; - uint8 InCmd; - uint8 InCmd_CC; - - tri_vertex InQuad_F3Vertices[3]; - - line_point InPLine_PrevPoint; - - uint32 FBRW_X; - uint32 FBRW_Y; - uint32 FBRW_W; - uint32 FBRW_H; - uint32 FBRW_CurY; - uint32 FBRW_CurX; - - // - // Display Parameters - // - uint32 DisplayFB_XStart; - uint32 DisplayFB_YStart; - - uint32 HorizStart; - uint32 HorizEnd; - - uint32 VertStart; - uint32 VertEnd; - uint32 DisplayMode; - bool DisplayOff; - - // - // Display work vars - // - bool PhaseChange; - bool InVBlank; - bool sl_zero_reached; - bool skip; - bool field; - bool field_ram_readout; - uint32 DisplayFB_CurYOffset; - uint32 DisplayFB_CurLineYReadout; - - // - // - // - uint64 GPUClockCounter; - uint32 GPUClockRatio; - uint32 LinesPerField; - uint32 scanline; - uint32 DotClockCounter; - - int32 LineClockCounter; - int32 LinePhase; - - int32 DrawTimeAvail; - - pscpu_timestamp_t lastts; - - uint8 DitherLUT[4][4][512]; // Y, X, 8-bit source value(256 extra for saturation) - - CTEntry Commands[256]; - // - // - // - bool dump_framebuffer; - // - // - // - EmulateSpecStruct *espec; - MDFN_Surface *surface; - MDFN_Rect *DisplayRect; - int32 *LineWidths; - int LineVisFirst, LineVisLast; - bool ShowHOverscan; - bool CorrectAspect; - int32 HVis; - int32 HVisOffs; - int32 NCABaseW; - int32 hmc_to_visible; - /*const*/ bool HardwarePALType; - uint32 OutputLUT[384]; - // - // - // Y, X - uint16 GPURAM[512][1024]; - - public: - uint32 GetVertStart() { return VertStart; } - uint32 GetVertEnd() { return VertEnd; } - int FirstLine; -}; - - extern PS_GPU GPU; - - void GPU_Init(bool pal_clock_and_tv) MDFN_COLD; - void GPU_Kill(void) MDFN_COLD; - - - void GPU_GetGunXTranslation(float* scale, float* offs); - - void GPU_Power(void) MDFN_COLD; - - void GPU_ResetTS(void); - - void GPU_StartFrame(EmulateSpecStruct *espec); - - MDFN_FASTCALL pscpu_timestamp_t GPU_Update(const pscpu_timestamp_t timestamp); - - MDFN_FASTCALL void GPU_Write(const pscpu_timestamp_t timestamp, uint32 A, uint32 V); - - static INLINE bool GPU_CalcFIFOReadyBit(void) - { - if(GPU.InCmd & (PS_GPU::INCMD_PLINE | PS_GPU::INCMD_QUAD)) - return false; - - if(GPU.BlitterFIFO.CanRead() == 0) - return true; - - if(GPU.InCmd & (PS_GPU::INCMD_FBREAD | PS_GPU::INCMD_FBWRITE)) - return false; - - if(GPU.BlitterFIFO.CanRead() >= GPU.Commands[GPU.BlitterFIFO.Peek() >> 24].fifo_fb_len) - return false; - - return true; - } - - static INLINE bool GPU_DMACanWrite(void) - { - return GPU_CalcFIFOReadyBit(); - } - - MDFN_FASTCALL void GPU_WriteDMA(uint32 V); - uint32 GPU_ReadDMA(void); - - MDFN_FASTCALL uint32 GPU_Read(const pscpu_timestamp_t timestamp, uint32 A); - - static INLINE int32 GPU_GetScanlineNum(void) - { - return GPU.scanline; - } - - static INLINE uint16 GPU_PeekRAM(uint32 A) - { - return GPU.GPURAM[(A >> 10) & 0x1FF][A & 0x3FF]; - } - - static INLINE void GPU_PokeRAM(uint32 A, uint16 V) - { - GPU.GPURAM[(A >> 10) & 0x1FF][A & 0x3FF] = V; - } -} -#endif diff --git a/psx/octoshock/psx/gpu_common.inc b/psx/octoshock/psx/gpu_common.inc deleted file mode 100644 index 81d40c4ec6a..00000000000 --- a/psx/octoshock/psx/gpu_common.inc +++ /dev/null @@ -1,424 +0,0 @@ -/******************************************************************************/ -/* Mednafen Sony PS1 Emulation Module */ -/******************************************************************************/ -/* gpu_common.inc: -** Copyright (C) 2011-2017 Mednafen Team -** -** 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., -** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -// -// Reference voodoo, since section anchors don't work with externs -// WARNING: Don't use with members of (anonymous) unions! -// -#define GLBVAR(x) static auto& x = GPU.x; - -GLBVAR(CLUT_Cache) -GLBVAR(CLUT_Cache_VB) -GLBVAR(SUCV) -GLBVAR(TexCache) -GLBVAR(DMAControl) -GLBVAR(ClipX0) -GLBVAR(ClipY0) -GLBVAR(ClipX1) -GLBVAR(ClipY1) -GLBVAR(OffsX) -GLBVAR(OffsY) -GLBVAR(MaskSetOR) -GLBVAR(MaskEvalAND) -GLBVAR(dtd) -GLBVAR(dfe) -GLBVAR(TexDisable) -GLBVAR(TexDisableAllowChange) -GLBVAR(tww) -GLBVAR(twh) -GLBVAR(twx) -GLBVAR(twy) -GLBVAR(TexPageX) -GLBVAR(TexPageY) -GLBVAR(SpriteFlip) -GLBVAR(abr) -GLBVAR(TexMode) -GLBVAR(Commands) -GLBVAR(BlitterFIFO) -GLBVAR(DataReadBuffer) -GLBVAR(DataReadBufferEx) -GLBVAR(IRQPending) -GLBVAR(InCmd) -GLBVAR(InCmd_CC) -GLBVAR(InQuad_F3Vertices) -GLBVAR(InPLine_PrevPoint) -GLBVAR(FBRW_X) -GLBVAR(FBRW_Y) -GLBVAR(FBRW_W) -GLBVAR(FBRW_H) -GLBVAR(FBRW_CurY) -GLBVAR(FBRW_CurX) -GLBVAR(DisplayFB_XStart) -GLBVAR(DisplayFB_YStart) -GLBVAR(HorizStart) -GLBVAR(HorizEnd) -GLBVAR(VertStart) -GLBVAR(VertEnd) -GLBVAR(DisplayMode) -GLBVAR(DisplayOff) -GLBVAR(PhaseChange) -GLBVAR(InVBlank) -GLBVAR(sl_zero_reached) -GLBVAR(skip) -GLBVAR(field) -GLBVAR(field_ram_readout) -GLBVAR(DisplayFB_CurYOffset) -GLBVAR(DisplayFB_CurLineYReadout) -GLBVAR(GPUClockCounter) -GLBVAR(GPUClockRatio) -GLBVAR(LinesPerField) -GLBVAR(scanline) -GLBVAR(DotClockCounter) -GLBVAR(LineClockCounter) -GLBVAR(LinePhase) -GLBVAR(DrawTimeAvail) -GLBVAR(lastts) -GLBVAR(DitherLUT) -GLBVAR(espec) -GLBVAR(surface) -GLBVAR(DisplayRect) -GLBVAR(LineWidths) -GLBVAR(LineVisFirst) -GLBVAR(LineVisLast) -GLBVAR(ShowHOverscan) -GLBVAR(CorrectAspect) -GLBVAR(HVis) -GLBVAR(HVisOffs) -GLBVAR(NCABaseW) -GLBVAR(hmc_to_visible) -GLBVAR(HardwarePALType) -GLBVAR(OutputLUT) -GLBVAR(GPURAM) - -#undef GLBVAR -// -// -// -// - -MDFN_HIDE extern const CTEntry Commands_00_1F[0x20]; -MDFN_HIDE extern const CTEntry Commands_20_3F[0x20]; -MDFN_HIDE extern const CTEntry Commands_40_5F[0x20]; -MDFN_HIDE extern const CTEntry Commands_60_7F[0x20]; -MDFN_HIDE extern const CTEntry Commands_80_FF[0x80]; - - -template -static INLINE void PlotPixel(uint32 x, uint32 y, uint16 fore_pix) -{ - y &= 511; // More Y precision bits than GPU RAM installed in (non-arcade, at least) Playstation hardware. - - if(BlendMode >= 0 && (fore_pix & 0x8000)) - { - uint16 bg_pix = GPURAM[y][x]; // Don't use bg_pix for mask evaluation, it's modified in blending code paths. - uint16 pix; // = fore_pix & 0x8000; - -/* - static const int32 tab[4][2] = - { - { 2, 2 }, - { 4, 4 }, - { 4, -4 }, - { 4, 1 } - }; -*/ - // Efficient 15bpp pixel math algorithms from blargg - switch(BlendMode) - { - default: // to silence clang - break; - - case 0: - bg_pix |= 0x8000; - pix = ((fore_pix + bg_pix) - ((fore_pix ^ bg_pix) & 0x0421)) >> 1; - break; - - case 1: - { - bg_pix &= ~0x8000; - - uint32 sum = fore_pix + bg_pix; - uint32 carry = (sum - ((fore_pix ^ bg_pix) & 0x8421)) & 0x8420; - - pix = (sum - carry) | (carry - (carry >> 5)); - } - break; - - case 2: - { - bg_pix |= 0x8000; - fore_pix &= ~0x8000; - - uint32 diff = bg_pix - fore_pix + 0x108420; - uint32 borrow = (diff - ((bg_pix ^ fore_pix) & 0x108420)) & 0x108420; - - pix = (diff - borrow) & (borrow - (borrow >> 5)); - } - break; - - case 3: - { - bg_pix &= ~0x8000; - fore_pix = ((fore_pix >> 2) & 0x1CE7) | 0x8000; - - uint32 sum = fore_pix + bg_pix; - uint32 carry = (sum - ((fore_pix ^ bg_pix) & 0x8421)) & 0x8420; - - pix = (sum - carry) | (carry - (carry >> 5)); - } - break; - } - - if(!MaskEval_TA || !(GPURAM[y][x] & 0x8000)) - GPURAM[y][x] = (textured ? pix : (pix & 0x7FFF)) | MaskSetOR; - } - else - { - if(!MaskEval_TA || !(GPURAM[y][x] & 0x8000)) - GPURAM[y][x] = (textured ? fore_pix : (fore_pix & 0x7FFF)) | MaskSetOR; - } -} - -static INLINE uint16 ModTexel(uint16 texel, int32 r, int32 g, int32 b, const int32 dither_x, const int32 dither_y) -{ - uint16 ret = texel & 0x8000; - - ret |= DitherLUT[dither_y][dither_x][(((texel & 0x1F) * r) >> (5 - 1))] << 0; - ret |= DitherLUT[dither_y][dither_x][(((texel & 0x3E0) * g) >> (10 - 1))] << 5; - ret |= DitherLUT[dither_y][dither_x][(((texel & 0x7C00) * b) >> (15 - 1))] << 10; - - return(ret); -} - -template -static INLINE void Update_CLUT_Cache(uint16 raw_clut) -{ - if(TexMode_TA < 2) - { - const uint32 new_ccvb = ((raw_clut & 0x7FFF) | (TexMode_TA << 16)); // Confirmed upper bit of raw_clut is ignored(at least on SCPH-5501's GPU). - - if(CLUT_Cache_VB != new_ccvb) - { - uint16* const gpulp = GPURAM[(raw_clut >> 6) & 0x1FF]; - const uint32 cxo = (raw_clut & 0x3F) << 4; - const uint32 count = (TexMode_TA ? 256 : 16); - - DrawTimeAvail -= count; - - for(unsigned i = 0; i < count; i++) - { - CLUT_Cache[i] = gpulp[(cxo + i) & 0x3FF]; - } - - CLUT_Cache_VB = new_ccvb; - } - } -} - -#if 0 - TexWindowX_AND = ~(tww << 3); - TexWindowX_ADD = ((twx & tww) << 3; - - TexWindowY_AND = ~(twh << 3); - TexWindowY_OR = (twy & twh) << 3; - - uint32 u = (u_arg & TexWindowX_AND) TexWindowX_OR; - uint32 v = (v_arg & TexWindowY_AND) | TexWindowY_OR; - uint32 fbtex_x = TexPageX + (u >> (2 - TexMode_TA)); - uint32 fbtex_y = TexPageY + v; - uint16 fbw = GPURAM[fbtex_y][fbtex_x & 1023]; - - if(TexMode_TA != 2) - { - if(TexMode_TA == 0) - fbw = (fbw >> ((u & 3) * 4)) & 0xF; - else - fbw = (fbw >> ((u & 1) * 8)) & 0xFF; - - fbw = CLUT_Cache[fbw]; - } -#endif - -static INLINE void RecalcTexWindowStuff(void) -{ - SUCV.TWX_AND = ~(tww << 3); - SUCV.TWX_ADD = ((twx & tww) << 3) + (TexPageX << (2 - std::min(2, TexMode))); - - SUCV.TWY_AND = ~(twh << 3); - SUCV.TWY_ADD = ((twy & twh) << 3) + TexPageY; -} - -template -static INLINE uint16 GetTexel(uint32 u_arg, uint32 v_arg) -{ - static_assert(TexMode_TA <= 2, "TexMode_TA must be <= 2"); - - uint32 u_ext = ((u_arg & SUCV.TWX_AND) + SUCV.TWX_ADD); - uint32 fbtex_x = ((u_ext >> (2 - TexMode_TA))) & 1023; - uint32 fbtex_y = (v_arg & SUCV.TWY_AND) + SUCV.TWY_ADD; - uint32 gro = fbtex_y * 1024U + fbtex_x; - - decltype(&TexCache[0]) c; - - switch(TexMode_TA) - { - case 0: c = &TexCache[((gro >> 2) & 0x3) | ((gro >> 8) & 0xFC)]; break; // 64x64 - case 1: c = &TexCache[((gro >> 2) & 0x7) | ((gro >> 7) & 0xF8)]; break; // 64x32 (NOT 32x64!) - case 2: c = &TexCache[((gro >> 2) & 0x7) | ((gro >> 7) & 0xF8)]; break; // 32x32 - } - - if(MDFN_UNLIKELY(c->Tag != (gro &~ 0x3))) - { - // SCPH-1001 old revision GPU is like(for sprites at least): (20 + 4) - // SCPH-5501 new revision GPU is like(for sprites at least): (12 + 4) - // - // We'll be conservative and just go with 4 for now, until we can run some tests with triangles too. - // - DrawTimeAvail -= 4; - memcpy(c->Data, (uint16*)GPURAM + (gro &~ 0x3), 4 * sizeof(uint16)); - c->Tag = (gro &~ 0x3); - } - - uint16 fbw = c->Data[gro & 0x3]; - - if(TexMode_TA != 2) - { - if(TexMode_TA == 0) - fbw = (fbw >> ((u_ext & 3) * 4)) & 0xF; - else - fbw = (fbw >> ((u_ext & 1) * 8)) & 0xFF; - - fbw = CLUT_Cache[fbw]; - } - - return(fbw); -} - -static INLINE bool LineSkipTest(unsigned y) -{ - //DisplayFB_XStart >= OffsX && DisplayFB_YStart >= OffsY && - // ((y & 1) == (DisplayFB_CurLineYReadout & 1)) - - if((DisplayMode & 0x24) != 0x24) - return false; - - if(!dfe && ((y & 1) == ((DisplayFB_YStart + field_ram_readout) & 1))/* && !DisplayOff*/) //&& (y >> 1) >= DisplayFB_YStart && (y >> 1) < (DisplayFB_YStart + (VertEnd - VertStart))) - return true; - - return false; -} - - -// -// Command table generation macros follow: -// - -//#define BM_HELPER(fg) { fg(0), fg(1), fg(2), fg(3) } - -#define POLY_HELPER_SUB(bm, cv, tm, mam) \ - Command_DrawPolygon<3 + ((cv & 0x8) >> 3), ((cv & 0x10) >> 4), ((cv & 0x4) >> 2), ((cv & 0x2) >> 1) ? bm : -1, ((cv & 1) ^ 1) & ((cv & 0x4) >> 2), tm, mam > - -#define POLY_HELPER_FG(bm, cv) \ - { \ - POLY_HELPER_SUB(bm, cv, ((cv & 0x4) ? 0 : 0), 0), \ - POLY_HELPER_SUB(bm, cv, ((cv & 0x4) ? 1 : 0), 0), \ - POLY_HELPER_SUB(bm, cv, ((cv & 0x4) ? 2 : 0), 0), \ - POLY_HELPER_SUB(bm, cv, ((cv & 0x4) ? 2 : 0), 0), \ - POLY_HELPER_SUB(bm, cv, ((cv & 0x4) ? 0 : 0), 1), \ - POLY_HELPER_SUB(bm, cv, ((cv & 0x4) ? 1 : 0), 1), \ - POLY_HELPER_SUB(bm, cv, ((cv & 0x4) ? 2 : 0), 1), \ - POLY_HELPER_SUB(bm, cv, ((cv & 0x4) ? 2 : 0), 1), \ - } - -#define POLY_HELPER(cv) \ - { \ - { POLY_HELPER_FG(0, cv), POLY_HELPER_FG(1, cv), POLY_HELPER_FG(2, cv), POLY_HELPER_FG(3, cv) }, \ - 1 + (3 /*+ ((cv & 0x8) >> 3)*/) * ( 1 + ((cv & 0x4) >> 2) + ((cv & 0x10) >> 4) ) - ((cv & 0x10) >> 4), \ - 1, \ - false \ - } - -// -// - -#define SPR_HELPER_SUB(bm, cv, tm, mam) Command_DrawSprite<(cv >> 3) & 0x3, ((cv & 0x4) >> 2), ((cv & 0x2) >> 1) ? bm : -1, ((cv & 1) ^ 1) & ((cv & 0x4) >> 2), tm, mam> - -#define SPR_HELPER_FG(bm, cv) \ - { \ - SPR_HELPER_SUB(bm, cv, ((cv & 0x4) ? 0 : 0), 0), \ - SPR_HELPER_SUB(bm, cv, ((cv & 0x4) ? 1 : 0), 0), \ - SPR_HELPER_SUB(bm, cv, ((cv & 0x4) ? 2 : 0), 0), \ - SPR_HELPER_SUB(bm, cv, ((cv & 0x4) ? 2 : 0), 0), \ - SPR_HELPER_SUB(bm, cv, ((cv & 0x4) ? 0 : 0), 1), \ - SPR_HELPER_SUB(bm, cv, ((cv & 0x4) ? 1 : 0), 1), \ - SPR_HELPER_SUB(bm, cv, ((cv & 0x4) ? 2 : 0), 1), \ - SPR_HELPER_SUB(bm, cv, ((cv & 0x4) ? 2 : 0), 1), \ - } - - -#define SPR_HELPER(cv) \ - { \ - { SPR_HELPER_FG(0, cv), SPR_HELPER_FG(1, cv), SPR_HELPER_FG(2, cv), SPR_HELPER_FG(3, cv) }, \ - 2 + ((cv & 0x4) >> 2) + ((cv & 0x18) ? 0 : 1), \ - 2 | ((cv & 0x4) >> 2) | ((cv & 0x18) ? 0 : 1), /* |, not +, for this */ \ - false \ - } - -// -// - -#define LINE_HELPER_SUB(bm, cv, mam) Command_DrawLine<((cv & 0x08) >> 3), ((cv & 0x10) >> 4), ((cv & 0x2) >> 1) ? bm : -1, mam> - -#define LINE_HELPER_FG(bm, cv) \ - { \ - LINE_HELPER_SUB(bm, cv, 0), \ - LINE_HELPER_SUB(bm, cv, 0), \ - LINE_HELPER_SUB(bm, cv, 0), \ - LINE_HELPER_SUB(bm, cv, 0), \ - LINE_HELPER_SUB(bm, cv, 1), \ - LINE_HELPER_SUB(bm, cv, 1), \ - LINE_HELPER_SUB(bm, cv, 1), \ - LINE_HELPER_SUB(bm, cv, 1) \ - } - -#define LINE_HELPER(cv) \ - { \ - { LINE_HELPER_FG(0, cv), LINE_HELPER_FG(1, cv), LINE_HELPER_FG(2, cv), LINE_HELPER_FG(3, cv) }, \ - 3 + ((cv & 0x10) >> 4), \ - 1, \ - false \ - } - -// -// - - -#define OTHER_HELPER_FG(bm, arg_ptr) { arg_ptr, arg_ptr, arg_ptr, arg_ptr, arg_ptr, arg_ptr, arg_ptr, arg_ptr } -#define OTHER_HELPER(arg_cs, arg_fbcs, arg_ss, arg_ptr) { { OTHER_HELPER_FG(0, arg_ptr), OTHER_HELPER_FG(1, arg_ptr), OTHER_HELPER_FG(2, arg_ptr), OTHER_HELPER_FG(3, arg_ptr) }, arg_cs, arg_fbcs, arg_ss } -#define OTHER_HELPER_X2(arg_cs, arg_fbcs, arg_ss, arg_ptr) OTHER_HELPER(arg_cs, arg_fbcs, arg_ss, arg_ptr), OTHER_HELPER(arg_cs, arg_fbcs, arg_ss, arg_ptr) -#define OTHER_HELPER_X4(arg_cs, arg_fbcs, arg_ss, arg_ptr) OTHER_HELPER_X2(arg_cs, arg_fbcs, arg_ss, arg_ptr), OTHER_HELPER_X2(arg_cs, arg_fbcs, arg_ss, arg_ptr) -#define OTHER_HELPER_X8(arg_cs, arg_fbcs, arg_ss, arg_ptr) OTHER_HELPER_X4(arg_cs, arg_fbcs, arg_ss, arg_ptr), OTHER_HELPER_X4(arg_cs, arg_fbcs, arg_ss, arg_ptr) -#define OTHER_HELPER_X16(arg_cs, arg_fbcs, arg_ss, arg_ptr) OTHER_HELPER_X8(arg_cs, arg_fbcs, arg_ss, arg_ptr), OTHER_HELPER_X8(arg_cs, arg_fbcs, arg_ss, arg_ptr) -#define OTHER_HELPER_X32(arg_cs, arg_fbcs, arg_ss, arg_ptr) OTHER_HELPER_X16(arg_cs, arg_fbcs, arg_ss, arg_ptr), OTHER_HELPER_X16(arg_cs, arg_fbcs, arg_ss, arg_ptr) - -#define NULLCMD_FG(bm) { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL } -#define NULLCMD() { { NULLCMD_FG(0), NULLCMD_FG(1), NULLCMD_FG(2), NULLCMD_FG(3) }, 1, 1, true } - diff --git a/psx/octoshock/psx/gpu_line.cpp b/psx/octoshock/psx/gpu_line.cpp deleted file mode 100644 index 446100b209a..00000000000 --- a/psx/octoshock/psx/gpu_line.cpp +++ /dev/null @@ -1,299 +0,0 @@ -/******************************************************************************/ -/* Mednafen Sony PS1 Emulation Module */ -/******************************************************************************/ -/* gpu_line.cpp: -** Copyright (C) 2011-2017 Mednafen Team -** -** 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., -** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "psx.h" -#include "gpu.h" - -namespace MDFN_IEN_PSX -{ -namespace PS_GPU_INTERNAL -{ - -#include "gpu_common.inc" - -struct line_fxp_coord -{ - uint64 x, y; - uint32 r, g, b; -}; - -struct line_fxp_step -{ - int64 dx_dk, dy_dk; - int32 dr_dk, dg_dk, db_dk; -}; - -enum { Line_XY_FractBits = 32 }; -enum { Line_RGB_FractBits = 12 }; - -template -static INLINE void LinePointToFXPCoord(const line_point &point, const line_fxp_step &step, line_fxp_coord &coord) -{ - coord.x = ((uint64)point.x << Line_XY_FractBits) | (1ULL << (Line_XY_FractBits - 1)); - coord.y = ((uint64)point.y << Line_XY_FractBits) | (1ULL << (Line_XY_FractBits - 1)); - - coord.x -= 1024; - - if(step.dy_dk < 0) - coord.y -= 1024; - - if(goraud) - { - coord.r = (point.r << Line_RGB_FractBits) | (1 << (Line_RGB_FractBits - 1)); - coord.g = (point.g << Line_RGB_FractBits) | (1 << (Line_RGB_FractBits - 1)); - coord.b = (point.b << Line_RGB_FractBits) | (1 << (Line_RGB_FractBits - 1)); - } -} - -static INLINE int64 LineDivide(int64 delta, int32 dk) -{ - delta = (uint64)delta << Line_XY_FractBits; - - if(delta < 0) - delta -= dk - 1; - if(delta > 0) - delta += dk - 1; - - return(delta / dk); -} - -template -static INLINE void LinePointsToFXPStep(const line_point &point0, const line_point &point1, const int32 dk, line_fxp_step &step) -{ - if(!dk) - { - step.dx_dk = 0; - step.dy_dk = 0; - - if(goraud) - { - step.dr_dk = 0; - step.dg_dk = 0; - step.db_dk = 0; - } - return; - } - - step.dx_dk = LineDivide(point1.x - point0.x, dk); - step.dy_dk = LineDivide(point1.y - point0.y, dk); - - if(goraud) - { - step.dr_dk = (int32)((uint32)(point1.r - point0.r) << Line_RGB_FractBits) / dk; - step.dg_dk = (int32)((uint32)(point1.g - point0.g) << Line_RGB_FractBits) / dk; - step.db_dk = (int32)((uint32)(point1.b - point0.b) << Line_RGB_FractBits) / dk; - } -} - -template -static INLINE void AddLineStep(line_fxp_coord &point, const line_fxp_step &step) -{ - point.x += step.dx_dk; - point.y += step.dy_dk; - - if(goraud) - { - point.r += step.dr_dk; - point.g += step.dg_dk; - point.b += step.db_dk; - } -} - -template -static void DrawLine(line_point *points) -{ - int32 i_dx; - int32 i_dy; - int32 k; - line_fxp_coord cur_point; - line_fxp_step step; - - i_dx = abs(points[1].x - points[0].x); - i_dy = abs(points[1].y - points[0].y); - k = (i_dx > i_dy) ? i_dx : i_dy; - - if(i_dx >= 1024) - return; - - if(i_dy >= 512) - return; - - if(points[0].x >= points[1].x && k) - { - line_point tmp = points[1]; - - points[1] = points[0]; - points[0] = tmp; - } - - DrawTimeAvail -= k * 2; - - // - // - // - - LinePointsToFXPStep(points[0], points[1], k, step); - LinePointToFXPCoord(points[0], step, cur_point); - - // - // - // - for(int32 i = 0; i <= k; i++) // <= is not a typo. - { - // Sign extension is not necessary here for x and y, due to the maximum values that ClipX1 and ClipY1 can contain. - const int32 x = (cur_point.x >> Line_XY_FractBits) & 2047; - const int32 y = (cur_point.y >> Line_XY_FractBits) & 2047; - uint16 pix = 0x8000; - - if(!LineSkipTest(y)) - { - uint8 r, g, b; - - if(goraud) - { - r = cur_point.r >> Line_RGB_FractBits; - g = cur_point.g >> Line_RGB_FractBits; - b = cur_point.b >> Line_RGB_FractBits; - } - else - { - r = points[0].r; - g = points[0].g; - b = points[0].b; - } - - if(dtd) - { - pix |= DitherLUT[y & 3][x & 3][r] << 0; - pix |= DitherLUT[y & 3][x & 3][g] << 5; - pix |= DitherLUT[y & 3][x & 3][b] << 10; - } - else - { - pix |= (r >> 3) << 0; - pix |= (g >> 3) << 5; - pix |= (b >> 3) << 10; - } - - // FIXME: There has to be a faster way than checking for being inside the drawing area for each pixel. - if(x >= ClipX0 && x <= ClipX1 && y >= ClipY0 && y <= ClipY1) - PlotPixel(x, y, pix); - } - - AddLineStep(cur_point, step); - } -} - -template -static void Command_DrawLine(const uint32 *cb) -{ - const uint8 cc = cb[0] >> 24; // For pline handling later. - line_point points[2]; - - DrawTimeAvail -= 16; // FIXME, correct time. - - if(polyline && InCmd == PS_GPU::INCMD_PLINE) - { - //printf("PLINE N\n"); - points[0] = InPLine_PrevPoint; - } - else - { - points[0].r = (*cb >> 0) & 0xFF; - points[0].g = (*cb >> 8) & 0xFF; - points[0].b = (*cb >> 16) & 0xFF; - cb++; - - points[0].x = sign_x_to_s32(11, ((*cb >> 0) & 0xFFFF)) + OffsX; - points[0].y = sign_x_to_s32(11, ((*cb >> 16) & 0xFFFF)) + OffsY; - cb++; - } - - if(goraud) - { - points[1].r = (*cb >> 0) & 0xFF; - points[1].g = (*cb >> 8) & 0xFF; - points[1].b = (*cb >> 16) & 0xFF; - cb++; - } - else - { - points[1].r = points[0].r; - points[1].g = points[0].g; - points[1].b = points[0].b; - } - - points[1].x = sign_x_to_s32(11, ((*cb >> 0) & 0xFFFF)) + OffsX; - points[1].y = sign_x_to_s32(11, ((*cb >> 16) & 0xFFFF)) + OffsY; - cb++; - - if(polyline) - { - InPLine_PrevPoint = points[1]; - - if(InCmd != PS_GPU::INCMD_PLINE) - { - InCmd = PS_GPU::INCMD_PLINE; - InCmd_CC = cc; - } - } - - DrawLine(points); -} - -MDFN_HIDE extern const CTEntry Commands_40_5F[0x20] = -{ - LINE_HELPER(0x40), - LINE_HELPER(0x41), - LINE_HELPER(0x42), - LINE_HELPER(0x43), - LINE_HELPER(0x44), - LINE_HELPER(0x45), - LINE_HELPER(0x46), - LINE_HELPER(0x47), - LINE_HELPER(0x48), - LINE_HELPER(0x49), - LINE_HELPER(0x4a), - LINE_HELPER(0x4b), - LINE_HELPER(0x4c), - LINE_HELPER(0x4d), - LINE_HELPER(0x4e), - LINE_HELPER(0x4f), - LINE_HELPER(0x50), - LINE_HELPER(0x51), - LINE_HELPER(0x52), - LINE_HELPER(0x53), - LINE_HELPER(0x54), - LINE_HELPER(0x55), - LINE_HELPER(0x56), - LINE_HELPER(0x57), - LINE_HELPER(0x58), - LINE_HELPER(0x59), - LINE_HELPER(0x5a), - LINE_HELPER(0x5b), - LINE_HELPER(0x5c), - LINE_HELPER(0x5d), - LINE_HELPER(0x5e), - LINE_HELPER(0x5f) -}; - -} -} diff --git a/psx/octoshock/psx/gpu_polygon.cpp b/psx/octoshock/psx/gpu_polygon.cpp deleted file mode 100644 index 12941eeda46..00000000000 --- a/psx/octoshock/psx/gpu_polygon.cpp +++ /dev/null @@ -1,635 +0,0 @@ -/******************************************************************************/ -/* Mednafen Sony PS1 Emulation Module */ -/******************************************************************************/ -/* gpu_polygon.cpp: -** Copyright (C) 2011-2017 Mednafen Team -** -** 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., -** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#pragma GCC optimize ("no-unroll-loops,no-peel-loops") - -#include "psx.h" -#include "gpu.h" - -namespace MDFN_IEN_PSX -{ -namespace PS_GPU_INTERNAL -{ -#include "gpu_common.inc" - -#define COORD_FBS 12 -#define COORD_MF_INT(n) ((n) << COORD_FBS) -#define COORD_POST_PADDING 12 - -struct i_group -{ - uint32 u, v; - uint32 r, g, b; -}; - -struct i_deltas -{ - uint32 du_dx, dv_dx; - uint32 dr_dx, dg_dx, db_dx; - - uint32 du_dy, dv_dy; - uint32 dr_dy, dg_dy, db_dy; -}; - -static INLINE int64 MakePolyXFP(uint32 x) -{ - return ((uint64)x << 32) + ((1ULL << 32) - (1 << 11)); -} - -static INLINE int64 MakePolyXFPStep(int32 dx, int32 dy) -{ - int64 ret; - int64 dx_ex = (uint64)dx << 32; - - if(dx_ex < 0) - dx_ex -= dy - 1; - - if(dx_ex > 0) - dx_ex += dy - 1; - - ret = dx_ex / dy; - - return(ret); -} - -static INLINE int32 GetPolyXFP_Int(int64 xfp) -{ - return(xfp >> 32); -} - -#define CALCIS(x,y) (((B.x - A.x) * (C.y - B.y)) - ((C.x - B.x) * (B.y - A.y))) -template -static INLINE bool CalcIDeltas(i_deltas &idl, const tri_vertex &A, const tri_vertex &B, const tri_vertex &C) -{ - int32 denom = CALCIS(x, y); - - if(!denom) - return(false); - - if(goraud) - { - idl.dr_dx = (uint32)(CALCIS(r, y) * (1 << COORD_FBS) / denom) << COORD_POST_PADDING; - idl.dr_dy = (uint32)(CALCIS(x, r) * (1 << COORD_FBS) / denom) << COORD_POST_PADDING; - - idl.dg_dx = (uint32)(CALCIS(g, y) * (1 << COORD_FBS) / denom) << COORD_POST_PADDING; - idl.dg_dy = (uint32)(CALCIS(x, g) * (1 << COORD_FBS) / denom) << COORD_POST_PADDING; - - idl.db_dx = (uint32)(CALCIS(b, y) * (1 << COORD_FBS) / denom) << COORD_POST_PADDING; - idl.db_dy = (uint32)(CALCIS(x, b) * (1 << COORD_FBS) / denom) << COORD_POST_PADDING; - } - - if(textured) - { - idl.du_dx = (uint32)(CALCIS(u, y) * (1 << COORD_FBS) / denom) << COORD_POST_PADDING; - idl.du_dy = (uint32)(CALCIS(x, u) * (1 << COORD_FBS) / denom) << COORD_POST_PADDING; - - idl.dv_dx = (uint32)(CALCIS(v, y) * (1 << COORD_FBS) / denom) << COORD_POST_PADDING; - idl.dv_dy = (uint32)(CALCIS(x, v) * (1 << COORD_FBS) / denom) << COORD_POST_PADDING; - } - - return(true); -} -#undef CALCIS - -template -static INLINE void AddIDeltas_DX(i_group &ig, const i_deltas &idl, uint32 count = 1) -{ - if(textured) - { - ig.u += idl.du_dx * count; - ig.v += idl.dv_dx * count; - } - - if(goraud) - { - ig.r += idl.dr_dx * count; - ig.g += idl.dg_dx * count; - ig.b += idl.db_dx * count; - } -} - -template -static INLINE void AddIDeltas_DY(i_group &ig, const i_deltas &idl, uint32 count = 1) -{ - if(textured) - { - ig.u += idl.du_dy * count; - ig.v += idl.dv_dy * count; - } - - if(goraud) - { - ig.r += idl.dr_dy * count; - ig.g += idl.dg_dy * count; - ig.b += idl.db_dy * count; - } -} - -template -static INLINE void DrawSpan(int y, const int32 x_start, const int32 x_bound, i_group ig, const i_deltas &idl) -{ - if(LineSkipTest(y)) - return; - - int32 x_ig_adjust = x_start; - int32 w = x_bound - x_start; - int32 x = sign_x_to_s32(11, x_start); - - if(x < ClipX0) - { - int32 delta = ClipX0 - x; - x_ig_adjust += delta; - x += delta; - w -= delta; - } - - if((x + w) > (ClipX1 + 1)) - w = ClipX1 + 1 - x; - - if(w <= 0) - return; - - //printf("%d %d %d %d\n", x, w, ClipX0, ClipX1); - - AddIDeltas_DX(ig, idl, x_ig_adjust); - AddIDeltas_DY(ig, idl, y); - - if(goraud || textured) - DrawTimeAvail -= w * 2; - else if((BlendMode >= 0) || MaskEval_TA) - DrawTimeAvail -= w + ((w + 1) >> 1); - else - DrawTimeAvail -= w; - - do - { - const uint32 r = ig.r >> (COORD_FBS + COORD_POST_PADDING); - const uint32 g = ig.g >> (COORD_FBS + COORD_POST_PADDING); - const uint32 b = ig.b >> (COORD_FBS + COORD_POST_PADDING); - - //assert(x >= ClipX0 && x <= ClipX1); - - if(textured) - { - uint16 fbw = GetTexel(ig.u >> (COORD_FBS + COORD_POST_PADDING), ig.v >> (COORD_FBS + COORD_POST_PADDING)); - - if(fbw) - { - if(TexMult) - { - uint32 dither_x = x & 3; - uint32 dither_y = y & 3; - - if(!dtd) - { - dither_x = 3; - dither_y = 2; - } - - fbw = ModTexel(fbw, r, g, b, dither_x, dither_y); - } - PlotPixel(x, y, fbw); - } - } - else - { - uint16 pix = 0x8000; - - if(goraud && dtd) - { - pix |= DitherLUT[y & 3][x & 3][r] << 0; - pix |= DitherLUT[y & 3][x & 3][g] << 5; - pix |= DitherLUT[y & 3][x & 3][b] << 10; - } - else - { - pix |= (r >> 3) << 0; - pix |= (g >> 3) << 5; - pix |= (b >> 3) << 10; - } - - PlotPixel(x, y, pix); - } - - x++; - AddIDeltas_DX(ig, idl); - } while(MDFN_LIKELY(--w > 0)); -} - -template -static INLINE void DrawTriangle(tri_vertex *vertices) -{ - i_deltas idl; - unsigned core_vertex; - - // - // Calculate the "core" vertex based on the unsorted input vertices, and sort vertices by Y. - // - { - unsigned cvtemp = 0; - - if(vertices[1].x <= vertices[0].x) - { - if(vertices[2].x <= vertices[1].x) - cvtemp = (1 << 2); - else - cvtemp = (1 << 1); - } - else if(vertices[2].x < vertices[0].x) - cvtemp = (1 << 2); - else - cvtemp = (1 << 0); - - if(vertices[2].y < vertices[1].y) - { - std::swap(vertices[2], vertices[1]); - cvtemp = ((cvtemp >> 1) & 0x2) | ((cvtemp << 1) & 0x4) | (cvtemp & 0x1); - } - - if(vertices[1].y < vertices[0].y) - { - std::swap(vertices[1], vertices[0]); - cvtemp = ((cvtemp >> 1) & 0x1) | ((cvtemp << 1) & 0x2) | (cvtemp & 0x4); - } - - if(vertices[2].y < vertices[1].y) - { - std::swap(vertices[2], vertices[1]); - cvtemp = ((cvtemp >> 1) & 0x2) | ((cvtemp << 1) & 0x4) | (cvtemp & 0x1); - } - - core_vertex = cvtemp >> 1; - } - - // - // 0-height, abort out. - // - if(vertices[0].y == vertices[2].y) - return; - - if((vertices[2].y - vertices[0].y) >= 512) - { - //PSX_WARNING("[GPU] Triangle height too large: %d", (vertices[2].y - vertices[0].y)); - return; - } - - if(abs(vertices[2].x - vertices[0].x) >= 1024 || - abs(vertices[2].x - vertices[1].x) >= 1024 || - abs(vertices[1].x - vertices[0].x) >= 1024) - { - //PSX_WARNING("[GPU] Triangle width too large: %d %d %d", abs(vertices[2].x - vertices[0].x), abs(vertices[2].x - vertices[1].x), abs(vertices[1].x - vertices[0].x)); - return; - } - - if(!CalcIDeltas(idl, vertices[0], vertices[1], vertices[2])) - return; - - // [0] should be top vertex, [2] should be bottom vertex, [1] should be off to the side vertex. - // - // - int64 base_coord; - int64 base_step; - - int64 bound_coord_us; - int64 bound_coord_ls; - - bool right_facing; - i_group ig; - - if(textured) - { - ig.u = (COORD_MF_INT(vertices[core_vertex].u) + (1 << (COORD_FBS - 1))) << COORD_POST_PADDING; - ig.v = (COORD_MF_INT(vertices[core_vertex].v) + (1 << (COORD_FBS - 1))) << COORD_POST_PADDING; - } - - ig.r = (COORD_MF_INT(vertices[core_vertex].r) + (1 << (COORD_FBS - 1))) << COORD_POST_PADDING; - ig.g = (COORD_MF_INT(vertices[core_vertex].g) + (1 << (COORD_FBS - 1))) << COORD_POST_PADDING; - ig.b = (COORD_MF_INT(vertices[core_vertex].b) + (1 << (COORD_FBS - 1))) << COORD_POST_PADDING; - - AddIDeltas_DX(ig, idl, -vertices[core_vertex].x); - AddIDeltas_DY(ig, idl, -vertices[core_vertex].y); - - base_coord = MakePolyXFP(vertices[0].x); - base_step = MakePolyXFPStep((vertices[2].x - vertices[0].x), (vertices[2].y - vertices[0].y)); - - // - // - // - - if(vertices[1].y == vertices[0].y) - { - bound_coord_us = 0; - right_facing = (bool)(vertices[1].x > vertices[0].x); - } - else - { - bound_coord_us = MakePolyXFPStep((vertices[1].x - vertices[0].x), (vertices[1].y - vertices[0].y)); - right_facing = (bool)(bound_coord_us > base_step); - } - - if(vertices[2].y == vertices[1].y) - bound_coord_ls = 0; - else - bound_coord_ls = MakePolyXFPStep((vertices[2].x - vertices[1].x), (vertices[2].y - vertices[1].y)); - - // - // Left side draw order - // - // core_vertex == 0 - // Left(base): vertices[0] -> (?vertices[1]?) -> vertices[2] - // - // core_vertex == 1: - // Left(base): vertices[1] -> vertices[2], vertices[1] -> vertices[0] - // - // core_vertex == 2: - // Left(base): vertices[2] -> (?vertices[1]?) -> vertices[0] - //printf("%d %d\n", core_vertex, right_facing); - struct - { - uint64 x_coord[2]; - uint64 x_step[2]; - - int32 y_coord; - int32 y_bound; - - bool dec_mode; - } tripart[2]; - -#if 0 - switch(core_vertex) - { - case 0: - tripart[0].dec_mode = tripart[1].dec_mode = false; - - tripart[0].y_coord = vertices[0].y; - tripart[0].y_bound = vertices[1].y; - if(vertices[0].y != vertices[1].y) - { - tripart[0].x_coord[0] = MakePolyXFP(vertices[0].x); - tripart[0].x_step[0] = - - tripart[0].x_coord[1] = MakePolyXFP(vertices[0].x); - tripart[0].x_step[1] = - } - break; - - case 1: - break; - - case 2: - break; - } -#endif - - unsigned vo = 0; - unsigned vp = 0; - - if(core_vertex) - vo = 1; - - if(core_vertex == 2) - vp = 3; - - { - auto* tp = &tripart[vo]; - - tp->y_coord = vertices[0 ^ vo].y; - tp->y_bound = vertices[1 ^ vo].y; - tp->x_coord[right_facing] = MakePolyXFP(vertices[0 ^ vo].x); - tp->x_step[right_facing] = bound_coord_us; - tp->x_coord[!right_facing] = base_coord + ((vertices[vo].y - vertices[0].y) * base_step); - tp->x_step[!right_facing] = base_step; - tp->dec_mode = vo; - } - - { - auto* tp = &tripart[vo ^ 1]; - - tp->y_coord = vertices[1 ^ vp].y; - tp->y_bound = vertices[2 ^ vp].y; - tp->x_coord[right_facing] = MakePolyXFP(vertices[1 ^ vp].x); - tp->x_step[right_facing] = bound_coord_ls; - tp->x_coord[!right_facing] = base_coord + ((vertices[1 ^ vp].y - vertices[0].y) * base_step); //base_coord + ((vertices[1].y - vertices[0].y) * base_step); - tp->x_step[!right_facing] = base_step; - tp->dec_mode = vp; - } - - for(unsigned i = 0; i < 2; i++) //2; i++) - { - int32 yi = tripart[i].y_coord; - int32 yb = tripart[i].y_bound; - - uint64 lc = tripart[i].x_coord[0]; - uint64 ls = tripart[i].x_step[0]; - - uint64 rc = tripart[i].x_coord[1]; - uint64 rs = tripart[i].x_step[1]; - - if(tripart[i].dec_mode) - { - while(MDFN_LIKELY(yi > yb)) - { - yi--; - lc -= ls; - rc -= rs; - // - // - // - int32 y = sign_x_to_s32(11, yi); - - if(y < ClipY0) - break; - - if(y > ClipY1) - { - DrawTimeAvail -= 2; - continue; - } - - DrawSpan(yi, GetPolyXFP_Int(lc), GetPolyXFP_Int(rc), ig, idl); - } - } - else - { - while(MDFN_LIKELY(yi < yb)) - { - int32 y = sign_x_to_s32(11, yi); - - if(y > ClipY1) - break; - - if(y < ClipY0) - { - DrawTimeAvail -= 2; - goto skipit; - } - - DrawSpan(yi, GetPolyXFP_Int(lc), GetPolyXFP_Int(rc), ig, idl); - // - // - // - skipit: ; - yi++; - lc += ls; - rc += rs; - } - } - } - -#if 0 - printf("[GPU] Vertices: %d:%d(r=%d, g=%d, b=%d) -> %d:%d(r=%d, g=%d, b=%d) -> %d:%d(r=%d, g=%d, b=%d)\n\n\n", vertices[0].x, vertices[0].y, - vertices[0].r, vertices[0].g, vertices[0].b, - vertices[1].x, vertices[1].y, - vertices[1].r, vertices[1].g, vertices[1].b, - vertices[2].x, vertices[2].y, - vertices[2].r, vertices[2].g, vertices[2].b); -#endif -} - -template -static void Command_DrawPolygon(const uint32 *cb) -{ - const unsigned cb0 = cb[0]; - tri_vertex vertices[3] = {0}; //zero 04-oct-2020 - zero initialize for more deterministic results (sometimes UV arent set) - unsigned sv = 0; - //uint32 tpage = 0; - - // Base timing is approximate, and could be improved. - if(numvertices == 4 && InCmd == PS_GPU::INCMD_QUAD) - DrawTimeAvail -= (28 + 18); - else - DrawTimeAvail -= (64 + 18); - - if(goraud && textured) - DrawTimeAvail -= 150 * 3; - else if(goraud) - DrawTimeAvail -= 96 * 3; - else if(textured) - DrawTimeAvail -= 60 * 3; - - if(numvertices == 4) - { - if(InCmd == PS_GPU::INCMD_QUAD) - { - memcpy(&vertices[0], &InQuad_F3Vertices[1], 2 * sizeof(tri_vertex)); - sv = 2; - } - } - //else - // memset(vertices, 0, sizeof(vertices)); - - for(unsigned v = sv; v < 3; v++) - { - if(v == 0 || goraud) - { - uint32 raw_color = (*cb & 0xFFFFFF); - - vertices[v].r = raw_color & 0xFF; - vertices[v].g = (raw_color >> 8) & 0xFF; - vertices[v].b = (raw_color >> 16) & 0xFF; - - cb++; - } - else - { - vertices[v].r = vertices[0].r; - vertices[v].g = vertices[0].g; - vertices[v].b = vertices[0].b; - } - - vertices[v].x = sign_x_to_s32(11, ((int16)(*cb & 0xFFFF))) + OffsX; - vertices[v].y = sign_x_to_s32(11, ((int16)(*cb >> 16))) + OffsY; - cb++; - - if(textured) - { - vertices[v].u = (*cb & 0xFF); - vertices[v].v = (*cb >> 8) & 0xFF; - - if(v == 0) - { - Update_CLUT_Cache((*cb >> 16) & 0xFFFF); - } - - cb++; - } - } - - if(numvertices == 4) - { - if(InCmd == PS_GPU::INCMD_QUAD) - { - InCmd = PS_GPU::INCMD_NONE; - } - else - { - InCmd = PS_GPU::INCMD_QUAD; - InCmd_CC = cb0 >> 24; - memcpy(&InQuad_F3Vertices[0], &vertices[0], sizeof(tri_vertex) * 3); - } - } - - DrawTriangle(vertices); -} - -#undef COORD_POST_PADDING -#undef COORD_FBS -#undef COORD_MF_INT - -MDFN_HIDE extern const CTEntry Commands_20_3F[0x20] = -{ - /* 0x20 */ - POLY_HELPER(0x20), - POLY_HELPER(0x21), - POLY_HELPER(0x22), - POLY_HELPER(0x23), - POLY_HELPER(0x24), - POLY_HELPER(0x25), - POLY_HELPER(0x26), - POLY_HELPER(0x27), - POLY_HELPER(0x28), - POLY_HELPER(0x29), - POLY_HELPER(0x2a), - POLY_HELPER(0x2b), - POLY_HELPER(0x2c), - POLY_HELPER(0x2d), - POLY_HELPER(0x2e), - POLY_HELPER(0x2f), - POLY_HELPER(0x30), - POLY_HELPER(0x31), - POLY_HELPER(0x32), - POLY_HELPER(0x33), - POLY_HELPER(0x34), - POLY_HELPER(0x35), - POLY_HELPER(0x36), - POLY_HELPER(0x37), - POLY_HELPER(0x38), - POLY_HELPER(0x39), - POLY_HELPER(0x3a), - POLY_HELPER(0x3b), - POLY_HELPER(0x3c), - POLY_HELPER(0x3d), - POLY_HELPER(0x3e), - POLY_HELPER(0x3f) -}; - -} -} diff --git a/psx/octoshock/psx/gpu_sprite.cpp b/psx/octoshock/psx/gpu_sprite.cpp deleted file mode 100644 index 0a139775257..00000000000 --- a/psx/octoshock/psx/gpu_sprite.cpp +++ /dev/null @@ -1,274 +0,0 @@ -/******************************************************************************/ -/* Mednafen Sony PS1 Emulation Module */ -/******************************************************************************/ -/* gpu_sprite.cpp: -** Copyright (C) 2011-2017 Mednafen Team -** -** 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., -** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "psx.h" -#include "gpu.h" - -namespace MDFN_IEN_PSX -{ -namespace PS_GPU_INTERNAL -{ -#include "gpu_common.inc" - -template -static void DrawSprite(int32 x_arg, int32 y_arg, int32 w, int32 h, uint8 u_arg, uint8 v_arg, uint32 color) -{ - const int32 r = color & 0xFF; - const int32 g = (color >> 8) & 0xFF; - const int32 b = (color >> 16) & 0xFF; - const uint16 fill_color = 0x8000 | ((r >> 3) << 0) | ((g >> 3) << 5) | ((b >> 3) << 10); - - int32 x_start, x_bound; - int32 y_start, y_bound; - uint8 u, v; - int v_inc = 1, u_inc = 1; - - //printf("[GPU] Sprite: x=%d, y=%d, w=%d, h=%d\n", x_arg, y_arg, w, h); - - x_start = x_arg; - x_bound = x_arg + w; - - y_start = y_arg; - y_bound = y_arg + h; - - if(textured) - { - u = u_arg; - v = v_arg; - - //if(FlipX || FlipY || (u & 1) || (v & 1) || ((TexMode_TA == 0) && ((u & 3) || (v & 3)))) - // fprintf(stderr, "Flippy: %d %d 0x%02x 0x%02x\n", FlipX, FlipY, u, v); - - if(FlipX) - { - u_inc = -1; - u |= 1; - } - // FIXME: Something weird happens when lower bit of u is set and we're not doing horizontal flip, but I'm not sure what it is exactly(needs testing) - // It may only happen to the first pixel, so look for that case too during testing. - //else - // u = (u + 1) & ~1; - - if(FlipY) - { - v_inc = -1; - } - } - - if(x_start < ClipX0) - { - if(textured) - u += (ClipX0 - x_start) * u_inc; - - x_start = ClipX0; - } - - if(y_start < ClipY0) - { - if(textured) - v += (ClipY0 - y_start) * v_inc; - - y_start = ClipY0; - } - - if(x_bound > (ClipX1 + 1)) - x_bound = ClipX1 + 1; - - if(y_bound > (ClipY1 + 1)) - y_bound = ClipY1 + 1; - - //HeightMode && !dfe && ((y & 1) == ((DisplayFB_YStart + !field_atvs) & 1)) && !DisplayOff - //printf("%d:%d, %d, %d ---- heightmode=%d displayfb_ystart=%d field_atvs=%d displayoff=%d\n", w, h, scanline, dfe, HeightMode, DisplayFB_YStart, field_atvs, DisplayOff); - - for(int32 y = y_start; MDFN_LIKELY(y < y_bound); y++) - { - uint8 u_r; - - if(textured) - u_r = u; - - if(!LineSkipTest(y)) - { - if(MDFN_LIKELY(x_bound > x_start)) - { - // - // TODO: From tests on a PS1, even a 0-width sprite takes up time to "draw" proportional to its height. - // - int32 suck_time = /*8 +*/ (x_bound - x_start); - - if((BlendMode >= 0) || MaskEval_TA) - suck_time += (((x_bound + 1) & ~1) - (x_start & ~1)) >> 1; - - DrawTimeAvail -= suck_time; - } - - for(int32 x = x_start; MDFN_LIKELY(x < x_bound); x++) - { - if(textured) - { - uint16 fbw = GetTexel(u_r, v); - - if(fbw) - { - if(TexMult) - { - fbw = ModTexel(fbw, r, g, b, 3, 2); - } - PlotPixel(x, y, fbw); - } - } - else - PlotPixel(x, y, fill_color); - - if(textured) - u_r += u_inc; - } - } - if(textured) - v += v_inc; - } -} - -template -static void Command_DrawSprite(const uint32 *cb) -{ - int32 x, y; - int32 w, h; - uint8 u = 0, v = 0; - uint32 color = 0; - - DrawTimeAvail -= 16; // FIXME, correct time. - - color = *cb & 0x00FFFFFF; - cb++; - - x = sign_x_to_s32(11, (*cb & 0xFFFF)); - y = sign_x_to_s32(11, (*cb >> 16)); - cb++; - - if(textured) - { - u = *cb & 0xFF; - v = (*cb >> 8) & 0xFF; - Update_CLUT_Cache((*cb >> 16) & 0xFFFF); - cb++; - } - - switch(raw_size) - { - default: - case 0: - w = (*cb & 0x3FF); - h = (*cb >> 16) & 0x1FF; - cb++; - break; - - case 1: - w = 1; - h = 1; - break; - - case 2: - w = 8; - h = 8; - break; - - case 3: - w = 16; - h = 16; - break; - } - - //printf("SPRITE: %d %d %d -- %d %d\n", raw_size, x, y, w, h); - - x = sign_x_to_s32(11, x + OffsX); - y = sign_x_to_s32(11, y + OffsY); - - switch(SpriteFlip & 0x3000) - { - case 0x0000: - if(!TexMult || color == 0x808080) - DrawSprite(x, y, w, h, u, v, color); - else - DrawSprite(x, y, w, h, u, v, color); - break; - - case 0x1000: - if(!TexMult || color == 0x808080) - DrawSprite(x, y, w, h, u, v, color); - else - DrawSprite(x, y, w, h, u, v, color); - break; - - case 0x2000: - if(!TexMult || color == 0x808080) - DrawSprite(x, y, w, h, u, v, color); - else - DrawSprite(x, y, w, h, u, v, color); - break; - - case 0x3000: - if(!TexMult || color == 0x808080) - DrawSprite(x, y, w, h, u, v, color); - else - DrawSprite(x, y, w, h, u, v, color); - break; - } -} - -MDFN_HIDE extern const CTEntry Commands_60_7F[0x20] = -{ - SPR_HELPER(0x60), - SPR_HELPER(0x61), - SPR_HELPER(0x62), - SPR_HELPER(0x63), - SPR_HELPER(0x64), - SPR_HELPER(0x65), - SPR_HELPER(0x66), - SPR_HELPER(0x67), - SPR_HELPER(0x68), - SPR_HELPER(0x69), - SPR_HELPER(0x6a), - SPR_HELPER(0x6b), - SPR_HELPER(0x6c), - SPR_HELPER(0x6d), - SPR_HELPER(0x6e), - SPR_HELPER(0x6f), - SPR_HELPER(0x70), - SPR_HELPER(0x71), - SPR_HELPER(0x72), - SPR_HELPER(0x73), - SPR_HELPER(0x74), - SPR_HELPER(0x75), - SPR_HELPER(0x76), - SPR_HELPER(0x77), - SPR_HELPER(0x78), - SPR_HELPER(0x79), - SPR_HELPER(0x7a), - SPR_HELPER(0x7b), - SPR_HELPER(0x7c), - SPR_HELPER(0x7d), - SPR_HELPER(0x7e), - SPR_HELPER(0x7f) -}; - -} -} diff --git a/psx/octoshock/psx/gte.cpp b/psx/octoshock/psx/gte.cpp deleted file mode 100644 index 228062d68cd..00000000000 --- a/psx/octoshock/psx/gte.cpp +++ /dev/null @@ -1,1672 +0,0 @@ -/******************************************************************************/ -/* Mednafen Sony PS1 Emulation Module */ -/******************************************************************************/ -/* gte.cpp: -** Copyright (C) 2011-2016 Mednafen Team -** -** 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., -** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#pragma GCC optimize ("no-unroll-loops,no-peel-loops") - -#ifndef PSXDEV_GTE_TESTING -#include "psx.h" -#include "gte.h" -#endif - -/* Notes: - - AVSZ3/AVSZ4: - OTZ is MAC0 >> 12 - OTZ overflow/underflow flag is set in an overflow condition even if MAC0 == 0. - sf field bit has no effect? - - FLAG register: - Bits present mask: 0xfffff000 - - Checksum bit can't be directly set, it's apparently calculated like (bool)(FLAGS & 0x7f87e000) - - Instructions effectively clear it 0 at start. (todo: test "invalid" instructions) - - X/Y FIFO [3] register write pushes a copy down to [2] - -*/ - -#ifndef PSXDEV_GTE_TESTING -namespace MDFN_IEN_PSX -{ -#endif - -typedef struct -{ - int16 MX[3][3]; - int16 dummy; -} gtematrix; -#ifndef PSXDEV_GTE_TESTING -static_assert(sizeof(gtematrix) == 20, "gtematrix wrong size!"); -#endif - -typedef struct -{ - union - { - struct - { - uint8 R; - uint8 G; - uint8 B; - uint8 CD; - }; - uint8 Raw8[4]; - }; -} gtergb; - -typedef struct -{ - int16 X; - int16 Y; -} gtexy; - -static uint32 CR[32]; -static uint32 FLAGS; // Temporary for instruction execution, copied into CR[31] at end of instruction execution. - -typedef union -{ - gtematrix All[4]; - int32 Raw[4][5]; // Don't read from this(Raw[][]), only write(and when writing, if running on a big-endian platform, swap the upper 16-bits with the lower 16-bits) - int16 Raw16[4][10]; - - struct - { - gtematrix Rot; - gtematrix Light; - gtematrix Color; - gtematrix AbbyNormal; - }; -} Matrices_t; - -static Matrices_t Matrices; - -static union -{ - int32 All[4][4]; // Really only [4][3], but [4] to ease address calculation. - - struct - { - int32 T[4]; - int32 B[4]; - int32 FC[4]; - int32 Null[4]; - }; -} CRVectors; - -static int32 OFX; -static int32 OFY; -static uint16 H; -static int16 DQA; -static int32 DQB; - -static int16 ZSF3; -static int16 ZSF4; - - -// Begin DR -static int16 Vectors[3][4]; -static gtergb RGB; -static uint16 OTZ; - -static int16 IR[4]; - -#define IR0 IR[0] -#define IR1 IR[1] -#define IR2 IR[2] -#define IR3 IR[3] - -static gtexy XY_FIFO[4]; -static uint16 Z_FIFO[4]; -static gtergb RGB_FIFO[3]; -static int32 MAC[4]; -static uint32 LZCS; -static uint32 LZCR; - -static uint32 Reg23; -// end DR - -static INLINE uint8 Sat5(int16 cc) -{ - if(cc < 0) - cc = 0; - if(cc > 0x1F) - cc = 0x1F; - return(cc); -} - -// -// Newton-Raphson division table. (Initialized at startup; do NOT save in save states!) -// -static uint8 DivTable[0x100 + 1]; -static INLINE uint32 CalcRecip(uint16 divisor) -{ - int32 x = (0x101 + DivTable[(((divisor & 0x7FFF) + 0x40) >> 7)]); - int32 tmp = (((int32)divisor * -x) + 0x80) >> 8; - int32 tmp2 = ((x * (131072 + tmp)) + 0x80) >> 8; - - return(tmp2); -} - -void GTE_Init(void) -{ - for(uint32_t divisor = 0x8000; divisor < 0x10000; divisor += 0x80) - { - uint32_t xa = 512; - - for(unsigned i = 1; i < 5; i++) - { - xa = (xa * (1024 * 512 - ((divisor >> 7) * xa))) >> 18; - } - - DivTable[(divisor >> 7) & 0xFF] = ((xa + 1) >> 1) - 0x101; - //printf("%04x, %02x\n", divisor, ((xa + 1) >> 1) - 0x101); - } - - // - // To avoid a bounds limiting if statement in the emulation code: - DivTable[0x100] = DivTable[0xFF]; -} - -void GTE_Power(void) -{ - memset(CR, 0, sizeof(CR)); - //memset(DR, 0, sizeof(DR)); - - memset(Matrices.All, 0, sizeof(Matrices.All)); - memset(CRVectors.All, 0, sizeof(CRVectors.All)); - OFX = 0; - OFY = 0; - H = 0; - DQA = 0; - DQB = 0; - ZSF3 = 0; - ZSF4 = 0; - - - memset(Vectors, 0, sizeof(Vectors)); - memset(&RGB, 0, sizeof(RGB)); - OTZ = 0; - IR0 = 0; - IR1 = 0; - IR2 = 0; - IR3 = 0; - - memset(XY_FIFO, 0, sizeof(XY_FIFO)); - memset(Z_FIFO, 0, sizeof(Z_FIFO)); - memset(RGB_FIFO, 0, sizeof(RGB_FIFO)); - memset(MAC, 0, sizeof(MAC)); - LZCS = 0; - LZCR = 0; - - Reg23 = 0; -} - -void GTE_WriteCR(unsigned int which, uint32 value) -{ - static const uint32 mask_table[32] = { - /* 0x00 */ - 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0000FFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, - - /* 0x08 */ - 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0000FFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, - - /* 0x10 */ - 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0000FFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, - - /* 0x18 */ - 0xFFFFFFFF, 0xFFFFFFFF, 0x0000FFFF, 0x0000FFFF, 0xFFFFFFFF, 0x0000FFFF, 0x0000FFFF, 0xFFFFFFFF - }; - - //PSX_WARNING("[GTE] Write CR %d, 0x%08x", which, value); - - value &= mask_table[which]; - - CR[which] = value | (CR[which] & ~mask_table[which]); - - if(which < 24) - { - int we = which >> 3; - which &= 0x7; - - if(which >= 5) - CRVectors.All[we][which - 5] = value; - else - { - #ifdef MSB_FIRST - Matrices.Raw[we][which] = (value << 16) | (value >> 16); - #else - Matrices.Raw[we][which] = value; - #endif - } - return; - } - - switch(which) - { - case 24: - OFX = value; - break; - - case 25: - OFY = value; - break; - - case 26: - H = value; - break; - - case 27: - DQA = value; - break; - - case 28: - DQB = value; - break; - - case 29: - ZSF3 = value; - break; - - case 30: - ZSF4 = value; - break; - - case 31: - CR[31] = (value & 0x7ffff000) | ((value & 0x7f87e000) ? (1 << 31) : 0); - break; - } -} - -uint32 GTE_ReadCR(unsigned int which) -{ - uint32 ret = 0; - - switch(which) - { - default: - ret = CR[which]; - if(which == 4 || which == 12 || which == 20) - ret = (int16)ret; - break; - - case 24: - ret = OFX; - break; - - case 25: - ret = OFY; - break; - - case 26: - ret = (int16)H; - break; - - case 27: - ret = (int16)DQA; - break; - - case 28: - ret = DQB; - break; - - case 29: - ret = (int16)ZSF3; - break; - - case 30: - ret = (int16)ZSF4; - break; - - case 31: - ret = CR[31]; - break; - } - - return(ret); -} - -void GTE_WriteDR(unsigned int which, uint32 value) -{ - switch(which & 0x1F) - { - case 0: - Vectors[0][0] = value; - Vectors[0][1] = value >> 16; - break; - - case 1: - Vectors[0][2] = value; - break; - - case 2: - Vectors[1][0] = value; - Vectors[1][1] = value >> 16; - break; - - case 3: - Vectors[1][2] = value; - break; - - case 4: - Vectors[2][0] = value; - Vectors[2][1] = value >> 16; - break; - - case 5: - Vectors[2][2] = value; - break; - - case 6: - RGB.R = value >> 0; - RGB.G = value >> 8; - RGB.B = value >> 16; - RGB.CD = value >> 24; - break; - - case 7: - OTZ = value; - break; - - case 8: - IR0 = value; - break; - - case 9: - IR1 = value; - break; - - case 10: - IR2 = value; - break; - - case 11: - IR3 = value; - break; - - case 12: - XY_FIFO[0].X = value; - XY_FIFO[0].Y = value >> 16; - break; - - case 13: - XY_FIFO[1].X = value; - XY_FIFO[1].Y = value >> 16; - break; - - case 14: - XY_FIFO[2].X = value; - XY_FIFO[2].Y = value >> 16; - XY_FIFO[3].X = value; - XY_FIFO[3].Y = value >> 16; - break; - - case 15: - XY_FIFO[3].X = value; - XY_FIFO[3].Y = value >> 16; - - XY_FIFO[0] = XY_FIFO[1]; - XY_FIFO[1] = XY_FIFO[2]; - XY_FIFO[2] = XY_FIFO[3]; - break; - - case 16: - Z_FIFO[0] = value; - break; - - case 17: - Z_FIFO[1] = value; - break; - - case 18: - Z_FIFO[2] = value; - break; - - case 19: - Z_FIFO[3] = value; - break; - - case 20: - RGB_FIFO[0].R = value; - RGB_FIFO[0].G = value >> 8; - RGB_FIFO[0].B = value >> 16; - RGB_FIFO[0].CD = value >> 24; - break; - - case 21: - RGB_FIFO[1].R = value; - RGB_FIFO[1].G = value >> 8; - RGB_FIFO[1].B = value >> 16; - RGB_FIFO[1].CD = value >> 24; - break; - - case 22: - RGB_FIFO[2].R = value; - RGB_FIFO[2].G = value >> 8; - RGB_FIFO[2].B = value >> 16; - RGB_FIFO[2].CD = value >> 24; - break; - - case 23: - Reg23 = value; - break; - - case 24: - MAC[0] = value; - break; - - case 25: - MAC[1] = value; - break; - - case 26: - MAC[2] = value; - break; - - case 27: - MAC[3] = value; - break; - - case 28: - IR1 = ((value >> 0) & 0x1F) << 7; - IR2 = ((value >> 5) & 0x1F) << 7; - IR3 = ((value >> 10) & 0x1F) << 7; - break; - - case 29: // Read-only - break; - - case 30: - LZCS = value; - LZCR = MDFN_lzcount32(value ^ ((int32)value >> 31)); - break; - - case 31: // Read-only - break; - } -} - -uint32 GTE_ReadDR(unsigned int which) -{ - uint32 ret = 0; - - switch(which & 0x1F) - { - case 0: - ret = (uint16)Vectors[0][0] | ((uint16)Vectors[0][1] << 16); - break; - - case 1: - ret = (int16)Vectors[0][2]; - break; - - case 2: - ret = (uint16)Vectors[1][0] | ((uint16)Vectors[1][1] << 16); - break; - - case 3: - ret = (int16)Vectors[1][2]; - break; - - case 4: - ret = (uint16)Vectors[2][0] | ((uint16)Vectors[2][1] << 16); - break; - - case 5: - ret = (int16)Vectors[2][2]; - break; - - case 6: - ret = RGB.R | (RGB.G << 8) | (RGB.B << 16) | (RGB.CD << 24); - break; - - case 7: - ret = (uint16)OTZ; - break; - - case 8: - ret = (int16)IR0; - break; - - case 9: - ret = (int16)IR1; - break; - - case 10: - ret = (int16)IR2; - break; - - case 11: - ret = (int16)IR3; - break; - - case 12: - ret = (uint16)XY_FIFO[0].X | ((uint16)XY_FIFO[0].Y << 16); - break; - - case 13: - ret = (uint16)XY_FIFO[1].X | ((uint16)XY_FIFO[1].Y << 16); - break; - - case 14: - ret = (uint16)XY_FIFO[2].X | ((uint16)XY_FIFO[2].Y << 16); - break; - - case 15: - ret = (uint16)XY_FIFO[3].X | ((uint16)XY_FIFO[3].Y << 16); - break; - - case 16: - ret = (uint16)Z_FIFO[0]; - break; - - case 17: - ret = (uint16)Z_FIFO[1]; - break; - - case 18: - ret = (uint16)Z_FIFO[2]; - break; - - case 19: - ret = (uint16)Z_FIFO[3]; - break; - - case 20: - ret = RGB_FIFO[0].R | (RGB_FIFO[0].G << 8) | (RGB_FIFO[0].B << 16) | (RGB_FIFO[0].CD << 24); - break; - - case 21: - ret = RGB_FIFO[1].R | (RGB_FIFO[1].G << 8) | (RGB_FIFO[1].B << 16) | (RGB_FIFO[1].CD << 24); - break; - - case 22: - ret = RGB_FIFO[2].R | (RGB_FIFO[2].G << 8) | (RGB_FIFO[2].B << 16) | (RGB_FIFO[2].CD << 24); - break; - - case 23: - ret = Reg23; - break; - - case 24: - ret = MAC[0]; - break; - - case 25: - ret = MAC[1]; - break; - - case 26: - ret = MAC[2]; - break; - - case 27: - ret = MAC[3]; - break; - - case 28: - case 29: - ret = Sat5(IR1 >> 7) | (Sat5(IR2 >> 7) << 5) | (Sat5(IR3 >> 7) << 10); - break; - - case 30: - ret = LZCS; - break; - - case 31: - ret = LZCR; - break; - } - return(ret); -} - -#define sign_x_to_s64(_bits, _value) (((int64)((uint64)(_value) << (64 - _bits))) >> (64 - _bits)) -static INLINE int64 A_MV(unsigned which, int64 value) -{ - if(value >= (1LL << 43)) - FLAGS |= 1 << (30 - which); - - if(value < -(1LL << 43)) - FLAGS |= 1 << (27 - which); - - return sign_x_to_s64(44, value); -} - -static INLINE int64 F(int64 value) -{ - if(value < -2147483648LL) - { - // flag set here - FLAGS |= 1 << 15; - } - - if(value > 2147483647LL) - { - // flag set here - FLAGS |= 1 << 16; - } - return(value); -} - - -static INLINE int16 Lm_B(unsigned int which, int32 value, int lm) -{ - int32 tmp = lm << 15; - - if(value < (-32768 + tmp)) - { - // set flag here - FLAGS |= 1 << (24 - which); - value = -32768 + tmp; - } - - if(value > 32767) - { - // Set flag here - FLAGS |= 1 << (24 - which); - value = 32767; - } - - return(value); -} - - -static INLINE int16 Lm_B_PTZ(unsigned int which, int32 value, int32 ftv_value, int lm) -{ - int32 tmp = lm << 15; - - if(ftv_value < -32768) - { - FLAGS |= 1 << (24 - which); - } - - if(ftv_value > 32767) - { - FLAGS |= 1 << (24 - which); - } - - if(value < (-32768 + tmp)) - { - value = -32768 + tmp; - } - - if(value > 32767) - { - value = 32767; - } - - return(value); -} - -static INLINE uint8 Lm_C(unsigned int which, int32 value) -{ - if(value & ~0xFF) - { - // Set flag here - FLAGS |= 1 << (21 - which); // Tested with GPF - - if(value < 0) - value = 0; - - if(value > 255) - value = 255; - } - - return(value); -} - -static INLINE int32 Lm_D(int32 value, int unchained) -{ - // Not sure if we should have it as int64, or just chain on to and special case when the F flags are set. - if(!unchained) - { - if(FLAGS & (1 << 15)) - { - FLAGS |= 1 << 18; - return(0); - } - - if(FLAGS & (1 << 16)) - { - FLAGS |= 1 << 18; - return(0xFFFF); - } - } - - if(value < 0) - { - // Set flag here - value = 0; - FLAGS |= 1 << 18; // Tested with AVSZ3 - } - else if(value > 65535) - { - // Set flag here. - value = 65535; - FLAGS |= 1 << 18; // Tested with AVSZ3 - } - - return(value); -} - -static INLINE int32 Lm_G(unsigned int which, int32 value) -{ - if(value < -1024) - { - // Set flag here - value = -1024; - FLAGS |= 1 << (14 - which); - } - - if(value > 1023) - { - // Set flag here. - value = 1023; - FLAGS |= 1 << (14 - which); - } - - return(value); -} - -// limit to 4096, not 4095 -static INLINE int32 Lm_H(int32 value) -{ - if(value < 0) - { - value = 0; - FLAGS |= 1 << 12; - } - - if(value > 4096) - { - value = 4096; - FLAGS |= 1 << 12; - } - - return(value); -} - -static INLINE void MAC_to_RGB_FIFO(void) -{ - RGB_FIFO[0] = RGB_FIFO[1]; - RGB_FIFO[1] = RGB_FIFO[2]; - RGB_FIFO[2].R = Lm_C(0, MAC[1] >> 4); - RGB_FIFO[2].G = Lm_C(1, MAC[2] >> 4); - RGB_FIFO[2].B = Lm_C(2, MAC[3] >> 4); - RGB_FIFO[2].CD = RGB.CD; -} - - -static INLINE void MAC_to_IR(int lm) -{ - IR1 = Lm_B(0, MAC[1], lm); - IR2 = Lm_B(1, MAC[2], lm); - IR3 = Lm_B(2, MAC[3], lm); -} - -static INLINE void MultiplyMatrixByVector(const gtematrix *matrix, const int16 *v, const int32 *crv, uint32 sf, int lm) -{ - unsigned i; - - for(i = 0; i < 3; i++) - { - int64 tmp; - int32 mulr[3]; - - tmp = (uint64)(int64)crv[i] << 12; - - if(matrix == &Matrices.AbbyNormal) - { - if(i == 0) - { - mulr[0] = -((RGB.R << 4) * v[0]); - mulr[1] = (RGB.R << 4) * v[1]; - mulr[2] = IR0 * v[2]; - } - else - { - mulr[0] = (int16)CR[i] * v[0]; - mulr[1] = (int16)CR[i] * v[1]; - mulr[2] = (int16)CR[i] * v[2]; - } - } - else - { - mulr[0] = matrix->MX[i][0] * v[0]; - mulr[1] = matrix->MX[i][1] * v[1]; - mulr[2] = matrix->MX[i][2] * v[2]; - } - - tmp = A_MV(i, tmp + mulr[0]); - if(crv == CRVectors.FC) - { - Lm_B(i, tmp >> sf, false); - tmp = 0; - } - - tmp = A_MV(i, tmp + mulr[1]); - tmp = A_MV(i, tmp + mulr[2]); - - MAC[1 + i] = tmp >> sf; - } - - - MAC_to_IR(lm); -} - - -static INLINE void MultiplyMatrixByVector_PT(const gtematrix *matrix, const int16 *v, const int32 *crv, uint32 sf, int lm) -{ - int64 tmp[3]; - unsigned i; - - for(i = 0; i < 3; i++) - { - int32 mulr[3]; - - tmp[i] = (uint64)(int64)crv[i] << 12; - - mulr[0] = matrix->MX[i][0] * v[0]; - mulr[1] = matrix->MX[i][1] * v[1]; - mulr[2] = matrix->MX[i][2] * v[2]; - - tmp[i] = A_MV(i, tmp[i] + mulr[0]); - tmp[i] = A_MV(i, tmp[i] + mulr[1]); - tmp[i] = A_MV(i, tmp[i] + mulr[2]); - - MAC[1 + i] = tmp[i] >> sf; - } - - IR1 = Lm_B(0, MAC[1], lm); - IR2 = Lm_B(1, MAC[2], lm); - //printf("FTV: %08x %08x\n", crv[2], (uint32)(tmp[2] >> 12)); - IR3 = Lm_B_PTZ(2, MAC[3], tmp[2] >> 12, lm); - - Z_FIFO[0] = Z_FIFO[1]; - Z_FIFO[1] = Z_FIFO[2]; - Z_FIFO[2] = Z_FIFO[3]; - Z_FIFO[3] = Lm_D(tmp[2] >> 12, true); -} - - -#define DECODE_FIELDS \ - const uint32 sf MDFN_NOWARN_UNUSED = (instr & (1 << 19)) ? 12 : 0; \ - const uint32 mx MDFN_NOWARN_UNUSED = (instr >> 17) & 0x3; \ - const uint32 v_i = (instr >> 15) & 0x3; \ - const int32* cv MDFN_NOWARN_UNUSED = CRVectors.All[(instr >> 13) & 0x3]; \ - const int lm MDFN_NOWARN_UNUSED = (instr >> 10) & 1; \ - int16 v[3] MDFN_NOWARN_UNUSED; \ - if(v_i == 3) \ - { \ - v[0] = IR1; \ - v[1] = IR2; \ - v[2] = IR3; \ - } \ - else \ - { \ - v[0] = Vectors[v_i][0]; \ - v[1] = Vectors[v_i][1]; \ - v[2] = Vectors[v_i][2]; \ - } - - -static INLINE int32 SQR(uint32 instr) -{ - DECODE_FIELDS; - - MAC[1] = ((IR1 * IR1) >> sf); - MAC[2] = ((IR2 * IR2) >> sf); - MAC[3] = ((IR3 * IR3) >> sf); - - MAC_to_IR(lm); - - return(5); -} - -static INLINE int32 MVMVA(uint32 instr) -{ - DECODE_FIELDS; - - MultiplyMatrixByVector(&Matrices.All[mx], v, cv, sf, lm); - - return(8); -} - -static INLINE unsigned CountLeadingZeroU16(uint16 val) -{ - unsigned ret = 0; - - while(!(val & 0x8000) && ret < 16) - { - val <<= 1; - ret++; - } - - return ret; -} - -static INLINE uint32 Divide(uint32 dividend, uint32 divisor) -{ - //if((Z_FIFO[3] * 2) > H) - if((divisor * 2) > dividend) - { - unsigned shift_bias = CountLeadingZeroU16(divisor); - - dividend <<= shift_bias; - divisor <<= shift_bias; - - return std::min(0x1FFFF, ((uint64)dividend * CalcRecip(divisor | 0x8000) + 32768) >> 16); - } - else - { - FLAGS |= 1 << 17; - return 0x1FFFF; - } -} - -static INLINE void TransformXY(int64 h_div_sz) -{ - MAC[0] = F((int64)OFX + IR1 * h_div_sz) >> 16; - XY_FIFO[3].X = Lm_G(0, MAC[0]); - - MAC[0] = F((int64)OFY + IR2 * h_div_sz) >> 16; - XY_FIFO[3].Y = Lm_G(1, MAC[0]); - - XY_FIFO[0] = XY_FIFO[1]; - XY_FIFO[1] = XY_FIFO[2]; - XY_FIFO[2] = XY_FIFO[3]; -} - -static INLINE void TransformDQ(int64 h_div_sz) -{ - MAC[0] = F((int64)DQB + DQA * h_div_sz); - IR0 = Lm_H(((int64)DQB + DQA * h_div_sz) >> 12); -} - -static INLINE int32 RTPS(uint32 instr) -{ - DECODE_FIELDS; - int64 h_div_sz; - - MultiplyMatrixByVector_PT(&Matrices.Rot, Vectors[0], CRVectors.T, sf, lm); - h_div_sz = Divide(H, Z_FIFO[3]); - - TransformXY(h_div_sz); - TransformDQ(h_div_sz); - - return(15); -} - -static INLINE int32 RTPT(uint32 instr) -{ - DECODE_FIELDS; - int i; - - for(i = 0; i < 3; i++) - { - int64 h_div_sz; - - MultiplyMatrixByVector_PT(&Matrices.Rot, Vectors[i], CRVectors.T, sf, lm); - h_div_sz = Divide(H, Z_FIFO[3]); - - TransformXY(h_div_sz); - - if(i == 2) - TransformDQ(h_div_sz); - } - - return(23); -} - -static INLINE void NormColor(uint32 sf, int lm, uint32 v) -{ - int16 tmp_vector[3]; - - MultiplyMatrixByVector(&Matrices.Light, Vectors[v], CRVectors.Null, sf, lm); - - tmp_vector[0] = IR1; tmp_vector[1] = IR2; tmp_vector[2] = IR3; - MultiplyMatrixByVector(&Matrices.Color, tmp_vector, CRVectors.B, sf, lm); - - MAC_to_RGB_FIFO(); -} - -static INLINE int32 NCS(uint32 instr) -{ - DECODE_FIELDS; - - NormColor(sf, lm, 0); - - return(14); -} - -static int32 NCT(uint32 instr) -{ - DECODE_FIELDS; - int i; - - for(i = 0; i < 3; i++) - NormColor(sf, lm, i); - - return(30); -} - -static INLINE void NormColorColor(uint32 v, uint32 sf, int lm) -{ - int16 tmp_vector[3]; - - MultiplyMatrixByVector(&Matrices.Light, Vectors[v], CRVectors.Null, sf, lm); - - tmp_vector[0] = IR1; tmp_vector[1] = IR2; tmp_vector[2] = IR3; - MultiplyMatrixByVector(&Matrices.Color, tmp_vector, CRVectors.B, sf, lm); - - MAC[1] = ((RGB.R << 4) * IR1) >> sf; - MAC[2] = ((RGB.G << 4) * IR2) >> sf; - MAC[3] = ((RGB.B << 4) * IR3) >> sf; - - MAC_to_IR(lm); - - MAC_to_RGB_FIFO(); -} - -static INLINE int32 NCCS(uint32 instr) -{ - DECODE_FIELDS; - - NormColorColor(0, sf, lm); - return(17); -} - - -static INLINE int32 NCCT(uint32 instr) -{ - int i; - DECODE_FIELDS; - - for(i = 0; i < 3; i++) - NormColorColor(i, sf, lm); - - return(39); -} - -static INLINE void DepthCue(int mult_IR123, int RGB_from_FIFO, uint32 sf, int lm) -{ - int32 RGB_temp[3]; - int32 IR_temp[3] = { IR1, IR2, IR3 }; - int i; - - //assert(sf); - - if(RGB_from_FIFO) - { - RGB_temp[0] = RGB_FIFO[0].R << 4; - RGB_temp[1] = RGB_FIFO[0].G << 4; - RGB_temp[2] = RGB_FIFO[0].B << 4; - } - else - { - RGB_temp[0] = RGB.R << 4; - RGB_temp[1] = RGB.G << 4; - RGB_temp[2] = RGB.B << 4; - } - - if(mult_IR123) - { - for(i = 0; i < 3; i++) - { - MAC[1 + i] = A_MV(i, ((int64)((uint64)(int64)CRVectors.FC[i] << 12) - RGB_temp[i] * IR_temp[i])) >> sf; - MAC[1 + i] = A_MV(i, (RGB_temp[i] * IR_temp[i] + IR0 * Lm_B(i, MAC[1 + i], false))) >> sf; - } - } - else - { - for(i = 0; i < 3; i++) - { - MAC[1 + i] = A_MV(i, ((int64)((uint64)(int64)CRVectors.FC[i] << 12) - (int32)((uint32)RGB_temp[i] << 12))) >> sf; - MAC[1 + i] = A_MV(i, ((int64)((uint64)(int64)RGB_temp[i] << 12) + IR0 * Lm_B(i, MAC[1 + i], false))) >> sf; - } - } - - MAC_to_IR(lm); - - MAC_to_RGB_FIFO(); -} - - -static INLINE int32 DCPL(uint32 instr) -{ - DECODE_FIELDS; - - DepthCue(true, false, sf, lm); - - return(8); -} - - -static INLINE int32 DPCS(uint32 instr) -{ - DECODE_FIELDS; - - DepthCue(false, false, sf, lm); - - return(8); -} - -static INLINE int32 DPCT(uint32 instr) -{ - int i; - DECODE_FIELDS; - - for(i = 0; i < 3; i++) - { - DepthCue(false, true, sf, lm); - } - - return(17); -} - -static INLINE int32 INTPL(uint32 instr) -{ - DECODE_FIELDS; - - MAC[1] = A_MV(0, ((int64)((uint64)(int64)CRVectors.FC[0] << 12) - (int32)((uint32)(int32)IR1 << 12))) >> sf; - MAC[2] = A_MV(1, ((int64)((uint64)(int64)CRVectors.FC[1] << 12) - (int32)((uint32)(int32)IR2 << 12))) >> sf; - MAC[3] = A_MV(2, ((int64)((uint64)(int64)CRVectors.FC[2] << 12) - (int32)((uint32)(int32)IR3 << 12))) >> sf; - - MAC[1] = A_MV(0, ((int64)((uint64)(int64)IR1 << 12) + IR0 * Lm_B(0, MAC[1], false)) >> sf); - MAC[2] = A_MV(1, ((int64)((uint64)(int64)IR2 << 12) + IR0 * Lm_B(1, MAC[2], false)) >> sf); - MAC[3] = A_MV(2, ((int64)((uint64)(int64)IR3 << 12) + IR0 * Lm_B(2, MAC[3], false)) >> sf); - - MAC_to_IR(lm); - - MAC_to_RGB_FIFO(); - - return(8); -} - - -static INLINE void NormColorDepthCue(uint32 v, uint32 sf, int lm) -{ - int16 tmp_vector[3]; - - MultiplyMatrixByVector(&Matrices.Light, Vectors[v], CRVectors.Null, sf, lm); - - tmp_vector[0] = IR1; tmp_vector[1] = IR2; tmp_vector[2] = IR3; - MultiplyMatrixByVector(&Matrices.Color, tmp_vector, CRVectors.B, sf, lm); - - DepthCue(true, false, sf, lm); -} - -static INLINE int32 NCDS(uint32 instr) -{ - DECODE_FIELDS; - - NormColorDepthCue(0, sf, lm); - - return(19); -} - -static INLINE int32 NCDT(uint32 instr) -{ - int i; - DECODE_FIELDS; - - for(i = 0; i < 3; i++) - { - NormColorDepthCue(i, sf, lm); - } - - return(44); -} - -static INLINE int32 CC(uint32 instr) -{ - DECODE_FIELDS; - int16 tmp_vector[3]; - - tmp_vector[0] = IR1; tmp_vector[1] = IR2; tmp_vector[2] = IR3; - MultiplyMatrixByVector(&Matrices.Color, tmp_vector, CRVectors.B, sf, lm); - - MAC[1] = ((RGB.R << 4) * IR1) >> sf; - MAC[2] = ((RGB.G << 4) * IR2) >> sf; - MAC[3] = ((RGB.B << 4) * IR3) >> sf; - - MAC_to_IR(lm); - - MAC_to_RGB_FIFO(); - - return(11); -} - -static INLINE int32 CDP(uint32 instr) -{ - DECODE_FIELDS; - int16 tmp_vector[3]; - - tmp_vector[0] = IR1; tmp_vector[1] = IR2; tmp_vector[2] = IR3; - MultiplyMatrixByVector(&Matrices.Color, tmp_vector, CRVectors.B, sf, lm); - - DepthCue(true, false, sf, lm); - - return(13); -} - -static INLINE int32 NCLIP(uint32 instr) -{ - DECODE_FIELDS; - - MAC[0] = F( (int64)(XY_FIFO[0].X * (XY_FIFO[1].Y - XY_FIFO[2].Y)) + (XY_FIFO[1].X * (XY_FIFO[2].Y - XY_FIFO[0].Y)) + (XY_FIFO[2].X * (XY_FIFO[0].Y - XY_FIFO[1].Y)) - ); - - return(8); -} - -static INLINE int32 AVSZ3(uint32 instr) -{ - DECODE_FIELDS; - - MAC[0] = F(((int64)ZSF3 * (Z_FIFO[1] + Z_FIFO[2] + Z_FIFO[3]))); - - OTZ = Lm_D(MAC[0] >> 12, false); - - return(5); -} - -static INLINE int32 AVSZ4(uint32 instr) -{ - DECODE_FIELDS; - - MAC[0] = F(((int64)ZSF4 * (Z_FIFO[0] + Z_FIFO[1] + Z_FIFO[2] + Z_FIFO[3]))); - - OTZ = Lm_D(MAC[0] >> 12, false); - - return(5); -} - - -// -32768 * -32768 - 32767 * -32768 = 2147450880 -// (2 ^ 31) - 1 = 2147483647 -static INLINE int32 OP(uint32 instr) -{ - DECODE_FIELDS; - - MAC[1] = ((Matrices.Rot.MX[1][1] * IR3) - (Matrices.Rot.MX[2][2] * IR2)) >> sf; - MAC[2] = ((Matrices.Rot.MX[2][2] * IR1) - (Matrices.Rot.MX[0][0] * IR3)) >> sf; - MAC[3] = ((Matrices.Rot.MX[0][0] * IR2) - (Matrices.Rot.MX[1][1] * IR1)) >> sf; - - MAC_to_IR(lm); - - return(6); -} - -static INLINE int32 GPF(uint32 instr) -{ - DECODE_FIELDS; - - MAC[1] = (IR0 * IR1) >> sf; - MAC[2] = (IR0 * IR2) >> sf; - MAC[3] = (IR0 * IR3) >> sf; - - MAC_to_IR(lm); - - MAC_to_RGB_FIFO(); - - return(5); -} - -static INLINE int32 GPL(uint32 instr) -{ - DECODE_FIELDS; - - MAC[1] = A_MV(0, (int64)((uint64)(int64)MAC[1] << sf) + (IR0 * IR1)) >> sf; - MAC[2] = A_MV(1, (int64)((uint64)(int64)MAC[2] << sf) + (IR0 * IR2)) >> sf; - MAC[3] = A_MV(2, (int64)((uint64)(int64)MAC[3] << sf) + (IR0 * IR3)) >> sf; - - MAC_to_IR(lm); - - MAC_to_RGB_FIFO(); - - return(5); -} - -/* - ---------------------------------------------------------------------------------------------- -| 24 23 22 21 20 | 19 | 18 17 | 16 15 | 14 13 | 12 11 | 10 | 9 8 7 6 | 5 4 3 2 1 0 | -|-------------------------------------------------------------------------------------------| -| (unused) | sf | mx | v | cv |(unused)| lm | (unused) | opcode | ---------------------------------------------------------------------------------------------- - (unused) = unused, ignored - - sf = shift 12 - - mx = matrix selection - - v = source vector - - cv = add vector(translation/back/far color(bugged)/none) - - (unused) = unused, ignored - - lm = limit negative results to 0 - - (unused) = unused, ignored - - opcode = operation code -*/ - -int32 GTE_Instruction(uint32 instr) -{ - const unsigned code = instr & 0x3F; - int32 ret = 1; - - FLAGS = 0; - - switch(code) - { - default: -#ifndef PSXDEV_GTE_TESTING - PSX_WARNING("[GTE] Unknown instruction code: 0x%02x", code); -#endif - break; - - case 0x00: // alternate? - case 0x01: - ret = RTPS(instr); - break; - -/* - case 0x02: // UNSTABLE? - break; - - case 0x03: // UNSTABLE? - break; - - case 0x04: // Probably simple with v,cv,sf,mx,lm ignored. Same calculation as 0x3B? - break; - - case 0x05: // UNSTABLE? - break; -*/ - - case 0x06: - ret = NCLIP(instr); - break; - -/* - case 0x07: // UNSTABLE? - break; - - case 0x08: // UNSTABLE? - break; - - case 0x09: // UNSTABLE? - break; - - case 0x0A: // UNSTABLE? - break; - - case 0x0B: // UNSTABLE? - break; - -*/ - - case 0x0C: - ret = OP(instr); - break; - -/* - case 0x0D: // UNSTABLE? - break; - - case 0x0E: // UNSTABLE? - break; - - case 0x0F: // UNSTABLE? - break; -*/ - - case 0x10: - ret = DPCS(instr); - break; - - case 0x11: - ret = INTPL(instr); - break; - - case 0x12: - ret = MVMVA(instr); - break; - - case 0x13: - ret = NCDS(instr); - break; - - case 0x14: - ret = CDP(instr); - break; - - -/* - case 0x15: // does one push on RGB FIFO, what else... - break; -*/ - - case 0x16: - ret = NCDT(instr); - break; - -/* - case 0x17: // PARTIALLY UNSTABLE(depending on sf or v or cv or mx or lm???), similar behavior under some conditions to 0x16? - break; - - case 0x18: - break; - - case 0x19: - break; -*/ - - // case 0x1A handled next to case 0x29 - - case 0x1B: - ret = NCCS(instr); - break; - - case 0x1C: - ret = CC(instr); - break; - -/* - case 0x1D: - break; -*/ - - case 0x1E: - ret = NCS(instr); - break; - -/* - case 0x1F: - break; -*/ - - case 0x20: - ret = NCT(instr); - break; -/* - case 0x21: - break; - - case 0x22: // UNSTABLE? - break; - - case 0x23: - break; - - case 0x24: - break; - - case 0x25: - break; - - case 0x26: - break; - - case 0x27: - break; -*/ - - case 0x28: - ret = SQR(instr); - break; - - case 0x1A: // Alternate for 0x29? - case 0x29: - ret = DCPL(instr); - break; - - case 0x2A: - ret = DPCT(instr); - break; - -/* - case 0x2B: - break; - - case 0x2C: - break; -*/ - - case 0x2D: - ret = AVSZ3(instr); - break; - - case 0x2E: - ret = AVSZ4(instr); - break; - -/* - case 0x2F: // UNSTABLE? - break; -*/ - - case 0x30: - ret = RTPT(instr); - break; - -/* - case 0x31: // UNSTABLE? - break; - - case 0x32: // UNSTABLE? - break; - - case 0x33: // UNSTABLE? - break; - - case 0x34: // UNSTABLE? - break; - - case 0x35: // UNSTABLE? - break; - - case 0x36: // UNSTABLE? - break; - - case 0x37: // UNSTABLE? - break; - - case 0x38: - break; - - case 0x39: // Probably simple with v,cv,sf,mx,lm ignored. - break; - - case 0x3A: // Probably simple with v,cv,sf,mx,lm ignored. - break; - - case 0x3B: // Probably simple with v,cv,sf,mx,lm ignored. Same calculation as 0x04? - break; - - case 0x3C: // UNSTABLE? - break; -*/ - - case 0x3D: - ret = GPF(instr); - break; - - case 0x3E: - ret = GPL(instr); - break; - - case 0x3F: - ret = NCCT(instr); - break; - } - - if(FLAGS & 0x7f87e000) - FLAGS |= 1 << 31; - - CR[31] = FLAGS; - - return(ret - 1); -} - -void GTE_SyncState(bool isReader, EW::NewState *ns) -{ - NSS(CR); - NSS(FLAGS); - - NSS(Matrices); - - NSS(CRVectors); - - NSS(OFX); - NSS(OFY); - NSS(H); - NSS(DQA); - NSS(DQB); - - NSS(ZSF3); - NSS(ZSF4); - NSS(Vectors); - - NSS(RGB); - NSS(OTZ); - NSS(IR); - - NSS(XY_FIFO); - - NSS(Z_FIFO); - - NSS(RGB_FIFO); - - NSS(MAC); - - NSS(LZCS); - NSS(LZCR); - NSS(Reg23); -} - -#ifndef PSXDEV_GTE_TESTING -} -#endif diff --git a/psx/octoshock/psx/gte.h b/psx/octoshock/psx/gte.h deleted file mode 100644 index b31260d65d3..00000000000 --- a/psx/octoshock/psx/gte.h +++ /dev/null @@ -1,42 +0,0 @@ -/******************************************************************************/ -/* Mednafen Sony PS1 Emulation Module */ -/******************************************************************************/ -/* gte.h: -** Copyright (C) 2011-2016 Mednafen Team -** -** 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., -** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef __MDFN_PSX_GTE_H -#define __MDFN_PSX_GTE_H - -namespace MDFN_IEN_PSX -{ - -void GTE_Init(void) MDFN_COLD; -void GTE_Power(void) MDFN_COLD; - -int32 GTE_Instruction(uint32 instr); - -void GTE_WriteCR(unsigned int which, uint32 value); -void GTE_WriteDR(unsigned int which, uint32 value); - -uint32 GTE_ReadCR(unsigned int which); -uint32 GTE_ReadDR(unsigned int which); - - -} - -#endif diff --git a/psx/octoshock/psx/input/dualanalog.cpp b/psx/octoshock/psx/input/dualanalog.cpp deleted file mode 100644 index 181d6a33249..00000000000 --- a/psx/octoshock/psx/input/dualanalog.cpp +++ /dev/null @@ -1,269 +0,0 @@ -/******************************************************************************/ -/* Mednafen Sony PS1 Emulation Module */ -/******************************************************************************/ -/* dualanalog.cpp: -** Copyright (C) 2012-2016 Mednafen Team -** -** 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., -** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "../psx.h" -#include "../frontio.h" -#include "dualanalog.h" - -namespace MDFN_IEN_PSX -{ - -class InputDevice_DualAnalog : public InputDevice -{ - public: - - InputDevice_DualAnalog(bool joystick_mode_); - virtual ~InputDevice_DualAnalog(); - - virtual void Power(void); - virtual void UpdateInput(const void *data); - virtual void SyncState(bool isReader, EW::NewState *ns); - - // - // - // - virtual void SetDTR(bool new_dtr); - virtual bool GetDSR(void); - virtual bool Clock(bool TxD, int32 &dsr_pulse_delay); - - private: - -//non-serialized state - IO_DualAnalog* io; - - bool joystick_mode; - bool dtr; - - uint8 buttons[2]; - uint8 axes[2][2]; - - int32 command_phase; - uint32 bitpos; - uint8 receive_buffer; - - uint8 command; - - uint8 transmit_buffer[8]; - uint32 transmit_pos; - uint32 transmit_count; -}; - -InputDevice_DualAnalog::InputDevice_DualAnalog(bool joystick_mode_) : joystick_mode(joystick_mode_) -{ - Power(); -} - -InputDevice_DualAnalog::~InputDevice_DualAnalog() -{ - -} - -void InputDevice_DualAnalog::Power(void) -{ - dtr = 0; - - buttons[0] = buttons[1] = 0; - - command_phase = 0; - - bitpos = 0; - - receive_buffer = 0; - - command = 0; - - memset(transmit_buffer, 0, sizeof(transmit_buffer)); - - transmit_pos = 0; - transmit_count = 0; -} - -void InputDevice_DualAnalog::SyncState(bool isReader, EW::NewState *ns) -{ - NSS(joystick_mode); - NSS(dtr); - - NSS(buttons); - NSS(axes); - - NSS(command_phase); - NSS(bitpos); - NSS(receive_buffer); - - NSS(command); - - NSS(transmit_buffer); - NSS(transmit_pos); - NSS(transmit_count); -} - -void InputDevice_DualAnalog::UpdateInput(const void *data) -{ - io = (IO_DualAnalog*)data; - - buttons[0] = io->buttons[0]; - buttons[1] = io->buttons[1]; - - //OCTOSHOCK EDIT - so we can set values directly - //for(int stick = 0; stick < 2; stick++) - //{ - // for(int axis = 0; axis < 2; axis++) - // { - // const uint8* aba = &d8[2] + stick * 8 + axis * 4; - // int32 tmp; - - // tmp = 32768 + MDFN_de16lsb(&aba[0]) - ((int32)MDFN_de16lsb(&aba[2]) * 32768 / 32767); - // tmp >>= 8; - - // axes[stick][axis] = tmp; - // } - //} - - axes[0][0] = io->right_x; - axes[0][1] = io->right_y; - axes[1][0] = io->left_x; - axes[1][1] = io->left_y; - - //printf("%d %d %d %d\n", axes[0][0], axes[0][1], axes[1][0], axes[1][1]); -} - - -void InputDevice_DualAnalog::SetDTR(bool new_dtr) -{ - if(!dtr && new_dtr) - { - command_phase = 0; - bitpos = 0; - transmit_pos = 0; - transmit_count = 0; - } - else if(dtr && !new_dtr) - { - //if(bitpos || transmit_count) - // printf("[PAD] Abort communication!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"); - } - - dtr = new_dtr; -} - -bool InputDevice_DualAnalog::GetDSR(void) -{ - if(!dtr) - return(0); - - if(!bitpos && transmit_count) - return(1); - - return(0); -} - -bool InputDevice_DualAnalog::Clock(bool TxD, int32 &dsr_pulse_delay) -{ - bool ret = 1; - - dsr_pulse_delay = 0; - - if(!dtr) - return(1); - - if(transmit_count) - ret = (transmit_buffer[transmit_pos] >> bitpos) & 1; - - receive_buffer &= ~(1 << bitpos); - receive_buffer |= TxD << bitpos; - bitpos = (bitpos + 1) & 0x7; - - if(!bitpos) - { - //printf("[PAD] Receive: %02x -- command_phase=%d\n", receive_buffer, command_phase); - - if(transmit_count) - { - transmit_pos++; - transmit_count--; - } - - - switch(command_phase) - { - case 0: - if(receive_buffer != 0x01) - command_phase = -1; - else - { - transmit_buffer[0] = joystick_mode ? 0x53 : 0x73; - transmit_pos = 0; - transmit_count = 1; - command_phase++; - } - break; - - case 1: - command = receive_buffer; - command_phase++; - - transmit_buffer[0] = 0x5A; - - //if(command != 0x42) - // fprintf(stderr, "Gamepad unhandled command: 0x%02x\n", command); - - if(command == 0x42) - { - transmit_buffer[1] = 0xFF ^ buttons[0]; - transmit_buffer[2] = 0xFF ^ buttons[1]; - transmit_buffer[3] = axes[0][0]; - transmit_buffer[4] = axes[0][1]; - transmit_buffer[5] = axes[1][0]; - transmit_buffer[6] = axes[1][1]; - transmit_pos = 0; - transmit_count = 7; - io->active = true; - } - else - { - command_phase = -1; - transmit_buffer[1] = 0; - transmit_buffer[2] = 0; - transmit_pos = 0; - transmit_count = 0; - } - break; - case 2: - //if(receive_buffer) - // printf("%d: %02x\n", 7 - transmit_count, receive_buffer); - break; - } - } - - if(!bitpos && transmit_count) - dsr_pulse_delay = 0x40; //0x100; - - return(ret); -} - -InputDevice *Device_DualAnalog_Create(bool joystick_mode) -{ - return new InputDevice_DualAnalog(joystick_mode); -} - - - -} diff --git a/psx/octoshock/psx/input/dualanalog.h b/psx/octoshock/psx/input/dualanalog.h deleted file mode 100644 index 47d897be160..00000000000 --- a/psx/octoshock/psx/input/dualanalog.h +++ /dev/null @@ -1,40 +0,0 @@ -/******************************************************************************/ -/* Mednafen Sony PS1 Emulation Module */ -/******************************************************************************/ -/* dualanalog.h: -** Copyright (C) 2012-2016 Mednafen Team -** -** 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., -** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - - -#ifndef __MDFN_PSX_INPUT_DUALANALOG_H -#define __MDFN_PSX_INPUT_DUALANALOG_H - -namespace MDFN_IEN_PSX -{ -InputDevice *Device_DualAnalog_Create(bool joystick_mode); - -EW_PACKED( -struct IO_DualAnalog -{ - u8 buttons[2]; - u8 right_x, right_y; - u8 left_x, left_y; - u8 active; -}); - -} -#endif diff --git a/psx/octoshock/psx/input/dualshock.cpp b/psx/octoshock/psx/input/dualshock.cpp deleted file mode 100644 index 400c69d4f4e..00000000000 --- a/psx/octoshock/psx/input/dualshock.cpp +++ /dev/null @@ -1,1054 +0,0 @@ -/******************************************************************************/ -/* Mednafen Sony PS1 Emulation Module */ -/******************************************************************************/ -/* dualshock.cpp: -** Copyright (C) 2012-2017 Mednafen Team -** -** 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., -** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "../psx.h" -#include "../frontio.h" -#include "dualshock.h" - -/* - TODO: - If we ever call Update() more than once per video frame(IE 50/60Hz), we'll need to add debounce logic to the analog mode button evaluation code. -*/ - -/* Notes: - - Both DA and DS style rumblings work in both analog and digital modes. - - Regarding getting Dual Shock style rumble working, Sony is evil and/or mean. The owl tells me to burn Sony with boiling oil. - - To enable Dual Shock-style rumble, the game has to at least enter MAD MUNCHKINS MODE with command 0x43, and send the appropriate data(not the actual rumble type data per-se) - with command 0x4D. - - DualAnalog-style rumble support seems to be borked until power loss if MAD MUNCHKINS MODE is even entered once...investigate further. - - Command 0x44 in MAD MUNCHKINS MODE can turn on/off analog mode(and the light with it). - - Command 0x42 in MAD MUNCHKINS MODE will return the analog mode style gamepad data, even when analog mode is off. In combination with command 0x44, this could hypothetically - be used for using the light in the gamepad as some kind of game mechanic). - - Dual Analog-style rumble notes(some of which may apply to DS too): - Rumble appears to stop if you hold DTR active(TODO: for how long? instant?). (TODO: investigate if it's still stopped even if a memory card device number is sent. It may be, since rumble may - cause excessive current draw in combination with memory card access) - - Rumble will work even if you interrupt the communication process after you've sent the rumble data(via command 0x42). - Though if you interrupt it when you've only sent partial rumble data, dragons will eat you and I don't know(seems to have timing-dependent or random effects or something; - based on VERY ROUGH testing). -*/ - -namespace MDFN_IEN_PSX -{ - -class InputDevice_DualShock : public InputDevice -{ - public: - - InputDevice_DualShock(); - virtual ~InputDevice_DualShock(); - - virtual void Power(void); - virtual void SyncState(bool isReader, EW::NewState *ns); - - virtual void Update(const pscpu_timestamp_t timestamp); - virtual void ResetTS(void); - virtual void UpdateInput(const void *data); - - // - // - // - virtual void SetDTR(bool new_dtr); - virtual bool GetDSR(void); - virtual bool Clock(bool TxD, int32 &dsr_pulse_delay); - - private: - - void CheckManualAnaModeChange(void); - - //non-serialized state - IO_Dualshock* io; - - // - // - bool cur_ana_button_state; - bool prev_ana_button_state; - int64 combo_anatoggle_counter; - // - - bool da_rumble_compat; - - bool analog_mode; - bool analog_mode_locked; - - bool mad_munchkins; - uint8 rumble_magic[6]; - - uint8 rumble_param[2]; - - bool dtr; - - uint8 buttons[2]; - uint8 axes[2][2]; - - int32 command_phase; - uint32 bitpos; - uint8 receive_buffer; - - uint8 command; - - uint8 transmit_buffer[8]; - uint32 transmit_pos; - uint32 transmit_count; - - // - // - // - pscpu_timestamp_t lastts; - - // - // - bool amct_enabled; -}; - -InputDevice_DualShock::InputDevice_DualShock() -{ - Power(); -} - -InputDevice_DualShock::~InputDevice_DualShock() -{ - -} - -void InputDevice_DualShock::Update(const pscpu_timestamp_t timestamp) -{ - lastts = timestamp; -} - -void InputDevice_DualShock::ResetTS(void) -{ - //printf("%lld\n", combo_anatoggle_counter); - if(combo_anatoggle_counter >= 0) - combo_anatoggle_counter += lastts; - lastts = 0; -} - -// -// This simulates the behavior of the actual DualShock(analog toggle button evaluation is suspended while DTR is active). -// Call in Update(), and whenever dtr goes inactive in the port access code. -void InputDevice_DualShock::CheckManualAnaModeChange(void) -{ - if(!dtr) - { - bool need_mode_toggle = false; - - if(amct_enabled) - { - if(buttons[0] == 0x09 && buttons[1] == 0x0f) - { - if(combo_anatoggle_counter == -1) - combo_anatoggle_counter = 0; - else if(combo_anatoggle_counter >= (44100 * 768)) - { - need_mode_toggle = true; - combo_anatoggle_counter = -2; - } - } - else - combo_anatoggle_counter = -1; - } - else - { - combo_anatoggle_counter = -1; - if(cur_ana_button_state && (cur_ana_button_state != prev_ana_button_state)) - { - need_mode_toggle = true; - } - } - - if(need_mode_toggle) - { - if(analog_mode_locked) - { - //MDFN_DispMessage(_("%s: Analog mode is locked %s."), gp_name.c_str(), analog_mode ? _("on") : _("off")); - } - else - analog_mode = !analog_mode; - } - - prev_ana_button_state = cur_ana_button_state; // Don't move this outside of the if(!dtr) block! - } -} - -void InputDevice_DualShock::Power(void) -{ - amct_enabled = false; //for octoshock, this function isn't supported - - combo_anatoggle_counter = -2; - lastts = 0; - // - // - - dtr = 0; - - buttons[0] = buttons[1] = 0; - - command_phase = 0; - - bitpos = 0; - - receive_buffer = 0; - - command = 0; - - memset(transmit_buffer, 0, sizeof(transmit_buffer)); - - transmit_pos = 0; - transmit_count = 0; - - analog_mode = false; - analog_mode_locked = false; - - mad_munchkins = false; - memset(rumble_magic, 0xFF, sizeof(rumble_magic)); - memset(rumble_param, 0, sizeof(rumble_param)); - - da_rumble_compat = true; - - prev_ana_button_state = false; -} - - void InputDevice_DualShock::SyncState(bool isReader, EW::NewState *ns) - { - NSS(cur_ana_button_state); - NSS(prev_ana_button_state); - NSS(combo_anatoggle_counter); - - NSS(da_rumble_compat); - - NSS(analog_mode); - NSS(analog_mode_locked); - - NSS(mad_munchkins); - NSS(rumble_magic); - - NSS(rumble_param); - - NSS(dtr); - - NSS(buttons); - NSS(axes); - - NSS(command_phase); - NSS(bitpos); - NSS(receive_buffer); - - NSS(command); - - NSS(transmit_buffer); - NSS(transmit_pos); - NSS(transmit_count); - - //THERES MORE BUFFER SIZE SANITY CHECKS HERE. DONT LIKE THAT STUFF - } - -void InputDevice_DualShock::UpdateInput(const void *data) -{ - io = (IO_Dualshock*)data; - uint8 *d8 = (uint8 *)data; - uint8* const rumb_dp = &d8[3 + 16]; - - buttons[0] = d8[0]; - buttons[1] = d8[1]; - cur_ana_button_state = d8[2] & 0x01; - - //OCTOSHOCK EDIT - so we can set values directly - //for(int stick = 0; stick < 2; stick++) - //{ - // for(int axis = 0; axis < 2; axis++) - // { - // //const uint8* aba = &d8[3] + stick * 8 + axis * 4; - // //int32 tmp; - - // //tmp = 32767 + MDFN_de16lsb(&aba[0]) - MDFN_de16lsb(&aba[2]); - // //tmp = (tmp * 0x100) / 0xFFFF; - // - // } - //} - axes[0][0] = d8[3]; - axes[0][1] = d8[4]; - axes[1][0] = d8[5]; - axes[1][1] = d8[6]; - - - //printf("%3d:%3d, %3d:%3d\n", axes[0][0], axes[0][1], axes[1][0], axes[1][1]); - - //printf("RUMBLE: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n", rumble_magic[0], rumble_magic[1], rumble_magic[2], rumble_magic[3], rumble_magic[4], rumble_magic[5]); - //printf("%d, 0x%02x 0x%02x\n", da_rumble_compat, rumble_param[0], rumble_param[1]); - - if(da_rumble_compat == false) - { - uint8 sneaky_weaky = 0; - - if(rumble_param[0] == 0x01) - sneaky_weaky = 0xFF; - - MDFN_en16lsb(rumb_dp, (sneaky_weaky << 0) | (rumble_param[1] << 8)); - } - else - { - uint8 sneaky_weaky = 0; - - if(((rumble_param[0] & 0xC0) == 0x40) && ((rumble_param[1] & 0x01) == 0x01)) - sneaky_weaky = 0xFF; - - MDFN_en16lsb(rumb_dp, sneaky_weaky << 0); - } - - // - // Encode analog mode state. - // - d8[2] &= ~0x6; - d8[2] |= (analog_mode ? 0x02 : 0x00); - d8[2] |= (analog_mode_locked ? 0x04 : 0x00); -} - - -void InputDevice_DualShock::SetDTR(bool new_dtr) -{ - const bool old_dtr = dtr; - dtr = new_dtr; // Set it to new state before we call CheckManualAnaModeChange(). - - if(!old_dtr && dtr) - { - command_phase = 0; - bitpos = 0; - transmit_pos = 0; - transmit_count = 0; - } - else if(old_dtr && !dtr) - { - CheckManualAnaModeChange(); - //if(bitpos || transmit_count) - // printf("[PAD] Abort communication!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"); - } -} - -bool InputDevice_DualShock::GetDSR(void) -{ - if(!dtr) - return(0); - - if(!bitpos && transmit_count) - return(1); - - return(0); -} - -bool InputDevice_DualShock::Clock(bool TxD, int32 &dsr_pulse_delay) -{ - bool ret = 1; - - dsr_pulse_delay = 0; - - if(!dtr) - return(1); - - if(transmit_count) - ret = (transmit_buffer[transmit_pos] >> bitpos) & 1; - - receive_buffer &= ~(1 << bitpos); - receive_buffer |= TxD << bitpos; - bitpos = (bitpos + 1) & 0x7; - - if(!bitpos) - { - //if(command == 0x44) - //if(command == 0x4D) //mad_munchkins) // || command == 0x43) - // fprintf(stderr, "[PAD] Receive: %02x -- command=%02x, command_phase=%d, transmit_pos=%d\n", receive_buffer, command, command_phase, transmit_pos); - - if(transmit_count) - { - transmit_pos++; - transmit_count--; - } - - switch(command_phase) - { - case 0: - if(receive_buffer != 0x01) - command_phase = -1; - else - { - if(mad_munchkins) - { - transmit_buffer[0] = 0xF3; - transmit_pos = 0; - transmit_count = 1; - command_phase = 101; - } - else - { - transmit_buffer[0] = analog_mode ? 0x73 : 0x41; - transmit_pos = 0; - transmit_count = 1; - command_phase++; - } - } - break; - - case 1: - command = receive_buffer; - command_phase++; - - transmit_buffer[0] = 0x5A; - - //fprintf(stderr, "Gamepad command: 0x%02x\n", command); - //if(command != 0x42 && command != 0x43) - // fprintf(stderr, "Gamepad unhandled command: 0x%02x\n", command); - - if(command == 0x42) - { - transmit_buffer[0] = 0x5A; - transmit_pos = 0; - transmit_count = 1; - command_phase = (command << 8) | 0x00; - } - else if(command == 0x43) - { - transmit_pos = 0; - if(analog_mode) - { - transmit_buffer[1] = 0xFF ^ buttons[0]; - transmit_buffer[2] = 0xFF ^ buttons[1]; - transmit_buffer[3] = axes[0][0]; - transmit_buffer[4] = axes[0][1]; - transmit_buffer[5] = axes[1][0]; - transmit_buffer[6] = axes[1][1]; - transmit_count = 7; - io->active = 1; - } - else - { - transmit_buffer[1] = 0xFF ^ buttons[0]; - transmit_buffer[2] = 0xFF ^ buttons[1]; - transmit_count = 3; - io->active = 1; - } - } - else - { - command_phase = -1; - transmit_buffer[1] = 0; - transmit_buffer[2] = 0; - transmit_pos = 0; - transmit_count = 0; - } - break; - - case 2: - { - if(command == 0x43 && transmit_pos == 2 && (receive_buffer == 0x01)) - { - //fprintf(stderr, "Mad Munchkins mode entered!\n"); - mad_munchkins = true; - - if(da_rumble_compat) - { - rumble_param[0] = 0; - rumble_param[1] = 0; - da_rumble_compat = false; - } - command_phase = -1; - } - } - break; - - case 101: - command = receive_buffer; - - //fprintf(stderr, "Mad Munchkins DualShock command: 0x%02x\n", command); - - if(command >= 0x40 && command <= 0x4F) - { - transmit_buffer[0] = 0x5A; - transmit_pos = 0; - transmit_count = 1; - command_phase = (command << 8) | 0x00; - } - else - { - transmit_count = 0; - command_phase = -1; - } - break; - - /************************/ - /* MMMode 1, Command 0x40 */ - /************************/ - case 0x4000: - if(receive_buffer == 0x00) - { - transmit_buffer[0] = 0; /**/ transmit_pos = 0; transmit_count = 1; /**/ - command_phase++; - } - else - command_phase = -1; - break; - - case 0x4001: - transmit_buffer[0] = 0x00; - transmit_buffer[1] = 0x00; - transmit_buffer[2] = 0x00; - transmit_buffer[3] = 0x00; - transmit_buffer[4] = 0x00; - transmit_pos = 0; - transmit_count = 5; - command_phase = -1; - break; - - - /************************/ - /* MMMode 1, Command 0x41 */ - /************************/ - case 0x4100: - if(receive_buffer == 0x00) - { - transmit_buffer[0] = 0; /**/ transmit_pos = 0; transmit_count = 1; /**/ - command_phase++; - } - else - command_phase = -1; - break; - - case 0x4101: - transmit_buffer[0] = 0x00; - transmit_buffer[1] = 0x00; - transmit_buffer[2] = 0x00; - transmit_buffer[3] = 0x00; - transmit_buffer[4] = 0x00; - transmit_pos = 0; - transmit_count = 5; - command_phase = -1; - break; - - /**************************/ - /* MMMode 0&1, Command 0x42 */ - /**************************/ - case 0x4200: - transmit_pos = 0; - if(analog_mode || mad_munchkins) - { - transmit_buffer[0] = 0xFF ^ buttons[0]; - transmit_buffer[1] = 0xFF ^ buttons[1]; - transmit_buffer[2] = axes[0][0]; - transmit_buffer[3] = axes[0][1]; - transmit_buffer[4] = axes[1][0]; - transmit_buffer[5] = axes[1][1]; - transmit_count = 6; - io->active = 1; - } - else - { - transmit_buffer[0] = 0xFF ^ buttons[0]; - transmit_buffer[1] = 0xFF ^ buttons[1]; - transmit_count = 2; - io->active = 1; - - if(!(rumble_magic[2] & 0xFE)) - { - transmit_buffer[transmit_count++] = 0x00; - transmit_buffer[transmit_count++] = 0x00; - } - } - command_phase++; - break; - - case 0x4201: // Weak(in DS mode) - if(da_rumble_compat) - rumble_param[0] = receive_buffer; - // Dualshock weak - else if(rumble_magic[0] == 0x00 && rumble_magic[2] != 0x00 && rumble_magic[3] != 0x00 && rumble_magic[4] != 0x00 && rumble_magic[5] != 0x00) - rumble_param[0] = receive_buffer; - command_phase++; - break; - - case 0x4202: - if(da_rumble_compat) - rumble_param[1] = receive_buffer; - else if(rumble_magic[1] == 0x01) // DualShock strong - rumble_param[1] = receive_buffer; - else if(rumble_magic[1] == 0x00 && rumble_magic[2] != 0x00 && rumble_magic[3] != 0x00 && rumble_magic[4] != 0x00 && rumble_magic[5] != 0x00) // DualShock weak - rumble_param[0] = receive_buffer; - - command_phase++; - break; - - case 0x4203: - if(da_rumble_compat) - { - - } - else if(rumble_magic[1] == 0x00 && rumble_magic[2] == 0x01) - rumble_param[1] = receive_buffer; // DualShock strong. - command_phase++; // Nowhere here we come! - break; - - /************************/ - /* MMMode 1, Command 0x43 */ - /************************/ - case 0x4300: - if(receive_buffer == 0x00) - { - transmit_buffer[0] = 0; /**/ transmit_pos = 0; transmit_count = 1; /**/ - command_phase++; - } - else - command_phase = -1; - break; - - case 0x4301: - if(receive_buffer == 0x00) - { - //fprintf(stderr, "Mad Munchkins mode left!\n"); - mad_munchkins = false; - } - transmit_buffer[0] = 0x00; - transmit_buffer[1] = 0x00; - transmit_buffer[2] = 0x00; - transmit_buffer[3] = 0x00; - transmit_buffer[4] = 0x00; - transmit_pos = 0; - transmit_count = 5; - command_phase = -1; - break; - - /************************/ - /* MMMode 1, Command 0x44 */ - /************************/ - case 0x4400: - if(receive_buffer == 0x00) - { - transmit_buffer[0] = 0; /**/ transmit_pos = 0; transmit_count = 1; /**/ - command_phase++; - } - else - command_phase = -1; - break; - - case 0x4401: - transmit_buffer[0] = 0x00; - transmit_buffer[1] = 0x00; - transmit_buffer[2] = 0x00; - transmit_buffer[3] = 0x00; - transmit_buffer[4] = 0x00; - transmit_pos = 0; - transmit_count = 5; - command_phase++; - - // Ignores locking state. - switch(receive_buffer) - { - case 0x00: - analog_mode = false; - //fprintf(stderr, "Analog mode disabled\n"); - break; - - case 0x01: - analog_mode = true; - //fprintf(stderr, "Analog mode enabled\n"); - break; - } - break; - - case 0x4402: - switch(receive_buffer) - { - case 0x02: - analog_mode_locked = false; - break; - - case 0x03: - analog_mode_locked = true; - break; - } - command_phase = -1; - break; - - /************************/ - /* MMMode 1, Command 0x45 */ - /************************/ - case 0x4500: - if(receive_buffer == 0x00) - { - transmit_buffer[0] = 0x01; /**/ transmit_pos = 0; transmit_count = 1; /**/ - command_phase++; - } - else - command_phase = -1; - break; - - case 0x4501: - transmit_buffer[0] = 0x02; - transmit_buffer[1] = analog_mode ? 0x01 : 0x00; - transmit_buffer[2] = 0x02; - transmit_buffer[3] = 0x01; - transmit_buffer[4] = 0x00; - transmit_pos = 0; - transmit_count = 5; - command_phase = -1; - break; - - - /************************/ - /* MMMode 1, Command 0x46 */ - /************************/ - case 0x4600: - if(receive_buffer == 0x00) - { - transmit_buffer[0] = 0; /**/ transmit_pos = 0; transmit_count = 1; /**/ - command_phase++; - } - else - command_phase = -1; - break; - - case 0x4601: - if(receive_buffer == 0x00) - { - transmit_buffer[0] = 0x00; - transmit_buffer[1] = 0x01; - transmit_buffer[2] = 0x02; - transmit_buffer[3] = 0x00; - transmit_buffer[4] = 0x0A; - } - else if(receive_buffer == 0x01) - { - transmit_buffer[0] = 0x00; - transmit_buffer[1] = 0x01; - transmit_buffer[2] = 0x01; - transmit_buffer[3] = 0x01; - transmit_buffer[4] = 0x14; - } - else - { - transmit_buffer[0] = 0x00; - transmit_buffer[1] = 0x00; - transmit_buffer[2] = 0x00; - transmit_buffer[3] = 0x00; - transmit_buffer[4] = 0x00; - } - transmit_pos = 0; - transmit_count = 5; - command_phase = -1; - break; - - /************************/ - /* MMMode 1, Command 0x47 */ - /************************/ - case 0x4700: - if(receive_buffer == 0x00) - { - transmit_buffer[0] = 0; /**/ transmit_pos = 0; transmit_count = 1; /**/ - command_phase++; - } - else - command_phase = -1; - break; - - case 0x4701: - if(receive_buffer == 0x00) - { - transmit_buffer[0] = 0x00; - transmit_buffer[1] = 0x02; - transmit_buffer[2] = 0x00; - transmit_buffer[3] = 0x01; - transmit_buffer[4] = 0x00; - } - else - { - transmit_buffer[0] = 0x00; - transmit_buffer[1] = 0x00; - transmit_buffer[2] = 0x00; - transmit_buffer[3] = 0x00; - transmit_buffer[4] = 0x00; - } - transmit_pos = 0; - transmit_count = 5; - command_phase = -1; - break; - - /************************/ - /* MMMode 1, Command 0x48 */ - /************************/ - case 0x4800: - if(receive_buffer == 0x00) - { - transmit_buffer[0] = 0; /**/ transmit_pos = 0; transmit_count = 1; /**/ - command_phase++; - } - else - command_phase = -1; - break; - - case 0x4801: - if(receive_buffer == 0x00) - { - transmit_buffer[0] = 0x00; - transmit_buffer[1] = 0x00; - transmit_buffer[2] = 0x00; - transmit_buffer[3] = 0x01; - transmit_buffer[4] = rumble_param[0]; - } - else if(receive_buffer == 0x01) - { - transmit_buffer[0] = 0x00; - transmit_buffer[1] = 0x00; - transmit_buffer[2] = 0x00; - transmit_buffer[3] = 0x01; - transmit_buffer[4] = rumble_param[1]; - } - else - { - transmit_buffer[0] = 0x00; - transmit_buffer[1] = 0x00; - transmit_buffer[2] = 0x00; - transmit_buffer[3] = 0x00; - transmit_buffer[4] = 0x00; - } - transmit_pos = 0; - transmit_count = 5; - command_phase = -1; - break; - - /************************/ - /* MMMode 1, Command 0x49 */ - /************************/ - case 0x4900: - if(receive_buffer == 0x00) - { - transmit_buffer[0] = 0; /**/ transmit_pos = 0; transmit_count = 1; /**/ - command_phase++; - } - else - command_phase = -1; - break; - - case 0x4901: - transmit_buffer[0] = 0x00; - transmit_buffer[1] = 0x00; - transmit_buffer[2] = 0x00; - transmit_buffer[3] = 0x00; - transmit_buffer[4] = 0x00; - transmit_pos = 0; - transmit_count = 5; - command_phase = -1; - break; - - /************************/ - /* MMMode 1, Command 0x4A */ - /************************/ - case 0x4A00: - if(receive_buffer == 0x00) - { - transmit_buffer[0] = 0; /**/ transmit_pos = 0; transmit_count = 1; /**/ - command_phase++; - } - else - command_phase = -1; - break; - - case 0x4A01: - transmit_buffer[0] = 0x00; - transmit_buffer[1] = 0x00; - transmit_buffer[2] = 0x00; - transmit_buffer[3] = 0x00; - transmit_buffer[4] = 0x00; - transmit_pos = 0; - transmit_count = 5; - command_phase = -1; - break; - - /************************/ - /* MMMode 1, Command 0x4B */ - /************************/ - case 0x4B00: - if(receive_buffer == 0x00) - { - transmit_buffer[0] = 0; /**/ transmit_pos = 0; transmit_count = 1; /**/ - command_phase++; - } - else - command_phase = -1; - break; - - case 0x4B01: - transmit_buffer[0] = 0x00; - transmit_buffer[1] = 0x00; - transmit_buffer[2] = 0x00; - transmit_buffer[3] = 0x00; - transmit_buffer[4] = 0x00; - transmit_pos = 0; - transmit_count = 5; - command_phase = -1; - break; - - /************************/ - /* MMMode 1, Command 0x4C */ - /************************/ - case 0x4C00: - if(receive_buffer == 0x00) - { - transmit_buffer[0] = 0; /**/ transmit_pos = 0; transmit_count = 1; /**/ - command_phase++; - } - else - command_phase = -1; - break; - - case 0x4C01: - if(receive_buffer == 0x00) - { - transmit_buffer[0] = 0x00; - transmit_buffer[1] = 0x00; - transmit_buffer[2] = 0x04; - transmit_buffer[3] = 0x00; - transmit_buffer[4] = 0x00; - } - else if(receive_buffer == 0x01) - { - transmit_buffer[0] = 0x00; - transmit_buffer[1] = 0x00; - transmit_buffer[2] = 0x07; - transmit_buffer[3] = 0x00; - transmit_buffer[4] = 0x00; - } - else - { - transmit_buffer[0] = 0x00; - transmit_buffer[1] = 0x00; - transmit_buffer[2] = 0x00; - transmit_buffer[3] = 0x00; - transmit_buffer[4] = 0x00; - } - - transmit_pos = 0; - transmit_count = 5; - command_phase = -1; - break; - - /************************/ - /* MMMode 1, Command 0x4D */ - /************************/ - case 0x4D00: - if(receive_buffer == 0x00) - { - transmit_buffer[0] = rumble_magic[0]; /**/ transmit_pos = 0; transmit_count = 1; /**/ - command_phase++; - } - else - command_phase = -1; - break; - - case 0x4D01: - case 0x4D02: - case 0x4D03: - case 0x4D04: - case 0x4D05: - case 0x4D06: - { - unsigned index = command_phase - 0x4D01; - - if(index < 5) - { - transmit_buffer[0] = rumble_magic[1 + index]; - transmit_pos = 0; - transmit_count = 1; - command_phase++; - } - else - command_phase = -1; - - rumble_magic[index] = receive_buffer; - } - break; - - /************************/ - /* MMMode 1, Command 0x4E */ - /************************/ - case 0x4E00: - if(receive_buffer == 0x00) - { - transmit_buffer[0] = 0; /**/ transmit_pos = 0; transmit_count = 1; /**/ - command_phase++; - } - else - command_phase = -1; - break; - - case 0x4E01: - transmit_buffer[0] = 0x00; - transmit_buffer[1] = 0x00; - transmit_buffer[2] = 0x00; - transmit_buffer[3] = 0x00; - transmit_buffer[4] = 0x00; - transmit_pos = 0; - transmit_count = 5; - command_phase = -1; - break; - - - /************************/ - /* MMMode 1, Command 0x4F */ - /************************/ - case 0x4F00: - if(receive_buffer == 0x00) - { - transmit_buffer[0] = 0; /**/ transmit_pos = 0; transmit_count = 1; /**/ - command_phase++; - } - else - command_phase = -1; - break; - - case 0x4F01: - transmit_buffer[0] = 0x00; - transmit_buffer[1] = 0x00; - transmit_buffer[2] = 0x00; - transmit_buffer[3] = 0x00; - transmit_buffer[4] = 0x00; - transmit_pos = 0; - transmit_count = 5; - command_phase = -1; - break; - } - } - - if(!bitpos && transmit_count) - dsr_pulse_delay = 0x40; //0x100; - - return(ret); -} - -InputDevice *Device_DualShock_Create() -{ - return new InputDevice_DualShock(); -} - -} diff --git a/psx/octoshock/psx/input/dualshock.h b/psx/octoshock/psx/input/dualshock.h deleted file mode 100644 index c8f3010760f..00000000000 --- a/psx/octoshock/psx/input/dualshock.h +++ /dev/null @@ -1,46 +0,0 @@ -/******************************************************************************/ -/* Mednafen Sony PS1 Emulation Module */ -/******************************************************************************/ -/* dualshock.h: -** Copyright (C) 2012-2016 Mednafen Team -** -** 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., -** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef __MDFN_PSX_INPUT_DUALSHOCK_H -#define __MDFN_PSX_INPUT_DUALSHOCK_H - -#include "octoshock.h" - -namespace MDFN_IEN_PSX -{ - InputDevice *Device_DualShock_Create(); - - EW_PACKED( - struct IO_Dualshock - { - u8 buttons[3]; - u8 right_x, right_y; - u8 left_x, left_y; - u8 active; - u8 pad[8]; - u8 pad2[3]; - u16 rumble; - u8 pad3[11]; - }); -} - - -#endif diff --git a/psx/octoshock/psx/input/gamepad.cpp b/psx/octoshock/psx/input/gamepad.cpp deleted file mode 100644 index e388adc5b5d..00000000000 --- a/psx/octoshock/psx/input/gamepad.cpp +++ /dev/null @@ -1,238 +0,0 @@ -/******************************************************************************/ -/* Mednafen Sony PS1 Emulation Module */ -/******************************************************************************/ -/* gamepad.cpp: -** Copyright (C) 2011-2016 Mednafen Team -** -** 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., -** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "../psx.h" -#include "../frontio.h" -#include "gamepad.h" - -namespace MDFN_IEN_PSX -{ - -class InputDevice_Gamepad : public InputDevice -{ - public: - - InputDevice_Gamepad(); - virtual ~InputDevice_Gamepad(); - - virtual void Power(void); - virtual void UpdateInput(const void *data); - virtual void SyncState(bool isReader, EW::NewState *ns); - - // - // - // - virtual void SetDTR(bool new_dtr); - virtual bool GetDSR(void); - virtual bool Clock(bool TxD, int32 &dsr_pulse_delay); - - private: - -//non-serialized state - IO_Gamepad* io; - - bool dtr; - - uint8 buttons[2]; - - int32 command_phase; - uint32 bitpos; - uint8 receive_buffer; - - uint8 command; - - uint8 transmit_buffer[3]; - uint32 transmit_pos; - uint32 transmit_count; -}; - -InputDevice_Gamepad::InputDevice_Gamepad() -{ - Power(); -} - -InputDevice_Gamepad::~InputDevice_Gamepad() -{ - -} - -void InputDevice_Gamepad::Power(void) -{ - dtr = 0; - - buttons[0] = buttons[1] = 0; - - command_phase = 0; - - bitpos = 0; - - receive_buffer = 0; - - command = 0; - - memset(transmit_buffer, 0, sizeof(transmit_buffer)); - - transmit_pos = 0; - transmit_count = 0; -} - -void InputDevice_Gamepad::SyncState(bool isReader, EW::NewState *ns) -{ - NSS(dtr); - - NSS(buttons); - - NSS(command_phase); - NSS(bitpos); - NSS(receive_buffer); - - NSS(command); - - NSS(transmit_buffer); - NSS(transmit_pos); - NSS(transmit_count); -} - -void InputDevice_Gamepad::UpdateInput(const void *data) -{ - io = (IO_Gamepad*)data; - - buttons[0] = io->buttons[0]; - buttons[1] = io->buttons[1]; -} - - -void InputDevice_Gamepad::SetDTR(bool new_dtr) -{ - if(!dtr && new_dtr) - { - command_phase = 0; - bitpos = 0; - transmit_pos = 0; - transmit_count = 0; - } - else if(dtr && !new_dtr) - { - //if(bitpos || transmit_count) - // printf("[PAD] Abort communication!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"); - } - - dtr = new_dtr; -} - -bool InputDevice_Gamepad::GetDSR(void) -{ - if(!dtr) - return(0); - - if(!bitpos && transmit_count) - return(1); - - return(0); -} - -bool InputDevice_Gamepad::Clock(bool TxD, int32 &dsr_pulse_delay) -{ - bool ret = 1; - - dsr_pulse_delay = 0; - - if(!dtr) - return(1); - - if(transmit_count) - ret = (transmit_buffer[transmit_pos] >> bitpos) & 1; - - receive_buffer &= ~(1 << bitpos); - receive_buffer |= TxD << bitpos; - bitpos = (bitpos + 1) & 0x7; - - if(!bitpos) - { - //printf("[PAD] Receive: %02x -- command_phase=%d\n", receive_buffer, command_phase); - - if(transmit_count) - { - transmit_pos++; - transmit_count--; - } - - - switch(command_phase) - { - case 0: - if(receive_buffer != 0x01) - command_phase = -1; - else - { - transmit_buffer[0] = 0x41; - transmit_pos = 0; - transmit_count = 1; - command_phase++; - } - break; - - case 1: - command = receive_buffer; - command_phase++; - - transmit_buffer[0] = 0x5A; - - //if(command != 0x42) - // fprintf(stderr, "Gamepad unhandled command: 0x%02x\n", command); - //assert(command == 0x42); - if(command == 0x42) - { - //printf("PAD COmmand 0x42, sl=%u\n", GPU->GetScanlineNum()); - - transmit_buffer[1] = 0xFF ^ buttons[0]; - transmit_buffer[2] = 0xFF ^ buttons[1]; - transmit_pos = 0; - transmit_count = 3; - io->active = true; - } - else - { - command_phase = -1; - transmit_buffer[1] = 0; - transmit_buffer[2] = 0; - transmit_pos = 0; - transmit_count = 0; - } - break; - - } - } - - if(!bitpos && transmit_count) - dsr_pulse_delay = 0x40; //0x100; - - return(ret); -} - -InputDevice *Device_Gamepad_Create(void) -{ - return new InputDevice_Gamepad(); -} - - - -} diff --git a/psx/octoshock/psx/input/gamepad.h b/psx/octoshock/psx/input/gamepad.h deleted file mode 100644 index 7c1059f5015..00000000000 --- a/psx/octoshock/psx/input/gamepad.h +++ /dev/null @@ -1,38 +0,0 @@ -/******************************************************************************/ -/* Mednafen Sony PS1 Emulation Module */ -/******************************************************************************/ -/* gamepad.h: -** Copyright (C) 2011-2016 Mednafen Team -** -** 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., -** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef __MDFN_PSX_INPUT_GAMEPAD_H -#define __MDFN_PSX_INPUT_GAMEPAD_H - -namespace MDFN_IEN_PSX -{ - -InputDevice *Device_Gamepad_Create(void); - - EW_PACKED( - struct IO_Gamepad - { - u8 buttons[2]; - u8 active; - }); - -} -#endif diff --git a/psx/octoshock/psx/input/guncon.cpp b/psx/octoshock/psx/input/guncon.cpp deleted file mode 100644 index 2386ea4b75e..00000000000 --- a/psx/octoshock/psx/input/guncon.cpp +++ /dev/null @@ -1,372 +0,0 @@ -/******************************************************************************/ -/* Mednafen Sony PS1 Emulation Module */ -/******************************************************************************/ -/* guncon.cpp: -** Copyright (C) 2012-2016 Mednafen Team -** -** 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., -** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "../psx.h" -#include "../frontio.h" -#include "guncon.h" - -namespace MDFN_IEN_PSX -{ - -class InputDevice_GunCon final : public InputDevice -{ - public: - - InputDevice_GunCon(void); - virtual ~InputDevice_GunCon(); - - virtual void Power(void) override; - virtual void UpdateInput(const void *data) override; - virtual bool RequireNoFrameskip(void) override; - virtual pscpu_timestamp_t GPULineHook(const pscpu_timestamp_t line_timestamp, bool vsync, uint32 *pixels, const MDFN_PixelFormat* const format, const unsigned width, const unsigned pix_clock_offset, const unsigned pix_clock, const unsigned pix_clock_divider) override; - - // - // - // - virtual void SetDTR(bool new_dtr) override; - virtual bool GetDSR(void) override; - virtual bool Clock(bool TxD, int32 &dsr_pulse_delay) override; - - private: - - bool dtr; - - uint8 buttons; - bool trigger_eff; - bool trigger_noclear; - uint16 hit_x, hit_y; - - int16 nom_x, nom_y; - int32 os_shot_counter; - bool prev_oss; - - int32 command_phase; - uint32 bitpos; - uint8 receive_buffer; - - uint8 command; - - uint8 transmit_buffer[16]; - uint32 transmit_pos; - uint32 transmit_count; - - // - // Video timing stuff - bool prev_vsync; - int line_counter; -}; - -InputDevice_GunCon::InputDevice_GunCon(void) -{ - Power(); -} - -InputDevice_GunCon::~InputDevice_GunCon() -{ - -} - -void InputDevice_GunCon::Power(void) -{ - dtr = 0; - - buttons = 0; - trigger_eff = 0; - trigger_noclear = 0; - hit_x = 0; - hit_y = 0; - - nom_x = 0; - nom_y = 0; - - os_shot_counter = 0; - prev_oss = 0; - - command_phase = 0; - - bitpos = 0; - - receive_buffer = 0; - - command = 0; - - memset(transmit_buffer, 0, sizeof(transmit_buffer)); - - transmit_pos = 0; - transmit_count = 0; - - prev_vsync = 0; - line_counter = 0; -} - -//void InputDevice_GunCon::StateAction(StateMem* sm, const unsigned load, const bool data_only, const char* sname_prefix) -//{ -// SFORMAT StateRegs[] = -// { -// SFVAR(dtr), -// -// SFVAR(buttons), -// SFVAR(trigger_eff), -// SFVAR(trigger_noclear), -// SFVAR(hit_x), -// SFVAR(hit_y), -// -// SFVAR(nom_x), -// SFVAR(nom_y), -// SFVAR(os_shot_counter), -// SFVAR(prev_oss), -// -// SFVAR(command_phase), -// SFVAR(bitpos), -// SFVAR(receive_buffer), -// -// SFVAR(command), -// -// SFARRAY(transmit_buffer, sizeof(transmit_buffer)), -// SFVAR(transmit_pos), -// SFVAR(transmit_count), -// -// SFVAR(prev_vsync), -// SFVAR(line_counter), -// -// SFEND -// }; -// char section_name[32]; -// trio_snprintf(section_name, sizeof(section_name), "%s_GunCon", sname_prefix); -// -// if(!MDFNSS_StateAction(sm, load, data_only, StateRegs, section_name, true) && load) -// Power(); -// else if(load) -// { -// if((transmit_pos + transmit_count) > sizeof(transmit_buffer)) -// { -// transmit_pos = 0; -// transmit_count = 0; -// } -// } -//} - - -void InputDevice_GunCon::UpdateInput(const void *data) -{ - uint8 *d8 = (uint8 *)data; - - nom_x = (int16)MDFN_de16lsb(&d8[0]); - nom_y = (int16)MDFN_de16lsb(&d8[2]); - - trigger_noclear = (bool)(d8[4] & 0x1); - trigger_eff |= trigger_noclear; - - buttons = d8[4] >> 1; - - if(os_shot_counter > 0) // FIXME if UpdateInput() is ever called more than once per video frame(at ~50 or ~60Hz). - os_shot_counter--; - - if((d8[4] & 0x8) && !prev_oss && os_shot_counter == 0) - os_shot_counter = 4; - prev_oss = d8[4] & 0x8; - - //MDFN_DispMessage("%08x %08x", nom_x, nom_y); -} - -bool InputDevice_GunCon::RequireNoFrameskip(void) -{ - return(true); -} - -pscpu_timestamp_t InputDevice_GunCon::GPULineHook(const pscpu_timestamp_t line_timestamp, bool vsync, uint32 *pixels, const MDFN_PixelFormat* const format, const unsigned width, - const unsigned pix_clock_offset, const unsigned pix_clock, const unsigned pix_clock_divider) -{ - if(vsync && !prev_vsync) - line_counter = 0; - - if(pixels && pix_clock) - { - int32 gx; - int32 gy; - - gx = (nom_x * 2 + pix_clock_divider) / (pix_clock_divider * 2); - gy = nom_y; - - for(int32 ix = gx; ix < (gx + (int32)(pix_clock / 762925)); ix++) - { - if(ix >= 0 && ix < (int)width && line_counter >= gy && line_counter < (gy + 8)) - { - int r, g, b, a; - - format->DecodeColor(pixels[ix], r, g, b, a); - - if((r + g + b) >= 0x40) // Wrong, but not COMPLETELY ABSOLUTELY wrong, at least. ;) - { - hit_x = (int64)(ix + pix_clock_offset) * 8000000 / pix_clock; // GunCon has what appears to be an 8.00MHz ceramic resonator in it. - hit_y = line_counter; - } - } - } - - chair_x = gx; - chair_y = gy - line_counter; - } - - line_counter++; - - return(PSX_EVENT_MAXTS); -} - -void InputDevice_GunCon::SetDTR(bool new_dtr) -{ - if(!dtr && new_dtr) - { - command_phase = 0; - bitpos = 0; - transmit_pos = 0; - transmit_count = 0; - } - else if(dtr && !new_dtr) - { - //if(bitpos || transmit_count) - // printf("[PAD] Abort communication!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"); - } - - dtr = new_dtr; -} - -bool InputDevice_GunCon::GetDSR(void) -{ - if(!dtr) - return(0); - - if(!bitpos && transmit_count) - return(1); - - return(0); -} - -bool InputDevice_GunCon::Clock(bool TxD, int32 &dsr_pulse_delay) -{ - bool ret = 1; - - dsr_pulse_delay = 0; - - if(!dtr) - return(1); - - if(transmit_count) - ret = (transmit_buffer[transmit_pos] >> bitpos) & 1; - - receive_buffer &= ~(1 << bitpos); - receive_buffer |= TxD << bitpos; - bitpos = (bitpos + 1) & 0x7; - - if(!bitpos) - { - //printf("[PAD] Receive: %02x -- command_phase=%d\n", receive_buffer, command_phase); - - if(transmit_count) - { - transmit_pos++; - transmit_count--; - } - - - switch(command_phase) - { - case 0: - if(receive_buffer != 0x01) - command_phase = -1; - else - { - transmit_buffer[0] = 0x63; - transmit_pos = 0; - transmit_count = 1; - command_phase++; - } - break; - - case 2: - //if(receive_buffer) - // printf("%02x\n", receive_buffer); - break; - - case 1: - command = receive_buffer; - command_phase++; - - transmit_buffer[0] = 0x5A; - - //puts("MOO"); - //if(command != 0x42) - // fprintf(stderr, "GunCon unhandled command: 0x%02x\n", command); - //assert(command == 0x42); - if(command == 0x42) - { - transmit_buffer[1] = 0xFF ^ ((buttons & 0x01) << 3); - transmit_buffer[2] = 0xFF ^ (trigger_eff << 5) ^ ((buttons & 0x02) << 5); - - if(os_shot_counter > 0) - { - hit_x = 0x01; - hit_y = 0x0A; - transmit_buffer[2] |= (1 << 5); - if(os_shot_counter == 2 || os_shot_counter == 3) - { - transmit_buffer[2] &= ~(1 << 5); - } - } - - MDFN_en16lsb(&transmit_buffer[3], hit_x); - MDFN_en16lsb(&transmit_buffer[5], hit_y); - - hit_x = 0x01; - hit_y = 0x0A; - - transmit_pos = 0; - transmit_count = 7; - - trigger_eff = trigger_noclear; - } - else - { - command_phase = -1; - transmit_buffer[1] = 0; - transmit_buffer[2] = 0; - transmit_pos = 0; - transmit_count = 0; - } - break; - - } - } - - if(!bitpos && transmit_count) - dsr_pulse_delay = 100; //0x80; //0x40; - - return(ret); -} - -InputDevice *Device_GunCon_Create(void) -{ - return new InputDevice_GunCon(); -} - - - -} diff --git a/psx/octoshock/psx/input/guncon.h b/psx/octoshock/psx/input/guncon.h deleted file mode 100644 index 0f04814fee1..00000000000 --- a/psx/octoshock/psx/input/guncon.h +++ /dev/null @@ -1,31 +0,0 @@ -/******************************************************************************/ -/* Mednafen Sony PS1 Emulation Module */ -/******************************************************************************/ -/* guncon.h: -** Copyright (C) 2012-2016 Mednafen Team -** -** 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., -** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef __MDFN_PSX_INPUT_GUNCON_H -#define __MDFN_PSX_INPUT_GUNCON_H - -namespace MDFN_IEN_PSX -{ - -InputDevice *Device_GunCon_Create(void); - -} -#endif diff --git a/psx/octoshock/psx/input/justifier.cpp b/psx/octoshock/psx/input/justifier.cpp deleted file mode 100644 index b3894a81a85..00000000000 --- a/psx/octoshock/psx/input/justifier.cpp +++ /dev/null @@ -1,378 +0,0 @@ -/******************************************************************************/ -/* Mednafen Sony PS1 Emulation Module */ -/******************************************************************************/ -/* justifier.cpp: -** Copyright (C) 2012-2016 Mednafen Team -** -** 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., -** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "../psx.h" -#include "../frontio.h" -#include "justifier.h" - -namespace MDFN_IEN_PSX -{ - -class InputDevice_Justifier final : public InputDevice -{ - public: - - InputDevice_Justifier(void); - virtual ~InputDevice_Justifier(); - - virtual void Power(void) override; - virtual void UpdateInput(const void *data) override; - virtual bool RequireNoFrameskip(void) override; - virtual pscpu_timestamp_t GPULineHook(const pscpu_timestamp_t timestamp, bool vsync, uint32 *pixels, const MDFN_PixelFormat* const format, const unsigned width, const unsigned pix_clock_offset, const unsigned pix_clock, const unsigned pix_clock_divider) override; - - // - // - // - virtual void SetDTR(bool new_dtr) override; - virtual bool GetDSR(void) override; - virtual bool Clock(bool TxD, int32 &dsr_pulse_delay) override; - - private: - - bool dtr; - - uint8 buttons; - bool trigger_eff; - bool trigger_noclear; - - bool need_hit_detect; - - int16 nom_x, nom_y; - int32 os_shot_counter; - bool prev_oss; - - int32 command_phase; - uint32 bitpos; - uint8 receive_buffer; - - uint8 command; - - uint8 transmit_buffer[16]; - uint32 transmit_pos; - uint32 transmit_count; - - // - // Video timing stuff - bool prev_vsync; - int line_counter; -}; - -InputDevice_Justifier::InputDevice_Justifier(void) -{ - Power(); -} - -InputDevice_Justifier::~InputDevice_Justifier() -{ - -} - -void InputDevice_Justifier::Power(void) -{ - dtr = 0; - - buttons = 0; - trigger_eff = 0; - trigger_noclear = 0; - - need_hit_detect = false; - - nom_x = 0; - nom_y = 0; - - os_shot_counter = 0; - prev_oss = 0; - - command_phase = 0; - - bitpos = 0; - - receive_buffer = 0; - - command = 0; - - memset(transmit_buffer, 0, sizeof(transmit_buffer)); - - transmit_pos = 0; - transmit_count = 0; - - prev_vsync = 0; - line_counter = 0; -} - -void InputDevice_Justifier::UpdateInput(const void *data) -{ - uint8 *d8 = (uint8 *)data; - - nom_x = (int16)MDFN_de16lsb(&d8[0]); - nom_y = (int16)MDFN_de16lsb(&d8[2]); - - trigger_noclear = (bool)(d8[4] & 0x1); - trigger_eff |= trigger_noclear; - - buttons = (d8[4] >> 1) & 0x3; - - if(os_shot_counter > 0) // FIXME if UpdateInput() is ever called more than once per video frame(at ~50 or ~60Hz). - os_shot_counter--; - - if((d8[4] & 0x8) && !prev_oss && os_shot_counter == 0) - os_shot_counter = 10; - prev_oss = d8[4] & 0x8; -} - -//void InputDevice_Justifier::StateAction(StateMem* sm, const unsigned load, const bool data_only, const char* sname_prefix) -//{ -// SFORMAT StateRegs[] = -// { -// SFVAR(dtr), -// -// SFVAR(buttons), -// SFVAR(trigger_eff), -// SFVAR(trigger_noclear), -// -// SFVAR(need_hit_detect), -// -// SFVAR(nom_x), -// SFVAR(nom_y), -// SFVAR(os_shot_counter), -// SFVAR(prev_oss), -// -// SFVAR(command_phase), -// SFVAR(bitpos), -// SFVAR(receive_buffer), -// -// SFVAR(command), -// -// SFARRAY(transmit_buffer, sizeof(transmit_buffer)), -// SFVAR(transmit_pos), -// SFVAR(transmit_count), -// -// SFVAR(prev_vsync), -// SFVAR(line_counter), -// -// SFEND -// }; -// char section_name[32]; -// trio_snprintf(section_name, sizeof(section_name), "%s_Justifier", sname_prefix); -// -// if(!MDFNSS_StateAction(sm, load, data_only, StateRegs, section_name, true) && load) -// Power(); -// else if(load) -// { -// if((transmit_pos + transmit_count) > sizeof(transmit_buffer)) -// { -// transmit_pos = 0; -// transmit_count = 0; -// } -// } -//} - - -bool InputDevice_Justifier::RequireNoFrameskip(void) -{ - return(true); -} - -pscpu_timestamp_t InputDevice_Justifier::GPULineHook(const pscpu_timestamp_t timestamp, bool vsync, uint32 *pixels, const MDFN_PixelFormat* const format, const unsigned width, - const unsigned pix_clock_offset, const unsigned pix_clock, const unsigned pix_clock_divider) -{ - pscpu_timestamp_t ret = PSX_EVENT_MAXTS; - - if(vsync && !prev_vsync) - line_counter = 0; - - if(pixels && pix_clock) - { - int32 gx; - int32 gy; - int32 gxa; - - gx = (nom_x * 2 + pix_clock_divider) / (pix_clock_divider * 2); - gy = nom_y; - gxa = gx; // - (pix_clock / 400000); - //if(gxa < 0 && gx >= 0) - // gxa = 0; - - if(!os_shot_counter && need_hit_detect) - { - for(int32 ix = gxa; ix < (gxa + (int32)(pix_clock / 762925)); ix++) - { - if(ix >= 0 && ix < (int)width && line_counter >= (gy - 6) && line_counter <= (gy + 6)) - { - int r, g, b, a; - - format->DecodeColor(pixels[ix], r, g, b, a); - - if((r + g + b) >= 0x40) // Wrong, but not COMPLETELY ABSOLUTELY wrong, at least. ;) - { - ret = timestamp + (int64)(ix + pix_clock_offset) * (44100 * 768) / pix_clock - 177; - break; - } - } - } - } - - chair_x = gx; - chair_y = gy - line_counter; - } - - line_counter++; - - return(ret); -} - -void InputDevice_Justifier::SetDTR(bool new_dtr) -{ - if(!dtr && new_dtr) - { - command_phase = 0; - bitpos = 0; - transmit_pos = 0; - transmit_count = 0; - } - else if(dtr && !new_dtr) - { - //if(bitpos || transmit_count) - // printf("[PAD] Abort communication!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"); - } - - dtr = new_dtr; -} - -bool InputDevice_Justifier::GetDSR(void) -{ - if(!dtr) - return(0); - - if(!bitpos && transmit_count) - return(1); - - return(0); -} - -bool InputDevice_Justifier::Clock(bool TxD, int32 &dsr_pulse_delay) -{ - bool ret = 1; - - dsr_pulse_delay = 0; - - if(!dtr) - return(1); - - if(transmit_count) - ret = (transmit_buffer[transmit_pos] >> bitpos) & 1; - - receive_buffer &= ~(1 << bitpos); - receive_buffer |= TxD << bitpos; - bitpos = (bitpos + 1) & 0x7; - - if(!bitpos) - { - //printf("[PAD] Receive: %02x -- command_phase=%d\n", receive_buffer, command_phase); - - if(transmit_count) - { - transmit_pos++; - transmit_count--; - } - - - switch(command_phase) - { - case 0: - if(receive_buffer != 0x01) - command_phase = -1; - else - { - transmit_buffer[0] = 0x31; - transmit_pos = 0; - transmit_count = 1; - command_phase++; - } - break; - - case 2: - //if(receive_buffer) - // printf("%02x\n", receive_buffer); - command_phase++; - break; - - case 3: - need_hit_detect = receive_buffer & 0x10; // TODO, see if it's (val&0x10) == 0x10, or some other mask value. - command_phase++; - break; - - case 1: - command = receive_buffer; - command_phase++; - - transmit_buffer[0] = 0x5A; - - //if(command != 0x42) - // fprintf(stderr, "Justifier unhandled command: 0x%02x\n", command); - //assert(command == 0x42); - if(command == 0x42) - { - transmit_buffer[1] = 0xFF ^ ((buttons & 2) << 2); - transmit_buffer[2] = 0xFF ^ (trigger_eff << 7) ^ ((buttons & 1) << 6); - - if(os_shot_counter > 0) - { - transmit_buffer[2] |= (1 << 7); - if(os_shot_counter == 6 || os_shot_counter == 5) - { - transmit_buffer[2] &= ~(1 << 7); - } - } - - transmit_pos = 0; - transmit_count = 3; - - trigger_eff = trigger_noclear; - } - else - { - command_phase = -1; - transmit_buffer[1] = 0; - transmit_buffer[2] = 0; - transmit_pos = 0; - transmit_count = 0; - } - break; - - } - } - - if(!bitpos && transmit_count) - dsr_pulse_delay = 200; - - return(ret); -} - -InputDevice *Device_Justifier_Create(void) -{ - return new InputDevice_Justifier(); -} - - - - -} diff --git a/psx/octoshock/psx/input/justifier.h b/psx/octoshock/psx/input/justifier.h deleted file mode 100644 index acd7d944698..00000000000 --- a/psx/octoshock/psx/input/justifier.h +++ /dev/null @@ -1,31 +0,0 @@ -/******************************************************************************/ -/* Mednafen Sony PS1 Emulation Module */ -/******************************************************************************/ -/* justifier.h: -** Copyright (C) 2012-2016 Mednafen Team -** -** 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., -** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef __MDFN_PSX_INPUT_JUSTIFIER_H -#define __MDFN_PSX_INPUT_JUSTIFIER_H - -namespace MDFN_IEN_PSX -{ - -InputDevice *Device_Justifier_Create(void); - -} -#endif diff --git a/psx/octoshock/psx/input/memcard.cpp b/psx/octoshock/psx/input/memcard.cpp deleted file mode 100644 index 67edc048a18..00000000000 --- a/psx/octoshock/psx/input/memcard.cpp +++ /dev/null @@ -1,578 +0,0 @@ -/******************************************************************************/ -/* Mednafen Sony PS1 Emulation Module */ -/******************************************************************************/ -/* memcard.cpp: -** Copyright (C) 2012-2016 Mednafen Team -** -** 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., -** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -// I could find no other commands than 'R', 'W', and 'S' (not sure what 'S' is for, however) - -#include -#include "../psx.h" -#include "../frontio.h" -#include "memcard.h" - -#define BIGCASE2(X) case X+0: case X+1: -#define BIGCASE4(X) BIGCASE2(X+0) BIGCASE2(X+2) -#define BIGCASE8(X) BIGCASE4(X+0) BIGCASE4(X+4) -#define BIGCASE16(X) BIGCASE8(X+0) BIGCASE8(X+8) -#define BIGCASE32(X) BIGCASE16(X+0) BIGCASE16(X+16) -#define BIGCASE64(X) BIGCASE32(X+0) BIGCASE32(X+32) -#define BIGCASE128(X) BIGCASE64(X+0) BIGCASE64(X+64) - -namespace MDFN_IEN_PSX -{ - -class InputDevice_Memcard : public InputDevice -{ - public: - - InputDevice_Memcard(); - virtual ~InputDevice_Memcard(); - - virtual const char* GetName() const { return "InputDevice_Memcard"; } - - virtual void Power(void); - virtual void SyncState(bool isReader, EW::NewState *ns); - // - // - // - virtual void SetDTR(bool new_dtr); - virtual bool GetDSR(void); - virtual bool Clock(bool TxD, int32 &dsr_pulse_delay); - - // - // - virtual uint32 GetNVSize(void); - virtual const uint8* ReadNV(void) const override; - virtual void WriteNV(const uint8 *buffer, uint32 offset, uint32 size); - - virtual uint64 GetNVDirtyCount(void) const; - virtual void ResetNVDirtyCount(void); - - private: - - void Format(void); - - bool presence_new; - - uint8 card_data[1 << 17]; - uint8 rw_buffer[128]; - uint8 write_xor; - - // - // Used to avoid saving unused memory cards' card data in save states. - // Set to false on object initialization, set to true when data is written to card_data that differs - // from existing data(either from loading a memory card saved to disk, or from a game writing to the memory card). - // - // Save and load its state to/from save states. - // - bool data_used; - - // - // Do not save dirty_count in save states! - // - uint64 dirty_count; - - bool dtr; - int32 command_phase; - uint32 bitpos; - uint8 receive_buffer; - - uint8 command; - uint16 addr; - uint8 calced_xor; - - uint8 transmit_buffer; - uint32 transmit_count; -}; - -void InputDevice_Memcard::Format(void) -{ - memset(card_data, 0x00, sizeof(card_data)); - - card_data[0x00] = 0x4D; - card_data[0x01] = 0x43; - card_data[0x7F] = 0x0E; - - for(unsigned int A = 0x80; A < 0x800; A += 0x80) - { - card_data[A + 0x00] = 0xA0; - card_data[A + 0x08] = 0xFF; - card_data[A + 0x09] = 0xFF; - card_data[A + 0x7F] = 0xA0; - } - - for(unsigned int A = 0x0800; A < 0x1200; A += 0x80) - { - card_data[A + 0x00] = 0xFF; - card_data[A + 0x01] = 0xFF; - card_data[A + 0x02] = 0xFF; - card_data[A + 0x03] = 0xFF; - card_data[A + 0x08] = 0xFF; - card_data[A + 0x09] = 0xFF; - } -} - -InputDevice_Memcard::InputDevice_Memcard() -{ - Power(); - - data_used = false; - dirty_count = 0; - - // Init memcard as formatted. - assert(sizeof(card_data) == (1 << 17)); - Format(); -} - -InputDevice_Memcard::~InputDevice_Memcard() -{ - -} - -void InputDevice_Memcard::Power(void) -{ - presence_new = true; - memset(rw_buffer, 0, sizeof(rw_buffer)); - write_xor = 0; - - dtr = 0; - command_phase = 0; - bitpos = 0; - receive_buffer = 0; - - command = 0; - addr = 0; - calced_xor = 0; - - transmit_buffer = 0; - transmit_count = 0; -} - -void InputDevice_Memcard::SyncState(bool isReader, EW::NewState *ns) -{ - NSS(presence_new); - - NSS(rw_buffer); - NSS(write_xor); - - NSS(dtr); - NSS(command_phase); - NSS(bitpos); - NSS(receive_buffer); - - NSS(command); - NSS(addr); - NSS(calced_xor); - - NSS(transmit_buffer); - NSS(transmit_count); - - NSS(data_used); - - //(now there was logic to avoid savestating cards that had never been used. only needed if we have a pool of cards) - //(also it called Format() but I dont see how that makes sense at all and anyway I'm ignoring it) - - //now for the BIG QUESTION, regarding clobber's lament. - //we need to dump the contents of the card along with the register state. its necessary for safety. - //HOWEVER - we clear the dirty flag. that way, a user wont accidentally `clobber` his savestates when loading a state. - //instead, the state will only be dirtied when the game actually modifies the contents - NSS(card_data); - - if(isReader) - dirty_count = 0; -} -// -//int InputDevice_Memcard::StateAction(StateMem* sm, int load, int data_only, const char* section_name) -//{ -// // Don't save dirty_count. -// SFORMAT StateRegs[] = -// { -// SFVAR(presence_new), -// -// SFARRAY(rw_buffer, sizeof(rw_buffer)), -// SFVAR(write_xor), -// -// SFVAR(dtr), -// SFVAR(command_phase), -// SFVAR(bitpos), -// SFVAR(receive_buffer), -// -// SFVAR(command), -// SFVAR(addr), -// SFVAR(calced_xor), -// -// SFVAR(transmit_buffer), -// SFVAR(transmit_count), -// -// SFVAR(data_used), -// -// SFEND -// }; -// -// SFORMAT CD_StateRegs[] = -// { -// SFARRAY(card_data, sizeof(card_data)), -// SFEND -// }; -// int ret = 1; -// -// if(MDFNSS_StateAction(sm, load, data_only, StateRegs, section_name) != 0) -// { -// //printf("%s data_used=%d\n", section_name, data_used); -// if(data_used) -// { -// std::string tmp_name = std::string(section_name) + "_DT"; -// -// ret &= MDFNSS_StateAction(sm, load, data_only, CD_StateRegs, tmp_name.c_str()); -// } -// -// if(load) -// { -// if(data_used) -// dirty_count++; -// else -// { -// //printf("Format: %s\n", section_name); -// Format(); -// } -// } -// } -// else -// ret = 0; -// -// return(ret); -//} - - -void InputDevice_Memcard::SetDTR(bool new_dtr) -{ - if(!dtr && new_dtr) - { - command_phase = 0; - bitpos = 0; - transmit_count = 0; - } - else if(dtr && !new_dtr) - { - if(command_phase > 0) - PSX_WARNING("[MCR] Communication aborted on phase %d", command_phase); - } - dtr = new_dtr; -} - -bool InputDevice_Memcard::GetDSR(void) -{ - if(!dtr) - return(0); - - if(!bitpos && transmit_count) - return(1); - - return(0); -} - -bool InputDevice_Memcard::Clock(bool TxD, int32 &dsr_pulse_delay) -{ - bool ret = 1; - - dsr_pulse_delay = 0; - - if(!dtr) - return(1); - - if(transmit_count) - ret = (transmit_buffer >> bitpos) & 1; - - receive_buffer &= ~(1 << bitpos); - receive_buffer |= TxD << bitpos; - bitpos = (bitpos + 1) & 0x7; - - if(!bitpos) - { - //if(command_phase > 0 || transmit_count) - // printf("[MCRDATA] Received_data=0x%02x, Sent_data=0x%02x\n", receive_buffer, transmit_buffer); - - if(transmit_count) - { - transmit_count--; - } - - - - if(command_phase == 0) - { - if(receive_buffer != 0x81) - command_phase = -1; - else - { - //printf("[MCR] Device selected\n"); - transmit_buffer = presence_new ? 0x08 : 0x00; - transmit_count = 1; - command_phase++; - } - } - else if(command_phase == 1) - { - command = receive_buffer; - //printf("[MCR] Command received: %c\n", command); - if(command == 'R' || command == 'W') - { - command_phase++; - transmit_buffer = 0x5A; - transmit_count = 1; - } - else - { - if(command == 'S') - { - PSX_WARNING("[MCR] Memcard S command unsupported."); - } - - command_phase = -1; - transmit_buffer = 0; - transmit_count = 0; - } - } - else if(command_phase == 2) - { - transmit_buffer = 0x5D; - transmit_count = 1; - command_phase++; - } - else if(command_phase == 3) - { - transmit_buffer = 0x00; - transmit_count = 1; - if(command == 'R') - command_phase = 1000; - else if(command == 'W') - command_phase = 2000; - } - // - // Read - // - else if(command_phase == 1000) - { - addr = receive_buffer << 8; - transmit_buffer = receive_buffer; - transmit_count = 1; - command_phase++; - } - else if(command_phase == 1001) - { - addr |= receive_buffer & 0xFF; - transmit_buffer = '\\'; - transmit_count = 1; - command_phase++; - } - else if(command_phase == 1002) - { - PSX_DBG(PSX_DBG_SPARSE, "[MCR] Read Command: 0x%04x\n", addr); - if(addr >= (sizeof(card_data) >> 7)) - addr = 0xFFFF; - - calced_xor = 0; - transmit_buffer = ']'; - transmit_count = 1; - command_phase++; - - // TODO: enable this code(or something like it) when CPU instruction timing is a bit better. - // - //dsr_pulse_delay = 32000; - //goto SkipDPD; - // - } - else if(command_phase == 1003) - { - transmit_buffer = addr >> 8; - calced_xor ^= transmit_buffer; - transmit_count = 1; - command_phase++; - } - else if(command_phase == 1004) - { - transmit_buffer = addr & 0xFF; - calced_xor ^= transmit_buffer; - - if(addr == 0xFFFF) - { - transmit_count = 1; - command_phase = -1; - } - else - { - transmit_count = 1; - command_phase = 1024; - } - } - // Transmit actual 128 bytes data - else if(command_phase >= (1024 + 0) && command_phase <= (1024 + 128 - 1)) - { - transmit_buffer = card_data[(addr << 7) + (command_phase - 1024)]; - calced_xor ^= transmit_buffer; - transmit_count = 1; - command_phase++; - } - // XOR - else if(command_phase == (1024 + 128)) - { - transmit_buffer = calced_xor; - transmit_count = 1; - command_phase++; - } - // End flag - else if(command_phase == (1024 + 129)) - { - transmit_buffer = 'G'; - transmit_count = 1; - command_phase = -1; - } - // - // Write - // - else if(command_phase == 2000) - { - calced_xor = receive_buffer; - addr = receive_buffer << 8; - transmit_buffer = receive_buffer; - transmit_count = 1; - command_phase++; - } - else if(command_phase == 2001) - { - calced_xor ^= receive_buffer; - addr |= receive_buffer & 0xFF; - PSX_DBG(PSX_DBG_SPARSE, "[MCR] Write command: 0x%04x\n", addr); - transmit_buffer = receive_buffer; - transmit_count = 1; - command_phase = 2048; - } - else if(command_phase >= (2048 + 0) && command_phase <= (2048 + 128 - 1)) - { - calced_xor ^= receive_buffer; - rw_buffer[command_phase - 2048] = receive_buffer; - - transmit_buffer = receive_buffer; - transmit_count = 1; - command_phase++; - } - else if(command_phase == (2048 + 128)) // XOR - { - write_xor = receive_buffer; - transmit_buffer = '\\'; - transmit_count = 1; - command_phase++; - } - else if(command_phase == (2048 + 129)) - { - transmit_buffer = ']'; - transmit_count = 1; - command_phase++; - } - else if(command_phase == (2048 + 130)) // End flag - { - //MDFN_DispMessage("%02x %02x", calced_xor, write_xor); - //printf("[MCR] Write End. Actual_XOR=0x%02x, CW_XOR=0x%02x\n", calced_xor, write_xor); - - if(calced_xor != write_xor) - { - transmit_buffer = 'N'; - PSX_WARNING("[MCR] Write end, calced_xor(0x%02x) != written_xor(0x%02x)", calced_xor, write_xor); - } - else if(addr >= (sizeof(card_data) >> 7)) - { - transmit_buffer = 0xFF; - PSX_WARNING("[MCR] Attempt to write to invalid block 0x%04x", addr); - } - else - { - transmit_buffer = 'G'; - presence_new = false; - - // If the current data is different from the data to be written, increment the dirty count. - // memcpy()'ing over to card_data is also conditionalized here for a slight optimization. - if(memcmp(&card_data[addr << 7], rw_buffer, 128)) - { - memcpy(&card_data[addr << 7], rw_buffer, 128); - dirty_count++; - data_used = true; - } - } - - transmit_count = 1; - command_phase = -1; - } - - //if(command_phase != -1 || transmit_count) - // printf("[MCR] Receive: 0x%02x, Send: 0x%02x -- %d\n", receive_buffer, transmit_buffer, command_phase); - } - - if(!bitpos && transmit_count) - dsr_pulse_delay = 0x100; - - //SkipDPD: ; - - return(ret); -} - -uint32 InputDevice_Memcard::GetNVSize(void) -{ - return(sizeof(card_data)); -} - -const uint8* InputDevice_Memcard::ReadNV(void) const -{ - return card_data; -} - -void InputDevice_Memcard::WriteNV(const uint8 *buffer, uint32 offset, uint32 size) -{ - if(size) - { - dirty_count++; - } - - while(size--) - { - if(card_data[offset & (sizeof(card_data) - 1)] != *buffer) - data_used = true; - - card_data[offset & (sizeof(card_data) - 1)] = *buffer; - buffer++; - offset++; - } -} - -uint64 InputDevice_Memcard::GetNVDirtyCount(void) const -{ - return(dirty_count); -} - -void InputDevice_Memcard::ResetNVDirtyCount(void) -{ - dirty_count = 0; -} - - -InputDevice *Device_Memcard_Create(void) -{ - return new InputDevice_Memcard(); -} - -} diff --git a/psx/octoshock/psx/input/memcard.h b/psx/octoshock/psx/input/memcard.h deleted file mode 100644 index 58dbc45d9d0..00000000000 --- a/psx/octoshock/psx/input/memcard.h +++ /dev/null @@ -1,32 +0,0 @@ -/******************************************************************************/ -/* Mednafen Sony PS1 Emulation Module */ -/******************************************************************************/ -/* memcard.h: -** Copyright (C) 2012-2016 Mednafen Team -** -** 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., -** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef __MDFN_PSX_INPUT_MEMCARD_H -#define __MDFN_PSX_INPUT_MEMCARD_H - -namespace MDFN_IEN_PSX -{ - -InputDevice *Device_Memcard_Create(void); - -} - -#endif diff --git a/psx/octoshock/psx/input/mouse.cpp b/psx/octoshock/psx/input/mouse.cpp deleted file mode 100644 index d7bb7179ce4..00000000000 --- a/psx/octoshock/psx/input/mouse.cpp +++ /dev/null @@ -1,304 +0,0 @@ -/******************************************************************************/ -/* Mednafen Sony PS1 Emulation Module */ -/******************************************************************************/ -/* mouse.cpp: -** Copyright (C) 2012-2016 Mednafen Team -** -** 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., -** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "../psx.h" -#include "../frontio.h" -#include "mouse.h" - -namespace MDFN_IEN_PSX -{ - -class InputDevice_Mouse final : public InputDevice -{ - public: - - InputDevice_Mouse(); - virtual ~InputDevice_Mouse(); - - virtual void Power(void) override; - virtual void UpdateInput(const void *data) override; - - virtual void Update(const pscpu_timestamp_t timestamp) override; - virtual void ResetTS(void) override; - - // - // - // - virtual void SetDTR(bool new_dtr) override; - virtual bool Clock(bool TxD, int32 &dsr_pulse_delay) override; - - private: - - int32 lastts; - int32 clear_timeout; - - bool dtr; - - uint8 button; - uint8 button_post_mask; - int32 accum_xdelta; - int32 accum_ydelta; - - int32 command_phase; - uint32 bitpos; - uint8 receive_buffer; - - uint8 command; - - uint8 transmit_buffer[5]; - uint32 transmit_pos; - uint32 transmit_count; -}; - -InputDevice_Mouse::InputDevice_Mouse() -{ - Power(); -} - -InputDevice_Mouse::~InputDevice_Mouse() -{ - -} - -void InputDevice_Mouse::Update(const pscpu_timestamp_t timestamp) -{ - int32 cycles = timestamp - lastts; - - clear_timeout += cycles; - if(clear_timeout >= (33868800 / 4)) - { - //puts("Mouse timeout\n"); - clear_timeout = 0; - accum_xdelta = 0; - accum_ydelta = 0; - button &= button_post_mask; - } - - lastts = timestamp; -} - -void InputDevice_Mouse::ResetTS(void) -{ - lastts = 0; -} - -void InputDevice_Mouse::Power(void) -{ - lastts = 0; - clear_timeout = 0; - - dtr = 0; - - button = 0; - button_post_mask = 0; - accum_xdelta = 0; - accum_ydelta = 0; - - command_phase = 0; - - bitpos = 0; - - receive_buffer = 0; - - command = 0; - - memset(transmit_buffer, 0, sizeof(transmit_buffer)); - - transmit_pos = 0; - transmit_count = 0; -} - -//void InputDevice_Mouse::StateAction(StateMem* sm, const unsigned load, const bool data_only, const char* sname_prefix) -//{ -// SFORMAT StateRegs[] = -// { -// SFVAR(clear_timeout), -// -// SFVAR(dtr), -// -// SFVAR(button), -// SFVAR(button_post_mask), -// SFVAR(accum_xdelta), -// SFVAR(accum_ydelta), -// -// SFVAR(command_phase), -// SFVAR(bitpos), -// SFVAR(receive_buffer), -// -// SFVAR(command), -// -// SFARRAY(transmit_buffer, sizeof(transmit_buffer)), -// SFVAR(transmit_pos), -// SFVAR(transmit_count), -// -// SFEND -// }; -// char section_name[32]; -// trio_snprintf(section_name, sizeof(section_name), "%s_Mouse", sname_prefix); -// -// if(!MDFNSS_StateAction(sm, load, data_only, StateRegs, section_name, true) && load) -// Power(); -// else if(load) -// { -// if((transmit_pos + transmit_count) > sizeof(transmit_buffer)) -// { -// transmit_pos = 0; -// transmit_count = 0; -// } -// } -//} - - -void InputDevice_Mouse::UpdateInput(const void *data) -{ - accum_xdelta += (int32)MDFN_de32lsb((uint8*)data + 0); - accum_ydelta += (int32)MDFN_de32lsb((uint8*)data + 4); - - if(accum_xdelta > 30 * 127) accum_xdelta = 30 * 127; - if(accum_xdelta < 30 * -128) accum_xdelta = 30 * -128; - - if(accum_ydelta > 30 * 127) accum_ydelta = 30 * 127; - if(accum_ydelta < 30 * -128) accum_ydelta = 30 * -128; - - button |= *((uint8 *)data + 8); - button_post_mask = *((uint8 *)data + 8); - - //if(button) - // MDFN_DispMessage("Button\n"); - //printf("%d %d\n", accum_xdelta, accum_ydelta); -} - - -void InputDevice_Mouse::SetDTR(bool new_dtr) -{ - if(!dtr && new_dtr) - { - command_phase = 0; - bitpos = 0; - transmit_pos = 0; - transmit_count = 0; - } - else if(dtr && !new_dtr) - { - //if(bitpos || transmit_count) - // printf("[PAD] Abort communication!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"); - } - - dtr = new_dtr; -} - -bool InputDevice_Mouse::Clock(bool TxD, int32 &dsr_pulse_delay) -{ - bool ret = 1; - - dsr_pulse_delay = 0; - - if(!dtr) - return(1); - - if(transmit_count) - ret = (transmit_buffer[transmit_pos] >> bitpos) & 1; - - receive_buffer &= ~(1 << bitpos); - receive_buffer |= TxD << bitpos; - bitpos = (bitpos + 1) & 0x7; - - if(!bitpos) - { - //printf("[PAD] Receive: %02x -- command_phase=%d\n", receive_buffer, command_phase); - - if(transmit_count) - { - transmit_pos++; - transmit_count--; - } - - - switch(command_phase) - { - case 0: - if(receive_buffer != 0x01) - command_phase = -1; - else - { - transmit_buffer[0] = 0x12; - transmit_pos = 0; - transmit_count = 1; - command_phase++; - } - break; - - case 1: - command = receive_buffer; - command_phase++; - - transmit_buffer[0] = 0x5A; - - if(command == 0x42) - { - int32 xdelta = accum_xdelta; - int32 ydelta = accum_ydelta; - - if(xdelta < -128) xdelta = -128; - if(xdelta > 127) xdelta = 127; - - if(ydelta < -128) ydelta = -128; - if(ydelta > 127) ydelta = 127; - - transmit_buffer[1] = 0xFF; - transmit_buffer[2] = 0xFC ^ (button << 2); - transmit_buffer[3] = xdelta; - transmit_buffer[4] = ydelta; - - accum_xdelta -= xdelta; - accum_ydelta -= ydelta; - - button &= button_post_mask; - - transmit_pos = 0; - transmit_count = 5; - - clear_timeout = 0; - } - else - { - command_phase = -1; - transmit_pos = 0; - transmit_count = 0; - } - break; - - } - } - - if(!bitpos && transmit_count) - dsr_pulse_delay = 0x40; //0x100; - - return(ret); -} - -InputDevice *Device_Mouse_Create(void) -{ - return new InputDevice_Mouse(); -} - - -} diff --git a/psx/octoshock/psx/input/mouse.h b/psx/octoshock/psx/input/mouse.h deleted file mode 100644 index 71a7b9412ba..00000000000 --- a/psx/octoshock/psx/input/mouse.h +++ /dev/null @@ -1,30 +0,0 @@ -/******************************************************************************/ -/* Mednafen Sony PS1 Emulation Module */ -/******************************************************************************/ -/* mouse.h: -** Copyright (C) 2012-2016 Mednafen Team -** -** 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., -** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef __MDFN_PSX_INPUT_MOUSE_H -#define __MDFN_PSX_INPUT_MOUSE_H - -namespace MDFN_IEN_PSX -{ - -InputDevice *Device_Mouse_Create(void); -} -#endif diff --git a/psx/octoshock/psx/input/multitap.cpp b/psx/octoshock/psx/input/multitap.cpp deleted file mode 100644 index c9591156c74..00000000000 --- a/psx/octoshock/psx/input/multitap.cpp +++ /dev/null @@ -1,517 +0,0 @@ -/******************************************************************************/ -/* Mednafen Sony PS1 Emulation Module */ -/******************************************************************************/ -/* multitap.cpp: -** Copyright (C) 2012-2016 Mednafen Team -** -** 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., -** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include -#include "../psx.h" -#include "../frontio.h" -#include "multitap.h" - -/* - TODO: PS1 multitap appears to have some internal knowledge of controller IDs, so it won't get "stuck" waiting for data from a controller that'll never - come. We currently sort of "cheat" due to how the dsr_pulse_delay stuff works, but in the future we should try to emulate this multitap functionality. - - Also, full-mode read startup and subport controller ID read timing isn't quite right, so we should fix that too. -*/ - -/* - Notes from tests on real thing(not necessarily emulated the same way here): - - Manual port selection read mode: - Write 0x01-0x04 instead of 0x01 as first byte, selects port(1=A,2=B,3=C,4=D) to access. - - Ports that don't exist(0x00, 0x05-0xFF) or don't have a device plugged in will not respond(no DSR pulse). - - Full read mode: - Bit0 of third byte(from-zero-index=0x02) should be set to 1 to enter full read mode, on subsequent reads. - - Appears to require a controller to be plugged into the port specified by the first byte as per manual port selection read mode, - to write the byte necessary to enter full-read mode; but once the third byte with the bit set has been written, no controller in - that port is required for doing full reads(and the manual port selection is ignored when doing a full read). - - However, if there are no controllers plugged in, the returned data will be short: - % 0: 0xff - % 1: 0x80 - % 2: 0x5a - - Example full-read bytestream(with controllers plugged into port A, port B, and port C, with port D empty): - % 0: 0xff - % 1: 0x80 - % 2: 0x5a - - % 3: 0x73 (Port A controller data start) - % 4: 0x5a - % 5: 0xff - % 6: 0xff - % 7: 0x80 - % 8: 0x8c - % 9: 0x79 - % 10: 0x8f - - % 11: 0x53 (Port B controller data start) - % 12: 0x5a - % 13: 0xff - % 14: 0xff - % 15: 0x80 - % 16: 0x80 - % 17: 0x75 - % 18: 0x8e - - % 19: 0x41 (Port C controller data start) - % 20: 0x5a - % 21: 0xff - % 22: 0xff - % 23: 0xff - % 24: 0xff - % 25: 0xff - % 26: 0xff - - % 27: 0xff (Port D controller data start) - % 28: 0xff - % 29: 0xff - % 30: 0xff - % 31: 0xff - % 32: 0xff - % 33: 0xff - % 34: 0xff - -*/ - -namespace MDFN_IEN_PSX -{ - -InputDevice_Multitap::InputDevice_Multitap() -{ - for(int i = 0; i < 4; i++) - { - //dummies - pad_devices[i] = new InputDevice(); - mc_devices[i] = new InputDevice(); - } - Power(); -} - -InputDevice_Multitap::~InputDevice_Multitap() -{ - for (int i = 0; i < 4; i++) - { - delete pad_devices[i]; - delete mc_devices[i]; - pad_devices[i] = NULL; - mc_devices[i] = NULL; - } -} - -void InputDevice_Multitap::SetSubDevice(unsigned int sub_index, InputDevice *device, InputDevice *mc_device) -{ - assert(sub_index < 4); - - //printf("%d\n", sub_index); - - delete pad_devices[sub_index]; - delete mc_devices[sub_index]; - - pad_devices[sub_index] = device; - mc_devices[sub_index] = mc_device; -} - - -void InputDevice_Multitap::Power(void) -{ - selected_device = -1; - bit_counter = 0; - receive_buffer = 0; - byte_counter = 0; - - mc_mode = false; - full_mode = false; - full_mode_setting = false; - - prev_fm_success = false; - memset(sb, 0, sizeof(sb)); - - fm_dp = 0; - memset(fm_buffer, 0, sizeof(fm_buffer)); - fm_command_error = false; - - for(int i = 0; i < 4; i++) - { - if(pad_devices[i]) - pad_devices[i]->Power(); - - if(mc_devices[i]) - mc_devices[i]->Power(); - } -} - -//void InputDevice_Multitap::StateAction(StateMem* sm, const unsigned load, const bool data_only, const char* sname_prefix) -//{ -// SFORMAT StateRegs[] = -// { -// SFVAR(dtr), -// -// SFVAR(selected_device), -// SFVAR(full_mode_setting), -// -// SFVAR(full_mode), -// SFVAR(mc_mode), -// -// SFVAR(fm_dp), -// SFARRAY(&fm_buffer[0][0], sizeof(fm_buffer) / sizeof(fm_buffer[0][0])), -// -// SFVAR(fm_deferred_error_temp), -// SFVAR(fm_deferred_error), -// SFVAR(fm_command_error), -// -// SFVAR(command), -// SFVAR(receive_buffer), -// SFVAR(bit_counter), -// SFVAR(byte_counter), -// -// SFEND -// }; -// char section_name[32]; -// trio_snprintf(section_name, sizeof(section_name), "%s_MT", sname_prefix); -// -// if(!MDFNSS_StateAction(sm, load, data_only, StateRegs, section_name, true) && load) -// Power(); -// else if(load) -// { -// -// } -// -// for(unsigned i = 0; i < 4; i++) -// { -// char tmpbuf[32]; -// -// trio_snprintf(tmpbuf, sizeof(tmpbuf), "%sP%u", section_name, i); -// pad_devices[i]->StateAction(sm, load, data_only, tmpbuf); -// } -// -// for(unsigned i = 0; i < 4; i++) -// { -// char tmpbuf[32]; -// -// trio_snprintf(tmpbuf, sizeof(tmpbuf), "%sMC%u", section_name, i); -// mc_devices[i]->StateAction(sm, load, data_only, tmpbuf); -// } -//} - -void InputDevice_Multitap::Update(const pscpu_timestamp_t timestamp) -{ - for(unsigned i = 0; i < 4; i++) - { - pad_devices[i]->Update(timestamp); - mc_devices[i]->Update(timestamp); - } -} - -void InputDevice_Multitap::ResetTS(void) -{ - for(unsigned i = 0; i < 4; i++) - { - pad_devices[i]->ResetTS(); - mc_devices[i]->ResetTS(); - } -} - - -bool InputDevice_Multitap::RequireNoFrameskip(void) -{ - bool ret = false; - - for(unsigned i = 0; i < 4; i++) - ret |= pad_devices[i]->RequireNoFrameskip(); - - return(ret); -} - -pscpu_timestamp_t InputDevice_Multitap::GPULineHook(const pscpu_timestamp_t line_timestamp, bool vsync, uint32 *pixels, const MDFN_PixelFormat* const format, const unsigned width, const unsigned pix_clock_offset, const unsigned pix_clock, const unsigned pix_clock_divider) -{ - pscpu_timestamp_t ret = PSX_EVENT_MAXTS; - - for(unsigned i = 0; i < 4; i++) - { - pscpu_timestamp_t tmp = pad_devices[i]->GPULineHook(line_timestamp, vsync, pixels, format, width, pix_clock_offset, pix_clock, pix_clock_divider); - - if(i == 0) // FIXME; though the problems the design flaw causes(multitap issues with justifier) are documented at least. - ret = tmp; - } - - return(ret); -} - - -void InputDevice_Multitap::SetDTR(bool new_dtr) -{ - bool old_dtr = dtr; - dtr = new_dtr; - - if(!dtr) - { - if(old_dtr) - { - //printf("Multitap stop.\n"); - } - - bit_counter = 0; - receive_buffer = 0; - selected_device = -1; - mc_mode = false; - full_mode = false; - } - - if(!old_dtr && dtr) - { - full_mode = full_mode_setting; - - if(!prev_fm_success) - { - memset(sb, 0, sizeof(sb)); - for(unsigned i = 0; i < 4; i++) - sb[i][0] = 0x42; - } - - prev_fm_success = false; - - byte_counter = 0; - - //if(full_mode) - // printf("Multitap start: %d\n", full_mode); - } - - for(int i = 0; i < 4; i++) - { - pad_devices[i]->SetDTR(dtr); - mc_devices[i]->SetDTR(dtr); - } -} - -bool InputDevice_Multitap::GetDSR(void) -{ - return(0); -} - -bool InputDevice_Multitap::Clock(bool TxD, int32 &dsr_pulse_delay) -{ - if(!dtr) - return(1); - - bool ret = 1; - int32 tmp_pulse_delay[2][4] = { { 0, 0, 0, 0 }, { 0, 0, 0, 0 } }; - - //printf("Receive bit: %d\n", TxD); - //printf("TxD %d\n", TxD); - - receive_buffer &= ~ (1 << bit_counter); - receive_buffer |= TxD << bit_counter; - - if(1) - { - if(byte_counter == 0) - { - bool mangled_txd = TxD; - - if(bit_counter < 4) - mangled_txd = (0x01 >> bit_counter) & 1; - - for(unsigned i = 0; i < 4; i++) - { - pad_devices[i]->Clock(mangled_txd, tmp_pulse_delay[0][i]); - mc_devices[i]->Clock(mangled_txd, tmp_pulse_delay[1][i]); - } - } - else - { - if(full_mode) - { - if(byte_counter == 1) - ret = (0x80 >> bit_counter) & 1; - else if(byte_counter == 2) - ret = (0x5A >> bit_counter) & 1; - else if(byte_counter >= 0x03 && byte_counter < 0x03 + 0x08 * 4) - { - if(!fm_command_error && byte_counter < (0x03 + 0x08)) - { - for(unsigned i = 0; i < 4; i++) - { - fm_buffer[i][byte_counter - 0x03] &= (pad_devices[i]->Clock((sb[i][byte_counter - 0x03] >> bit_counter) & 1, tmp_pulse_delay[0][i]) << bit_counter) | (~(1U << bit_counter)); - } - } - ret &= (MDAP(fm_buffer)[byte_counter - 0x03] >> bit_counter) & 1; - } - } - else // to if(full_mode) - { - if((unsigned)selected_device < 4) - { - ret &= pad_devices[selected_device]->Clock(TxD, tmp_pulse_delay[0][selected_device]); - ret &= mc_devices[selected_device]->Clock(TxD, tmp_pulse_delay[1][selected_device]); - } - } - } // end else to if(byte_counter == 0) - } - - // - // - // - - bit_counter = (bit_counter + 1) & 0x7; - if(bit_counter == 0) - { - //printf("MT Receive: 0x%02x\n", receive_buffer); - if(byte_counter == 0) - { - mc_mode = (bool)(receive_buffer & 0xF0); - if(mc_mode) - full_mode = false; - - //printf("Zoomba: 0x%02x\n", receive_buffer); - //printf("Full mode: %d %d %d\n", full_mode, bit_counter, byte_counter); - - if(full_mode) - { - memset(fm_buffer, 0xFF, sizeof(fm_buffer)); - selected_device = 0; - } - else - { - //printf("Device select: %02x\n", receive_buffer); - selected_device = ((receive_buffer & 0xF) - 1) & 0xFF; - } - } - - if(byte_counter == 1) - { - command = receive_buffer; - - //printf("Multitap sub-command: %02x\n", command); - - if(full_mode) - { - if(command != 0x42) - fm_command_error = true; - else - fm_command_error = false; - } - else - { - fm_command_error = false; - } - } - - if((!mc_mode || full_mode) && byte_counter == 2) - { - //printf("Full mode setting: %02x\n", receive_buffer); - full_mode_setting = receive_buffer & 0x01; - } - - if(full_mode) - { - if(byte_counter >= 3 + 8 * 0 && byte_counter < (3 + 8 * 4)) - { - const unsigned adjbi = byte_counter - 3; - - sb[adjbi >> 3][adjbi & 0x7] = receive_buffer; - } - - if(byte_counter == 33) - prev_fm_success = true; - } - - // Handle DSR stuff - if(full_mode) - { - if(byte_counter == 0) // Next byte: 0x80 - { - dsr_pulse_delay = 1000; - - fm_dp = 0; - for(unsigned i = 0; i < 4; i++) - fm_dp |= (((bool)(tmp_pulse_delay[0][i])) << i); - } - else if(byte_counter == 1) // Next byte: 0x5A - dsr_pulse_delay = 0x40; - else if(byte_counter == 2) // Next byte(typically, controller-dependent): 0x41 - { - if(fm_dp) - dsr_pulse_delay = 0x40; - else - { - byte_counter = 255; - dsr_pulse_delay = 0; - } - } - else if(byte_counter >= 3 && byte_counter < 34) // Next byte when byte_counter==3 (typically, controller-dependent): 0x5A - { - if(byte_counter < 10) - { - int d = 0x40; - - for(unsigned i = 0; i < 4; i++) - { - int32 tpd = tmp_pulse_delay[0][i]; - - if(byte_counter == 3 && (fm_dp & (1U << i)) && tpd == 0) - { - //printf("SNORG: %u %02x\n", i, sb[i][0]); - fm_command_error = true; - } - - if(tpd > d) - d = tpd; - } - - dsr_pulse_delay = d; - } - else - dsr_pulse_delay = 0x20; - - if(byte_counter == 3 && fm_command_error) - { - byte_counter = 255; - dsr_pulse_delay = 0; - } - } - } // end if(full_mode) - else - { - if((unsigned)selected_device < 4) - { - dsr_pulse_delay = std::max(tmp_pulse_delay[0][selected_device], tmp_pulse_delay[1][selected_device]); - } - } - - - // - // - // - - //printf("Byte Counter Increment\n"); - if(byte_counter < 255) - byte_counter++; - } - - - - return(ret); -} - -} diff --git a/psx/octoshock/psx/input/multitap.h b/psx/octoshock/psx/input/multitap.h deleted file mode 100644 index b2a6491fd9d..00000000000 --- a/psx/octoshock/psx/input/multitap.h +++ /dev/null @@ -1,80 +0,0 @@ -/******************************************************************************/ -/* Mednafen Sony PS1 Emulation Module */ -/******************************************************************************/ -/* multitap.h: -** Copyright (C) 2012-2016 Mednafen Team -** -** 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., -** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef __MDFN_PSX_INPUT_MULTITAP_H -#define __MDFN_PSX_INPUT_MULTITAP_H - -namespace MDFN_IEN_PSX -{ - -class InputDevice_Multitap final : public InputDevice -{ - public: - - InputDevice_Multitap(); - virtual ~InputDevice_Multitap(); - virtual void Power(void) override; - - virtual void Update(const pscpu_timestamp_t timestamp) override; - virtual void ResetTS(void) override; - - virtual bool RequireNoFrameskip(void) override; - virtual pscpu_timestamp_t GPULineHook(const pscpu_timestamp_t line_timestamp, bool vsync, uint32 *pixels, const MDFN_PixelFormat* const format, const unsigned width, const unsigned pix_clock_offset, const unsigned pix_clock, const unsigned pix_clock_divider) override; - - void SetSubDevice(unsigned int sub_index, InputDevice *device, InputDevice *mc_device); - - // - // - // - virtual void SetDTR(bool new_dtr) override; - virtual bool GetDSR(void) override; - virtual bool Clock(bool TxD, int32 &dsr_pulse_delay) override; - - private: - - InputDevice *pad_devices[4]; - InputDevice *mc_devices[4]; - - bool dtr; - - int selected_device; - bool full_mode_setting; - - bool full_mode; - bool mc_mode; - bool prev_fm_success; - - uint8 fm_dp; // Device-present. - uint8 fm_buffer[4][8]; - - uint8 sb[4][8]; - - bool fm_command_error; - - uint8 command; - uint8 receive_buffer; - uint8 bit_counter; - uint8 byte_counter; -}; - -} - -#endif diff --git a/psx/octoshock/psx/input/negcon.cpp b/psx/octoshock/psx/input/negcon.cpp deleted file mode 100644 index 0187be427ea..00000000000 --- a/psx/octoshock/psx/input/negcon.cpp +++ /dev/null @@ -1,261 +0,0 @@ -/******************************************************************************/ -/* Mednafen Sony PS1 Emulation Module */ -/******************************************************************************/ -/* negcon.cpp: -** Copyright (C) 2012-2016 Mednafen Team -** -** 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., -** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "../psx.h" -#include "../frontio.h" -#include "negcon.h" - -namespace MDFN_IEN_PSX -{ - -class InputDevice_neGcon final : public InputDevice -{ - public: - - InputDevice_neGcon(void); - virtual ~InputDevice_neGcon(); - - virtual void Power(void) override; - virtual void UpdateInput(const void *data) override; - virtual void SyncState(bool isReader, EW::NewState *ns) override; - - // - // - // - virtual void SetDTR(bool new_dtr) override; - virtual bool GetDSR(void) override; - virtual bool Clock(bool TxD, int32 &dsr_pulse_delay) override; - - private: - - //non-serialized state - IO_NegCon* io; - - bool dtr; - - uint8 buttons[2]; - uint8 twist; - uint8 anabuttons[3]; - - int32 command_phase; - uint32 bitpos; - uint8 receive_buffer; - - uint8 command; - - uint8 transmit_buffer[8]; - uint32 transmit_pos; - uint32 transmit_count; -}; - -InputDevice_neGcon::InputDevice_neGcon(void) -{ - Power(); -} - -InputDevice_neGcon::~InputDevice_neGcon() -{ - -} - -void InputDevice_neGcon::Power(void) -{ - dtr = 0; - - buttons[0] = buttons[1] = 0; - twist = 0; - anabuttons[0] = 0; - anabuttons[1] = 0; - anabuttons[2] = 0; - - command_phase = 0; - - bitpos = 0; - - receive_buffer = 0; - - command = 0; - - memset(transmit_buffer, 0, sizeof(transmit_buffer)); - - transmit_pos = 0; - transmit_count = 0; -} - -void InputDevice_neGcon::SyncState(bool isReader, EW::NewState *ns) -{ - NSS(dtr); - - NSS(buttons); - NSS(twist); - NSS(anabuttons); - - NSS(command_phase); - NSS(bitpos); - NSS(receive_buffer); - - NSS(command); - - NSS(transmit_buffer); - NSS(transmit_pos); - NSS(transmit_count); -} - -void InputDevice_neGcon::UpdateInput(const void *data) -{ - io = (IO_NegCon*)data; - - buttons[0] = io->buttons[0]; - buttons[1] = io->buttons[1]; - - twist = io->twist; //((32768 + MDFN_de16lsb((const uint8 *)data + 2) - (((int32)MDFN_de16lsb((const uint8 *)data + 4) * 32768 + 16383) / 32767)) * 255 + 32767) / 65535; - - anabuttons[0] = io->anabuttons[0]; - anabuttons[1] = io->anabuttons[1]; - anabuttons[2] = io->anabuttons[2]; - - //anabuttons[0] = (MDFN_de16lsb((const uint8 *)data + 6) * 255 + 16383) / 32767; - //anabuttons[1] = (MDFN_de16lsb((const uint8 *)data + 8) * 255 + 16383) / 32767; - //anabuttons[2] = (MDFN_de16lsb((const uint8 *)data + 10) * 255 + 16383) / 32767; - - //printf("%02x %02x %02x %02x\n", twist, anabuttons[0], anabuttons[1], anabuttons[2]); -} - - -void InputDevice_neGcon::SetDTR(bool new_dtr) -{ - if(!dtr && new_dtr) - { - command_phase = 0; - bitpos = 0; - transmit_pos = 0; - transmit_count = 0; - } - else if(dtr && !new_dtr) - { - //if(bitpos || transmit_count) - // printf("[PAD] Abort communication!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"); - } - - dtr = new_dtr; -} - -bool InputDevice_neGcon::GetDSR(void) -{ - if(!dtr) - return(0); - - if(!bitpos && transmit_count) - return(1); - - return(0); -} - -bool InputDevice_neGcon::Clock(bool TxD, int32 &dsr_pulse_delay) -{ - bool ret = 1; - - dsr_pulse_delay = 0; - - if(!dtr) - return(1); - - if(transmit_count) - ret = (transmit_buffer[transmit_pos] >> bitpos) & 1; - - receive_buffer &= ~(1 << bitpos); - receive_buffer |= TxD << bitpos; - bitpos = (bitpos + 1) & 0x7; - - if(!bitpos) - { - //printf("[PAD] Receive: %02x -- command_phase=%d\n", receive_buffer, command_phase); - - if(transmit_count) - { - transmit_pos++; - transmit_count--; - } - - - switch(command_phase) - { - case 0: - if(receive_buffer != 0x01) - command_phase = -1; - else - { - transmit_buffer[0] = 0x23; - transmit_pos = 0; - transmit_count = 1; - command_phase++; - dsr_pulse_delay = 256; - } - break; - - case 1: - command = receive_buffer; - command_phase++; - - transmit_buffer[0] = 0x5A; - - //if(command != 0x42) - // fprintf(stderr, "Gamepad unhandled command: 0x%02x\n", command); - - if(command == 0x42) - { - transmit_buffer[1] = 0xFF ^ buttons[0]; - transmit_buffer[2] = 0xFF ^ buttons[1]; - transmit_buffer[3] = twist; // Twist, 0x00 through 0xFF, 0x80 center. - transmit_buffer[4] = anabuttons[0]; // Analog button I, 0x00 through 0xFF, 0x00 = no pressing, 0xFF = max. - transmit_buffer[5] = anabuttons[1]; // Analog button II, "" - transmit_buffer[6] = anabuttons[2]; // Left shoulder analog button, "" - transmit_pos = 0; - transmit_count = 7; - dsr_pulse_delay = 256; - } - else - { - command_phase = -1; - transmit_buffer[1] = 0; - transmit_buffer[2] = 0; - transmit_pos = 0; - transmit_count = 0; - } - break; - - case 2: - if(transmit_count > 0) - dsr_pulse_delay = 128; - break; - } - } - - return(ret); -} - -InputDevice *Device_neGcon_Create(void) -{ - return new InputDevice_neGcon(); -} - - -} diff --git a/psx/octoshock/psx/input/negcon.h b/psx/octoshock/psx/input/negcon.h deleted file mode 100644 index 003396e0e38..00000000000 --- a/psx/octoshock/psx/input/negcon.h +++ /dev/null @@ -1,39 +0,0 @@ -/******************************************************************************/ -/* Mednafen Sony PS1 Emulation Module */ -/******************************************************************************/ -/* negcon.h: -** Copyright (C) 2012-2016 Mednafen Team -** -** 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., -** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef __MDFN_PSX_INPUT_NEGCON_H -#define __MDFN_PSX_INPUT_NEGCON_H - -namespace MDFN_IEN_PSX -{ - InputDevice *Device_neGcon_Create(void); - - EW_PACKED( - struct IO_NegCon - { - u8 buttons[2]; - u8 twist; - u8 anabuttons[3]; - u8 active; - }); - -} -#endif diff --git a/psx/octoshock/psx/irq.cpp b/psx/octoshock/psx/irq.cpp deleted file mode 100644 index 0e471ca3a4d..00000000000 --- a/psx/octoshock/psx/irq.cpp +++ /dev/null @@ -1,170 +0,0 @@ -/******************************************************************************/ -/* Mednafen Sony PS1 Emulation Module */ -/******************************************************************************/ -/* irq.cpp: -** Copyright (C) 2011-2016 Mednafen Team -** -** 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., -** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "psx.h" - -namespace MDFN_IEN_PSX -{ - -static uint16 Asserted; -static uint16 Mask; -static uint16 Status; - -static INLINE void Recalc(void) -{ - CPU->AssertIRQ(0, (bool)(Status & Mask)); -} - -void IRQ_SyncState(bool isReader, EW::NewState *ns) -{ - NSS(Asserted); - NSS(Mask); - NSS(Status); - - //as usual, not sure why this is necessary - if(isReader) - { - Recalc(); - } -} - -void IRQ_Assert(int which, bool status) -{ - uint32 old_Asserted = Asserted; - //PSX_WARNING("[IRQ] Assert: %d %d", which, status); - - //if(which == IRQ_SPU && status && (Asserted & (1 << which))) - // MDFN_DispMessage("SPU IRQ glitch??"); - - Asserted &= ~(1 << which); - - if(status) - { - Asserted |= 1 << which; - //Status |= 1 << which; - Status |= (old_Asserted ^ Asserted) & Asserted; - } - - Recalc(); -} - - -MDFN_FASTCALL void IRQ_Write(uint32 A, uint32 V) -{ - // FIXME if we ever have "accurate" bus emulation - V <<= (A & 3) * 8; - - //printf("[IRQ] Write: 0x%08x 0x%08x --- PAD TEMP\n", A, V); - - if(A & 4) - Mask = V; - else - { - Status &= V; - //Status |= Asserted; - } - - Recalc(); -} - - -MDFN_FASTCALL uint32 IRQ_Read(uint32 A) -{ - uint32 ret = 0; - - if(A & 4) - ret = Mask; - else - ret = Status; - - // FIXME: Might want to move this out to psx.cpp eventually. - ret |= 0x1F800000; - ret >>= (A & 3) * 8; - - - //printf("[IRQ] Read: 0x%08x 0x%08x --- PAD TEMP\n", A, ret); - - return(ret); -} - -void IRQ_Power(void) -{ - Asserted = 0; - Status = 0; - Mask = 0; - - Recalc(); -} - -void IRQ_Reset(void) -{ - Asserted = 0; - Status = 0; - Mask = 0; - - Recalc(); -} - - -uint32 IRQ_GetRegister(unsigned int which, char *special, const uint32 special_len) -{ - uint32 ret = 0; - - switch(which) - { - case IRQ_GSREG_ASSERTED: - ret = Asserted; - break; - - case IRQ_GSREG_STATUS: - ret = Status; - break; - - case IRQ_GSREG_MASK: - ret = Mask; - break; - } - return(ret); -} - -void IRQ_SetRegister(unsigned int which, uint32 value) -{ - switch(which) - { - case IRQ_GSREG_ASSERTED: - Asserted = value; - Recalc(); - break; - - case IRQ_GSREG_STATUS: - Status = value; - Recalc(); - break; - - case IRQ_GSREG_MASK: - Mask = value; - Recalc(); - break; - } -} - - -} diff --git a/psx/octoshock/psx/irq.h b/psx/octoshock/psx/irq.h deleted file mode 100644 index b14663279d9..00000000000 --- a/psx/octoshock/psx/irq.h +++ /dev/null @@ -1,63 +0,0 @@ -/******************************************************************************/ -/* Mednafen Sony PS1 Emulation Module */ -/******************************************************************************/ -/* irq.h: -** Copyright (C) 2011-2016 Mednafen Team -** -** 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., -** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef __MDFN_PSX_IRQ_H -#define __MDFN_PSX_IRQ_H - -namespace MDFN_IEN_PSX -{ - - -enum -{ - IRQ_VBLANK = 0, - IRQ_GPU = 1, - IRQ_CD = 2, - IRQ_DMA = 3, // Probably - IRQ_TIMER_0 = 4, - IRQ_TIMER_1 = 5, - IRQ_TIMER_2 = 6, - IRQ_SIO = 7, - IRQ_SPU = 9, - IRQ_PIO = 10, // Probably -}; - -void IRQ_Power(void) MDFN_COLD; -void IRQ_Assert(int which, bool asserted); - -MDFN_FASTCALL void IRQ_Write(uint32 A, uint32 V); -MDFN_FASTCALL uint32 IRQ_Read(uint32 A); - - -enum -{ - IRQ_GSREG_ASSERTED = 0, - IRQ_GSREG_STATUS = 1, - IRQ_GSREG_MASK = 2 -}; - -uint32 IRQ_GetRegister(unsigned int which, char *special, const uint32 special_len); -void IRQ_SetRegister(unsigned int which, uint32 value); - -} - - -#endif diff --git a/psx/octoshock/psx/masmem.h b/psx/octoshock/psx/masmem.h deleted file mode 100644 index 0a9ff185ecb..00000000000 --- a/psx/octoshock/psx/masmem.h +++ /dev/null @@ -1,121 +0,0 @@ -/******************************************************************************/ -/* Mednafen Sony PS1 Emulation Module */ -/******************************************************************************/ -/* masmem.h: -** Copyright (C) 2012-2016 Mednafen Team -** -** 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., -** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef __MDFN_PSX_MASMEM_H -#define __MDFN_PSX_MASMEM_H - -// address must not be >= size specified by template parameter, and address must be a multiple of the byte-size of the -// unit(1,2,4) being read(except for Read/WriteU24, which only needs to be byte-aligned). -// - -template //, unsigned pre_padding_count, unsigned post_padding_count> -struct MultiAccessSizeMem -{ - //uint8 pre_padding[pre_padding_count ? pre_padding_count : 1]; - - union - { - uint8 data8[size]; - uint64 alignment_dummy[1]; - }; - - //uint8 post_padding[post_padding_count ? post_padding_count : 1]; - - template - INLINE T Read(uint32 address) - { - return MDFN_deXsb(data8 + address); - } - - template - INLINE void Write(uint32 address, T value) - { - MDFN_enXsb(data8 + address, value); - } - - INLINE uint8 ReadU8(uint32 address) - { - return Read(address); - } - - INLINE uint16 ReadU16(uint32 address) - { - return Read(address); - } - - INLINE uint32 ReadU32(uint32 address) - { - return Read(address); - } - - INLINE uint32 ReadU24(uint32 address) - { - uint32 ret; - - if(!big_endian) - { - ret = ReadU8(address) << 0; - ret |= ReadU8(address + 1) << 8; - ret |= ReadU8(address + 2) << 16; - } - else - { - ret = ReadU8(address) << 16; - ret |= ReadU8(address + 1) << 8; - ret |= ReadU8(address + 2) << 0; - } - return(ret); - } - - - INLINE void WriteU8(uint32 address, uint8 value) - { - Write(address, value); - } - - INLINE void WriteU16(uint32 address, uint16 value) - { - Write(address, value); - } - - INLINE void WriteU32(uint32 address, uint32 value) - { - Write(address, value); - } - - INLINE void WriteU24(uint32 address, uint32 value) - { - if(!big_endian) - { - WriteU8(address + 0, value >> 0); - WriteU8(address + 1, value >> 8); - WriteU8(address + 2, value >> 16); - } - else - { - WriteU8(address + 0, value >> 16); - WriteU8(address + 1, value >> 8); - WriteU8(address + 2, value >> 0); - } - } -}; - -#endif diff --git a/psx/octoshock/psx/mdec.cpp b/psx/octoshock/psx/mdec.cpp deleted file mode 100644 index 52028ee12e4..00000000000 --- a/psx/octoshock/psx/mdec.cpp +++ /dev/null @@ -1,886 +0,0 @@ -/******************************************************************************/ -/* Mednafen Sony PS1 Emulation Module */ -/******************************************************************************/ -/* mdec.cpp: -** Copyright (C) 2011-2016 Mednafen Team -** -** 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., -** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#pragma GCC optimize ("unroll-loops") - -/* - MDEC_READ_FIFO(tfr) vs InCounter vs MDEC_DMACanRead() is a bit fragile right now. Actually, the entire horrible state machine monstrosity is fragile. - - TODO: OutFIFOReady, so <16bpp works right. - - TODO CODE: - - bool InFIFOReady; - - if(InFIFO.CanWrite()) - { - InFIFO.Write(V); - - if(InCommand) - { - if(InCounter != 0xFFFF) - { - InCounter--; - - // This condition when InFIFO.CanWrite() != 0 is a bit buggy on real hardware, decoding loop *seems* to be reading too - // much and pulling garbage from the FIFO. - if(InCounter == 0xFFFF) - InFIFOReady = true; - } - - if(InFIFO.CanWrite() == 0) - InFIFOReady = true; - } - } -*/ - -// Good test-case games: -// Dragon Knight 4(bad disc?) -// Final Fantasy 7 intro movie. -// GameShark Version 4.0 intro movie; (clever) abuse of DMA channel 0. -// SimCity 2000 startup. - - -#include - -#include "psx.h" -#include "mdec.h" -#include "FastFIFO.h" -#include "math_ops.h" - -#include "masmem.h" - -#if defined(__SSE2__) || (defined(ARCH_X86) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9))) -#include -#include -#endif - -#if 0 //defined(HAVE_NEON_INTRINSICS) -#include -#endif - -#if defined(HAVE_ALTIVEC_INTRINSICS) && defined(HAVE_ALTIVEC_H) - #include -#endif - -#ifndef MDFN_ALIGN -#define MDFN_ALIGN(n) __attribute__ ((aligned (n))) -#endif - -namespace MDFN_IEN_PSX -{ - -static int32 ClockCounter; -static unsigned MDRPhase; -static FastFIFO InFIFO; -static FastFIFO OutFIFO; - -static int8 block_y[8][8]; -static int8 block_cb[8][8]; // [y >> 1][x >> 1] -static int8 block_cr[8][8]; // [y >> 1][x >> 1] - -static uint32 Control; -static uint32 Command; -static bool InCommand; - -static uint8 QMatrix[2][64]; -static uint32 QMIndex; - -static EW_VAR_ALIGN(16) int16 IDCTMatrix[64]; -static uint32 IDCTMIndex; - -static uint8 QScale; - -static EW_VAR_ALIGN(16) int16 Coeff[64]; -static uint32 CoeffIndex; -static uint32 DecodeWB; - -static union -{ - uint32 pix32[48]; - uint16 pix16[96]; - uint8 pix8[192]; -} PixelBuffer; -static uint32 PixelBufferReadOffset; -static uint32 PixelBufferCount32; - -static uint16 InCounter; - -static uint8 RAMOffsetY; -static uint8 RAMOffsetCounter; -static uint8 RAMOffsetWWS; - -static const uint8 ZigZag[64] = -{ - 0x00, 0x08, 0x01, 0x02, 0x09, 0x10, 0x18, 0x11, - 0x0a, 0x03, 0x04, 0x0b, 0x12, 0x19, 0x20, 0x28, - 0x21, 0x1a, 0x13, 0x0c, 0x05, 0x06, 0x0d, 0x14, - 0x1b, 0x22, 0x29, 0x30, 0x38, 0x31, 0x2a, 0x23, - 0x1c, 0x15, 0x0e, 0x07, 0x0f, 0x16, 0x1d, 0x24, - 0x2b, 0x32, 0x39, 0x3a, 0x33, 0x2c, 0x25, 0x1e, - 0x17, 0x1f, 0x26, 0x2d, 0x34, 0x3b, 0x3c, 0x35, - 0x2e, 0x27, 0x2f, 0x36, 0x3d, 0x3e, 0x37, 0x3f, -}; - -void MDEC_Power(void) -{ - ClockCounter = 0; - MDRPhase = 0; - - InFIFO.Flush(); - OutFIFO.Flush(); - - memset(block_y, 0, sizeof(block_y)); - memset(block_cb, 0, sizeof(block_cb)); - memset(block_cr, 0, sizeof(block_cr)); - - Control = 0; - Command = 0; - InCommand = false; - - memset(QMatrix, 0, sizeof(QMatrix)); - QMIndex = 0; - - memset(IDCTMatrix, 0, sizeof(IDCTMatrix)); - IDCTMIndex = 0; - - QScale = 0; - - memset(Coeff, 0, sizeof(Coeff)); - CoeffIndex = 0; - DecodeWB = 0; - - memset(PixelBuffer.pix32, 0, sizeof(PixelBuffer.pix32)); - PixelBufferReadOffset = 0; - PixelBufferCount32 = 0; - - InCounter = 0; - - RAMOffsetY = 0; - RAMOffsetCounter = 0; - RAMOffsetWWS = 0; -} - -template void MDEC_SyncState(EW::NewState *ns) -{ - NSS(ClockCounter); - NSS(MDRPhase); - - SSS(InFIFO); - SSS(OutFIFO); - - NSS(block_y); - NSS(block_cb); - NSS(block_cr); - - NSS(Control); - NSS(Command); - NSS(InCommand); - - NSS(QMatrix); - NSS(QMIndex); - - NSS(IDCTMatrix); - NSS(IDCTMIndex); - - NSS(QScale); - - NSS(Coeff); - NSS(CoeffIndex); - NSS(DecodeWB); - - NSS(PixelBuffer); - NSS(PixelBufferReadOffset); - NSS(PixelBufferCount32); - - NSS(InCounter); - - NSS(RAMOffsetY); - NSS(RAMOffsetCounter); - NSS(RAMOffsetWWS); - - if(isReader) - { - PixelBufferCount32 %= (sizeof(PixelBuffer.pix32) / sizeof(PixelBuffer.pix32[0])) + 1; - } -} - -void MDEC_SyncState(bool isReader, EW::NewState *ns) -{ - if(isReader) MDEC_SyncState(ns); - else MDEC_SyncState(ns); -} - -static INLINE int8 Mask9ClampS8(int32 v) -{ - v = sign_x_to_s32(9, v); - - if(v < -128) - v = -128; - - if(v > 127) - v = 127; - - return v; -} - -//////////////////////// -// -// -#pragma GCC push_options - -#if defined(__SSE2__) || (defined(ARCH_X86) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9))) -// -// -// -#pragma GCC target("sse2") -template -static INLINE void IDCT_1D_Multi(int16 *in_coeff, T *out_coeff) -{ - for(unsigned col = 0; col < 8; col++) - { - __m128i c = _mm_load_si128((__m128i *)&in_coeff[(col * 8)]); - - for(unsigned x = 0; x < 8; x++) - { - __m128i sum; - __m128i m; - alignas(16) int32 tmp[4]; - - m = _mm_load_si128((__m128i *)&IDCTMatrix[(x * 8)]); - sum = _mm_madd_epi16(m, c); - sum = _mm_add_epi32(sum, _mm_shuffle_epi32(sum, (3 << 0) | (2 << 2) | (1 << 4) | (0 << 6))); - sum = _mm_add_epi32(sum, _mm_shuffle_epi32(sum, (1 << 0) | (0 << 2))); - - //_mm_store_ss((float *)&tmp[0], (__m128)sum); - _mm_store_si128((__m128i*)tmp, sum); - - if(sizeof(T) == 1) - out_coeff[(col * 8) + x] = Mask9ClampS8((tmp[0] + 0x4000) >> 15); - else - out_coeff[(x * 8) + col] = (tmp[0] + 0x4000) >> 15; - } - } -} -// -// -// -#elif 0 //defined(HAVE_NEON_INTRINSICS) -// -// -// -template -static INLINE void IDCT_1D_Multi(int16 *in_coeff, T *out_coeff) -{ - for(unsigned col = 0; col < 8; col++) - { - register int16x4_t c0 = vld1_s16(MDFN_ASSUME_ALIGNED(in_coeff + col * 8 + 0, sizeof(int16x4_t))); - register int16x4_t c1 = vld1_s16(MDFN_ASSUME_ALIGNED(in_coeff + col * 8 + 4, sizeof(int16x4_t))); - int32 buf[8]; - - for(unsigned x = 0; x < 8; x++) - { - register int32x4_t accum; - register int32x2_t sum2; - - accum = vdupq_n_s32(0); - accum = vmlal_s16(accum, c0, vld1_s16(MDFN_ASSUME_ALIGNED(IDCTMatrix + x * 8 + 0, sizeof(int16x4_t)))); - accum = vmlal_s16(accum, c1, vld1_s16(MDFN_ASSUME_ALIGNED(IDCTMatrix + x * 8 + 4, sizeof(int16x4_t)))); - sum2 = vadd_s32(vget_high_s32(accum), vget_low_s32(accum)); - sum2 = vpadd_s32(sum2, sum2); - vst1_lane_s32(buf + x, sum2, 0); - } - - for(unsigned x = 0; x < 8; x++) - { - if(sizeof(T) == 1) - out_coeff[(col * 8) + x] = Mask9ClampS8((buf[x] + 0x4000) >> 15); - else - out_coeff[(x * 8) + col] = (buf[x] + 0x4000) >> 15; - } - } -} -// -// -// -#else -// -// -// -template -static INLINE void IDCT_1D_Multi(int16 *in_coeff, T *out_coeff) -{ - for(unsigned col = 0; col < 8; col++) - { - for(unsigned x = 0; x < 8; x++) - { - int32 sum = 0; - - for(unsigned u = 0; u < 8; u++) - { - sum += (in_coeff[(col * 8) + u] * IDCTMatrix[(x * 8) + u]); - } - - if(sizeof(T) == 1) - out_coeff[(col * 8) + x] = Mask9ClampS8((sum + 0x4000) >> 15); - else - out_coeff[(x * 8) + col] = (sum + 0x4000) >> 15; - } - } -} -// -// -// -#endif - -static NO_INLINE void IDCT(int16 *in_coeff, int8 *out_coeff) -{ - alignas(16) int16 tmpbuf[64]; - - IDCT_1D_Multi(in_coeff, tmpbuf); - IDCT_1D_Multi(tmpbuf, out_coeff); -} -#pragma GCC pop_options -// -// -/////////////////////// - -static INLINE void YCbCr_to_RGB(const int8 y, const int8 cb, const int8 cr, int &r, int &g, int &b) -{ - // - // The formula for green is still a bit off(precision/rounding issues when both cb and cr are non-zero). - // - - r = Mask9ClampS8(y + (((359 * cr) + 0x80) >> 8)); - //g = Mask9ClampS8(y + (((-88 * cb) + (-183 * cr) + 0x80) >> 8)); - g = Mask9ClampS8(y + ((((-88 * cb) &~ 0x1F) + ((-183 * cr) &~ 0x07) + 0x80) >> 8)); - b = Mask9ClampS8(y + (((454 * cb) + 0x80) >> 8)); - - r ^= 0x80; - g ^= 0x80; - b ^= 0x80; -} - -static INLINE uint16 RGB_to_RGB555(uint8 r, uint8 g, uint8 b) -{ - r = (r + 4) >> 3; - g = (g + 4) >> 3; - b = (b + 4) >> 3; - - if(r > 0x1F) - r = 0x1F; - - if(g > 0x1F) - g = 0x1F; - - if(b > 0x1F) - b = 0x1F; - - return((r << 0) | (g << 5) | (b << 10)); -} - -static void EncodeImage(const unsigned ybn) -{ - //printf("ENCODE, %d\n", (Command & 0x08000000) ? 256 : 384); - - PixelBufferCount32 = 0; - - switch((Command >> 27) & 0x3) - { - case 0: // 4bpp - { - const uint8 us_xor = (Command & (1U << 26)) ? 0x00 : 0x88; - uint8* pix_out = PixelBuffer.pix8; - - for(int y = 0; y < 8; y++) - { - for(int x = 0; x < 8; x += 2) - { - uint8 p0 = std::min(127, block_y[y][x + 0] + 8); - uint8 p1 = std::min(127, block_y[y][x + 1] + 8); - - *pix_out = ((p0 >> 4) | (p1 & 0xF0)) ^ us_xor; - pix_out++; - } - } - PixelBufferCount32 = 8; - } - break; - - - case 1: // 8bpp - { - const uint8 us_xor = (Command & (1U << 26)) ? 0x00 : 0x80; - uint8* pix_out = PixelBuffer.pix8; - - for(int y = 0; y < 8; y++) - { - for(int x = 0; x < 8; x++) - { - *pix_out = (uint8)block_y[y][x] ^ us_xor; - pix_out++; - } - } - PixelBufferCount32 = 16; - } - break; - - case 2: // 24bpp - { - const uint8 rgb_xor = (Command & (1U << 26)) ? 0x80 : 0x00; - uint8* pix_out = PixelBuffer.pix8; - - for(int y = 0; y < 8; y++) - { - const int8* by = &block_y[y][0]; - const int8* cb = &block_cb[(y >> 1) | ((ybn & 2) << 1)][(ybn & 1) << 2]; - const int8* cr = &block_cr[(y >> 1) | ((ybn & 2) << 1)][(ybn & 1) << 2]; - - for(int x = 0; x < 8; x++) - { - int r, g, b; - - YCbCr_to_RGB(by[x], cb[x >> 1], cr[x >> 1], r, g, b); - - pix_out[0] = r ^ rgb_xor; - pix_out[1] = g ^ rgb_xor; - pix_out[2] = b ^ rgb_xor; - pix_out += 3; - } - } - PixelBufferCount32 = 48; - } - break; - - case 3: // 16bpp - { - uint16 pixel_xor = ((Command & 0x02000000) ? 0x8000 : 0x0000) | ((Command & (1U << 26)) ? 0x4210 : 0x0000); - uint16* pix_out = PixelBuffer.pix16; - - for(int y = 0; y < 8; y++) - { - const int8* by = &block_y[y][0]; - const int8* cb = &block_cb[(y >> 1) | ((ybn & 2) << 1)][(ybn & 1) << 2]; - const int8* cr = &block_cr[(y >> 1) | ((ybn & 2) << 1)][(ybn & 1) << 2]; - - for(int x = 0; x < 8; x++) - { - int r, g, b; - - YCbCr_to_RGB(by[x], cb[x >> 1], cr[x >> 1], r, g, b); - - MDFN_en16lsb(pix_out, pixel_xor ^ RGB_to_RGB555(r, g, b)); - pix_out++; - } - } - PixelBufferCount32 = 32; - } - break; - - } -} - -static INLINE void WriteImageData(uint16 V, int32* eat_cycles) -{ - const uint32 qmw = (bool)(DecodeWB < 2); - - //printf("MDEC DMA SubWrite: %04x, %d\n", V, CoeffIndex); - - if(!CoeffIndex) - { - if(V == 0xFE00) - { - //printf("FE00 @ %u\n", DecodeWB); - return; - } - - QScale = V >> 10; - - { - int q = QMatrix[qmw][0]; // No QScale here! - int ci = sign_10_to_s16(V & 0x3FF); - int tmp; - - if(q != 0) - tmp = (int32)((uint32)(ci * q) << 4) + (ci ? ((ci < 0) ? 8 : -8) : 0); - else - tmp = (uint32)(ci * 2) << 4; - - // Not sure if it should be 0x3FFF or 0x3FF0 or maybe 0x3FF8? - Coeff[ZigZag[0]] = std::min(0x3FFF, std::max(-0x4000, tmp)); - CoeffIndex++; - } - } - else - { - if(V == 0xFE00) - { - while(CoeffIndex < 64) - Coeff[ZigZag[CoeffIndex++]] = 0; - } - else - { - uint32 rlcount = V >> 10; - - for(uint32 i = 0; i < rlcount && CoeffIndex < 64; i++) - { - Coeff[ZigZag[CoeffIndex]] = 0; - CoeffIndex++; - } - - if(CoeffIndex < 64) - { - int q = QScale * QMatrix[qmw][CoeffIndex]; - int ci = sign_10_to_s16(V & 0x3FF); - int tmp; - - if(q != 0) - tmp = (int32)((uint32)((ci * q) >> 3) << 4) + (ci ? ((ci < 0) ? 8 : -8) : 0); - else - tmp = (uint32)(ci * 2) << 4; - - // Not sure if it should be 0x3FFF or 0x3FF0 or maybe 0x3FF8? - Coeff[ZigZag[CoeffIndex]] = std::min(0x3FFF, std::max(-0x4000, tmp)); - CoeffIndex++; - } - } - } - - if(CoeffIndex == 64) - { - CoeffIndex = 0; - - //printf("Block %d finished\n", DecodeWB); - - switch(DecodeWB) - { - case 0: IDCT(Coeff, MDAP(block_cr)); break; - case 1: IDCT(Coeff, MDAP(block_cb)); break; - case 2: IDCT(Coeff, MDAP(block_y)); break; - case 3: IDCT(Coeff, MDAP(block_y)); break; - case 4: IDCT(Coeff, MDAP(block_y)); break; - case 5: IDCT(Coeff, MDAP(block_y)); break; - } - - // Timing in the PS1 MDEC is complex due to (apparent) pipelining, but the average when decoding a large number of blocks is - // about 512. - *eat_cycles += 512; - - if(DecodeWB >= 2) - { - EncodeImage((DecodeWB + 4) % 6); - } - - DecodeWB++; - if(DecodeWB == (((Command >> 27) & 2) ? 6 : 3)) - { - DecodeWB = ((Command >> 27) & 2) ? 0 : 2; - } - } -} - -#if 1 - -// -// -// -#define MDEC_WAIT_COND(n) { case __COUNTER__: if(!(n)) { MDRPhase = __COUNTER__ - MDRPhaseBias - 1; return; } } - -#define MDEC_WRITE_FIFO(n) { MDEC_WAIT_COND(OutFIFO.CanWrite()); OutFIFO.Write(n); } -#define MDEC_READ_FIFO(n) { MDEC_WAIT_COND(InFIFO.CanRead()); n = InFIFO.Read(); } -#define MDEC_EAT_CLOCKS(n) { ClockCounter -= (n); MDEC_WAIT_COND(ClockCounter > 0); } - -MDFN_FASTCALL void MDEC_Run(int32 clocks) -{ - static const unsigned MDRPhaseBias = __COUNTER__ + 1; - - //MDFN_DispMessage("%u", OutFIFO.CanRead()); - - ClockCounter += clocks; - - if(ClockCounter > 128) - { - //if(MDRPhase != 0) - // printf("SNORT: %d\n", ClockCounter); - ClockCounter = 128; - } - - switch(MDRPhase + MDRPhaseBias) - { - for(;;) - { - InCommand = false; - MDEC_READ_FIFO(Command); // This must be the first MDEC_* macro used! - InCommand = true; - MDEC_EAT_CLOCKS(1); - - //printf("****************** Command: %08x, %02x\n", Command, Command >> 29); - - // - // - // - if(((Command >> 29) & 0x7) == 1) - { - InCounter = Command & 0xFFFF; - OutFIFO.Flush(); - //OutBuffer.Flush(); - - PixelBufferCount32 = 0; - CoeffIndex = 0; - - if((Command >> 27) & 2) - DecodeWB = 0; - else - DecodeWB = 2; - - switch((Command >> 27) & 0x3) - { - case 0: - case 1: RAMOffsetWWS = 0; break; - case 2: RAMOffsetWWS = 6; break; - case 3: RAMOffsetWWS = 4; break; - } - RAMOffsetY = 0; - RAMOffsetCounter = RAMOffsetWWS; - - InCounter--; - do - { - uint32 tfr; - int32 need_eat; // = 0; - - MDEC_READ_FIFO(tfr); - InCounter--; - -// printf("KA: %04x %08x\n", InCounter, tfr); - - need_eat = 0; - PixelBufferCount32 = 0; - WriteImageData(tfr, &need_eat); - WriteImageData(tfr >> 16, &need_eat); - - MDEC_EAT_CLOCKS(need_eat); - - PixelBufferReadOffset = 0; - while(PixelBufferReadOffset < PixelBufferCount32) - { - MDEC_WRITE_FIFO((MDFN_de32lsb(&PixelBuffer.pix32[PixelBufferReadOffset++]))); - } - } while(InCounter != 0xFFFF); - } - // - // - // - else if(((Command >> 29) & 0x7) == 2) - { - QMIndex = 0; - InCounter = 0x10 + ((Command & 0x1) ? 0x10 : 0x00); - - InCounter--; - do - { - uint32 tfr; - - MDEC_READ_FIFO(tfr); - InCounter--; - - //printf("KA: %04x %08x\n", InCounter, tfr); - - for(int i = 0; i < 4; i++) - { - QMatrix[QMIndex >> 6][QMIndex & 0x3F] = (uint8)tfr; - QMIndex = (QMIndex + 1) & 0x7F; - tfr >>= 8; - } - } while(InCounter != 0xFFFF); - } - // - // - // - else if(((Command >> 29) & 0x7) == 3) - { - IDCTMIndex = 0; - InCounter = 0x20; - - InCounter--; - do - { - uint32 tfr; - - MDEC_READ_FIFO(tfr); - InCounter--; - - for(unsigned i = 0; i < 2; i++) - { - IDCTMatrix[((IDCTMIndex & 0x7) << 3) | ((IDCTMIndex >> 3) & 0x7)] = (int16)(tfr & 0xFFFF) >> 3; - IDCTMIndex = (IDCTMIndex + 1) & 0x3F; - - tfr >>= 16; - } - } while(InCounter != 0xFFFF); - } - else - { - InCounter = Command & 0xFFFF; - } - } // end for(;;) - } -} -#endif - -MDFN_FASTCALL void MDEC_DMAWrite(uint32 V) -{ - if(InFIFO.CanWrite()) - { - InFIFO.Write(V); - MDEC_Run(0); - } - else - { - PSX_DBG(PSX_DBG_WARNING, "[MDEC] DMA write when input FIFO is full!!\n"); - } -} - -MDFN_FASTCALL uint32 MDEC_DMARead(uint32* offs) -{ - uint32 V = 0; - - *offs = 0; - - if(MDFN_LIKELY(OutFIFO.CanRead())) - { - V = OutFIFO.Read(); - - *offs = (RAMOffsetY & 0x7) * RAMOffsetWWS; - - if(RAMOffsetY & 0x08) - { - *offs = (*offs - RAMOffsetWWS*7); - } - - RAMOffsetCounter--; - if(!RAMOffsetCounter) - { - RAMOffsetCounter = RAMOffsetWWS; - RAMOffsetY++; - } - - MDEC_Run(0); - } - else - { - PSX_DBG(PSX_DBG_WARNING, "[MDEC] DMA read when output FIFO is empty!\n"); - } - - return(V); -} - -bool MDEC_DMACanWrite(void) -{ - return((InFIFO.CanWrite() >= 0x20) && (Control & (1U << 30)) && InCommand && InCounter != 0xFFFF); -} - -bool MDEC_DMACanRead(void) -{ - return((OutFIFO.CanRead() >= 0x20) && (Control & (1U << 29))); -} - -MDFN_FASTCALL void MDEC_Write(const pscpu_timestamp_t timestamp, uint32 A, uint32 V) -{ - //PSX_WARNING("[MDEC] Write: 0x%08x 0x%08x, %d --- %u %u", A, V, timestamp, InFIFO.CanRead(), OutFIFO.CanRead()); - if(A & 4) - { - if(V & 0x80000000) // Reset? - { - MDRPhase = 0; - InCounter = 0; - Command = 0; - InCommand = false; - - PixelBufferCount32 = 0; - ClockCounter = 0; - QMIndex = 0; - IDCTMIndex = 0; - - QScale = 0; - - memset(Coeff, 0, sizeof(Coeff)); - CoeffIndex = 0; - DecodeWB = 0; - - InFIFO.Flush(); - OutFIFO.Flush(); - } - Control = V & 0x7FFFFFFF; - } - else - { - if(InFIFO.CanWrite()) - { - InFIFO.Write(V); - - if(!InCommand) - { - if(ClockCounter < 1) - ClockCounter = 1; - } - MDEC_Run(0); - } - else - { - PSX_DBG(PSX_DBG_WARNING, "MDEC manual write FIFO overflow?!\n"); - } - } -} - -MDFN_FASTCALL uint32 MDEC_Read(const pscpu_timestamp_t timestamp, uint32 A) -{ - uint32 ret = 0; - - if(A & 4) - { - ret = 0; - - ret |= (OutFIFO.CanRead() == 0) << 31; - ret |= (InFIFO.CanWrite() == 0) << 30; - ret |= InCommand << 29; - - ret |= MDEC_DMACanWrite() << 28; - ret |= MDEC_DMACanRead() << 27; - - ret |= ((Command >> 25) & 0xF) << 23; - - // Needs refactoring elsewhere to work right: ret |= ((DecodeWB + 4) % 6) << 16; - - ret |= InCounter & 0xFFFF; - } - else - { - if(OutFIFO.CanRead()) - ret = OutFIFO.Read(); - } - - //PSX_WARNING("[MDEC] Read: 0x%08x 0x%08x -- %d %d", A, ret, InputBuffer.CanRead(), InCounter); - - return(ret); -} - -} diff --git a/psx/octoshock/psx/mdec.h b/psx/octoshock/psx/mdec.h deleted file mode 100644 index 9e9ef01787b..00000000000 --- a/psx/octoshock/psx/mdec.h +++ /dev/null @@ -1,44 +0,0 @@ -/******************************************************************************/ -/* Mednafen Sony PS1 Emulation Module */ -/******************************************************************************/ -/* mdec.h: -** Copyright (C) 2011-2016 Mednafen Team -** -** 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., -** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef __MDFN_PSX_MDEC_H -#define __MDFN_PSX_MDEC_H - -namespace MDFN_IEN_PSX -{ - -MDFN_FASTCALL void MDEC_DMAWrite(uint32 V); - -MDFN_FASTCALL uint32 MDEC_DMARead(uint32* offs); - -MDFN_FASTCALL void MDEC_Write(const pscpu_timestamp_t timestamp, uint32 A, uint32 V); -MDFN_FASTCALL uint32 MDEC_Read(const pscpu_timestamp_t timestamp, uint32 A); - - -void MDEC_Power(void) MDFN_COLD; - -bool MDEC_DMACanWrite(void); -bool MDEC_DMACanRead(void); -MDFN_FASTCALL void MDEC_Run(int32 clocks); - -} - -#endif diff --git a/psx/octoshock/psx/psx.cpp b/psx/octoshock/psx/psx.cpp deleted file mode 100644 index e7ab6b2f3fc..00000000000 --- a/psx/octoshock/psx/psx.cpp +++ /dev/null @@ -1,2862 +0,0 @@ -/******************************************************************************/ -/* Mednafen Sony PS1 Emulation Module */ -/******************************************************************************/ -/* psx.cpp: -** Copyright (C) 2011-2017 Mednafen Team -** -** 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., -** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "octoshock.h" -#include "psx.h" -#include "mdec.h" -#include "frontio.h" -#include "timer.h" -#include "sio.h" -#include "cdc.h" -#include "Stream.h" -#include "spu.h" -#include "error.h" -#include "tests.h" -#include "endian.h" -#include "emuware/EW_state.h" - -#include "input/dualshock.h" -#include "input/dualanalog.h" -#include "input/negcon.h" -#include "input/gamepad.h" -#include "input/memcard.h" -#include "input/multitap.h" - -#include -#include -#include - -//I apologize for the absolute madness of the resolution management and framebuffer management and normalizing in here. -//It's grown entirely out of control. The main justification for the original design was not wrecking mednafen internals too much. - -//we're a bit sloppy right now.. use this to make sure theres adequate room for double-sizing a 400px wide screen -#define FB_WIDTH 800 -#define FB_HEIGHT 576 - -#define kScanlineWidthHeuristicIndex 64 - -//extern MDFNGI EmulatedPSX; - -int16 soundbuf[1024 * 1024]; //how big? big enough. -int VTBackBuffer = 0; -bool GpuFrameForLag = false; -static MDFN_Rect VTDisplayRects[2]; -#include "video/Deinterlacer.h" -static bool PrevInterlaced; -static Deinterlacer deint; -static EmulateSpecStruct espec; - -template inline void reconstruct(T* t) { - t->~T(); - new(t) T(); -} -template inline void reconstruct(T* t, A a) { - t->~T(); - new(t) T(a); -} - -namespace MDFN_IEN_PSX -{ - - -#if PSX_DBGPRINT_ENABLE -static unsigned psx_dbg_level = 0; - -void PSX_DBG_BIOS_PUTC(uint8 c) noexcept -{ - if(psx_dbg_level >= PSX_DBG_BIOS_PRINT) - { - if(c == 0x1B) - return; - - fputc(c, stdout); - - //if(c == '\n') - //{ - // fputc('%', stdout); - // fputc(' ', stdout); - //} - fflush(stdout); - } -} - -void PSX_DBG(unsigned level, const char *format, ...) noexcept -{ - if(psx_dbg_level >= level) - { - va_list ap; - - va_start(ap, format); - - trio_vprintf(format, ap); - - va_end(ap); - } -} -#else -static unsigned const psx_dbg_level = 0; -#endif - - -struct MDFN_PseudoRNG // Based off(but not the same as) public-domain "JKISS" PRNG. -{ - MDFN_COLD MDFN_PseudoRNG() - { - ResetState(); - } - - uint32 RandU32(void) - { - uint64 t; - - x = 314527869 * x + 1234567; - y ^= y << 5; y ^= y >> 7; y ^= y << 22; - t = 4294584393ULL * z + c; c = t >> 32; z = t; - lcgo = (19073486328125ULL * lcgo) + 1; - - return (x + y + z) ^ (lcgo >> 16); - } - - uint32 RandU32(uint32 mina, uint32 maxa) - { - const uint32 range_m1 = maxa - mina; - uint32 range_mask; - uint32 tmp; - - range_mask = range_m1; - range_mask |= range_mask >> 1; - range_mask |= range_mask >> 2; - range_mask |= range_mask >> 4; - range_mask |= range_mask >> 8; - range_mask |= range_mask >> 16; - - do - { - tmp = RandU32() & range_mask; - } while(tmp > range_m1); - - return(mina + tmp); - } - - MDFN_COLD void ResetState(void) // Must always reset to the same state. - { - x = 123456789; - y = 987654321; - z = 43219876; - c = 6543217; - lcgo = 0xDEADBEEFCAFEBABEULL; - } - - uint32 x,y,z,c; - uint64 lcgo; -}; - -static MDFN_PseudoRNG PSX_PRNG; - -uint32 PSX_GetRandU32(uint32 mina, uint32 maxa) -{ - return PSX_PRNG.RandU32(mina, maxa); -} - -static std::vector *cdifs = NULL; -static std::vector cdifs_scex_ids; - -static uint64 Memcard_PrevDC[8]; -static int64 Memcard_SaveDelay[8]; - -PS_CPU *CPU = NULL; -PS_SPU *SPU = NULL; -PS_CDC *CDC = NULL; -FrontIO *FIO = NULL; - -static MultiAccessSizeMem<512 * 1024, false> *BIOSROM = NULL; -static MultiAccessSizeMem<65536, false> *PIOMem = NULL; - -MultiAccessSizeMem<2048 * 1024, false> MainRAM; - -static uint32 TextMem_Start; -static std::vector TextMem; - -static const uint32 SysControl_Mask[9] = { 0x00ffffff, 0x00ffffff, 0xffffffff, 0x2f1fffff, - 0xffffffff, 0x2f1fffff, 0x2f1fffff, 0xffffffff, - 0x0003ffff }; - -static const uint32 SysControl_OR[9] = { 0x1f000000, 0x1f000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000 }; - -static struct -{ - union - { - struct - { - uint32 PIO_Base; // 0x1f801000 // BIOS Init: 0x1f000000, Writeable bits: 0x00ffffff(assumed, verify), FixedOR = 0x1f000000 - uint32 Unknown0; // 0x1f801004 // BIOS Init: 0x1f802000, Writeable bits: 0x00ffffff, FixedOR = 0x1f000000 - uint32 Unknown1; // 0x1f801008 // BIOS Init: 0x0013243f, ???? - uint32 Unknown2; // 0x1f80100c // BIOS Init: 0x00003022, Writeable bits: 0x2f1fffff, FixedOR = 0x00000000 - - uint32 BIOS_Mapping; // 0x1f801010 // BIOS Init: 0x0013243f, ???? - uint32 SPU_Delay; // 0x1f801014 // BIOS Init: 0x200931e1, Writeable bits: 0x2f1fffff, FixedOR = 0x00000000 - Affects bus timing on access to SPU - uint32 CDC_Delay; // 0x1f801018 // BIOS Init: 0x00020843, Writeable bits: 0x2f1fffff, FixedOR = 0x00000000 - uint32 Unknown4; // 0x1f80101c // BIOS Init: 0x00070777, ???? - uint32 Unknown5; // 0x1f801020 // BIOS Init: 0x00031125(but rewritten with other values often), Writeable bits: 0x0003ffff, FixedOR = 0x00000000 -- Possibly CDC related - }; - uint32 Regs[9]; - }; -} SysControl; - -static unsigned DMACycleSteal = 0; // Doesn't need to be saved in save states, since it's recalculated in the ForceEventUpdates() call chain. - -void PSX_SetDMACycleSteal(unsigned stealage) -{ - if(stealage > 200) // Due to 8-bit limitations in the CPU core. - stealage = 200; - - DMACycleSteal = stealage; -} - - -// -// Event stuff -// - -static pscpu_timestamp_t Running; // Set to -1 when not desiring exit, and 0 when we are. - -struct event_list_entry -{ - uint32 which; - pscpu_timestamp_t event_time; - event_list_entry *prev; - event_list_entry *next; -}; - -static event_list_entry events[PSX_EVENT__COUNT]; - -static void EventReset(void) -{ - for(unsigned i = 0; i < PSX_EVENT__COUNT; i++) - { - events[i].which = i; - - if(i == PSX_EVENT__SYNFIRST) - events[i].event_time = (int32)0x80000000; - else if(i == PSX_EVENT__SYNLAST) - events[i].event_time = 0x7FFFFFFF; - else - events[i].event_time = PSX_EVENT_MAXTS; - - events[i].prev = (i > 0) ? &events[i - 1] : NULL; - events[i].next = (i < (PSX_EVENT__COUNT - 1)) ? &events[i + 1] : NULL; - } -} - -//static void RemoveEvent(event_list_entry *e) -//{ -// e->prev->next = e->next; -// e->next->prev = e->prev; -//} - -static void RebaseTS(const pscpu_timestamp_t timestamp) -{ - for(unsigned i = 0; i < PSX_EVENT__COUNT; i++) - { - if(i == PSX_EVENT__SYNFIRST || i == PSX_EVENT__SYNLAST) - continue; - - assert(events[i].event_time > timestamp); - events[i].event_time -= timestamp; - } - - CPU->SetEventNT(events[PSX_EVENT__SYNFIRST].next->event_time); -} - -void PSX_SetEventNT(const int type, const pscpu_timestamp_t next_timestamp) -{ - event_list_entry *e = &events[type]; - - if(next_timestamp < e->event_time) - { - event_list_entry *fe = e; - - do - { - fe = fe->prev; - } - while(next_timestamp < fe->event_time); - - // Remove this event from the list, temporarily of course. - e->prev->next = e->next; - e->next->prev = e->prev; - - // Insert into the list, just after "fe". - e->prev = fe; - e->next = fe->next; - fe->next->prev = e; - fe->next = e; - - e->event_time = next_timestamp; - } - else if(next_timestamp > e->event_time) - { - event_list_entry *fe = e; - - do - { - fe = fe->next; - } while(next_timestamp > fe->event_time); - - // Remove this event from the list, temporarily of course - e->prev->next = e->next; - e->next->prev = e->prev; - - // Insert into the list, just BEFORE "fe". - e->prev = fe->prev; - e->next = fe; - fe->prev->next = e; - fe->prev = e; - - e->event_time = next_timestamp; - } - - CPU->SetEventNT(events[PSX_EVENT__SYNFIRST].next->event_time & Running); -} - -// Called from debug.cpp too. -void ForceEventUpdates(const pscpu_timestamp_t timestamp) -{ - PSX_SetEventNT(PSX_EVENT_GPU, GPU_Update(timestamp)); - PSX_SetEventNT(PSX_EVENT_CDC, CDC->Update(timestamp)); - - PSX_SetEventNT(PSX_EVENT_TIMER, TIMER_Update(timestamp)); - - PSX_SetEventNT(PSX_EVENT_DMA, DMA_Update(timestamp)); - - PSX_SetEventNT(PSX_EVENT_FIO, FIO->Update(timestamp)); - - CPU->SetEventNT(events[PSX_EVENT__SYNFIRST].next->event_time); -} - -bool MDFN_FASTCALL PSX_EventHandler(const pscpu_timestamp_t timestamp) -{ - event_list_entry *e = events[PSX_EVENT__SYNFIRST].next; - - while(timestamp >= e->event_time) // If Running = 0, PSX_EventHandler() may be called even if there isn't an event per-se, so while() instead of do { ... } while - { - event_list_entry *prev = e->prev; - pscpu_timestamp_t nt; - - switch(e->which) - { - default: abort(); - - case PSX_EVENT_GPU: - nt = GPU_Update(e->event_time); - break; - - case PSX_EVENT_CDC: - nt = CDC->Update(e->event_time); - break; - - case PSX_EVENT_TIMER: - nt = TIMER_Update(e->event_time); - break; - - case PSX_EVENT_DMA: - nt = DMA_Update(e->event_time); - break; - - case PSX_EVENT_FIO: - nt = FIO->Update(e->event_time); - break; - } -#if PSX_EVENT_SYSTEM_CHECKS - assert(nt > e->event_time); -#endif - - PSX_SetEventNT(e->which, nt); - - // Order of events can change due to calling PSX_SetEventNT(), this prev business ensures we don't miss an event due to reordering. - e = prev->next; - } - - return(Running); -} - - -void PSX_RequestMLExit(void) -{ - Running = 0; - CPU->SetEventNT(0); -} - - -// -// End event stuff -// - -// Remember to update MemPeek<>() and MemPoke<>() when we change address decoding in MemRW() -template static INLINE void MemRW(pscpu_timestamp_t ×tamp, uint32 A, uint32 &V) -{ - #if 0 - if(IsWrite) - printf("Write%d: %08x(orig=%08x), %08x\n", (int)(sizeof(T) * 8), A & mask[A >> 29], A, V); - else - printf("Read%d: %08x(orig=%08x)\n", (int)(sizeof(T) * 8), A & mask[A >> 29], A); - #endif - - if(!IsWrite) - timestamp += DMACycleSteal; - - if(A < 0x00800000) - { - if(IsWrite) - { - //timestamp++; // Best-case timing. - } - else - { - timestamp += 3; - } - - if(Access24) - { - if(IsWrite) - MainRAM.WriteU24(A & 0x1FFFFF, V); - else - V = MainRAM.ReadU24(A & 0x1FFFFF); - } - else - { - if(IsWrite) - MainRAM.Write(A & 0x1FFFFF, V); - else - V = MainRAM.Read(A & 0x1FFFFF); - } - - return; - } - - if(A >= 0x1FC00000 && A <= 0x1FC7FFFF) - { - if(!IsWrite) - { - if(Access24) - V = BIOSROM->ReadU24(A & 0x7FFFF); - else - V = BIOSROM->Read(A & 0x7FFFF); - } - - return; - } - - if(timestamp >= events[PSX_EVENT__SYNFIRST].next->event_time) - PSX_EventHandler(timestamp); - - if(A >= 0x1F801000 && A <= 0x1F802FFF) - { - //if(IsWrite) - // printf("HW Write%d: %08x %08x\n", (unsigned int)(sizeof(T)*8), (unsigned int)A, (unsigned int)V); - //else - // printf("HW Read%d: %08x\n", (unsigned int)(sizeof(T)*8), (unsigned int)A); - - if(A >= 0x1F801C00 && A <= 0x1F801FFF) // SPU - { - if(sizeof(T) == 4 && !Access24) - { - if(IsWrite) - { - //timestamp += 15; - - //if(timestamp >= events[PSX_EVENT__SYNFIRST].next->event_time) - // PSX_EventHandler(timestamp); - - SPU->Write(timestamp, A | 0, V); - SPU->Write(timestamp, A | 2, V >> 16); - } - else - { - timestamp += 36; - - if(timestamp >= events[PSX_EVENT__SYNFIRST].next->event_time) - PSX_EventHandler(timestamp); - - V = SPU->Read(timestamp, A); - V |= SPU->Read(timestamp, A | 2) << 16; - } - } - else - { - if(IsWrite) - { - //timestamp += 8; - - //if(timestamp >= events[PSX_EVENT__SYNFIRST].next->event_time) - // PSX_EventHandler(timestamp); - - SPU->Write(timestamp, A & ~1, V); - } - else - { - timestamp += 16; // Just a guess, need to test. - - if(timestamp >= events[PSX_EVENT__SYNFIRST].next->event_time) - PSX_EventHandler(timestamp); - - V = SPU->Read(timestamp, A & ~1); - } - } - return; - } // End SPU - - - // CDC: TODO - 8-bit access. - if(A >= 0x1f801800 && A <= 0x1f80180F) - { - if(!IsWrite) - { - timestamp += 6 * sizeof(T); //24; - } - - if(IsWrite) - CDC->Write(timestamp, A & 0x3, V); - else - V = CDC->Read(timestamp, A & 0x3); - - return; - } - - if(A >= 0x1F801810 && A <= 0x1F801817) - { - if(!IsWrite) - timestamp++; - - if(IsWrite) - GPU_Write(timestamp, A, V); - else - V = GPU_Read(timestamp, A); - - return; - } - - if(A >= 0x1F801820 && A <= 0x1F801827) - { - if(!IsWrite) - timestamp++; - - if(IsWrite) - MDEC_Write(timestamp, A, V); - else - V = MDEC_Read(timestamp, A); - - return; - } - - if(A >= 0x1F801000 && A <= 0x1F801023) - { - unsigned index = (A & 0x1F) >> 2; - - if(!IsWrite) - timestamp++; - - //if(A == 0x1F801014 && IsWrite) - // fprintf(stderr, "%08x %08x\n",A,V); - - if(IsWrite) - { - V <<= (A & 3) * 8; - SysControl.Regs[index] = V & SysControl_Mask[index]; - } - else - { - V = SysControl.Regs[index] | SysControl_OR[index]; - V >>= (A & 3) * 8; - } - return; - } - - if(A >= 0x1F801040 && A <= 0x1F80104F) - { - if(!IsWrite) - timestamp++; - - if(IsWrite) - FIO->Write(timestamp, A, V); - else - V = FIO->Read(timestamp, A); - return; - } - - if(A >= 0x1F801050 && A <= 0x1F80105F) - { - if(!IsWrite) - timestamp++; - -#if 0 - if(IsWrite) - { - PSX_WARNING("[SIO] Write: 0x%08x 0x%08x %u", A, V, (unsigned)sizeof(T)); - } - else - { - PSX_WARNING("[SIO] Read: 0x%08x", A); - } -#endif - - if(IsWrite) - SIO_Write(timestamp, A, V); - else - V = SIO_Read(timestamp, A); - return; - } - -#if 0 - if(A >= 0x1F801060 && A <= 0x1F801063) - { - if(IsWrite) - { - - } - else - { - - } - - return; - } -#endif - - if(A >= 0x1F801070 && A <= 0x1F801077) // IRQ - { - if(!IsWrite) - timestamp++; - - if(IsWrite) - IRQ_Write(A, V); - else - V = IRQ_Read(A); - return; - } - - if(A >= 0x1F801080 && A <= 0x1F8010FF) // DMA - { - if(!IsWrite) - timestamp++; - - if(IsWrite) - DMA_Write(timestamp, A, V); - else - V = DMA_Read(timestamp, A); - - return; - } - - if(A >= 0x1F801100 && A <= 0x1F80113F) // Root counters - { - if(!IsWrite) - timestamp++; - - if(IsWrite) - TIMER_Write(timestamp, A, V); - else - V = TIMER_Read(timestamp, A); - - return; - } - } - - - if(A >= 0x1F000000 && A <= 0x1F7FFFFF) - { - if(!IsWrite) - { - //if((A & 0x7FFFFF) <= 0x84) - //PSX_WARNING("[PIO] Read%d from 0x%08x at time %d", (int)(sizeof(T) * 8), A, timestamp); - - V = ~0U; // A game this affects: Tetris with Cardcaptor Sakura - - if(PIOMem) - { - if((A & 0x7FFFFF) < 65536) - { - if(Access24) - V = PIOMem->ReadU24(A & 0x7FFFFF); - else - V = PIOMem->Read(A & 0x7FFFFF); - } - else if((A & 0x7FFFFF) < (65536 + TextMem.size())) - { - if(Access24) - V = MDFN_de24lsb(&TextMem[(A & 0x7FFFFF) - 65536]); - else switch(sizeof(T)) - { - case 1: V = TextMem[(A & 0x7FFFFF) - 65536]; break; - case 2: V = MDFN_de16lsb(&TextMem[(A & 0x7FFFFF) - 65536]); break; - case 4: V = MDFN_de32lsb(&TextMem[(A & 0x7FFFFF) - 65536]); break; - } - } - } - } - return; - } - - if(A == 0xFFFE0130) // Per tests on PS1, ignores the access(sort of, on reads the value is forced to 0 if not aligned) if not aligned to 4-bytes. - { - if(!IsWrite) - V = CPU->GetBIU(); - else - CPU->SetBIU(V); - - return; - } - - if(IsWrite) - { - PSX_WARNING("[MEM] Unknown write%d to %08x at time %d, =%08x(%d)", (int)(sizeof(T) * 8), A, timestamp, V, V); - } - else - { - V = 0; - PSX_WARNING("[MEM] Unknown read%d from %08x at time %d", (int)(sizeof(T) * 8), A, timestamp); - } -} - -void MDFN_FASTCALL PSX_MemWrite8(pscpu_timestamp_t timestamp, uint32 A, uint32 V) -{ - MemRW(timestamp, A, V); -} - -void MDFN_FASTCALL PSX_MemWrite16(pscpu_timestamp_t timestamp, uint32 A, uint32 V) -{ - MemRW(timestamp, A, V); -} - -void MDFN_FASTCALL PSX_MemWrite24(pscpu_timestamp_t timestamp, uint32 A, uint32 V) -{ - MemRW(timestamp, A, V); -} - -void MDFN_FASTCALL PSX_MemWrite32(pscpu_timestamp_t timestamp, uint32 A, uint32 V) -{ - MemRW(timestamp, A, V); -} - -uint8 MDFN_FASTCALL PSX_MemRead8(pscpu_timestamp_t ×tamp, uint32 A) -{ - uint32 V; - - MemRW(timestamp, A, V); - - return(V); -} - -uint16 MDFN_FASTCALL PSX_MemRead16(pscpu_timestamp_t ×tamp, uint32 A) -{ - uint32 V; - - MemRW(timestamp, A, V); - - return(V); -} - -uint32 MDFN_FASTCALL PSX_MemRead24(pscpu_timestamp_t ×tamp, uint32 A) -{ - uint32 V; - - MemRW(timestamp, A, V); - - return(V); -} - -uint32 MDFN_FASTCALL PSX_MemRead32(pscpu_timestamp_t ×tamp, uint32 A) -{ - uint32 V; - - MemRW(timestamp, A, V); - - return(V); -} - -template static INLINE uint32 MemPeek(pscpu_timestamp_t timestamp, uint32 A) -{ - if(A < 0x00800000) - { - if(Access24) - return(MainRAM.ReadU24(A & 0x1FFFFF)); - else - return(MainRAM.Read(A & 0x1FFFFF)); - } - - if(A >= 0x1FC00000 && A <= 0x1FC7FFFF) - { - if(Access24) - return(BIOSROM->ReadU24(A & 0x7FFFF)); - else - return(BIOSROM->Read(A & 0x7FFFF)); - } - - if(A >= 0x1F801000 && A <= 0x1F802FFF) - { - if(A >= 0x1F801C00 && A <= 0x1F801FFF) // SPU - { - // TODO - - } // End SPU - - - // CDC: TODO - 8-bit access. - if(A >= 0x1f801800 && A <= 0x1f80180F) - { - // TODO - - } - - if(A >= 0x1F801810 && A <= 0x1F801817) - { - // TODO - - } - - if(A >= 0x1F801820 && A <= 0x1F801827) - { - // TODO - - } - - if(A >= 0x1F801000 && A <= 0x1F801023) - { - unsigned index = (A & 0x1F) >> 2; - return((SysControl.Regs[index] | SysControl_OR[index]) >> ((A & 3) * 8)); - } - - if(A >= 0x1F801040 && A <= 0x1F80104F) - { - // TODO - - } - - if(A >= 0x1F801050 && A <= 0x1F80105F) - { - // TODO - - } - - - if(A >= 0x1F801070 && A <= 0x1F801077) // IRQ - { - // TODO - - } - - if(A >= 0x1F801080 && A <= 0x1F8010FF) // DMA - { - // TODO - - } - - if(A >= 0x1F801100 && A <= 0x1F80113F) // Root counters - { - // TODO - - } - } - - - if(A >= 0x1F000000 && A <= 0x1F7FFFFF) - { - if(PIOMem) - { - if((A & 0x7FFFFF) < 65536) - { - if(Access24) - return(PIOMem->ReadU24(A & 0x7FFFFF)); - else - return(PIOMem->Read(A & 0x7FFFFF)); - } - else if((A & 0x7FFFFF) < (65536 + TextMem.size())) - { - if(Access24) - return(MDFN_de24lsb(&TextMem[(A & 0x7FFFFF) - 65536])); - else switch(sizeof(T)) - { - case 1: return(TextMem[(A & 0x7FFFFF) - 65536]); break; - case 2: return(MDFN_de16lsb(&TextMem[(A & 0x7FFFFF) - 65536])); break; - case 4: return(MDFN_de32lsb(&TextMem[(A & 0x7FFFFF) - 65536])); break; - } - } - } - return(~0U); - } - - if(A == 0xFFFE0130) - return CPU->GetBIU(); - - return(0); -} - -uint8 PSX_MemPeek8(uint32 A) -{ - return MemPeek(0, A); -} - -uint16 PSX_MemPeek16(uint32 A) -{ - return MemPeek(0, A); -} - -uint32 PSX_MemPeek32(uint32 A) -{ - return MemPeek(0, A); -} - -template static INLINE void MemPoke(pscpu_timestamp_t timestamp, uint32 A, T V) -{ - if(A < 0x00800000) - { - if(Access24) - MainRAM.WriteU24(A & 0x1FFFFF, V); - else - MainRAM.Write(A & 0x1FFFFF, V); - - return; - } - - if(A >= 0x1FC00000 && A <= 0x1FC7FFFF) - { - if(Access24) - BIOSROM->WriteU24(A & 0x7FFFF, V); - else - BIOSROM->Write(A & 0x7FFFF, V); - - return; - } - - if(A >= 0x1F801000 && A <= 0x1F802FFF) - { - if(A >= 0x1F801000 && A <= 0x1F801023) - { - unsigned index = (A & 0x1F) >> 2; - SysControl.Regs[index] = (V << ((A & 3) * 8)) & SysControl_Mask[index]; - return; - } - } - - if(A == 0xFFFE0130) - { - CPU->SetBIU(V); - return; - } -} - -void PSX_MemPoke8(uint32 A, uint8 V) -{ - MemPoke(0, A, V); -} - -void PSX_MemPoke16(uint32 A, uint16 V) -{ - MemPoke(0, A, V); -} - -void PSX_MemPoke32(uint32 A, uint32 V) -{ - MemPoke(0, A, V); -} - -static void PSX_Power(bool powering_up) -{ - PSX_PRNG.ResetState(); // Should occur first! - - memset(MainRAM.data8, 0, 2048 * 1024); - - for(unsigned i = 0; i < 9; i++) - SysControl.Regs[i] = 0; - - CPU->Power(); - - EventReset(); - - TIMER_Power(); - - DMA_Power(); - - FIO->Reset(powering_up); - SIO_Power(); - - MDEC_Power(); - CDC->Power(); - GPU_Power(); - //SPU->Power(); // Called from CDC->Power() - IRQ_Power(); - - ForceEventUpdates(0); - - deint.ClearState(); -} - - -void PSX_GPULineHook(const pscpu_timestamp_t timestamp, const pscpu_timestamp_t line_timestamp, bool vsync, uint32 *pixels, const MDFN_PixelFormat* const format, const unsigned width, const unsigned pix_clock_offset, const unsigned pix_clock, const unsigned pix_clock_divider) -{ - FIO->GPULineHook(timestamp, line_timestamp, vsync, pixels, format, width, pix_clock_offset, pix_clock, pix_clock_divider); -} - -} - -using namespace MDFN_IEN_PSX; - -struct ShockConfig -{ - //// multires is a hint that, if set, indicates that the system has fairly programmable video modes(particularly, the ability - //// to display multiple horizontal resolutions, such as the PCE, PC-FX, or Genesis). In practice, it will cause the driver - //// code to set the linear interpolation on by default. (TRUE for psx) - //// lcm_width and lcm_height are the least common multiples of all possible - //// resolutions in the frame buffer as specified by DisplayRect/LineWidths(Ex for PCE: widths of 256, 341.333333, 512, - //// lcm = 1024) - //// nominal_width and nominal_height specify the resolution that Mednafen should display - //// the framebuffer image in at 1x scaling, scaled from the dimensions of DisplayRect, and optionally the LineWidths array - //// passed through espec to the Emulate() function. - //int lcm_width; - //int lcm_height; - //int nominal_width; - //int nominal_height; - int fb_width; // Width of the framebuffer(not necessarily width of the image). MDFN_Surface width should be >= this. - int fb_height; // Height of the framebuffer passed to the Emulate() function(not necessarily height of the image) - - //last used render options - ShockRenderOptions opts; -} s_ShockConfig; - - -struct ShockState -{ - bool power; - bool eject; -} s_ShockState; - - -struct ShockPeripheral -{ - ePeripheralType type = ePeripheralType_None; - u8 buffer[32]; //must be larger than 16+3+1 or thereabouts because the dualshock writes some rumble data into it. bleck, ill fix it later - //TODO: test for multitap. does it need to be as large as 4 of whatever the single largest port would be? - //well, it must manage its own stuff.. its not like we feed in external data, right? - InputDevice* device = nullptr; - - ~ShockPeripheral() - { - //do not do this! FIO takes care of finishing this off - //I know, it's all a mess - //delete device; - } -}; - -static int addressToPortNum(int address) -{ - int portnum = SHOCK_INVALID_ADDRESS; - //WHY did I choose 1 indexed? I dunno, let's roll with it - if (address == 0x01) portnum = 0; - else if (address == 0x02) portnum = 1; - else if (address == 0x11) portnum = 2; - else if (address == 0x21) portnum = 3; - else if (address == 0x31) portnum = 4; - else if (address == 0x41) portnum = 5; - else if (address == 0x12) portnum = 6; - else if (address == 0x22) portnum = 7; - else if (address == 0x32) portnum = 8; - else if (address == 0x42) portnum = 9; - return portnum; -} - -struct { - - //"This is kind of redundant with the frontIO code, and should be merged with it eventually, when the configurability gets more advanced" - //I dunno. - - std::array ports; - - void Initialize() - { - reconstruct(&ports); - for(int i=0;i<10;i++) - memset(ports[i].buffer,0,sizeof(ports[i].buffer)); - reconstruct(FIO); - } - - //TODO: "Take care to call ->Power() only if the device actually changed." - //(like, is this about savestates? seems silly" - s32 Connect(s32 address, s32 type) - { - int portnum = addressToPortNum(address); - if(portnum == SHOCK_INVALID_ADDRESS) return SHOCK_INVALID_ADDRESS; - - //check whats already there - if(ports[portnum].type == ePeripheralType_None && type == ePeripheralType_None) return SHOCK_OK; //NOP - if(ports[portnum].type != ePeripheralType_None && type != ePeripheralType_None) return SHOCK_NOCANDO; //cant re-connect something without disconnecting first - - //disconnecting: - if(type == ePeripheralType_None) { - ports[portnum].type = ePeripheralType_None; - memset(ports[portnum].buffer,0,sizeof(ports[portnum].buffer)); - - //fall through to setup a nonexistent `next` for disconnecting, instead of returning now - } - - //connecting: - InputDevice* next = nullptr; - switch(type) - { - case ePeripheralType_Pad: next = Device_Gamepad_Create(); break; - case ePeripheralType_DualShock: next = Device_DualShock_Create(); break; - case ePeripheralType_DualAnalog: next = Device_DualAnalog_Create(false); break; - case ePeripheralType_Multitap: next = new InputDevice_Multitap(); break; - case ePeripheralType_NegCon: next = Device_neGcon_Create(); break; - case ePeripheralType_None: next = new InputDevice(); break; //dummy - break; - default: - return SHOCK_ERROR; - } - ports[portnum].type = (ePeripheralType)type; - if(ports[portnum].device) delete ports[portnum].device; - ports[portnum].device = next; - memset(ports[portnum].buffer,0,sizeof(ports[portnum].buffer)); - - if (portnum == 0 || portnum == 1) - { - FIO->Ports[portnum] = next; - FIO->PortData[portnum] = ports[portnum].buffer; - } - else { - //must be multitap child device - int portidx = (address & 0xF) - 1; - int subidx = (address >> 4) - 1; - auto tap = (InputDevice_Multitap*)FIO->Ports[portidx]; - auto mcdummy = new InputDevice(); - //next-> - tap->SetSubDevice(subidx, next, mcdummy); - } - - return SHOCK_OK; - } - - s32 PollActive(s32 address, bool clear) - { - int portnum = addressToPortNum(address); - if (portnum == SHOCK_INVALID_ADDRESS) return SHOCK_INVALID_ADDRESS; - - s32 ret = SHOCK_FALSE; - - u8* buf = ports[portnum].buffer; - switch(ports[portnum].type) - { - case ePeripheralType_DualShock: - { - IO_Dualshock* io_dualshock = (IO_Dualshock*)buf; - if(io_dualshock->active) ret = SHOCK_TRUE; - if(clear) io_dualshock->active = 0; - return ret; - break; - } - case ePeripheralType_DualAnalog: - { - IO_DualAnalog* io_dualanalog = (IO_DualAnalog*)buf; - if(io_dualanalog->active) ret = SHOCK_TRUE; - if(clear) io_dualanalog->active = 0; - return ret; - break; - } - case ePeripheralType_Pad: - { - IO_Gamepad* io_gamepad = (IO_Gamepad*)buf; - if(io_gamepad->active) ret = SHOCK_TRUE; - if(clear) io_gamepad->active = 0; - return ret; - break; - } - case ePeripheralType_NegCon: - { - IO_NegCon* io_negcon = (IO_NegCon*)buf; - if (io_negcon->active) ret = SHOCK_TRUE; - if (clear) io_negcon->active = 0; - return ret; - break; - } - - case ePeripheralType_None: - return SHOCK_NOCANDO; - - default: - return SHOCK_ERROR; - } - } - - s32 SetPadInput(s32 address, u32 buttons, u8 left_x, u8 left_y, u8 right_x, u8 right_y) - { - int portnum = addressToPortNum(address); - if (portnum == SHOCK_INVALID_ADDRESS) return SHOCK_INVALID_ADDRESS; - - u8* buf = ports[portnum].buffer; - switch(ports[portnum].type) - { - case ePeripheralType_DualShock: - { - IO_Dualshock* io_dualshock = (IO_Dualshock*)buf; - io_dualshock->buttons[0] = (buttons>>0)&0xFF; - io_dualshock->buttons[1] = (buttons>>8)&0xFF; - io_dualshock->buttons[2] = (buttons>>16)&0xFF; //this is only the analog mode button - io_dualshock->right_x = right_x; - io_dualshock->right_y = right_y; - io_dualshock->left_x = left_x; - io_dualshock->left_y = left_y; - return SHOCK_OK; - } - case ePeripheralType_Pad: - { - IO_Gamepad* io_gamepad = (IO_Gamepad*)buf; - io_gamepad->buttons[0] = (buttons>>0)&0xFF; - io_gamepad->buttons[1] = (buttons>>8)&0xFF; - return SHOCK_OK; - } - case ePeripheralType_DualAnalog: - { - IO_DualAnalog* io_dualanalog = (IO_DualAnalog*)buf; - io_dualanalog->buttons[0] = (buttons>>0)&0xFF; - io_dualanalog->buttons[1] = (buttons>>8)&0xFF; - io_dualanalog->right_x = right_x; - io_dualanalog->right_y = right_y; - io_dualanalog->left_x = left_x; - io_dualanalog->left_y = left_y; - return SHOCK_OK; - } - case ePeripheralType_NegCon: - { - IO_NegCon* io_negcon = (IO_NegCon*)buf; - io_negcon->buttons[0] = (buttons >> 0) & 0xFF; - io_negcon->buttons[1] = (buttons >> 8) & 0xFF; - io_negcon->twist = left_x; - io_negcon->anabuttons[0] = left_y; - io_negcon->anabuttons[1] = right_x; - io_negcon->anabuttons[2] = right_y; - return SHOCK_OK; - } - - default: - return SHOCK_ERROR; - } - } - - s32 MemcardTransact(s32 address, ShockMemcardTransaction* transaction) - { - int portnum = addressToPortNum(address); - if (portnum == SHOCK_INVALID_ADDRESS) return SHOCK_INVALID_ADDRESS; - - //TODO - once we get flexible here, do some extra condition checks.. whether memcards exist, etc. much like devices. - switch(transaction->transaction) - { - case eShockMemcardTransaction_Connect: - //cant connect when a memcard is already connected - if(!strcmp(FIO->MCPorts[portnum]->GetName(),"InputDevice_Memcard")) - return SHOCK_NOCANDO; - delete FIO->MCPorts[portnum]; //delete dummy - FIO->MCPorts[portnum] = Device_Memcard_Create(); - - case eShockMemcardTransaction_Disconnect: - return SHOCK_ERROR; //not supported yet - - case eShockMemcardTransaction_Write: - FIO->MCPorts[portnum]->WriteNV((uint8*)transaction->buffer128k,0,128*1024); - FIO->MCPorts[portnum]->ResetNVDirtyCount(); - return SHOCK_OK; - - case eShockMemcardTransaction_Read: - { - const u8* ptr = FIO->MCPorts[portnum]->ReadNV(); - memcpy(transaction->buffer128k,ptr,128*1024); - FIO->MCPorts[portnum]->ResetNVDirtyCount(); - return SHOCK_OK; - } - - case eShockMemcardTransaction_CheckDirty: - if(FIO->GetMemcardDirtyCount(portnum)) - return SHOCK_TRUE; - else return SHOCK_FALSE; - - default: - return SHOCK_ERROR; - } - } - - void UpdateInput() - { - for(int i=0;iUpdateInput(ports[i].buffer); - } - } - -} s_ShockPeripheralState; - -EW_EXPORT s32 shock_Peripheral_Connect(void* psx, s32 address, s32 type) -{ - return s_ShockPeripheralState.Connect(address, type); -} - -EW_EXPORT s32 shock_Peripheral_SetPadInput(void* psx, s32 address, u32 buttons, u8 left_x, u8 left_y, u8 right_x, u8 right_y) -{ - return s_ShockPeripheralState.SetPadInput(address, buttons, left_x, left_y, right_x, right_y); -} - -EW_EXPORT s32 shock_Peripheral_PollActive(void* psx, s32 address, s32 clear) -{ - return s_ShockPeripheralState.PollActive(address, clear!=SHOCK_FALSE); -} - -EW_EXPORT s32 shock_Peripheral_MemcardTransact(void* psx, s32 address, ShockMemcardTransaction* transaction) -{ - return s_ShockPeripheralState.MemcardTransact(address, transaction); -} - -static void MountCPUAddressSpace() -{ - for(uint32 ma = 0x00000000; ma < 0x00800000; ma += 2048 * 1024) - { - CPU->SetFastMap(MainRAM.data8, 0x00000000 + ma, 2048 * 1024); - CPU->SetFastMap(MainRAM.data8, 0x80000000 + ma, 2048 * 1024); - CPU->SetFastMap(MainRAM.data8, 0xA0000000 + ma, 2048 * 1024); - } - - CPU->SetFastMap(BIOSROM->data8, 0x1FC00000, 512 * 1024); - CPU->SetFastMap(BIOSROM->data8, 0x9FC00000, 512 * 1024); - CPU->SetFastMap(BIOSROM->data8, 0xBFC00000, 512 * 1024); - - if(PIOMem) - { - CPU->SetFastMap(PIOMem->data8, 0x1F000000, 65536); - CPU->SetFastMap(PIOMem->data8, 0x9F000000, 65536); - CPU->SetFastMap(PIOMem->data8, 0xBF000000, 65536); - } -} - -static MDFN_Surface *VTBuffer[2] = { NULL, NULL }; -static int *VTLineWidths[2] = { NULL, NULL }; -static bool s_FramebufferNormalized; -static bool s_Created; -static int s_FramebufferCurrent; -static int s_FramebufferCurrentWidth; - -EW_EXPORT s32 shock_Create(void** psx, s32 region, void* firmware512k) -{ - #ifdef SHOCK_RUN_TESTS - static bool ranTests = false; - if(!ranTests) - { - ranTests = true; - MDFN_RunMathTests(); - } - #endif - - //TODO - //psx_dbg_level = MDFN_GetSettingUI("psx.dbg_level"); - //DBG_Init(); - - //yeah, we only support a static instance. - //we'll flag whether it's created though - *psx = NULL; - s_Created = true; - - //PIO Mem: why wouldn't we want this? - static const bool WantPIOMem = true; - - BIOSROM = new MultiAccessSizeMem<512 * 1024, false>(); - memcpy(BIOSROM->data8, firmware512k, 512 * 1024); - - if(WantPIOMem) PIOMem = new MultiAccessSizeMem<65536, false>(); - else PIOMem = NULL; - - CPU = new PS_CPU(); - SPU = new PS_SPU(); - GPU_Init(region == REGION_EU); - CDC = new PS_CDC(); - DMA_Init(); - - - //setup gpu output surfaces - MDFN_PixelFormat nf(MDFN_COLORSPACE_RGB, 4, 16, 8, 0, 24); - for(int i=0;i<2;i++) - { - VTBuffer[i] = new MDFN_Surface(NULL, FB_WIDTH, FB_HEIGHT, FB_WIDTH, nf); - VTLineWidths[i] = (int *)calloc(FB_HEIGHT, sizeof(int)); - } - - for(int rc = 0; rc < 0x8000; rc++) - { - const uint8 a = rc; - const uint8 b = rc >> 8; - - (GPU.OutputLUT + 0)[a] = ((a & 0x1F) << (3 + nf.Rshift)) | ((a >> 5) << (3 + nf.Gshift)); - (GPU.OutputLUT + 256)[b] = ((b & 0x3) << (6 + nf.Gshift)) | (((b >> 2) & 0x1F) << (3 + nf.Bshift)); - } - - FIO = new FrontIO(); - s_ShockPeripheralState.Initialize(); - - MountCPUAddressSpace(); - - s_ShockState.power = false; - s_ShockState.eject = false; - - //do we need to do anything particualr with the CDC disc/tray state? survey says... no. - - return SHOCK_OK; -} - -EW_EXPORT s32 shock_Destroy(void* psx) -{ - if(!s_Created) - return SHOCK_NOCANDO; - - s_Created = false; - - for(int i=0;i<2;i++) - { - delete VTBuffer[i]; - VTBuffer[i] = nullptr; - - free(VTLineWidths[i]); - VTLineWidths[i] = nullptr; - } - - TextMem.resize(0); - - if(CDC) - { - delete CDC; - CDC = NULL; - } - - if(SPU) - { - delete SPU; - SPU = NULL; - } - - GPU_Kill(); - - if(CPU) - { - delete CPU; - CPU = NULL; - } - - if(FIO) - { - delete FIO; - FIO = NULL; - } - - DMA_Kill(); - - if(BIOSROM) - { - delete BIOSROM; - BIOSROM = NULL; - } - - if(PIOMem) - { - delete PIOMem; - PIOMem = NULL; - } - - cdifs = NULL; - - return SHOCK_OK; -} - -//Sets the power to ON. It is an error to turn an already-on console ON again -EW_EXPORT s32 shock_PowerOn(void* psx) -{ - if(s_ShockState.power) return SHOCK_NOCANDO; - - s_ShockState.power = true; - PSX_Power(true); - - return SHOCK_OK; -} - -//Triggers a soft reset immediately. Returns SHOCK_NOCANDO if console is powered off. -EW_EXPORT s32 shock_SoftReset(void *psx) -{ - if (!s_ShockState.power) return SHOCK_NOCANDO; - - PSX_Power(false); - - return SHOCK_OK; -} - -//Sets the power to OFF. It is an error to turn an already-off console OFF again -EW_EXPORT s32 shock_PowerOff(void* psx) -{ - if(!s_ShockState.power) return SHOCK_NOCANDO; - - //not supported yet - return SHOCK_ERROR; -} - -EW_EXPORT s32 shock_Step(void* psx, eShockStep step) -{ - //only eShockStep_Frame is supported - - pscpu_timestamp_t timestamp = 0; - - memset(&espec, 0, sizeof(EmulateSpecStruct)); - - espec.VideoFormatChanged = false; - espec.surface = (MDFN_Surface *)VTBuffer[VTBackBuffer]; - espec.LineWidths = (int *)VTLineWidths[VTBackBuffer]; - espec.skip = false; - espec.soundmultiplier = 1.0; - espec.NeedRewind = false; - - espec.MasterCycles = 0; - - espec.SoundBufMaxSize = 1024*1024; - espec.SoundRate = 44100; - espec.SoundBuf = soundbuf; - espec.SoundBufSize = 0; - espec.SoundVolume = 1.0; - - //not sure about this - espec.skip = s_ShockConfig.opts.skip; - - if (s_ShockConfig.opts.deinterlaceMode == eShockDeinterlaceMode_Weave) - deint.SetType(Deinterlacer::DEINT_WEAVE); - if (s_ShockConfig.opts.deinterlaceMode == eShockDeinterlaceMode_Bob) - deint.SetType(Deinterlacer::DEINT_BOB); - if (s_ShockConfig.opts.deinterlaceMode == eShockDeinterlaceMode_BobOffset) - deint.SetType(Deinterlacer::DEINT_BOB_OFFSET); - - //------------------------- - - s_ShockPeripheralState.UpdateInput(); - - //GPU->StartFrame(psf_loader ? NULL : espec); //a reminder that when we do psf, we will be telling the gpu not to draw - GPU_StartFrame(&espec); - - //not that it matters, but we may need to control this at some point - static const int ResampleQuality = 5; - SPU->StartFrame(espec.SoundRate, ResampleQuality); - - GpuFrameForLag = false; - - Running = -1; - timestamp = CPU->Run(timestamp, psx_dbg_level >= PSX_DBG_BIOS_PRINT, /*psf_loader != NULL*/ false); //huh? - assert(timestamp); - - ForceEventUpdates(timestamp); - if(GPU_GetScanlineNum() < 100) - printf("[BUUUUUUUG] Frame timing end glitch; scanline=%u, st=%u\n", GPU_GetScanlineNum(), timestamp); - - espec.SoundBufSize = SPU->EndFrame(espec.SoundBuf); - - CDC->ResetTS(); - TIMER_ResetTS(); - DMA_ResetTS(); - GPU_ResetTS(); - FIO->ResetTS(); - - RebaseTS(timestamp); - - espec.MasterCycles = timestamp; - - //(memcard saving happened here) - - //---------------------- - - VTDisplayRects[VTBackBuffer] = espec.DisplayRect; - - //if interlacing is active, do that processing now - if(espec.InterlaceOn) - { - if(!PrevInterlaced) - deint.ClearState(); - - deint.Process(espec.surface, espec.DisplayRect, espec.LineWidths, espec.InterlaceField); - - PrevInterlaced = true; - - espec.InterlaceOn = false; - espec.InterlaceField = 0; - } - - //new frame, hasnt been normalized - s_FramebufferNormalized = false; - s_FramebufferCurrent = 0; - s_FramebufferCurrentWidth = FB_WIDTH; - - //just in case we debug printed or something like that - fflush(stdout); - fflush(stderr); - - - return SHOCK_OK; -} - -struct FramebufferCropInfo -{ - int width, height, xo, yo; -}; - -static void _shock_AnalyzeFramebufferCropInfo(int fbIndex, FramebufferCropInfo* info) -{ - //presently, except for contrived test programs, it is safe to assume this is the same for the entire frame (no known use by games) - //however, due to the dump_framebuffer, it may be incorrect at scanline 0. so lets use another one for the heuristic here - //you'd think we could use FirstLine instead of kScanlineWidthHeuristicIndex, but sometimes it hasnt been set (screen off) so it's confusing - int width = VTLineWidths[fbIndex][kScanlineWidthHeuristicIndex]; - int height = espec.DisplayRect.h; - int yo = espec.DisplayRect.y; - - //fix a common error here from disabled screens (?) - //I think we're lucky in selecting these lines kind of randomly. need a better plan. - if (width <= 0) width = VTLineWidths[fbIndex][0]; - - if (s_ShockConfig.opts.renderType == eShockRenderType_Framebuffer) - { - //printf("%d %d %d %d | %d | %d\n",yo,height, GPU->GetVertStart(), GPU->GetVertEnd(), espec.DisplayRect.y, GPU->FirstLine); - - height = GPU.GetVertEnd() - GPU.GetVertStart(); - yo = GPU.FirstLine; - - if (espec.DisplayRect.h == 288 || espec.DisplayRect.h == 240) - { - } - else - { - height *= 2; - //only return even scanlines to avoid bouncing the interlacing - if (yo & 1) yo--; - } - - //this can happen when the display turns on mid-frame - //maybe an off by one error here..? - if (yo + height >= espec.DisplayRect.h) - yo = espec.DisplayRect.h - height; - - //sometimes when changing modes we have trouble..? - if (yo<0) yo = 0; - } - - info->width = width; - info->height = height; - info->xo = 0; - info->yo = yo; -} - - -//`normalizes` the framebuffer to 700x480 (or 800x576 for PAL) by pixel doubling and wrecking the AR a little bit as needed -void NormalizeFramebuffer() -{ - //mednafen's advised solution for smooth gaming: "scale the output width to z * nominal_width, and the output height to z * nominal_height, where nominal_width and nominal_height are members of the MDFNGI struct" - //IOW, mednafen's strategy is to put everything in a 320x240 and scale it up 3x to 960x720 by default (which is adequate to contain the largest PSX framebuffer of 700x480) - - //psxtech says horizontal resolutions can be: 256, 320, 512, 640, 368 pixels - //mednafen will turn those into 2800/{ 10, 8, 5, 4, 7 } -> 280,350,560,700,400 - //additionally with the crop options we can cut it down by 160/X -> { 16, 20, 32, 40, 22 } -> { 264, 330, 528, 660, 378 } - //this means our virtual area for doubling is no longer 800 but 756 - - //heres my strategy: - //try to do the smart thing, try to get aspect ratio near the right value - //intended AR = 320/240 = 1.3333 - //280x240 - ok (AR 1.1666666666666666666666666666667) - //350x240 - ok (AR 1.4583333333333333333333333333333) - //400x240 - ok (AR 1.6666666666666666666666666666667) - //560x240 - scale vertically by 2 = 560x480 ~ 280x240 - //700x240 - scale vertically by 2 = 700x480 ~ 350x240 - //280x480 - scale horizontally by 2 = 560x480 ~ 280x240 - //350x480 - scale horizontally by 2 = 700x480 ~ 350x240 - //400x480 - scale horizontally by 2 = 800x480 ~ 400x240 - //560x480 - ok ~ 280x240 - //700x480 - ok ~ 350x240 - - //NOTE: this approach is very redundant with the displaymanager AR tracking stuff - //however, it will help us avoid stressing the displaymanager (for example, a 700x240 will freak it out kind of. we could send it a much more sensible 700x480) - - //always fetch description - FramebufferCropInfo cropInfo; - _shock_AnalyzeFramebufferCropInfo(0, &cropInfo); - int width = cropInfo.width; - int height = cropInfo.height; - - int virtual_width = 800; - int virtual_height = 480; - if (GPU.HardwarePALType) - virtual_height = 576; - - if (s_ShockConfig.opts.renderType == eShockRenderType_ClipOverscan) - virtual_width = 756; - if (s_ShockConfig.opts.renderType == eShockRenderType_Framebuffer) - { - //not quite sure what to here yet - //virtual_width = width * 2; ? - virtual_width = 736; - } - - int xs=1,ys=1; - - //I. as described above - //if(width == 280 && height == 240) {} - //if(width == 350 && height == 240) {} - //if(width == 400 && height == 240) {} - //if(width == 560 && height == 240) ys=2; - //if(width == 700 && height == 240) ys=2; - //if(width == 280 && height == 480) xs=2; - //if(width == 350 && height == 480) xs=2; - //if(width == 400 && height == 480) xs=2; - //if(width == 560 && height == 480) {} - //if(width == 700 && height == 480) {} - - //II. as the snes 'always double size framebuffer'. I think thats a better idea, and we already have the concept - //ORIGINALLY (as of r8528 when PAL support was added) a threshold of 276 was used. I'm not sure where that came from. - //288 seems to be a more correct value? (it's the typical PAL half resolution, corresponding to 240 for NTSC) - //maybe I meant to type 576, but that doesnt make sense--the height can't exceed that. - if(width <= 400 && height <= 288) xs=ys=2; - if(width > 400 && height <= 288) ys=2; - if(width <= 400 && height > 288) xs=2; - if(width > 400 && height > 288) {} - - //TODO - shrink it entirely if cropping. EDIT-any idea what this means? if you figure it out, just do it. - - int xm = (virtual_width - width*xs) / 2; - int ym = (virtual_height - height*ys) / 2; - - int curr = 0; - - //1. double the height, while cropping down - if(height != virtual_height) - { - uint32* src = VTBuffer[curr]->pixels + (s_FramebufferCurrentWidth * (espec.DisplayRect.y + cropInfo.yo)) + espec.DisplayRect.x; //? - uint32* dst = VTBuffer[curr^1]->pixels; - int tocopy = width*4; - - //float from top as needed - memset(dst, 0, ym*tocopy); - dst += width * ym; - - if(ys==2) - { - for(int y=0;ypixels + (s_ShockConfig.fb_width*espec.DisplayRect.y) + espec.DisplayRect.x; - uint32* dst = VTBuffer[curr^1]->pixels; - - for(int y=0;yflags & eShockFramebufferFlags_Normalize) - if(!s_FramebufferNormalized) - { - NormalizeFramebuffer(); - s_FramebufferNormalized = true; - } - - int fbIndex = s_FramebufferCurrent; - - //always fetch description - FramebufferCropInfo cropInfo; - _shock_AnalyzeFramebufferCropInfo(fbIndex, &cropInfo); - int width = cropInfo.width; - int height = cropInfo.height; - int yo = cropInfo.yo; - - //sloppy, but the above AnalyzeFramebufferCropInfo() will give us too short of a buffer - if(fb->flags & eShockFramebufferFlags_Normalize) - { - height = espec.DisplayRect.h; - yo = 0; - } - - fb->width = width; - fb->height = height; - - //is that all we needed? - if(fb->ptr == NULL) - { - return SHOCK_OK; - } - - //maybe we need to output the framebuffer - //do a raster loop and copy it to the target - uint32* src = VTBuffer[fbIndex]->pixels + (s_FramebufferCurrentWidth*yo) + espec.DisplayRect.x; - uint32* dst = (u32*)fb->ptr; - int tocopy = width*4; - for(int y=0;y(&data[0x10]); - SP = MDFN_de32lsb(&data[0x30]); - TextStart = MDFN_de32lsb(&data[0x18]); - TextSize = MDFN_de32lsb(&data[0x1C]); - - if(ignore_pcsp) - printf("TextStart=0x%08x\nTextSize=0x%08x\n", TextStart, TextSize); - else - printf("PC=0x%08x\nSP=0x%08x\nTextStart=0x%08x\nTextSize=0x%08x\n", PC, SP, TextStart, TextSize); - - TextStart &= 0x1FFFFF; - - if(TextSize > 2048 * 1024) - { - throw(MDFN_Error(0, "Text section too large")); - } - - if(TextSize > (size - 0x800)) - throw(MDFN_Error(0, "Text section recorded size is larger than data available in file. Header=0x%08x, Available=0x%08x", TextSize, size - 0x800)); - - if(TextSize < (size - 0x800)) - throw(MDFN_Error(0, "Text section recorded size is smaller than data available in file. Header=0x%08x, Available=0x%08x", TextSize, size - 0x800)); - - if(!TextMem.size()) - { - TextMem_Start = TextStart; - TextMem.resize(TextSize); - } - - if(TextStart < TextMem_Start) - { - uint32 old_size = TextMem.size(); - - //printf("RESIZE: 0x%08x\n", TextMem_Start - TextStart); - - TextMem.resize(old_size + TextMem_Start - TextStart); - memmove(&TextMem[TextMem_Start - TextStart], &TextMem[0], old_size); - - TextMem_Start = TextStart; - } - - if(TextMem.size() < (TextStart - TextMem_Start + TextSize)) - TextMem.resize(TextStart - TextMem_Start + TextSize); - - memcpy(&TextMem[TextStart - TextMem_Start], data + 0x800, TextSize); - - - // - // - // - - // BIOS patch - BIOSROM->WriteU32(0x6990, (3 << 26) | ((0xBF001000 >> 2) & ((1 << 26) - 1))); -// BIOSROM->WriteU32(0x691C, (3 << 26) | ((0xBF001000 >> 2) & ((1 << 26) - 1))); - -// printf("INSN: 0x%08x\n", BIOSROM->ReadU32(0x6990)); -// exit(1); - uint8 *po; - - po = &PIOMem->data8[0x0800]; - - MDFN_en32lsb(po, (0x0 << 26) | (31 << 21) | (0x8 << 0)); // JR - po += 4; - MDFN_en32lsb(po, 0); // NOP(kinda) - po += 4; - - po = &PIOMem->data8[0x1000]; - - // Load cacheable-region target PC into r2 - MDFN_en32lsb(po, (0xF << 26) | (0 << 21) | (1 << 16) | (0x9F001010 >> 16)); // LUI - po += 4; - MDFN_en32lsb(po, (0xD << 26) | (1 << 21) | (2 << 16) | (0x9F001010 & 0xFFFF)); // ORI - po += 4; - - // Jump to r2 - MDFN_en32lsb(po, (0x0 << 26) | (2 << 21) | (0x8 << 0)); // JR - po += 4; - MDFN_en32lsb(po, 0); // NOP(kinda) - po += 4; - - // - // 0x9F001010: - // - - // Load source address into r8 - uint32 sa = 0x9F000000 + 65536; - MDFN_en32lsb(po, (0xF << 26) | (0 << 21) | (1 << 16) | (sa >> 16)); // LUI - po += 4; - MDFN_en32lsb(po, (0xD << 26) | (1 << 21) | (8 << 16) | (sa & 0xFFFF)); // ORI - po += 4; - - // Load dest address into r9 - MDFN_en32lsb(po, (0xF << 26) | (0 << 21) | (1 << 16) | (TextMem_Start >> 16)); // LUI - po += 4; - MDFN_en32lsb(po, (0xD << 26) | (1 << 21) | (9 << 16) | (TextMem_Start & 0xFFFF)); // ORI - po += 4; - - // Load size into r10 - MDFN_en32lsb(po, (0xF << 26) | (0 << 21) | (1 << 16) | (TextMem.size() >> 16)); // LUI - po += 4; - MDFN_en32lsb(po, (0xD << 26) | (1 << 21) | (10 << 16) | (TextMem.size() & 0xFFFF)); // ORI - po += 4; - - // - // Loop begin - // - - MDFN_en32lsb(po, (0x24 << 26) | (8 << 21) | (1 << 16)); // LBU to r1 - po += 4; - - MDFN_en32lsb(po, (0x08 << 26) | (10 << 21) | (10 << 16) | 0xFFFF); // Decrement size - po += 4; - - MDFN_en32lsb(po, (0x28 << 26) | (9 << 21) | (1 << 16)); // SB from r1 - po += 4; - - MDFN_en32lsb(po, (0x08 << 26) | (8 << 21) | (8 << 16) | 0x0001); // Increment source addr - po += 4; - - MDFN_en32lsb(po, (0x05 << 26) | (0 << 21) | (10 << 16) | (-5 & 0xFFFF)); - po += 4; - MDFN_en32lsb(po, (0x08 << 26) | (9 << 21) | (9 << 16) | 0x0001); // Increment dest addr - po += 4; - - // - // Loop end - // - - // Load SP into r29 - if(ignore_pcsp) - { - po += 16; - } - else - { - MDFN_en32lsb(po, (0xF << 26) | (0 << 21) | (1 << 16) | (SP >> 16)); // LUI - po += 4; - MDFN_en32lsb(po, (0xD << 26) | (1 << 21) | (29 << 16) | (SP & 0xFFFF)); // ORI - po += 4; - - // Load PC into r2 - MDFN_en32lsb(po, (0xF << 26) | (0 << 21) | (1 << 16) | ((PC >> 16) | 0x8000)); // LUI - po += 4; - MDFN_en32lsb(po, (0xD << 26) | (1 << 21) | (2 << 16) | (PC & 0xFFFF)); // ORI - po += 4; - } - - // Half-assed instruction cache flush. ;) - for(unsigned i = 0; i < 1024; i++) - { - MDFN_en32lsb(po, 0); - po += 4; - } - - - - // Jump to r2 - MDFN_en32lsb(po, (0x0 << 26) | (2 << 21) | (0x8 << 0)); // JR - po += 4; - MDFN_en32lsb(po, 0); // NOP(kinda) - po += 4; -} - -EW_EXPORT s32 shock_MountEXE(void* psx, void* exebuf, s32 size, s32 ignore_pcsp) -{ - LoadEXE((uint8*)exebuf, (uint32)size, !!ignore_pcsp); - return SHOCK_OK; -} - -EW_EXPORT s32 shock_CreateDisc(ShockDiscRef** outDisc, void *Opaque, s32 lbaCount, ShockDisc_ReadTOC ReadTOC, ShockDisc_ReadLBA ReadLBA2448, bool suppliesDeinterleavedSubcode) -{ - *outDisc = new ShockDiscRef(Opaque, lbaCount, ReadTOC, ReadLBA2448, suppliesDeinterleavedSubcode); - return SHOCK_OK; -} - -ShockDiscRef* s_CurrDisc = NULL; -ShockDiscInfo s_CurrDiscInfo; - -static s32 _shock_SetOrPokeDisc(void* psx, ShockDiscRef* disc, bool poke) -{ - ShockDiscInfo info; - strcpy(info.id,"\0\0\0\0"); - info.region = REGION_NONE; - if(disc != NULL) - { - shock_AnalyzeDisc(disc,&info); - } - - s_CurrDiscInfo = info; - s_CurrDisc = disc; - - CDC->SetDisc(s_CurrDisc,s_CurrDiscInfo.id, poke); - - return SHOCK_OK; -} - -//Sets the disc in the tray. Returns SHOCK_NOCANDO if it's closed (TODO). You can pass NULL to remove a disc from the tray -EW_EXPORT s32 shock_SetDisc(void* psx, ShockDiscRef* disc) -{ - return _shock_SetOrPokeDisc(psx,disc,false); -} - -EW_EXPORT s32 shock_PokeDisc(void* psx, ShockDiscRef* disc) -{ - //let's talk about why this function is needed. well, let's paste an old comment on the subject: - //heres a comment from some old savestating code. something to keep in mind (maybe or maybe not a surprise depending on your point of view) - //"Call SetDisc() BEFORE we load CDC state, since SetDisc() has emulation side effects. We might want to clean this up in the future." - //I'm not really sure I like how SetDisc works, so I'm glad this was brought to our attention - - return _shock_SetOrPokeDisc(psx,disc,true); -} - -EW_EXPORT s32 shock_OpenTray(void* psx) -{ - if(s_ShockState.eject) return SHOCK_NOCANDO; - s_ShockState.eject = true; - CDC->OpenTray(); - return SHOCK_OK; -} - -EW_EXPORT s32 shock_CloseTray(void* psx) -{ - if(!s_ShockState.eject) return SHOCK_NOCANDO; - s_ShockState.eject = false; - CDC->CloseTray(false); - return SHOCK_OK; -} - - -EW_EXPORT s32 shock_DestroyDisc(ShockDiscRef* disc) -{ - delete disc; - return SHOCK_OK; -} - - -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); - virtual uint8 *map(void); - virtual void unmap(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: - CDIF *cdintf; - const uint32 start_lba; - const uint32 sector_count; - int64 position; -}; - -//THIS CODE SHOULD BE REMOVED WHEN A MORE ROBUST ISO PARSER IS ADDED. -class ShockDiscRef_Stream_Thing : public Stream -{ - public: - - ShockDiscRef_Stream_Thing(ShockDiscRef *cdintf_arg, uint32 lba_arg, uint32 sector_count_arg); - ~ShockDiscRef_Stream_Thing(); - - virtual uint64 attributes(void); - virtual uint8 *map(void); - virtual void unmap(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: - ShockDiscRef *cdintf; - const uint32 start_lba; - const uint32 sector_count; - int64 position; -}; - -ShockDiscRef_Stream_Thing::ShockDiscRef_Stream_Thing(ShockDiscRef *cdintf_arg, uint32 start_lba_arg, uint32 sector_count_arg) - : cdintf(cdintf_arg) - , start_lba(start_lba_arg) - , sector_count(sector_count_arg) -{ - -} - -ShockDiscRef_Stream_Thing::~ShockDiscRef_Stream_Thing() -{ - -} - -uint64 ShockDiscRef_Stream_Thing::attributes(void) -{ - return(ATTRIBUTE_READABLE | ATTRIBUTE_SEEKABLE); -} - -uint8 *ShockDiscRef_Stream_Thing::map(void) -{ - return NULL; -} - -void ShockDiscRef_Stream_Thing::unmap(void) -{ - -} - -uint64 ShockDiscRef_Stream_Thing::read(void *data, uint64 count, bool error_on_eos) -{ - if(count > (((uint64)sector_count * 2048) - position)) - { - //if(error_on_eos) - //{ - // throw "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->ReadLBA2048(start_lba + (rp / 2048), buf)) - { - //throw MDFN_Error(ErrnoHolder(EIO)); - return 0; //??????????? - } - - //::printf("Meow: %08llx -- %08llx\n", count, (rp - position) + std::min(2048 - (rp & 2047), count - (rp - position))); - memcpy((uint8*)data + (rp - position), buf + (rp & 2047), std::min(2048 - (rp & 2047), count - (rp - position))); - } - - position += count; - - return count; -} - -void ShockDiscRef_Stream_Thing::write(const void *data, uint64 count) -{ - -} - -void ShockDiscRef_Stream_Thing::seek(int64 offset, int whence) -{ - int64 new_position; - - switch(whence) - { - default: - - 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; -} - -int64 ShockDiscRef_Stream_Thing::tell(void) -{ - return position; -} - -int64 ShockDiscRef_Stream_Thing::size(void) -{ - return(sector_count * 2048); -} - -void ShockDiscRef_Stream_Thing::close(void) -{ - -} - -//Analyzes the disc by inspecting other things, in case the system.cnf determination failed -static s32 AnalyzeDiscEx(ShockDiscRef* disc, ShockDiscInfo* info) -{ - const char *id = NULL; - uint8 buf[2048]; - uint8 fbuf[2048 + 1]; - unsigned ipos, opos; - - //clear it out in case of error - info->region = REGION_NONE; - info->id[0] = 0; - - memset(fbuf, 0, sizeof(fbuf)); - - //if it wasnt mode 2, we failed - s32 readed = disc->ReadLBA2048(4, buf); - if(readed != 0x02) - return SHOCK_ERROR; - - //lowercase strings for searching - for(ipos = 0, opos = 0; ipos < 0x48; ipos++) - { - if(buf[ipos] > 0x20 && buf[ipos] < 0x80) - { - fbuf[opos++] = tolower(buf[ipos]); - } - } - - fbuf[opos++] = 0; - - PSX_DBG(PSX_DBG_SPARSE, "License string: %s", (char *)fbuf); - - if(strstr((char *)fbuf, "licensedby") != NULL) - { - if(strstr((char *)fbuf, "america") != NULL) - { - strcpy(info->id,"SCEA"); - info->region = REGION_NA; - return SHOCK_OK; - } - else if(strstr((char *)fbuf, "europe") != NULL) - { - strcpy(info->id,"SCEE"); - info->region = REGION_EU; - return SHOCK_OK; - } - else if(strstr((char *)fbuf, "japan") != NULL) - { - strcpy(info->id,"SCEI"); - info->region = REGION_JP; - return SHOCK_OK; - } - else if(strstr((char *)fbuf, "sonycomputerentertainmentinc.") != NULL) - { - strcpy(info->id,"SCEI"); - info->region = REGION_JP; - return SHOCK_OK; - } - } - - return SHOCK_ERROR; -} - -//this is kind of lame. cant we get a proper iso fs parser here? -EW_EXPORT s32 shock_AnalyzeDisc(ShockDiscRef* disc, ShockDiscInfo* info) -{ - const char *ret = NULL; - Stream *fp = NULL; - CDUtility::TOC toc; - - //(*CDInterfaces)[disc]->ReadTOC(&toc); - - //if(toc.first_track > 1 || toc. - - try - { - uint8 pvd[2048]; - unsigned pvd_search_count = 0; - - fp = new ShockDiscRef_Stream_Thing(disc, 0, ~0); - fp->seek(0x8000, SEEK_SET); - - do - { - if((pvd_search_count++) == 32) - throw "PVD search count limit met."; - - fp->read(pvd, 2048); - - if(memcmp(&pvd[1], "CD001", 5)) - throw "Not ISO-9660"; - - if(pvd[0] == 0xFF) - throw "Missing Primary Volume Descriptor"; - } while(pvd[0] != 0x01); - //[156 ... 189], 34 bytes - uint32 rdel = MDFN_de32lsb(&pvd[0x9E]); - uint32 rdel_len = MDFN_de32lsb(&pvd[0xA6]); - - if(rdel_len >= (1024 * 1024 * 10)) // Arbitrary sanity check. - throw "Root directory table too large"; - - fp->seek((int64)rdel * 2048, SEEK_SET); - //printf("%08x, %08x\n", rdel * 2048, rdel_len); - - //I think this loop is scanning directory entries until it finds system.cnf and if it never finishes we'll just fall out - while(fp->tell() < (((int64)rdel * 2048) + rdel_len)) - { - uint8 len_dr = fp->get_u8(); - uint8 dr[256 + 1]; - - memset(dr, 0xFF, sizeof(dr)); - - if(!len_dr) - break; - - memset(dr, 0, sizeof(dr)); - dr[0] = len_dr; - fp->read(dr + 1, len_dr - 1); - - uint8 len_fi = dr[0x20]; - - if(len_fi == 12 && !memcmp(&dr[0x21], "SYSTEM.CNF;1", 12)) - { - uint32 file_lba = MDFN_de32lsb(&dr[0x02]); - //uint32 file_len = MDFN_de32lsb(&dr[0x0A]); - uint8 fb[2048 + 1]; - char *bootpos; - - memset(fb, 0, sizeof(fb)); - fp->seek(file_lba * 2048, SEEK_SET); - fp->read(fb, 2048); - - if((bootpos = strstr((char*)fb, "BOOT"))) - { - bootpos += 4; - while(*bootpos == ' ' || *bootpos == '\t') bootpos++; - if(*bootpos == '=') - { - bootpos++; - while(*bootpos == ' ' || *bootpos == '\t') bootpos++; - if(!strncasecmp(bootpos, "cdrom:", 6)) - { - char* tmp; - - bootpos += 6; - - // strrchr() way will pick up Tekken 3, but only enable if needed due to possibility of regressions. - //if((tmp = strrchr(bootpos, '\\'))) - // bootpos = tmp + 1; - while(*bootpos == '\\') - bootpos++; - - if((tmp = strchr(bootpos, '_'))) *tmp = 0; - if((tmp = strchr(bootpos, '.'))) *tmp = 0; - if((tmp = strchr(bootpos, ';'))) *tmp = 0; - //puts(bootpos); - - if(strlen(bootpos) == 4 && toupper(bootpos[0]) == 'S' && (toupper(bootpos[1]) == 'C' || toupper(bootpos[1]) == 'L' || toupper(bootpos[1]) == 'I')) - { - switch(toupper(bootpos[2])) - { - case 'E': - info->region = REGION_EU; - strcpy(info->id,"SCEE"); - goto Breakout; - - case 'U': - info->region = REGION_NA; - strcpy(info->id,"SCEA"); - goto Breakout; - - case 'K': // Korea? - case 'B': - case 'P': - info->region = REGION_JP; - strcpy(info->id,"SCEI"); - goto Breakout; - } - } - } - } - } - - //puts((char*)fb); - //puts("ASOFKOASDFKO"); - } - } - } - catch(const char* str) - { - //puts(e.what()); - } - - //uhmm couldnt find system.cnf. try another way - return AnalyzeDiscEx(disc,info); - -Breakout: - - return SHOCK_OK; -} - -bool ShockDiscRef::ReadLBA_PW(uint8* pwbuf96, int32 lba, bool hint_fullread) -{ - //TODO - whats that hint mean - //reference: static const int32 LBA_Read_Minimum = -150; - //reference: static const int32 LBA_Read_Maximum = 449849; // 100 * 75 * 60 - 150 - 1 - u8 tmp[2448]; - s32 ret = ReadLBA2448(lba,tmp); - if(ret != SHOCK_OK) - return false; - memcpy(pwbuf96,tmp+2352,96); - return true; -} - -s32 ShockDiscRef::ReadLBA2448(s32 lba, void* dst2448) -{ - return InternalReadLBA2448(lba, dst2448, true); -} - -s32 ShockDiscRef::InternalReadLBA2448(s32 lba, void* dst2448, bool needSubcode) -{ - int ret = mcbReadLBA2448(mOpaque, lba, dst2448); - if(ret != SHOCK_OK) - return ret; - - if(needSubcode && mSuppliesDeinterleavedSubcode) - { - //presently, CDC consumes deinterleaved subcode. - //perhaps this could be optimized in the future - u8 tmp[96]; - CDUtility::subpw_interleave((u8*)dst2448+2352,tmp); - memcpy((u8*)dst2448+2352,tmp,96); - } - - return SHOCK_OK; -} - -//adapts the ReadLBA2448 results to a 2048 byte sector and returns the mode, as required -s32 ShockDiscRef::ReadLBA2048(s32 lba, void* dst2048) -{ - union Sector { - struct { - u8 sync[12]; - u8 adr[3]; - u8 mode; - union { - struct { - u8 data2048[2048]; - u8 ecc[4]; - u8 reserved[8]; - u8 ecm[276]; - }; - u8 data2336[2336]; - }; - }; - u8 buf[2352]; - }; - - union XASector { - struct { - u8 sync[12]; - u8 adr[3]; - u8 mode; - u8 subheader[8]; - union { - u8 data2048[2048]; - u8 ecc[4]; - u8 ecm[276]; - } form1; - union { - u8 data2334[2334]; - u8 ecc[4]; - } form2; - }; - u8 buf[2352]; - }; - - static union { - struct { - union { - XASector xasector; - Sector sector; - }; - u8 subcode[96]; - }; - u8 buf2448[2448]; - }; - - s32 ret = InternalReadLBA2448(lba,buf2448,false); - if(ret != SHOCK_OK) - return ret; - - if(sector.mode == 1) - memcpy(dst2048,sector.data2048,2048); - else - memcpy(dst2048,xasector.form1.data2048,2048); - - return sector.mode; -} - -//Returns information about a memory buffer for peeking (main memory, spu memory, etc.) -EW_EXPORT s32 shock_GetMemData(void* psx, void** ptr, s32* size, s32 memType) -{ - switch(memType) - { - case eMemType_MainRAM: *ptr = MainRAM.data8; *size = 2048*1024; break; - case eMemType_BiosROM: *ptr = BIOSROM->data8; *size = 512*1024; break; - case eMemType_PIOMem: *ptr = PIOMem->data8; *size = 64*1024; break; - case eMemType_GPURAM: *ptr = GPU.GPURAM; *size = 2*512*1024; break; - case eMemType_SPURAM: *ptr = SPU->SPURAM; *size = 512*1024; break; - case eMemType_DCache: *ptr = CPU->debug_GetScratchRAMPtr(); *size = 1024; break; - default: - return SHOCK_ERROR; - } - return SHOCK_OK; -} - -class PSX -{ -public: - templatevoid SyncState(EW::NewState *ns); -} s_PSX; - -namespace MDFN_IEN_PSX { -void DMA_SyncState(bool isReader, EW::NewState *ns); -void GTE_SyncState(bool isReader, EW::NewState *ns); -void TIMER_SyncState(bool isReader, EW::NewState *ns); -void SIO_SyncState(bool isReader, EW::NewState *ns); -void MDEC_SyncState(bool isReader, EW::NewState *ns); -void IRQ_SyncState(bool isReader, EW::NewState *ns); -} - -SYNCFUNC(PSX) -{ - NSS(s_ShockState); - PSS(MainRAM.data8, 2*1024*1024); - NSS(SysControl.Regs); - NSS(PSX_PRNG.lcgo); - NSS(PSX_PRNG.x); - NSS(PSX_PRNG.y); - NSS(PSX_PRNG.z); - NSS(PSX_PRNG.c); - - //note: mednafen used to save the current disc index. that's kind of nice, I guess, if you accept that responsibility in the core. - //but we're not doing things that way. - //I think instead maybe we should generate a hash of the inserted disc and save that, and then check if theres a mismatch between the disc at the time of the savestate and the current disc - //but we'll do that in the frontend for now - - //old: - // "TODO: Remember to increment dirty count in memory card state loading routine." - //not sure what this means or whether I like it - - //I've kept the ordering of these sections the same, in case its important for some unknown reason.. for now. - - TSS(CPU); - - ns->EnterSection("GTE"); - GTE_SyncState(isReader,ns); - ns->ExitSection("GTE"); - - ns->EnterSection("DMA"); - DMA_SyncState(isReader,ns); - ns->ExitSection("DMA"); - - ns->EnterSection("TIMER"); - TIMER_SyncState(isReader,ns); - ns->ExitSection("TIMER"); - - ns->EnterSection("SIO"); - SIO_SyncState(isReader,ns); - ns->ExitSection("SIO"); - - TSS(CDC); - - ns->EnterSection("MDEC"); - MDEC_SyncState(isReader,ns); - ns->ExitSection("MDEC"); - - TSS((&GPU)); //did some special logic for the CPU, ordering may matter, but probably not - - TSS(SPU); - TSS(FIO); //TODO - DUALSHOCK, MC - - - //"Do it last." the comments say. And all this other nonsense about IRQs in the other state syncing functions. weird..... - //ret &= IRQ_StateAction(sm, load, data_only); // - - ns->EnterSection("IRQ"); - IRQ_SyncState(isReader,ns); - ns->ExitSection("IRQ"); - - if(isReader) - { - //the purpose of this is to restore the sorting of the event list - //event updates are programmed to have no effect if the time step is 0 - //and at this point, the time base timestamp will be 0 (it always is after a frame advance) - //so the event updaters just run, do nothing, and restore themselves in the list - ForceEventUpdates(0); // FIXME to work with debugger step mode. - } -} - -EW_EXPORT s32 shock_StateTransaction(void *psx, ShockStateTransaction* transaction) -{ - switch(transaction->transaction) - { - case eShockStateTransaction_BinarySize: - { - EW::NewStateDummy dummy; - s_PSX.SyncState(&dummy); - return dummy.GetLength(); - } - case eShockStateTransaction_BinaryLoad: - { - if(transaction->buffer == NULL) return SHOCK_ERROR; - EW::NewStateExternalBuffer loader((char*)transaction->buffer, transaction->bufferLength); - s_PSX.SyncState(&loader); - if(!loader.Overflow() && loader.GetLength() == transaction->bufferLength) - return SHOCK_OK; - else return SHOCK_ERROR; - } - case eShockStateTransaction_BinarySave: - { - if(transaction->buffer == NULL) return SHOCK_ERROR; - EW::NewStateExternalBuffer saver((char*)transaction->buffer, transaction->bufferLength); - s_PSX.SyncState(&saver); - if(!saver.Overflow() && saver.GetLength() == transaction->bufferLength) - return SHOCK_OK; - else return SHOCK_ERROR; - } - case eShockStateTransaction_TextLoad: - { - EW::NewStateExternalFunctions saver(&transaction->ff); - s_PSX.SyncState(&saver); - return SHOCK_OK; - } - case eShockStateTransaction_TextSave: - { - EW::NewStateExternalFunctions loader(&transaction->ff); - s_PSX.SyncState(&loader); - return SHOCK_OK; - } - return SHOCK_ERROR; - - default: - return SHOCK_ERROR; - } -} - -EW_EXPORT s32 shock_GetRegisters_CPU(void* psx, ShockRegisters_CPU* buffer) -{ - memcpy(buffer->GPR,CPU->debug_GetGPRPtr(),32*4); - buffer->PC = CPU->GetRegister(PS_CPU::GSREG_PC_NEXT,NULL,0); - buffer->PC_NEXT = CPU->GetRegister(PS_CPU::GSREG_PC_NEXT,NULL,0); - buffer->IN_BD_SLOT = CPU->GetRegister(PS_CPU::GSREG_IN_BD_SLOT,NULL,0); - buffer->LO = CPU->GetRegister(PS_CPU::GSREG_LO,NULL,0); - buffer->HI = CPU->GetRegister(PS_CPU::GSREG_HI,NULL,0); - buffer->SR = CPU->GetRegister(PS_CPU::GSREG_SR,NULL,0); - buffer->CAUSE = CPU->GetRegister(PS_CPU::GSREG_CAUSE,NULL,0); - buffer->EPC = CPU->GetRegister(PS_CPU::GSREG_EPC,NULL,0); - - return SHOCK_OK; -} - -//Sets a CPU register. Rather than have an enum for the registers, lets just use the index (not offset) within the struct -EW_EXPORT s32 shock_SetRegister_CPU(void* psx, s32 index, u32 value) -{ - //takes advantage of layout of GSREG_ matchign our struct (not an accident!) - CPU->SetRegister((u32)index,value); - - return SHOCK_OK; -} - -EW_EXPORT s32 shock_SetRenderOptions(void* pxs, ShockRenderOptions* opts) -{ - GPU.SetRenderOptions(opts); - s_ShockConfig.opts = *opts; - return SHOCK_OK; -} - -extern void* g_ShockTraceCallbackOpaque; -extern ShockCallback_Trace g_ShockTraceCallback; -extern ShockCallback_Mem g_ShockMemCallback; -extern eShockMemCb g_ShockMemCbType; - -//Sets the callback to be used for CPU tracing -EW_EXPORT s32 shock_SetTraceCallback(void* psx, void* opaque, ShockCallback_Trace callback) -{ - g_ShockTraceCallbackOpaque = opaque; - g_ShockTraceCallback = callback; - - return SHOCK_OK; -} - -//Sets the callback to be used for memory hook events -EW_EXPORT s32 shock_SetMemCb(void* psx, ShockCallback_Mem callback, eShockMemCb cbMask) -{ - g_ShockMemCallback = callback; - g_ShockMemCbType = cbMask; - return SHOCK_OK; -} - -//Sets whether LEC is enabled (sector level error correction). Defaults to FALSE (disabled) -EW_EXPORT s32 shock_SetLEC(void* psx, bool enabled) -{ - CDC->SetLEC(enabled); - return SHOCK_OK; -} - -//whether "determine lag from GPU frames" signal is set (GPU did something considered non-lag) -//returns SHOCK_TRUE or SHOCK_FALSE -EW_EXPORT s32 shock_GetGPUUnlagged(void* psx) -{ - return GpuFrameForLag ? SHOCK_TRUE : SHOCK_FALSE; -} - -EW_EXPORT s32 shock_PeekMemory(void* psx, u32 address, u8* value) -{ - if (!s_Created) { - return SHOCK_NOCANDO; - } - - *value = CPU->PeekMem8(address); - return SHOCK_OK; -} - -EW_EXPORT s32 shock_PokeMemory(void* psx, u32 address, u8 value) -{ - if (!s_Created) { - return SHOCK_NOCANDO; - } - - CPU->PokeMem8(address, value); - return SHOCK_OK; - -} diff --git a/psx/octoshock/psx/psx.h b/psx/octoshock/psx/psx.h deleted file mode 100644 index 699bd09246c..00000000000 --- a/psx/octoshock/psx/psx.h +++ /dev/null @@ -1,460 +0,0 @@ -/******************************************************************************/ -/* Mednafen Sony PS1 Emulation Module */ -/******************************************************************************/ -/* psx.h: -** Copyright (C) 2011-2016 Mednafen Team -** -** 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., -** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#pragma once - -#include "octoshock.h" -#include "emuware/emuware.h" -#include "video/surface.h" -#include "masmem.h" -#include "endian.h" -#include "emuware/EW_state.h" -#include "math_ops.h" - -// -// Comment out these 2 defines for extra speeeeed. -// -#define PSX_DBGPRINT_ENABLE 1 -#define PSX_EVENT_SYSTEM_CHECKS 1 - -// -// It's highly unlikely the user will want these if they're intentionally compiling without the debugger. -#ifndef WANT_DEBUGGER - #undef PSX_DBGPRINT_ENABLE - #undef PSX_EVENT_SYSTEM_CHECKS -#endif -// -// -// - -namespace MDFN_IEN_PSX -{ - #define PSX_DBG_ERROR 0 // Emulator-level error. - #define PSX_DBG_WARNING 1 // Warning about game doing questionable things/hitting stuff that might not be emulated correctly. - #define PSX_DBG_BIOS_PRINT 2 // BIOS printf/putchar output. - #define PSX_DBG_SPARSE 3 // Sparse(relatively) information debug messages(CDC commands). - #define PSX_DBG_FLOOD 4 // Heavy informational debug messages(GPU commands; TODO). - -#if PSX_DBGPRINT_ENABLE - void PSX_DBG(unsigned level, const char *format, ...) noexcept MDFN_COLD MDFN_FORMATSTR(gnu_printf, 2, 3); - void PSX_DBG_BIOS_PUTC(uint8 c) noexcept; - - #define PSX_WARNING(format, ...) { PSX_DBG(PSX_DBG_WARNING, format "\n", ## __VA_ARGS__); } - #define PSX_DBGINFO(format, ...) { } -#else - static INLINE void PSX_DBG(unsigned level, const char* format, ...) { } - static INLINE void PSX_DBG_BIOS_PUTC(uint8 c) { } - static INLINE void PSX_WARNING(const char* format, ...) { } - static INLINE void PSX_DBGINFO(const char* format, ...) { } -#endif - - typedef int32 pscpu_timestamp_t; - - bool MDFN_FASTCALL PSX_EventHandler(const pscpu_timestamp_t timestamp); - - void MDFN_FASTCALL PSX_MemWrite8(pscpu_timestamp_t timestamp, uint32 A, uint32 V); - void MDFN_FASTCALL PSX_MemWrite16(pscpu_timestamp_t timestamp, uint32 A, uint32 V); - void MDFN_FASTCALL PSX_MemWrite24(pscpu_timestamp_t timestamp, uint32 A, uint32 V); - void MDFN_FASTCALL PSX_MemWrite32(pscpu_timestamp_t timestamp, uint32 A, uint32 V); - - uint8 MDFN_FASTCALL PSX_MemRead8(pscpu_timestamp_t ×tamp, uint32 A); - uint16 MDFN_FASTCALL PSX_MemRead16(pscpu_timestamp_t ×tamp, uint32 A); - uint32 MDFN_FASTCALL PSX_MemRead24(pscpu_timestamp_t ×tamp, uint32 A); - uint32 MDFN_FASTCALL PSX_MemRead32(pscpu_timestamp_t ×tamp, uint32 A); - - uint8 PSX_MemPeek8(uint32 A); - uint16 PSX_MemPeek16(uint32 A); - uint32 PSX_MemPeek32(uint32 A); - - // Should write to WO-locations if possible - void PSX_MemPoke8(uint32 A, uint8 V); - void PSX_MemPoke16(uint32 A, uint16 V); - void PSX_MemPoke32(uint32 A, uint32 V); - - void PSX_RequestMLExit(void); - void ForceEventUpdates(const pscpu_timestamp_t timestamp); - - enum - { - PSX_EVENT__SYNFIRST = 0, - PSX_EVENT_GPU, - PSX_EVENT_CDC, - //PSX_EVENT_SPU, - PSX_EVENT_TIMER, - PSX_EVENT_DMA, - PSX_EVENT_FIO, - PSX_EVENT__SYNLAST, - PSX_EVENT__COUNT, - }; - - #define PSX_EVENT_MAXTS 0x20000000 - void PSX_SetEventNT(const int type, const pscpu_timestamp_t next_timestamp); - - void PSX_SetDMACycleSteal(unsigned stealage); - - void PSX_GPULineHook(const pscpu_timestamp_t timestamp, const pscpu_timestamp_t line_timestamp, bool vsync, uint32 *pixels, const MDFN_PixelFormat* const format, const unsigned width, const unsigned pix_clock_offset, const unsigned pix_clock, const unsigned pix_clock_divider); - - uint32 PSX_GetRandU32(uint32 mina, uint32 maxa); -} - - -#include "dis.h" -#include "cpu.h" -#include "irq.h" -#include "gpu.h" -#include "dma.h" -//#include "sio.h" -#include "debug.h" - -namespace MDFN_IEN_PSX -{ - class PS_CDC; - class PS_SPU; - - MDFN_HIDE extern PS_CPU *CPU; - MDFN_HIDE extern PS_CDC *CDC; - MDFN_HIDE extern PS_SPU *SPU; - MDFN_HIDE extern MultiAccessSizeMem<2048 * 1024, false> MainRAM; -} - -enum eRegion -{ - REGION_JP = 0, - REGION_NA = 1, - REGION_EU = 2, - REGION_NONE = 3 -}; - -enum eShockDeinterlaceMode -{ - eShockDeinterlaceMode_Weave, - eShockDeinterlaceMode_Bob, - eShockDeinterlaceMode_BobOffset -}; - -enum eShockStep -{ - eShockStep_Frame -}; - -enum eShockFramebufferFlags -{ - eShockFramebufferFlags_None = 0, - eShockFramebufferFlags_Normalize = 1 -}; - -enum eShockRenderType -{ - eShockRenderType_Normal, - eShockRenderType_ClipOverscan, - - //this should discard peculiar X adjustments during scan-out (done) - //as well as peculiar Y adjustments (not done) - //it's unclear whether the latter will actually ever be needed.. - //are any earthquake effects shaking the whole screen? - eShockRenderType_Framebuffer -}; - -enum eMemType -{ - eMemType_MainRAM = 0, //2048K - eMemType_BiosROM = 1, //512K - eMemType_PIOMem = 2, //64K - eMemType_GPURAM = 3, //512K - eMemType_SPURAM = 4, //512K - eMemType_DCache = 5 //1K -}; - -enum ePeripheralType -{ - ePeripheralType_None = 0, //can be used to signify disconnection - - ePeripheralType_Pad = 1, //SCPH-1080 - ePeripheralType_DualShock = 2, //SCPH-1200 - ePeripheralType_DualAnalog = 3, //SCPH-1180 - ePeripheralType_NegCon = 4, - - ePeripheralType_Multitap = 10, -}; - -enum eShockStateTransaction : s32 -{ - eShockStateTransaction_BinarySize = 0, - eShockStateTransaction_BinaryLoad = 1, - eShockStateTransaction_BinarySave = 2, - eShockStateTransaction_TextLoad = 3, - eShockStateTransaction_TextSave = 4 -}; - -enum eShockMemcardTransaction -{ - eShockMemcardTransaction_Connect = 0, //connects it to the addressed port (not supported yet) - eShockMemcardTransaction_Disconnect = 1, //disconnects it from the addressed port (not supported yet) - eShockMemcardTransaction_Write = 2, //writes from the frontend to the memcard - eShockMemcardTransaction_Read = 3, //reads from the memcard to the frontend. Also clears the dirty flag - eShockMemcardTransaction_CheckDirty = 4, //checks whether the memcard is dirty -}; - -enum eShockMemCb -{ - eShockMemCb_None = 0, - eShockMemCb_Read = 1, - eShockMemCb_Write = 2, - eShockMemCb_Execute = 4 -}; - -#define MDFN_MSC_RESET 0 -#define MDFN_MSC_POWER 1 -#define MDFN_MSC_INSERT_DISK 2 -#define MDFN_MSC_SELECT_DISK 3 -#define MDFN_MSC_EJECT_DISK 4 - -#define SHOCK_OK 0 -#define SHOCK_FALSE 0 -#define SHOCK_TRUE 1 -#define SHOCK_ERROR -1 -#define SHOCK_NOCANDO -2 -#define SHOCK_INVALID_ADDRESS -3 -#define SHOCK_OVERFLOW -4 - -struct ShockTOCTrack -{ - u8 adr; - u8 control; - u32 lba; -}; - -struct ShockTOC -{ - u8 first_track; - u8 last_track; - u8 disc_type; -}; - -struct ShockRegisters_CPU -{ - u32 GPR[32]; - u32 PC, PC_NEXT; - u32 IN_BD_SLOT; - u32 LO, HI; - u32 SR, CAUSE, EPC; -}; - -// [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). -typedef s32 (*ShockDisc_ReadTOC)(void* opaque, ShockTOC *read_target, ShockTOCTrack tracks[100 + 1]); -typedef s32 (*ShockDisc_ReadLBA)(void* opaque, s32 lba, void* dst); - -//The callback to be issued for traces -typedef void (*ShockCallback_Trace)(void* opaque, u32 PC, u32 inst, const char* msg); - -//the callback to be issued for memory hook events -//note: only one callback can be set. the type is sent to mask that one callback, not indicate which event type the callback is fore. -//there isnt one callback per type. -typedef void (*ShockCallback_Mem)(u32 address, eShockMemCb type, u32 size, u32 value); - -class ShockDiscRef -{ -public: - ShockDiscRef(void *opaque, s32 lbaCount, ShockDisc_ReadTOC cbReadTOC, ShockDisc_ReadLBA cbReadLBA2448, bool suppliesDeinterleavedSubcode) - : mOpaque(opaque) - , mLbaCount(lbaCount) - , mcbReadTOC(cbReadTOC) - , mcbReadLBA2448(cbReadLBA2448) - , mSuppliesDeinterleavedSubcode(suppliesDeinterleavedSubcode) - { - } - - s32 ReadTOC( ShockTOC *read_target, ShockTOCTrack tracks[100 + 1]) - { - return mcbReadTOC(mOpaque, read_target, tracks); - } - - //formerly ReadRawSector - //Reads 2352 + 96 - s32 ReadLBA2448(s32 lba, void* dst2448); - - //formerly ReadRawSectorPWOnly - //Reads 96 bytes (of raw subchannel PW data) into pwbuf. - //Probably the same format as what's at the end of ReadLBA2448 - //TODO - reorder args - bool ReadLBA_PW(uint8* pwbuf96, int32 lba, bool hint_fullread); - - //only used by disc analysis stuff which should be refactored anyway. should eventually be removed - s32 ReadLBA2048(s32 lba, void* dst2048); - -private: - s32 InternalReadLBA2448(s32 lba, void* dst2448, bool needSubcode); - void *mOpaque; - s32 mLbaCount; - ShockDisc_ReadTOC mcbReadTOC; - ShockDisc_ReadLBA mcbReadLBA2448; - bool mSuppliesDeinterleavedSubcode; -}; - -struct ShockDiscInfo -{ - s32 region; - char id[5]; //SCEI, SCEA, SCEE, etc. with null terminator -}; - -struct ShockFramebufferInfo -{ - s32 width, height; - s32 flags; - void* ptr; -}; - -struct ShockRenderOptions -{ - s32 scanline_start, scanline_end; - eShockRenderType renderType; - eShockDeinterlaceMode deinterlaceMode; - bool skip; -}; - -struct ShockMemcardTransaction -{ - eShockMemcardTransaction transaction; - void* buffer128k; -}; - -struct ShockStateTransaction -{ - eShockStateTransaction transaction; - void *buffer; - s32 bufferLength; - - //originally this was a pointer, however, we had problems getting it to marshal correctly - EW::FPtrs ff; -}; - -//Creates a ShockDiscRef (representing a disc) with the given properties. Returns it in the specified output pointer. -//The ReadLBA2048 function should return 0x01 or 0x02 depending on which mode was there. -//Others should return SHOCK_OK -EW_EXPORT s32 shock_CreateDisc(ShockDiscRef** outDisc, void *Opaque, s32 lbaCount, ShockDisc_ReadTOC ReadTOC, ShockDisc_ReadLBA ReadLBA2448, bool suppliesDeinterleavedSubcode); - -//Destroys a ShockDiscRef created with shock_CreateDisc. Make sure you havent left it in the playstation before destroying it! -EW_EXPORT s32 shock_DestroyDisc(ShockDiscRef* disc); - -//Inspects a disc by looking for the system.cnf and retrieves some necessary information about it. -//Useful for determining the region of a disc -EW_EXPORT s32 shock_AnalyzeDisc(ShockDiscRef* disc, ShockDiscInfo* info); - -//Creates the psx instance as a console of the specified region. -//Additionally mounts the firmware from the provided buffer (the contents are copied) -//TODO - receive a model number parameter instead -EW_EXPORT s32 shock_Create(void** psx, s32 region, void* firmware512k); - -//Frees the psx instance created with shock_Create -EW_EXPORT s32 shock_Destroy(void* psx); - -//Attaches (or detaches) a peripheral at the given address. -//Send ePeripheralType_None to detach. -//Do not attach when something is already attached. -//You can detach when nothing is attached. -//Returns SHOCK_NOCANDO if something inappropriate is done. -//Presently this has only been validated as functioning correctly before the initial PowerOn, but we would like to use it other times. -EW_EXPORT s32 shock_Peripheral_Connect(void* psx, s32 address, s32 type); - -//Sets pad-type input (pad,dualshock,dualanalog) on the specified address; -//Read more about the input format (buttons, analog range) here: TBD -EW_EXPORT s32 shock_Peripheral_SetPadInput(void* psx, s32 address, u32 buttons, u8 left_x, u8 left_y, u8 right_x, u8 right_y); - -//Performs one of several transactions on an attached memory card. -EW_EXPORT s32 shock_Peripheral_MemcardTransact(void* psx, s32 address, ShockMemcardTransaction* transaction); - -//Polls the given peripheral address for it's active flag status (inverse of lag flag) -//If you want, the lag flag can be cleared -//Returns SHOCK_TRUE if the input has been read this frame -//Returns SHOCK_FALSE if the input hasnt been read this frame (is lagging) -//Returns SHOCK_NOCANDO if there is no peripheral there -//Returns SHOCK_INVALID_ADDRESS if address is invalid -//Returns SHOCK_ERROR for other errors. -EW_EXPORT s32 shock_Peripheral_PollActive(void* psx, s32 address, s32 clear); - -//Mounts a PS-EXE executable -EW_EXPORT s32 shock_MountEXE(void* psx, void* exebuf, s32 size, s32 ignore_pcsp); - -//Sets the power to ON. Returns SHOCK_NOCANDO if already on. -EW_EXPORT s32 shock_PowerOn(void* psx); - -//Triggers a soft reset immediately. Returns SHOCK_NOCANDO if console is powered off. -EW_EXPORT s32 shock_SoftReset(void* psx); - -//Sets the power to OFF. Returns SHOCK_NOCANDO if already off. -EW_EXPORT s32 shock_PowerOff(void* psx); - -//Opens the disc tray. Returns SHOCK_NOCANDO if already open. -EW_EXPORT s32 shock_OpenTray(void* psx); - -//Sets the disc in the tray. Returns SHOCK_NOCANDO if it's closed. You can pass NULL to remove a disc from the tray -EW_EXPORT s32 shock_SetDisc(void* psx, ShockDiscRef* disc); - -//POKES the disc in the tray, for use after loading a state. Does not affect any of the internal emulation parameters -EW_EXPORT s32 shock_PokeDisc(void* psx, ShockDiscRef* disc); - -//Closes the disc tray. Returns SHOCK_NOCANDO if already closed. -EW_EXPORT s32 shock_CloseTray(void* psx); - -//Sets rendering options for next frame -EW_EXPORT s32 shock_SetRenderOptions(void* psx, ShockRenderOptions* opts); - -//Steps emulation by the specified interval -//TODO - think about something. After loadstating, the device input state is probably nonsense. -//Normally we'd set the input before frame advancing. But every frontend might not do that, and we might not be stepping by one frame. -//What to do about this? -EW_EXPORT s32 shock_Step(void* psx, eShockStep step); - -//Fetches the framebuffer. Can retrieve parameters (set the job ptr to NULL) or fill the provided job ptr with the framebuffer (make sure its big enough). -//This helps us copy fewer times. -EW_EXPORT s32 shock_GetFramebuffer(void* psx, ShockFramebufferInfo* fb); - -//Returns the queued SPU output (usually ~737 samples per frame) as the normal 16bit interleaved stereo format -//The size of the queue will be returned. Make sure your buffer can handle it. Pass NULL just to get the required size. -EW_EXPORT s32 shock_GetSamples(void* psx, void* buffer); - -//Returns information about a memory buffer for peeking (main memory, spu memory, etc.) -EW_EXPORT s32 shock_GetMemData(void* psx, void** ptr, s32* size, s32 memType); - -//Savestate work. Returns the size if that's what was requested, otherwise error codes -EW_EXPORT s32 shock_StateTransaction(void *psx, ShockStateTransaction* transaction); - -//Retrieves the CPU registers in a compact struct -EW_EXPORT s32 shock_GetRegisters_CPU(void* psx, ShockRegisters_CPU* buffer); - -//Sets a CPU register. Rather than have an enum for the registers, lets just use the index (not offset) within the struct -EW_EXPORT s32 shock_SetRegister_CPU(void* psx, s32 index, u32 value); - -//Sets the callback to be used for CPU tracing -EW_EXPORT s32 shock_SetTraceCallback(void* psx, void* opaque, ShockCallback_Trace callback); - -//Sets whether LEC is enabled (sector level error correction). Defaults to FALSE (disabled) -EW_EXPORT s32 shock_SetLEC(void* psx, bool enabled); - -//whether "determine lag from GPU frames" signal is set (GPU did something considered non-lag) -//returns SHOCK_TRUE or SHOCK_FALSE -EW_EXPORT s32 shock_GetGPUUnlagged(void* psx); - -EW_EXPORT s32 shock_PeekMemory(void* psx, u32 address, u8* value); - -EW_EXPORT s32 shock_PokeMemory(void* psx, u32 address, u8 value); \ No newline at end of file diff --git a/psx/octoshock/psx/sio.cpp b/psx/octoshock/psx/sio.cpp deleted file mode 100644 index 8f2fb97be2f..00000000000 --- a/psx/octoshock/psx/sio.cpp +++ /dev/null @@ -1,120 +0,0 @@ -/******************************************************************************/ -/* Mednafen Sony PS1 Emulation Module */ -/******************************************************************************/ -/* sio.cpp: -** Copyright (C) 2011-2016 Mednafen Team -** -** 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., -** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "psx.h" -#include "sio.h" - -namespace MDFN_IEN_PSX -{ - -// Dummy implementation. - -static uint16 Status; -static uint16 Mode; -static uint16 Control; -static uint16 BaudRate; -static uint32 DataBuffer; - -void SIO_Power(void) -{ - Status = 0; - Mode = 0; - Control = 0; - BaudRate = 0; - DataBuffer = 0; -} - -uint32 SIO_Read(pscpu_timestamp_t timestamp, uint32 A) -{ - uint32 ret = 0; - - switch(A & 0xE) - { - default: - PSX_WARNING("[SIO] Unknown read: 0x%08x -- %d\n", A, timestamp); - break; - - case 0x0: - //case 0x2: - ret = DataBuffer >> ((A & 2) * 8); - break; - - case 0x4: - ret = Status; - break; - - case 0x8: - ret = Mode; - break; - - case 0xA: - ret = Control; - break; - - case 0xE: - ret = BaudRate; - break; - } - - return(ret >> ((A & 1) * 8)); -} - -void SIO_Write(pscpu_timestamp_t timestamp, uint32 A, uint32 V) -{ - V <<= (A & 1) * 8; - - switch(A & 0xE) - { - default: - PSX_WARNING("[SIO] Unknown write: 0x%08x 0x%08x -- %d\n", A, V, timestamp); - break; - - case 0x0: - //case 0x2: - V <<= (A & 2) * 8; - DataBuffer = V; - break; - - case 0x8: - Mode = V; - break; - - case 0xA: - Control = V; - break; - - case 0xE: - BaudRate = V; - break; - } -} - - -void SIO_SyncState(bool isReader, EW::NewState *ns) -{ - NSS(Status); - NSS(Mode); - NSS(Control); - NSS(BaudRate); - NSS(DataBuffer); -} - -} diff --git a/psx/octoshock/psx/sio.h b/psx/octoshock/psx/sio.h deleted file mode 100644 index c8241132bee..00000000000 --- a/psx/octoshock/psx/sio.h +++ /dev/null @@ -1,34 +0,0 @@ -/******************************************************************************/ -/* Mednafen Sony PS1 Emulation Module */ -/******************************************************************************/ -/* sio.h: -** Copyright (C) 2011-2016 Mednafen Team -** -** 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., -** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef __MDFN_PSX_SIO_H -#define __MDFN_PSX_SIO_H - -namespace MDFN_IEN_PSX -{ - -void SIO_Write(pscpu_timestamp_t timestamp, uint32 A, uint32 V); -uint32 SIO_Read(pscpu_timestamp_t timestamp, uint32 A); -void SIO_Power(void); - -} - -#endif diff --git a/psx/octoshock/psx/spu.cpp b/psx/octoshock/psx/spu.cpp deleted file mode 100644 index d6b4aac541c..00000000000 --- a/psx/octoshock/psx/spu.cpp +++ /dev/null @@ -1,1534 +0,0 @@ -/******************************************************************************/ -/* Mednafen Sony PS1 Emulation Module */ -/******************************************************************************/ -/* spu.cpp: -** Copyright (C) 2011-2016 Mednafen Team -** -** 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., -** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#pragma GCC optimize ("unroll-loops") - -/* TODO: - Note to self: Emulating the SPU at more timing accuracy than sample, and emulating the whole SPU RAM write port FIFO thing and hypothetical periodic FIFO commit to - SPU RAM(maybe every 32 CPU cycles, with exceptions?) will likely necessitate a much more timing-accurate CPU core, and emulation of the SPU delay register(or at least the - effects of the standard value written to it), to avoid game glitches. Probably more trouble than it's worth.... - - SPU IRQ emulation isn't totally correct, behavior is kind of complex; run more tests on PS1. - - Test reverb upsampler on the real thing. - - Alter reverb algorithm to process in the pattern of L,R,L,R,L,R on each input sample, instead of doing both L and R on every 2 input samples(make - sure the real thing does it this way too, I think it at least runs the downsampler this way). - - Alter reverb algorithm to perform saturation more often, as occurs on the real thing. - - See if sample flag & 0x8 does anything weird, like suppressing the program-readable block end flag setting. - - Determine the actual purpose of global register 0x2C(is it REALLY an address multiplier? And if so, does it affect the reverb offsets too?) - - For ADSR and volume sweep, should the divider be reset to 0 on &0x8000 == true, or should the upper bit be cleared? - - Should shift occur on all stages of ADPCM sample decoding, or only at the end? - - On the real thing, there's some kind of weirdness with ADSR when you voice on when attack_rate(raw) = 0x7F; the envelope level register is repeatedly - reset to 0, which you can see by manual writes to the envelope level register. Normally in the attack phase when attack_rate = 0x7F, enveloping is - effectively stuck/paused such that the value you write is sticky and won't be replaced or reset. Note that after you voice on, you can write a new - attack_rate < 0x7F, and enveloping will work "normally" again shortly afterwards. You can even write an attack_rate of 0x7F at that point to pause - enveloping clocking. I doubt any games rely on this, but it's something to keep in mind if we ever need greater insight as to how the SPU functions - at a low-level in order to emulate it at cycle granularity rather than sample granularity, and it may not be a bad idea to investigate this oddity - further and emulate it in the future regardless. - - Voice 1 and 3 waveform output writes to SPURAM might not be correct(noted due to problems reading this area of SPU RAM on the real thing - based on my expectations of how this should work). -*/ - -/* - Notes: - All addresses(for 16-bit access, at least) within the SPU address space appear to be fully read/write as if they were RAM, though - values at some addresses(like the envelope current value) will be "overwritten" by the sound processing at certain times. - - 32-bit and 8-bit reads act as if it were RAM(not tested with all addresses, but a few, assuming the rest are the same), but 8-bit writes - to odd addresses appear to be ignored, and 8-bit writes to even addresses are treated as 16-bit writes(most likely, but, need to code custom assembly to - fully test the upper 8 bits). NOTE: the preceding information doesn't necessarily cover accesses with side effects, they still need to be tested; and it - of course covers reads/writes from the point of view of software running on the CPU. - - It doesn't appear to be possible to enable FM on the first channel/voice(channel/voice 0). - - Lower bit of channel start address appears to be masked out to 0(such that ADPCM block decoding is always 8 16-bit units, 16 bytes, aligned), as far as - block-decoding and flag-set program-readable loop address go. -*/ - -/* - Update() isn't called on Read and Writes for performance reasons, it's called with sufficient granularity from the event - system, though this will obviously need to change if we ever emulate the SPU with better precision than per-sample(pair). -*/ - -#define SPUIRQ_DBG(format, ...) { printf("[SPUIRQDBG] " format " -- Voice 22 CA=0x%06x,LA=0x%06x\n", ## __VA_ARGS__, Voices[22].CurAddr, Voices[22].LoopAddr); } - -#include "psx.h" -#include "cdc.h" -#include "spu.h" - -namespace MDFN_IEN_PSX -{ - -static const int16 FIR_Table[256][4] = -{ - #include "spu_fir_table.inc" -}; - -PS_SPU::PS_SPU() -{ - last_rate = -1; - last_quality = ~0U; - - IntermediateBufferPos = 0; - memset(IntermediateBuffer, 0, sizeof(IntermediateBuffer)); -} - -PS_SPU::~PS_SPU() -{ -} - - -void PS_SPU::Power(void) -{ - clock_divider = 768; - - memset(SPURAM, 0, sizeof(SPURAM)); - - for(int i = 0; i < 24; i++) - { - memset(Voices[i].DecodeBuffer, 0, sizeof(Voices[i].DecodeBuffer)); - Voices[i].DecodeM2 = 0; - Voices[i].DecodeM1 = 0; - - Voices[i].DecodePlayDelay = 0; - Voices[i].DecodeWritePos = 0; - Voices[i].DecodeReadPos = 0; - Voices[i].DecodeAvail = 0; - - Voices[i].DecodeShift = 0; - Voices[i].DecodeWeight = 0; - Voices[i].DecodeFlags = 0; - - Voices[i].IgnoreSampLA = false; - - Voices[i].Sweep[0].Power(); - Voices[i].Sweep[1].Power(); - - Voices[i].Pitch = 0; - Voices[i].CurPhase = 0; - - Voices[i].StartAddr = 0; - - Voices[i].CurAddr = 0; - - Voices[i].ADSRControl = 0; - - Voices[i].LoopAddr = 0; - - Voices[i].PreLRSample = 0; - - memset(&Voices[i].ADSR, 0, sizeof(SPU_ADSR)); - } - - GlobalSweep[0].Power(); - GlobalSweep[1].Power(); - - NoiseDivider = 0; - NoiseCounter = 0; - LFSR = 0; - - FM_Mode = 0; - Noise_Mode = 0; - Reverb_Mode = 0; - ReverbWA = 0; - - ReverbVol[0] = ReverbVol[1] = 0; - - CDVol[0] = CDVol[1] = 0; - - ExternVol[0] = ExternVol[1] = 0; - - IRQAddr = 0; - - RWAddr = 0; - - SPUControl = 0; - - VoiceOn = 0; - VoiceOff = 0; - - BlockEnd = 0; - - CWA = 0; - - memset(Regs, 0, sizeof(Regs)); - memset(AuxRegs, 0, sizeof(AuxRegs)); - memset(RDSB, 0, sizeof(RDSB)); - memset(RUSB, 0, sizeof(RUSB)); - RvbResPos = 0; - - ReverbCur = ReverbWA; - - IRQAsserted = false; -} - -static INLINE void CalcVCDelta(const uint8 zs, uint8 speed, bool log_mode, bool dec_mode, bool inv_increment, int16 Current, int &increment, int &divinco) -{ - increment = (7 - (speed & 0x3)); - - if(inv_increment) - increment = ~increment; - - divinco = 32768; - - if(speed < 0x2C) - increment = (unsigned)increment << ((0x2F - speed) >> 2); - - if(speed >= 0x30) - divinco >>= (speed - 0x2C) >> 2; - - if(log_mode) - { - if(dec_mode) // Log decrement mode - increment = (Current * increment) >> 15; - else // Log increment mode - { - if((Current & 0x7FFF) >= 0x6000) - { - if(speed < 0x28) - increment >>= 2; - else if(speed >= 0x2C) - divinco >>= 2; - else // 0x28 ... 0x2B - { - increment >>= 1; - divinco >>= 1; - } - } - } - } // end if(log_mode) - - if(divinco == 0 && speed < zs) //0x7F) - divinco = 1; -} - - -INLINE void SPU_Sweep::Power(void) -{ - Control = 0; - Current = 0; - Divider = 0; -} - -INLINE void SPU_Sweep::WriteControl(uint16 value) -{ - Control = value; -} - -INLINE int16 SPU_Sweep::ReadVolume(void) -{ - return((int16)Current); -} - -void SPU_Sweep::Clock(void) -{ - if(!(Control & 0x8000)) - { - Current = (Control & 0x7FFF) << 1; - return; - } - - if(Control & 0x8000) // Sweep enabled - { - const bool log_mode = (bool)(Control & 0x4000); - const bool dec_mode = (bool)(Control & 0x2000); - const bool inv_mode = (bool)(Control & 0x1000); - const bool inv_increment = (dec_mode ^ inv_mode) | (dec_mode & log_mode); - const uint16 vc_cv_xor = (inv_mode & !(dec_mode & log_mode)) ? 0xFFFF : 0x0000; - const uint16 TestInvert = inv_mode ? 0xFFFF : 0x0000; - int increment; - int divinco; - - CalcVCDelta(0x7F, Control & 0x7F, log_mode, dec_mode, inv_increment, (int16)(Current ^ vc_cv_xor), increment, divinco); - //printf("%d %d\n", divinco, increment); - - if((dec_mode & !(inv_mode & log_mode)) && ((Current & 0x8000) == (inv_mode ? 0x0000 : 0x8000) || (Current == 0))) - { - // - // Not sure if this condition should stop the Divider adding or force the increment value to 0. - // - Current = 0; - } - else - { - Divider += divinco; - - if(Divider & 0x8000) - { - Divider = 0; - - if(dec_mode || ((Current ^ TestInvert) != 0x7FFF)) - { - uint16 PrevCurrent = Current; - Current = Current + increment; - - //printf("%04x %04x\n", PrevCurrent, Current); - - if(!dec_mode && ((Current ^ PrevCurrent) & 0x8000) && ((Current ^ TestInvert) & 0x8000)) - Current = 0x7FFF ^ TestInvert; - } - } - } - } -} - -INLINE void SPU_Sweep::WriteVolume(int16 value) -{ - Current = value; -} - - -// -// Take care not to trigger SPU IRQ for the next block before its decoding start. -// -void PS_SPU::RunDecoder(SPU_Voice *voice) -{ - // 5 through 0xF appear to be 0 on the real thing. - static const int32 Weights[16][2] = - { - // s-1 s-2 - { 0, 0 }, - { 60, 0 }, - { 115, -52 }, - { 98, -55 }, - { 122, -60 }, - }; - - if(voice->DecodeAvail >= 11) - { - if(SPUControl & 0x40) - { - unsigned test_addr = (voice->CurAddr - 1) & 0x3FFFF; - if(IRQAddr == test_addr || IRQAddr == (test_addr & 0x3FFF8)) - { - //SPUIRQ_DBG("SPU IRQ (VDA): 0x%06x", addr); - IRQAsserted = true; - IRQ_Assert(IRQ_SPU, IRQAsserted); - } - } - return; - } - - - if((voice->CurAddr & 0x7) == 0) - { - // - // Handle delayed flags from the previously-decoded block. - // - // NOTE: The timing of setting the BlockEnd bit here, and forcing ADSR envelope volume to 0, is a bit late. (And I'm not sure if it should be done once - // per decoded block, or more than once, but that's probably not something games would rely on, but we should test it anyway). - // - // Correctish timing can be achieved by moving this block of code up above voice->DecodeAvail >= 11, and sticking it inside an: if(voice->DecodeAvail <= 12), - // though more tests are needed on the ADPCM decoding process as a whole before we should actually make such a change. Additionally, we'd probably - // have to separate the CurAddr = LoopAddr logic, so we don't generate spurious early SPU IRQs. - // - if(voice->DecodeFlags & 0x1) - { - voice->CurAddr = voice->LoopAddr & ~0x7; - - BlockEnd |= 1 << (voice - Voices); - - if(!(voice->DecodeFlags & 0x2)) // Force enveloping to 0 if not "looping". TODO: Should we reset the ADSR divider counter too? - { - if(!(Noise_Mode & (1 << (voice - Voices)))) - { - voice->ADSR.Phase = ADSR_RELEASE; - voice->ADSR.EnvLevel = 0; - } - } - } - } - - //for(int z = 0; z < 4; z++) - { - if(SPUControl & 0x40) - { - unsigned test_addr = voice->CurAddr & 0x3FFFF; - if(IRQAddr == test_addr || IRQAddr == (test_addr & 0x3FFF8)) - { - //SPUIRQ_DBG("SPU IRQ: 0x%06x", addr); - IRQAsserted = true; - IRQ_Assert(IRQ_SPU, IRQAsserted); - } - } - - if((voice->CurAddr & 0x7) == 0) - { - const uint16 CV = SPURAM[voice->CurAddr]; - - voice->DecodeShift = CV & 0xF; - voice->DecodeWeight = (CV >> 4) & 0xF; - voice->DecodeFlags = (CV >> 8) & 0xFF; - - if(voice->DecodeFlags & 0x4) - { - if(!voice->IgnoreSampLA) - { - voice->LoopAddr = voice->CurAddr; - } - else - { - if((voice->LoopAddr ^ voice->CurAddr) & ~0x7) - { - PSX_DBG(PSX_DBG_FLOOD, "[SPU] Ignore: LoopAddr=0x%08x, SampLA=0x%08x\n", voice->LoopAddr, voice->CurAddr); - } - } - } - voice->CurAddr = (voice->CurAddr + 1) & 0x3FFFF; - } - - // - // Don't else this block; we need to ALWAYS decode 4 samples per call to RunDecoder() if DecodeAvail < 11, or else sample playback - // at higher rates will fail horribly. - // - { - const int32 weight_m1 = Weights[voice->DecodeWeight][0]; - const int32 weight_m2 = Weights[voice->DecodeWeight][1]; - uint16 CV; - unsigned shift; - uint32 coded; - int16 *tb = &voice->DecodeBuffer[voice->DecodeWritePos]; - - CV = SPURAM[voice->CurAddr]; - shift = voice->DecodeShift; - - if(MDFN_UNLIKELY(shift > 12)) - { - //PSX_DBG(PSX_DBG_FLOOD, "[SPU] Buggy/Illegal ADPCM block shift value on voice %u: %u\n", (unsigned)(voice - Voices), shift); - - shift = 8; - CV &= 0x8888; - } - - coded = (uint32)CV << 12; - - for(int i = 0; i < 4; i++) - { - int32 sample = (int16)(coded & 0xF000) >> shift; - - sample += ((voice->DecodeM2 * weight_m2) >> 6); - sample += ((voice->DecodeM1 * weight_m1) >> 6); - - clamp(&sample, -32768, 32767); - - tb[i] = sample; - voice->DecodeM2 = voice->DecodeM1; - voice->DecodeM1 = sample; - coded >>= 4; - } - voice->DecodeWritePos = (voice->DecodeWritePos + 4) & 0x1F; - voice->DecodeAvail += 4; - voice->CurAddr = (voice->CurAddr + 1) & 0x3FFFF; - } - } -} - -void PS_SPU::CacheEnvelope(SPU_Voice *voice) -{ - uint32 raw = voice->ADSRControl; - SPU_ADSR *ADSR = &voice->ADSR; - int32 Sl, Dr, Ar, Rr, Sr; - - Sl = (raw >> 0) & 0x0F; - Dr = (raw >> 4) & 0x0F; - Ar = (raw >> 8) & 0x7F; - - Rr = (raw >> 16) & 0x1F; - Sr = (raw >> 22) & 0x7F; - - - ADSR->AttackExp = (bool)(raw & (1 << 15)); - ADSR->ReleaseExp = (bool)(raw & (1 << 21)); - ADSR->SustainExp = (bool)(raw & (1 << 31)); - ADSR->SustainDec = (bool)(raw & (1 << 30)); - - ADSR->AttackRate = Ar; - ADSR->DecayRate = Dr << 2; - ADSR->SustainRate = Sr; - ADSR->ReleaseRate = Rr << 2; - - ADSR->SustainLevel = (Sl + 1) << 11; -} - -INLINE void PS_SPU::ResetEnvelope(SPU_Voice *voice) -{ - SPU_ADSR *ADSR = &voice->ADSR; - - ADSR->EnvLevel = 0; - ADSR->Divider = 0; - ADSR->Phase = ADSR_ATTACK; -} - -INLINE void PS_SPU::ReleaseEnvelope(SPU_Voice *voice) -{ - SPU_ADSR *ADSR = &voice->ADSR; - - ADSR->Divider = 0; - ADSR->Phase = ADSR_RELEASE; -} - - -INLINE void PS_SPU::RunEnvelope(SPU_Voice *voice) -{ - SPU_ADSR *ADSR = &voice->ADSR; - int increment; - int divinco; - int16 uoflow_reset; - - if(ADSR->Phase == ADSR_ATTACK && ADSR->EnvLevel == 0x7FFF) - ADSR->Phase++; - - //static INLINE void CalcVCDelta(const uint8 zs, uint8 speed, bool log_mode, bool decrement, bool inv_increment, int16 Current, int &increment, int &divinco) - switch(ADSR->Phase) - { - default: // Won't happen, but helps shut up gcc warnings. - case ADSR_ATTACK: - CalcVCDelta(0x7F, ADSR->AttackRate, ADSR->AttackExp, false, false, (int16)ADSR->EnvLevel, increment, divinco); - uoflow_reset = 0x7FFF; - break; - - case ADSR_DECAY: - CalcVCDelta(0x1F << 2, ADSR->DecayRate, true, true, true, (int16)ADSR->EnvLevel, increment, divinco); - uoflow_reset = 0; - break; - - case ADSR_SUSTAIN: - CalcVCDelta(0x7F, ADSR->SustainRate, ADSR->SustainExp, ADSR->SustainDec, ADSR->SustainDec, (int16)ADSR->EnvLevel, increment, divinco); - uoflow_reset = ADSR->SustainDec ? 0 : 0x7FFF; - break; - - case ADSR_RELEASE: - CalcVCDelta(0x1F << 2, ADSR->ReleaseRate, ADSR->ReleaseExp, true, true, (int16)ADSR->EnvLevel, increment, divinco); - uoflow_reset = 0; - break; - } - - ADSR->Divider += divinco; - if(ADSR->Divider & 0x8000) - { - const uint16 prev_level = ADSR->EnvLevel; - - ADSR->Divider = 0; - ADSR->EnvLevel += increment; - - if(ADSR->Phase == ADSR_ATTACK) - { - // If previous the upper bit was 0, but now it's 1, handle overflow. - if(((prev_level ^ ADSR->EnvLevel) & ADSR->EnvLevel) & 0x8000) - ADSR->EnvLevel = uoflow_reset; - } - else - { - if(ADSR->EnvLevel & 0x8000) - ADSR->EnvLevel = uoflow_reset; - } - if(ADSR->Phase == ADSR_DECAY && (uint16)ADSR->EnvLevel < ADSR->SustainLevel) - ADSR->Phase++; - } -} - -INLINE void PS_SPU::CheckIRQAddr(uint32 addr) -{ - if(SPUControl & 0x40) - { - if(IRQAddr == addr) - { - //SPUIRQ_DBG("SPU IRQ (ALT): 0x%06x", addr); - IRQAsserted = true; - IRQ_Assert(IRQ_SPU, IRQAsserted); - } - } -} - -INLINE void PS_SPU::WriteSPURAM(uint32 addr, uint16 value) -{ - CheckIRQAddr(addr); - - SPURAM[addr] = value; -} - -INLINE uint16 PS_SPU::ReadSPURAM(uint32 addr) -{ - CheckIRQAddr(addr); - return(SPURAM[addr]); -} - -#include "spu_reverb.inc" - -INLINE void PS_SPU::RunNoise(void) -{ - const unsigned rf = ((SPUControl >> 8) & 0x3F); - uint32 NoiseDividerInc = (2 << (rf >> 2)); - uint32 NoiseCounterInc = 4 + (rf & 0x3); - - if(rf >= 0x3C) - { - NoiseDividerInc = 0x8000; - NoiseCounterInc = 8; - } - - NoiseDivider += NoiseDividerInc; - if(NoiseDivider & 0x8000) - { - NoiseDivider = 0; - - NoiseCounter += NoiseCounterInc; - if(NoiseCounter & 0x8) - { - NoiseCounter &= 0x7; - LFSR = (LFSR << 1) | (((LFSR >> 15) ^ (LFSR >> 12) ^ (LFSR >> 11) ^ (LFSR >> 10) ^ 1) & 1); - } - } -} - -int32 PS_SPU::UpdateFromCDC(int32 clocks) -//pscpu_timestamp_t PS_SPU::Update(const pscpu_timestamp_t timestamp) -{ - //int32 clocks = timestamp - lastts; - int32 sample_clocks = 0; - //lastts = timestamp; - - clock_divider -= clocks; - - while(clock_divider <= 0) - { - clock_divider += 768; - sample_clocks++; - } - - while(sample_clocks > 0) - { - // xxx[0] = left, xxx[1] = right - - // Accumulated sound output. - int32 accum[2] = { 0, 0 }; - - // Accumulated sound output for reverb input - int32 accum_fv[2] = { 0, 0 }; - - // Output of reverb processing. - int32 reverb[2] = { 0, 0 }; - - // Final output. - int32 output[2] = { 0, 0 }; - - const uint32 PhaseModCache = FM_Mode & ~ 1; -/* -** -** 0x1F801DAE Notes and Conjecture: -** ------------------------------------------------------------------------------------- -** | 15 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 4 3 2 1 0 | -** | ? | *13| ? | ba | *10 | wrr|rdr| df | is | c | -** ------------------------------------------------------------------------------------- -** -** c - Appears to be delayed copy of lower 6 bits from 0x1F801DAA. -** -** is - Interrupt asserted out status. (apparently not instantaneous status though...) -** -** df - Related to (c & 0x30) == 0x20 or (c & 0x30) == 0x30, at least. -** 0 = DMA busy(FIFO not empty when in DMA write mode?)? -** 1 = DMA ready? Something to do with the FIFO? -** -** rdr - Read(DMA read?) Ready? -** -** wrr - Write(DMA write?) Ready? -** -** *10 - Unknown. Some sort of (FIFO?) busy status?(BIOS tests for this bit in places) -** -** ba - Alternates between 0 and 1, even when SPUControl bit15 is 0; might be related to CD audio and voice 1 and 3 writing to SPU RAM. -** -** *13 - Unknown, was set to 1 when testing with an SPU delay system reg value of 0x200921E1(test result might not be reliable, re-run). -*/ - SPUStatus = SPUControl & 0x3F; - SPUStatus |= IRQAsserted ? 0x40 : 0x00; - - if(Regs[0xD6] == 0x4) // TODO: Investigate more(case 0x2C in global regs r/w handler) - SPUStatus |= (CWA & 0x100) ? 0x800 : 0x000; - - for(int voice_num = 0; voice_num < 24; voice_num++) - { - SPU_Voice *voice = &Voices[voice_num]; - int32 voice_pvs; - - voice->PreLRSample = 0; - - //PSX_WARNING("[SPU] Voice %d CurPhase=%08x, pitch=%04x, CurAddr=%08x", voice_num, voice->CurPhase, voice->Pitch, voice->CurAddr); - - if(voice->DecodePlayDelay) - { - voice->IgnoreSampLA = false; - } - - // - // Decode new samples if necessary. - // - RunDecoder(voice); - - - // - // - // - int l, r; - - if(Noise_Mode & (1 << voice_num)) - voice_pvs = (int16)LFSR; - else - { - const int si = voice->DecodeReadPos; - const int pi = ((voice->CurPhase & 0xFFF) >> 4); - - voice_pvs = ((voice->DecodeBuffer[(si + 0) & 0x1F] * FIR_Table[pi][0]) + - (voice->DecodeBuffer[(si + 1) & 0x1F] * FIR_Table[pi][1]) + - (voice->DecodeBuffer[(si + 2) & 0x1F] * FIR_Table[pi][2]) + - (voice->DecodeBuffer[(si + 3) & 0x1F] * FIR_Table[pi][3])) >> 15; - } - - voice_pvs = (voice_pvs * (int16)voice->ADSR.EnvLevel) >> 15; - voice->PreLRSample = voice_pvs; - - if(voice_num == 1 || voice_num == 3) - { - int index = voice_num >> 1; - - WriteSPURAM(0x400 | (index * 0x200) | CWA, voice_pvs); - } - - - l = (voice_pvs * voice->Sweep[0].ReadVolume()) >> 15; - r = (voice_pvs * voice->Sweep[1].ReadVolume()) >> 15; - - accum[0] += l; - accum[1] += r; - - if(Reverb_Mode & (1 << voice_num)) - { - accum_fv[0] += l; - accum_fv[1] += r; - } - - // Run sweep - for(int lr = 0; lr < 2; lr++) - voice->Sweep[lr].Clock(); - - // Increment stuff - if(!voice->DecodePlayDelay) - { - unsigned phase_inc; - - // Run enveloping - RunEnvelope(voice); - - if(PhaseModCache & (1 << voice_num)) - { - // This old formula: phase_inc = (voice->Pitch * ((voice - 1)->PreLRSample + 0x8000)) >> 15; - // is incorrect, as it does not handle carrier pitches >= 0x8000 properly. - phase_inc = voice->Pitch + (((int16)voice->Pitch * ((voice - 1)->PreLRSample)) >> 15); - } - else - phase_inc = voice->Pitch; - - if(phase_inc > 0x3FFF) - phase_inc = 0x3FFF; - - { - const uint32 tmp_phase = voice->CurPhase + phase_inc; - const unsigned used = tmp_phase >> 12; - - voice->CurPhase = tmp_phase & 0xFFF; - voice->DecodeAvail -= used; - voice->DecodeReadPos = (voice->DecodeReadPos + used) & 0x1F; - } - } - else - voice->DecodePlayDelay--; - - if(VoiceOff & (1U << voice_num)) - { - if(voice->ADSR.Phase != ADSR_RELEASE) - { - // TODO/FIXME: - // To fix all the missing notes in "Dragon Ball GT: Final Bout" music, !voice->DecodePlayDelay instead of - // voice->DecodePlayDelay < 3 is necessary, but that would cause the length of time for which the voice off is - // effectively ignored to be too long by about half a sample(rough test measurement). That, combined with current - // CPU and DMA emulation timing inaccuracies(execution generally too fast), creates a significant risk of regressions - // in other games, so be very conservative for now. - // - // Also, voice on should be ignored during the delay as well, but comprehensive tests are needed before implementing that - // due to some effects that appear to occur repeatedly during the delay on a PS1 but are currently only emulated as - // performed when the voice on is processed(e.g. curaddr = startaddr). - // - if(voice->DecodePlayDelay < 3) - { - if(voice->DecodePlayDelay) - PSX_DBG(PSX_DBG_WARNING, "[SPU] Voice %u off maybe should be ignored, but isn't due to current emulation code limitations; dpd=%u\n", voice_num, voice->DecodePlayDelay); - - ReleaseEnvelope(voice); - } - else - PSX_DBG(PSX_DBG_WARNING, "[SPU] Voice %u off ignored.\n", voice_num); - } - } - - if(VoiceOn & (1U << voice_num)) - { - //printf("Voice On: %u\n", voice_num); - - ResetEnvelope(voice); - - voice->DecodeFlags = 0; - voice->DecodeWritePos = 0; - voice->DecodeReadPos = 0; - voice->DecodeAvail = 0; - voice->DecodePlayDelay = 4; - - BlockEnd &= ~(1 << voice_num); - - // - // Weight/filter previous value initialization: - // - voice->DecodeM2 = 0; - voice->DecodeM1 = 0; - - voice->CurPhase = 0; - voice->CurAddr = voice->StartAddr & ~0x7; - voice->IgnoreSampLA = false; - } - - if(!(SPUControl & 0x8000)) - { - voice->ADSR.Phase = ADSR_RELEASE; - voice->ADSR.EnvLevel = 0; - } - } - - VoiceOff = 0; - VoiceOn = 0; - - // "Mute" control doesn't seem to affect CD audio(though CD audio reverb wasn't tested...) - // TODO: If we add sub-sample timing accuracy, see if it's checked for every channel at different times, or just once. - if(!(SPUControl & 0x4000)) - { - accum[0] = 0; - accum[1] = 0; - accum_fv[0] = 0; - accum_fv[1] = 0; - } - - // Get CD-DA - { - int32 cda_raw[2]; - int32 cdav[2]; - - CDC->GetCDAudio(cda_raw); // PS_CDC::GetCDAudio() guarantees the variables passed by reference will be set to 0, - // and that their range shall be -32768 through 32767. - - WriteSPURAM(CWA | 0x000, cda_raw[0]); - WriteSPURAM(CWA | 0x200, cda_raw[1]); - - for(unsigned i = 0; i < 2; i++) - cdav[i] = (cda_raw[i] * CDVol[i]) >> 15; - - if(SPUControl & 0x0001) - { - accum[0] += cdav[0]; - accum[1] += cdav[1]; - - if(SPUControl & 0x0004) // TODO: Test this bit(and see if it is really dependent on bit0) - { - accum_fv[0] += cdav[0]; - accum_fv[1] += cdav[1]; - } - } - } - - CWA = (CWA + 1) & 0x1FF; - - RunNoise(); - - for(unsigned lr = 0; lr < 2; lr++) - clamp(&accum_fv[lr], -32768, 32767); - - RunReverb(accum_fv, reverb); - - for(unsigned lr = 0; lr < 2; lr++) - { - accum[lr] += ((reverb[lr] * ReverbVol[lr]) >> 15); - clamp(&accum[lr], -32768, 32767); - output[lr] = (accum[lr] * GlobalSweep[lr].ReadVolume()) >> 15; - clamp(&output[lr], -32768, 32767); - } - - if(IntermediateBufferPos < 4096) // Overflow might occur in some debugger use cases. - { - // 75%, for some (resampling) headroom. - for(unsigned lr = 0; lr < 2; lr++) - IntermediateBuffer[IntermediateBufferPos][lr] = (output[lr] * 3 + 2) >> 2; - - IntermediateBufferPos++; - } - - sample_clocks--; - - // Clock global sweep - for(unsigned lr = 0; lr < 2; lr++) - GlobalSweep[lr].Clock(); - } - - //assert(clock_divider < 768); - - return clock_divider; -} - -void PS_SPU::WriteDMA(uint32 V) -{ - //SPUIRQ_DBG("DMA Write, RWAddr after=0x%06x", RWAddr); - WriteSPURAM(RWAddr, V); - RWAddr = (RWAddr + 1) & 0x3FFFF; - - WriteSPURAM(RWAddr, V >> 16); - RWAddr = (RWAddr + 1) & 0x3FFFF; - - - CheckIRQAddr(RWAddr); -} - -uint32 PS_SPU::ReadDMA(void) -{ - uint32 ret; - - ret = (uint16)ReadSPURAM(RWAddr); - RWAddr = (RWAddr + 1) & 0x3FFFF; - - ret |= (uint32)(uint16)ReadSPURAM(RWAddr) << 16; - RWAddr = (RWAddr + 1) & 0x3FFFF; - - CheckIRQAddr(RWAddr); - - //SPUIRQ_DBG("DMA Read, RWAddr after=0x%06x", RWAddr); - - return(ret); -} - -void PS_SPU::Write(pscpu_timestamp_t timestamp, uint32 A, uint16 V) -{ - //if((A & 0x3FF) < 0x180) - // PSX_WARNING("[SPU] Write: %08x %04x", A, V); - - A &= 0x3FF; - - if(A >= 0x200) - { - //printf("Write: %08x %04x\n", A, V); - if(A < 0x260) - { - SPU_Voice *voice = &Voices[(A - 0x200) >> 2]; - voice->Sweep[(A & 2) >> 1].WriteVolume(V); - } - else if(A < 0x280) - AuxRegs[(A & 0x1F) >> 1] = V; - - return; - } - - if(A < 0x180) - { - SPU_Voice *voice = &Voices[A >> 4]; - - switch(A & 0xF) - { - case 0x00: - case 0x02: - voice->Sweep[(A & 2) >> 1].WriteControl(V); - break; - - case 0x04: voice->Pitch = V; - break; - - case 0x06: voice->StartAddr = (V << 2) & 0x3FFFF; - break; - - case 0x08: voice->ADSRControl &= 0xFFFF0000; - voice->ADSRControl |= V; - CacheEnvelope(voice); - break; - - case 0x0A: voice->ADSRControl &= 0x0000FFFF; - voice->ADSRControl |= V << 16; - CacheEnvelope(voice); - break; - - case 0x0C: voice->ADSR.EnvLevel = V; - break; - - case 0x0E: voice->LoopAddr = (V << 2) & 0x3FFFF; - voice->IgnoreSampLA = true; - - if(voice->DecodePlayDelay || (VoiceOn & (1U << (voice - Voices)))) - { - PSX_WARNING("[SPU] Loop address for voice %u written during voice on delay.", (unsigned)(voice - Voices)); - } - //if((voice - Voices) == 22) - //{ - // SPUIRQ_DBG("Manual loop address setting for voice %d: %04x", (int)(voice - Voices), V); - //} - break; - } - } - else - { - switch(A & 0x7F) - { - case 0x00: - case 0x02: GlobalSweep[(A & 2) >> 1].WriteControl(V); - break; - - case 0x04: ReverbVol[0] = (int16)V; - break; - - case 0x06: ReverbVol[1] = (int16)V; - break; - - // Voice ON: - case 0x08: VoiceOn &= 0xFFFF0000; - VoiceOn |= V << 0; - break; - - case 0x0a: VoiceOn &= 0x0000FFFF; - VoiceOn |= (V & 0xFF) << 16; - break; - - // Voice OFF: - case 0x0c: VoiceOff &= 0xFFFF0000; - VoiceOff |= V << 0; - break; - - case 0x0e: VoiceOff &= 0x0000FFFF; - VoiceOff |= (V & 0xFF) << 16; - break; - - case 0x10: FM_Mode &= 0xFFFF0000; - FM_Mode |= V << 0; - break; - - case 0x12: FM_Mode &= 0x0000FFFF; - FM_Mode |= (V & 0xFF) << 16; - break; - - case 0x14: Noise_Mode &= 0xFFFF0000; - Noise_Mode |= V << 0; - break; - - case 0x16: Noise_Mode &= 0x0000FFFF; - Noise_Mode |= (V & 0xFF) << 16; - break; - - case 0x18: Reverb_Mode &= 0xFFFF0000; - Reverb_Mode |= V << 0; - break; - - case 0x1A: Reverb_Mode &= 0x0000FFFF; - Reverb_Mode |= (V & 0xFF) << 16; - break; - - case 0x1C: BlockEnd &= 0xFFFF0000; - BlockEnd |= V << 0; - break; - - case 0x1E: BlockEnd &= 0x0000FFFF; - BlockEnd |= V << 16; - break; - - case 0x22: ReverbWA = (V << 2) & 0x3FFFF; - ReverbCur = ReverbWA; - //PSX_WARNING("[SPU] Reverb WA set: 0x%04x", V); - break; - - case 0x24: IRQAddr = (V << 2) & 0x3FFFF; - CheckIRQAddr(RWAddr); - //SPUIRQ_DBG("Set IRQAddr=0x%06x", IRQAddr); - break; - - case 0x26: RWAddr = (V << 2) & 0x3FFFF; - CheckIRQAddr(RWAddr); - //SPUIRQ_DBG("Set RWAddr=0x%06x", RWAddr); - break; - - case 0x28: WriteSPURAM(RWAddr, V); - RWAddr = (RWAddr + 1) & 0x3FFFF; - CheckIRQAddr(RWAddr); - break; - - case 0x2A: //if((SPUControl & 0x80) && !(V & 0x80)) - // printf("\n\n\n\n ************** REVERB PROCESSING DISABLED\n\n\n\n"); - - SPUControl = V; - //SPUIRQ_DBG("Set SPUControl=0x%04x -- IRQA=%06x, RWA=%06x", V, IRQAddr, RWAddr); - //printf("SPU control write: %04x\n", V); - if(!(V & 0x40)) - { - IRQAsserted = false; - IRQ_Assert(IRQ_SPU, IRQAsserted); - } - CheckIRQAddr(RWAddr); - break; - - case 0x2C: PSX_WARNING("[SPU] Global reg 0x2c set: 0x%04x", V); - break; - - case 0x30: CDVol[0] = (int16)V; - break; - - case 0x32: CDVol[1] = (int16)V; - break; - - case 0x34: ExternVol[0] = (int16)V; - break; - - case 0x36: ExternVol[1] = (int16)V; - break; - - case 0x38: - case 0x3A: GlobalSweep[(A & 2) >> 1].WriteVolume(V); - break; - } - } - - Regs[(A & 0x1FF) >> 1] = V; -} - -uint16 PS_SPU::Read(pscpu_timestamp_t timestamp, uint32 A) -{ - A &= 0x3FF; - - PSX_DBGINFO("[SPU] Read: %08x", A); - - if(A >= 0x200) - { - if(A < 0x260) - { - SPU_Voice *voice = &Voices[(A - 0x200) >> 2]; - - //printf("Read: %08x %04x\n", A, voice->Sweep[(A & 2) >> 1].ReadVolume()); - - return voice->Sweep[(A & 2) >> 1].ReadVolume(); - } - else if(A < 0x280) - return(AuxRegs[(A & 0x1F) >> 1]); - - return(0xFFFF); - } - - - if(A < 0x180) - { - SPU_Voice *voice = &Voices[A >> 4]; - - switch(A & 0xF) - { - case 0x0C: return(voice->ADSR.EnvLevel); - case 0x0E: return(voice->LoopAddr >> 2); - } - } - else - { - switch(A & 0x7F) - { - case 0x1C: return(BlockEnd); - case 0x1E: return(BlockEnd >> 16); - - case 0x26: //PSX_WARNING("[SPU] RWADDR Read"); - break; - - case 0x28: PSX_WARNING("[SPU] SPURAM Read port(?) Read"); - - { - uint16 ret = ReadSPURAM(RWAddr); - - RWAddr = (RWAddr + 1) & 0x3FFFF; - CheckIRQAddr(RWAddr); - - return(ret); - } - - case 0x2a: - return(SPUControl); - -/* FIXME: What is this used for? */ - case 0x3C: - //PSX_WARNING("[SPU] Read Unknown: %08x", A); - return(0); - - case 0x38: - case 0x3A: return(GlobalSweep[(A & 2) >> 1].ReadVolume()); - } - } - - return(Regs[(A & 0x1FF) >> 1]); -} - - -void PS_SPU::StartFrame(double rate, uint32 quality) -{ - if((int)rate != last_rate || quality != last_quality) - { - int err = 0; - - last_rate = (int)rate; - last_quality = quality; - } - -} - -int32 PS_SPU::EndFrame(int16 *SoundBuf) -{ - //lastts = 0; - - if(last_rate == 44100) - { - int32 ret = IntermediateBufferPos; - - memcpy(SoundBuf, IntermediateBuffer, IntermediateBufferPos * 2 * sizeof(int16)); - IntermediateBufferPos = 0; - - return(ret); - } - else - { - IntermediateBufferPos = 0; - return 0; - } -} - -SYNCFUNC(PS_SPU) -{ - NSS(Voices); - - NSS(NoiseDivider); - NSS(NoiseCounter); - NSS(LFSR); - - NSS(FM_Mode); - NSS(Noise_Mode); - NSS(Reverb_Mode); - - NSS(ReverbWA); - - NSS(GlobalSweep); - - NSS(ReverbVol); - - NSS(CDVol); - NSS(ExternVol); - - NSS(IRQAddr); - - NSS(RWAddr); - - NSS(SPUControl); - - NSS(VoiceOn); - NSS(VoiceOff); - - NSS(BlockEnd); - - NSS(CWA); - - NSS(Regs); - NSS(AuxRegs); - - NSS(RDSB); - NSS(RUSB); - NSS(RvbResPos); - - - NSS(ReverbCur); - NSS(IRQAsserted); - - NSS(clock_divider); - - NSS(SPURAM); - - if(isReader) - { - for(unsigned i = 0; i < 24; i++) - { - Voices[i].DecodeReadPos &= 0x1F; - Voices[i].DecodeWritePos &= 0x1F; - Voices[i].CurAddr &= 0x3FFFF; - Voices[i].StartAddr &= 0x3FFFF; - Voices[i].LoopAddr &= 0x3FFFF; - } - - if(clock_divider <= 0 || clock_divider > 768) - clock_divider = 768; - - RWAddr &= 0x3FFFF; - CWA &= 0x1FF; - - ReverbWA &= 0x3FFFF; - ReverbCur &= 0x3FFFF; - - RvbResPos &= 0x3F; - - IRQ_Assert(IRQ_SPU, IRQAsserted); - } -} - -uint16 PS_SPU::PeekSPURAM(uint32 address) -{ - return(SPURAM[address & 0x3FFFF]); -} - -void PS_SPU::PokeSPURAM(uint32 address, uint16 value) -{ - SPURAM[address & 0x3FFFF] = value; -} - -uint32 PS_SPU::GetRegister(unsigned int which, char *special, const uint32 special_len) -{ - uint32 ret = 0xDEADBEEF; - - if(which >= 0x8000) - { - unsigned int v = (which - 0x8000) >> 8; - - switch((which & 0xFF) | 0x8000) - { - case GSREG_V0_VOL_CTRL_L: - ret = Regs[v * 8 + 0x0]; - break; - - case GSREG_V0_VOL_CTRL_R: - ret = Regs[v * 8 + 0x1]; - break; - - case GSREG_V0_VOL_L: - ret = Voices[v].Sweep[0].ReadVolume() & 0xFFFF; - break; - - case GSREG_V0_VOL_R: - ret = Voices[v].Sweep[1].ReadVolume() & 0xFFFF; - break; - - case GSREG_V0_PITCH: - ret = Voices[v].Pitch; - break; - - case GSREG_V0_STARTADDR: - ret = Voices[v].StartAddr; - break; - - case GSREG_V0_ADSR_CTRL: - ret = Voices[v].ADSRControl; - break; - - case GSREG_V0_ADSR_LEVEL: - ret = Voices[v].ADSR.EnvLevel; - break; - - case GSREG_V0_LOOP_ADDR: - ret = Voices[v].LoopAddr; - break; - - case GSREG_V0_READ_ADDR: - ret = Voices[v].CurAddr; - break; - } - } - else if(which >= GSREG_FB_SRC_A && which <= GSREG_IN_COEF_R) - { - ret = ReverbRegs[which - GSREG_FB_SRC_A]; - } - else switch(which) - { - case GSREG_SPUCONTROL: - ret = SPUControl; - break; - - case GSREG_FM_ON: - ret = FM_Mode; - break; - - case GSREG_NOISE_ON: - ret = Noise_Mode; - break; - - case GSREG_REVERB_ON: - ret = Reverb_Mode; - break; - - case GSREG_CDVOL_L: - ret = (uint16)CDVol[0]; - break; - - case GSREG_CDVOL_R: - ret = (uint16)CDVol[1]; - break; - - case GSREG_MAINVOL_CTRL_L: - ret = Regs[0xC0]; - break; - - case GSREG_MAINVOL_CTRL_R: - ret = Regs[0xC1]; - break; - - case GSREG_MAINVOL_L: - ret = GlobalSweep[0].ReadVolume() & 0xFFFF; - break; - - case GSREG_MAINVOL_R: - ret = GlobalSweep[1].ReadVolume() & 0xFFFF; - break; - - case GSREG_RVBVOL_L: - ret = (uint16)ReverbVol[0]; - break; - - case GSREG_RVBVOL_R: - ret = (uint16)ReverbVol[1]; - break; - - case GSREG_RWADDR: - ret = RWAddr; - break; - - case GSREG_IRQADDR: - ret = IRQAddr; - break; - - case GSREG_REVERBWA: - ret = ReverbWA >> 2; - break; - - case GSREG_VOICEON: - ret = VoiceOn; - break; - - case GSREG_VOICEOFF: - ret = VoiceOff; - break; - - case GSREG_BLOCKEND: - ret = BlockEnd; - break; - } - - return(ret); -} - -void PS_SPU::SetRegister(unsigned int which, uint32 value) -{ - if(which >= GSREG_FB_SRC_A && which <= GSREG_IN_COEF_R) - { - ReverbRegs[which - GSREG_FB_SRC_A] = value; - } - else switch(which) - { - case GSREG_SPUCONTROL: - SPUControl = value; - break; - - case GSREG_FM_ON: - FM_Mode = value & 0xFFFFFF; - break; - - case GSREG_NOISE_ON: - Noise_Mode = value & 0xFFFFFF; - break; - - case GSREG_REVERB_ON: - Reverb_Mode = value & 0xFFFFFF; - break; - - case GSREG_CDVOL_L: - CDVol[0] = (int16)value; - break; - - case GSREG_CDVOL_R: - CDVol[1] = (int16)value; - break; - - case GSREG_MAINVOL_CTRL_L: - Regs[0xC0] = value; - GlobalSweep[0].WriteControl(value); - //GlobalSweep[0].Control = value; - break; - - case GSREG_MAINVOL_CTRL_R: - Regs[0xC1] = value; - GlobalSweep[1].WriteControl(value); - //GlobalSweep[1].Control = value; - break; - - case GSREG_MAINVOL_L: - GlobalSweep[0].WriteVolume(value); - break; - - case GSREG_MAINVOL_R: - GlobalSweep[1].WriteVolume(value); - break; - - case GSREG_RVBVOL_L: - ReverbVol[0] = (int16)value; - break; - - case GSREG_RVBVOL_R: - ReverbVol[1] = (int16)value; - break; - - case GSREG_RWADDR: - RWAddr = value & 0x3FFFF; - break; - - case GSREG_IRQADDR: - IRQAddr = value & 0x3FFFC; - break; - - // - // REVERB_WA - // - - case GSREG_VOICEON: - VoiceOn = value & 0xFFFFFF; - break; - - case GSREG_VOICEOFF: - VoiceOff = value & 0xFFFFFF; - break; - - case GSREG_BLOCKEND: - BlockEnd = value & 0xFFFFFF; - break; - } -} - - - -} diff --git a/psx/octoshock/psx/spu.h b/psx/octoshock/psx/spu.h deleted file mode 100644 index e3b1a2422d3..00000000000 --- a/psx/octoshock/psx/spu.h +++ /dev/null @@ -1,352 +0,0 @@ -/******************************************************************************/ -/* Mednafen Sony PS1 Emulation Module */ -/******************************************************************************/ -/* spu.h: -** Copyright (C) 2011-2016 Mednafen Team -** -** 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., -** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef __MDFN_PSX_SPU_H -#define __MDFN_PSX_SPU_H - -namespace MDFN_IEN_PSX -{ - -enum -{ - ADSR_ATTACK = 0, - ADSR_DECAY = 1, - ADSR_SUSTAIN = 2, - ADSR_RELEASE = 3 -}; - -struct SPU_ADSR -{ - uint16 EnvLevel; // We typecast it to (int16) in several places, but keep it here as (uint16) to prevent signed overflow/underflow, which compilers - // may not treat consistently. - uint32 Divider; - uint32 Phase; - - bool AttackExp; - bool SustainExp; - bool SustainDec; - bool ReleaseExp; - - int32 AttackRate; // Ar - int32 DecayRate; // Dr * 4 - int32 SustainRate; // Sr - int32 ReleaseRate; // Rr * 4 - - int32 SustainLevel; // (Sl + 1) << 11 -}; - -class PS_SPU; -class SPU_Sweep -{ - friend class PS_SPU; // For save states - FIXME(remove in future?) - - public: - SPU_Sweep() { } - ~SPU_Sweep() { } - - void Power(void); - - void WriteControl(uint16 value); - int16 ReadVolume(void); - - void WriteVolume(int16 value); - - void Clock(void); - - private: - uint16 Control; - uint16 Current; // We typecast it to (int16) in several places, but keep it here as (uint16) to prevent signed overflow/underflow, which compilers - // may not treat consistently. - uint32 Divider; -}; - -struct SPU_Voice -{ - int16 DecodeBuffer[0x20]; - int16 DecodeM2; - int16 DecodeM1; - - uint32 DecodePlayDelay; - uint32 DecodeWritePos; - uint32 DecodeReadPos; - uint32 DecodeAvail; - - uint8 DecodeShift; - uint8 DecodeWeight; - uint8 DecodeFlags; - - bool IgnoreSampLA; - - SPU_Sweep Sweep[2]; - - uint16 Pitch; - uint32 CurPhase; - - uint32 StartAddr; - - uint32 CurAddr; - - uint32 ADSRControl; - - uint32 LoopAddr; - - int32 PreLRSample; // After enveloping, but before L/R volume. Range of -32768 to 32767 - - SPU_ADSR ADSR; -}; - -class PS_SPU -{ - public: - - PS_SPU() MDFN_COLD; - ~PS_SPU() MDFN_COLD; - - templatevoid SyncState(EW::NewState *ns); - - void Power(void) MDFN_COLD; - void Write(pscpu_timestamp_t timestamp, uint32 A, uint16 V); - uint16 Read(pscpu_timestamp_t timestamp, uint32 A); - - void WriteDMA(uint32 V); - uint32 ReadDMA(void); - - void StartFrame(double rate, uint32 quality); - int32 EndFrame(int16 *SoundBuf); - - int32 UpdateFromCDC(int32 clocks); - //pscpu_timestamp_t Update(pscpu_timestamp_t timestamp); - - uint16 SPURAM[524288 / sizeof(uint16)]; - -private: - - void CheckIRQAddr(uint32 addr); - void WriteSPURAM(uint32 addr, uint16 value); - uint16 ReadSPURAM(uint32 addr); - - void RunDecoder(SPU_Voice *voice); - - void CacheEnvelope(SPU_Voice *voice); - void ResetEnvelope(SPU_Voice *voice); - void ReleaseEnvelope(SPU_Voice *voice); - void RunEnvelope(SPU_Voice *voice); - - -void RunReverb(const int32* in, int32* out); - void RunNoise(void); - bool GetCDAudio(int32 &l, int32 &r); - - SPU_Voice Voices[24]; - - uint32 NoiseDivider; - uint32 NoiseCounter; - uint16 LFSR; - - uint32 FM_Mode; - uint32 Noise_Mode; - uint32 Reverb_Mode; - - uint32 ReverbWA; - - SPU_Sweep GlobalSweep[2]; // Doesn't affect reverb volume! - - int32 ReverbVol[2]; - - int32 CDVol[2]; - int32 ExternVol[2]; - - uint32 IRQAddr; - - uint32 RWAddr; - - uint16 SPUControl; - - uint32 VoiceOn; - uint32 VoiceOff; - - uint32 BlockEnd; - - uint32 CWA; - - union - { - uint16 Regs[0x100]; - struct - { - uint16 VoiceRegs[0xC0]; - union - { - uint16 GlobalRegs[0x20]; - struct - { - uint16 _Global0[0x17]; - uint16 SPUStatus; - uint16 _Global1[0x08]; - }; - }; - union - { - uint16 ReverbRegs[0x20]; - - struct - { - uint16 FB_SRC_A; - uint16 FB_SRC_B; - int16 IIR_ALPHA; - int16 ACC_COEF_A; - int16 ACC_COEF_B; - int16 ACC_COEF_C; - int16 ACC_COEF_D; - int16 IIR_COEF; - int16 FB_ALPHA; - int16 FB_X; - uint16 IIR_DEST_A[2]; - uint16 ACC_SRC_A[2]; - uint16 ACC_SRC_B[2]; - uint16 IIR_SRC_A[2]; - uint16 IIR_DEST_B[2]; - uint16 ACC_SRC_C[2]; - uint16 ACC_SRC_D[2]; - uint16 IIR_SRC_B[2]; - uint16 MIX_DEST_A[2]; - uint16 MIX_DEST_B[2]; - int16 IN_COEF[2]; - }; - }; - }; - }; - - uint16 AuxRegs[0x10]; - - int16 RDSB[2][128]; - int16 RUSB[2][64]; - int32 RvbResPos; - - uint32 ReverbCur; - - uint32 Get_Reverb_Offset(uint32 offset); - int16 RD_RVB(uint16 raw_offs, int32 extra_offs = 0); - void WR_RVB(uint16 raw_offs, int16 sample); - - bool IRQAsserted; - - //pscpu_timestamp_t lastts; - int32 clock_divider; - - int last_rate; - uint32 last_quality; - - // Buffers 44.1KHz samples, should have enough for two(worst-case scenario) video frames(2* ~735 frames NTSC, 2* ~882 PAL) plus jitter plus enough for the resampler leftovers. - // We'll just go with 4096 because powers of 2 are AWESOME and such. - uint32 IntermediateBufferPos; - int16 IntermediateBuffer[4096][2]; - - public: - enum - { - GSREG_SPUCONTROL = 0, - - GSREG_FM_ON, - GSREG_NOISE_ON, - GSREG_REVERB_ON, - - GSREG_CDVOL_L, - GSREG_CDVOL_R, - - GSREG_MAINVOL_CTRL_L, - GSREG_MAINVOL_CTRL_R, - - GSREG_MAINVOL_L, - GSREG_MAINVOL_R, - - GSREG_RVBVOL_L, - GSREG_RVBVOL_R, - - GSREG_RWADDR, - - GSREG_IRQADDR, - - GSREG_REVERBWA, - - GSREG_VOICEON, - GSREG_VOICEOFF, - GSREG_BLOCKEND, - - // Note: the order of these should match the reverb reg array - GSREG_FB_SRC_A, - GSREG_FB_SRC_B, - GSREG_IIR_ALPHA, - GSREG_ACC_COEF_A, - GSREG_ACC_COEF_B, - GSREG_ACC_COEF_C, - GSREG_ACC_COEF_D, - GSREG_IIR_COEF, - GSREG_FB_ALPHA, - GSREG_FB_X, - GSREG_IIR_DEST_A0, - GSREG_IIR_DEST_A1, - GSREG_ACC_SRC_A0, - GSREG_ACC_SRC_A1, - GSREG_ACC_SRC_B0, - GSREG_ACC_SRC_B1, - GSREG_IIR_SRC_A0, - GSREG_IIR_SRC_A1, - GSREG_IIR_DEST_B0, - GSREG_IIR_DEST_B1, - GSREG_ACC_SRC_C0, - GSREG_ACC_SRC_C1, - GSREG_ACC_SRC_D0, - GSREG_ACC_SRC_D1, - GSREG_IIR_SRC_B1, - GSREG_IIR_SRC_B0, - GSREG_MIX_DEST_A0, - GSREG_MIX_DEST_A1, - GSREG_MIX_DEST_B0, - GSREG_MIX_DEST_B1, - GSREG_IN_COEF_L, - GSREG_IN_COEF_R, - - - // Multiply v * 256 for each extra voice - GSREG_V0_VOL_CTRL_L = 0x8000, - GSREG_V0_VOL_CTRL_R, - GSREG_V0_VOL_L, - GSREG_V0_VOL_R, - GSREG_V0_PITCH, - GSREG_V0_STARTADDR, - GSREG_V0_ADSR_CTRL, - GSREG_V0_ADSR_LEVEL, - GSREG_V0_LOOP_ADDR, - GSREG_V0_READ_ADDR - }; - - uint32 GetRegister(unsigned int which, char *special, const uint32 special_len); - void SetRegister(unsigned int which, uint32 value); - - uint16 PeekSPURAM(uint32 address); - void PokeSPURAM(uint32 address, uint16 value); -}; - - -} - -#endif diff --git a/psx/octoshock/psx/spu_fir_table.inc b/psx/octoshock/psx/spu_fir_table.inc deleted file mode 100644 index dabee3cb18b..00000000000 --- a/psx/octoshock/psx/spu_fir_table.inc +++ /dev/null @@ -1,256 +0,0 @@ - { (int16)0x12c7, (int16)0x59b3, (int16)0x1307, (int16)0xffff }, - { (int16)0x1288, (int16)0x59b2, (int16)0x1347, (int16)0xffff }, - { (int16)0x1249, (int16)0x59b0, (int16)0x1388, (int16)0xffff }, - { (int16)0x120b, (int16)0x59ad, (int16)0x13c9, (int16)0xffff }, - { (int16)0x11cd, (int16)0x59a9, (int16)0x140b, (int16)0xffff }, - { (int16)0x118f, (int16)0x59a4, (int16)0x144d, (int16)0xffff }, - { (int16)0x1153, (int16)0x599e, (int16)0x1490, (int16)0xffff }, - { (int16)0x1116, (int16)0x5997, (int16)0x14d4, (int16)0xffff }, - { (int16)0x10db, (int16)0x598f, (int16)0x1517, (int16)0xffff }, - { (int16)0x109f, (int16)0x5986, (int16)0x155c, (int16)0xffff }, - { (int16)0x1065, (int16)0x597c, (int16)0x15a0, (int16)0xffff }, - { (int16)0x102a, (int16)0x5971, (int16)0x15e6, (int16)0xffff }, - { (int16)0x0ff1, (int16)0x5965, (int16)0x162c, (int16)0xffff }, - { (int16)0x0fb7, (int16)0x5958, (int16)0x1672, (int16)0xffff }, - { (int16)0x0f7f, (int16)0x5949, (int16)0x16b9, (int16)0xffff }, - { (int16)0x0f46, (int16)0x593a, (int16)0x1700, (int16)0xffff }, - { (int16)0x0f0f, (int16)0x592a, (int16)0x1747, (int16)0x0000 }, - { (int16)0x0ed7, (int16)0x5919, (int16)0x1790, (int16)0x0000 }, - { (int16)0x0ea1, (int16)0x5907, (int16)0x17d8, (int16)0x0000 }, - { (int16)0x0e6b, (int16)0x58f4, (int16)0x1821, (int16)0x0000 }, - { (int16)0x0e35, (int16)0x58e0, (int16)0x186b, (int16)0x0000 }, - { (int16)0x0e00, (int16)0x58cb, (int16)0x18b5, (int16)0x0000 }, - { (int16)0x0dcb, (int16)0x58b5, (int16)0x1900, (int16)0x0000 }, - { (int16)0x0d97, (int16)0x589e, (int16)0x194b, (int16)0x0001 }, - { (int16)0x0d63, (int16)0x5886, (int16)0x1996, (int16)0x0001 }, - { (int16)0x0d30, (int16)0x586d, (int16)0x19e2, (int16)0x0001 }, - { (int16)0x0cfd, (int16)0x5853, (int16)0x1a2e, (int16)0x0001 }, - { (int16)0x0ccb, (int16)0x5838, (int16)0x1a7b, (int16)0x0002 }, - { (int16)0x0c99, (int16)0x581c, (int16)0x1ac8, (int16)0x0002 }, - { (int16)0x0c68, (int16)0x57ff, (int16)0x1b16, (int16)0x0002 }, - { (int16)0x0c38, (int16)0x57e2, (int16)0x1b64, (int16)0x0003 }, - { (int16)0x0c07, (int16)0x57c3, (int16)0x1bb3, (int16)0x0003 }, - { (int16)0x0bd8, (int16)0x57a3, (int16)0x1c02, (int16)0x0003 }, - { (int16)0x0ba9, (int16)0x5782, (int16)0x1c51, (int16)0x0004 }, - { (int16)0x0b7a, (int16)0x5761, (int16)0x1ca1, (int16)0x0004 }, - { (int16)0x0b4c, (int16)0x573e, (int16)0x1cf1, (int16)0x0005 }, - { (int16)0x0b1e, (int16)0x571b, (int16)0x1d42, (int16)0x0005 }, - { (int16)0x0af1, (int16)0x56f6, (int16)0x1d93, (int16)0x0006 }, - { (int16)0x0ac4, (int16)0x56d1, (int16)0x1de5, (int16)0x0007 }, - { (int16)0x0a98, (int16)0x56ab, (int16)0x1e37, (int16)0x0007 }, - { (int16)0x0a6c, (int16)0x5684, (int16)0x1e89, (int16)0x0008 }, - { (int16)0x0a40, (int16)0x565b, (int16)0x1edc, (int16)0x0009 }, - { (int16)0x0a16, (int16)0x5632, (int16)0x1f2f, (int16)0x0009 }, - { (int16)0x09eb, (int16)0x5609, (int16)0x1f82, (int16)0x000a }, - { (int16)0x09c1, (int16)0x55de, (int16)0x1fd6, (int16)0x000b }, - { (int16)0x0998, (int16)0x55b2, (int16)0x202a, (int16)0x000c }, - { (int16)0x096f, (int16)0x5585, (int16)0x207f, (int16)0x000d }, - { (int16)0x0946, (int16)0x5558, (int16)0x20d4, (int16)0x000e }, - { (int16)0x091e, (int16)0x5529, (int16)0x2129, (int16)0x000f }, - { (int16)0x08f7, (int16)0x54fa, (int16)0x217f, (int16)0x0010 }, - { (int16)0x08d0, (int16)0x54ca, (int16)0x21d5, (int16)0x0011 }, - { (int16)0x08a9, (int16)0x5499, (int16)0x222c, (int16)0x0012 }, - { (int16)0x0883, (int16)0x5467, (int16)0x2282, (int16)0x0013 }, - { (int16)0x085d, (int16)0x5434, (int16)0x22da, (int16)0x0015 }, - { (int16)0x0838, (int16)0x5401, (int16)0x2331, (int16)0x0016 }, - { (int16)0x0813, (int16)0x53cc, (int16)0x2389, (int16)0x0018 }, - { (int16)0x07ef, (int16)0x5397, (int16)0x23e1, (int16)0x0019 }, - { (int16)0x07cb, (int16)0x5361, (int16)0x2439, (int16)0x001b }, - { (int16)0x07a7, (int16)0x532a, (int16)0x2492, (int16)0x001c }, - { (int16)0x0784, (int16)0x52f3, (int16)0x24eb, (int16)0x001e }, - { (int16)0x0762, (int16)0x52ba, (int16)0x2545, (int16)0x0020 }, - { (int16)0x0740, (int16)0x5281, (int16)0x259e, (int16)0x0021 }, - { (int16)0x071e, (int16)0x5247, (int16)0x25f8, (int16)0x0023 }, - { (int16)0x06fd, (int16)0x520c, (int16)0x2653, (int16)0x0025 }, - { (int16)0x06dc, (int16)0x51d0, (int16)0x26ad, (int16)0x0027 }, - { (int16)0x06bb, (int16)0x5194, (int16)0x2708, (int16)0x0029 }, - { (int16)0x069b, (int16)0x5156, (int16)0x2763, (int16)0x002c }, - { (int16)0x067c, (int16)0x5118, (int16)0x27be, (int16)0x002e }, - { (int16)0x065c, (int16)0x50da, (int16)0x281a, (int16)0x0030 }, - { (int16)0x063e, (int16)0x509a, (int16)0x2876, (int16)0x0033 }, - { (int16)0x061f, (int16)0x505a, (int16)0x28d2, (int16)0x0035 }, - { (int16)0x0601, (int16)0x5019, (int16)0x292e, (int16)0x0038 }, - { (int16)0x05e4, (int16)0x4fd7, (int16)0x298b, (int16)0x003a }, - { (int16)0x05c7, (int16)0x4f95, (int16)0x29e7, (int16)0x003d }, - { (int16)0x05aa, (int16)0x4f52, (int16)0x2a44, (int16)0x0040 }, - { (int16)0x058e, (int16)0x4f0e, (int16)0x2aa1, (int16)0x0043 }, - { (int16)0x0572, (int16)0x4ec9, (int16)0x2aff, (int16)0x0046 }, - { (int16)0x0556, (int16)0x4e84, (int16)0x2b5c, (int16)0x0049 }, - { (int16)0x053b, (int16)0x4e3e, (int16)0x2bba, (int16)0x004d }, - { (int16)0x0520, (int16)0x4df7, (int16)0x2c18, (int16)0x0050 }, - { (int16)0x0506, (int16)0x4db0, (int16)0x2c76, (int16)0x0054 }, - { (int16)0x04ec, (int16)0x4d68, (int16)0x2cd4, (int16)0x0057 }, - { (int16)0x04d2, (int16)0x4d20, (int16)0x2d33, (int16)0x005b }, - { (int16)0x04b9, (int16)0x4cd7, (int16)0x2d91, (int16)0x005f }, - { (int16)0x04a0, (int16)0x4c8d, (int16)0x2df0, (int16)0x0063 }, - { (int16)0x0488, (int16)0x4c42, (int16)0x2e4f, (int16)0x0067 }, - { (int16)0x0470, (int16)0x4bf7, (int16)0x2eae, (int16)0x006b }, - { (int16)0x0458, (int16)0x4bac, (int16)0x2f0d, (int16)0x006f }, - { (int16)0x0441, (int16)0x4b5f, (int16)0x2f6c, (int16)0x0074 }, - { (int16)0x042a, (int16)0x4b13, (int16)0x2fcc, (int16)0x0078 }, - { (int16)0x0413, (int16)0x4ac5, (int16)0x302b, (int16)0x007d }, - { (int16)0x03fc, (int16)0x4a77, (int16)0x308b, (int16)0x0082 }, - { (int16)0x03e7, (int16)0x4a29, (int16)0x30ea, (int16)0x0087 }, - { (int16)0x03d1, (int16)0x49d9, (int16)0x314a, (int16)0x008c }, - { (int16)0x03bc, (int16)0x498a, (int16)0x31aa, (int16)0x0091 }, - { (int16)0x03a7, (int16)0x493a, (int16)0x3209, (int16)0x0096 }, - { (int16)0x0392, (int16)0x48e9, (int16)0x3269, (int16)0x009c }, - { (int16)0x037e, (int16)0x4898, (int16)0x32c9, (int16)0x00a1 }, - { (int16)0x036a, (int16)0x4846, (int16)0x3329, (int16)0x00a7 }, - { (int16)0x0356, (int16)0x47f4, (int16)0x3389, (int16)0x00ad }, - { (int16)0x0343, (int16)0x47a1, (int16)0x33e9, (int16)0x00b3 }, - { (int16)0x0330, (int16)0x474e, (int16)0x3449, (int16)0x00ba }, - { (int16)0x031d, (int16)0x46fa, (int16)0x34a9, (int16)0x00c0 }, - { (int16)0x030b, (int16)0x46a6, (int16)0x3509, (int16)0x00c7 }, - { (int16)0x02f9, (int16)0x4651, (int16)0x3569, (int16)0x00cd }, - { (int16)0x02e7, (int16)0x45fc, (int16)0x35c9, (int16)0x00d4 }, - { (int16)0x02d6, (int16)0x45a6, (int16)0x3629, (int16)0x00db }, - { (int16)0x02c4, (int16)0x4550, (int16)0x3689, (int16)0x00e3 }, - { (int16)0x02b4, (int16)0x44fa, (int16)0x36e8, (int16)0x00ea }, - { (int16)0x02a3, (int16)0x44a3, (int16)0x3748, (int16)0x00f2 }, - { (int16)0x0293, (int16)0x444c, (int16)0x37a8, (int16)0x00fa }, - { (int16)0x0283, (int16)0x43f4, (int16)0x3807, (int16)0x0101 }, - { (int16)0x0273, (int16)0x439c, (int16)0x3867, (int16)0x010a }, - { (int16)0x0264, (int16)0x4344, (int16)0x38c6, (int16)0x0112 }, - { (int16)0x0255, (int16)0x42eb, (int16)0x3926, (int16)0x011b }, - { (int16)0x0246, (int16)0x4292, (int16)0x3985, (int16)0x0123 }, - { (int16)0x0237, (int16)0x4239, (int16)0x39e4, (int16)0x012c }, - { (int16)0x0229, (int16)0x41df, (int16)0x3a43, (int16)0x0135 }, - { (int16)0x021b, (int16)0x4185, (int16)0x3aa2, (int16)0x013f }, - { (int16)0x020d, (int16)0x412a, (int16)0x3b00, (int16)0x0148 }, - { (int16)0x0200, (int16)0x40d0, (int16)0x3b5f, (int16)0x0152 }, - { (int16)0x01f2, (int16)0x4074, (int16)0x3bbd, (int16)0x015c }, - { (int16)0x01e5, (int16)0x4019, (int16)0x3c1b, (int16)0x0166 }, - { (int16)0x01d9, (int16)0x3fbd, (int16)0x3c79, (int16)0x0171 }, - { (int16)0x01cc, (int16)0x3f62, (int16)0x3cd7, (int16)0x017b }, - { (int16)0x01c0, (int16)0x3f05, (int16)0x3d35, (int16)0x0186 }, - { (int16)0x01b4, (int16)0x3ea9, (int16)0x3d92, (int16)0x0191 }, - { (int16)0x01a8, (int16)0x3e4c, (int16)0x3def, (int16)0x019c }, - { (int16)0x019c, (int16)0x3def, (int16)0x3e4c, (int16)0x01a8 }, - { (int16)0x0191, (int16)0x3d92, (int16)0x3ea9, (int16)0x01b4 }, - { (int16)0x0186, (int16)0x3d35, (int16)0x3f05, (int16)0x01c0 }, - { (int16)0x017b, (int16)0x3cd7, (int16)0x3f62, (int16)0x01cc }, - { (int16)0x0171, (int16)0x3c79, (int16)0x3fbd, (int16)0x01d9 }, - { (int16)0x0166, (int16)0x3c1b, (int16)0x4019, (int16)0x01e5 }, - { (int16)0x015c, (int16)0x3bbd, (int16)0x4074, (int16)0x01f2 }, - { (int16)0x0152, (int16)0x3b5f, (int16)0x40d0, (int16)0x0200 }, - { (int16)0x0148, (int16)0x3b00, (int16)0x412a, (int16)0x020d }, - { (int16)0x013f, (int16)0x3aa2, (int16)0x4185, (int16)0x021b }, - { (int16)0x0135, (int16)0x3a43, (int16)0x41df, (int16)0x0229 }, - { (int16)0x012c, (int16)0x39e4, (int16)0x4239, (int16)0x0237 }, - { (int16)0x0123, (int16)0x3985, (int16)0x4292, (int16)0x0246 }, - { (int16)0x011b, (int16)0x3926, (int16)0x42eb, (int16)0x0255 }, - { (int16)0x0112, (int16)0x38c6, (int16)0x4344, (int16)0x0264 }, - { (int16)0x010a, (int16)0x3867, (int16)0x439c, (int16)0x0273 }, - { (int16)0x0101, (int16)0x3807, (int16)0x43f4, (int16)0x0283 }, - { (int16)0x00fa, (int16)0x37a8, (int16)0x444c, (int16)0x0293 }, - { (int16)0x00f2, (int16)0x3748, (int16)0x44a3, (int16)0x02a3 }, - { (int16)0x00ea, (int16)0x36e8, (int16)0x44fa, (int16)0x02b4 }, - { (int16)0x00e3, (int16)0x3689, (int16)0x4550, (int16)0x02c4 }, - { (int16)0x00db, (int16)0x3629, (int16)0x45a6, (int16)0x02d6 }, - { (int16)0x00d4, (int16)0x35c9, (int16)0x45fc, (int16)0x02e7 }, - { (int16)0x00cd, (int16)0x3569, (int16)0x4651, (int16)0x02f9 }, - { (int16)0x00c7, (int16)0x3509, (int16)0x46a6, (int16)0x030b }, - { (int16)0x00c0, (int16)0x34a9, (int16)0x46fa, (int16)0x031d }, - { (int16)0x00ba, (int16)0x3449, (int16)0x474e, (int16)0x0330 }, - { (int16)0x00b3, (int16)0x33e9, (int16)0x47a1, (int16)0x0343 }, - { (int16)0x00ad, (int16)0x3389, (int16)0x47f4, (int16)0x0356 }, - { (int16)0x00a7, (int16)0x3329, (int16)0x4846, (int16)0x036a }, - { (int16)0x00a1, (int16)0x32c9, (int16)0x4898, (int16)0x037e }, - { (int16)0x009c, (int16)0x3269, (int16)0x48e9, (int16)0x0392 }, - { (int16)0x0096, (int16)0x3209, (int16)0x493a, (int16)0x03a7 }, - { (int16)0x0091, (int16)0x31aa, (int16)0x498a, (int16)0x03bc }, - { (int16)0x008c, (int16)0x314a, (int16)0x49d9, (int16)0x03d1 }, - { (int16)0x0087, (int16)0x30ea, (int16)0x4a29, (int16)0x03e7 }, - { (int16)0x0082, (int16)0x308b, (int16)0x4a77, (int16)0x03fc }, - { (int16)0x007d, (int16)0x302b, (int16)0x4ac5, (int16)0x0413 }, - { (int16)0x0078, (int16)0x2fcc, (int16)0x4b13, (int16)0x042a }, - { (int16)0x0074, (int16)0x2f6c, (int16)0x4b5f, (int16)0x0441 }, - { (int16)0x006f, (int16)0x2f0d, (int16)0x4bac, (int16)0x0458 }, - { (int16)0x006b, (int16)0x2eae, (int16)0x4bf7, (int16)0x0470 }, - { (int16)0x0067, (int16)0x2e4f, (int16)0x4c42, (int16)0x0488 }, - { (int16)0x0063, (int16)0x2df0, (int16)0x4c8d, (int16)0x04a0 }, - { (int16)0x005f, (int16)0x2d91, (int16)0x4cd7, (int16)0x04b9 }, - { (int16)0x005b, (int16)0x2d33, (int16)0x4d20, (int16)0x04d2 }, - { (int16)0x0057, (int16)0x2cd4, (int16)0x4d68, (int16)0x04ec }, - { (int16)0x0054, (int16)0x2c76, (int16)0x4db0, (int16)0x0506 }, - { (int16)0x0050, (int16)0x2c18, (int16)0x4df7, (int16)0x0520 }, - { (int16)0x004d, (int16)0x2bba, (int16)0x4e3e, (int16)0x053b }, - { (int16)0x0049, (int16)0x2b5c, (int16)0x4e84, (int16)0x0556 }, - { (int16)0x0046, (int16)0x2aff, (int16)0x4ec9, (int16)0x0572 }, - { (int16)0x0043, (int16)0x2aa1, (int16)0x4f0e, (int16)0x058e }, - { (int16)0x0040, (int16)0x2a44, (int16)0x4f52, (int16)0x05aa }, - { (int16)0x003d, (int16)0x29e7, (int16)0x4f95, (int16)0x05c7 }, - { (int16)0x003a, (int16)0x298b, (int16)0x4fd7, (int16)0x05e4 }, - { (int16)0x0038, (int16)0x292e, (int16)0x5019, (int16)0x0601 }, - { (int16)0x0035, (int16)0x28d2, (int16)0x505a, (int16)0x061f }, - { (int16)0x0033, (int16)0x2876, (int16)0x509a, (int16)0x063e }, - { (int16)0x0030, (int16)0x281a, (int16)0x50da, (int16)0x065c }, - { (int16)0x002e, (int16)0x27be, (int16)0x5118, (int16)0x067c }, - { (int16)0x002c, (int16)0x2763, (int16)0x5156, (int16)0x069b }, - { (int16)0x0029, (int16)0x2708, (int16)0x5194, (int16)0x06bb }, - { (int16)0x0027, (int16)0x26ad, (int16)0x51d0, (int16)0x06dc }, - { (int16)0x0025, (int16)0x2653, (int16)0x520c, (int16)0x06fd }, - { (int16)0x0023, (int16)0x25f8, (int16)0x5247, (int16)0x071e }, - { (int16)0x0021, (int16)0x259e, (int16)0x5281, (int16)0x0740 }, - { (int16)0x0020, (int16)0x2545, (int16)0x52ba, (int16)0x0762 }, - { (int16)0x001e, (int16)0x24eb, (int16)0x52f3, (int16)0x0784 }, - { (int16)0x001c, (int16)0x2492, (int16)0x532a, (int16)0x07a7 }, - { (int16)0x001b, (int16)0x2439, (int16)0x5361, (int16)0x07cb }, - { (int16)0x0019, (int16)0x23e1, (int16)0x5397, (int16)0x07ef }, - { (int16)0x0018, (int16)0x2389, (int16)0x53cc, (int16)0x0813 }, - { (int16)0x0016, (int16)0x2331, (int16)0x5401, (int16)0x0838 }, - { (int16)0x0015, (int16)0x22da, (int16)0x5434, (int16)0x085d }, - { (int16)0x0013, (int16)0x2282, (int16)0x5467, (int16)0x0883 }, - { (int16)0x0012, (int16)0x222c, (int16)0x5499, (int16)0x08a9 }, - { (int16)0x0011, (int16)0x21d5, (int16)0x54ca, (int16)0x08d0 }, - { (int16)0x0010, (int16)0x217f, (int16)0x54fa, (int16)0x08f7 }, - { (int16)0x000f, (int16)0x2129, (int16)0x5529, (int16)0x091e }, - { (int16)0x000e, (int16)0x20d4, (int16)0x5558, (int16)0x0946 }, - { (int16)0x000d, (int16)0x207f, (int16)0x5585, (int16)0x096f }, - { (int16)0x000c, (int16)0x202a, (int16)0x55b2, (int16)0x0998 }, - { (int16)0x000b, (int16)0x1fd6, (int16)0x55de, (int16)0x09c1 }, - { (int16)0x000a, (int16)0x1f82, (int16)0x5609, (int16)0x09eb }, - { (int16)0x0009, (int16)0x1f2f, (int16)0x5632, (int16)0x0a16 }, - { (int16)0x0009, (int16)0x1edc, (int16)0x565b, (int16)0x0a40 }, - { (int16)0x0008, (int16)0x1e89, (int16)0x5684, (int16)0x0a6c }, - { (int16)0x0007, (int16)0x1e37, (int16)0x56ab, (int16)0x0a98 }, - { (int16)0x0007, (int16)0x1de5, (int16)0x56d1, (int16)0x0ac4 }, - { (int16)0x0006, (int16)0x1d93, (int16)0x56f6, (int16)0x0af1 }, - { (int16)0x0005, (int16)0x1d42, (int16)0x571b, (int16)0x0b1e }, - { (int16)0x0005, (int16)0x1cf1, (int16)0x573e, (int16)0x0b4c }, - { (int16)0x0004, (int16)0x1ca1, (int16)0x5761, (int16)0x0b7a }, - { (int16)0x0004, (int16)0x1c51, (int16)0x5782, (int16)0x0ba9 }, - { (int16)0x0003, (int16)0x1c02, (int16)0x57a3, (int16)0x0bd8 }, - { (int16)0x0003, (int16)0x1bb3, (int16)0x57c3, (int16)0x0c07 }, - { (int16)0x0003, (int16)0x1b64, (int16)0x57e2, (int16)0x0c38 }, - { (int16)0x0002, (int16)0x1b16, (int16)0x57ff, (int16)0x0c68 }, - { (int16)0x0002, (int16)0x1ac8, (int16)0x581c, (int16)0x0c99 }, - { (int16)0x0002, (int16)0x1a7b, (int16)0x5838, (int16)0x0ccb }, - { (int16)0x0001, (int16)0x1a2e, (int16)0x5853, (int16)0x0cfd }, - { (int16)0x0001, (int16)0x19e2, (int16)0x586d, (int16)0x0d30 }, - { (int16)0x0001, (int16)0x1996, (int16)0x5886, (int16)0x0d63 }, - { (int16)0x0001, (int16)0x194b, (int16)0x589e, (int16)0x0d97 }, - { (int16)0x0000, (int16)0x1900, (int16)0x58b5, (int16)0x0dcb }, - { (int16)0x0000, (int16)0x18b5, (int16)0x58cb, (int16)0x0e00 }, - { (int16)0x0000, (int16)0x186b, (int16)0x58e0, (int16)0x0e35 }, - { (int16)0x0000, (int16)0x1821, (int16)0x58f4, (int16)0x0e6b }, - { (int16)0x0000, (int16)0x17d8, (int16)0x5907, (int16)0x0ea1 }, - { (int16)0x0000, (int16)0x1790, (int16)0x5919, (int16)0x0ed7 }, - { (int16)0x0000, (int16)0x1747, (int16)0x592a, (int16)0x0f0f }, - { (int16)0xffff, (int16)0x1700, (int16)0x593a, (int16)0x0f46 }, - { (int16)0xffff, (int16)0x16b9, (int16)0x5949, (int16)0x0f7f }, - { (int16)0xffff, (int16)0x1672, (int16)0x5958, (int16)0x0fb7 }, - { (int16)0xffff, (int16)0x162c, (int16)0x5965, (int16)0x0ff1 }, - { (int16)0xffff, (int16)0x15e6, (int16)0x5971, (int16)0x102a }, - { (int16)0xffff, (int16)0x15a0, (int16)0x597c, (int16)0x1065 }, - { (int16)0xffff, (int16)0x155c, (int16)0x5986, (int16)0x109f }, - { (int16)0xffff, (int16)0x1517, (int16)0x598f, (int16)0x10db }, - { (int16)0xffff, (int16)0x14d4, (int16)0x5997, (int16)0x1116 }, - { (int16)0xffff, (int16)0x1490, (int16)0x599e, (int16)0x1153 }, - { (int16)0xffff, (int16)0x144d, (int16)0x59a4, (int16)0x118f }, - { (int16)0xffff, (int16)0x140b, (int16)0x59a9, (int16)0x11cd }, - { (int16)0xffff, (int16)0x13c9, (int16)0x59ad, (int16)0x120b }, - { (int16)0xffff, (int16)0x1388, (int16)0x59b0, (int16)0x1249 }, - { (int16)0xffff, (int16)0x1347, (int16)0x59b2, (int16)0x1288 }, - { (int16)0xffff, (int16)0x1307, (int16)0x59b3, (int16)0x12c7 }, diff --git a/psx/octoshock/psx/spu_reverb.inc b/psx/octoshock/psx/spu_reverb.inc deleted file mode 100644 index 6a75485bfe9..00000000000 --- a/psx/octoshock/psx/spu_reverb.inc +++ /dev/null @@ -1,217 +0,0 @@ -/******************************************************************************/ -/* Mednafen Sony PS1 Emulation Module */ -/******************************************************************************/ -/* spu_reverb.inc: -** Copyright (C) 2011-2016 Mednafen Team -** -** 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., -** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -static int16 ReverbSat(int32 samp) MDFN_WARN_UNUSED_RESULT; -static INLINE int16 ReverbSat(int32 samp) -{ - if(samp > 32767) - samp = 32767; - - if(samp < -32768) - samp = -32768; - - return(samp); -} - -static INLINE int16 ReverbNeg(int16 samp) -{ - if(samp == -32768) - return 0x7FFF; - - return -samp; -} - -INLINE uint32 PS_SPU::Get_Reverb_Offset(uint32 in_offset) -{ - uint32 offset = ReverbCur + (in_offset & 0x3FFFF); - - offset += ReverbWA & ((int32)(offset << 13) >> 31); - offset &= 0x3FFFF; - - // For debugging in case there are any problems with games misprogramming the reverb registers in a race-conditiony manner that - // causes important data in SPU RAM to be trashed: - //if(offset < ReverbWA) - // printf("BARF: offset=%05x reverbwa=%05x reverbcur=%05x in_offset=%05x\n", offset, ReverbWA, ReverbCur, in_offset & 0x3FFFF); - - return(offset); -} - -int16 NO_INLINE PS_SPU::RD_RVB(uint16 raw_offs, int32 extra_offs) -{ - return ReadSPURAM(Get_Reverb_Offset((raw_offs << 2) + extra_offs)); -} - -void NO_INLINE PS_SPU::WR_RVB(uint16 raw_offs, int16 sample) -{ - if(SPUControl & 0x80) - WriteSPURAM(Get_Reverb_Offset(raw_offs << 2), sample); -} - -// -// Zeroes optimized out; middle removed too(it's 16384) -static const int16 ResampTable[20] = -{ - -1, 2, -10, 35, -103, 266, -616, 1332, -2960, 10246, 10246, -2960, 1332, -616, 266, -103, 35, -10, 2, -1, -}; - -static INLINE int32 Reverb4422(const int16 *src) -{ - int32 out = 0; // 32-bits is adequate(it won't overflow) - - for(unsigned i = 0; i < 20; i++) - out += ResampTable[i] * src[i * 2]; - - // Middle non-zero - out += 0x4000 * src[19]; - - out >>= 15; - - clamp(&out, -32768, 32767); - - return(out); -} - -template -static INLINE int32 Reverb2244(const int16 *src) -{ - int32 out; // 32-bits is adequate(it won't overflow) - - if(phase) - { - // Middle non-zero - out = src[9]; - } - else - { - out = 0; - - for(unsigned i = 0; i < 20; i++) - out += ResampTable[i] * src[i]; - - out >>= 14; - - clamp(&out, -32768, 32767); - } - - return(out); -} - -static int32 IIASM(const int16 IIR_ALPHA, const int16 insamp) -{ - if(MDFN_UNLIKELY(IIR_ALPHA == -32768)) - { - //const int32 iai_adj = sign_x_to_s32(17, (32768 - IIR_ALPHA)); - //tmp = iai_adj * in_samp - - if(insamp == -32768) - return 0; - else - return insamp * -65536; - } - else - return insamp * (32768 - IIR_ALPHA); -} - -// -// Take care to thoroughly test the reverb resampling code when modifying anything that uses RvbResPos. -// -INLINE void PS_SPU::RunReverb(const int32* in, int32* out) -{ - int32 upsampled[2] = { 0, 0 }; - - for(unsigned lr = 0; lr < 2; lr++) - { - RDSB[lr][RvbResPos | 0x00] = in[lr]; - RDSB[lr][RvbResPos | 0x40] = in[lr]; // So we don't have to &/bounds check in our MAC loop - } - - if(RvbResPos & 1) - { - int32 downsampled[2]; - - for(unsigned lr = 0; lr < 2; lr++) - downsampled[lr] = Reverb4422(&RDSB[lr][(RvbResPos - 38) & 0x3F]); - - // - // Run algorithm - // - for(unsigned lr = 0; lr < 2; lr++) - { - const int16 IIR_INPUT_A = ReverbSat((((RD_RVB(IIR_SRC_A[lr ^ 0]) * IIR_COEF) >> 14) + ((downsampled[lr] * IN_COEF[lr]) >> 14)) >> 1); - const int16 IIR_INPUT_B = ReverbSat((((RD_RVB(IIR_SRC_B[lr ^ 1]) * IIR_COEF) >> 14) + ((downsampled[lr] * IN_COEF[lr]) >> 14)) >> 1); - const int16 IIR_A = ReverbSat((((IIR_INPUT_A * IIR_ALPHA) >> 14) + (IIASM(IIR_ALPHA, RD_RVB(IIR_DEST_A[lr], -1)) >> 14)) >> 1); - const int16 IIR_B = ReverbSat((((IIR_INPUT_B * IIR_ALPHA) >> 14) + (IIASM(IIR_ALPHA, RD_RVB(IIR_DEST_B[lr], -1)) >> 14)) >> 1); - - WR_RVB(IIR_DEST_A[lr], IIR_A); - WR_RVB(IIR_DEST_B[lr], IIR_B); - - const int32 ACC = ((RD_RVB(ACC_SRC_A[lr]) * ACC_COEF_A) >> 14) + - ((RD_RVB(ACC_SRC_B[lr]) * ACC_COEF_B) >> 14) + - ((RD_RVB(ACC_SRC_C[lr]) * ACC_COEF_C) >> 14) + - ((RD_RVB(ACC_SRC_D[lr]) * ACC_COEF_D) >> 14); - - const int16 FB_A = RD_RVB(MIX_DEST_A[lr] - FB_SRC_A); - const int16 FB_B = RD_RVB(MIX_DEST_B[lr] - FB_SRC_B); - const int16 MDA = ReverbSat((ACC + ((FB_A * ReverbNeg(FB_ALPHA)) >> 14)) >> 1); - const int16 MDB = ReverbSat(FB_A + ((((MDA * FB_ALPHA) >> 14) + ((FB_B * ReverbNeg(FB_X)) >> 14)) >> 1)); - const int16 IVB = ReverbSat(FB_B + ((MDB * FB_X) >> 15)); - - WR_RVB(MIX_DEST_A[lr], MDA); - WR_RVB(MIX_DEST_B[lr], MDB); -#if 0 - { - static uint32 sqcounter; - RUSB[lr][(RvbResPos >> 1) | 0x20] = RUSB[lr][RvbResPos >> 1] = ((sqcounter & 0xFF) == 0) ? 0x8000 : 0x0000; //((sqcounter & 0x80) ? 0x7000 : 0x9000); - sqcounter += lr; - } -#else - RUSB[lr][(RvbResPos >> 1) | 0x20] = RUSB[lr][RvbResPos >> 1] = IVB; // Output sample -#endif - } - // - // - // - ReverbCur = (ReverbCur + 1) & 0x3FFFF; - if(!ReverbCur) - ReverbCur = ReverbWA; - - for(unsigned lr = 0; lr < 2; lr++) - upsampled[lr] = Reverb2244(&RUSB[lr][((RvbResPos >> 1) - 19) & 0x1F]); - } - else - { - for(unsigned lr = 0; lr < 2; lr++) - upsampled[lr] = Reverb2244(&RUSB[lr][((RvbResPos >> 1) - 19) & 0x1F]); - } - - RvbResPos = (RvbResPos + 1) & 0x3F; - - for(unsigned lr = 0; lr < 2; lr++) - { -#if 0 - if(!lr) - printf("%d\n", (-upsampled[lr]) >> 1); -#endif - - out[lr] = upsampled[lr]; - } -} - diff --git a/psx/octoshock/psx/timer.cpp b/psx/octoshock/psx/timer.cpp deleted file mode 100644 index cef46f74e17..00000000000 --- a/psx/octoshock/psx/timer.cpp +++ /dev/null @@ -1,520 +0,0 @@ -/******************************************************************************/ -/* Mednafen Sony PS1 Emulation Module */ -/******************************************************************************/ -/* timer.cpp: -** Copyright (C) 2011-2016 Mednafen Team -** -** 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., -** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#pragma GCC optimize ("unroll-loops") - -#include -#include "psx.h" -#include "timer.h" - -/* - Notes(some of it may be incomplete or wrong in subtle ways) - - Control bits: - Lower 3 bits of mode, for timer1(when mode is | 0x100): - 0x1 = don't count while in vblank(except that the first count while in vblank does go through) - 0x3 = vblank going inactive triggers timer reset, then some interesting behavior where counting again is delayed... - 0x5 = vblank going inactive triggers timer reset, and only count within vblank. - 0x7 = Wait until vblank goes active then inactive, then start counting? - For timer2: - 0x1 = timer stopped(TODO: confirm on real system) - - Target match counter reset enable 0x008 - Target match IRQ enable 0x010 - Overflow IRQ enable 0x020 - IRQ evaluation auto-reset 0x040 - --unknown-- 0x080 - Clock selection 0x100 - Divide by 8(timer 2 only?) 0x200 - - Counter: - Reset to 0 on writes to the mode/status register. - - Status flags: - Current IRQ line status? 0x0400 - Compare flag 0x0800 - Cleared on mode/status read. - Set repeatedly while counter == target. - - Overflow/Carry flag 0x1000 - Cleared on mode/status read. - Set repeatedly after counter overflows from 0xFFFF->0 while before the next clocking(FIXME: currently not emulated correctly in respect - to the constant/repeated setting after an overflow but before the next clocking). - - Hidden flags: - IRQ done - Cleared on writes to the mode/status register, on writes to the count register, and apparently automatically when the counter - increments if (Mode & 0x40) [Note: If target mode is enabled, and target is 0, IRQ done flag won't be automatically reset] - - There seems to be a brief period(edge condition?) where, if target match reset mode is enabled, you can (sometimes?) read the target value in the count - register before it's reset to 0. Currently not emulated; I doubt any games rely on this, but who knows. Maybe a PSX equivalent - of the PC Engine "Battle Royale"? ;) - - A timer is somewhat unreliable when target match reset mode is enabled and the 33MHz clock is used. Average 2.4 counts seem to be - skipped for that timer every target match reset, but oddly subtracting only 2 from the desired target match value seems to effectively - negate the loss...wonder if my test program is faulty in some way. Currently not emulated. - - Counters using GPU clock sources(hretrace,dot clock) reportedly will with a low probability return wrong count values on an actual PS1, - so keep this in mind when writing test programs(IE keep reading the count value until two consecutive reads return the same value). - Currently not emulated. -*/ - -/* - FIXME: Clock appropriately(and update events) when using SetRegister() via the debugger. - - TODO: If we ever return randomish values to "simulate" open bus, remember to change the return type and such of the TIMER_Read() function to full 32-bit too. -*/ - -namespace MDFN_IEN_PSX -{ - -struct Timer -{ - uint32 Mode; - uint32 Counter; // Only 16-bit, but 32-bit here for detecting counting past target. - uint32 Target; - - uint32 Div8Counter; - - bool IRQDone; - int32 DoZeCounting; -}; - -static bool vblank; -static bool hretrace; -static Timer Timers[3]; -static pscpu_timestamp_t lastts; - -static uint32 CalcNextEvent(void) -{ - uint32 next_event = 1024; // - - for(unsigned i = 0; i < 3; i++) - { - if(!(Timers[i].Mode & 0x30)) // If IRQ is disabled, abort for this timer(don't look at IRQDone for this test, or things will break since its resetting is deferred!). - continue; - - if((Timers[i].Mode & 0x8) && (Timers[i].Counter == 0) && (Timers[i].Target == 0) && !Timers[i].IRQDone) - { - next_event = 1; - continue; - } - - // - // - if((i == 0 || i == 1) && (Timers[i].Mode & 0x100)) // If clocked by GPU, abort for this timer(will result in poor granularity for pixel-clock-derived timer IRQs, but whatever). - continue; - - if(Timers[i].DoZeCounting <= 0) - continue; - - if((i == 0x2) && (Timers[i].Mode & 0x1)) - continue; - - // - // - // - const uint32 target = ((Timers[i].Mode & 0x18) && (Timers[i].Counter < Timers[i].Target)) ? Timers[i].Target : 0x10000; - const uint32 count_delta = target - Timers[i].Counter; - uint32 tmp_clocks; - - if((i == 0x2) && (Timers[i].Mode & 0x200)) - tmp_clocks = (count_delta * 8) - Timers[i].Div8Counter; - else - tmp_clocks = count_delta; - - if(next_event > tmp_clocks) - next_event = tmp_clocks; - } - - return(next_event); -} - -static MDFN_FASTCALL bool TimerMatch(unsigned i) -{ - bool irq_exact = false; - - Timers[i].Mode |= 0x0800; - - if(Timers[i].Mode & 0x008) - Timers[i].Counter %= std::max(1, Timers[i].Target); - - if((Timers[i].Mode & 0x10) && !Timers[i].IRQDone) - { - if(Timers[i].Counter == 0 || Timers[i].Counter == Timers[i].Target) - irq_exact = true; - -#if 1 - { - const uint16 lateness = (Timers[i].Mode & 0x008) ? Timers[i].Counter : (Timers[i].Counter - Timers[i].Target); - - if(lateness > ((i == 1 && (Timers[i].Mode & 0x100)) ? 0 : 3)) - PSX_DBG(PSX_DBG_WARNING, "[TIMER] Timer %d match IRQ trigger late: %u\n", i, lateness); - } -#endif - - Timers[i].IRQDone = true; - IRQ_Assert(IRQ_TIMER_0 + i, true); - IRQ_Assert(IRQ_TIMER_0 + i, false); - } - - return irq_exact; -} - -static MDFN_FASTCALL bool TimerOverflow(unsigned i) -{ - bool irq_exact = false; - - Timers[i].Mode |= 0x1000; - Timers[i].Counter &= 0xFFFF; - - if((Timers[i].Mode & 0x20) && !Timers[i].IRQDone) - { - if(Timers[i].Counter == 0) - irq_exact = true; - -#if 1 - if(Timers[i].Counter > ((i == 1 && (Timers[i].Mode & 0x100)) ? 0 : 3)) - PSX_DBG(PSX_DBG_WARNING, "[TIMER] Timer %d overflow IRQ trigger late: %u\n", i, Timers[i].Counter); -#endif - - Timers[i].IRQDone = true; - IRQ_Assert(IRQ_TIMER_0 + i, true); - IRQ_Assert(IRQ_TIMER_0 + i, false); - } - - return irq_exact; -} - -static MDFN_FASTCALL void ClockTimer(int i, uint32 clocks) -{ - if(Timers[i].DoZeCounting <= 0) - clocks = 0; - - if(i == 0x2) - { - uint32 d8_clocks; - - Timers[i].Div8Counter += clocks; - d8_clocks = Timers[i].Div8Counter >> 3; - Timers[i].Div8Counter &= 0x7; - - if(Timers[i].Mode & 0x200) // Divide by 8, at least for timer 0x2 - clocks = d8_clocks; - - if(Timers[i].Mode & 1) - clocks = 0; - } - - if((Timers[i].Mode & 0x008) && Timers[i].Target == 0 && Timers[i].Counter == 0) - TimerMatch(i); - else if(clocks) - { - uint32 before = Timers[i].Counter; - - Timers[i].Counter += clocks; - - if(Timers[i].Mode & 0x40) - Timers[i].IRQDone = false; - - bool irq_exact = false; - - // - // Target match handling - // - if((before < Timers[i].Target && Timers[i].Counter >= Timers[i].Target) || (Timers[i].Counter >= Timers[i].Target + 0x10000)) - irq_exact |= TimerMatch(i); - - // - // Overflow handling - // - if(Timers[i].Counter >= 0x10000) - irq_exact |= TimerOverflow(i); - - // - if((Timers[i].Mode & 0x40) && !irq_exact) - Timers[i].IRQDone = false; - } -} - -MDFN_FASTCALL void TIMER_SetVBlank(bool status) -{ - switch(Timers[1].Mode & 0x7) - { - case 0x1: - Timers[1].DoZeCounting = !status; - break; - - case 0x3: - if(vblank && !status) - { - Timers[1].Counter = 0; - if(Timers[1].Counter == Timers[1].Target) - TimerMatch(1); - } - break; - - case 0x5: - Timers[1].DoZeCounting = status; - if(vblank && !status) - { - Timers[1].Counter = 0; - if(Timers[1].Counter == Timers[1].Target) - TimerMatch(1); - } - break; - - case 0x7: - if(Timers[1].DoZeCounting == -1) - { - if(!vblank && status) - Timers[1].DoZeCounting = 0; - } - else if(Timers[1].DoZeCounting == 0) - { - if(vblank && !status) - Timers[1].DoZeCounting = 1; - } - break; - } - vblank = status; -} - -MDFN_FASTCALL void TIMER_SetHRetrace(bool status) -{ - if(hretrace && !status) - { - if((Timers[0].Mode & 0x7) == 0x3) - { - Timers[0].Counter = 0; - - if(Timers[0].Counter == Timers[0].Target) - TimerMatch(0); - } - } - - hretrace = status; -} - -MDFN_FASTCALL void TIMER_AddDotClocks(uint32 count) -{ - if(Timers[0].Mode & 0x100) - ClockTimer(0, count); -} - -void TIMER_ClockHRetrace(void) -{ - if(Timers[1].Mode & 0x100) - ClockTimer(1, 1); -} - -MDFN_FASTCALL pscpu_timestamp_t TIMER_Update(const pscpu_timestamp_t timestamp) -{ - int32 cpu_clocks = timestamp - lastts; - - for(int i = 0; i < 3; i++) - { - uint32 timer_clocks = cpu_clocks; - - if(Timers[i].Mode & 0x100) - continue; - - ClockTimer(i, timer_clocks); - } - - lastts = timestamp; - - return(timestamp + CalcNextEvent()); -} - -static MDFN_FASTCALL void CalcCountingStart(unsigned which) -{ - Timers[which].DoZeCounting = true; - - switch(which) - { - case 1: - switch(Timers[which].Mode & 0x07) - { - case 0x1: - Timers[which].DoZeCounting = !vblank; - break; - - case 0x5: - Timers[which].DoZeCounting = vblank; - break; - - case 0x7: - Timers[which].DoZeCounting = -1; - break; - } - break; - - - } -} - -MDFN_FASTCALL void TIMER_Write(const pscpu_timestamp_t timestamp, uint32 A, uint16 V) -{ - TIMER_Update(timestamp); - - int which = (A >> 4) & 0x3; - - V <<= (A & 3) * 8; - - PSX_DBGINFO("[TIMER] Write: %08x %04x\n", A, V); - - if(which >= 3) - return; - - switch(A & 0xC) - { - case 0x0: Timers[which].IRQDone = false; - Timers[which].Counter = V & 0xFFFF; - break; - - case 0x4: Timers[which].Mode = (V & 0x3FF) | (Timers[which].Mode & 0x1C00); - Timers[which].IRQDone = false; - Timers[which].Counter = 0; - - CalcCountingStart(which); // Call after setting .Mode - break; - - case 0x8: Timers[which].Target = V & 0xFFFF; - break; - - case 0xC: // Open bus - break; - } - - if(Timers[which].Counter == Timers[which].Target) - TimerMatch(which); - - PSX_SetEventNT(PSX_EVENT_TIMER, timestamp + CalcNextEvent()); -} - -MDFN_FASTCALL uint16 TIMER_Read(const pscpu_timestamp_t timestamp, uint32 A) -{ - uint16 ret = 0; - int which = (A >> 4) & 0x3; - - if(which >= 3) - { - PSX_WARNING("[TIMER] Open Bus Read: 0x%08x", A); - - return(ret >> ((A & 3) * 8)); - } - - TIMER_Update(timestamp); - - switch(A & 0xC) - { - case 0x0: ret = Timers[which].Counter; - break; - - case 0x4: ret = Timers[which].Mode; - Timers[which].Mode &= ~0x1000; - if(Timers[which].Counter != Timers[which].Target) - Timers[which].Mode &= ~0x0800; - break; - - case 0x8: ret = Timers[which].Target; - break; - - case 0xC: PSX_WARNING("[TIMER] Open Bus Read: 0x%08x", A); - break; - } - - return(ret >> ((A & 3) * 8)); -} - - -void TIMER_ResetTS(void) -{ - lastts = 0; -} - - -void TIMER_Power(void) -{ - lastts = 0; - - hretrace = false; - vblank = false; - memset(Timers, 0, sizeof(Timers)); -} - -void TIMER_SyncState(bool isReader, EW::NewState *ns) -{ - NSS(Timers); - NSS(vblank); - NSS(hretrace); -} - -uint32 TIMER_GetRegister(unsigned int which, char *special, const uint32 special_len) -{ - int tw = (which >> 4) & 0x3; - uint32 ret = 0; - - switch(which & 0xF) - { - case TIMER_GSREG_COUNTER0: - ret = Timers[tw].Counter; - break; - - case TIMER_GSREG_MODE0: - ret = Timers[tw].Mode; - break; - - case TIMER_GSREG_TARGET0: - ret = Timers[tw].Target; - break; - } - - return(ret); -} - -void TIMER_SetRegister(unsigned int which, uint32 value) -{ - int tw = (which >> 4) & 0x3; - - switch(which & 0xF) - { - case TIMER_GSREG_COUNTER0: - Timers[tw].Counter = value & 0xFFFF; - break; - - case TIMER_GSREG_MODE0: - Timers[tw].Mode = value & 0xFFFF; - break; - - case TIMER_GSREG_TARGET0: - Timers[tw].Target = value & 0xFFFF; - break; - } - - if (Timers[tw].Counter == Timers[tw].Target) - TimerMatch(tw); - -} - - -} diff --git a/psx/octoshock/psx/timer.h b/psx/octoshock/psx/timer.h deleted file mode 100644 index 0eef5ce1515..00000000000 --- a/psx/octoshock/psx/timer.h +++ /dev/null @@ -1,62 +0,0 @@ -/******************************************************************************/ -/* Mednafen Sony PS1 Emulation Module */ -/******************************************************************************/ -/* timer.h: -** Copyright (C) 2011-2016 Mednafen Team -** -** 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., -** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef __MDFN_PSX_TIMER_H -#define __MDFN_PSX_TIMER_H - -namespace MDFN_IEN_PSX -{ - -enum -{ - TIMER_GSREG_COUNTER0 = 0x00, - TIMER_GSREG_MODE0, - TIMER_GSREG_TARGET0, - - TIMER_GSREG_COUNTER1 = 0x10, - TIMER_GSREG_MODE1, - TIMER_GSREG_TARGET1, - - TIMER_GSREG_COUNTER2 = 0x20, - TIMER_GSREG_MODE2, - TIMER_GSREG_TARGET2, -}; - -uint32 TIMER_GetRegister(unsigned int which, char *special, const uint32 special_len); -void TIMER_SetRegister(unsigned int which, uint32 value); - - -MDFN_FASTCALL void TIMER_Write(const pscpu_timestamp_t timestamp, uint32 A, uint16 V); -MDFN_FASTCALL uint16 TIMER_Read(const pscpu_timestamp_t timestamp, uint32 A); - -MDFN_FASTCALL void TIMER_AddDotClocks(uint32 count); -void TIMER_ClockHRetrace(void); -MDFN_FASTCALL void TIMER_SetHRetrace(bool status); -MDFN_FASTCALL void TIMER_SetVBlank(bool status); - -MDFN_FASTCALL pscpu_timestamp_t TIMER_Update(const pscpu_timestamp_t); -void TIMER_ResetTS(void); - -void TIMER_Power(void) MDFN_COLD; - -} - -#endif diff --git a/psx/octoshock/test/miniclient/miniclient.cpp b/psx/octoshock/test/miniclient/miniclient.cpp deleted file mode 100644 index 335697be99a..00000000000 --- a/psx/octoshock/test/miniclient/miniclient.cpp +++ /dev/null @@ -1,345 +0,0 @@ -#include - -#include "octoshock.h" -#include "psx/psx.h" - -// 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 -}; - -#ifndef __PACKED - #ifdef __GNUC__ - #define __PACKED __attribute__((__packed__)) - #else - #define __PACKED - #endif -#endif - -#ifndef __GNUC__ -#pragma pack(push, 1) -#pragma warning(disable : 4103) -#endif -struct bmpimgheader_struct -{ - u32 size; - s32 width; - s32 height; - u16 planes; - u16 bpp; - u32 cmptype; - u32 imgsize; - s32 hppm; - s32 vppm; - u32 numcol; - u32 numimpcol; -} ; -struct bmpfileheader_struct -{ - u16 id __PACKED; - u32 size __PACKED; - u16 reserved1 __PACKED; - u16 reserved2 __PACKED; - u32 imgoffset __PACKED; -}; -#ifndef __GNUC__ -#pragma pack(pop) -#endif - -int WriteBMP32(int width, int height, const void* buf, const char *filename) -{ - bmpfileheader_struct fileheader; - bmpimgheader_struct imageheader; - FILE *file; - size_t elems_written = 0; - memset(&fileheader, 0, sizeof(fileheader)); - fileheader.size = sizeof(fileheader); - fileheader.id = 'B' | ('M' << 8); - fileheader.imgoffset = sizeof(fileheader)+sizeof(imageheader); - - memset(&imageheader, 0, sizeof(imageheader)); - imageheader.size = sizeof(imageheader); - imageheader.width = width; - imageheader.height = height; - imageheader.planes = 1; - imageheader.bpp = 32; - imageheader.cmptype = 0; // None - imageheader.imgsize = imageheader.width * imageheader.height * 4; - - if ((file = fopen(filename,"wb")) == NULL) - return 0; - - elems_written += fwrite(&fileheader, 1, sizeof(fileheader), file); - elems_written += fwrite(&imageheader, 1, sizeof(imageheader), file); - - for(int i=0;iReadTOC(read_target, tracks); } - static s32 s_ReadLBA2448(void* opaque, s32 lba, void* dst) { return ((BinReader2352*)opaque)->ReadLBA2448(lba,dst); } - - ~BinReader2352() - { - fclose(inf); - shock_DestroyDisc(disc); - } - -private: - int lbaCount; - FILE* inf; - - - union Sector { - struct { - u8 sync[12]; - u8 adr[3]; - u8 mode; - union { - struct { - u8 data2048[2048]; - u8 ecc[4]; - u8 reserved[8]; - u8 ecm[276]; - }; - u8 data2336[2336]; - }; - }; - u8 buf[2352]; - }; - - union XASector { - struct { - u8 sync[12]; - u8 adr[3]; - u8 mode; - u8 subheader[8]; - union { - u8 data2048[2048]; - u8 ecc[4]; - u8 ecm[276]; - } form1; - union { - u8 data2334[2334]; - u8 ecc[4]; - } form2; - }; - u8 buf[2352]; - }; - - union { - XASector xasector; - Sector sector; - }; - - - s32 ReadTOC( ShockTOC *read_target, ShockTOCTrack tracks[100 + 1]) - { - memset(read_target,0,sizeof(*read_target)); - read_target->disc_type = 0; - read_target->first_track = 1; - read_target->last_track = 1; - tracks[1].adr = 1; - tracks[1].lba = 0; - tracks[1].control = 4; - tracks[2].adr = 1; - tracks[2].lba = lbaCount; - tracks[2].control = 0; - tracks[100].adr = 1; - tracks[100].lba = lbaCount; - tracks[100].control = 0; - return SHOCK_OK; - } - - s32 ReadLBA2448(s32 lba, void* dst) - { - fseek(inf,lba*2352,SEEK_SET); - fread(dst,1,2352,inf); - //do something for subcode I guess - memset((u8*)dst+2352,0,96); - hacky_MakeSubPQ(lba,(u8*)dst+2352,1,0); - - //not the right thing to do - //return ((Sector*)dst)->mode; - - return SHOCK_OK; - } - - uint8 U8_to_BCD(uint8 num) - { - return( ((num / 10) << 4) + (num % 10) ); - } - - 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 hacky_MakeSubPQ(int lba, u8* SubPWBuf, int track, int track_start) - { - uint8 buf[0xC]; - uint32 lba_relative; - uint32 ma, sa, fa; - uint32 m, s, f; - uint8 pause_or = 0x00; - - lba_relative = abs((int32)lba - track_start); - - 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 - - memset(buf, 0, 0xC); - buf[0] = (adr << 0) | (0x04 << 4); - buf[1] = U8_to_BCD(track); - - buf[2] = U8_to_BCD(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) | pause_or; - } - - -}; - -int main(int argc, char **argv) -{ - const char* fwpath = argv[1]; - const char* discpath = argv[2]; - const char* outdir = argv[3]; - - FILE* inf; - - //load up the firmware - char firmware[512*1024]; - inf = fopen(fwpath,"rb"); - fread(firmware,1,512*1024,inf); - fclose(inf); - - BinReader2352 bin(discpath); - ShockDiscInfo info; - shock_AnalyzeDisc(bin.disc, &info); - printf("disc id: %s\n",info.id); - - //placeholder for instance - void* psx = NULL; - - ShockRenderOptions renderOpts; - renderOpts.deinterlaceMode = eShockDeinterlaceMode_Weave; - renderOpts.renderType = eShockRenderType_Normal; - renderOpts.scanline_start = 0; - renderOpts.scanline_end = 239; - renderOpts.skip = false; - - - shock_Create(&psx, REGION_NA, firmware); - shock_OpenTray(psx); - shock_SetDisc(psx,bin.disc); - shock_CloseTray(psx); - shock_SetRenderOptions(psx, &renderOpts); - shock_Peripheral_Connect(psx,0x01,ePeripheralType_DualShock); - shock_PowerOn(psx); - - int framectr = 0; - for(;;) - { - printf("frame %d\n",framectr); - shock_Step(psx,eShockStep_Frame); - if(framectr%60==0) - { - //dump a screen grab - ShockFramebufferInfo fbinfo; - static u32 buf[1024*1024]; - fbinfo.ptr = buf; - fbinfo.flags = eShockFramebufferFlags_Normalize; - shock_GetFramebuffer(psx,&fbinfo); - char fname[128]; - sprintf(fname,"%s\\test%03d.bmp",outdir,framectr/60); - WriteBMP32(fbinfo.width,fbinfo.height,buf,fname); //rgb is backwards - } - - framectr++; - } -} \ No newline at end of file diff --git a/psx/octoshock/test/miniclient/miniclient.vcxproj b/psx/octoshock/test/miniclient/miniclient.vcxproj deleted file mode 100644 index 690de4ab298..00000000000 --- a/psx/octoshock/test/miniclient/miniclient.vcxproj +++ /dev/null @@ -1,166 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {5A0DAC84-1170-4B1A-B9A9-F566A1D97790} - Win32Proj - miniclient - 10.0 - - - - Application - true - Unicode - v143 - - - Application - true - Unicode - v143 - - - Application - false - true - Unicode - v143 - - - Application - false - true - Unicode - v143 - - - - - - - - - - - - - - - - - - - true - $(ProjectDir)\..\..\..\..\output\dll\ - - - true - $(ProjectDir)\..\..\..\..\output\dll\ - - - false - $(ProjectDir)\..\..\..\..\output\dll\ - - - false - $(ProjectDir)\..\..\..\..\output\dll\ - - - - - - Level3 - Disabled - _CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - ..\..;..\..\emuware\msvc - - - Console - true - - - - - - - Level3 - Disabled - _CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - ..\..;..\..\emuware\msvc - - - Console - true - - - - - Level3 - - - MaxSpeed - true - true - _CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - ..\..;..\..\emuware\msvc - - - Console - true - true - true - - - - - Level3 - - - MaxSpeed - true - true - _CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - ..\..;..\..\emuware\msvc - - - Console - true - true - true - - - - - - - - {5f35cafc-6208-4fbe-ad17-0e69ba3f70ec} - - - - - - - - - - - \ No newline at end of file diff --git a/psx/octoshock/test/miniclient/miniclient.vcxproj.filters b/psx/octoshock/test/miniclient/miniclient.vcxproj.filters deleted file mode 100644 index a5d3d63429d..00000000000 --- a/psx/octoshock/test/miniclient/miniclient.vcxproj.filters +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/psx/octoshock/tests.cpp b/psx/octoshock/tests.cpp deleted file mode 100644 index c75c3dd3572..00000000000 --- a/psx/octoshock/tests.cpp +++ /dev/null @@ -1,1952 +0,0 @@ -// DO NOT REMOVE/DISABLE THESE MATH AND COMPILER SANITY TESTS. THEY EXIST FOR A REASON. - -/* 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 - */ - -// We really don't want NDEBUG defined ;) -#ifdef HAVE_CONFIG_H -#include -#endif - -#undef NDEBUG - -#include -#include -#include -#include "octoshock.h" -#include "math_ops.h" -#include "error.h" -#include "endian.h" - -#ifdef WANT_TEST_LEPACKER -#include "lepacker.h" -#endif - -#include "tests.h" - -#ifdef WANT_TEST_HASHES -#include -#include -#endif - -#ifdef WANT_TEST_TIME -#include -#include -#endif - -#ifdef WANT_TEST_ZLIB -#include -#endif - -#undef NDEBUG -#include -#include - -#include "psx/masmem.h" - -#if defined(HAVE_FENV_H) -#include -#endif - -#include - -#if defined(HAVE_ALTIVEC_INTRINSICS) && defined(HAVE_ALTIVEC_H) -#include -#endif - -#ifdef __ARM_NEON__ -#include -#endif - -#ifdef __MMX__ -#include -#endif - -#ifdef __SSE__ -#include -#endif - -namespace MDFN_TESTS_CPP -{ - -// Don't define this static, and don't define it const. We want these tests to be done at run time, not compile time(although maybe we should do both...). -typedef struct -{ - int bits; - uint32 negative_one; - uint32 mostneg; - int32 mostnegresult; -} MathTestEntry; - -#define ADD_MTE(_bits) { _bits, ((uint32)1 << _bits) - 1, (uint32)1 << (_bits - 1), (int32)(0 - ((uint32)1 << (_bits - 1))) } - -MathTestEntry math_test_vals[] = -{ - { 9, 0x01FF, 0x0100, -256 }, - { 10, 0x03FF, 0x0200, -512 }, - { 11, 0x07FF, 0x0400, -1024 }, - { 12, 0x0FFF, 0x0800, -2048 }, - { 13, 0x1FFF, 0x1000, -4096 }, - { 14, 0x3FFF, 0x2000, -8192 }, - { 15, 0x7FFF, 0x4000, -16384 }, - - ADD_MTE(17), - ADD_MTE(18), - ADD_MTE(19), - ADD_MTE(20), - ADD_MTE(21), - ADD_MTE(22), - ADD_MTE(23), - ADD_MTE(24), - ADD_MTE(25), - ADD_MTE(26), - ADD_MTE(27), - ADD_MTE(28), - ADD_MTE(29), - ADD_MTE(30), - ADD_MTE(31), - - { 0, 0, 0, 0 }, -}; - -static void TestSignExtend(void) -{ - MathTestEntry *itoo = math_test_vals; - - assert(sign_9_to_s16(itoo->negative_one) == -1 && sign_9_to_s16(itoo->mostneg) == itoo->mostnegresult); - itoo++; - - assert(sign_10_to_s16(itoo->negative_one) == -1 && sign_10_to_s16(itoo->mostneg) == itoo->mostnegresult); - itoo++; - - assert(sign_11_to_s16(itoo->negative_one) == -1 && sign_11_to_s16(itoo->mostneg) == itoo->mostnegresult); - itoo++; - - assert(sign_12_to_s16(itoo->negative_one) == -1 && sign_12_to_s16(itoo->mostneg) == itoo->mostnegresult); - itoo++; - - assert(sign_13_to_s16(itoo->negative_one) == -1 && sign_13_to_s16(itoo->mostneg) == itoo->mostnegresult); - itoo++; - - assert(sign_14_to_s16(itoo->negative_one) == -1 && sign_14_to_s16(itoo->mostneg) == itoo->mostnegresult); - itoo++; - - assert(sign_15_to_s16(itoo->negative_one) == -1 && sign_15_to_s16(itoo->mostneg) == itoo->mostnegresult); - itoo++; - - assert(sign_x_to_s32(17, itoo->negative_one) == -1 && sign_x_to_s32(17, itoo->mostneg) == itoo->mostnegresult); - itoo++; - - assert(sign_x_to_s32(18, itoo->negative_one) == -1 && sign_x_to_s32(18, itoo->mostneg) == itoo->mostnegresult); - itoo++; - - assert(sign_x_to_s32(19, itoo->negative_one) == -1 && sign_x_to_s32(19, itoo->mostneg) == itoo->mostnegresult); - itoo++; - - assert(sign_x_to_s32(20, itoo->negative_one) == -1 && sign_x_to_s32(20, itoo->mostneg) == itoo->mostnegresult); - itoo++; - - assert(sign_x_to_s32(21, itoo->negative_one) == -1 && sign_x_to_s32(21, itoo->mostneg) == itoo->mostnegresult); - itoo++; - - assert(sign_x_to_s32(22, itoo->negative_one) == -1 && sign_x_to_s32(22, itoo->mostneg) == itoo->mostnegresult); - itoo++; - - assert(sign_x_to_s32(23, itoo->negative_one) == -1 && sign_x_to_s32(23, itoo->mostneg) == itoo->mostnegresult); - itoo++; - - assert(sign_x_to_s32(24, itoo->negative_one) == -1 && sign_x_to_s32(24, itoo->mostneg) == itoo->mostnegresult); - itoo++; - - assert(sign_x_to_s32(25, itoo->negative_one) == -1 && sign_x_to_s32(25, itoo->mostneg) == itoo->mostnegresult); - itoo++; - - assert(sign_x_to_s32(26, itoo->negative_one) == -1 && sign_x_to_s32(26, itoo->mostneg) == itoo->mostnegresult); - itoo++; - - assert(sign_x_to_s32(27, itoo->negative_one) == -1 && sign_x_to_s32(27, itoo->mostneg) == itoo->mostnegresult); - itoo++; - - assert(sign_x_to_s32(28, itoo->negative_one) == -1 && sign_x_to_s32(28, itoo->mostneg) == itoo->mostnegresult); - itoo++; - - assert(sign_x_to_s32(29, itoo->negative_one) == -1 && sign_x_to_s32(29, itoo->mostneg) == itoo->mostnegresult); - itoo++; - - assert(sign_x_to_s32(30, itoo->negative_one) == -1 && sign_x_to_s32(30, itoo->mostneg) == itoo->mostnegresult); - itoo++; - - assert(sign_x_to_s32(31, itoo->negative_one) == -1 && sign_x_to_s32(31, itoo->mostneg) == itoo->mostnegresult); - itoo++; -} - -static void DoSizeofTests(void) -{ - assert(sizeof(uint8) == 1); - assert(sizeof(int8) == 1); - - assert(sizeof(uint16) == 2); - assert(sizeof(int16) == 2); - - assert(sizeof(uint32) == 4); - assert(sizeof(int32) == 4); - - assert(sizeof(uint64) == 8); - assert(sizeof(int64) == 8); - - assert(sizeof(char) == 1); - assert(sizeof(int) == 4); - assert(sizeof(long) >= 4); - assert(sizeof(long long) >= 8); - - assert(sizeof(float) >= 4); - assert(sizeof(double) >= 8); - assert(sizeof(long double) >= 8); - - assert(sizeof(void*) >= 4); - - assert(sizeof(char) == SIZEOF_CHAR); - assert(sizeof(short) == SIZEOF_SHORT); - assert(sizeof(int) == SIZEOF_INT); - assert(sizeof(long) == SIZEOF_LONG); - assert(sizeof(long long) == SIZEOF_LONG_LONG); - - assert(sizeof(off_t) == SIZEOF_OFF_T); - assert(sizeof(ptrdiff_t) == SIZEOF_PTRDIFF_T); - assert(sizeof(size_t) == SIZEOF_SIZE_T); - assert(sizeof(void*) == SIZEOF_VOID_P); - - assert(sizeof(double) == SIZEOF_DOUBLE); -} - -static void TestTypesSign(void) -{ - // Make sure the "char" type is signed(pass -fsigned-char to gcc). New code in Mednafen shouldn't be written with the - // assumption that "char" is signed, but there likely is at least some code that does. - { - char tmp = 255; - assert(tmp < 0); - } -} - -static void AntiNSOBugTest_Sub1_a(int *array) NO_INLINE; -static void AntiNSOBugTest_Sub1_a(int *array) -{ - for(int value = 0; value < 127; value++) - array[value] += (int8)value * 15; -} - -static void AntiNSOBugTest_Sub1_b(int *array) NO_INLINE; -static void AntiNSOBugTest_Sub1_b(int *array) -{ - for(int value = 127; value < 256; value++) - array[value] += (int8)value * 15; -} - -static void AntiNSOBugTest_Sub2(int *array) NO_INLINE; -static void AntiNSOBugTest_Sub2(int *array) -{ - for(int value = 0; value < 256; value++) - array[value] += (int8)value * 15; -} - -static void AntiNSOBugTest_Sub3(int *array) NO_INLINE; -static void AntiNSOBugTest_Sub3(int *array) -{ - for(int value = 0; value < 256; value++) - { - if(value >= 128) - array[value] = (value - 256) * 15; - else - array[value] = value * 15; - } -} - -static void DoAntiNSOBugTest(void) -{ - int array1[256], array2[256], array3[256]; - - memset(array1, 0, sizeof(array1)); - memset(array2, 0, sizeof(array2)); - memset(array3, 0, sizeof(array3)); - - AntiNSOBugTest_Sub1_a(array1); - AntiNSOBugTest_Sub1_b(array1); - AntiNSOBugTest_Sub2(array2); - AntiNSOBugTest_Sub3(array3); - - for(int i = 0; i < 256; i++) - { - assert((array1[i] == array2[i]) && (array2[i] == array3[i])); - } - //for(int value = 0; value < 256; value++) - // printf("%d, %d\n", (int8)value, ((int8)value) * 15); -} - -// -// Related: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61741 -// -// Not found to be causing problems in Mednafen(unlike the earlier no-strict-overflow problem and associated test), -// but better safe than sorry. -// -static void DoAntiNSOBugTest2014_SubA(int a) NO_INLINE NO_CLONE; -static void DoAntiNSOBugTest2014_SubA(int a) -{ - char c = 0; - - for(; a; a--) - { - for(; c >= 0; c++) - { - - } - } - - assert(c == -128); -} - -static int ANSOBT_CallCount; -static void DoAntiNSOBugTest2014_SubMx_F(void) NO_INLINE NO_CLONE; -static void DoAntiNSOBugTest2014_SubMx_F(void) -{ - ANSOBT_CallCount++; - - assert(ANSOBT_CallCount < 1000); -} - -static void DoAntiNSOBugTest2014_SubM1(void) NO_INLINE NO_CLONE; -static void DoAntiNSOBugTest2014_SubM1(void) -{ - char a; - - for(a = 127 - 1; a >= 0; a++) - DoAntiNSOBugTest2014_SubMx_F(); -} - -static void DoAntiNSOBugTest2014_SubM3(void) NO_INLINE NO_CLONE; -static void DoAntiNSOBugTest2014_SubM3(void) -{ - char a; - - for(a = 127 - 3; a >= 0; a++) - DoAntiNSOBugTest2014_SubMx_F(); -} - - -static void DoAntiNSOBugTest2014(void) -{ - DoAntiNSOBugTest2014_SubA(1); - - ANSOBT_CallCount = 0; - DoAntiNSOBugTest2014_SubM1(); - assert(ANSOBT_CallCount == 2); - - ANSOBT_CallCount = 0; - DoAntiNSOBugTest2014_SubM3(); - assert(ANSOBT_CallCount == 4); -} - -#ifdef WANT_TEST_LEPACKER -void DoLEPackerTest(void) -{ - MDFN::LEPacker mizer; - static const uint8 correct_result[24] = { 0xed, 0xfe, 0xed, 0xde, 0xaa, 0xca, 0xef, 0xbe, 0xbe, 0xba, 0xfe, 0xca, 0xad, 0xde, 0x01, 0x9a, 0x0c, 0xa7, 0xff, 0x00, 0xff, 0xff, 0x55, 0x7f }; - - uint64 u64_test = 0xDEADCAFEBABEBEEFULL; - uint32 u32_test = 0xDEEDFEED; - uint16 u16_test = 0xCAAA; - uint8 u8_test = 0x55; - int32 s32_test = -5829478; - int16 s16_test = -1; - int8 s8_test = 127; - - bool bool_test0 = 0; - bool bool_test1 = 1; - - mizer ^ u32_test; - mizer ^ u16_test; - mizer ^ u64_test; - mizer ^ bool_test1; - mizer ^ s32_test; - mizer ^ bool_test0; - mizer ^ s16_test; - mizer ^ u8_test; - mizer ^ s8_test; - - assert(mizer.size() == 24); - - for(unsigned int i = 0; i < mizer.size(); i++) - { - assert(mizer[i] == correct_result[i]); - } - - u64_test = 0; - u32_test = 0; - u16_test = 0; - u8_test = 0; - s32_test = 0; - s16_test = 0; - s8_test = 0; - - bool_test0 = 1; - bool_test1 = 0; - - mizer.set_read_mode(true); - - mizer ^ u32_test; - mizer ^ u16_test; - mizer ^ u64_test; - mizer ^ bool_test1; - mizer ^ s32_test; - mizer ^ bool_test0; - mizer ^ s16_test; - mizer ^ u8_test; - mizer ^ s8_test; - - - assert(u32_test == 0xDEEDFEED); - assert(u16_test == 0xCAAA); - assert(u64_test == 0xDEADCAFEBABEBEEFULL); - assert(u8_test == 0x55); - assert(s32_test == -5829478); - assert(s16_test == -1); - assert(s8_test == 127); - assert(bool_test0 == 0); - assert(bool_test1 == 1); -} -#endif - -struct MathTestTSOEntry -{ - int32 a; - int32 b; -}; - -// Don't declare as static(though whopr might mess it up anyway) -MathTestTSOEntry MathTestTSOTests[] = -{ - { 0x7FFFFFFF, 2 }, - { 0x7FFFFFFE, 0x7FFFFFFF }, - { 0x7FFFFFFF, 0x7FFFFFFF }, - { 0x7FFFFFFE, 0x7FFFFFFE }, -}; - -volatile int32 MDFNTestsCPP_SLS_Var = (int32)0xDEADBEEF; -volatile int8 MDFNTestsCPP_SLS_Var8 = (int8)0xEF; -volatile int16 MDFNTestsCPP_SLS_Var16 = (int16)0xBEEF; -int32 MDFNTestsCPP_SLS_Var_NT = (int32)0xDEADBEEF; -int32 MDFNTestsCPP_SLS_Var_NT2 = (int32)0x7EADBEEF; - -static uint64 NO_INLINE NO_CLONE Mul_U16U16U32U64_Proper(uint16 a, uint16 b) // For reference -{ - return (uint32)a * (uint32)b; -} - -static uint64 NO_INLINE NO_CLONE Mul_U16U16U32U64(uint16 a, uint16 b) -{ - return (uint32)(a * b); -} - -static void TestSignedOverflow(void) -{ - assert(Mul_U16U16U32U64_Proper(65535, 65535) == 0xfffe0001ULL); - assert(Mul_U16U16U32U64(65535, 65535) == 0xfffe0001ULL); - - for(unsigned int i = 0; i < sizeof(MathTestTSOTests) / sizeof(MathTestTSOEntry); i++) - { - int32 a = MathTestTSOTests[i].a; - int32 b = MathTestTSOTests[i].b; - - assert((a + b) < a && (a + b) < b); - - assert((a + 0x7FFFFFFE) < a); - assert((b + 0x7FFFFFFE) < b); - - assert((a + 0x7FFFFFFF) < a); - assert((b + 0x7FFFFFFF) < b); - - assert((int32)(a + 0x80000000) < a); - assert((int32)(b + 0x80000000) < b); - - assert((int32)(a ^ 0x80000000) < a); - assert((int32)(b ^ 0x80000000) < b); - } - - for(unsigned i = 0; i < 64; i++) - { - MDFNTestsCPP_SLS_Var = (MDFNTestsCPP_SLS_Var << 1) ^ ((MDFNTestsCPP_SLS_Var << 2) + 0x7FFFFFFF) ^ ((MDFNTestsCPP_SLS_Var >> 31) & 0x3); - MDFNTestsCPP_SLS_Var8 = (MDFNTestsCPP_SLS_Var8 << 1) ^ ((MDFNTestsCPP_SLS_Var8 << 2) + 0x7F) ^ ((MDFNTestsCPP_SLS_Var8 >> 7) & 0x3); - MDFNTestsCPP_SLS_Var16 = (MDFNTestsCPP_SLS_Var16 << 1) ^ ((MDFNTestsCPP_SLS_Var16 << 2) + 0x7FFF) ^ ((MDFNTestsCPP_SLS_Var16 >> 15) & 0x3); - } - - { - int8 a = MDFNTestsCPP_SLS_Var8; - int16 b = MDFNTestsCPP_SLS_Var16; - int32 c = MDFNTestsCPP_SLS_Var; - int64 d = (int64)MDFNTestsCPP_SLS_Var * (int64)MDFNTestsCPP_SLS_Var; - int32 e = c; - int64 f = c; - - for(int i = 0; i < 64; i++) - { - a += a * i + b; - b += b * i + c; - c += c * i + d; - d += d * i + a; - - e += e * i + c; - f += f * i + c; - } - //printf("%08x %16llx - %02x %04x %08x %16llx\n", (uint32)e, (uint64)f, (uint8)a, (uint16)b, (uint32)c, (uint64)d); - assert((uint32)e == (uint32)f && (uint32)e == 0x00c37de2 && (uint64)f == 0x5d17261900c37de2); - assert((uint8)a == 0xbf); - assert((uint16)b == 0xb77c); - assert((uint32)c == 0xb4244622U); - assert((uint64)d == 0xa966e02ed95c83fULL); - } - - - //printf("%02x %04x %08x\n", (uint8)MDFNTestsCPP_SLS_Var8, (uint16)MDFNTestsCPP_SLS_Var16, (uint32)MDFNTestsCPP_SLS_Var); - assert((uint8)MDFNTestsCPP_SLS_Var8 == 0x04); - assert((uint16)MDFNTestsCPP_SLS_Var16 == 0xa7d8); - assert((uint32)MDFNTestsCPP_SLS_Var == 0x4ef11a23); - - for(signed i = 1; i != 0; i =~-i); // Not really signed overflow, but meh! - for(signed i = -1; i != 0; i <<= 1); - for(signed i = 1; i >= 0; i *= 3); - - if(MDFNTestsCPP_SLS_Var_NT < 0) - assert((MDFNTestsCPP_SLS_Var_NT << 2) > 0); - - if(MDFNTestsCPP_SLS_Var_NT2 > 0) - assert((MDFNTestsCPP_SLS_Var_NT2 << 2) < 0); -} - -unsigned MDFNTests_OverShiftAmounts[3] = { 8, 16, 32}; -uint32 MDFNTests_OverShiftTV = 0xBEEFD00D; -static void TestDefinedOverShift(void) -{ - //for(unsigned sa = 0; sa < 4; sa++) - { - for(unsigned i = 0; i < 2; i++) - { - uint8 v8 = MDFNTests_OverShiftTV; - uint16 v16 = MDFNTests_OverShiftTV; - uint32 v32 = MDFNTests_OverShiftTV; - - int8 iv8 = MDFNTests_OverShiftTV; - int16 iv16 = MDFNTests_OverShiftTV; - int32 iv32 = MDFNTests_OverShiftTV; - - if(i == 1) - { - v8 >>= MDFNTests_OverShiftAmounts[0]; - v16 >>= MDFNTests_OverShiftAmounts[1]; - v32 = (uint64)v32 >> MDFNTests_OverShiftAmounts[2]; - - iv8 >>= MDFNTests_OverShiftAmounts[0]; - iv16 >>= MDFNTests_OverShiftAmounts[1]; - iv32 = (int64)iv32 >> MDFNTests_OverShiftAmounts[2]; - } - else - { - v8 <<= MDFNTests_OverShiftAmounts[0]; - v16 <<= MDFNTests_OverShiftAmounts[1]; - v32 = (uint64)v32 << MDFNTests_OverShiftAmounts[2]; - - iv8 <<= MDFNTests_OverShiftAmounts[0]; - iv16 <<= MDFNTests_OverShiftAmounts[1]; - iv32 = (int64)iv32 << MDFNTests_OverShiftAmounts[2]; - } - - assert(v8 == 0); - assert(v16 == 0); - assert(v32 == 0); - - assert(iv8 == 0); - assert(iv16 == -(int)i); - assert(iv32 == -(int)i); - } - } -} - -static uint8 BoolConvSupportFunc(void) MDFN_COLD NO_INLINE; -static uint8 BoolConvSupportFunc(void) -{ - return 0xFF; -} - -static bool BoolConv0(void) MDFN_COLD NO_INLINE; -static bool BoolConv0(void) -{ - return BoolConvSupportFunc() & 1; -} - -static void BoolTestThing(unsigned val) MDFN_COLD NO_INLINE; -static void BoolTestThing(unsigned val) -{ - if(val != 1) - printf("%u\n", val); - - assert(val == 1); -} - -static void TestBoolConv(void) -{ - BoolTestThing(BoolConv0()); -} - -static void TestNarrowConstFold(void) NO_INLINE MDFN_COLD; -static void TestNarrowConstFold(void) -{ - unsigned sa = 8; - uint8 za[1] = { 0 }; - int a; - - a = za[0] < (uint8)(1 << sa); - - assert(a == 0); -} - - -unsigned MDFNTests_ModTern_a = 2; -unsigned MDFNTests_ModTern_b = 0; -static void ModTernTestEval(unsigned v) NO_INLINE MDFN_COLD; -static void ModTernTestEval(unsigned v) -{ - assert(v == 0); -} - -static void TestModTern(void) NO_INLINE MDFN_COLD; -static void TestModTern(void) -{ - if(!MDFNTests_ModTern_b) - { - MDFNTests_ModTern_b = MDFNTests_ModTern_a; - - if(1 % (MDFNTests_ModTern_a ? MDFNTests_ModTern_a : 2)) - MDFNTests_ModTern_b = 0; - } - ModTernTestEval(MDFNTests_ModTern_b); -} - -static int TestBWNotMask31GTZ_Sub(int a) NO_INLINE NO_CLONE; -static int TestBWNotMask31GTZ_Sub(int a) -{ - a = (((~a) & 0x80000000LL) > 0) + 1; - return a; -} - -static void TestBWNotMask31GTZ(void) -{ - assert(TestBWNotMask31GTZ_Sub(0) == 2); -} - -int MDFN_tests_TestTernary_val = 0; -static void NO_INLINE NO_CLONE TestTernary_Sub(void) -{ - MDFN_tests_TestTernary_val++; -} - -static void TestTernary(void) -{ - int a = ((MDFN_tests_TestTernary_val++) ? (MDFN_tests_TestTernary_val = 20) : (TestTernary_Sub(), MDFN_tests_TestTernary_val)); - - assert(a == 2); -} - -size_t TestLLVM15470_Counter; -void NO_INLINE NO_CLONE TestLLVM15470_Sub2(size_t x) -{ - assert(x == TestLLVM15470_Counter); - TestLLVM15470_Counter++; -} - -void NO_INLINE NO_CLONE TestLLVM15470_Sub(size_t m) -{ - size_t m2 = ~(size_t)0; - - for(size_t i = 1; i <= 4; i *= m) - m2++; - - for(size_t a = 0; a < 2; a++) - { - for(size_t b = 1; b <= 2; b++) - { - TestLLVM15470_Sub2(a * m2 + b); - } - } -} - -void NO_INLINE NO_CLONE TestLLVM15470(void) -{ - TestLLVM15470_Counter = 1; - TestLLVM15470_Sub(2); -} - -int NO_INLINE NO_CLONE TestGCC60196_Sub(const int16* data, int count) -{ - int ret = 0; - - for(int i = 0; i < count; i++) - ret += i * data[i]; - - return ret; -} - -void NO_INLINE NO_CLONE TestGCC60196(void) -{ - int16 ta[16]; - - for(unsigned i = 0; i < 16; i++) - ta[i] = 1; - - assert(TestGCC60196_Sub(ta, sizeof(ta) / sizeof(ta[0])) == 120); -} - - -uint16 gcc69606_var = 0; -int32 NO_INLINE NO_CLONE TestGCC69606_Sub(int8 a, uint8 e) -{ - int32 f = 1; - int32 mod = ~(int32)a; - int32 d = 0; - - if(gcc69606_var > f) - { - e = gcc69606_var; - d = gcc69606_var | e; - mod = 8; - } - - return (7 + d) % mod; -} - -void NO_INLINE NO_CLONE TestGCC69606(void) -{ - assert(TestGCC69606_Sub(0, 0) == 0); -} - -int8 gcc70941_array[2] = { 0, 0 }; -void NO_INLINE NO_CLONE TestGCC70941(void) -{ - int8 tmp = (0x7F - gcc70941_array[0] - ((gcc70941_array[0] && gcc70941_array[1]) ^ 0x8080)); - - assert(tmp == -1); -} - -void NO_INLINE NO_CLONE TestGCC71488_Sub(long long* p, int v) -{ - for(unsigned i = 0; i < 4; i++) - p[i] = ((!p[4]) > (unsigned)!v) + !p[4]; -} - -void NO_INLINE NO_CLONE TestGCC71488(void) -{ - long long p[5] = { 0, 0, 0, 0, 0 }; - - TestGCC71488_Sub(p, 1); - - assert(p[0] == 2 && p[1] == 2 && p[2] == 2 && p[3] == 2 && p[4] == 0); -} - -int NO_INLINE NO_CLONE TestGCC80631_Sub(int* p) -{ - int ret = -1; - - for(int i = 0; i < 8; i++) - if(p[i]) - ret = i; - - return ret; -} - -void NO_INLINE NO_CLONE TestGCC80631(void) -{ - int p[32]; - - for(int i = 0; i < 32; i++) - p[i] = (i == 0 || i >= 8); - - assert(TestGCC80631_Sub(p) == 0); -} - -NO_INLINE NO_CLONE void TestGCC81740_Sub(int* p, unsigned count) -{ - static const int good[20] = { 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 10, 5, 6, 7, 8, 15, 10, 11, 12, 13 }; - - assert(count == 20); - - for(unsigned i = 0; i < count; i++) - assert(good[i] == p[i]); -} - -int TestGCC81740_b; - -NO_INLINE NO_CLONE void TestGCC81740(void) -{ - int v[4][5] = { 0 }; - - for(unsigned i = 0; i < sizeof(v) / sizeof(int); i++) - (&v[0][0])[i] = i; - - for(int a = 3; a >= 0; a--) - for(TestGCC81740_b = 0; TestGCC81740_b < 3; TestGCC81740_b++) - v[TestGCC81740_b + 1][a + 1] = v[TestGCC81740_b][a]; - - TestGCC81740_Sub(&v[0][0], sizeof(v) / sizeof(int)); -} - -template -void NO_INLINE NO_CLONE TestSUCompare_Sub(A a, B b) -{ - assert(a < b); -} - -int16 TestSUCompare_x0 = 256; - -void NO_INLINE NO_CLONE TestSUCompare(void) -{ - int8 a = 1; - uint8 b = 255; - int16 c = 1; - uint16 d = 65535; - int32 e = 1; - uint32 f = ~0U; - int64 g = ~(uint32)0; - uint64 h = ~(uint64)0; - - assert(a < b); - assert(c < d); - assert((uint32)e < f); - assert((uint64)g < h); - - TestSUCompare_Sub(1, 255); - TestSUCompare_Sub(1, 65535); - - TestSUCompare_Sub(TestSUCompare_x0, 255); -} - -template -NO_INLINE NO_CLONE void CheckAlignasType_Sub(void* p) -{ - assert(((uintptr_t)p % alignof(T)) == 0); -} - -template -NO_INLINE NO_CLONE void CheckAlignasI_Sub(void* p) -{ - assert(((uintptr_t)p % I) == 0); -} - -template -NO_INLINE NO_CLONE void CheckAlignasType(void) -{ - alignas(alignof(T)) uint8 lv0[sizeof(T) + 1]; - alignas(alignof(T)) uint8 lv1[sizeof(T) + 1]; - alignas(alignof(T)) static uint8 gv0[sizeof(T) + 1]; - alignas(alignof(T)) static uint8 gv1[sizeof(T) + 1]; - - CheckAlignasType_Sub((void*)lv0); - CheckAlignasType_Sub((void*)lv1); - CheckAlignasType_Sub((void*)gv0); - CheckAlignasType_Sub((void*)gv1); -} - -template -NO_INLINE NO_CLONE void CheckAlignasI(void) -{ - alignas(I) uint8 lv0[I + 1]; - alignas(I) uint8 lv1[I + 1]; - alignas(I) static uint8 gv0[I + 1]; - alignas(I) static uint8 gv1[I + 1]; - - CheckAlignasI_Sub((void*)lv0); - CheckAlignasI_Sub((void*)lv1); - CheckAlignasI_Sub((void*)gv0); - CheckAlignasI_Sub((void*)gv1); -} - -static void DoAlignmentChecks(void) -{ - static_assert(alignof(uint8) <= sizeof(uint8), "Alignment of type is greater than size of type."); - static_assert(alignof(uint16) <= sizeof(uint16), "Alignment of type is greater than size of type."); - static_assert(alignof(uint32) <= sizeof(uint32), "Alignment of type is greater than size of type."); - static_assert(alignof(uint64) <= sizeof(uint64), "Alignment of type is greater than size of type."); - - CheckAlignasType(); - CheckAlignasType(); - CheckAlignasType(); - CheckAlignasType(); - CheckAlignasType(); - -#if defined(ARCH_X86) - CheckAlignasI<16>(); -#endif - -#if defined(__MMX__) - CheckAlignasType<__m64>(); -#endif - -#if defined(__SSE__) - CheckAlignasType<__m128>(); -#endif - -#if defined(HAVE_ALTIVEC_INTRINSICS) - CheckAlignasType(); - CheckAlignasType(); -#endif - -#ifdef __ARM_NEON__ - CheckAlignasType(); - CheckAlignasType(); - CheckAlignasType(); -#endif -} - - -static uint32 NO_INLINE NO_CLONE RunMASMemTests_DoomAndGloom(uint32 offset) -{ - MultiAccessSizeMem<4, false> mt0; - - mt0.WriteU32(offset, 4); - mt0.WriteU16(offset, 0); - mt0.WriteU32(offset, mt0.ReadU32(offset) + 1); - - return mt0.ReadU32(offset); -} - -static void RunMASMemTests(void) -{ - // Little endian: - { - MultiAccessSizeMem<4, false> mt0; - - mt0.WriteU16(0, 0xDEAD); - mt0.WriteU32(0, 0xCAFEBEEF); - mt0.WriteU16(2, mt0.ReadU16(0)); - mt0.WriteU8(1, mt0.ReadU8(0)); - mt0.WriteU16(2, mt0.ReadU16(0)); - mt0.WriteU32(0, mt0.ReadU32(0) + 0x13121111); - - assert(mt0.ReadU16(0) == 0x0100 && mt0.ReadU16(2) == 0x0302); - assert(mt0.ReadU32(0) == 0x03020100); - - mt0.WriteU32(0, 0xB0B0AA55); - mt0.WriteU24(0, 0xDEADBEEF); - assert(mt0.ReadU32(0) == 0xB0ADBEEF); - assert(mt0.ReadU24(1) == 0x00B0ADBE); - } - - // Big endian: - { - MultiAccessSizeMem<4, true> mt0; - - mt0.WriteU16(2, 0xDEAD); - mt0.WriteU32(0, 0xCAFEBEEF); - mt0.WriteU16(0, mt0.ReadU16(2)); - mt0.WriteU8(2, mt0.ReadU8(3)); - mt0.WriteU16(0, mt0.ReadU16(2)); - mt0.WriteU32(0, mt0.ReadU32(0) + 0x13121111); - - assert(mt0.ReadU16(2) == 0x0100 && mt0.ReadU16(0) == 0x0302); - assert(mt0.ReadU32(0) == 0x03020100); - - mt0.WriteU32(0, 0xB0B0AA55); - mt0.WriteU24(1, 0xDEADBEEF); - assert(mt0.ReadU32(0) == 0xB0ADBEEF); - assert(mt0.ReadU24(0) == 0x00B0ADBE); - } - - assert(RunMASMemTests_DoomAndGloom(0) == 1); -} - -static void NO_INLINE NO_CLONE RunMiscEndianTests(uint32 arg0, uint32 arg1) -{ - uint8 mem[8]; - - memset(mem, 0xFF, sizeof(mem)); - - MDFN_en24msb(&mem[0], arg0); - MDFN_en24lsb(&mem[4], arg1); - - assert(MDFN_de32lsb(&mem[0]) == 0xFF030201); - assert(MDFN_de32lsb(&mem[4]) == 0xFF030201); - - assert(MDFN_de32msb(&mem[0]) == 0x010203FF); - assert(MDFN_de32msb(&mem[4]) == 0x010203FF); - - assert(MDFN_de32lsb(&mem[0]) == 0xFF030201); - assert(MDFN_de32msb(&mem[4]) == 0x010203FF); - - assert(MDFN_de24lsb(&mem[0]) == 0x030201); - assert(MDFN_de24lsb(&mem[4]) == 0x030201); - - assert(MDFN_de24msb(&mem[0]) == 0x010203); - assert(MDFN_de24msb(&mem[4]) == 0x010203); - - assert(MDFN_de24lsb(&mem[1]) == 0xFF0302); - assert(MDFN_de24lsb(&mem[5]) == 0xFF0302); - - assert(MDFN_de24msb(&mem[1]) == 0x0203FF); - assert(MDFN_de24msb(&mem[5]) == 0x0203FF); - - assert(MDFN_de64lsb(&mem[0]) == 0xFF030201FF030201ULL); - assert(MDFN_de64msb(&mem[0]) == 0x010203FF010203FFULL); - // - // - // - uint16 mem16[8] = { 0x1122, 0x3344, 0x5566, 0x7788, 0x99AA, 0xBBCC, 0xDDEE, 0xFF00 }; - - for(unsigned i = 0; i < 8; i++) - { - assert(ne16_rbo_le(mem16, i << 1) == mem16[i]); - assert(ne16_rbo_be(mem16, i << 1) == mem16[i]); - } - - for(unsigned i = 0; i < 4; i++) - { - assert(ne16_rbo_le(mem16, i * 4) == (uint32)(mem16[i * 2] | (mem16[i * 2 + 1] << 16))); - assert(ne16_rbo_be(mem16, i * 4) == (uint32)(mem16[i * 2 + 1] | (mem16[i * 2] << 16))); - } - - for(unsigned i = 0; i < 16; i++) - { - assert(ne16_rbo_le(mem16, i) == (uint8)(mem16[i >> 1] >> ((i & 1) * 8))); - assert(ne16_rbo_be(mem16, i) == (uint8)(mem16[i >> 1] >> (8 - ((i & 1) * 8)))); - } - - ne16_rwbo_le(mem16, 0, &mem16[7]); - ne16_rwbo_le(mem16, 0, &mem16[6]); - ne16_rwbo_be(mem16, 4, &mem16[3]); - ne16_rwbo_be(mem16, 4, &mem16[1]); - - assert(mem16[7] == 0x1122); - assert(mem16[0] == 0xDDEE); - assert(mem16[3] == 0x5566); - assert(mem16[2] == 0x3344); - - { - uint64 v64 = 0xDEADBEEFCAFEBABEULL; - - for(unsigned i = 0; i < 8; i++) - { - if(!(i & 0x7)) - { - assert(ne64_rbo_be(&v64, i) == v64); - assert(ne64_rbo_le(&v64, i) == v64); - } - - if(!(i & 0x3)) - { - assert(ne64_rbo_be(&v64, i) == (uint32)(v64 >> (32 - i * 8))); - assert(ne64_rbo_le(&v64, i) == (uint32)(v64 >> (i * 8))); - } - - if(!(i & 0x1)) - { - assert(ne64_rbo_be(&v64, i) == (uint16)(v64 >> (48 - i * 8))); - assert(ne64_rbo_le(&v64, i) == (uint16)(v64 >> (i * 8))); - } - - assert(ne64_rbo_be(&v64, i) == (uint8)(v64 >> (56 - i * 8))); - assert(ne64_rbo_le(&v64, i) == (uint8)(v64 >> (i * 8))); - } - - ne64_wbo_be(&v64, 0, 0xCAFEBABEDEADBEEF); - assert(v64 == 0xCAFEBABEDEADBEEF); - ne64_wbo_le(&v64, 0, 0xD00FDAD0); - ne64_wbo_be(&v64, 0, 0xF00D); - uint8 z[2] = { 0xC0, 0xBB }; - ne64_rwbo_be(&v64, 2, &z[0]); - ne64_rwbo_le(&v64, 4, &z[1]); - - ne64_rwbo_le(&v64, 5, &z[0]); - ne64_rwbo_be(&v64, 3, &z[1]); - - assert(z[0] == 0xC0 && z[1] == 0xBB); - assert(v64 == 0xF00DC0BBD00FDAD0ULL); - } - - // - // - // - for(unsigned i = 0; i < 8; i++) - { - for(unsigned z = 0; z < 8; z++) - mem[z] = z; - - #ifdef LSB_FIRST - Endian_V_NE_BE(mem, i); - #else - Endian_V_NE_LE(mem, i); - #endif - - for(unsigned z = 0; z < 8; z++) - assert(mem[z] == ((z >= i) ? z : (i - 1 - z))); - } -} - -static void NO_INLINE NO_CLONE ExceptionTestSub(int v, int n, int* y) -{ - if(n) - { - if(n & 1) - { - try - { - ExceptionTestSub(v + n, n - 1, y); - } - catch(const std::exception &e) - { - (*y)++; - throw; - } - } - else - ExceptionTestSub(v + n, n - 1, y); - } - else - throw MDFN_Error(v, "%d", v); -} - -static NO_CLONE NO_INLINE int RunExceptionTests_TEP(void* data) -{ - std::atomic_int_least32_t* sv = (std::atomic_int_least32_t*)data; - - sv->fetch_sub(1, std::memory_order_release); - - while(sv->load(std::memory_order_acquire) > 0); - - unsigned t = 0; - - for(; !t || sv->load(std::memory_order_acquire) == 0; t++) - { - int y = 0; - int z = 0; - - for(int x = -8; x < 8; x++) - { - try - { - ExceptionTestSub(x, x & 3, &y); - } - catch(const MDFN_Error &e) - { - int epv = x; - - for(unsigned i = x & 3; i; i--) - epv += i; - - z += epv; - - assert(e.GetErrno() == epv); - assert(atoi(e.what()) == epv); - continue; - } - catch(...) - { - abort(); - } - abort(); - } - - assert(y == 16); - assert(z == 32); - } - - return t; -} - -std::vector stltests_vec[2]; - -static void NO_INLINE NO_CLONE RunSTLTests_Sub0(int v) -{ - stltests_vec[0].assign(v, v); -} - -static void RunSTLTests(void) -{ - assert(stltests_vec[0] == stltests_vec[1]); - RunSTLTests_Sub0(0); - assert(stltests_vec[0] == stltests_vec[1]); - RunSTLTests_Sub0(1); - RunSTLTests_Sub0(0); - assert(stltests_vec[0] == stltests_vec[1]); -} - -static void LZTZCount_Test(void) -{ - for(uint32 i = 0, x = 0; i < 33; i++, x = (x << 1) + 1) - { - assert(MDFN_tzcount16(~x) == std::min(16, i)); - assert(MDFN_tzcount32(~x) == i); - assert(MDFN_lzcount32(x) == 32 - i); - } - - for(uint32 i = 0, x = 0; i < 33; i++, x = (x ? (x << 1) : 1)) - { - assert(MDFN_tzcount16(x) == (std::min(17, i) + 16) % 17); - assert(MDFN_tzcount32(x) == (i + 32) % 33); - assert(MDFN_lzcount32(x) == 32 - i); - } - - for(uint64 i = 0, x = 0; i < 65; i++, x = (x << 1) + 1) - { - assert(MDFN_tzcount64(~x) == i); - assert(MDFN_lzcount64(x) == 64 - i); - } - - for(uint64 i = 0, x = 0; i < 65; i++, x = (x ? (x << 1) : 1)) - { - assert(MDFN_tzcount64(x) == (i + 64) % 65); - assert(MDFN_lzcount64(x) == 64 - i); - } - - uint32 tv = 0; - for(uint32 i = 0, x = 1; i < 200; i++, x = (x * 9) + MDFN_lzcount32(x) + MDFN_lzcount32(x >> (x & 31))) - { - tv += x; - } - assert(tv == 0x397d920f); - - uint64 tv64 = 0; - for(uint64 i = 0, x = 1; i < 200; i++, x = (x * 9) + MDFN_lzcount64(x) + MDFN_lzcount64(x >> (x & 63))) - { - tv64 += x; - } - assert(tv64 == 0x7b8263de01922c29); -} - -// don't make this static, and don't make it local scope. Whole-program optimization might defeat the purpose of this, though... -unsigned int mdfn_shifty_test[4] = -{ - 0, 8, 16, 32 -}; - - -// Don't make static. -double mdfn_fptest0_sub(double x, double n) MDFN_COLD NO_INLINE; -double mdfn_fptest0_sub(double x, double n) -{ - double u = x / (n * n); - - return(u); -} - -static void fptest0(void) -{ - assert(mdfn_fptest0_sub(36, 2) == 9); -} - -volatile double mdfn_fptest1_v; -static void fptest1(void) -{ - mdfn_fptest1_v = 1.0; - - for(int i = 0; i < 128; i++) - mdfn_fptest1_v *= 2; - - assert(mdfn_fptest1_v == 340282366920938463463374607431768211456.0); -} - -#if defined(HAVE_FENV_H) && defined(HAVE_NEARBYINTF) -// For advisory/debug purposes, don't error out on failure. -static void libc_rounding_test(void) -{ - unsigned old_rm = fegetround(); - float tv = 4118966.75; - float goodres = 4118967.0; - float res; - - fesetround(FE_TONEAREST); - - if((res = nearbyintf(tv)) != goodres) - fprintf(stderr, "\n***** Buggy libc nearbyintf() detected(%f != %f). *****\n\n", res, goodres); - - fesetround(old_rm); -} -#else -static void libc_rounding_test(void) -{ - -} -#endif - -static int pow_test_sub_a(int y, double z) NO_INLINE NO_CLONE; -static int pow_test_sub_a(int y, double z) -{ - return std::min(floor(pow(10, z)), std::min(floor(pow(10, y)), (int)pow(10, y))); -} - -static int pow_test_sub_b(int y) NO_INLINE NO_CLONE; -static int pow_test_sub_b(int y) -{ - return std::min(floor(pow(2, y)), (int)pow(2, y)); -} - -static void pow_test(void) -{ - unsigned muller10 = 1; - unsigned muller2 = 1; - - for(int y = 0; y < 10; y++, muller10 *= 10, muller2 <<= 1) - { - unsigned res10 = pow_test_sub_a(y, y); - unsigned res2 = pow_test_sub_b(y); - - //printf("%u %u\n", res10, res2); - - assert(res10 == muller10); - assert(res2 == muller2); - } -} - -static void RunFPTests(void) -{ - fptest0(); - fptest1(); - - libc_rounding_test(); - pow_test(); -} - -static void NO_CLONE NO_INLINE NE1664_Test_Sub(uint16* buf) -{ - ne16_wbo_be(buf, 3, 0xAA); - ne16_wbo_be(buf, 2, 0xDEAD); - ne16_wbo_be(buf, 0, 0xCAFEBEEF); - ne16_wbo_be(buf, 0, ne16_rbo_be(buf, 2) ^ ne16_rbo_be(buf, 0)); - ne16_wbo_be(buf, 0, ne16_rbo_be(buf, 0) ^ ne16_rbo_be(buf, 2)); -} - -static void NO_CLONE NO_INLINE NE1664_Test_Sub64(uint64* buf) -{ - ne64_wbo_be(buf, 0, 0x1111); - ne64_wbo_be(buf, 2, 0x2222); - ne64_wbo_be(buf, 4, 0x4444); - ne64_wbo_be(buf, 6, 0x6666); - - ne64_wbo_be(buf, 0, 0x33333333); - ne64_wbo_be(buf, 4, 0x77777777); - - *buf += ne64_rbo_be(buf, 0) + ne64_rbo_be(buf, 2) + ne64_rbo_be(buf, 4) + ne64_rbo_be(buf, 6); -} - -static void NE1664_Test(void) -{ - uint16 buf[2] = { 0, 0 }; - uint64 var64 = 0xDEADBEEFCAFEF00DULL; - - NE1664_Test_Sub(buf); - NE1664_Test_Sub64(&var64); - - assert((buf[0] == buf[1]) && buf[0] == 0x7411); - assert(var64 == 0x333333337778CCCBULL); -} - -#ifdef WANT_TEST_ZLIB -static void zlib_test(void) -{ - auto cfl = zlibCompileFlags(); - - assert((2 << ((cfl >> 0) & 0x3)) == sizeof(uInt)); - assert((2 << ((cfl >> 2) & 0x3)) == sizeof(uLong)); - assert((2 << ((cfl >> 4) & 0x3)) == sizeof(voidpf)); - - #ifdef Z_LARGE64 - if((2 << ((cfl >> 6) & 0x3)) != sizeof(z_off_t)) - { - assert(sizeof(z_off64_t) == 8); - assert(&gztell == &gztell64); - } - #else - assert((2 << ((cfl >> 6) & 0x3)) == sizeof(z_off_t)); - #endif -} -#endif - -#ifdef WANT_TEST_MEMOPS -static NO_INLINE NO_CLONE void memops_test_sub(uint8* mem8) -{ - for(unsigned offs = 0; offs < 8; offs++) - { - for(unsigned len = 1; len < 32; len++) - { - memset(mem8, 0x88, 64); - - MDFN_FastArraySet(&mem8[offs], 0x55, len); - - for(unsigned i = 0; i < 64; i++) - { - if(i < offs || i >= (offs + len)) - assert(mem8[i] == 0x88); - else - assert(mem8[i] == 0x55); - } - } - } -} - -static void memops_test(void) -{ - uint8 mem8[64]; - - memops_test_sub(mem8); -} -#endif - -static void TestLog2(void) -{ - static const struct - { - uint64 val; - unsigned expected; - } log2_test_vals[] = - { - { 0, 0 }, - { 1, 0 }, - { 2, 1 }, - { 3, 1 }, - { 4, 2 }, - { 5, 2 }, - { 6, 2 }, - { 7, 2 }, - { 4095, 11 }, - { 4096, 12 }, - { 4097, 12 }, - { 0x7FFE, 14 }, - { 0x7FFF, 14 }, - { 0x8000, 15 }, - { 0x8001, 15 }, - { 0xFFFF, 15 }, - { 0x7FFFFFFF, 30 }, - { 0x80000000, 31 }, - { 0xFFFFFFFF, 31 }, - { 0x7FFFFFFFFFFFFFFEULL, 62 }, - { 0x7FFFFFFFFFFFFFFFULL, 62 }, - { 0x8000000000000000ULL, 63 }, - { 0x8000000000000001ULL, 63 }, - { 0x8AAAAAAAAAAAAAAAULL, 63 }, - { 0xFFFFFFFFFFFFFFFFULL, 63 }, - }; - - for(const auto& tv : log2_test_vals) - { - if((uint32)tv.val == tv.val) - { - assert(MDFN_log2((uint32)tv.val) == tv.expected); - assert(MDFN_log2((int32)tv.val) == tv.expected); - } - - assert(MDFN_log2((uint64)tv.val) == tv.expected); - assert(MDFN_log2((int64)tv.val) == tv.expected); - } -} - -static void TestRoundPow2(void) -{ - static const struct - { - uint64 val; - uint64 expected; - } rup2_test_vals[] = - { - { 0, 1 }, - { 1, 1 }, - { 2, 2 }, - { 3, 4 }, - { 4, 4 }, - { 5, 8 }, - { 7, 8 }, - { 8, 8 }, - { 0x7FFF, 0x8000 }, - { 0x8000, 0x8000 }, - { 0x8001, 0x10000 }, - { 0x10000, 0x10000 }, - { 0x10001, 0x20000 }, - { 0x7FFFFFFF, 0x80000000 }, - { 0x80000000, 0x80000000 }, - { 0x80000001, 0x100000000ULL }, - { 0x100000000ULL, 0x100000000ULL }, - { 0x100000001ULL, 0x200000000ULL }, - { 0xFFFFFFFFFFFFFFFFULL, 0 }, - }; - - for(auto const& tv : rup2_test_vals) - { - if((uint32)tv.val == tv.val) - { - assert(round_up_pow2((uint32)tv.val) == (uint64)tv.expected); - assert(round_up_pow2((int32)tv.val) == (uint64)tv.expected); - } - - assert(round_up_pow2((uint64)tv.val) == (uint64)tv.expected); - assert(round_up_pow2((int64)tv.val) == (uint64)tv.expected); - } - - for(unsigned i = 1; i < 64; i++) - { - if(i < 32) - { - assert(round_up_pow2((uint32)(((uint64)1 << i) + 0)) == ((uint64)1 << i)); - assert(round_up_pow2((uint32)(((uint64)1 << i) + 1)) == (((uint64)1 << i) << 1)); - } - assert(round_up_pow2(((uint64)1 << i) + 0) == ((uint64)1 << i)); - assert(round_up_pow2(((uint64)1 << i) + 1) == (((uint64)1 << i) << 1)); - } - - assert(round_nearest_pow2((uint16)0xC000, false) == 0x00008000U); - assert(round_nearest_pow2( (int16)0x6000, false) == 0x00004000U); - assert(round_nearest_pow2( (int16)0x6000, true) == 0x00008000U); - assert(round_nearest_pow2((uint16)0xC000) == 0x00010000U); - assert(round_nearest_pow2( (int16)0xC000) == 0x100000000ULL); - - for(int i = 0; i < 64; i++) - { - assert( round_nearest_pow2(((uint64)1 << i) + 0) == (((uint64)1 << i) << 0) ); - if(i > 0) - { - assert( round_nearest_pow2(((uint64)1 << i) + ((uint64)1 << (i - 1)) ) == (((uint64)1 << i) << 1) ); - assert( round_nearest_pow2(((uint64)1 << i) + ((uint64)1 << (i - 1)) - 1) == (((uint64)1 << i) << 0) ); - } - - assert( round_nearest_pow2(((uint64)1 << i) + 0, false) == (((uint64)1 << i) << 0) ); - if(i > 0) - { - assert( round_nearest_pow2(((uint64)1 << i) + ((uint64)1 << (i - 1)) + 1, false) == (((uint64)1 << i) << 1) ); - assert( round_nearest_pow2(((uint64)1 << i) + ((uint64)1 << (i - 1)) + 0, false) == (((uint64)1 << i) << 0) ); - assert( round_nearest_pow2(((uint64)1 << i) + ((uint64)1 << (i - 1)) - 1, false) == (((uint64)1 << i) << 0) ); - } - - { - float tmp = i ? floor((1.0 / 2) + (float)i / (1U << MDFN_log2(i))) * (1U << MDFN_log2(i)) : 1.0; - //printf("%d, %d %d -- %f\n", i, round_nearest_pow2(i, true), round_nearest_pow2(i, false), tmp); - assert(tmp == round_nearest_pow2(i)); - } - } - - #if 0 - { - uint64 lcg = 7; - uint64 accum = 0; - - for(unsigned i = 0; i < 256; i++, lcg = (lcg * 6364136223846793005ULL) + 1442695040888963407ULL) - accum += round_up_pow2(lcg) * 1 + round_up_pow2((uint32)lcg) * 3 + round_up_pow2((uint16)lcg) * 5 + round_up_pow2((uint8)lcg) * 7; - - assert(accum == 0xb40001fbdb46577cULL); - } - #endif -} - -template -static NO_INLINE NO_CLONE RT TestCasts_Sub_L(T v) -{ - return (RT)v << sa; -} - -template -static NO_INLINE NO_CLONE RT TestCasts_Sub_R(T v) -{ - return (RT)v >> sa; -} - -template -static INLINE RT TestCasts_Sub(T v) -{ - if(sa < 0) - return TestCasts_Sub_R(v); - else - return TestCasts_Sub_L(v); -} - -static void TestCastShift(void) -{ - assert((TestCasts_Sub< int64, uint8, 4>(0xEF) == 0x0000000000000EF0ULL)); - assert((TestCasts_Sub(0xEF) == 0xFFFFFFFFFFFFFEF0ULL)); - - assert((TestCasts_Sub< int64, uint16, 4>(0xBEEF) == 0x00000000000BEEF0ULL)); - assert((TestCasts_Sub(0xBEEF) == 0xFFFFFFFFFFFBEEF0ULL)); - - assert((TestCasts_Sub< int64, uint32, 4>(0xDEADBEEF) == 0x0000000DEADBEEF0ULL)); - assert((TestCasts_Sub(0xDEADBEEF) == 0xFFFFFFFDEADBEEF0ULL)); - - assert((TestCasts_Sub< int64, uint8, 20>(0xEF) == 0x000000000EF00000ULL)); - assert((TestCasts_Sub(0xEF) == 0xFFFFFFFFFEF00000ULL)); - - assert((TestCasts_Sub< int64, uint16, 20>(0xBEEF) == 0x0000000BEEF00000ULL)); - assert((TestCasts_Sub(0xBEEF) == 0xFFFFFFFBEEF00000ULL)); - - assert((TestCasts_Sub< int64, uint32, 20>(0xDEADBEEF) == 0x000DEADBEEF00000ULL)); - assert((TestCasts_Sub(0xDEADBEEF) == 0xFFFDEADBEEF00000ULL)); - - assert((TestCasts_Sub< int64, uint8, -4>(0xEF) == 0x000000000000000EULL)); - assert((TestCasts_Sub(0xEF) == 0x0FFFFFFFFFFFFFFEULL)); - - assert((TestCasts_Sub< int64, uint16, -4>(0xBEEF) == 0x0000000000000BEEULL)); - assert((TestCasts_Sub(0xBEEF) == 0x0FFFFFFFFFFFFBEEULL)); - - assert((TestCasts_Sub< int64, uint32, -4>(0xDEADBEEF) == 0x000000000DEADBEEULL)); - assert((TestCasts_Sub(0xDEADBEEF) == 0x0FFFFFFFFDEADBEEULL)); - - assert((TestCasts_Sub< int64, uint8, -20>(0xEF) == 0x0000000000000000ULL)); - assert((TestCasts_Sub(0xEF) == 0x00000FFFFFFFFFFFULL)); - - assert((TestCasts_Sub< int64, uint16, -20>(0xBEEF) == 0x0000000000000000ULL)); - assert((TestCasts_Sub(0xBEEF) == 0x00000FFFFFFFFFFFULL)); - - assert((TestCasts_Sub< int64, uint32, -20>(0xDEADBEEF) == 0x0000000000000DEAULL)); - assert((TestCasts_Sub(0xDEADBEEF) == 0x00000FFFFFFFFDEAULL)); -} - -#ifdef WANT_TEST_TIME -static void Time_Test(void) -{ - { - struct tm ut = Time::UTCTime(0); - - assert(ut.tm_sec == 0); - assert(ut.tm_min == 0); - assert(ut.tm_hour == 0); - assert(ut.tm_mday == 1); - assert(ut.tm_mon == 0); - assert(ut.tm_year = 70); - assert(ut.tm_wday == 4); - assert(ut.tm_yday == 0); - assert(ut.tm_isdst <= 0); - } - - #ifndef WIN32 - if(sizeof(time_t) >= 8) - #endif - { - struct tm ut = Time::UTCTime((int64)1 << 32); - - assert(ut.tm_sec == 16); - assert(ut.tm_min == 28); - assert(ut.tm_hour == 6); - assert(ut.tm_mday == 7); - assert(ut.tm_mon == 1); - assert(ut.tm_year = 106); - assert(ut.tm_wday == 0); - assert(ut.tm_yday == 37); - assert(ut.tm_isdst <= 0); - } -} -#endif - -const char* MDFN_tests_stringA = "AB\0C"; -const char* MDFN_tests_stringB = "AB\0CD"; -const char* MDFN_tests_stringC = "AB\0X"; - -static void TestSStringNullChar(void) -{ - assert(MDFN_tests_stringA != MDFN_tests_stringB && MDFN_tests_stringA[3] == 'C' && MDFN_tests_stringB[4] == 'D'); - assert(MDFN_tests_stringA != MDFN_tests_stringC && MDFN_tests_stringB != MDFN_tests_stringC && MDFN_tests_stringC[3] == 'X'); -} - -static void TestArithRightShift(void) -{ - { - int32 meow; - - meow = 1; - meow >>= 1; - assert(meow == 0); - - meow = 5; - meow >>= 1; - assert(meow == 2); - - meow = -1; - meow >>= 1; - assert(meow == -1); - - meow = -5; - meow >>= 1; - assert(meow == -3); - - meow = 1; - meow /= 2; - assert(meow == 0); - - meow = 5; - meow /= 2; - assert(meow == 2); - - meow = -1; - meow /= 2; - assert(meow == 0); - - meow = -5; - meow /= 2; - assert(meow == -2); - - meow = -5; - meow = (int32)(meow + ((uint32)meow >> 31)) >> 1; - assert(meow == -2); - - #if 0 - meow = 1 << 30; - meow <<= 1; - assert(meow == -2147483648); - - meow = 1 << 31; - meow <<= 1; - assert(meow == 0); - #endif - } - - - // New tests added May 22, 2010 to detect MSVC compiler(and possibly other compilers) bad code generation. - { - uint32 test_tab[4] = { 0x2000 | 0x1000, 0x2000, 0x1000, 0x0000 }; - const uint32 result_tab[4][2] = { { 0xE, 0x7 }, { 0xE, 0x0 }, { 0x0, 0x7 }, { 0x0, 0x0 } }; - - for(int i = 0; i < 4; i++) - { - uint32 hflip_xor; - uint32 vflip_xor; - uint32 bgsc; - - bgsc = test_tab[i]; - - hflip_xor = ((int32)(bgsc << 18) >> 30) & 0xE; - vflip_xor = ((int32)(bgsc << 19) >> 31) & 0x7; - - assert(hflip_xor == result_tab[i][0]); - assert(vflip_xor == result_tab[i][1]); - - //printf("%d %d\n", hflip_xor, result_tab[i][0]); - //printf("%d %d\n", vflip_xor, result_tab[i][1]); - } - - uint32 lfsr = 1; - - // quick and dirty RNG(to also test non-constant-expression evaluation, at least until compilers are extremely advanced :b) - for(int i = 0; i < 256; i++) - { - int feedback = ((lfsr >> 7) & 1) ^ ((lfsr >> 14) & 1); - lfsr = ((lfsr << 1) & 0x7FFF) | feedback; - - uint32 hflip_xor; - uint32 vflip_xor; - uint32 hflip_xor_alt; - uint32 vflip_xor_alt; - uint32 bgsc; - - bgsc = lfsr; - - hflip_xor = ((int32)(bgsc << 18) >> 30) & 0xE; - vflip_xor = ((int32)(bgsc << 19) >> 31) & 0x7; - - hflip_xor_alt = bgsc & 0x2000 ? 0xE : 0; - vflip_xor_alt = bgsc & 0x1000 ? 0x7 : 0; - - assert(hflip_xor == hflip_xor_alt); - assert(vflip_xor == vflip_xor_alt); - } - } -} - -#ifdef WANT_TEST_THREADS -static int ThreadSafeErrno_Test_Entry(void* data) -{ - MDFN_Sem** sem = (MDFN_Sem**)data; - - errno = 0; - - MDFND_PostSem(sem[0]); - MDFND_WaitSem(sem[1]); - - errno = 0xDEAD; - MDFND_PostSem(sem[0]); - return 0; -} - -static void ThreadSafeErrno_Test(void) -{ - //uint64 st = Time::MonoUS(); - // - MDFN_Sem* sem[2] = { MDFND_CreateSem(), MDFND_CreateSem() }; - MDFN_Thread* thr = MDFND_CreateThread(ThreadSafeErrno_Test_Entry, sem); - - MDFND_WaitSem(sem[0]); - errno = 0; - MDFND_PostSem(sem[1]); - MDFND_WaitSem(sem[0]); - assert(errno != 0xDEAD); - MDFND_WaitThread(thr, nullptr); - MDFND_DestroySem(sem[0]); - MDFND_DestroySem(sem[1]); - // - // - // - errno = 0; - //printf("%llu\n", (unsigned long long)Time::MonoUS() - st); -} -#endif - -} - -using namespace MDFN_TESTS_CPP; - -#ifdef WANT_TEST_EXCEPTIONS -void MDFN_RunExceptionTests(const unsigned thread_count, const unsigned thread_delay) -{ - std::atomic_int_least32_t sv; - - if(thread_count == 1) - { - sv.store(-1, std::memory_order_release); - RunExceptionTests_TEP(&sv); - } - else - { - ThreadSafeErrno_Test(); - // - // - std::vector t; - std::vector trv; - - t.resize(thread_count); - trv.resize(thread_count); - - sv.store(thread_count, std::memory_order_release); - - for(unsigned i = 0; i < thread_count; i++) - t[i] = MDFND_CreateThread(RunExceptionTests_TEP, &sv); - - Time::SleepMS(thread_delay); - - sv.store(-1, std::memory_order_release); - - for(unsigned i = 0; i < thread_count; i++) - MDFND_WaitThread(t[i], &trv[i]); - - for(unsigned i = 0; i < thread_count; i++) - printf("%d: %d\n", i, trv[i]); - } -} -#endif - -bool MDFN_RunMathTests(void) -{ - DoSizeofTests(); - - TestSStringNullChar(); - - TestTypesSign(); - - TestArithRightShift(); - - DoAlignmentChecks(); - TestSignedOverflow(); - TestDefinedOverShift(); - TestBoolConv(); - TestNarrowConstFold(); - - TestGCC60196(); - TestGCC69606(); - TestGCC70941(); - TestGCC71488(); - TestGCC80631(); - TestGCC81740(); - - TestModTern(); - TestBWNotMask31GTZ(); - TestTernary(); - TestLLVM15470(); - - TestSUCompare(); - - TestSignExtend(); - - DoAntiNSOBugTest(); - DoAntiNSOBugTest2014(); - - #ifdef WANT_TEST_LEPACKER - DoLEPackerTest(); - #endif - - TestLog2(); - - TestRoundPow2(); - - RunFPTests(); - - RunMASMemTests(); - - RunMiscEndianTests(0xAA010203, 0xBB030201); - - #ifdef WANT_TEST_EXCEPTIONS - MDFN_RunExceptionTests(1, 0); - #endif - - RunSTLTests(); - - LZTZCount_Test(); - - NE1664_Test(); - - #ifdef WANT_TEST_HASH - sha1_test(); - sha256_test(); - #endif - - #ifdef WANT_TEST_ZLIB - zlib_test(); - #endif - - #ifdef WANT_TEST_MEMOPS - memops_test(); - #endif - - #ifdef WANT_TEST_TIME - Time_Test(); - #endif - - TestCastShift(); - -#if 0 -// Not really a math test. - const char *test_paths[] = { "/meow", "/meow/cow", "\\meow", "\\meow\\cow", "\\\\meow", "\\\\meow\\cow", - "/meow.", "/me.ow/cow.", "\\meow.", "\\me.ow\\cow.", "\\\\meow.", "\\\\meow\\cow.", - "/meow.txt", "/me.ow/cow.txt", "\\meow.txt", "\\me.ow\\cow.txt", "\\\\meow.txt", "\\\\meow\\cow.txt" - - "/meow", "/meow\\cow", "\\meow", "\\meow/cow", "\\\\meow", "\\\\meow/cow", - "/meow.", "\\me.ow/cow.", "\\meow.", "/me.ow\\cow.", "\\\\meow.", "\\\\meow/cow.", - "/meow.txt", "/me.ow\\cow.txt", "\\meow.txt", "\\me.ow/cow.txt", "\\\\meow.txt", "\\\\meow/cow.txt", - "/bark///dog", "\\bark\\\\\\dog" }; - - for(unsigned i = 0; i < sizeof(test_paths) / sizeof(const char *); i++) - { - std::string file_path = std::string(test_paths[i]); - std::string dir_path; - std::string file_base; - std::string file_ext; - - MDFN_GetFilePathComponents(file_path, &dir_path, &file_base, &file_ext); - - printf("%s ------ dir=%s --- base=%s --- ext=%s\n", file_path.c_str(), dir_path.c_str(), file_base.c_str(), file_ext.c_str()); - - } -#endif - - return(1); -} - diff --git a/psx/octoshock/tests.h b/psx/octoshock/tests.h deleted file mode 100644 index fbf67cf18fe..00000000000 --- a/psx/octoshock/tests.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef __MDFN_TESTS_H -#define __MDFN_TESTS_H - -bool MDFN_RunMathTests(void); -void MDFN_RunExceptionTests(const unsigned thread_count, const unsigned thread_delay); - -#endif - diff --git a/psx/octoshock/video.h b/psx/octoshock/video.h deleted file mode 100644 index ed3f5def39b..00000000000 --- a/psx/octoshock/video.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef __MDFN_VIDEO_H -#define __MDFN_VIDEO_H - -#include "video/surface.h" -//#include "video/primitives.h" -//#include "video/text.h" - -#include - -void MDFN_ResetMessages(void); -void MDFN_InitFontData(void); -void MDFN_DispMessage(const char *format, ...); - -int MDFN_InitVirtualVideo(void); -void MDFN_KillVirtualVideo(void); - - -#endif diff --git a/psx/octoshock/video/Deinterlacer.cpp b/psx/octoshock/video/Deinterlacer.cpp deleted file mode 100644 index 1e608af3ab1..00000000000 --- a/psx/octoshock/video/Deinterlacer.cpp +++ /dev/null @@ -1,211 +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 "octoshock.h" -#include "video.h" - -#include "Deinterlacer.h" - -Deinterlacer::Deinterlacer() : FieldBuffer(NULL), StateValid(false), DeintType(DEINT_WEAVE) -{ - PrevDRect.x = 0; - PrevDRect.y = 0; - - PrevDRect.w = 0; - PrevDRect.h = 0; -} - -Deinterlacer::~Deinterlacer() -{ - if(FieldBuffer) - { - delete FieldBuffer; - FieldBuffer = NULL; - } -} - -void Deinterlacer::SetType(unsigned dt) -{ - if(DeintType != dt) - { - DeintType = dt; - - LWBuffer.resize(0); - if(FieldBuffer) - { - delete FieldBuffer; - FieldBuffer = NULL; - } - StateValid = false; - } -} - -template -void Deinterlacer::InternalProcess(MDFN_Surface *surface, MDFN_Rect &DisplayRect, int32 *LineWidths, const bool field) -{ - // - // We need to output with LineWidths as always being valid to handle the case of horizontal resolution change between fields - // while in interlace mode, so clear the first LineWidths entry if it's == ~0, and - // [...] - const bool LineWidths_In_Valid = (LineWidths[0] != ~0); - const bool WeaveGood = (StateValid && PrevDRect.h == DisplayRect.h && DeintType == DEINT_WEAVE); - // - // XReposition stuff is to prevent exceeding the dimensions of the video surface under certain conditions(weave deinterlacer, previous field has higher - // horizontal resolution than current field, and current field's rectangle has an x offset that's too large when taking into consideration the previous field's - // width; for simplicity, we don't check widths, but just assume that the previous field's maximum width is >= than the current field's maximum width). - // - const int32 XReposition = ((WeaveGood && DisplayRect.x > PrevDRect.x) ? DisplayRect.x : 0); - - //printf("%2d %2d, %d\n", DisplayRect.x, PrevDRect.x, XReposition); - - if(XReposition) - DisplayRect.x = 0; - - if(surface->h && !LineWidths_In_Valid) - { - LineWidths[0] = 0; - } - - for(int y = 0; y < DisplayRect.h / 2; y++) - { - // [...] - // set all relevant source line widths to the contents of DisplayRect(also simplifies the src_lw and related pointer calculation code - // farther below. - if(!LineWidths_In_Valid) - LineWidths[(y * 2) + field + DisplayRect.y] = DisplayRect.w; - - if(XReposition) - { - memmove(surface->pix() + ((y * 2) + field + DisplayRect.y) * surface->pitchinpix, - surface->pix() + ((y * 2) + field + DisplayRect.y) * surface->pitchinpix + XReposition, - LineWidths[(y * 2) + field + DisplayRect.y] * sizeof(T)); - } - - if(WeaveGood) - { - const T* src = FieldBuffer->pix() + y * FieldBuffer->pitchinpix; - T* dest = surface->pix() + ((y * 2) + (field ^ 1) + DisplayRect.y) * surface->pitchinpix + DisplayRect.x; - int32 *dest_lw = &LineWidths[(y * 2) + (field ^ 1) + DisplayRect.y]; - - *dest_lw = LWBuffer[y]; - - memcpy(dest, src, LWBuffer[y] * sizeof(T)); - } - else if(DeintType == DEINT_BOB) - { - const T* src = surface->pix() + ((y * 2) + field + DisplayRect.y) * surface->pitchinpix + DisplayRect.x; - T* dest = surface->pix() + ((y * 2) + (field ^ 1) + DisplayRect.y) * surface->pitchinpix + DisplayRect.x; - const int32 *src_lw = &LineWidths[(y * 2) + field + DisplayRect.y]; - int32 *dest_lw = &LineWidths[(y * 2) + (field ^ 1) + DisplayRect.y]; - - *dest_lw = *src_lw; - - memcpy(dest, src, *src_lw * sizeof(T)); - } - else - { - const int32 *src_lw = &LineWidths[(y * 2) + field + DisplayRect.y]; - const T* src = surface->pix() + ((y * 2) + field + DisplayRect.y) * surface->pitchinpix + DisplayRect.x; - const int32 dly = ((y * 2) + (field + 1) + DisplayRect.y); - T* dest = surface->pix() + dly * surface->pitchinpix + DisplayRect.x; - - if(y == 0 && field) - { - T black = surface->MakeColor(0, 0, 0); - T* dm2 = surface->pix() + (dly - 2) * surface->pitchinpix; - - LineWidths[dly - 2] = *src_lw; - - for(int x = 0; x < *src_lw; x++) - dm2[x] = black; - } - - if(dly < (DisplayRect.y + DisplayRect.h)) - { - LineWidths[dly] = *src_lw; - memcpy(dest, src, *src_lw * sizeof(T)); - } - } - - // - // - // - // - // - // - if(DeintType == DEINT_WEAVE) - { - const int32 *src_lw = &LineWidths[(y * 2) + field + DisplayRect.y]; - const T* src = surface->pix() + ((y * 2) + field + DisplayRect.y) * surface->pitchinpix + DisplayRect.x; - T* dest = FieldBuffer->pix() + y * FieldBuffer->pitchinpix; - - memcpy(dest, src, *src_lw * sizeof(uint32)); - LWBuffer[y] = *src_lw; - - StateValid = true; - } - } -} - -void Deinterlacer::Process(MDFN_Surface *surface, MDFN_Rect &DisplayRect, int32 *LineWidths, const bool field) -{ - const MDFN_Rect DisplayRect_Original = DisplayRect; - - if(DeintType == DEINT_WEAVE) - { - if(!FieldBuffer || FieldBuffer->w < surface->w || FieldBuffer->h < (surface->h / 2)) - { - if(FieldBuffer) - delete FieldBuffer; - - FieldBuffer = new MDFN_Surface(NULL, surface->w, surface->h / 2, surface->w, surface->format); - LWBuffer.resize(FieldBuffer->h); - } - else if(memcmp(&surface->format, &FieldBuffer->format, sizeof(MDFN_PixelFormat))) - { - FieldBuffer->SetFormat(surface->format, StateValid && PrevDRect.h == DisplayRect.h); - } - } - - switch (surface->format.opp) - { - case 1: - InternalProcess(surface, DisplayRect, LineWidths, field); - break; - - case 2: - InternalProcess(surface, DisplayRect, LineWidths, field); - break; - - case 4: - InternalProcess(surface, DisplayRect, LineWidths, field); - break; - } - - PrevDRect = DisplayRect_Original; -} - -void Deinterlacer::ClearState(void) -{ - StateValid = false; - - PrevDRect.x = 0; - PrevDRect.y = 0; - - PrevDRect.w = 0; - PrevDRect.h = 0; -} diff --git a/psx/octoshock/video/Deinterlacer.h b/psx/octoshock/video/Deinterlacer.h deleted file mode 100644 index 7f7c6704c79..00000000000 --- a/psx/octoshock/video/Deinterlacer.h +++ /dev/null @@ -1,59 +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_DEINTERLACER_H -#define __MDFN_DEINTERLACER_H - -#include - -class Deinterlacer -{ - public: - - Deinterlacer(); - ~Deinterlacer(); - - enum - { - DEINT_BOB_OFFSET = 0, // Code will fall-through to this case under certain conditions, too. - DEINT_BOB, - DEINT_WEAVE, - }; - - void SetType(unsigned t); - inline unsigned GetType(void) - { - return(DeintType); - } - - void Process(MDFN_Surface *surface, MDFN_Rect &DisplayRect, int32 *LineWidths, const bool field); - - void ClearState(void); - - private: - - template - void InternalProcess(MDFN_Surface *surface, MDFN_Rect &DisplayRect, int32 *LineWidths, const bool field); - - MDFN_Surface *FieldBuffer; - std::vector LWBuffer; - bool StateValid; - MDFN_Rect PrevDRect; - unsigned DeintType; -}; - -#endif diff --git a/psx/octoshock/video/convert.cpp b/psx/octoshock/video/convert.cpp deleted file mode 100644 index d328f190c70..00000000000 --- a/psx/octoshock/video/convert.cpp +++ /dev/null @@ -1,248 +0,0 @@ -/******************************************************************************/ -/* Mednafen - Multi-system Emulator */ -/******************************************************************************/ -/* convert.cpp - Pixel format conversion -** Copyright (C) 2020 Mednafen Team -** -** 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., -** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "octoshock.h" -#include "surface.h" -#include "convert.h" - -template -static NO_INLINE void Convert_Slow(const void* src, void* dest, uint32 count, const MDFN_PixelFormatConverter::convert_context* ctx) -{ - MDFN_PixelFormat old_pf = ctx->spf; - MDFN_PixelFormat new_pf = ctx->dpf; - - old_pf.opp = sizeof(OT); - new_pf.opp = sizeof(NT); - - old_pf.colorspace = old_colorspace; - new_pf.colorspace = new_colorspace; - // - // - OT* src_row = (OT*)src; - NT* dest_row = src_equals_dest ? (NT*)src_row : (NT*)dest; - - for(unsigned x = 0; MDFN_LIKELY(x < count); x++) - { - if(sizeof(OT) == 1) - dest_row[x] = ctx->palconv[src_row[x]]; - else - { - int r, g, b, a; - - old_pf.DecodeColor(src_row[x], r, g, b, a); - dest_row[x] = new_pf.MakeColor(r, g, b, a); - } - } -} - -template -static NO_INLINE void Convert_Fast(const void* src, void* dest, uint32 count, const MDFN_PixelFormatConverter::convert_context* ctx) -{ - const MDFN_PixelFormat old_pf = MDFN_PixelFormat(old_pftag); - const MDFN_PixelFormat new_pf = MDFN_PixelFormat(new_pftag); - OT* src_row = (OT*)src; - NT* dest_row = src_equals_dest ? (NT*)src_row : (NT*)dest; - - for(unsigned x = 0; MDFN_LIKELY(x < count); x++) - { - uint32 c = src_row[x]; - - if(sizeof(OT) == 1) - dest_row[x] = ctx->palconv[c]; - else if(old_pftag == MDFN_PixelFormat::IRGB16_1555 && new_pftag == MDFN_PixelFormat::RGB16_565) - dest_row[x] = (c & 0x1F) | ((c << 1) & 0xF800) | (MDFN_PixelFormat::LUT8to6[MDFN_PixelFormat::LUT5to8[(c >> 5) & 0x1F]] << 5); - else if(old_pftag == MDFN_PixelFormat::RGB16_565 && new_pftag == MDFN_PixelFormat::IRGB16_1555) - dest_row[x] = (c & 0x1F) | ((c >> 1) & 0x7C00) | (MDFN_PixelFormat::LUT8to5[MDFN_PixelFormat::LUT6to8[(c >> 5) & 0x3F]] << 5); - else - { - int r, g, b, a; - - if(old_pftag == MDFN_PixelFormat::IRGB16_1555) - { - r = MDFN_PixelFormat::LUT5to8[(c >> 10) & 0x1F]; - g = MDFN_PixelFormat::LUT5to8[(c >> 5) & 0x1F]; - b = MDFN_PixelFormat::LUT5to8[(c >> 0) & 0x1F]; - a = 0; - } - else if(old_pftag == MDFN_PixelFormat::RGB16_565) - { - r = MDFN_PixelFormat::LUT5to8[(c >> 11) & 0x1F]; - g = MDFN_PixelFormat::LUT6to8[(c >> 5) & 0x3F]; - b = MDFN_PixelFormat::LUT5to8[(c >> 0) & 0x1F]; - a = 0; - } - else if(old_pftag == MDFN_PixelFormat::ARGB16_4444) - { - a = ((c & 0xF000) >> 8) | ((c & 0xF000) >> 12); - r = ((c & 0xF00) >> 4) | ((c & 0xF00) >> 8); - g = ((c & 0xF0) >> 0) | ((c & 0xF0) >> 4); - b = ((c & 0xF) << 4) | ((c & 0xF) >> 0); - } - else - old_pf.DecodeColor(c, r, g, b, a); - -/* - if(new_pftag == MDFN_PixelFormat::RGB8X3_888 || new_pftag == MDFN_PixelFormat::BGR8X3_888) - { - if(new_pftag == MDFN_PixelFormat::RGB8X3_888) - { - dest_row[x * 3 + 0] = r; - dest_row[x * 3 + 1] = g; - dest_row[x * 3 + 2] = b; - } - else - { - dest_row[x * 3 + 0] = b; - dest_row[x * 3 + 1] = g; - dest_row[x * 3 + 2] = r; - } - } - else -*/ - { - if(new_pftag == MDFN_PixelFormat::IRGB16_1555) - c = (MDFN_PixelFormat::LUT8to5[r] << 10) | (MDFN_PixelFormat::LUT8to5[g] << 5) | (MDFN_PixelFormat::LUT8to5[b] << 0); - else if(new_pftag == MDFN_PixelFormat::RGB16_565) - c = (MDFN_PixelFormat::LUT8to5[r] << 11) | (MDFN_PixelFormat::LUT8to6[g] << 5) | (MDFN_PixelFormat::LUT8to5[b] << 0); - else - c = new_pf.MakeColor(r, g, b, a); - - dest_row[x] = c; - } - } - } -} - -template -static void Convert_xxxx8888(const void* src, void* dest, uint32 count, const MDFN_PixelFormatConverter::convert_context* ctx) -{ - const MDFN_PixelFormat spf = ctx->spf; - const MDFN_PixelFormat dpf = ctx->dpf; - const unsigned tmp = (0 << spf.Rshift) | (1 << spf.Gshift) | (2 << spf.Bshift) | (3 << spf.Ashift); - const unsigned drs[4] = { dpf.Rshift, dpf.Gshift, dpf.Bshift, dpf.Ashift }; - const unsigned sh[4] = { (uint8)drs[(tmp >> 0) & 3], (uint8)drs[(tmp >> 8) & 3], (uint8)drs[(tmp >> 16) & 3], (uint8)drs[(tmp >> 24) & 3] }; - uint32* src_row = (uint32*)src; - uint32* dest_row = src_equals_dest ? src_row : (uint32*)dest; - - for(unsigned x = 0; MDFN_LIKELY(x < count); x++) - { - uint32 c = src_row[x]; - - dest_row[x] = ((uint8)(c >> 0) << sh[0]) | ((uint8)(c >> 8) << sh[1]) | ((uint8)(c >> 16) << sh[2]) | ((uint8)(c >> 24) << sh[3]); - } -} - -template -static MDFN_PixelFormatConverter::convert_func CalcConversionFunction(const MDFN_PixelFormat& spf, const MDFN_PixelFormat& dpf) -{ -#if 1 - switch(spf.tag) - { - #define CROWE(st, sft, dt, dft) case MDFN_PixelFormat::dft: return Convert_Fast; - #define CROW(st, sft) case MDFN_PixelFormat::sft: \ - switch(dpf.tag) \ - { \ - default: break; \ - CROWE(st, sft, uint32, ABGR32_8888) \ - CROWE(st, sft, uint32, ARGB32_8888) \ - CROWE(st, sft, uint32, RGBA32_8888) \ - CROWE(st, sft, uint32, BGRA32_8888) \ - CROWE(st, sft, uint16, IRGB16_1555) \ - CROWE(st, sft, uint16, RGB16_565) \ - CROWE(st, sft, uint16, ARGB16_4444) \ - /*CROWE(st, sft, uint8, RGB8X3_888)*/ \ - /*CROWE(st, sft, uint8, RGB8X3_888)*/ \ - } \ - break; - default: break; - CROW(uint32, ABGR32_8888) - CROW(uint32, ARGB32_8888) - CROW(uint32, RGBA32_8888) - CROW(uint32, BGRA32_8888) - CROW(uint16, IRGB16_1555) - CROW(uint16, RGB16_565) - CROW(uint16, ARGB16_4444) - // - //CROW(uint8, RGB8P_888) - //CROW(uint8, RGB8P_666) - #undef CROWE - #undef CROW - } -#endif - -#if 1 - if(spf.opp == dpf.opp && spf.colorspace == dpf.colorspace) - { - if(spf.opp == 4 && !((spf.Rshift | spf.Gshift | spf.Bshift | spf.Ashift | dpf.Rshift | dpf.Gshift | dpf.Bshift | dpf.Ashift) & 7)) - { - return Convert_xxxx8888; - } - } -#endif - - // - // Slow fallback: - // - #define CROWE(scs, stype, dcs, dtype) case (dcs << 4) | sizeof(dtype): return Convert_Slow; break; - #define CROW(scs, stype) \ - case (scs << 4) | sizeof(stype): \ - switch((dpf.colorspace << 4) | dpf.opp) \ - { \ - CROWE(scs, stype, MDFN_COLORSPACE_RGB, uint8) \ - CROWE(scs, stype, MDFN_COLORSPACE_RGB, uint16) \ - CROWE(scs, stype, MDFN_COLORSPACE_RGB, uint32) \ - } \ - break; - switch((spf.colorspace << 4) | spf.opp) - { - CROW(MDFN_COLORSPACE_RGB, uint8) - CROW(MDFN_COLORSPACE_RGB, uint16) - CROW(MDFN_COLORSPACE_RGB, uint32) - } - #undef CROWE - #undef CROW - - return nullptr; -} - - -MDFN_PixelFormatConverter::MDFN_PixelFormatConverter(const MDFN_PixelFormat& src_pf, const MDFN_PixelFormat& dest_pf, const MDFN_PaletteEntry* palette) -{ - ctx.spf = src_pf; - ctx.dpf = dest_pf; - - if(palette) - { - ctx.palconv.reset(new uint32[256]); - - for(unsigned i = 0; i < 256; i++) - { - uint8 r, g, b; - - ctx.spf.DecodePColor(palette[i], r, g, b); - ctx.palconv[i] = ctx.dpf.MakeColor(r, g, b, 0); - } - } - - convert1 = CalcConversionFunction(ctx.spf, ctx.dpf); - convert2 = CalcConversionFunction(ctx.spf, ctx.dpf); -} - diff --git a/psx/octoshock/video/convert.h b/psx/octoshock/video/convert.h deleted file mode 100644 index 1cc3e5a6208..00000000000 --- a/psx/octoshock/video/convert.h +++ /dev/null @@ -1,59 +0,0 @@ -/******************************************************************************/ -/* Mednafen - Multi-system Emulator */ -/******************************************************************************/ -/* convert.h - Pixel format conversion -** Copyright (C) 2020 Mednafen Team -** -** 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., -** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef __MDFN_VIDEO_CONVERT_H -#define __MDFN_VIDEO_CONVERT_H - -#include -#include "octoshock.h" -#include "surface.h" - - class MDFN_PixelFormatConverter - { - public: - MDFN_PixelFormatConverter(const MDFN_PixelFormat& src_pf, const MDFN_PixelFormat& dest_pf, const MDFN_PaletteEntry* palette = nullptr); - - INLINE void Convert(void* dest, uint32 count) - { - convert1(dest, dest, count, &ctx); - } - - INLINE void Convert(const void* src, void* dest, uint32 count) - { - convert2(src, dest, count, &ctx); - } - - struct convert_context - { - MDFN_PixelFormat spf; - MDFN_PixelFormat dpf; - std::unique_ptr palconv; - }; - - typedef void (*convert_func)(const void*, void*, uint32, const convert_context*); - private: - - convert_func convert1; - convert_func convert2; - convert_context ctx; - }; - -#endif diff --git a/psx/octoshock/video/surface.cpp b/psx/octoshock/video/surface.cpp deleted file mode 100644 index df81173ccc1..00000000000 --- a/psx/octoshock/video/surface.cpp +++ /dev/null @@ -1,324 +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 -#include -#include -#include -#include -#include "octoshock.h" -#include "surface.h" -#include "convert.h" - -MDFN_Surface::MDFN_Surface() -{ - memset(&format, 0, sizeof(format)); - - pixels = NULL; - pixels8 = NULL; - pixels16 = NULL; - palette = NULL; - pixels_is_external = false; - pitchinpix = 0; - w = 0; - h = 0; -} - -MDFN_Surface::MDFN_Surface(void *const p_pixels, const uint32 p_width, const uint32 p_height, const uint32 p_pitchinpix, const MDFN_PixelFormat &nf, const bool alloc_init_pixels) -{ - Init(p_pixels, p_width, p_height, p_pitchinpix, nf, alloc_init_pixels); -} - -#if 0 -void MDFN_Surface::Resize(const uint32 p_width, const uint32 p_height, const uint32 p_pitchinpix) -{ - void *ptr = (format.bpp == 16) ? pixels16 : pixels; - uint64 old_asize = ((uint64)pitchinpix * (format.bpp >> 3)) * h; - uint64 new_asize = ((uint64)p_pitchinpix * (format.bpp >> 3)) * p_height; - - if(!(ptr = realloc(ptr, new_asize))) - throw MDFN_Error(ErrnoHolder(errno)); - - if(new_asize > old_asize) - memset((uint8*)ptr + old_asize, 0x00, new_asize - old_asize); - - if(format.bpp == 16) - pixels16 = (uint16*)ptr; - else - pixels = (uint32*)ptr; - - pitchinpix = p_pitchinpix; - w = p_width; - h = p_height; -} -#endif - -void MDFN_Surface::Init(void *const p_pixels, const uint32 p_width, const uint32 p_height, const uint32 p_pitchinpix, const MDFN_PixelFormat &nf, const bool alloc_init_pixels) -{ - void *rpix = NULL; - assert(nf.opp == 1 || nf.opp == 2 || nf.opp == 4); - - format = nf; - - if(nf.opp == 1) - { - //assert(!nf.Rshift && !nf.Gshift && !nf.Bshift && !nf.Ashift); - //assert(!nf.Rprec && !nf.Gprec && !nf.Bprec && !nf.Aprec); - } - else if(nf.opp == 2) - { - assert(nf.Rprec && nf.Gprec && nf.Bprec && nf.Aprec); - } - else - { - assert((nf.Rshift + nf.Gshift + nf.Bshift + nf.Ashift) == 48); - assert(!((nf.Rshift | nf.Gshift | nf.Bshift | nf.Ashift) & 0x7)); - - format.Rprec = 8; - format.Gprec = 8; - format.Bprec = 8; - format.Aprec = 8; - } - - pixels16 = NULL; - pixels8 = NULL; - pixels = NULL; - palette = NULL; - - pixels_is_external = false; - - if(p_pixels) - { - rpix = p_pixels; - pixels_is_external = true; - } - else - { - if(alloc_init_pixels) - rpix = calloc(1, p_pitchinpix * p_height * nf.opp); - else - rpix = malloc(p_pitchinpix * p_height * nf.opp); - - if(!rpix) - { - //ErrnoHolder ene(errno); - - throw "OLD ERROR"; - //throw(MDFN_Error(ene.Errno(), "%s", ene.StrError())); - } - } - - if(nf.opp == 1) - { - if(!(palette = (MDFN_PaletteEntry*) calloc(sizeof(MDFN_PaletteEntry), 256))) - { - //ErrnoHolder ene(errno); - - if(!pixels_is_external) - free(rpix); - - throw "OLD ERROR"; - //throw(MDFN_Error(ene.Errno(), "%s", ene.StrError())); - } - } - - if(nf.opp == 2) - pixels16 = (uint16 *)rpix; - else if(nf.opp == 1) - pixels8 = (uint8 *)rpix; - else - pixels = (uint32 *)rpix; - - w = p_width; - h = p_height; - - pitchinpix = p_pitchinpix; -} - -const uint8 MDFN_PixelFormat::LUT5to8[32] = -{ - 0x00, 0x08, 0x10, 0x18, 0x20, 0x29, 0x31, 0x39, 0x41, 0x4a, 0x52, 0x5a, 0x62, 0x6a, 0x73, 0x7b, - 0x83, 0x8b, 0x94, 0x9c, 0xa4, 0xac, 0xb4, 0xbd, 0xc5, 0xcd, 0xd5, 0xde, 0xe6, 0xee, 0xf6, 0xff -}; - -const uint8 MDFN_PixelFormat::LUT6to8[64] = -{ - 0x00, 0x04, 0x08, 0x0c, 0x10, 0x14, 0x18, 0x1c, 0x20, 0x24, 0x28, 0x2c, 0x30, 0x34, 0x38, 0x3c, - 0x40, 0x44, 0x48, 0x4c, 0x50, 0x55, 0x59, 0x5d, 0x61, 0x65, 0x69, 0x6d, 0x71, 0x75, 0x79, 0x7d, - 0x81, 0x85, 0x89, 0x8d, 0x91, 0x95, 0x99, 0x9d, 0xa1, 0xa5, 0xaa, 0xae, 0xb2, 0xb6, 0xba, 0xbe, - 0xc2, 0xc6, 0xca, 0xce, 0xd2, 0xd6, 0xda, 0xde, 0xe2, 0xe6, 0xea, 0xee, 0xf2, 0xf6, 0xfa, 0xff -}; - -const uint8 MDFN_PixelFormat::LUT8to5[256] = -{ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, - 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, - 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x08, 0x08, - 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x0a, - 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0c, - 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, - 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, - 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, - 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, - 0x13, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, - 0x15, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, - 0x17, 0x17, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, - 0x19, 0x19, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, - 0x1b, 0x1b, 0x1b, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, - 0x1d, 0x1d, 0x1d, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f -}; - -const uint8 MDFN_PixelFormat::LUT8to6[256] = -{ - 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x04, - 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07, 0x07, 0x08, - 0x08, 0x08, 0x08, 0x09, 0x09, 0x09, 0x09, 0x0a, 0x0a, 0x0a, 0x0a, 0x0b, 0x0b, 0x0b, 0x0b, 0x0c, - 0x0c, 0x0c, 0x0c, 0x0d, 0x0d, 0x0d, 0x0d, 0x0e, 0x0e, 0x0e, 0x0e, 0x0f, 0x0f, 0x0f, 0x0f, 0x10, - 0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11, 0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13, 0x14, - 0x14, 0x14, 0x14, 0x15, 0x15, 0x15, 0x15, 0x15, 0x16, 0x16, 0x16, 0x16, 0x17, 0x17, 0x17, 0x17, - 0x18, 0x18, 0x18, 0x18, 0x19, 0x19, 0x19, 0x19, 0x1a, 0x1a, 0x1a, 0x1a, 0x1b, 0x1b, 0x1b, 0x1b, - 0x1c, 0x1c, 0x1c, 0x1c, 0x1d, 0x1d, 0x1d, 0x1d, 0x1e, 0x1e, 0x1e, 0x1e, 0x1f, 0x1f, 0x1f, 0x1f, - 0x20, 0x20, 0x20, 0x20, 0x21, 0x21, 0x21, 0x21, 0x22, 0x22, 0x22, 0x22, 0x23, 0x23, 0x23, 0x23, - 0x24, 0x24, 0x24, 0x24, 0x25, 0x25, 0x25, 0x25, 0x26, 0x26, 0x26, 0x26, 0x27, 0x27, 0x27, 0x27, - 0x28, 0x28, 0x28, 0x28, 0x29, 0x29, 0x29, 0x29, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2b, 0x2b, 0x2b, - 0x2b, 0x2c, 0x2c, 0x2c, 0x2c, 0x2d, 0x2d, 0x2d, 0x2d, 0x2e, 0x2e, 0x2e, 0x2e, 0x2f, 0x2f, 0x2f, - 0x2f, 0x30, 0x30, 0x30, 0x30, 0x31, 0x31, 0x31, 0x31, 0x32, 0x32, 0x32, 0x32, 0x33, 0x33, 0x33, - 0x33, 0x34, 0x34, 0x34, 0x34, 0x35, 0x35, 0x35, 0x35, 0x36, 0x36, 0x36, 0x36, 0x37, 0x37, 0x37, - 0x37, 0x38, 0x38, 0x38, 0x38, 0x39, 0x39, 0x39, 0x39, 0x3a, 0x3a, 0x3a, 0x3a, 0x3b, 0x3b, 0x3b, - 0x3b, 0x3c, 0x3c, 0x3c, 0x3c, 0x3d, 0x3d, 0x3d, 0x3d, 0x3e, 0x3e, 0x3e, 0x3e, 0x3f, 0x3f, 0x3f -}; - -// When we're converting, only convert the w*h area(AKA leave the last part of the line, pitch32 - w, alone), -// for places where we store auxillary information there(graphics viewer in the debugger), and it'll be faster -// to boot. -void MDFN_Surface::SetFormat(const MDFN_PixelFormat &nf, bool convert) -{ - if(format == nf) - return; - // - void* old_pixels = nullptr; - void* new_pixels = nullptr; - void* new_palette = nullptr; - - switch(format.opp) - { - case 1: old_pixels = pix(); break; - case 2: old_pixels = pix(); break; - case 4: old_pixels = pix(); break; - } - - if(nf.opp != format.opp) - { - new_pixels = calloc(1, pitchinpix * h * nf.opp); - - if(nf.opp == 1) - new_palette = calloc(sizeof(MDFN_PaletteEntry), 256); - } - // - // - if(convert) - { - MDFN_PixelFormatConverter fconv(format, nf, (MDFN_PaletteEntry*)(palette ? palette : new_palette)); - size_t old_pitchinbytes = pitchinpix * format.opp; - size_t new_pitchinbytes = pitchinpix * nf.opp; - - if(new_pixels) - { - for(int32 y = 0; y < h; y++) - fconv.Convert((uint8*)old_pixels + y * old_pitchinbytes, (uint8*)new_pixels + y * new_pitchinbytes, w); - } - else - { - for(int32 y = 0; y < h; y++) - fconv.Convert((uint8*)old_pixels + y * old_pitchinbytes, w); - } - } - // - // - if(nf.opp != format.opp) - { - switch(format.opp) - { - case 1: pixels8 = nullptr; break; - case 2: pixels16 = nullptr; break; - case 4: pixels = nullptr; break; - } - - if(palette) - { - free(palette); - palette = nullptr; - } - - if(!pixels_is_external) - free(old_pixels); - - pixels_is_external = false; - - switch(nf.opp) - { - case 1: pixels8 = (uint8*)new_pixels; palette = (MDFN_PaletteEntry*)new_palette; break; - case 2: pixels16 = (uint16*)new_pixels; break; - case 4: pixels = (uint32*)new_pixels; break; - } - } - - format = nf; -} - -void MDFN_Surface::Fill(uint8 r, uint8 g, uint8 b, uint8 a) -{ - uint32 color = MakeColor(r, g, b, a); - - if(format.opp == 1) - { - assert(pixels8); - - for(int32 i = 0; i < pitchinpix * h; i++) - pixels8[i] = color; - } - else if(format.opp == 2) - { - assert(pixels16); - - for(int32 i = 0; i < pitchinpix * h; i++) - pixels16[i] = color; - } - else - { - assert(pixels); - - for(int32 i = 0; i < pitchinpix * h; i++) - pixels[i] = color; - } -} - -MDFN_Surface::~MDFN_Surface() -{ - if(!pixels_is_external) - { - if(pixels) - free(pixels); - if(pixels16) - free(pixels16); - if(pixels8) - free(pixels8); - if(palette) - free(palette); - } -} diff --git a/psx/octoshock/video/surface.h b/psx/octoshock/video/surface.h deleted file mode 100644 index 2df104aff4d..00000000000 --- a/psx/octoshock/video/surface.h +++ /dev/null @@ -1,335 +0,0 @@ -#ifndef __MDFN_SURFACE_H -#define __MDFN_SURFACE_H - -struct MDFN_Rect -{ - int32 x, y, w, h; -}; - -enum -{ - MDFN_COLORSPACE_RGB = 0, - //MDFN_COLORSPACE_LRGB = 1, // Linear RGB, 16-bit per component, TODO in the future? - //MDFN_COLORSPACE_YUV = 2, // TODO, maybe. -}; - -struct MDFN_PaletteEntry -{ - uint8 r, g, b; -}; - -/* -template -static constexpr INLINE uint64 MDFN_PixelFormat_SetTagT(const uint64 tag) -{ - return (tag & ~0xFF) | (sizeof(T) * 8); -} -*/ - -static constexpr INLINE uint64 MDFN_PixelFormat_MakeTag(const uint8 colorspace, - const uint8 opp, - const uint8 rs, const uint8 gs, const uint8 bs, const uint8 as, - const uint8 rp, const uint8 gp, const uint8 bp, const uint8 ap) -{ - // (8 * 6) = 48 - return ((uint64)colorspace << 56) | ((uint64)opp << 48) | - ((uint64)rs << (0 * 6)) | ((uint64)gs << (1 * 6)) | ((uint64)bs << (2 * 6)) | ((uint64)as << (3 * 6)) | - ((uint64)rp << (4 * 6)) | ((uint64)gp << (5 * 6)) | ((uint64)bp << (6 * 6)) | ((uint64)ap << (7 * 6)); -} - -class MDFN_PixelFormat -{ - public: - - // - // MDFN_PixelFormat constructors must remain inline for various code to be optimized - // properly by the compiler. - // - INLINE MDFN_PixelFormat(const uint64 tag_) : - tag(tag_), - colorspace((uint8)(tag_ >> 56)), - opp((uint8)(tag_ >> 48)), - Rshift((tag_ >> (0 * 6)) & 0x3F), - Gshift((tag_ >> (1 * 6)) & 0x3F), - Bshift((tag_ >> (2 * 6)) & 0x3F), - Ashift((tag_ >> (3 * 6)) & 0x3F), - Rprec((tag_ >> (4 * 6)) & 0x3F), - Gprec((tag_ >> (5 * 6)) & 0x3F), - Bprec((tag_ >> (6 * 6)) & 0x3F), - Aprec((tag_ >> (7 * 6)) & 0x3F) - { - // - } - - INLINE MDFN_PixelFormat() : - tag(0), - colorspace(0), - opp(0), - Rshift(0), Gshift(0), Bshift(0), Ashift(0), - Rprec(0), Gprec(0), Bprec(0), Aprec(0) - { - // - } - - INLINE MDFN_PixelFormat(const unsigned int colorspace_, - const uint8 opp_, - const uint8 rs, const uint8 gs, const uint8 bs, const uint8 as, - const uint8 rp = 8, const uint8 gp = 8, const uint8 bp = 8, const uint8 ap = 8) : - tag(MDFN_PixelFormat_MakeTag(colorspace_, opp_, rs, gs, bs, as, rp, gp, bp, ap)), - colorspace(colorspace_), - opp(opp_), - Rshift(rs), Gshift(gs), Bshift(bs), Ashift(as), - Rprec(rp), Gprec(gp), Bprec(bp), Aprec(ap) - { - // - } - - //constexpr MDFN_PixelFormat(MDFN_PixelFormat&) = default; - //constexpr MDFN_PixelFormat(MDFN_PixelFormat&&) = default; - //MDFN_PixelFormat& operator=(MDFN_PixelFormat&) = default; - - bool operator==(const uint64& t) - { - return tag == t; - } - - bool operator==(const MDFN_PixelFormat& a) - { - return tag == a.tag; - } - - bool operator!=(const MDFN_PixelFormat& a) - { - return !(*this == a); - } - - uint64 tag; - - uint8 colorspace; - uint8 opp; // Bytes per pixel; 1, 2, 4 (1 is WIP) - - uint8 Rshift; // Bit position of the lowest bit of the red component - uint8 Gshift; // [...] green component - uint8 Bshift; // [...] blue component - uint8 Ashift; // [...] alpha component. - - // For 16bpp, WIP - uint8 Rprec; - uint8 Gprec; - uint8 Bprec; - uint8 Aprec; - - // Creates a color value for the surface corresponding to the 8-bit R/G/B/A color passed. - INLINE uint32 MakeColor(uint8 r, uint8 g, uint8 b, uint8 a = 0) const - { - if(opp == 2) - { - uint32 ret; - - ret = ((r * ((1 << Rprec) - 1) + 127) / 255) << Rshift; - ret |= ((g * ((1 << Gprec) - 1) + 127) / 255) << Gshift; - ret |= ((b * ((1 << Bprec) - 1) + 127) / 255) << Bshift; - ret |= ((a * ((1 << Aprec) - 1) + 127) / 255) << Ashift; - - return ret; - } - else - return (r << Rshift) | (g << Gshift) | (b << Bshift) | (a << Ashift); - } - - INLINE MDFN_PaletteEntry MakePColor(uint8 r, uint8 g, uint8 b) const - { - MDFN_PaletteEntry ret; - - ret.r = ((r * ((1 << Rprec) - 1) + 127) / 255) << Rshift; - ret.g = ((g * ((1 << Gprec) - 1) + 127) / 255) << Gshift; - ret.b = ((b * ((1 << Bprec) - 1) + 127) / 255) << Bshift; - - return ret; - } - - INLINE void DecodePColor(const MDFN_PaletteEntry& pe, uint8 &r, uint8 &g, uint8 &b) const - { - r = ((pe.r >> Rshift) & ((1 << Rprec) - 1)) * 255 / ((1 << Rprec) - 1); - g = ((pe.g >> Gshift) & ((1 << Gprec) - 1)) * 255 / ((1 << Gprec) - 1); - b = ((pe.b >> Bshift) & ((1 << Bprec) - 1)) * 255 / ((1 << Bprec) - 1); - } - - // Gets the R/G/B/A values for the passed 32-bit surface pixel value - INLINE void DecodeColor(uint32 value, int &r, int &g, int &b, int &a) const - { - if(opp == 2) - { - r = ((value >> Rshift) & ((1 << Rprec) - 1)) * 255 / ((1 << Rprec) - 1); - g = ((value >> Gshift) & ((1 << Gprec) - 1)) * 255 / ((1 << Gprec) - 1); - b = ((value >> Bshift) & ((1 << Bprec) - 1)) * 255 / ((1 << Bprec) - 1); - a = ((value >> Ashift) & ((1 << Aprec) - 1)) * 255 / ((1 << Aprec) - 1); - } - else - { - r = (value >> Rshift) & 0xFF; - g = (value >> Gshift) & 0xFF; - b = (value >> Bshift) & 0xFF; - a = (value >> Ashift) & 0xFF; - } - } - - MDFN_HIDE static const uint8 LUT5to8[32]; - MDFN_HIDE static const uint8 LUT6to8[64]; - MDFN_HIDE static const uint8 LUT8to5[256]; - MDFN_HIDE static const uint8 LUT8to6[256]; - - INLINE void DecodeColor(uint32 value, int &r, int &g, int &b) const - { - int dummy_a; - - DecodeColor(value, r, g, b, dummy_a); - } - - static INLINE void TDecodeColor(uint64 tag, uint32 c, int* r, int* g, int* b) - { - if(tag == IRGB16_1555) - { - *r = LUT5to8[(c >> 10) & 0x1F]; - *g = LUT5to8[(c >> 5) & 0x1F]; - *b = LUT5to8[(c >> 0) & 0x1F]; - //*a = 0; - } - else if(tag == RGB16_565) - { - *r = LUT5to8[(c >> 11) & 0x1F]; - *g = LUT6to8[(c >> 5) & 0x3F]; - *b = LUT5to8[(c >> 0) & 0x1F]; - //*a = 0; - } - else - { - MDFN_PixelFormat pf = tag; - - pf.DecodeColor(c, *r, *g, *b); - } - } - - static INLINE uint32 TMakeColor(uint64 tag, uint8 r, uint8 g, uint8 b) - { - if(tag == IRGB16_1555) - return (LUT8to5[r] << 10) | (LUT8to5[g] << 5) | (LUT8to5[b] << 0); - else if(tag == RGB16_565) - return (LUT8to5[r] << 11) | (LUT8to6[g] << 5) | (LUT8to5[b] << 0); - else - { - MDFN_PixelFormat pf = tag; - - return pf.MakeColor(r, g, b); - } - } - - enum : uint64 - { - // - // All 24 possible RGB-colorspace xxxx32_8888 formats are supported by core Mednafen and emulation modules, - // but the ones not enumerated here will be less performant. - // - // In regards to emulation modules' video output, the alpha channel is for internal use, - // and should be ignored by driver-side/frontend code. - // - ABGR32_8888 = MDFN_PixelFormat_MakeTag(MDFN_COLORSPACE_RGB, 4, /**/ 0, 8, 16, 24, /**/ 8, 8, 8, 8), - ARGB32_8888 = MDFN_PixelFormat_MakeTag(MDFN_COLORSPACE_RGB, 4, /**/ 16, 8, 0, 24, /**/ 8, 8, 8, 8), - RGBA32_8888 = MDFN_PixelFormat_MakeTag(MDFN_COLORSPACE_RGB, 4, /**/ 24, 16, 8, 0, /**/ 8, 8, 8, 8), - BGRA32_8888 = MDFN_PixelFormat_MakeTag(MDFN_COLORSPACE_RGB, 4, /**/ 8, 16, 24, 0, /**/ 8, 8, 8, 8), - // - // These two RGB16 formats are the only 16-bit formats fully supported by core Mednafen code, - // and most emulation modules(also see MDFNGI::ExtraVideoFormatSupport) - // - // Alpha shift/precision weirdness for internal emulation module use. - // - IRGB16_1555 = MDFN_PixelFormat_MakeTag(MDFN_COLORSPACE_RGB, 2, /**/ 10, 5, 0, 16, /**/ 5, 5, 5, 8), - RGB16_565 = MDFN_PixelFormat_MakeTag(MDFN_COLORSPACE_RGB, 2, /**/ 11, 5, 0, 16, /**/ 5, 6, 5, 8), - // - // Following formats are not supported by emulation modules, and only partially supported by core - // Mednafen code: - // - ARGB16_4444 = MDFN_PixelFormat_MakeTag(MDFN_COLORSPACE_RGB, 2, /**/ 8, 4, 0, 12, /**/ 4, 4, 4, 4), - - // - // TODO: Following two hackyish formats are only valid when used as a destination pixel format with - // MDFN_PixelFormatConverter - // - // RGB8X3_888 = MDFN_PixelFormat_MakeTag(MDFN_COLORSPACE_RGB, 3, /**/ 0, 1, 2, 0, /**/ 8, 8, 8, 0), - // BGR8X3_888 = MDFN_PixelFormat_MakeTag(MDFN_COLORSPACE_RGB, 3, /**/ 2, 1, 0, 0, /**/ 8, 8, 8, 0), - // - // TODO: - //RGB8P_888 = MDFN_PixelFormat_MakeTag(MDFN_COLORSPACE_RGB, 1, /**/ 0, 0, 0, 8, /**/ 8, 8, 8, 0), - //RGB8P_666 = MDFN_PixelFormat_MakeTag(MDFN_COLORSPACE_RGB, 1, /**/ 0, 0, 0, 8, /**/ 6, 6, 6, 0), - }; -}; // MDFN_PixelFormat; - -// 8bpp support is incomplete -class MDFN_Surface -{ - public: - - MDFN_Surface(); - MDFN_Surface(void *const p_pixels, const uint32 p_width, const uint32 p_height, const uint32 p_pitchinpix, const MDFN_PixelFormat &nf, const bool alloc_init_pixels = true); - - ~MDFN_Surface(); - - uint8 *pixels8; - uint16 *pixels16; - uint32 *pixels; - - template - T* pix(void) - { - if(sizeof(T) == 1) - return (T*)pixels8; - else if(sizeof(T) == 2) - return (T*)pixels16; - else if(sizeof(T) == 4) - return (T*)pixels; - else - return NULL; - } - - MDFN_PaletteEntry *palette; - - bool pixels_is_external; - - // w, h, and pitch32 should always be > 0 - int32 w; - int32 h; - - union - { - int32 pitch32; // In pixels, not in bytes. - int32 pitchinpix; // New name, new code should use this. - }; - - MDFN_PixelFormat format; - - void Fill(uint8 r, uint8 g, uint8 b, uint8 a); - void SetFormat(const MDFN_PixelFormat &new_format, bool convert); - - // Creates a 32-bit value for the surface corresponding to the R/G/B/A color passed. - INLINE uint32 MakeColor(uint8 r, uint8 g, uint8 b, uint8 a = 0) const - { - return(format.MakeColor(r, g, b, a)); - } - - // Gets the R/G/B/A values for the passed 32-bit surface pixel value - INLINE void DecodeColor(uint32 value, int &r, int &g, int &b, int &a) const - { - format.DecodeColor(value, r, g, b, a); - } - - INLINE void DecodeColor(uint32 value, int &r, int &g, int &b) const - { - int dummy_a; - - DecodeColor(value, r, g, b, dummy_a); - } - private: - void Init(void *const p_pixels, const uint32 p_width, const uint32 p_height, const uint32 p_pitchinpix, const MDFN_PixelFormat &nf, const bool alloc_init_pixels); -}; - -#endif diff --git a/psx/octoshock/video/video-common.h b/psx/octoshock/video/video-common.h deleted file mode 100644 index dd5b4344f37..00000000000 --- a/psx/octoshock/video/video-common.h +++ /dev/null @@ -1,5 +0,0 @@ -#include "../mednafen.h" -#include "../video.h" -#include "../general.h" -#include "../driver.h" -