1 /* 2 * /home/ms/files/source/libsidtune/RCS/SidTune.h,v 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation; either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write to the Free Software 16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 */ 18 19 #ifndef SIDTUNE_H 20 #define SIDTUNE_H 21 22 23 #include "sidtypes.h" 24 #include "Buffer.h" 25 #include "SmartPtr.h" 26 27 #include <fstream> 28 29 30 const uint_least16_t SIDTUNE_MAX_SONGS = 256; 31 // Also PSID file format limit. 32 33 const uint_least16_t SIDTUNE_MAX_CREDIT_STRINGS = 10; 34 const uint_least16_t SIDTUNE_MAX_CREDIT_STRLEN = 80+1; 35 // 80 characters plus terminating zero. 36 37 const uint_least32_t SIDTUNE_MAX_MEMORY = 65536; 38 const uint_least32_t SIDTUNE_MAX_FILELEN = 65536+2+0x7C; 39 // C64KB+LOAD+PSID 40 41 const int SIDTUNE_SPEED_VBI = 0; // Vertical-Blanking-Interrupt 42 const int SIDTUNE_SPEED_CIA_1A = 60; // CIA 1 Timer A 43 44 const int SIDTUNE_CLOCK_UNKNOWN = 0x00; 45 const int SIDTUNE_CLOCK_PAL = 0x01; // These are also used in the 46 const int SIDTUNE_CLOCK_NTSC = 0x02; // emulator engine! 47 const int SIDTUNE_CLOCK_ANY = (SIDTUNE_CLOCK_PAL | SIDTUNE_CLOCK_NTSC); 48 49 const int SIDTUNE_SIDMODEL_UNKNOWN = 0x00; 50 const int SIDTUNE_SIDMODEL_6581 = 0x01; // These are also used in the 51 const int SIDTUNE_SIDMODEL_8580 = 0x02; // emulator engine! 52 const int SIDTUNE_SIDMODEL_ANY = (SIDTUNE_SIDMODEL_6581 | SIDTUNE_SIDMODEL_8580); 53 54 const int SIDTUNE_COMPATIBILITY_C64 = 0x00; // File is C64 compatible 55 const int SIDTUNE_COMPATIBILITY_PSID = 0x01; // File is PSID specific 56 const int SIDTUNE_COMPATIBILITY_R64 = 0x02; // File is Real C64 only 57 const int SIDTUNE_COMPATIBILITY_BASIC = 0x03; // File requires C64 Basic 58 59 60 // Required to export template 61 #ifndef _SidTune_cpp_ 62 extern 63 #endif 64 template class SID_EXTERN Buffer_sidtt<const uint_least8_t>; 65 66 struct SidTuneInfo 67 { 68 // An instance of this structure is used to transport values to 69 // and from SidTune objects. 70 71 // You must read (i.e. activate) sub-song specific information 72 // via: 73 // const SidTuneInfo& tuneInfo = SidTune[songNumber]; 74 // const SidTuneInfo& tuneInfo = SidTune.getInfo(); 75 // void SidTune.getInfo(tuneInfo&); 76 77 // Consider the following fields as read-only, because the SidTune class 78 // does not provide an implementation of: bool setInfo(const SidTuneInfo&). 79 // Currently, the only way to get the class to accept values which 80 // are written to these fields is by creating a derived class. 81 82 const char* formatString; // the name of the identified file format 83 const char* statusString; // error/status message of last operation 84 85 const char* speedString; // describing the speed a song is running at 86 87 uint_least16_t loadAddr; 88 uint_least16_t initAddr; 89 uint_least16_t playAddr; 90 91 uint_least16_t songs; 92 uint_least16_t startSong; 93 94 // The SID chip base address(es) used by the sidtune. 95 uint_least16_t sidChipBase1; // 0xD400 (normal, 1st SID) 96 uint_least16_t sidChipBase2; // 0xD?00 (2nd SID) or 0 (no 2nd SID) 97 98 // Available after song initialization. 99 // 100 uint_least16_t currentSong; // the one that has been initialized 101 uint_least8_t songSpeed; // intended speed, see top 102 uint_least8_t clockSpeed; // -"- 103 uint_least8_t relocStartPage; // First available page for relocation 104 uint_least8_t relocPages; // Number of pages available for relocation 105 bool musPlayer; // whether Sidplayer routine has been installed 106 int sidModel; // Sid Model required for this sid 107 int compatibility; // compatibility requirements 108 bool fixLoad; // whether load address might be duplicate 109 uint_least16_t songLength; // --- not yet supported --- 110 // 111 // Song title, credits, ... 112 // 0 = Title, 1 = Author, 2 = Copyright/Publisher 113 // 114 uint_least8_t numberOfInfoStrings; // the number of available text info lines 115 char* infoString[SIDTUNE_MAX_CREDIT_STRINGS]; 116 // 117 uint_least16_t numberOfCommentStrings; // --- not yet supported --- 118 char ** commentString; // --- not yet supported --- 119 // 120 uint_least32_t dataFileLen; // length of single-file sidtune file 121 uint_least32_t c64dataLen; // length of raw C64 data without load address 122 char* path; // path to sidtune files; "", if cwd 123 char* dataFileName; // a first file: e.g. "foo.c64"; "", if none 124 char* infoFileName; // a second file: e.g. "foo.sid"; "", if none 125 // 126 }; 127 128 129 class SID_EXTERN SidTune 130 { 131 private: 132 typedef enum 133 { 134 LOAD_NOT_MINE = 0, 135 LOAD_OK, 136 LOAD_ERROR 137 } LoadStatus; 138 139 public: // ---------------------------------------------------------------- 140 141 // If your opendir() and readdir()->d_name return path names 142 // that contain the forward slash (/) as file separator, but 143 // your operating system uses a different character, there are 144 // extra functions that can deal with this special case. Set 145 // separatorIsSlash to true if you like path names to be split 146 // correctly. 147 // You do not need these extra functions if your systems file 148 // separator is the forward slash. 149 // 150 // Load a sidtune from a file. 151 // 152 // To retrieve data from standard input pass in filename "-". 153 // If you want to override the default filename extensions use this 154 // contructor. Please note, that if the specified ``sidTuneFileName'' 155 // does exist and the loader is able to determine its file format, 156 // this function does not try to append any file name extension. 157 // See ``sidtune.cpp'' for the default list of file name extensions. 158 // You can specific ``sidTuneFileName = 0'', if you do not want to 159 // load a sidtune. You can later load one with open(). 160 SidTune(const char* fileName, const char **fileNameExt = 0, 161 const bool separatorIsSlash = false); 162 163 // Load a single-file sidtune from a memory buffer. 164 // Currently supported: PSID format 165 SidTune(const uint_least8_t* oneFileFormatSidtune, const uint_least32_t sidtuneLength); 166 167 virtual ~SidTune(); 168 169 // The sidTune class does not copy the list of file name extensions, 170 // so make sure you keep it. If the provided pointer is 0, the 171 // default list will be activated. This is a static list which 172 // is used by all SidTune objects. 173 void setFileNameExtensions(const char **fileNameExt); 174 175 // Load a sidtune into an existing object. 176 // From a file. 177 bool load(const char* fileName, const bool separatorIsSlash = false); 178 179 // From a buffer. 180 bool read(const uint_least8_t* sourceBuffer, const uint_least32_t bufferLen); 181 182 // Select sub-song (0 = default starting song) 183 // and retrieve active song information. 184 const SidTuneInfo& operator[](const uint_least16_t songNum); 185 186 // Select sub-song (0 = default starting song) 187 // and return active song number out of [1,2,..,SIDTUNE_MAX_SONGS]. 188 uint_least16_t selectSong(const uint_least16_t songNum); 189 190 // Retrieve sub-song specific information. 191 // Beware! Still member-wise copy! 192 const SidTuneInfo& getInfo(); 193 194 // Get a copy of sub-song specific information. 195 // Beware! Still member-wise copy! 196 void getInfo(SidTuneInfo&); 197 198 // Determine current state of object (true = okay, false = error). 199 // Upon error condition use ``getInfo'' to get a descriptive 200 // text string in ``SidTuneInfo.statusString''. 201 operator bool() { return status; } getStatus()202 bool getStatus() { return status; } 203 204 // Whether sidtune uses two SID chips. isStereo()205 bool isStereo() 206 { 207 return (info.sidChipBase1!=0 && info.sidChipBase2!=0); 208 } 209 210 // Copy sidtune into C64 memory (64 KB). 211 bool placeSidTuneInC64mem(uint_least8_t* c64buf); 212 213 // --- file save & format conversion --- 214 215 // These functions work for any successfully created object. 216 // overWriteFlag: true = Overwrite existing file. 217 // false = Default, return error when file already 218 // exists. 219 // One could imagine an "Are you sure ?"-checkbox before overwriting 220 // any file. 221 // returns: true = Successful, false = Error condition. 222 bool saveC64dataFile( const char* destFileName, const bool overWriteFlag = false ); 223 bool saveSIDfile( const char* destFileName, const bool overWriteFlag = false ); 224 bool savePSIDfile( const char* destFileName, const bool overWriteFlag = false ); 225 226 // This function can be used to remove a duplicate C64 load address in 227 // the C64 data (example: FE 0F 00 10 4C ...). A duplicate load address 228 // of offset 0x02 is indicated by the ``fixLoad'' flag in the SidTuneInfo 229 // structure. 230 // 231 // The ``force'' flag here can be used to remove the first load address 232 // and set new INIT/PLAY addresses regardless of whether a duplicate 233 // load address has been detected and indicated by ``fixLoad''. 234 // For instance, some position independent sidtunes contain a load address 235 // of 0xE000, but are loaded to 0x0FFE and call the player code at 0x1000. 236 // 237 // Do not forget to save the sidtune file. 238 void fixLoadAddress(const bool force = false, uint_least16_t initAddr = 0, 239 uint_least16_t playAddr = 0); 240 241 // Does not affect status of object, and therefore can be used 242 // to load files. Error string is put into info.statusString, though. 243 bool loadFile(const char* fileName, Buffer_sidtt<const uint_least8_t>& bufferRef); 244 245 bool saveToOpenFile( std::ofstream& toFile, const uint_least8_t* buffer, uint_least32_t bufLen ); 246 247 protected: // ------------------------------------------------------------- 248 249 SidTuneInfo info; 250 bool status; 251 252 uint_least8_t songSpeed[SIDTUNE_MAX_SONGS]; 253 uint_least8_t clockSpeed[SIDTUNE_MAX_SONGS]; 254 uint_least16_t songLength[SIDTUNE_MAX_SONGS]; 255 256 // holds text info from the format headers etc. 257 char infoString[SIDTUNE_MAX_CREDIT_STRINGS][SIDTUNE_MAX_CREDIT_STRLEN]; 258 259 // See instructions at top. 260 bool isSlashedFileName; 261 262 // For files with header: offset to real data 263 uint_least32_t fileOffset; 264 265 // Needed for MUS/STR player installation. 266 uint_least16_t musDataLen; 267 268 Buffer_sidtt<const uint_least8_t> cache; 269 270 // Filename extensions to append for various file types. 271 static const char** fileNameExtensions; 272 273 // --- protected member functions --- 274 275 // Convert 32-bit PSID-style speed word to internal tables. 276 void convertOldStyleSpeedToTables(uint_least32_t speed, 277 int clock = SIDTUNE_CLOCK_PAL); 278 279 virtual int convertPetsciiToAscii (SmartPtr_sidtt<const uint_least8_t>&, char*); 280 281 // Check compatibility details are sensible 282 bool checkCompatibility(void); 283 // Check for valid relocation information 284 bool checkRelocInfo(void); 285 // Common address resolution procedure 286 bool resolveAddrs(const uint_least8_t* c64data); 287 288 // Support for various file formats. 289 290 virtual LoadStatus PSID_fileSupport (Buffer_sidtt<const uint_least8_t>& dataBuf); 291 virtual bool PSID_fileSupportSave(std::ofstream& toFile, const uint_least8_t* dataBuffer); 292 293 virtual LoadStatus SID_fileSupport (Buffer_sidtt<const uint_least8_t>& dataBuf, 294 Buffer_sidtt<const uint_least8_t>& sidBuf); 295 virtual bool SID_fileSupportSave (std::ofstream& toFile); 296 297 virtual LoadStatus MUS_fileSupport (Buffer_sidtt<const uint_least8_t>& musBuf, 298 Buffer_sidtt<const uint_least8_t>& strBuf); 299 LoadStatus MUS_load (Buffer_sidtt<const uint_least8_t>& musBuf, 300 bool init = false); 301 LoadStatus MUS_load (Buffer_sidtt<const uint_least8_t>& musBuf, 302 Buffer_sidtt<const uint_least8_t>& strBuf, 303 bool init = false); 304 virtual bool MUS_detect (const void* buffer, const uint_least32_t bufLen, 305 uint_least32_t& voice3Index); 306 virtual bool MUS_mergeParts (Buffer_sidtt<const uint_least8_t>& musBuf, 307 Buffer_sidtt<const uint_least8_t>& strBuf); 308 virtual void MUS_setPlayerAddress(); 309 virtual void MUS_installPlayer (uint_least8_t *c64buf); 310 311 virtual LoadStatus INFO_fileSupport (Buffer_sidtt<const uint_least8_t>& dataBuf, 312 Buffer_sidtt<const uint_least8_t>& infoBuf); 313 virtual LoadStatus PRG_fileSupport (const char* fileName, 314 Buffer_sidtt<const uint_least8_t>& dataBuf); 315 virtual LoadStatus X00_fileSupport (const char* fileName, 316 Buffer_sidtt<const uint_least8_t>& dataBuf); 317 318 // Error and status message strings. 319 static const char* txt_songNumberExceed; 320 static const char* txt_empty; 321 static const char* txt_unrecognizedFormat; 322 static const char* txt_noDataFile; 323 static const char* txt_notEnoughMemory; 324 static const char* txt_cantLoadFile; 325 static const char* txt_cantOpenFile; 326 static const char* txt_fileTooLong; 327 static const char* txt_dataTooLong; 328 static const char* txt_cantCreateFile; 329 static const char* txt_fileIoError; 330 static const char* txt_VBI; 331 static const char* txt_CIA; 332 static const char* txt_noErrors; 333 static const char* txt_na; 334 static const char* txt_badAddr; 335 static const char* txt_badReloc; 336 static const char* txt_corrupt; 337 338 private: // --------------------------------------------------------------- 339 340 void init(); 341 void cleanup(); 342 #if !defined(SIDTUNE_NO_STDIN_LOADER) 343 void getFromStdIn(); 344 #endif 345 void getFromFiles(const char* name); 346 347 void deleteFileNameCopies(); 348 349 // Try to retrieve single-file sidtune from specified buffer. 350 void getFromBuffer(const uint_least8_t* const buffer, const uint_least32_t bufferLen); 351 352 // Cache the data of a single-file or two-file sidtune and its 353 // corresponding file names. 354 bool acceptSidTune(const char* dataFileName, const char* infoFileName, 355 Buffer_sidtt<const uint_least8_t>& buf); 356 357 bool createNewFileName(Buffer_sidtt<char>& destString, 358 const char* sourceName, const char* sourceExt); 359 360 int decompressPP20(Buffer_sidtt<const uint_least8_t>& buf); 361 362 private: // prevent copying 363 SidTune(const SidTune&); 364 SidTune& operator=(SidTune&); 365 }; 366 367 #endif /* SIDTUNE_H */ 368