/* * /home/ms/files/source/libsidtune/RCS/SidTune.h,v * * 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 SIDTUNE_H #define SIDTUNE_H #include "sidtypes.h" #include "Buffer.h" #include "SmartPtr.h" //#include const uint_least16_t SIDTUNE_MAX_SONGS = 256; // Also PSID file format limit. const uint_least16_t SIDTUNE_MAX_CREDIT_STRINGS = 10; const uint_least16_t SIDTUNE_MAX_CREDIT_STRLEN = 80+1; // 80 characters plus terminating zero. const uint_least32_t SIDTUNE_MAX_MEMORY = 65536; const uint_least32_t SIDTUNE_MAX_FILELEN = 65536+2+0x7C; // C64KB+LOAD+PSID const int SIDTUNE_SPEED_VBI = 0; // Vertical-Blanking-Interrupt const int SIDTUNE_SPEED_CIA_1A = 60; // CIA 1 Timer A const int SIDTUNE_CLOCK_UNKNOWN = 0x00; const int SIDTUNE_CLOCK_PAL = 0x01; // These are also used in the const int SIDTUNE_CLOCK_NTSC = 0x02; // emulator engine! const int SIDTUNE_CLOCK_ANY = (SIDTUNE_CLOCK_PAL | SIDTUNE_CLOCK_NTSC); const int SIDTUNE_SIDMODEL_UNKNOWN = 0x00; const int SIDTUNE_SIDMODEL_6581 = 0x01; // These are also used in the const int SIDTUNE_SIDMODEL_8580 = 0x02; // emulator engine! const int SIDTUNE_SIDMODEL_ANY = (SIDTUNE_SIDMODEL_6581 | SIDTUNE_SIDMODEL_8580); const int SIDTUNE_COMPATIBILITY_C64 = 0x00; // File is C64 compatible const int SIDTUNE_COMPATIBILITY_PSID = 0x01; // File is PSID specific const int SIDTUNE_COMPATIBILITY_R64 = 0x02; // File is Real C64 only // Required to export template #ifndef _SidTune_cpp_ extern #endif template class SID_EXTERN Buffer_sidtt; struct SidTuneInfo { // An instance of this structure is used to transport values to // and from SidTune objects. // You must read (i.e. activate) sub-song specific information // via: // const SidTuneInfo& tuneInfo = SidTune[songNumber]; // const SidTuneInfo& tuneInfo = SidTune.getInfo(); // void SidTune.getInfo(tuneInfo&); // Consider the following fields as read-only, because the SidTune class // does not provide an implementation of: bool setInfo(const SidTuneInfo&). // Currently, the only way to get the class to accept values which // are written to these fields is by creating a derived class. const char* formatString; // the name of the identified file format const char* statusString; // error/status message of last operation const char* speedString; // describing the speed a song is running at uint_least16_t loadAddr; uint_least16_t initAddr; uint_least16_t playAddr; uint_least16_t songs; uint_least16_t startSong; // The SID chip base address(es) used by the sidtune. uint_least16_t sidChipBase1; // 0xD400 (normal, 1st SID) uint_least16_t sidChipBase2; // 0xD?00 (2nd SID) or 0 (no 2nd SID) // Available after song initialization. // uint_least16_t irqAddr; // if (playAddr == 0), interrupt handler has been // installed and starts calling the C64 player // at this address uint_least16_t currentSong; // the one that has been initialized uint_least8_t songSpeed; // intended speed, see top uint_least8_t clockSpeed; // -"- uint_least8_t relocStartPage; // First available page for relocation uint_least8_t relocPages; // Number of pages available for relocation bool musPlayer; // whether Sidplayer routine has been installed int sidModel; // Sid Model required for this sid int compatibility; // compatibility requirements bool fixLoad; // whether load address might be duplicate uint_least16_t songLength; // --- not yet supported --- // // Song title, credits, ... // 0 = Title, 1 = Author, 2 = Copyright/Publisher // uint_least8_t numberOfInfoStrings; // the number of available text info lines char* infoString[SIDTUNE_MAX_CREDIT_STRINGS]; // uint_least16_t numberOfCommentStrings; // --- not yet supported --- char ** commentString; // --- not yet supported --- // uint_least32_t dataFileLen; // length of single-file sidtune file uint_least32_t c64dataLen; // length of raw C64 data without load address char* path; // path to sidtune files; "", if cwd char* dataFileName; // a first file: e.g. "foo.c64"; "", if none char* infoFileName; // a second file: e.g. "foo.sid"; "", if none // }; class SID_EXTERN SidTune { public: // ---------------------------------------------------------------- // If your opendir() and readdir()->d_name return path names // that contain the forward slash (/) as file separator, but // your operating system uses a different character, there are // extra functions that can deal with this special case. Set // separatorIsSlash to true if you like path names to be split // correctly. // You do not need these extra functions if your systems file // separator is the forward slash. // // Load a sidtune from a file. // // To retrieve data from standard input pass in filename "-". // If you want to override the default filename extensions use this // contructor. Please note, that if the specified ``sidTuneFileName'' // does exist and the loader is able to determine its file format, // this function does not try to append any file name extension. // See ``sidtune.cpp'' for the default list of file name extensions. // You can specific ``sidTuneFileName = 0'', if you do not want to // load a sidtune. You can later load one with open(). SidTune(const char* fileName, const char **fileNameExt = 0, const bool separatorIsSlash = false); // Load a single-file sidtune from a memory buffer. // Currently supported: PSID format SidTune(const uint_least8_t* oneFileFormatSidtune, const uint_least32_t sidtuneLength); virtual ~SidTune(); // The sidTune class does not copy the list of file name extensions, // so make sure you keep it. If the provided pointer is 0, the // default list will be activated. This is a static list which // is used by all SidTune objects. void setFileNameExtensions(const char **fileNameExt); // Load a sidtune into an existing object. // From a file. bool load(const char* fileName, const bool separatorIsSlash = false); // From a buffer. bool read(const uint_least8_t* sourceBuffer, const uint_least32_t bufferLen); // Select sub-song (0 = default starting song) // and retrieve active song information. const SidTuneInfo& operator[](const uint_least16_t songNum); // Select sub-song (0 = default starting song) // and return active song number out of [1,2,..,SIDTUNE_MAX_SONGS]. uint_least16_t selectSong(const uint_least16_t songNum); // Retrieve sub-song specific information. // Beware! Still member-wise copy! const SidTuneInfo& getInfo(); // Get a copy of sub-song specific information. // Beware! Still member-wise copy! void getInfo(SidTuneInfo&); // Determine current state of object (true = okay, false = error). // Upon error condition use ``getInfo'' to get a descriptive // text string in ``SidTuneInfo.statusString''. operator bool() { return status; } bool getStatus() { return status; } // Whether sidtune uses two SID chips. bool isStereo() { return (info.sidChipBase1!=0 && info.sidChipBase2!=0); } // Copy sidtune into C64 memory (64 KB). bool placeSidTuneInC64mem(uint_least8_t* c64buf); // --- file save & format conversion --- // These functions work for any successfully created object. // overWriteFlag: true = Overwrite existing file. // false = Default, return error when file already // exists. // One could imagine an "Are you sure ?"-checkbox before overwriting // any file. // returns: true = Successful, false = Error condition. bool saveC64dataFile( const char* destFileName, const bool overWriteFlag = false ); bool saveSIDfile( const char* destFileName, const bool overWriteFlag = false ); bool savePSIDfile( const char* destFileName, const bool overWriteFlag = false ); // This function can be used to remove a duplicate C64 load address in // the C64 data (example: FE 0F 00 10 4C ...). A duplicate load address // of offset 0x02 is indicated by the ``fixLoad'' flag in the SidTuneInfo // structure. // // The ``force'' flag here can be used to remove the first load address // and set new INIT/PLAY addresses regardless of whether a duplicate // load address has been detected and indicated by ``fixLoad''. // For instance, some position independent sidtunes contain a load address // of 0xE000, but are loaded to 0x0FFE and call the player code at 0x1000. // // Do not forget to save the sidtune file. void fixLoadAddress(const bool force = false, uint_least16_t initAddr = 0, uint_least16_t playAddr = 0); // Does not affect status of object, and therefore can be used // to load files. Error string is put into info.statusString, though. bool loadFile(const char* fileName, Buffer_sidtt& bufferRef); // bool saveToOpenFile( std::ofstream& toFile, const uint_least8_t* buffer, uint_least32_t bufLen ); protected: // ------------------------------------------------------------- SidTuneInfo info; bool status; uint_least8_t songSpeed[SIDTUNE_MAX_SONGS]; uint_least8_t clockSpeed[SIDTUNE_MAX_SONGS]; uint_least16_t songLength[SIDTUNE_MAX_SONGS]; // holds text info from the format headers etc. char infoString[SIDTUNE_MAX_CREDIT_STRINGS][SIDTUNE_MAX_CREDIT_STRLEN]; // See instructions at top. bool isSlashedFileName; public: // For files with header: offset to real data uint_least32_t fileOffset; protected: // Needed for MUS/STR player installation. uint_least16_t musDataLen; public: Buffer_sidtt cache; protected: // Filename extensions to append for various file types. static const char** fileNameExtensions; // --- protected member functions --- // Convert 32-bit PSID-style speed word to internal tables. void convertOldStyleSpeedToTables(uint_least32_t speed, int clock = SIDTUNE_CLOCK_PAL); // Check SidTuneInfo fields for all real c64 only formats bool checkRealC64Info(uint_least32_t speed); // Check the init address is legal for real C64 only tunes bool checkRealC64Init(void); // Check for valid relocation information bool checkRelocInfo(void); // Common address resolution procedure bool resolveAddrs(const uint_least8_t* c64data); // Support for various file formats. virtual bool PSID_fileSupport(const void* buffer, const uint_least32_t bufLen); //virtual bool PSID_fileSupportSave(std::ofstream& toFile, const uint_least8_t* dataBuffer); virtual bool SID_fileSupport(const void* dataBuffer, uint_least32_t dataBufLen, const void* sidBuffer, uint_least32_t sidBufLen); //virtual bool SID_fileSupportSave(std::ofstream& toFile); virtual bool MUS_fileSupport(Buffer_sidtt& musBufRef, Buffer_sidtt& strBufRef); virtual bool MUS_detect(const void* buffer, const uint_least32_t bufLen, uint_least32_t& voice3Index); virtual bool MUS_mergeParts(Buffer_sidtt& musBufRef, Buffer_sidtt& strBufRef); virtual void MUS_setPlayerAddress(); virtual void MUS_installPlayer(uint_least8_t *c64buf); virtual int MUS_decodePetLine(SmartPtr_sidtt&, char*); virtual bool INFO_fileSupport(const void* dataBuffer, uint_least32_t dataBufLen, const void* infoBuffer, uint_least32_t infoBufLen); // Error and status message strings. static const char* txt_songNumberExceed; static const char* txt_empty; static const char* txt_unrecognizedFormat; static const char* txt_noDataFile; static const char* txt_notEnoughMemory; static const char* txt_cantLoadFile; static const char* txt_cantOpenFile; static const char* txt_fileTooLong; static const char* txt_dataTooLong; static const char* txt_cantCreateFile; static const char* txt_fileIoError; static const char* txt_VBI; static const char* txt_CIA; static const char* txt_noErrors; static const char* txt_na; static const char* txt_badAddr; static const char* txt_badReloc; private: // --------------------------------------------------------------- void init(); void cleanup(); #if !defined(SIDTUNE_NO_STDIN_LOADER) void getFromStdIn(); #endif void getFromFiles(const char* name); void deleteFileNameCopies(); // Try to retrieve single-file sidtune from specified buffer. void getFromBuffer(const uint_least8_t* const buffer, const uint_least32_t bufferLen); // Cache the data of a single-file or two-file sidtune and its // corresponding file names. bool acceptSidTune(const char* dataFileName, const char* infoFileName, Buffer_sidtt& buf); bool createNewFileName(Buffer_sidtt& destString, const char* sourceName, const char* sourceExt); private: // prevent copying SidTune(const SidTune&); SidTune& operator=(SidTune&); }; #endif /* SIDTUNE_H */