Main Page | Class Hierarchy | Compound List | File List | Compound Members | File Members | Related Pages

psid_.cpp

Go to the documentation of this file.
00001 //
00002 // 1997/05/11 11:29:06
00003 //
00004 
00005 #include "psid_.h"
00006 
00007 
00008 const char text_format[] = "PlaySID one-file format (PSID)";
00009 const char text_psidTruncated[] = "ERROR: PSID file is most likely truncated";
00010 
00011 struct psidHeader
00012 {
00013         //
00014         // All values in big-endian order.
00015         //
00016         char id[4];          // 'PSID'
00017         ubyte version[2];    // 0x0001 or 0x0002
00018         ubyte data[2];       // 16-bit offset to binary data in file
00019         ubyte load[2];       // 16-bit C64 address to load file to
00020         ubyte init[2];       // 16-bit C64 address of init subroutine
00021         ubyte play[2];       // 16-bit C64 address of play subroutine
00022         ubyte songs[2];      // number of songs
00023         ubyte start[2];      // start song (1-256 !)
00024         ubyte speed[4];      // 32-bit speed info
00025                                  // bit: 0=50 Hz, 1=CIA 1 Timer A (default: 60 Hz)
00026         char name[32];       // ASCII strings, 31 characters long and
00027         char author[32];     // terminated by a trailing zero
00028         char copyright[32];  //
00029         ubyte flags[2];      // only version 0x0002
00030         ubyte reserved[4];   // only version 0x0002
00031 };
00032 
00033 
00034 bool sidTune::PSID_fileSupport( void* buffer, udword bufLen )
00035 {
00036         // Remove any format description or format error string.
00037         info.formatString = 0;
00038 
00039         // Require a first minimum size.
00040         if (bufLen < 6)
00041         {
00042                 return false;
00043         }
00044         // Now it is safe to access the first bytes.
00045         // Require a valid ID and version number.
00046         psidHeader* pHeader = (psidHeader*)buffer;
00047         if ( (readBEdword((ubyte*)pHeader->id) != 0x50534944)  // "PSID" ?
00048                 || (readBEword(pHeader->version) >= 3) )
00049         {
00050                 return false;
00051         }
00052         // Due to security concerns, input must be at least as long as version 1
00053         // plus C64 load address data. That is the area which will be accessed.
00054         if ( bufLen < (sizeof(psidHeader)+2) )
00055         {
00056                 info.formatString = text_psidTruncated;
00057                 return false;
00058         }
00059 
00060         fileOffset = readBEword(pHeader->data);
00061         info.loadAddr = readBEword(pHeader->load);
00062         info.initAddr = readBEword(pHeader->init);
00063         info.playAddr = readBEword(pHeader->play);
00064         info.songs = readBEword(pHeader->songs);
00065         info.startSong = readBEword(pHeader->start);
00066 
00067         if (info.songs > classMaxSongs)
00068         {
00069                 info.songs = classMaxSongs;
00070         }
00071         
00072         // Create the speed/clock setting table.
00073         udword oldStyleSpeed = readBEdword(pHeader->speed);
00074         convertOldStyleSpeedToTables(oldStyleSpeed);
00075         
00076         info.musPlayer = false;
00077         if ( readBEword(pHeader->version) >= 2 )
00078         {
00079                 if (( readBEword(pHeader->flags) & 1 ) == 1 )
00080                 {
00081                         info.musPlayer = true;
00082                 }
00083         }
00084   
00085         if ( info.loadAddr == 0 )
00086         {
00087                 ubyte* pData = (ubyte*)buffer + fileOffset;
00088                 info.loadAddr = readEndian( *(pData+1), *pData );
00089                 fileOffset += 2;
00090         }
00091         if ( info.initAddr == 0 )
00092         {
00093                 info.initAddr = info.loadAddr;
00094         }
00095         if ( info.startSong == 0 ) 
00096         {
00097                 info.startSong = 1;
00098         }
00099         
00100         // Now adjust MUS songs.
00101         if ( info.musPlayer )
00102         {
00103                 info.loadAddr = 0x1000;
00104                 info.initAddr = 0xc7b0;
00105                 info.playAddr = 0;
00106         }
00107 
00108         // Correctly terminate the info strings.
00109         pHeader->name[31] = 0;
00110         pHeader->author[31] = 0;
00111         pHeader->copyright[31] = 0;
00112 
00113         // Copy info strings, so they will not get lost.
00114         strcpy( &infoString[0][0], pHeader->name );
00115         info.nameString = &infoString[0][0];
00116         info.infoString[0] = &infoString[0][0];
00117         strcpy( &infoString[1][0], pHeader->author );
00118         info.authorString = &infoString[1][0];
00119         info.infoString[1] = &infoString[1][0];
00120         strcpy( &infoString[2][0], pHeader->copyright );
00121         info.copyrightString = &infoString[2][0];
00122         info.infoString[2] = &infoString[2][0];
00123         info.numberOfInfoStrings = 3;
00124         
00125         info.formatString = text_format;
00126         return true;
00127 }
00128 
00129 #if 0 //ALFRED - TODO
00130 bool sidTune::PSID_fileSupportSave( ofstream& fMyOut, ubyte* dataBuffer )
00131 {
00132         psidHeader myHeader;
00133         writeBEdword((ubyte*)myHeader.id,0x50534944);  // 'PSID'
00134         writeBEword(myHeader.version,2);
00135         writeBEword(myHeader.data,0x7C);
00136         writeBEword(myHeader.load,0);
00137         writeBEword(myHeader.init,info.initAddr);
00138         writeBEword(myHeader.play,info.playAddr);
00139         writeBEword(myHeader.songs,info.songs);
00140         writeBEword(myHeader.start,info.startSong);
00141 
00142         udword speed = 0;
00143         int maxBugSongs = ((info.songs <= 32) ? info.songs : 32);
00144         for (int s = 0; s < maxBugSongs; s++)
00145         {
00146                 if (songSpeed[s] == SIDTUNE_SPEED_CIA_1A)
00147                 {
00148                         speed |= (1<<s);
00149                 }
00150         }
00151         writeBEdword(myHeader.speed,speed);
00152 
00153         uword tmpFlags = 0;
00154         if ( info.musPlayer )
00155         {
00156                 tmpFlags |= 1;
00157         }
00158         writeBEword(myHeader.flags,tmpFlags);
00159         writeBEdword(myHeader.reserved,0);
00160         for ( int i = 0; i < 32; i++ )
00161         {
00162                 myHeader.name[i] = 0;
00163                 myHeader.author[i] = 0;
00164                 myHeader.copyright[i] = 0;
00165         }
00166         strncpy( myHeader.name, info.nameString, 31 );
00167         strncpy( myHeader.author, info.authorString, 31 );
00168         strncpy( myHeader.copyright, info.copyrightString, 31 );
00169         fMyOut.write( (char*)&myHeader, sizeof(psidHeader) );
00170         
00171         // Save C64 lo/hi load address (little-endian).
00172         ubyte saveAddr[2];
00173         saveAddr[0] = info.loadAddr & 255;
00174         saveAddr[1] = info.loadAddr >> 8;
00175         fMyOut.write( saveAddr, 2 );
00176         // Data starts at: bufferaddr + fileoffset
00177         // Data length: datafilelen - fileoffset
00178         fMyOut.write( dataBuffer + fileOffset, info.dataFileLen - fileOffset );
00179         if ( !fMyOut )
00180         {
00181                 return false;
00182         }
00183         else
00184         {
00185                 return true;
00186         }
00187 }
00188 #endif //ALFRED - TODO

Generated on Tue Feb 8 04:13:59 2005 for Esidplay by doxygen 1.3.3