summaryrefslogtreecommitdiff
path: root/sid/sidplay-libs-2.1.0/libsidplay/src/sidtune
diff options
context:
space:
mode:
authorGravatar waker <wakeroid@gmail.com>2009-08-19 22:45:01 +0200
committerGravatar waker <wakeroid@gmail.com>2009-08-19 22:45:01 +0200
commit2f34377d0352ed5aae777f813bbbadcffacbb579 (patch)
tree17498521f4349cf16af4d47940bccb2885eb9727 /sid/sidplay-libs-2.1.0/libsidplay/src/sidtune
parent49875b085e4c1fa6881a54b482e8439fc1c6daa9 (diff)
passed make distcheck; 0.1.0 release
Diffstat (limited to 'sid/sidplay-libs-2.1.0/libsidplay/src/sidtune')
-rw-r--r--sid/sidplay-libs-2.1.0/libsidplay/src/sidtune/IconInfo.cpp468
-rw-r--r--sid/sidplay-libs-2.1.0/libsidplay/src/sidtune/InfoFile.cpp395
-rw-r--r--sid/sidplay-libs-2.1.0/libsidplay/src/sidtune/MUS.cpp681
-rw-r--r--sid/sidplay-libs-2.1.0/libsidplay/src/sidtune/Makefile.am17
-rw-r--r--sid/sidplay-libs-2.1.0/libsidplay/src/sidtune/Makefile.in446
-rw-r--r--sid/sidplay-libs-2.1.0/libsidplay/src/sidtune/PP20.cpp289
-rw-r--r--sid/sidplay-libs-2.1.0/libsidplay/src/sidtune/PP20.h70
-rw-r--r--sid/sidplay-libs-2.1.0/libsidplay/src/sidtune/PP20_Defs.h39
-rw-r--r--sid/sidplay-libs-2.1.0/libsidplay/src/sidtune/PSID.cpp313
-rw-r--r--sid/sidplay-libs-2.1.0/libsidplay/src/sidtune/SidTune.cpp1150
-rw-r--r--sid/sidplay-libs-2.1.0/libsidplay/src/sidtune/SidTuneCfg.h35
-rw-r--r--sid/sidplay-libs-2.1.0/libsidplay/src/sidtune/SidTuneTools.cpp215
-rw-r--r--sid/sidplay-libs-2.1.0/libsidplay/src/sidtune/SidTuneTools.h85
13 files changed, 4203 insertions, 0 deletions
diff --git a/sid/sidplay-libs-2.1.0/libsidplay/src/sidtune/IconInfo.cpp b/sid/sidplay-libs-2.1.0/libsidplay/src/sidtune/IconInfo.cpp
new file mode 100644
index 00000000..37717694
--- /dev/null
+++ b/sid/sidplay-libs-2.1.0/libsidplay/src/sidtune/IconInfo.cpp
@@ -0,0 +1,468 @@
+/*
+ * /home/ms/files/source/libsidtune/RCS/IconInfo.cpp,v
+ *
+ * Amiga icon tooltype PlaySID file format (.info) support.
+ *
+ * This is a derived work, courtesy of Peter Kunath, who has
+ * provided an examplary source code to examine an Amiga icon file.
+ *
+ * It has been ported and heavily modified to suit certain
+ * requirements. This replaces the old code, which was simply
+ * scanning input data for a first, presumedly constant, Id string.
+ * This code does not require the default tool to serve as a
+ * constant Id by containing "SID:PlaySID".
+ *
+ * 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 "config.h"
+#include "SidTune.h"
+#include "SmartPtr.h"
+#include "SidTuneTools.h"
+#include "sidendian.h"
+
+#ifdef HAVE_EXCEPTIONS
+# include <new>
+#endif
+#include <string.h>
+#include <strstream>
+
+// Amiga Workbench specific structures.
+
+struct Border
+{
+ uint8_t LeftEdge[2]; // uint_least16_t; initial offsets from the origin
+ uint8_t TopEdge[2]; // uint_least16_t
+ uint8_t FrontPen, BackPen; // pens numbers for rendering
+ uint8_t DrawMode; // mode for rendering
+ uint8_t Count; // number of XY pairs
+ uint8_t pXY[4]; // int_least16_t *XY; vector coordinate pairs rel to LeftTop
+ uint8_t pNextBorder[4]; // Border *NextBorder; pointer to any other Border too
+};
+
+struct Image
+{
+ uint8_t LeftEdge[2]; // uint_least16_t; starting offset relative to some origin
+ uint8_t TopEdge[2]; // uint_least16_t; starting offsets relative to some origin
+ uint8_t Width[2]; // uint_least16_t; pixel size (though data is word-aligned)
+ uint8_t Height[2]; // uint_least16_t
+ uint8_t Depth[2]; // uint_least16_t; >= 0, for images you create
+ uint8_t pImageData[4]; // uint_least16_t *ImageData; pointer to the actual word-aligned bits
+ uint8_t PlanePick, PlaneOnOff;
+ uint8_t pNextImage[4]; // Image *NextImage;
+};
+
+struct Gadget
+{
+ uint8_t pNextGadget[4]; // Gadget *NextGadget; next gadget in the list
+ uint8_t LeftEdge[2]; // uint_least16_t; "hit box" of gadget
+ uint8_t TopEdge[2]; // uint_least16_t
+ uint8_t Width[2]; // uint_least16_t; "hit box" of gadget
+ uint8_t Height[2]; // uint_least16_t
+ uint8_t Flags[2]; // uint_least16_t; see below for list of defines
+ uint8_t Activation[2]; // uint_least16_t
+ uint8_t GadgetType[2]; // uint_least16_t; see below for defines
+ uint8_t pGadgetRender[4]; // Image *GadgetRender;
+ uint8_t pSelectRender[4]; // Image *SelectRender;
+ uint8_t pGadgetText[4]; // void *GadgetText;
+ uint8_t MutualExclude[4]; // udword
+ uint8_t pSpecialInfo[4]; // void *SpecialInfo;
+ uint8_t GadgetID[2]; // uint_least16_t
+ uint8_t UserData[4]; // udword; ptr to general purpose User data
+};
+
+struct DiskObject
+{
+ uint8_t Magic[2]; // uint_least16_t; a magic num at the start of the file
+ uint8_t Version[2]; // uint_least16_t; a version number, so we can change it
+ struct Gadget Gadget; // a copy of in core gadget
+ uint8_t Type;
+ uint8_t PAD_BYTE; // Pad it out to the next word boundry
+ uint8_t pDefaultTool[4]; // char *DefaultTool;
+ uint8_t ppToolTypes[4]; // char **ToolTypes;
+ uint8_t CurrentX[4]; // udword
+ uint8_t CurrentY[4]; // udword
+ uint8_t pDrawerData[4]; // char *DrawerData;
+ uint8_t pToolWindow[4]; // char *ToolWindow; only applies to tools
+ uint8_t StackSize[4]; // udword; only applies to tools
+};
+
+
+// A magic number, not easily impersonated.
+#define WB_DISKMAGIC 0xE310
+// Our current version number.
+#define WB_DISKVERSION 1
+// Our current revision number.
+#define WB_DISKREVISION 1
+// I only use the lower 8 bits of Gadget.UserData for the revision #.
+#define WB_DISKREVISIONMASK 0xFF
+
+// The Workbench object types.
+#define WB_DISK 1
+#define WB_DRAWER 2
+#define WB_TOOL 3
+#define WB_PROJECT 4
+#define WB_GARBAGE 5
+#define WB_DEVICE 6
+#define WB_KICK 7
+#define WB_APPICON 8
+
+// --- Gadget.Flags values ---
+// Combinations in these bits describe the highlight technique to be used.
+#define GFLG_GADGHIGHBITS 0x0003
+// Complement the select box.
+#define GFLG_GADGHCOMP 0x0000
+// Draw a box around the image.
+#define GFLG_GADGHBOX 0x0001
+// Blast in this alternate image.
+#define GFLG_GADGHIMAGE 0x0002
+// Don't highlight.
+#define GFLG_GADGHNONE 0x0003
+// Set if GadgetRender and SelectRender point to an Image structure,
+// clear if they point to Border structures.
+#define GFLG_GADGIMAGE 0x0004
+
+const char _sidtune_txt_format[] = "Raw plus PlaySID icon tooltype file (INFO)";
+
+const char _sidtune_keyword_id[] = "SID:PLAYSID";
+const char _sidtune_keyword_address[] = "ADDRESS=";
+const char _sidtune_keyword_songs[] = "SONGS=";
+const char _sidtune_keyword_speed[] = "SPEED=";
+const char _sidtune_keyword_name[] = "NAME=";
+const char _sidtune_keyword_author[] = "AUTHOR=";
+const char _sidtune_keyword_copyright[] = "COPYRIGHT=";
+const char _sidtune_keyword_musPlayer[] = "SIDSONG=YES";
+
+const char _sidtune_txt_noMemError[] = "ERROR: Not enough free memory";
+const char _sidtune_txt_corruptError[] = "ERROR: Info file is incomplete or corrupt";
+const char _sidtune_txt_noStringsError[] = "ERROR: Info file does not contain required strings";
+const char _sidtune_txt_dataCorruptError[] = "ERROR: C64 data file is corrupt";
+#if defined(SIDTUNE_REJECT_UNKNOWN_FIELDS)
+const char _sidtune_txt_chunkError[] = "ERROR: Invalid tooltype information in icon file";
+#endif
+
+const uint_least16_t safeBufferSize = 64; // for string comparison, stream parsing
+
+
+bool SidTune::INFO_fileSupport(const void* dataBuffer, uint_least32_t dataLength,
+ const void* infoBuffer, uint_least32_t infoLength)
+{
+ // Require a first minimum safety size.
+ uint_least32_t minSize = 1+sizeof(struct DiskObject);
+ if (infoLength < minSize)
+ return( false );
+
+ const DiskObject *dobject = (const DiskObject *)infoBuffer;
+
+ // Require Magic_Id in the first two bytes of the file.
+ if ( endian_16(dobject->Magic[0],dobject->Magic[1]) != WB_DISKMAGIC )
+ return false;
+
+ // Only version 1.x supported.
+ if ( endian_16(dobject->Version[0],dobject->Version[1]) != WB_DISKVERSION )
+ return false;
+
+ // A PlaySID icon must be of type project.
+ if ( dobject->Type != WB_PROJECT )
+ return false;
+
+ uint i; // general purpose index variable
+
+ // We want to skip a possible Gadget Image item.
+ const char *icon = (const char*)infoBuffer + sizeof(DiskObject);
+
+ if ( (endian_16(dobject->Gadget.Flags[0],dobject->Gadget.Flags[1]) & GFLG_GADGIMAGE) == 0)
+ {
+ // Calculate size of gadget borders (vector image).
+
+ if (dobject->Gadget.pGadgetRender[0] |
+ dobject->Gadget.pGadgetRender[1] |
+ dobject->Gadget.pGadgetRender[2] |
+ dobject->Gadget.pGadgetRender[3]) // border present?
+ {
+ // Require another minimum safety size.
+ minSize += sizeof(struct Border);
+ if (infoLength < minSize)
+ return( false );
+
+ const Border *brd = (const Border *)icon;
+ icon += sizeof(Border);
+ icon += brd->Count * (2+2); // pair of uint_least16_t
+ }
+
+ if (dobject->Gadget.pSelectRender[0] |
+ dobject->Gadget.pSelectRender[1] |
+ dobject->Gadget.pSelectRender[2] |
+ dobject->Gadget.pSelectRender[3]) // alternate border present?
+ {
+ // Require another minimum safety size.
+ minSize += sizeof(Border);
+ if (infoLength < minSize)
+ return( false );
+
+ const Border *brd = (const Border *)icon;
+ icon += sizeof(Border);
+ icon += brd->Count * (2+2); // pair of uint_least16_t
+ }
+ }
+ else
+ {
+ // Calculate size of gadget images (bitmap image).
+
+ if (dobject->Gadget.pGadgetRender[0] |
+ dobject->Gadget.pGadgetRender[1] |
+ dobject->Gadget.pGadgetRender[2] |
+ dobject->Gadget.pGadgetRender[3]) // image present?
+ {
+ // Require another minimum safety size.
+ minSize += sizeof(Image);
+ if (infoLength < minSize)
+ return( false );
+
+ const Image *img = (const Image *)icon;
+ icon += sizeof(Image);
+
+ uint_least32_t imgsize = 0;
+ for(i=0;i<endian_16(img->Depth[0],img->Depth[1]);i++)
+ {
+ if ( (img->PlanePick & (1<<i)) != 0)
+ {
+ // NOTE: Intuition relies on PlanePick to know how many planes
+ // of data are found in ImageData. There should be no more
+ // '1'-bits in PlanePick than there are planes in ImageData.
+ imgsize++;
+ }
+ }
+
+ imgsize *= ((endian_16(img->Width[0],img->Width[1])+15)/16)*2; // bytes per line
+ imgsize *= endian_16(img->Height[0],img->Height[1]); // bytes per plane
+
+ icon += imgsize;
+ }
+
+ if (dobject->Gadget.pSelectRender[0] |
+ dobject->Gadget.pSelectRender[1] |
+ dobject->Gadget.pSelectRender[2] |
+ dobject->Gadget.pSelectRender[3]) // alternate image present?
+ {
+ // Require another minimum safety size.
+ minSize += sizeof(Image);
+ if (infoLength < minSize)
+ return( false );
+
+ const Image *img = (const Image *)icon;
+ icon += sizeof(Image);
+
+ uint_least32_t imgsize = 0;
+ for(i=0;i<endian_16(img->Depth[0],img->Depth[1]);i++)
+ {
+ if ( (img->PlanePick & (1<<i)) != 0)
+ {
+ // NOTE: Intuition relies on PlanePick to know how many planes
+ // of data are found in ImageData. There should be no more
+ // '1'-bits in PlanePick than there are planes in ImageData.
+ imgsize++;
+ }
+ }
+
+ imgsize *= ((endian_16(img->Width[0],img->Width[1])+15)/16)*2; // bytes per line
+ imgsize *= endian_16(img->Height[0],img->Height[1]); // bytes per plane
+ icon += imgsize;
+ }
+ }
+
+ // Here use a smart pointer to prevent access violation errors.
+ SmartPtr_sidtt<const char> spTool((const char*)icon,infoLength-(uint_least32_t)(icon-(const char*)infoBuffer));
+ if ( !spTool )
+ {
+ info.formatString = _sidtune_txt_corruptError;
+ return false;
+ }
+
+ // A separate safe buffer is used for each tooltype string.
+#ifdef HAVE_EXCEPTIONS
+ SmartPtr_sidtt<char> spCmpBuf(new(std::nothrow) char[safeBufferSize],safeBufferSize,true);
+#else
+ SmartPtr_sidtt<char> spCmpBuf(new char[safeBufferSize],safeBufferSize,true);
+#endif
+ if ( !spCmpBuf )
+ {
+ info.formatString = _sidtune_txt_noMemError;
+ return false;
+ }
+
+#ifndef SID_HAVE_BAD_COMPILER
+ char* cmpBuf = spCmpBuf.tellBegin();
+#else
+ // This should not be necessary, but for some reason
+ // Microsoft Visual C++ says spCmpBuf is const...
+ char* cmpBuf = (char*) spCmpBuf.tellBegin();
+#endif
+
+ // Skip default tool.
+ spTool += endian_32(spTool[0],spTool[1],spTool[2],spTool[3]) + 4;
+
+ // Defaults.
+ fileOffset = 0; // no header in separate data file
+ info.sidChipBase1 = 0xd400;
+ info.sidChipBase2 = 0;
+ info.musPlayer = false;
+ info.numberOfInfoStrings = 0;
+ uint_least32_t oldStyleSpeed = 0;
+
+ // Flags for required entries.
+ bool hasAddress = false,
+ hasName = false,
+ hasAuthor = false,
+ hasCopyright = false,
+ hasSongs = false,
+ hasSpeed = false,
+ hasUnknownChunk = false;
+
+ // Calculate number of tooltype strings.
+ i = (endian_32(spTool[0],spTool[1],spTool[2],spTool[3])/4) - 1;
+ spTool += 4; // skip size info
+
+ while( i-- > 0 )
+ {
+ // Get length of this tool.
+ uint_least32_t toolLen = endian_32(spTool[0],spTool[1],spTool[2],spTool[3]);
+ spTool += 4; // skip tool length
+ // Copy item to safe buffer.
+ for ( uint ci = 0; ci < toolLen; ci++ )
+ {
+#ifndef SID_HAVE_BAD_COMPILER
+ spCmpBuf[ci] = spTool[ci];
+#else
+ // This should not be necessary, but for some reason
+ // Microsoft Visual C++ says spCmpBuf is const...
+ (*((char*) (&spCmpBuf[ci]))) = (char) spTool[ci];
+#endif
+ }
+ if ( !(spTool&&spCmpBuf) )
+ {
+ return false;
+ }
+
+ // Now check all possible keywords.
+ if ( SidTuneTools::myStrNcaseCmp(cmpBuf,_sidtune_keyword_address) == 0 )
+ {
+ std::istrstream addrIn(cmpBuf + strlen(_sidtune_keyword_address),
+ toolLen - strlen(_sidtune_keyword_address));
+ info.loadAddr = (uint_least16_t)SidTuneTools::readHex( addrIn );
+ info.initAddr = (uint_least16_t)SidTuneTools::readHex( addrIn );
+ info.playAddr = (uint_least16_t)SidTuneTools::readHex( addrIn );
+ if ( !addrIn )
+ {
+ return false;
+ }
+ hasAddress = true;
+ }
+ else if ( SidTuneTools::myStrNcaseCmp(cmpBuf,_sidtune_keyword_songs) == 0 )
+ {
+ std::istrstream numIn( cmpBuf + strlen(_sidtune_keyword_songs),
+ toolLen - strlen(_sidtune_keyword_songs) );
+ if ( !numIn )
+ {
+ return false;
+ }
+ info.songs = (uint_least16_t)SidTuneTools::readDec( numIn );
+ info.startSong = (uint_least16_t)SidTuneTools::readDec( numIn );
+ hasSongs = true;
+ }
+ else if ( SidTuneTools::myStrNcaseCmp(cmpBuf,_sidtune_keyword_speed) == 0 )
+ {
+ std::istrstream speedIn( cmpBuf + strlen(_sidtune_keyword_speed),
+ toolLen - strlen(_sidtune_keyword_speed) );
+ if ( !speedIn )
+ {
+ return false;
+ }
+ oldStyleSpeed = SidTuneTools::readHex(speedIn);
+ hasSpeed = true;
+ }
+ else if ( SidTuneTools::myStrNcaseCmp(cmpBuf,_sidtune_keyword_name) == 0 )
+ {
+ strncpy( &infoString[0][0], cmpBuf + strlen(_sidtune_keyword_name), 31 );
+ info.infoString[0] = &infoString[0][0];
+ hasName = true;
+ }
+ else if ( SidTuneTools::myStrNcaseCmp(cmpBuf,_sidtune_keyword_author) == 0 )
+ {
+ strncpy( &infoString[1][0], cmpBuf + strlen(_sidtune_keyword_author), 31 );
+ info.infoString[1] = &infoString[1][0];
+ hasAuthor = true;
+ }
+ else if ( SidTuneTools::myStrNcaseCmp(cmpBuf,_sidtune_keyword_copyright) == 0 )
+ {
+ strncpy( &infoString[2][0], cmpBuf + strlen(_sidtune_keyword_copyright), 31 );
+ info.infoString[2] = &infoString[2][0];
+ hasCopyright = true;
+ }
+ else if ( SidTuneTools::myStrNcaseCmp(cmpBuf,_sidtune_keyword_musPlayer) == 0 )
+ {
+ info.musPlayer = true;
+ }
+ else
+ {
+ hasUnknownChunk = true;
+#if defined(SIDTUNE_REJECT_UNKNOWN_FIELDS)
+ info.formatString = _sidtune_txt_chunkError;
+ return false;
+#endif
+ }
+ // Skip to next tool.
+ spTool += toolLen;
+ }
+
+ // Collected ``required'' information complete ?
+ if ( hasAddress && hasName && hasAuthor && hasCopyright && hasSongs && hasSpeed )
+ {
+ // Create the speed/clock setting table.
+ convertOldStyleSpeedToTables(oldStyleSpeed);
+ if (( info.loadAddr == 0 ) && ( dataLength != 0 ))
+ {
+ SmartPtr_sidtt<const uint_least8_t> spDataBuf((const uint_least8_t*)dataBuffer,dataLength);
+ spDataBuf += fileOffset;
+ info.loadAddr = endian_16(spDataBuf[1],spDataBuf[0]);
+ if ( !spDataBuf )
+ {
+ info.formatString = _sidtune_txt_dataCorruptError;
+ return false;
+ }
+ fileOffset += 2;
+ }
+ if ( info.initAddr == 0 )
+ {
+ info.initAddr = info.loadAddr;
+ }
+ info.numberOfInfoStrings = 3;
+ // We finally accept the input data.
+ info.formatString = _sidtune_txt_format;
+ return true;
+ }
+ else if ( hasAddress || hasName || hasAuthor || hasCopyright || hasSongs || hasSpeed )
+ {
+ // Something is missing (or damaged?).
+ info.formatString = _sidtune_txt_corruptError;
+ return false;
+ }
+ else
+ {
+ // No PlaySID conform info strings.
+ info.formatString = _sidtune_txt_noStringsError;
+ return false;
+ }
+}
diff --git a/sid/sidplay-libs-2.1.0/libsidplay/src/sidtune/InfoFile.cpp b/sid/sidplay-libs-2.1.0/libsidplay/src/sidtune/InfoFile.cpp
new file mode 100644
index 00000000..18e6d1b8
--- /dev/null
+++ b/sid/sidplay-libs-2.1.0/libsidplay/src/sidtune/InfoFile.cpp
@@ -0,0 +1,395 @@
+/*
+ * /home/ms/files/source/libsidtune/RCS/InfoFile.cpp,v
+ *
+ * SIDPLAY INFOFILE format support.
+ *
+ * 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 "config.h"
+
+#ifdef HAVE_EXCEPTIONS
+# include <new>
+#endif
+#include <iostream>
+#include <iomanip>
+#include <strstream>
+#include <ctype.h>
+#include <string.h>
+
+#include "SidTune.h"
+#include "SidTuneTools.h"
+#include "sidendian.h"
+
+
+const char text_format[] = "Raw plus SIDPLAY ASCII text file (SID)";
+
+const char text_truncatedError[] = "ERROR: SID file is truncated";
+const char text_noMemError[] = "ERROR: Not enough free memory";
+
+const char keyword_id[] = "SIDPLAY INFOFILE";
+
+const char keyword_name[] = "NAME="; // No white-space characters
+const char keyword_author[] = "AUTHOR="; // in these keywords, because
+const char keyword_copyright[] = "COPYRIGHT="; // we want to use a white-space
+const char keyword_released[] = "RELEASED="; // we want to use a white-space
+const char keyword_address[] = "ADDRESS="; // eating string stream to
+const char keyword_songs[] = "SONGS="; // parse most of the header.
+const char keyword_speed[] = "SPEED=";
+const char keyword_musPlayer[] = "SIDSONG=YES";
+const char keyword_reloc[] = "RELOC=";
+const char keyword_clock[] = "CLOCK=";
+const char keyword_sidModel[] = "SIDMODEL=";
+const char keyword_compatibility[] = "COMPATIBILITY=";
+
+const uint_least16_t sidMinFileSize = 1+sizeof(keyword_id); // Just to avoid a first segm.fault.
+const uint_least16_t parseChunkLen = 80; // Enough for all keywords incl. their values.
+
+
+bool SidTune::SID_fileSupport(const void* dataBuffer, uint_least32_t dataBufLen,
+ const void* sidBuffer, uint_least32_t sidBufLen)
+{
+ // Make sure SID buffer pointer is not zero.
+ // Check for a minimum file size. If it is smaller, we will not proceed.
+ if ((sidBuffer==0) || (sidBufLen<sidMinFileSize))
+ {
+ return false;
+ }
+
+ const char* pParseBuf = (const char*)sidBuffer;
+ // First line has to contain the exact identification string.
+ if ( SidTuneTools::myStrNcaseCmp( pParseBuf, keyword_id ) != 0 )
+ {
+ return false;
+ }
+ else
+ {
+ // At least the ID was found, so set a default error message.
+ info.formatString = text_truncatedError;
+
+ // Defaults.
+ fileOffset = 0; // no header in separate data file
+ info.sidChipBase1 = 0xd400;
+ info.sidChipBase2 = 0;
+ info.musPlayer = false;
+ info.numberOfInfoStrings = 0;
+ uint_least32_t oldStyleSpeed = 0;
+
+ // Flags for required entries.
+ bool hasAddress = false,
+ hasName = false,
+ hasAuthor = false,
+ hasReleased = false,
+ hasSongs = false,
+ hasSpeed = false;
+
+ // Using a temporary instance of an input string chunk.
+#ifdef HAVE_EXCEPTIONS
+ char* pParseChunk = new(std::nothrow) char[parseChunkLen+1];
+#else
+ char* pParseChunk = new char[parseChunkLen+1];
+#endif
+ if ( pParseChunk == 0 )
+ {
+ info.formatString = text_noMemError;
+ return false;
+ }
+
+ // Parse as long we have not collected all ``required'' entries.
+ //while ( !hasAddress || !hasName || !hasAuthor || !hasCopyright
+ // || !hasSongs || !hasSpeed )
+
+ // Above implementation is wrong, we need to get all known
+ // fields and then check if all ``required'' ones were found.
+ for (;;)
+ {
+ // Skip to next line. Leave loop, if none.
+ if (( pParseBuf = SidTuneTools::returnNextLine( pParseBuf )) == 0 )
+ {
+ break;
+ }
+ // And get a second pointer to the following line.
+ const char* pNextLine = SidTuneTools::returnNextLine( pParseBuf );
+ uint_least32_t restLen;
+ if ( pNextLine != 0 )
+ {
+ // Calculate number of chars between current pos and next line.
+ restLen = (uint_least32_t)(pNextLine - pParseBuf);
+ }
+ else
+ {
+ // Calculate number of chars between current pos and end of buf.
+ restLen = sidBufLen - (uint_least32_t)(pParseBuf - (char*)sidBuffer);
+ }
+ // Create whitespace eating (!) input string stream.
+ std::istrstream parseStream((char *) pParseBuf, restLen );
+ // A second one just for copying.
+ std::istrstream parseCopyStream((char *) pParseBuf, restLen );
+ if ( !parseStream || !parseCopyStream )
+ {
+ break;
+ }
+ // Now copy the next X characters except white-spaces.
+ for ( uint_least16_t i = 0; i < parseChunkLen; i++ )
+ {
+ char c;
+ parseCopyStream >> c;
+ pParseChunk[i] = c;
+ }
+ pParseChunk[parseChunkLen]=0;
+ // Now check for the possible keywords.
+ // ADDRESS
+ if ( SidTuneTools::myStrNcaseCmp( pParseChunk, keyword_address ) == 0 )
+ {
+ SidTuneTools::skipToEqu( parseStream );
+ info.loadAddr = (uint_least16_t)SidTuneTools::readHex( parseStream );
+ if ( !parseStream )
+ break;
+ info.initAddr = (uint_least16_t)SidTuneTools::readHex( parseStream );
+ if ( !parseStream )
+ break;
+ info.playAddr = (uint_least16_t)SidTuneTools::readHex( parseStream );
+ hasAddress = true;
+ }
+ // NAME
+ else if ( SidTuneTools::myStrNcaseCmp( pParseChunk, keyword_name ) == 0 )
+ {
+ SidTuneTools::copyStringValueToEOL(pParseBuf,&infoString[0][0],SIDTUNE_MAX_CREDIT_STRLEN);
+ info.infoString[0] = &infoString[0][0];
+ hasName = true;
+ }
+ // AUTHOR
+ else if ( SidTuneTools::myStrNcaseCmp( pParseChunk, keyword_author ) == 0 )
+ {
+ SidTuneTools::copyStringValueToEOL(pParseBuf,&infoString[1][0],SIDTUNE_MAX_CREDIT_STRLEN);
+ info.infoString[1] = &infoString[1][0];
+ hasAuthor = true;
+ }
+ // COPYRIGHT
+ else if ( SidTuneTools::myStrNcaseCmp( pParseChunk, keyword_copyright ) == 0 )
+ {
+ SidTuneTools::copyStringValueToEOL(pParseBuf,&infoString[2][0],SIDTUNE_MAX_CREDIT_STRLEN);
+ info.infoString[2] = &infoString[2][0];
+ hasReleased = true;
+ }
+ // RELEASED
+ else if ( SidTuneTools::myStrNcaseCmp( pParseChunk, keyword_released ) == 0 )
+ {
+ SidTuneTools::copyStringValueToEOL(pParseBuf,&infoString[2][0],SIDTUNE_MAX_CREDIT_STRLEN);
+ info.infoString[2] = &infoString[2][0];
+ hasReleased = true;
+ }
+ // SONGS
+ else if ( SidTuneTools::myStrNcaseCmp( pParseChunk, keyword_songs ) == 0 )
+ {
+ SidTuneTools::skipToEqu( parseStream );
+ info.songs = (uint_least16_t)SidTuneTools::readDec( parseStream );
+ info.startSong = (uint_least16_t)SidTuneTools::readDec( parseStream );
+ hasSongs = true;
+ }
+ // SPEED
+ else if ( SidTuneTools::myStrNcaseCmp( pParseChunk, keyword_speed ) == 0 )
+ {
+ SidTuneTools::skipToEqu( parseStream );
+ oldStyleSpeed = SidTuneTools::readHex(parseStream);
+ hasSpeed = true;
+ }
+ // SIDSONG
+ else if ( SidTuneTools::myStrNcaseCmp( pParseChunk, keyword_musPlayer ) == 0 )
+ {
+ info.musPlayer = true;
+ }
+ // RELOC
+ else if ( SidTuneTools::myStrNcaseCmp( pParseChunk, keyword_reloc ) == 0 )
+ {
+ info.relocStartPage = (uint_least8_t)SidTuneTools::readHex( parseStream );
+ if ( !parseStream )
+ break;
+ info.relocPages = (uint_least8_t)SidTuneTools::readHex( parseStream );
+ }
+ // CLOCK
+ else if ( SidTuneTools::myStrNcaseCmp( pParseChunk, keyword_clock ) == 0 )
+ {
+ char clock[8];
+ SidTuneTools::copyStringValueToEOL(pParseBuf,clock,sizeof(clock));
+ if ( SidTuneTools::myStrNcaseCmp( clock, "UNKNOWN" ) == 0 )
+ info.clockSpeed = SIDTUNE_CLOCK_UNKNOWN;
+ else if ( SidTuneTools::myStrNcaseCmp( clock, "PAL" ) == 0 )
+ info.clockSpeed = SIDTUNE_CLOCK_PAL;
+ else if ( SidTuneTools::myStrNcaseCmp( clock, "NTSC" ) == 0 )
+ info.clockSpeed = SIDTUNE_CLOCK_NTSC;
+ else if ( SidTuneTools::myStrNcaseCmp( clock, "ANY" ) == 0 )
+ info.clockSpeed = SIDTUNE_CLOCK_ANY;
+ }
+ // SIDMODEL
+ else if ( SidTuneTools::myStrNcaseCmp( pParseChunk, keyword_sidModel ) == 0 )
+ {
+ char model[8];
+ SidTuneTools::copyStringValueToEOL(pParseBuf,model,sizeof(model));
+ if ( SidTuneTools::myStrNcaseCmp( model, "UNKNOWN" ) == 0 )
+ info.sidModel = SIDTUNE_SIDMODEL_UNKNOWN;
+ else if ( SidTuneTools::myStrNcaseCmp( model, "6581" ) == 0 )
+ info.sidModel = SIDTUNE_SIDMODEL_6581;
+ else if ( SidTuneTools::myStrNcaseCmp( model, "8580" ) == 0 )
+ info.sidModel = SIDTUNE_SIDMODEL_8580;
+ else if ( SidTuneTools::myStrNcaseCmp( model, "ANY" ) == 0 )
+ info.sidModel = SIDTUNE_SIDMODEL_ANY;
+ }
+ // COMPATIBILITY
+ else if ( SidTuneTools::myStrNcaseCmp( pParseChunk, keyword_compatibility ) == 0 )
+ {
+ char comp[5];
+ SidTuneTools::copyStringValueToEOL(pParseBuf,comp,sizeof(comp));
+ if ( SidTuneTools::myStrNcaseCmp( comp, "C64" ) == 0 )
+ info.compatibility = SIDTUNE_COMPATIBILITY_C64;
+ else if ( SidTuneTools::myStrNcaseCmp( comp, "PSID" ) == 0 )
+ info.compatibility = SIDTUNE_COMPATIBILITY_PSID;
+ else if ( SidTuneTools::myStrNcaseCmp( comp, "R64" ) == 0 )
+ info.compatibility = SIDTUNE_COMPATIBILITY_R64;
+ }
+ };
+
+ delete[] pParseChunk;
+
+ // Again check for the ``required'' values.
+ if ( hasAddress || hasName || hasAuthor || hasReleased || hasSongs || hasSpeed )
+ {
+ // Check reserved fields to force real c64 compliance
+ if (info.compatibility == SIDTUNE_COMPATIBILITY_R64)
+ {
+ if (checkRealC64Info (oldStyleSpeed) == false)
+ return false;
+ }
+ // Create the speed/clock setting table.
+ convertOldStyleSpeedToTables(oldStyleSpeed, info.clockSpeed);
+ // loadAddr = 0 means, the address is stored in front of the C64 data.
+ // We cannot verify whether the dataBuffer contains valid data.
+ // All we want to know is whether the SID buffer is valid.
+ // If data is present, we access it (here to get the C64 load address).
+ if (info.loadAddr==0 && (dataBufLen>=(fileOffset+2)) && dataBuffer!=0)
+ {
+ const uint8_t* pDataBufCp = (const uint8_t*)dataBuffer + fileOffset;
+ info.loadAddr = endian_16( *(pDataBufCp + 1), *pDataBufCp );
+ fileOffset += 2; // begin of data
+ }
+ // Keep compatibility to PSID/SID.
+ if ( info.initAddr == 0 )
+ {
+ info.initAddr = info.loadAddr;
+ }
+ info.numberOfInfoStrings = 3;
+ // We finally accept the input data.
+ info.formatString = text_format;
+ return true;
+ }
+ else
+ {
+ // Something is missing (or damaged ?).
+ // Error string set above.
+ return false;
+ }
+ }
+}
+
+
+bool SidTune::SID_fileSupportSave( std::ofstream& toFile )
+{
+ toFile << keyword_id << std::endl
+ << keyword_address << std::hex << std::setw(4)
+ << std::setfill('0') << 0 << ','
+ << std::hex << std::setw(4) << info.initAddr << ","
+ << std::hex << std::setw(4) << info.playAddr << std::endl
+ << keyword_songs << std::dec << (int)info.songs << ","
+ << (int)info.startSong << std::endl;
+
+ uint_least32_t oldStyleSpeed = 0;
+ int maxBugSongs = ((info.songs <= 32) ? info.songs : 32);
+ for (int s = 0; s < maxBugSongs; s++)
+ {
+ if (songSpeed[s] == SIDTUNE_SPEED_CIA_1A)
+ {
+ oldStyleSpeed |= (1<<s);
+ }
+ }
+
+ toFile
+ << keyword_speed << std::hex << std::setw(8)
+ << oldStyleSpeed << std::endl
+ << keyword_name << info.infoString[0] << std::endl
+ << keyword_author << info.infoString[1] << std::endl
+ << keyword_released << info.infoString[2] << std::endl;
+ if ( info.musPlayer )
+ {
+ toFile << keyword_musPlayer << std::endl;
+ }
+ if ( info.relocStartPage )
+ {
+ toFile
+ << keyword_reloc << std::setfill('0')
+ << std::hex << std::setw(2) << (int) info.relocStartPage << ","
+ << std::hex << std::setw(2) << (int) info.relocPages << std::endl;
+ }
+ if ( info.clockSpeed != SIDTUNE_CLOCK_UNKNOWN )
+ {
+ toFile << keyword_clock;
+ switch (info.clockSpeed)
+ {
+ case SIDTUNE_CLOCK_PAL:
+ toFile << "PAL";
+ break;
+ case SIDTUNE_CLOCK_NTSC:
+ toFile << "NTSC";
+ break;
+ case SIDTUNE_CLOCK_ANY:
+ toFile << "ANY";
+ break;
+ }
+ toFile << std::endl;
+ }
+ if ( info.sidModel != SIDTUNE_SIDMODEL_UNKNOWN )
+ {
+ toFile << keyword_sidModel;
+ switch (info.sidModel)
+ {
+ case SIDTUNE_SIDMODEL_6581:
+ toFile << "6581";
+ break;
+ case SIDTUNE_SIDMODEL_8580:
+ toFile << "8580";
+ break;
+ case SIDTUNE_SIDMODEL_ANY:
+ toFile << "ANY";
+ break;
+ }
+ toFile << std::endl;
+ }
+ if ( info.compatibility == SIDTUNE_COMPATIBILITY_PSID )
+ {
+ toFile << keyword_compatibility << "C64" << std::endl;
+ }
+ else if ( info.compatibility == SIDTUNE_COMPATIBILITY_R64 )
+ {
+ toFile << keyword_compatibility << "R64" << std::endl;
+ }
+
+ if ( !toFile )
+ {
+ return false;
+ }
+ else
+ {
+ return true;
+ }
+}
diff --git a/sid/sidplay-libs-2.1.0/libsidplay/src/sidtune/MUS.cpp b/sid/sidplay-libs-2.1.0/libsidplay/src/sidtune/MUS.cpp
new file mode 100644
index 00000000..16ea8fe9
--- /dev/null
+++ b/sid/sidplay-libs-2.1.0/libsidplay/src/sidtune/MUS.cpp
@@ -0,0 +1,681 @@
+/*
+ * /home/ms/files/source/libsidtune/RCS/MUS.cpp,v
+ *
+ * Sidplayer and Stereo Sidplayer format support.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <string.h>
+
+#include "config.h"
+#include "SidTuneCfg.h"
+#include "SidTune.h"
+#include "sidendian.h"
+
+#ifdef HAVE_EXCEPTIONS
+# include <new>
+#endif
+
+static const char _sidtune_txt_format_mus[] = "C64 Sidplayer format (MUS)";
+static const char _sidtune_txt_format_str[] = "C64 Stereo Sidplayer format (MUS+STR)";
+static const char _sidtune_txt_notEnoughMemory[] = "ERROR: Not enough free memory";
+static const char _sidtune_txt_sizeExceeded[] = "ERROR: Total file size too large";
+
+static const uint_least16_t SIDTUNE_MUS_HLT_CMD = 0x14F;
+
+static const uint_least16_t SIDTUNE_MUS_DATA_ADDR = 0x0900;
+static const uint_least16_t SIDTUNE_SID1_BASE_ADDR = 0xd400;
+static const uint_least16_t SIDTUNE_SID2_BASE_ADDR = 0xd500;
+
+bool SidTune::MUS_fileSupport(Buffer_sidtt<const uint8_t>& musBuf,
+ Buffer_sidtt<const uint8_t>& strBuf)
+{
+ // Clear info strings.
+ for (int i = 0; i < SIDTUNE_MAX_CREDIT_STRINGS; i++)
+ infoString[i][0] = 0;
+
+ uint_least32_t voice3Index;
+ if ( !MUS_detect(musBuf.get(),musBuf.len(),voice3Index) )
+ return false;
+
+ // Voice3Index now is offset to text lines (uppercase Pet-strings).
+ SmartPtr_sidtt<const uint8_t> spPet(musBuf.get(),musBuf.len());
+ spPet += voice3Index;
+ {
+ for ( int line = 0; line < 5; line++ )
+ {
+ MUS_decodePetLine(spPet,infoString[line]);
+ info.infoString[line] = infoString[line];
+ }
+ }
+ info.numberOfInfoStrings = 5;
+
+ info.loadAddr = SIDTUNE_MUS_DATA_ADDR;
+ info.sidChipBase1 = SIDTUNE_SID1_BASE_ADDR;
+ info.songs = (info.startSong = 1);
+ info.musPlayer = true;
+
+ songSpeed[0] = SIDTUNE_SPEED_CIA_1A;
+#ifdef SIDTUNE_PSID2NG
+ clockSpeed[0] = SIDTUNE_CLOCK_ANY;
+#endif
+ fileOffset = 2; // data after load address
+
+ if ( !strBuf.isEmpty() )
+ {
+ if ( !MUS_detect(strBuf.get(),strBuf.len(),voice3Index) )
+ return false;
+
+ // Voice3Index now is offset to text lines (uppercase Pet-strings).
+ SmartPtr_sidtt<const uint8_t> spPet(strBuf.get(),strBuf.len());
+ spPet += voice3Index;
+ for ( int line = 5; line < 10; line++ )
+ {
+ MUS_decodePetLine(spPet,infoString[line]);
+ info.infoString[line] = infoString[line];
+ }
+ info.numberOfInfoStrings += 5;
+
+ info.sidChipBase2 = SIDTUNE_SID2_BASE_ADDR;
+ info.formatString = _sidtune_txt_format_str;
+ }
+ else
+ {
+ info.sidChipBase2 = 0;
+ info.formatString = _sidtune_txt_format_mus;
+ }
+ MUS_setPlayerAddress();
+
+ // Remove trailing empty lines.
+ const int lines = info.numberOfInfoStrings;
+ {
+ for ( int line = lines-1; line >= 0; line-- )
+ {
+ if (strlen(info.infoString[line]) == 0)
+ --info.numberOfInfoStrings;
+ else
+ break;
+ }
+ }
+
+ return true;
+}
+
+bool SidTune::MUS_detect(const void* buffer, const uint_least32_t bufLen,
+ uint_least32_t& voice3Index)
+{
+ SmartPtr_sidtt<const uint8_t> spMus((const uint8_t*)buffer,bufLen);
+ // Skip load address and 3x length entry.
+ uint_least32_t voice1Index = (2+3*2);
+ // Add length of voice 1 data.
+ voice1Index += endian_16(spMus[3],spMus[2]);
+ // Add length of voice 2 data.
+ uint_least32_t voice2Index = voice1Index + endian_16(spMus[5],spMus[4]);
+ // Add length of voice 3 data.
+ voice3Index = voice2Index + endian_16(spMus[7],spMus[6]);
+ return ((endian_16(spMus[voice1Index-2],spMus[voice1Index+1-2]) == SIDTUNE_MUS_HLT_CMD)
+ && (endian_16(spMus[voice2Index-2],spMus[voice2Index+1-2]) == SIDTUNE_MUS_HLT_CMD)
+ && (endian_16(spMus[voice3Index-2],spMus[voice3Index+1-2]) == SIDTUNE_MUS_HLT_CMD)
+ && spMus);
+}
+
+void SidTune::MUS_setPlayerAddress()
+{
+ if (info.sidChipBase2 == 0)
+ {
+ // Player #1.
+ info.initAddr = 0xec60;
+ info.playAddr = 0xec80;
+ }
+ else
+ {
+ // Player #1 + #2.
+ info.initAddr = 0xfc90;
+ info.playAddr = 0xfc96;
+ }
+}
+
+static const char _sidtune_CHRtab[256] = // CHR$ conversion table (0x01 = no output)
+{
+ 0x0, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0xd, 0x1, 0x1,
+ 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1,
+ 0x20,0x21, 0x1,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,
+ 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
+ 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,
+ 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x5b,0x24,0x5d,0x20,0x20,
+ // alternative: CHR$(92=0x5c) => ISO Latin-1(0xa3)
+ 0x2d,0x23,0x7c,0x2d,0x2d,0x2d,0x2d,0x7c,0x7c,0x5c,0x5c,0x2f,0x5c,0x5c,0x2f,0x2f,
+ 0x5c,0x23,0x5f,0x23,0x7c,0x2f,0x58,0x4f,0x23,0x7c,0x23,0x2b,0x7c,0x7c,0x26,0x5c,
+ // 0x80-0xFF
+ 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1,
+ 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1,
+ 0x20,0x7c,0x23,0x2d,0x2d,0x7c,0x23,0x7c,0x23,0x2f,0x7c,0x7c,0x2f,0x5c,0x5c,0x2d,
+ 0x2f,0x2d,0x2d,0x7c,0x7c,0x7c,0x7c,0x2d,0x2d,0x2d,0x2f,0x5c,0x5c,0x2f,0x2f,0x23,
+ 0x2d,0x23,0x7c,0x2d,0x2d,0x2d,0x2d,0x7c,0x7c,0x5c,0x5c,0x2f,0x5c,0x5c,0x2f,0x2f,
+ 0x5c,0x23,0x5f,0x23,0x7c,0x2f,0x58,0x4f,0x23,0x7c,0x23,0x2b,0x7c,0x7c,0x26,0x5c,
+ 0x20,0x7c,0x23,0x2d,0x2d,0x7c,0x23,0x7c,0x23,0x2f,0x7c,0x7c,0x2f,0x5c,0x5c,0x2d,
+ 0x2f,0x2d,0x2d,0x7c,0x7c,0x7c,0x7c,0x2d,0x2d,0x2d,0x2f,0x5c,0x5c,0x2f,0x2f,0x23
+};
+
+int SidTune::MUS_decodePetLine(SmartPtr_sidtt<const uint8_t>& spPet, char* dest)
+{
+ int count = 0;
+ char c;
+ do
+ {
+ c = _sidtune_CHRtab[*spPet]; // ASCII CHR$ conversion
+ if ((c>=0x20) && (count<=31))
+ {
+ dest[count++] = c; // copy to info string
+ }
+ // If character is 0x9d (left arrow key) then move back.
+ if ((*spPet==0x9d) && (count>=0))
+ {
+ count--;
+ }
+ spPet++;
+ }
+ while ( !((c==0x0D)||(c==0x00)||spPet.fail()) );
+ return count;
+}
+
+static const uint8_t _sidtune_sidplayer1[] =
+{
+ 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x61, 0xe1, 0x60, 0x01, 0x02, 0x04, 0x00, 0x07, 0x0e, 0x02, 0x02, 0xfe, 0x02, 0x02, 0xfe,
+ 0xfe, 0x00, 0x01, 0x00, 0xff, 0x00, 0x02, 0x04, 0x05, 0x07, 0x09, 0x0b, 0x1e, 0x18, 0x8b, 0x7e,
+ 0xfa, 0x06, 0xac, 0xf3, 0xe6, 0x8f, 0xf8, 0x2e, 0x86, 0x8e, 0x96, 0x9f, 0xa8, 0xb3, 0xbd, 0xc8,
+ 0xd4, 0xe1, 0xee, 0xfd, 0x8c, 0x78, 0x64, 0x50, 0x3c, 0x28, 0x14, 0x00, 0x00, 0x02, 0x03, 0x05,
+ 0x07, 0x08, 0x0a, 0x0c, 0x0d, 0x0f, 0x11, 0x12, 0x00, 0xe0, 0x00, 0x05, 0x0a, 0x0f, 0xf9, 0x00,
+ 0xf5, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00, 0x30, 0x00, 0x00, 0x40, 0x00, 0x00,
+ 0x50, 0x00, 0x00, 0x60, 0x00, 0x00, 0x70, 0x00, 0x00, 0x80, 0x00, 0x00, 0x90, 0x00, 0x00, 0xa0,
+ 0x00, 0xa9, 0x00, 0x8d, 0x00, 0xe0, 0xa2, 0x95, 0xa0, 0x42, 0xad, 0xa6, 0x02, 0xf0, 0x04, 0xa2,
+ 0x25, 0xa0, 0x40, 0x8e, 0x5b, 0xe1, 0x8c, 0x5c, 0xe1, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea,
+ 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea,
+ 0xea, 0x60, 0xa9, 0x00, 0x8d, 0x00, 0xe0, 0x86, 0x61, 0x84, 0x62, 0xa0, 0xbc, 0x99, 0x00, 0xe0,
+ 0x88, 0xd0, 0xfa, 0xa0, 0x72, 0x99, 0xbc, 0xe0, 0x88, 0xd0, 0xfa, 0x8d, 0x15, 0xd4, 0x8d, 0x16,
+ 0xd4, 0xa9, 0x08, 0x8d, 0x25, 0xe0, 0x8d, 0x17, 0xd4, 0x8d, 0x26, 0xe0, 0x8d, 0x18, 0xd4, 0xa9,
+ 0x90, 0x8d, 0x27, 0xe0, 0xa9, 0x60, 0x8d, 0x28, 0xe0, 0xa9, 0x0c, 0x8d, 0x29, 0xe0, 0xad, 0x5b,
+ 0xe1, 0x8d, 0x2d, 0xe0, 0xad, 0x5c, 0xe1, 0x8d, 0x2e, 0xe0, 0xa9, 0xff, 0x8d, 0xcc, 0xe0, 0xa9,
+ 0xd4, 0x85, 0x64, 0xa2, 0x02, 0xa9, 0xff, 0x9d, 0x0b, 0xe0, 0xa9, 0x01, 0x9d, 0x30, 0xe0, 0x9d,
+ 0x2a, 0xe0, 0x8a, 0x9d, 0x33, 0xe0, 0x9d, 0xae, 0xe0, 0xa9, 0x04, 0x9d, 0x39, 0xe0, 0xbd, 0xa8,
+ 0xe1, 0x9d, 0xba, 0xe0, 0xa9, 0x5b, 0x9d, 0x7e, 0xe0, 0xbd, 0x65, 0xe1, 0x85, 0x63, 0xa9, 0x00,
+ 0xa8, 0x91, 0x63, 0xc8, 0x91, 0x63, 0xc8, 0x91, 0x63, 0xa9, 0x08, 0x9d, 0x17, 0xe0, 0x9d, 0x9c,
+ 0xe0, 0xc8, 0x91, 0x63, 0xc8, 0x91, 0x63, 0xa9, 0x40, 0x9d, 0x1a, 0xe0, 0x91, 0x63, 0xa9, 0x20,
+ 0x9d, 0x1d, 0xe0, 0xc8, 0x91, 0x63, 0xa9, 0xf5, 0x9d, 0x20, 0xe0, 0xc8, 0x91, 0x63, 0xca, 0x10,
+ 0xa4, 0x8a, 0xa2, 0x17, 0x9d, 0x3e, 0xe1, 0xca, 0x10, 0xfa, 0xa5, 0x61, 0x18, 0x69, 0x06, 0x85,
+ 0x63, 0xa9, 0x00, 0xaa, 0xa8, 0x65, 0x62, 0x85, 0x64, 0x9d, 0xab, 0xe0, 0x9d, 0xb4, 0xe0, 0xa5,
+ 0x63, 0x9d, 0xa8, 0xe0, 0x9d, 0xb1, 0xe0, 0x18, 0x71, 0x61, 0x85, 0x63, 0xa5, 0x64, 0xc8, 0x71,
+ 0x61, 0xc8, 0xe8, 0xe0, 0x03, 0xd0, 0xe0, 0xa6, 0x63, 0xa8, 0x60, 0xa9, 0x00, 0x8d, 0x04, 0xd4,
+ 0x8d, 0x0b, 0xd4, 0x8d, 0x12, 0xd4, 0x8d, 0x01, 0xd4, 0x8d, 0x08, 0xd4, 0x8d, 0x0f, 0xd4, 0xa9,
+ 0x08, 0x8d, 0x17, 0xd4, 0xad, 0x5b, 0xe1, 0x8d, 0x04, 0xdc, 0xad, 0x5c, 0xe1, 0x8d, 0x05, 0xdc,
+ 0x60, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0x60,
+ 0xa9, 0x08, 0x8d, 0x00, 0xe0, 0x6c, 0x5d, 0xe1, 0xea, 0xea, 0xea, 0xad, 0x00, 0xe0, 0x30, 0xf0,
+ 0x09, 0x80, 0xa8, 0x29, 0x07, 0xf0, 0xee, 0xd8, 0x8c, 0x00, 0xe0, 0xea, 0xa5, 0xfb, 0x8d, 0x56,
+ 0xe1, 0xa5, 0xfc, 0x8d, 0x57, 0xe1, 0xa5, 0xfd, 0x8d, 0x58, 0xe1, 0xa5, 0xfe, 0x8d, 0x59, 0xe1,
+ 0xa5, 0xff, 0x8d, 0x5a, 0xe1, 0xad, 0x23, 0xe0, 0x18, 0x6d, 0xd9, 0xe0, 0x48, 0x29, 0x07, 0xa8,
+ 0xad, 0xdc, 0xe0, 0x69, 0x00, 0x85, 0xff, 0x68, 0x46, 0xff, 0x6a, 0x46, 0xff, 0x6a, 0x46, 0xff,
+ 0x6a, 0x18, 0x6d, 0x24, 0xe0, 0x8c, 0x15, 0xd4, 0x8d, 0x16, 0xd4, 0xad, 0x25, 0xe0, 0x8d, 0x17,
+ 0xd4, 0xad, 0x26, 0xe0, 0x8d, 0x18, 0xd4, 0xa9, 0xd4, 0x85, 0xfc, 0xa2, 0x00, 0xad, 0x00, 0xe0,
+ 0x3d, 0x62, 0xe1, 0xf0, 0x51, 0xbd, 0x65, 0xe1, 0x85, 0xfb, 0xbd, 0x0e, 0xe0, 0x18, 0x7d, 0x51,
+ 0xe0, 0xa8, 0xbd, 0x11, 0xe0, 0x7d, 0x54, 0xe0, 0x48, 0x98, 0x18, 0x7d, 0xcd, 0xe0, 0xa0, 0x00,
+ 0x91, 0xfb, 0x68, 0x7d, 0xd0, 0xe0, 0xc8, 0x91, 0xfb, 0xbd, 0x14, 0xe0, 0x18, 0x7d, 0x69, 0xe0,
+ 0x85, 0xff, 0xbd, 0x17, 0xe0, 0x7d, 0x6c, 0xe0, 0x48, 0xa5, 0xff, 0x18, 0x7d, 0xd3, 0xe0, 0xc8,
+ 0x91, 0xfb, 0x68, 0x7d, 0xd6, 0xe0, 0xc8, 0x91, 0xfb, 0xbd, 0x1d, 0xe0, 0xc8, 0xc8, 0x91, 0xfb,
+ 0xbd, 0x20, 0xe0, 0xc8, 0x91, 0xfb, 0xe8, 0xe0, 0x03, 0xd0, 0xa2, 0xac, 0x1a, 0xe0, 0xae, 0x1b,
+ 0xe0, 0xad, 0x1c, 0xe0, 0x8c, 0x04, 0xd4, 0x8e, 0x0b, 0xd4, 0x8d, 0x12, 0xd4, 0xae, 0x2d, 0xe0,
+ 0xac, 0x2e, 0xe0, 0x8e, 0x04, 0xdc, 0x8c, 0x05, 0xdc, 0xad, 0x1b, 0xd4, 0x8d, 0xbe, 0xe0, 0xad,
+ 0x1c, 0xd4, 0x8d, 0xbf, 0xe0, 0xa2, 0x00, 0xad, 0x00, 0xe0, 0x3d, 0x62, 0xe1, 0xf0, 0x10, 0x8e,
+ 0x2f, 0xe0, 0x20, 0x36, 0xe5, 0xad, 0x00, 0xe0, 0x29, 0x78, 0xf0, 0x03, 0x4c, 0x0c, 0xe5, 0xe8,
+ 0xe0, 0x03, 0xd0, 0xe3, 0xad, 0xc9, 0xe0, 0xd0, 0x52, 0xad, 0xca, 0xe0, 0x0d, 0xcb, 0xe0, 0xf0,
+ 0x78, 0xad, 0xdf, 0xe0, 0xd0, 0x28, 0xad, 0xca, 0xe0, 0xf0, 0x28, 0x18, 0x6d, 0xbd, 0xe0, 0xb0,
+ 0x07, 0xcd, 0xcc, 0xe0, 0x90, 0x60, 0xf0, 0x5e, 0xa9, 0x00, 0x8d, 0xdf, 0xe0, 0xad, 0xcb, 0xe0,
+ 0xf0, 0x54, 0xee, 0xdf, 0xe0, 0xad, 0xbd, 0xe0, 0xed, 0xcb, 0xe0, 0x4c, 0xb4, 0xe4, 0xad, 0xcb,
+ 0xe0, 0xf0, 0xd3, 0xad, 0xbd, 0xe0, 0x38, 0xed, 0xcb, 0xe0, 0xb0, 0x3a, 0xa9, 0x00, 0x8d, 0xdf,
+ 0xe0, 0xad, 0xca, 0xe0, 0xd0, 0x30, 0xee, 0xdf, 0xe0, 0xd0, 0x28, 0xce, 0xe0, 0xe0, 0xd0, 0x29,
+ 0xad, 0xdf, 0xe0, 0xd0, 0x11, 0xee, 0xdf, 0xe0, 0xad, 0xcb, 0xe0, 0xd0, 0x02, 0xa9, 0x20, 0x8d,
+ 0xe0, 0xe0, 0xa9, 0x00, 0xf0, 0x10, 0xce, 0xdf, 0xe0, 0xad, 0xca, 0xe0, 0xd0, 0x02, 0xa9, 0x20,
+ 0x8d, 0xe0, 0xe0, 0xad, 0xcc, 0xe0, 0x8d, 0xbd, 0xe0, 0xa2, 0x00, 0xbd, 0xc3, 0xe0, 0xf0, 0x44,
+ 0xa9, 0x00, 0x85, 0xff, 0xbc, 0xc0, 0xe0, 0xb9, 0xbd, 0xe0, 0xbc, 0xc6, 0xe0, 0xf0, 0x0e, 0x30,
+ 0x08, 0x0a, 0x26, 0xff, 0x88, 0xd0, 0xfa, 0xf0, 0x04, 0x4a, 0xc8, 0xd0, 0xfc, 0xbc, 0xc3, 0xe0,
+ 0x88, 0xd0, 0x0b, 0x9d, 0xcd, 0xe0, 0xa5, 0xff, 0x9d, 0xd0, 0xe0, 0x4c, 0x02, 0xe5, 0x88, 0xd0,
+ 0x0b, 0x9d, 0xd3, 0xe0, 0xa5, 0xff, 0x9d, 0xd6, 0xe0, 0x4c, 0x02, 0xe5, 0x8d, 0xd9, 0xe0, 0xa5,
+ 0xff, 0x8d, 0xdc, 0xe0, 0xe8, 0xe0, 0x03, 0xd0, 0xb2, 0xad, 0x00, 0xe0, 0x29, 0x7f, 0x8d, 0x00,
+ 0xe0, 0xad, 0x56, 0xe1, 0x85, 0xfb, 0xad, 0x57, 0xe1, 0x85, 0xfc, 0xad, 0x58, 0xe1, 0x85, 0xfd,
+ 0xad, 0x59, 0xe1, 0x85, 0xfe, 0xad, 0x5a, 0xe1, 0x85, 0xff, 0x6c, 0x5d, 0xe1, 0xbd, 0x60, 0xe0,
+ 0xd0, 0x03, 0x4c, 0x9f, 0xe6, 0x4c, 0xba, 0xe5, 0xde, 0x30, 0xe0, 0xd0, 0x03, 0x4c, 0xa0, 0xe6,
+ 0xbd, 0x36, 0xe0, 0x30, 0xe8, 0xd0, 0x1a, 0xbd, 0x3f, 0xe0, 0xf0, 0x05, 0xde, 0x3f, 0xe0, 0xd0,
+ 0x10, 0xbd, 0x39, 0xe0, 0xdd, 0x30, 0xe0, 0x90, 0x08, 0xbd, 0x1a, 0xe0, 0x29, 0xfe, 0x9d, 0x1a,
+ 0xe0, 0xbd, 0x42, 0xe0, 0xf0, 0x56, 0x0a, 0xbd, 0x0e, 0xe0, 0xb0, 0x1d, 0x7d, 0x45, 0xe0, 0x9d,
+ 0x0e, 0xe0, 0xa8, 0xbd, 0x11, 0xe0, 0x7d, 0x48, 0xe0, 0x9d, 0x11, 0xe0, 0x48, 0x98, 0xdd, 0x8d,
+ 0xe0, 0x68, 0xfd, 0x90, 0xe0, 0xb0, 0x1f, 0x90, 0x2e, 0xfd, 0x45, 0xe0, 0x9d, 0x0e, 0xe0, 0xbd,
+ 0x11, 0xe0, 0xfd, 0x48, 0xe0, 0x9d, 0x11, 0xe0, 0xbd, 0x8d, 0xe0, 0xdd, 0x0e, 0xe0, 0xbd, 0x90,
+ 0xe0, 0xfd, 0x11, 0xe0, 0x90, 0x11, 0xbd, 0x8d, 0xe0, 0x9d, 0x0e, 0xe0, 0xbd, 0x90, 0xe0, 0x9d,
+ 0x11, 0xe0, 0xa9, 0x00, 0x9d, 0x42, 0xe0, 0xbd, 0x60, 0xe0, 0xf0, 0x55, 0xbd, 0x4b, 0xe0, 0xf0,
+ 0x4b, 0xa0, 0x00, 0xde, 0x4e, 0xe0, 0xd0, 0x31, 0xbd, 0x51, 0xe0, 0x1d, 0x54, 0xe0, 0xd0, 0x1b,
+ 0xbd, 0x5d, 0xe0, 0x9d, 0x57, 0xe0, 0x9d, 0x4e, 0xe0, 0xbd, 0x4b, 0xe0, 0x0a, 0xbd, 0x5a, 0xe0,
+ 0x90, 0x04, 0x49, 0xff, 0x69, 0x00, 0x9d, 0x4b, 0xe0, 0xd0, 0x10, 0xbd, 0x57, 0xe0, 0x9d, 0x4e,
+ 0xe0, 0x98, 0x38, 0xfd, 0x4b, 0xe0, 0x9d, 0x4b, 0xe0, 0xc9, 0x00, 0x10, 0x01, 0x88, 0x18, 0x7d,
+ 0x51, 0xe0, 0x9d, 0x51, 0xe0, 0x98, 0x7d, 0x54, 0xe0, 0x9d, 0x54, 0xe0, 0xbd, 0x36, 0xe0, 0x30,
+ 0x15, 0xbd, 0x93, 0xe0, 0xf0, 0x10, 0x18, 0x7d, 0x14, 0xe0, 0x9d, 0x14, 0xe0, 0xbd, 0x96, 0xe0,
+ 0x7d, 0x17, 0xe0, 0x9d, 0x17, 0xe0, 0xbd, 0x63, 0xe0, 0xf0, 0x4b, 0xa0, 0x00, 0xde, 0x66, 0xe0,
+ 0xd0, 0x31, 0xbd, 0x69, 0xe0, 0x1d, 0x6c, 0xe0, 0xd0, 0x1b, 0xbd, 0x72, 0xe0, 0x9d, 0x6f, 0xe0,
+ 0x9d, 0x66, 0xe0, 0xbd, 0x63, 0xe0, 0x0a, 0xbd, 0x75, 0xe0, 0x90, 0x04, 0x49, 0xff, 0x69, 0x00,
+ 0x9d, 0x63, 0xe0, 0xd0, 0x10, 0xbd, 0x6f, 0xe0, 0x9d, 0x66, 0xe0, 0x98, 0x38, 0xfd, 0x63, 0xe0,
+ 0x9d, 0x63, 0xe0, 0xc9, 0x00, 0x10, 0x01, 0x88, 0x18, 0x7d, 0x69, 0xe0, 0x9d, 0x69, 0xe0, 0x98,
+ 0x7d, 0x6c, 0xe0, 0x9d, 0x6c, 0xe0, 0xbd, 0x36, 0xe0, 0x10, 0x03, 0x4c, 0x9f, 0xe6, 0xa0, 0x00,
+ 0xbd, 0xa2, 0xe0, 0xf0, 0x1c, 0x10, 0x01, 0xc8, 0x18, 0x6d, 0x23, 0xe0, 0x48, 0x29, 0x07, 0x8d,
+ 0x23, 0xe0, 0x68, 0x6a, 0x4a, 0x4a, 0x18, 0x79, 0xa6, 0xe1, 0x18, 0x6d, 0x24, 0xe0, 0x8d, 0x24,
+ 0xe0, 0x60, 0xbd, 0xa8, 0xe0, 0x85, 0xfd, 0xbd, 0xab, 0xe0, 0x85, 0xfe, 0xd0, 0x04, 0x60, 0x20,
+ 0x98, 0xe8, 0xad, 0x00, 0xe0, 0x3d, 0x62, 0xe1, 0xf0, 0xf4, 0xa0, 0x00, 0xb1, 0xfd, 0x85, 0xff,
+ 0xc8, 0xb1, 0xfd, 0xa8, 0xa5, 0xfd, 0x18, 0x69, 0x02, 0x85, 0xfd, 0x9d, 0xa8, 0xe0, 0xa5, 0xfe,
+ 0x69, 0x00, 0x85, 0xfe, 0x9d, 0xab, 0xe0, 0xa5, 0xff, 0x29, 0x03, 0xd0, 0xd2, 0xbd, 0x8d, 0xe0,
+ 0x9d, 0x0e, 0xe0, 0xbd, 0x90, 0xe0, 0x9d, 0x11, 0xe0, 0xa5, 0xff, 0x9d, 0x05, 0xe0, 0x98, 0x9d,
+ 0x02, 0xe0, 0x29, 0x07, 0xa8, 0xb9, 0x67, 0xe1, 0x8d, 0x6f, 0xe1, 0xbd, 0x02, 0xe0, 0x29, 0x38,
+ 0x4a, 0x4a, 0x4a, 0x7d, 0x81, 0xe0, 0x85, 0xfd, 0xbd, 0x02, 0xe0, 0x29, 0xc0, 0x0a, 0x2a, 0x2a,
+ 0xa8, 0xb9, 0x6f, 0xe1, 0x85, 0xfe, 0xbd, 0x02, 0xe0, 0x29, 0x07, 0xf0, 0x62, 0xa8, 0xb9, 0x72,
+ 0xe1, 0x65, 0xfe, 0x18, 0x7d, 0x84, 0xe0, 0x10, 0x05, 0x18, 0x69, 0x0c, 0xe6, 0xfd, 0xc9, 0x0c,
+ 0x90, 0x04, 0xe9, 0x0c, 0xc6, 0xfd, 0x85, 0xfe, 0xa8, 0xb9, 0x86, 0xe1, 0x85, 0xff, 0xb9, 0x7a,
+ 0xe1, 0xa4, 0xfd, 0x88, 0x30, 0x06, 0x46, 0xff, 0x6a, 0x88, 0x10, 0xfa, 0x18, 0x7d, 0x87, 0xe0,
+ 0x9d, 0x8d, 0xe0, 0xa5, 0xff, 0x7d, 0x8a, 0xe0, 0x9d, 0x90, 0xe0, 0xbd, 0x05, 0xe0, 0xd0, 0x03,
+ 0x4c, 0xa0, 0xe6, 0xbd, 0x45, 0xe0, 0x1d, 0x48, 0xe0, 0xf0, 0x16, 0xbd, 0x0e, 0xe0, 0xdd, 0x8d,
+ 0xe0, 0xbd, 0x11, 0xe0, 0xfd, 0x90, 0xe0, 0xa9, 0xfe, 0x6a, 0x9d, 0x42, 0xe0, 0x90, 0x11, 0xf0,
+ 0x4a, 0x9d, 0x42, 0xe0, 0xbd, 0x8d, 0xe0, 0x9d, 0x0e, 0xe0, 0xbd, 0x90, 0xe0, 0x9d, 0x11, 0xe0,
+ 0xbd, 0x36, 0xe0, 0x0a, 0xd0, 0x35, 0xbd, 0x93, 0xe0, 0xf0, 0x0c, 0xbd, 0x99, 0xe0, 0x9d, 0x14,
+ 0xe0, 0xbd, 0x9c, 0xe0, 0x9d, 0x17, 0xe0, 0xbd, 0x9f, 0xe0, 0xf0, 0x0f, 0xa4, 0xfd, 0x18, 0x79,
+ 0x92, 0xe1, 0xa4, 0xfe, 0x18, 0x79, 0x9a, 0xe1, 0x18, 0x90, 0x08, 0xbd, 0xa2, 0xe0, 0xf0, 0x0b,
+ 0xbd, 0xa5, 0xe0, 0x8d, 0x24, 0xe0, 0xa9, 0x00, 0x8d, 0x23, 0xe0, 0xbd, 0x3c, 0xe0, 0x9d, 0x3f,
+ 0xe0, 0xbd, 0x05, 0xe0, 0x29, 0x40, 0x9d, 0x36, 0xe0, 0xbd, 0x05, 0xe0, 0x4a, 0x4a, 0x29, 0x07,
+ 0xd0, 0x30, 0xbd, 0x05, 0xe0, 0x30, 0x14, 0xad, 0x27, 0xe0, 0x29, 0x3c, 0xd0, 0x1e, 0xad, 0x27,
+ 0xe0, 0x0a, 0x2a, 0x2a, 0xd0, 0x02, 0xa9, 0x04, 0x4c, 0x70, 0xe8, 0xad, 0x28, 0xe0, 0xf0, 0x0c,
+ 0x29, 0x3f, 0xd0, 0x08, 0xad, 0x28, 0xe0, 0x0a, 0x2a, 0x2a, 0xd0, 0x66, 0xa9, 0x10, 0x8d, 0x00,
+ 0xe0, 0x60, 0xc9, 0x01, 0xd0, 0x13, 0xbd, 0x05, 0xe0, 0x29, 0x20, 0xd0, 0x06, 0xad, 0x29, 0xe0,
+ 0x4c, 0x70, 0xe8, 0xbd, 0x2a, 0xe0, 0x4c, 0x70, 0xe8, 0xa8, 0xbd, 0x05, 0xe0, 0x29, 0xa0, 0xc9,
+ 0x80, 0xf0, 0x30, 0x85, 0xff, 0x18, 0xad, 0x27, 0xe0, 0xd0, 0x01, 0x38, 0x88, 0x88, 0xf0, 0x06,
+ 0x6a, 0xb0, 0x4e, 0x88, 0xd0, 0xfa, 0xa4, 0xff, 0x85, 0xff, 0xf0, 0x26, 0x46, 0xff, 0xb0, 0x41,
+ 0xf0, 0x42, 0x65, 0xff, 0xb0, 0x3e, 0xc8, 0x10, 0x19, 0x46, 0xff, 0xb0, 0x34, 0x65, 0xff, 0x90,
+ 0x11, 0xb0, 0x31, 0xad, 0x28, 0xe0, 0xf0, 0x29, 0x88, 0x88, 0xf0, 0x06, 0x4a, 0xb0, 0x22, 0x88,
+ 0xd0, 0xfa, 0x9d, 0x30, 0xe0, 0xbd, 0x1a, 0xe0, 0x29, 0xf6, 0x9d, 0x1a, 0xe0, 0x38, 0xbd, 0x02,
+ 0xe0, 0x29, 0x07, 0xd0, 0x03, 0x7e, 0x36, 0xe0, 0xbd, 0x1a, 0xe0, 0x69, 0x00, 0x9d, 0x1a, 0xe0,
+ 0x60, 0xa9, 0x10, 0x2c, 0xa9, 0x18, 0x8d, 0x00, 0xe0, 0x60, 0x98, 0x48, 0xa5, 0xff, 0x4a, 0x90,
+ 0x03, 0x4c, 0x42, 0xea, 0x4a, 0x4a, 0xb0, 0x1e, 0x4a, 0xb0, 0x0e, 0x9d, 0x9c, 0xe0, 0x9d, 0x17,
+ 0xe0, 0x68, 0x9d, 0x99, 0xe0, 0x9d, 0x14, 0xe0, 0x60, 0x4a, 0x90, 0x02, 0x09, 0xf8, 0x9d, 0x8a,
+ 0xe0, 0x68, 0x9d, 0x87, 0xe0, 0x60, 0x4a, 0xb0, 0x03, 0x4c, 0x4a, 0xe9, 0x4a, 0xb0, 0x61, 0x4a,
+ 0xb0, 0x0f, 0xd0, 0x08, 0x68, 0x9d, 0xa5, 0xe0, 0x8d, 0x24, 0xe0, 0x60, 0x68, 0x9d, 0x3c, 0xe0,
+ 0x60, 0xd0, 0x48, 0x68, 0x9d, 0x7e, 0xe0, 0xc9, 0x5b, 0xf0, 0x33, 0xa8, 0x4a, 0x4a, 0x4a, 0x38,
+ 0xe9, 0x0b, 0x18, 0x7d, 0x84, 0xe0, 0x30, 0x0c, 0xc9, 0x0c, 0x90, 0x11, 0xe9, 0x0c, 0xde, 0x81,
+ 0xe0, 0x4c, 0x0b, 0xe9, 0xc9, 0xf5, 0xb0, 0x05, 0x69, 0x0c, 0xfe, 0x81, 0xe0, 0x9d, 0x84, 0xe0,
+ 0x98, 0x29, 0x07, 0x38, 0xe9, 0x03, 0x18, 0x7d, 0x81, 0xe0, 0x9d, 0x81, 0xe0, 0x60, 0xbd, 0x78,
+ 0xe0, 0x9d, 0x81, 0xe0, 0xbd, 0x7b, 0xe0, 0x9d, 0x84, 0xe0, 0x60, 0x68, 0x9d, 0xc6, 0xe0, 0x60,
+ 0x4a, 0xb0, 0x08, 0x9d, 0x0b, 0xe0, 0x68, 0x9d, 0x08, 0xe0, 0x60, 0x4a, 0x6a, 0x6a, 0x6d, 0x5b,
+ 0xe1, 0x8d, 0x2d, 0xe0, 0x68, 0x6d, 0x5c, 0xe1, 0x8d, 0x2e, 0xe0, 0x60, 0x4a, 0x90, 0x03, 0x4c,
+ 0xd3, 0xe9, 0x4a, 0xb0, 0x40, 0x4a, 0xb0, 0x17, 0x4a, 0xb0, 0x0f, 0x68, 0x8d, 0x27, 0xe0, 0x4a,
+ 0x4a, 0x4a, 0xa8, 0xb9, 0xaf, 0xe1, 0x8d, 0x28, 0xe0, 0x60, 0x68, 0x9d, 0x5d, 0xe0, 0x60, 0x4a,
+ 0xb0, 0x05, 0x68, 0x8d, 0x01, 0xe0, 0x60, 0x68, 0xf0, 0x11, 0x9d, 0x75, 0xe0, 0xbc, 0x63, 0xe0,
+ 0xd0, 0x08, 0x9d, 0x63, 0xe0, 0xa9, 0x01, 0x9d, 0x66, 0xe0, 0x60, 0x9d, 0x63, 0xe0, 0x9d, 0x69,
+ 0xe0, 0x9d, 0x6c, 0xe0, 0x60, 0x4a, 0xb0, 0x30, 0x4a, 0xb0, 0x05, 0x68, 0x9d, 0x39, 0xe0, 0x60,
+ 0x68, 0xa0, 0x00, 0x4a, 0x90, 0x02, 0xc8, 0x18, 0x48, 0x29, 0x07, 0x79, 0xac, 0xe1, 0x9d, 0x78,
+ 0xe0, 0x9d, 0x81, 0xe0, 0x68, 0x4a, 0x4a, 0x4a, 0x18, 0x79, 0xad, 0xe1, 0x9d, 0x7b, 0xe0, 0x9d,
+ 0x84, 0xe0, 0xa9, 0x5b, 0x9d, 0x7e, 0xe0, 0x60, 0x4a, 0xb0, 0x05, 0x68, 0x9d, 0xa2, 0xe0, 0x60,
+ 0x68, 0x8d, 0xcc, 0xe0, 0x60, 0x4a, 0xb0, 0x27, 0x4a, 0xb0, 0x0d, 0x4a, 0xb0, 0x05, 0x68, 0x8d,
+ 0x29, 0xe0, 0x60, 0x68, 0x9d, 0x9f, 0xe0, 0x60, 0x4a, 0xb0, 0x0f, 0x68, 0x9d, 0x93, 0xe0, 0xa0,
+ 0x00, 0x0a, 0x90, 0x01, 0x88, 0x98, 0x9d, 0x96, 0xe0, 0x60, 0x68, 0x9d, 0x72, 0xe0, 0x60, 0x4a,
+ 0xb0, 0x1c, 0x4a, 0xb0, 0x15, 0x68, 0x9d, 0xb7, 0xe0, 0xa5, 0xfd, 0x9d, 0xb1, 0xe0, 0xa5, 0xfe,
+ 0x9d, 0xb4, 0xe0, 0xbd, 0x33, 0xe0, 0x9d, 0xae, 0xe0, 0x60, 0x68, 0x6c, 0x5f, 0xe1, 0x4a, 0xb0,
+ 0x1e, 0x68, 0xd0, 0x0a, 0x9d, 0x4b, 0xe0, 0x9d, 0x51, 0xe0, 0x9d, 0x54, 0xe0, 0x60, 0x9d, 0x5a,
+ 0xe0, 0xbc, 0x4b, 0xe0, 0xd0, 0x08, 0x9d, 0x4b, 0xe0, 0xa9, 0x01, 0x9d, 0x4e, 0xe0, 0x60, 0x68,
+ 0x9d, 0x2a, 0xe0, 0x60, 0x4a, 0x90, 0x08, 0x9d, 0x48, 0xe0, 0x68, 0x9d, 0x45, 0xe0, 0x60, 0x68,
+ 0x4a, 0xb0, 0x61, 0x4a, 0xb0, 0x25, 0x4a, 0xb0, 0x05, 0x4a, 0xa0, 0xf0, 0xd0, 0x06, 0x0a, 0x0a,
+ 0x0a, 0x0a, 0xa0, 0x0f, 0x85, 0xff, 0x98, 0xb0, 0x09, 0x3d, 0x1d, 0xe0, 0x05, 0xff, 0x9d, 0x1d,
+ 0xe0, 0x60, 0x3d, 0x20, 0xe0, 0x05, 0xff, 0x9d, 0x20, 0xe0, 0x60, 0x4a, 0xb0, 0x38, 0x4a, 0xb0,
+ 0x64, 0x85, 0xff, 0xbd, 0xba, 0xe0, 0xdd, 0xa9, 0xe1, 0xf0, 0x54, 0xfe, 0xba, 0xe0, 0xa8, 0xa5,
+ 0xfd, 0x99, 0xe1, 0xe0, 0xa5, 0xfe, 0x99, 0xf0, 0xe0, 0xbd, 0x33, 0xe0, 0x99, 0x2f, 0xe1, 0xa4,
+ 0xff, 0xb9, 0x17, 0xe1, 0xf0, 0x36, 0x85, 0xfe, 0xb9, 0xff, 0xe0, 0x85, 0xfd, 0xb9, 0x3e, 0xe1,
+ 0x9d, 0x33, 0xe0, 0x60, 0xb0, 0x4b, 0x4a, 0xb0, 0x3c, 0xa8, 0xa5, 0xfd, 0x99, 0xff, 0xe0, 0xa5,
+ 0xfe, 0x99, 0x17, 0xe1, 0xbd, 0x33, 0xe0, 0x99, 0x3e, 0xe1, 0xbd, 0xba, 0xe0, 0xdd, 0xa9, 0xe1,
+ 0xf0, 0x0d, 0xfe, 0xba, 0xe0, 0xa8, 0xa9, 0x00, 0x99, 0xf0, 0xe0, 0x60, 0xa9, 0x30, 0x2c, 0xa9,
+ 0x28, 0x8d, 0x00, 0xe0, 0x60, 0x0a, 0x0a, 0x0a, 0x0a, 0x4d, 0x25, 0xe0, 0x29, 0xf0, 0x4d, 0x25,
+ 0xe0, 0x8d, 0x25, 0xe0, 0x60, 0x4d, 0x26, 0xe0, 0x29, 0x0f, 0x4d, 0x26, 0xe0, 0x8d, 0x26, 0xe0,
+ 0x60, 0x4a, 0xb0, 0x0b, 0x4a, 0xb0, 0x04, 0x8d, 0xca, 0xe0, 0x60, 0x8d, 0xcb, 0xe0, 0x60, 0x4a,
+ 0x90, 0x03, 0x4c, 0xa5, 0xeb, 0x4a, 0xa8, 0xf0, 0x21, 0x88, 0xf0, 0x34, 0x88, 0xf0, 0x42, 0x88,
+ 0xf0, 0x4a, 0x88, 0xf0, 0x52, 0x88, 0xf0, 0x5c, 0x88, 0xf0, 0x66, 0x88, 0xf0, 0x73, 0x29, 0x07,
+ 0x09, 0x10, 0xb0, 0x03, 0x4c, 0xb7, 0xea, 0x4c, 0x7f, 0xea, 0xac, 0x26, 0xe0, 0xb0, 0x07, 0xc8,
+ 0x98, 0x29, 0x0f, 0xd0, 0x07, 0x60, 0x98, 0x29, 0x0f, 0xf0, 0x04, 0x88, 0x8c, 0x26, 0xe0, 0x60,
+ 0xbd, 0x62, 0xe1, 0x49, 0xff, 0x2d, 0x25, 0xe0, 0x90, 0x03, 0x1d, 0x62, 0xe1, 0x8d, 0x25, 0xe0,
+ 0x60, 0xbd, 0x1a, 0xe0, 0x29, 0xfb, 0x90, 0x55, 0x09, 0x04, 0xb0, 0x51, 0xbd, 0x1a, 0xe0, 0x29,
+ 0xfd, 0x90, 0x4a, 0x09, 0x02, 0xb0, 0x46, 0xad, 0x25, 0xe0, 0x29, 0xf7, 0x90, 0x02, 0x09, 0x08,
+ 0x8d, 0x25, 0xe0, 0x60, 0xad, 0x26, 0xe0, 0x29, 0x7f, 0x90, 0x02, 0x09, 0x80, 0x8d, 0x26, 0xe0,
+ 0x60, 0x98, 0x8d, 0xbd, 0xe0, 0x8d, 0xdf, 0xe0, 0xc8, 0x8c, 0xe0, 0xe0, 0x2a, 0x8d, 0xc9, 0xe0,
+ 0x60, 0x98, 0x2a, 0x9d, 0x60, 0xe0, 0x60, 0x4a, 0xb0, 0x27, 0x4a, 0xb0, 0x14, 0xd0, 0x02, 0xa9,
+ 0x08, 0x0a, 0x0a, 0x0a, 0x0a, 0x5d, 0x1a, 0xe0, 0x29, 0xf0, 0x5d, 0x1a, 0xe0, 0x9d, 0x1a, 0xe0,
+ 0x60, 0x0a, 0x0a, 0x0a, 0x0a, 0x4d, 0x26, 0xe0, 0x29, 0x70, 0x4d, 0x26, 0xe0, 0x8d, 0x26, 0xe0,
+ 0x60, 0x4a, 0x90, 0x04, 0x9d, 0xc0, 0xe0, 0x60, 0xa8, 0xf0, 0x20, 0x88, 0xf0, 0x40, 0x88, 0xf0,
+ 0x63, 0x29, 0x03, 0x9d, 0xc3, 0xe0, 0xa9, 0x00, 0x9d, 0xcd, 0xe0, 0x9d, 0xd0, 0xe0, 0x9d, 0xd3,
+ 0xe0, 0x9d, 0xd6, 0xe0, 0x8d, 0xd9, 0xe0, 0x8d, 0xdc, 0xe0, 0x60, 0xbd, 0xb7, 0xe0, 0xf0, 0x05,
+ 0xde, 0xb7, 0xe0, 0xf0, 0x12, 0xbd, 0x33, 0xe0, 0xdd, 0xae, 0xe0, 0xd0, 0x0b, 0xbd, 0xb1, 0xe0,
+ 0x85, 0xfd, 0xbd, 0xb4, 0xe0, 0x85, 0xfe, 0x60, 0xa9, 0x38, 0x8d, 0x00, 0xe0, 0x60, 0xbd, 0xba,
+ 0xe0, 0xdd, 0xa8, 0xe1, 0xf0, 0x18, 0xde, 0xba, 0xe0, 0xa8, 0x88, 0xb9, 0xf0, 0xe0, 0xf0, 0x0d,
+ 0x85, 0xfe, 0xb9, 0xe1, 0xe0, 0x85, 0xfd, 0xb9, 0x2f, 0xe1, 0x9d, 0x33, 0xe0, 0x60, 0xa9, 0x20,
+ 0x8d, 0x00, 0xe0, 0x60, 0xad, 0x00, 0xe0, 0x5d, 0x62, 0xe1, 0x8d, 0x00, 0xe0, 0xa9, 0x01, 0x9d,
+ 0x30, 0xe0, 0x60, 0xad, 0x00, 0xe0, 0x29, 0x07, 0x8d, 0x81, 0xec, 0xd0, 0x03, 0x20, 0xe9, 0xe2,
+ 0x60, 0x00, 0xa2, 0x51, 0xa0, 0xec, 0x8e, 0x5d, 0xe1, 0x8c, 0x5e, 0xe1, 0x20, 0xcf, 0xe1, 0xa2,
+ 0x00, 0xa0, 0x09, 0x20, 0x00, 0xe2, 0xa9, 0x07, 0x8d, 0x00, 0xe0, 0x8d, 0x81, 0xec, 0x60, 0x00,
+ 0x00, 0x00, 0xa9, 0x00, 0x29, 0xff, 0xf0, 0xf6, 0x4c, 0x29, 0xe3, 0xa9, 0x07, 0x8d, 0x00, 0xe0,
+ 0x60
+};
+
+static const uint8_t _sidtune_sidplayer2[] =
+{
+ 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x61, 0xf1, 0x60, 0x01, 0x02, 0x04, 0x00, 0x07, 0x0e, 0x02, 0x02, 0xfe, 0x02, 0x02, 0xfe,
+ 0xfe, 0x00, 0x01, 0x00, 0xff, 0x00, 0x02, 0x04, 0x05, 0x07, 0x09, 0x0b, 0x1e, 0x18, 0x8b, 0x7e,
+ 0xfa, 0x06, 0xac, 0xf3, 0xe6, 0x8f, 0xf8, 0x2e, 0x86, 0x8e, 0x96, 0x9f, 0xa8, 0xb3, 0xbd, 0xc8,
+ 0xd4, 0xe1, 0xee, 0xfd, 0x8c, 0x78, 0x64, 0x50, 0x3c, 0x28, 0x14, 0x00, 0x00, 0x02, 0x03, 0x05,
+ 0x07, 0x08, 0x0a, 0x0c, 0x0d, 0x0f, 0x11, 0x12, 0x00, 0xe0, 0x00, 0x05, 0x0a, 0x0f, 0xf9, 0x00,
+ 0xf5, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00, 0x30, 0x00, 0x00, 0x40, 0x00, 0x00,
+ 0x50, 0x00, 0x00, 0x60, 0x00, 0x00, 0x70, 0x00, 0x00, 0x80, 0x00, 0x00, 0x90, 0x00, 0x00, 0xa0,
+ 0x00, 0xa9, 0x00, 0x8d, 0x00, 0xf0, 0xa2, 0x95, 0xa0, 0x42, 0xad, 0xa6, 0x02, 0xf0, 0x04, 0xa2,
+ 0x25, 0xa0, 0x40, 0x8e, 0x5b, 0xf1, 0x8c, 0x5c, 0xf1, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea,
+ 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea,
+ 0xea, 0x60, 0xa9, 0x00, 0x8d, 0x00, 0xf0, 0x86, 0x61, 0x84, 0x62, 0xa0, 0xbc, 0x99, 0x00, 0xf0,
+ 0x88, 0xd0, 0xfa, 0xa0, 0x72, 0x99, 0xbc, 0xf0, 0x88, 0xd0, 0xfa, 0x8d, 0x15, 0xd5, 0x8d, 0x16,
+ 0xd5, 0xa9, 0x08, 0x8d, 0x25, 0xf0, 0x8d, 0x17, 0xd5, 0x8d, 0x26, 0xf0, 0x8d, 0x18, 0xd5, 0xa9,
+ 0x90, 0x8d, 0x27, 0xf0, 0xa9, 0x60, 0x8d, 0x28, 0xf0, 0xa9, 0x0c, 0x8d, 0x29, 0xf0, 0xad, 0x5b,
+ 0xf1, 0x8d, 0x2d, 0xf0, 0xad, 0x5c, 0xf1, 0x8d, 0x2e, 0xf0, 0xa9, 0xff, 0x8d, 0xcc, 0xf0, 0xa9,
+ 0xd5, 0x85, 0x64, 0xa2, 0x02, 0xa9, 0xff, 0x9d, 0x0b, 0xf0, 0xa9, 0x01, 0x9d, 0x30, 0xf0, 0x9d,
+ 0x2a, 0xf0, 0x8a, 0x9d, 0x33, 0xf0, 0x9d, 0xae, 0xf0, 0xa9, 0x04, 0x9d, 0x39, 0xf0, 0xbd, 0xa8,
+ 0xf1, 0x9d, 0xba, 0xf0, 0xa9, 0x5b, 0x9d, 0x7e, 0xf0, 0xbd, 0x65, 0xf1, 0x85, 0x63, 0xa9, 0x00,
+ 0xa8, 0x91, 0x63, 0xc8, 0x91, 0x63, 0xc8, 0x91, 0x63, 0xa9, 0x08, 0x9d, 0x17, 0xf0, 0x9d, 0x9c,
+ 0xf0, 0xc8, 0x91, 0x63, 0xc8, 0x91, 0x63, 0xa9, 0x40, 0x9d, 0x1a, 0xf0, 0x91, 0x63, 0xa9, 0x20,
+ 0x9d, 0x1d, 0xf0, 0xc8, 0x91, 0x63, 0xa9, 0xf5, 0x9d, 0x20, 0xf0, 0xc8, 0x91, 0x63, 0xca, 0x10,
+ 0xa4, 0x8a, 0xa2, 0x17, 0x9d, 0x3e, 0xf1, 0xca, 0x10, 0xfa, 0xa5, 0x61, 0x18, 0x69, 0x06, 0x85,
+ 0x63, 0xa9, 0x00, 0xaa, 0xa8, 0x65, 0x62, 0x85, 0x64, 0x9d, 0xab, 0xf0, 0x9d, 0xb4, 0xf0, 0xa5,
+ 0x63, 0x9d, 0xa8, 0xf0, 0x9d, 0xb1, 0xf0, 0x18, 0x71, 0x61, 0x85, 0x63, 0xa5, 0x64, 0xc8, 0x71,
+ 0x61, 0xc8, 0xe8, 0xe0, 0x03, 0xd0, 0xe0, 0xa6, 0x63, 0xa8, 0x60, 0xa9, 0x00, 0x8d, 0x04, 0xd5,
+ 0x8d, 0x0b, 0xd5, 0x8d, 0x12, 0xd5, 0x8d, 0x01, 0xd5, 0x8d, 0x08, 0xd5, 0x8d, 0x0f, 0xd5, 0xa9,
+ 0x08, 0x8d, 0x17, 0xd5, 0xad, 0x5b, 0xf1, 0x8d, 0x04, 0xdc, 0xad, 0x5c, 0xf1, 0x8d, 0x05, 0xdc,
+ 0x60, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0x60,
+ 0xa9, 0x08, 0x8d, 0x00, 0xf0, 0x6c, 0x5d, 0xf1, 0xea, 0xea, 0xea, 0xad, 0x00, 0xf0, 0x30, 0xf0,
+ 0x09, 0x80, 0xa8, 0x29, 0x07, 0xf0, 0xee, 0xd8, 0x8c, 0x00, 0xf0, 0xea, 0xa5, 0xfb, 0x8d, 0x56,
+ 0xf1, 0xa5, 0xfc, 0x8d, 0x57, 0xf1, 0xa5, 0xfd, 0x8d, 0x58, 0xf1, 0xa5, 0xfe, 0x8d, 0x59, 0xf1,
+ 0xa5, 0xff, 0x8d, 0x5a, 0xf1, 0xad, 0x23, 0xf0, 0x18, 0x6d, 0xd9, 0xf0, 0x48, 0x29, 0x07, 0xa8,
+ 0xad, 0xdc, 0xf0, 0x69, 0x00, 0x85, 0xff, 0x68, 0x46, 0xff, 0x6a, 0x46, 0xff, 0x6a, 0x46, 0xff,
+ 0x6a, 0x18, 0x6d, 0x24, 0xf0, 0x8c, 0x15, 0xd5, 0x8d, 0x16, 0xd5, 0xad, 0x25, 0xf0, 0x8d, 0x17,
+ 0xd5, 0xad, 0x26, 0xf0, 0x8d, 0x18, 0xd5, 0xa9, 0xd5, 0x85, 0xfc, 0xa2, 0x00, 0xad, 0x00, 0xf0,
+ 0x3d, 0x62, 0xf1, 0xf0, 0x51, 0xbd, 0x65, 0xf1, 0x85, 0xfb, 0xbd, 0x0e, 0xf0, 0x18, 0x7d, 0x51,
+ 0xf0, 0xa8, 0xbd, 0x11, 0xf0, 0x7d, 0x54, 0xf0, 0x48, 0x98, 0x18, 0x7d, 0xcd, 0xf0, 0xa0, 0x00,
+ 0x91, 0xfb, 0x68, 0x7d, 0xd0, 0xf0, 0xc8, 0x91, 0xfb, 0xbd, 0x14, 0xf0, 0x18, 0x7d, 0x69, 0xf0,
+ 0x85, 0xff, 0xbd, 0x17, 0xf0, 0x7d, 0x6c, 0xf0, 0x48, 0xa5, 0xff, 0x18, 0x7d, 0xd3, 0xf0, 0xc8,
+ 0x91, 0xfb, 0x68, 0x7d, 0xd6, 0xf0, 0xc8, 0x91, 0xfb, 0xbd, 0x1d, 0xf0, 0xc8, 0xc8, 0x91, 0xfb,
+ 0xbd, 0x20, 0xf0, 0xc8, 0x91, 0xfb, 0xe8, 0xe0, 0x03, 0xd0, 0xa2, 0xac, 0x1a, 0xf0, 0xae, 0x1b,
+ 0xf0, 0xad, 0x1c, 0xf0, 0x8c, 0x04, 0xd5, 0x8e, 0x0b, 0xd5, 0x8d, 0x12, 0xd5, 0xae, 0x2d, 0xf0,
+ 0xac, 0x2e, 0xf0, 0x8e, 0x04, 0xdc, 0x8c, 0x05, 0xdc, 0xad, 0x1b, 0xd5, 0x8d, 0xbe, 0xf0, 0xad,
+ 0x1c, 0xd5, 0x8d, 0xbf, 0xf0, 0xa2, 0x00, 0xad, 0x00, 0xf0, 0x3d, 0x62, 0xf1, 0xf0, 0x10, 0x8e,
+ 0x2f, 0xf0, 0x20, 0x36, 0xf5, 0xad, 0x00, 0xf0, 0x29, 0x78, 0xf0, 0x03, 0x4c, 0x0c, 0xf5, 0xe8,
+ 0xe0, 0x03, 0xd0, 0xe3, 0xad, 0xc9, 0xf0, 0xd0, 0x52, 0xad, 0xca, 0xf0, 0x0d, 0xcb, 0xf0, 0xf0,
+ 0x78, 0xad, 0xdf, 0xf0, 0xd0, 0x28, 0xad, 0xca, 0xf0, 0xf0, 0x28, 0x18, 0x6d, 0xbd, 0xf0, 0xb0,
+ 0x07, 0xcd, 0xcc, 0xf0, 0x90, 0x60, 0xf0, 0x5e, 0xa9, 0x00, 0x8d, 0xdf, 0xf0, 0xad, 0xcb, 0xf0,
+ 0xf0, 0x54, 0xee, 0xdf, 0xf0, 0xad, 0xbd, 0xf0, 0xed, 0xcb, 0xf0, 0x4c, 0xb4, 0xf4, 0xad, 0xcb,
+ 0xf0, 0xf0, 0xd3, 0xad, 0xbd, 0xf0, 0x38, 0xed, 0xcb, 0xf0, 0xb0, 0x3a, 0xa9, 0x00, 0x8d, 0xdf,
+ 0xf0, 0xad, 0xca, 0xf0, 0xd0, 0x30, 0xee, 0xdf, 0xf0, 0xd0, 0x28, 0xce, 0xe0, 0xf0, 0xd0, 0x29,
+ 0xad, 0xdf, 0xf0, 0xd0, 0x11, 0xee, 0xdf, 0xf0, 0xad, 0xcb, 0xf0, 0xd0, 0x02, 0xa9, 0x20, 0x8d,
+ 0xe0, 0xf0, 0xa9, 0x00, 0xf0, 0x10, 0xce, 0xdf, 0xf0, 0xad, 0xca, 0xf0, 0xd0, 0x02, 0xa9, 0x20,
+ 0x8d, 0xe0, 0xf0, 0xad, 0xcc, 0xf0, 0x8d, 0xbd, 0xf0, 0xa2, 0x00, 0xbd, 0xc3, 0xf0, 0xf0, 0x44,
+ 0xa9, 0x00, 0x85, 0xff, 0xbc, 0xc0, 0xf0, 0xb9, 0xbd, 0xf0, 0xbc, 0xc6, 0xf0, 0xf0, 0x0e, 0x30,
+ 0x08, 0x0a, 0x26, 0xff, 0x88, 0xd0, 0xfa, 0xf0, 0x04, 0x4a, 0xc8, 0xd0, 0xfc, 0xbc, 0xc3, 0xf0,
+ 0x88, 0xd0, 0x0b, 0x9d, 0xcd, 0xf0, 0xa5, 0xff, 0x9d, 0xd0, 0xf0, 0x4c, 0x02, 0xf5, 0x88, 0xd0,
+ 0x0b, 0x9d, 0xd3, 0xf0, 0xa5, 0xff, 0x9d, 0xd6, 0xf0, 0x4c, 0x02, 0xf5, 0x8d, 0xd9, 0xf0, 0xa5,
+ 0xff, 0x8d, 0xdc, 0xf0, 0xe8, 0xe0, 0x03, 0xd0, 0xb2, 0xad, 0x00, 0xf0, 0x29, 0x7f, 0x8d, 0x00,
+ 0xf0, 0xad, 0x56, 0xf1, 0x85, 0xfb, 0xad, 0x57, 0xf1, 0x85, 0xfc, 0xad, 0x58, 0xf1, 0x85, 0xfd,
+ 0xad, 0x59, 0xf1, 0x85, 0xfe, 0xad, 0x5a, 0xf1, 0x85, 0xff, 0x6c, 0x5d, 0xf1, 0xbd, 0x60, 0xf0,
+ 0xd0, 0x03, 0x4c, 0x9f, 0xf6, 0x4c, 0xba, 0xf5, 0xde, 0x30, 0xf0, 0xd0, 0x03, 0x4c, 0xa0, 0xf6,
+ 0xbd, 0x36, 0xf0, 0x30, 0xe8, 0xd0, 0x1a, 0xbd, 0x3f, 0xf0, 0xf0, 0x05, 0xde, 0x3f, 0xf0, 0xd0,
+ 0x10, 0xbd, 0x39, 0xf0, 0xdd, 0x30, 0xf0, 0x90, 0x08, 0xbd, 0x1a, 0xf0, 0x29, 0xfe, 0x9d, 0x1a,
+ 0xf0, 0xbd, 0x42, 0xf0, 0xf0, 0x56, 0x0a, 0xbd, 0x0e, 0xf0, 0xb0, 0x1d, 0x7d, 0x45, 0xf0, 0x9d,
+ 0x0e, 0xf0, 0xa8, 0xbd, 0x11, 0xf0, 0x7d, 0x48, 0xf0, 0x9d, 0x11, 0xf0, 0x48, 0x98, 0xdd, 0x8d,
+ 0xf0, 0x68, 0xfd, 0x90, 0xf0, 0xb0, 0x1f, 0x90, 0x2e, 0xfd, 0x45, 0xf0, 0x9d, 0x0e, 0xf0, 0xbd,
+ 0x11, 0xf0, 0xfd, 0x48, 0xf0, 0x9d, 0x11, 0xf0, 0xbd, 0x8d, 0xf0, 0xdd, 0x0e, 0xf0, 0xbd, 0x90,
+ 0xf0, 0xfd, 0x11, 0xf0, 0x90, 0x11, 0xbd, 0x8d, 0xf0, 0x9d, 0x0e, 0xf0, 0xbd, 0x90, 0xf0, 0x9d,
+ 0x11, 0xf0, 0xa9, 0x00, 0x9d, 0x42, 0xf0, 0xbd, 0x60, 0xf0, 0xf0, 0x55, 0xbd, 0x4b, 0xf0, 0xf0,
+ 0x4b, 0xa0, 0x00, 0xde, 0x4e, 0xf0, 0xd0, 0x31, 0xbd, 0x51, 0xf0, 0x1d, 0x54, 0xf0, 0xd0, 0x1b,
+ 0xbd, 0x5d, 0xf0, 0x9d, 0x57, 0xf0, 0x9d, 0x4e, 0xf0, 0xbd, 0x4b, 0xf0, 0x0a, 0xbd, 0x5a, 0xf0,
+ 0x90, 0x04, 0x49, 0xff, 0x69, 0x00, 0x9d, 0x4b, 0xf0, 0xd0, 0x10, 0xbd, 0x57, 0xf0, 0x9d, 0x4e,
+ 0xf0, 0x98, 0x38, 0xfd, 0x4b, 0xf0, 0x9d, 0x4b, 0xf0, 0xc9, 0x00, 0x10, 0x01, 0x88, 0x18, 0x7d,
+ 0x51, 0xf0, 0x9d, 0x51, 0xf0, 0x98, 0x7d, 0x54, 0xf0, 0x9d, 0x54, 0xf0, 0xbd, 0x36, 0xf0, 0x30,
+ 0x15, 0xbd, 0x93, 0xf0, 0xf0, 0x10, 0x18, 0x7d, 0x14, 0xf0, 0x9d, 0x14, 0xf0, 0xbd, 0x96, 0xf0,
+ 0x7d, 0x17, 0xf0, 0x9d, 0x17, 0xf0, 0xbd, 0x63, 0xf0, 0xf0, 0x4b, 0xa0, 0x00, 0xde, 0x66, 0xf0,
+ 0xd0, 0x31, 0xbd, 0x69, 0xf0, 0x1d, 0x6c, 0xf0, 0xd0, 0x1b, 0xbd, 0x72, 0xf0, 0x9d, 0x6f, 0xf0,
+ 0x9d, 0x66, 0xf0, 0xbd, 0x63, 0xf0, 0x0a, 0xbd, 0x75, 0xf0, 0x90, 0x04, 0x49, 0xff, 0x69, 0x00,
+ 0x9d, 0x63, 0xf0, 0xd0, 0x10, 0xbd, 0x6f, 0xf0, 0x9d, 0x66, 0xf0, 0x98, 0x38, 0xfd, 0x63, 0xf0,
+ 0x9d, 0x63, 0xf0, 0xc9, 0x00, 0x10, 0x01, 0x88, 0x18, 0x7d, 0x69, 0xf0, 0x9d, 0x69, 0xf0, 0x98,
+ 0x7d, 0x6c, 0xf0, 0x9d, 0x6c, 0xf0, 0xbd, 0x36, 0xf0, 0x10, 0x03, 0x4c, 0x9f, 0xf6, 0xa0, 0x00,
+ 0xbd, 0xa2, 0xf0, 0xf0, 0x1c, 0x10, 0x01, 0xc8, 0x18, 0x6d, 0x23, 0xf0, 0x48, 0x29, 0x07, 0x8d,
+ 0x23, 0xf0, 0x68, 0x6a, 0x4a, 0x4a, 0x18, 0x79, 0xa6, 0xf1, 0x18, 0x6d, 0x24, 0xf0, 0x8d, 0x24,
+ 0xf0, 0x60, 0xbd, 0xa8, 0xf0, 0x85, 0xfd, 0xbd, 0xab, 0xf0, 0x85, 0xfe, 0xd0, 0x04, 0x60, 0x20,
+ 0x98, 0xf8, 0xad, 0x00, 0xf0, 0x3d, 0x62, 0xf1, 0xf0, 0xf4, 0xa0, 0x00, 0xb1, 0xfd, 0x85, 0xff,
+ 0xc8, 0xb1, 0xfd, 0xa8, 0xa5, 0xfd, 0x18, 0x69, 0x02, 0x85, 0xfd, 0x9d, 0xa8, 0xf0, 0xa5, 0xfe,
+ 0x69, 0x00, 0x85, 0xfe, 0x9d, 0xab, 0xf0, 0xa5, 0xff, 0x29, 0x03, 0xd0, 0xd2, 0xbd, 0x8d, 0xf0,
+ 0x9d, 0x0e, 0xf0, 0xbd, 0x90, 0xf0, 0x9d, 0x11, 0xf0, 0xa5, 0xff, 0x9d, 0x05, 0xf0, 0x98, 0x9d,
+ 0x02, 0xf0, 0x29, 0x07, 0xa8, 0xb9, 0x67, 0xf1, 0x8d, 0x6f, 0xf1, 0xbd, 0x02, 0xf0, 0x29, 0x38,
+ 0x4a, 0x4a, 0x4a, 0x7d, 0x81, 0xf0, 0x85, 0xfd, 0xbd, 0x02, 0xf0, 0x29, 0xc0, 0x0a, 0x2a, 0x2a,
+ 0xa8, 0xb9, 0x6f, 0xf1, 0x85, 0xfe, 0xbd, 0x02, 0xf0, 0x29, 0x07, 0xf0, 0x62, 0xa8, 0xb9, 0x72,
+ 0xf1, 0x65, 0xfe, 0x18, 0x7d, 0x84, 0xf0, 0x10, 0x05, 0x18, 0x69, 0x0c, 0xe6, 0xfd, 0xc9, 0x0c,
+ 0x90, 0x04, 0xe9, 0x0c, 0xc6, 0xfd, 0x85, 0xfe, 0xa8, 0xb9, 0x86, 0xf1, 0x85, 0xff, 0xb9, 0x7a,
+ 0xf1, 0xa4, 0xfd, 0x88, 0x30, 0x06, 0x46, 0xff, 0x6a, 0x88, 0x10, 0xfa, 0x18, 0x7d, 0x87, 0xf0,
+ 0x9d, 0x8d, 0xf0, 0xa5, 0xff, 0x7d, 0x8a, 0xf0, 0x9d, 0x90, 0xf0, 0xbd, 0x05, 0xf0, 0xd0, 0x03,
+ 0x4c, 0xa0, 0xf6, 0xbd, 0x45, 0xf0, 0x1d, 0x48, 0xf0, 0xf0, 0x16, 0xbd, 0x0e, 0xf0, 0xdd, 0x8d,
+ 0xf0, 0xbd, 0x11, 0xf0, 0xfd, 0x90, 0xf0, 0xa9, 0xfe, 0x6a, 0x9d, 0x42, 0xf0, 0x90, 0x11, 0xf0,
+ 0x4a, 0x9d, 0x42, 0xf0, 0xbd, 0x8d, 0xf0, 0x9d, 0x0e, 0xf0, 0xbd, 0x90, 0xf0, 0x9d, 0x11, 0xf0,
+ 0xbd, 0x36, 0xf0, 0x0a, 0xd0, 0x35, 0xbd, 0x93, 0xf0, 0xf0, 0x0c, 0xbd, 0x99, 0xf0, 0x9d, 0x14,
+ 0xf0, 0xbd, 0x9c, 0xf0, 0x9d, 0x17, 0xf0, 0xbd, 0x9f, 0xf0, 0xf0, 0x0f, 0xa4, 0xfd, 0x18, 0x79,
+ 0x92, 0xf1, 0xa4, 0xfe, 0x18, 0x79, 0x9a, 0xf1, 0x18, 0x90, 0x08, 0xbd, 0xa2, 0xf0, 0xf0, 0x0b,
+ 0xbd, 0xa5, 0xf0, 0x8d, 0x24, 0xf0, 0xa9, 0x00, 0x8d, 0x23, 0xf0, 0xbd, 0x3c, 0xf0, 0x9d, 0x3f,
+ 0xf0, 0xbd, 0x05, 0xf0, 0x29, 0x40, 0x9d, 0x36, 0xf0, 0xbd, 0x05, 0xf0, 0x4a, 0x4a, 0x29, 0x07,
+ 0xd0, 0x30, 0xbd, 0x05, 0xf0, 0x30, 0x14, 0xad, 0x27, 0xf0, 0x29, 0x3c, 0xd0, 0x1e, 0xad, 0x27,
+ 0xf0, 0x0a, 0x2a, 0x2a, 0xd0, 0x02, 0xa9, 0x04, 0x4c, 0x70, 0xf8, 0xad, 0x28, 0xf0, 0xf0, 0x0c,
+ 0x29, 0x3f, 0xd0, 0x08, 0xad, 0x28, 0xf0, 0x0a, 0x2a, 0x2a, 0xd0, 0x66, 0xa9, 0x10, 0x8d, 0x00,
+ 0xf0, 0x60, 0xc9, 0x01, 0xd0, 0x13, 0xbd, 0x05, 0xf0, 0x29, 0x20, 0xd0, 0x06, 0xad, 0x29, 0xf0,
+ 0x4c, 0x70, 0xf8, 0xbd, 0x2a, 0xf0, 0x4c, 0x70, 0xf8, 0xa8, 0xbd, 0x05, 0xf0, 0x29, 0xa0, 0xc9,
+ 0x80, 0xf0, 0x30, 0x85, 0xff, 0x18, 0xad, 0x27, 0xf0, 0xd0, 0x01, 0x38, 0x88, 0x88, 0xf0, 0x06,
+ 0x6a, 0xb0, 0x4e, 0x88, 0xd0, 0xfa, 0xa4, 0xff, 0x85, 0xff, 0xf0, 0x26, 0x46, 0xff, 0xb0, 0x41,
+ 0xf0, 0x42, 0x65, 0xff, 0xb0, 0x3e, 0xc8, 0x10, 0x19, 0x46, 0xff, 0xb0, 0x34, 0x65, 0xff, 0x90,
+ 0x11, 0xb0, 0x31, 0xad, 0x28, 0xf0, 0xf0, 0x29, 0x88, 0x88, 0xf0, 0x06, 0x4a, 0xb0, 0x22, 0x88,
+ 0xd0, 0xfa, 0x9d, 0x30, 0xf0, 0xbd, 0x1a, 0xf0, 0x29, 0xf6, 0x9d, 0x1a, 0xf0, 0x38, 0xbd, 0x02,
+ 0xf0, 0x29, 0x07, 0xd0, 0x03, 0x7e, 0x36, 0xf0, 0xbd, 0x1a, 0xf0, 0x69, 0x00, 0x9d, 0x1a, 0xf0,
+ 0x60, 0xa9, 0x10, 0x2c, 0xa9, 0x18, 0x8d, 0x00, 0xf0, 0x60, 0x98, 0x48, 0xa5, 0xff, 0x4a, 0x90,
+ 0x03, 0x4c, 0x42, 0xfa, 0x4a, 0x4a, 0xb0, 0x1e, 0x4a, 0xb0, 0x0e, 0x9d, 0x9c, 0xf0, 0x9d, 0x17,
+ 0xf0, 0x68, 0x9d, 0x99, 0xf0, 0x9d, 0x14, 0xf0, 0x60, 0x4a, 0x90, 0x02, 0x09, 0xf8, 0x9d, 0x8a,
+ 0xf0, 0x68, 0x9d, 0x87, 0xf0, 0x60, 0x4a, 0xb0, 0x03, 0x4c, 0x4a, 0xf9, 0x4a, 0xb0, 0x61, 0x4a,
+ 0xb0, 0x0f, 0xd0, 0x08, 0x68, 0x9d, 0xa5, 0xf0, 0x8d, 0x24, 0xf0, 0x60, 0x68, 0x9d, 0x3c, 0xf0,
+ 0x60, 0xd0, 0x48, 0x68, 0x9d, 0x7e, 0xf0, 0xc9, 0x5b, 0xf0, 0x33, 0xa8, 0x4a, 0x4a, 0x4a, 0x38,
+ 0xe9, 0x0b, 0x18, 0x7d, 0x84, 0xf0, 0x30, 0x0c, 0xc9, 0x0c, 0x90, 0x11, 0xe9, 0x0c, 0xde, 0x81,
+ 0xf0, 0x4c, 0x0b, 0xf9, 0xc9, 0xf5, 0xb0, 0x05, 0x69, 0x0c, 0xfe, 0x81, 0xf0, 0x9d, 0x84, 0xf0,
+ 0x98, 0x29, 0x07, 0x38, 0xe9, 0x03, 0x18, 0x7d, 0x81, 0xf0, 0x9d, 0x81, 0xf0, 0x60, 0xbd, 0x78,
+ 0xf0, 0x9d, 0x81, 0xf0, 0xbd, 0x7b, 0xf0, 0x9d, 0x84, 0xf0, 0x60, 0x68, 0x9d, 0xc6, 0xf0, 0x60,
+ 0x4a, 0xb0, 0x08, 0x9d, 0x0b, 0xf0, 0x68, 0x9d, 0x08, 0xf0, 0x60, 0x4a, 0x6a, 0x6a, 0x6d, 0x5b,
+ 0xf1, 0x8d, 0x2d, 0xf0, 0x68, 0x6d, 0x5c, 0xf1, 0x8d, 0x2e, 0xf0, 0x60, 0x4a, 0x90, 0x03, 0x4c,
+ 0xd3, 0xf9, 0x4a, 0xb0, 0x40, 0x4a, 0xb0, 0x17, 0x4a, 0xb0, 0x0f, 0x68, 0x8d, 0x27, 0xf0, 0x4a,
+ 0x4a, 0x4a, 0xa8, 0xb9, 0xaf, 0xf1, 0x8d, 0x28, 0xf0, 0x60, 0x68, 0x9d, 0x5d, 0xf0, 0x60, 0x4a,
+ 0xb0, 0x05, 0x68, 0x8d, 0x01, 0xf0, 0x60, 0x68, 0xf0, 0x11, 0x9d, 0x75, 0xf0, 0xbc, 0x63, 0xf0,
+ 0xd0, 0x08, 0x9d, 0x63, 0xf0, 0xa9, 0x01, 0x9d, 0x66, 0xf0, 0x60, 0x9d, 0x63, 0xf0, 0x9d, 0x69,
+ 0xf0, 0x9d, 0x6c, 0xf0, 0x60, 0x4a, 0xb0, 0x30, 0x4a, 0xb0, 0x05, 0x68, 0x9d, 0x39, 0xf0, 0x60,
+ 0x68, 0xa0, 0x00, 0x4a, 0x90, 0x02, 0xc8, 0x18, 0x48, 0x29, 0x07, 0x79, 0xac, 0xf1, 0x9d, 0x78,
+ 0xf0, 0x9d, 0x81, 0xf0, 0x68, 0x4a, 0x4a, 0x4a, 0x18, 0x79, 0xad, 0xf1, 0x9d, 0x7b, 0xf0, 0x9d,
+ 0x84, 0xf0, 0xa9, 0x5b, 0x9d, 0x7e, 0xf0, 0x60, 0x4a, 0xb0, 0x05, 0x68, 0x9d, 0xa2, 0xf0, 0x60,
+ 0x68, 0x8d, 0xcc, 0xf0, 0x60, 0x4a, 0xb0, 0x27, 0x4a, 0xb0, 0x0d, 0x4a, 0xb0, 0x05, 0x68, 0x8d,
+ 0x29, 0xf0, 0x60, 0x68, 0x9d, 0x9f, 0xf0, 0x60, 0x4a, 0xb0, 0x0f, 0x68, 0x9d, 0x93, 0xf0, 0xa0,
+ 0x00, 0x0a, 0x90, 0x01, 0x88, 0x98, 0x9d, 0x96, 0xf0, 0x60, 0x68, 0x9d, 0x72, 0xf0, 0x60, 0x4a,
+ 0xb0, 0x1c, 0x4a, 0xb0, 0x15, 0x68, 0x9d, 0xb7, 0xf0, 0xa5, 0xfd, 0x9d, 0xb1, 0xf0, 0xa5, 0xfe,
+ 0x9d, 0xb4, 0xf0, 0xbd, 0x33, 0xf0, 0x9d, 0xae, 0xf0, 0x60, 0x68, 0x6c, 0x5f, 0xf1, 0x4a, 0xb0,
+ 0x1e, 0x68, 0xd0, 0x0a, 0x9d, 0x4b, 0xf0, 0x9d, 0x51, 0xf0, 0x9d, 0x54, 0xf0, 0x60, 0x9d, 0x5a,
+ 0xf0, 0xbc, 0x4b, 0xf0, 0xd0, 0x08, 0x9d, 0x4b, 0xf0, 0xa9, 0x01, 0x9d, 0x4e, 0xf0, 0x60, 0x68,
+ 0x9d, 0x2a, 0xf0, 0x60, 0x4a, 0x90, 0x08, 0x9d, 0x48, 0xf0, 0x68, 0x9d, 0x45, 0xf0, 0x60, 0x68,
+ 0x4a, 0xb0, 0x61, 0x4a, 0xb0, 0x25, 0x4a, 0xb0, 0x05, 0x4a, 0xa0, 0xf0, 0xd0, 0x06, 0x0a, 0x0a,
+ 0x0a, 0x0a, 0xa0, 0x0f, 0x85, 0xff, 0x98, 0xb0, 0x09, 0x3d, 0x1d, 0xf0, 0x05, 0xff, 0x9d, 0x1d,
+ 0xf0, 0x60, 0x3d, 0x20, 0xf0, 0x05, 0xff, 0x9d, 0x20, 0xf0, 0x60, 0x4a, 0xb0, 0x38, 0x4a, 0xb0,
+ 0x64, 0x85, 0xff, 0xbd, 0xba, 0xf0, 0xdd, 0xa9, 0xf1, 0xf0, 0x54, 0xfe, 0xba, 0xf0, 0xa8, 0xa5,
+ 0xfd, 0x99, 0xe1, 0xf0, 0xa5, 0xfe, 0x99, 0xf0, 0xf0, 0xbd, 0x33, 0xf0, 0x99, 0x2f, 0xf1, 0xa4,
+ 0xff, 0xb9, 0x17, 0xf1, 0xf0, 0x36, 0x85, 0xfe, 0xb9, 0xff, 0xf0, 0x85, 0xfd, 0xb9, 0x3e, 0xf1,
+ 0x9d, 0x33, 0xf0, 0x60, 0xb0, 0x4b, 0x4a, 0xb0, 0x3c, 0xa8, 0xa5, 0xfd, 0x99, 0xff, 0xf0, 0xa5,
+ 0xfe, 0x99, 0x17, 0xf1, 0xbd, 0x33, 0xf0, 0x99, 0x3e, 0xf1, 0xbd, 0xba, 0xf0, 0xdd, 0xa9, 0xf1,
+ 0xf0, 0x0d, 0xfe, 0xba, 0xf0, 0xa8, 0xa9, 0x00, 0x99, 0xf0, 0xf0, 0x60, 0xa9, 0x30, 0x2c, 0xa9,
+ 0x28, 0x8d, 0x00, 0xf0, 0x60, 0x0a, 0x0a, 0x0a, 0x0a, 0x4d, 0x25, 0xf0, 0x29, 0xf0, 0x4d, 0x25,
+ 0xf0, 0x8d, 0x25, 0xf0, 0x60, 0x4d, 0x26, 0xf0, 0x29, 0x0f, 0x4d, 0x26, 0xf0, 0x8d, 0x26, 0xf0,
+ 0x60, 0x4a, 0xb0, 0x0b, 0x4a, 0xb0, 0x04, 0x8d, 0xca, 0xf0, 0x60, 0x8d, 0xcb, 0xf0, 0x60, 0x4a,
+ 0x90, 0x03, 0x4c, 0xa5, 0xfb, 0x4a, 0xa8, 0xf0, 0x21, 0x88, 0xf0, 0x34, 0x88, 0xf0, 0x42, 0x88,
+ 0xf0, 0x4a, 0x88, 0xf0, 0x52, 0x88, 0xf0, 0x5c, 0x88, 0xf0, 0x66, 0x88, 0xf0, 0x73, 0x29, 0x07,
+ 0x09, 0x10, 0xb0, 0x03, 0x4c, 0xb7, 0xfa, 0x4c, 0x7f, 0xfa, 0xac, 0x26, 0xf0, 0xb0, 0x07, 0xc8,
+ 0x98, 0x29, 0x0f, 0xd0, 0x07, 0x60, 0x98, 0x29, 0x0f, 0xf0, 0x04, 0x88, 0x8c, 0x26, 0xf0, 0x60,
+ 0xbd, 0x62, 0xf1, 0x49, 0xff, 0x2d, 0x25, 0xf0, 0x90, 0x03, 0x1d, 0x62, 0xf1, 0x8d, 0x25, 0xf0,
+ 0x60, 0xbd, 0x1a, 0xf0, 0x29, 0xfb, 0x90, 0x55, 0x09, 0x04, 0xb0, 0x51, 0xbd, 0x1a, 0xf0, 0x29,
+ 0xfd, 0x90, 0x4a, 0x09, 0x02, 0xb0, 0x46, 0xad, 0x25, 0xf0, 0x29, 0xf7, 0x90, 0x02, 0x09, 0x08,
+ 0x8d, 0x25, 0xf0, 0x60, 0xad, 0x26, 0xf0, 0x29, 0x7f, 0x90, 0x02, 0x09, 0x80, 0x8d, 0x26, 0xf0,
+ 0x60, 0x98, 0x8d, 0xbd, 0xf0, 0x8d, 0xdf, 0xf0, 0xc8, 0x8c, 0xe0, 0xf0, 0x2a, 0x8d, 0xc9, 0xf0,
+ 0x60, 0x98, 0x2a, 0x9d, 0x60, 0xf0, 0x60, 0x4a, 0xb0, 0x27, 0x4a, 0xb0, 0x14, 0xd0, 0x02, 0xa9,
+ 0x08, 0x0a, 0x0a, 0x0a, 0x0a, 0x5d, 0x1a, 0xf0, 0x29, 0xf0, 0x5d, 0x1a, 0xf0, 0x9d, 0x1a, 0xf0,
+ 0x60, 0x0a, 0x0a, 0x0a, 0x0a, 0x4d, 0x26, 0xf0, 0x29, 0x70, 0x4d, 0x26, 0xf0, 0x8d, 0x26, 0xf0,
+ 0x60, 0x4a, 0x90, 0x04, 0x9d, 0xc0, 0xf0, 0x60, 0xa8, 0xf0, 0x20, 0x88, 0xf0, 0x40, 0x88, 0xf0,
+ 0x63, 0x29, 0x03, 0x9d, 0xc3, 0xf0, 0xa9, 0x00, 0x9d, 0xcd, 0xf0, 0x9d, 0xd0, 0xf0, 0x9d, 0xd3,
+ 0xf0, 0x9d, 0xd6, 0xf0, 0x8d, 0xd9, 0xf0, 0x8d, 0xdc, 0xf0, 0x60, 0xbd, 0xb7, 0xf0, 0xf0, 0x05,
+ 0xde, 0xb7, 0xf0, 0xf0, 0x12, 0xbd, 0x33, 0xf0, 0xdd, 0xae, 0xf0, 0xd0, 0x0b, 0xbd, 0xb1, 0xf0,
+ 0x85, 0xfd, 0xbd, 0xb4, 0xf0, 0x85, 0xfe, 0x60, 0xa9, 0x38, 0x8d, 0x00, 0xf0, 0x60, 0xbd, 0xba,
+ 0xf0, 0xdd, 0xa8, 0xf1, 0xf0, 0x18, 0xde, 0xba, 0xf0, 0xa8, 0x88, 0xb9, 0xf0, 0xf0, 0xf0, 0x0d,
+ 0x85, 0xfe, 0xb9, 0xe1, 0xf0, 0x85, 0xfd, 0xb9, 0x2f, 0xf1, 0x9d, 0x33, 0xf0, 0x60, 0xa9, 0x20,
+ 0x8d, 0x00, 0xf0, 0x60, 0xad, 0x00, 0xf0, 0x5d, 0x62, 0xf1, 0x8d, 0x00, 0xf0, 0xa9, 0x01, 0x9d,
+ 0x30, 0xf0, 0x60, 0xad, 0x00, 0xf0, 0x29, 0x07, 0x8d, 0x81, 0xfc, 0xd0, 0x03, 0x20, 0xe9, 0xf2,
+ 0x60, 0x00, 0xa2, 0x51, 0xa0, 0xfc, 0x8e, 0x5d, 0xf1, 0x8c, 0x5e, 0xf1, 0x20, 0xcf, 0xf1, 0xa2,
+ 0x00, 0xa0, 0x09, 0x20, 0x00, 0xf2, 0xa9, 0x07, 0x8d, 0x00, 0xf0, 0x8d, 0x81, 0xfc, 0x60, 0x00,
+ 0x00, 0x00, 0xa9, 0x00, 0x29, 0xff, 0xf0, 0xf6, 0x4c, 0x29, 0xf3, 0xa9, 0x07, 0x8d, 0x00, 0xf0,
+ 0x60, 0x00, 0x20, 0x60, 0xec, 0x4c, 0x60, 0xfc, 0x20, 0x80, 0xec, 0x4c, 0x80, 0xfc
+};
+
+bool SidTune::MUS_mergeParts(Buffer_sidtt<const uint8_t>& musBuf,
+ Buffer_sidtt<const uint8_t>& strBuf)
+{
+ Buffer_sidtt<uint8_t> mergeBuf;
+
+ uint_least32_t mergeLen = musBuf.len()+strBuf.len();
+
+ musDataLen = musBuf.len()-2;
+
+ // Sanity check. I do not trust those MUS/STR files around.
+ uint_least32_t freeSpace = endian_16(_sidtune_sidplayer1[1],_sidtune_sidplayer1[0])
+ - SIDTUNE_MUS_DATA_ADDR;
+ if ( (musBuf.len()+strBuf.len()-4) > freeSpace)
+ {
+ info.statusString = _sidtune_txt_sizeExceeded;
+ return false;
+ }
+
+#ifdef HAVE_EXCEPTIONS
+ if ( !mergeBuf.assign(new(std::nothrow) uint8_t[mergeLen],mergeLen) )
+#else
+ if ( !mergeBuf.assign(new uint8_t[mergeLen],mergeLen) )
+#endif
+ {
+ info.statusString = _sidtune_txt_notEnoughMemory;
+ return false;
+ }
+
+ // Install MUS data #1 including load address.
+#ifndef SID_HAVE_BAD_COMPILER
+ memcpy(mergeBuf.get(),musBuf.get(),musBuf.len());
+#else
+ memcpy((void*)mergeBuf.get(),musBuf.get(),musBuf.len());
+#endif
+
+ if ( !strBuf.isEmpty() && info.sidChipBase2!=0 )
+ {
+ // Install MUS data #2 _NOT_ including load address.
+#ifndef SID_HAVE_BAD_COMPILER
+ memcpy(mergeBuf.get()+musBuf.len(),strBuf.get()+2,strBuf.len()-2);
+#else
+ memcpy((void*)(mergeBuf.get()+musBuf.len()),strBuf.get()+2,strBuf.len()-2);
+#endif
+ }
+
+ musBuf.assign(mergeBuf.xferPtr(),mergeBuf.xferLen());
+ strBuf.erase();
+
+ return true;
+}
+
+void SidTune::MUS_installPlayer(uint8_t *c64buf)
+{
+ if (status && (c64buf != 0))
+ {
+ // Install MUS player #1.
+ uint_least16_t dest = endian_16(_sidtune_sidplayer1[1],
+ _sidtune_sidplayer1[0]);
+ memcpy(c64buf+dest,_sidtune_sidplayer1+2,sizeof(_sidtune_sidplayer1)-2);
+ // Point player #1 to data #1.
+ c64buf[dest+0xc6e] = SIDTUNE_MUS_DATA_ADDR&0xFF;
+ c64buf[dest+0xc70] = SIDTUNE_MUS_DATA_ADDR>>8;
+
+ if (info.sidChipBase2 != 0)
+ {
+ // Install MUS player #2.
+ dest = endian_16(_sidtune_sidplayer2[1],
+ _sidtune_sidplayer2[0]);
+ memcpy(c64buf+dest,_sidtune_sidplayer2+2,sizeof(_sidtune_sidplayer2)-2);
+ // Point player #2 to data #2.
+ c64buf[dest+0xc6e] = (SIDTUNE_MUS_DATA_ADDR+musDataLen)&0xFF;
+ c64buf[dest+0xc70] = (SIDTUNE_MUS_DATA_ADDR+musDataLen)>>8;
+ }
+ }
+}
diff --git a/sid/sidplay-libs-2.1.0/libsidplay/src/sidtune/Makefile.am b/sid/sidplay-libs-2.1.0/libsidplay/src/sidtune/Makefile.am
new file mode 100644
index 00000000..e1c06822
--- /dev/null
+++ b/sid/sidplay-libs-2.1.0/libsidplay/src/sidtune/Makefile.am
@@ -0,0 +1,17 @@
+
+noinst_LTLIBRARIES = libsidtune.la
+
+libsidtune_la_SOURCES = IconInfo.cpp \
+InfoFile.cpp \
+MUS.cpp \
+PP20.cpp \
+PP20.h \
+PP20_Defs.h \
+PSID.cpp \
+SidTune.cpp \
+SidTuneCfg.h \
+SidTuneTools.cpp \
+SidTuneTools.h
+
+# Remove bad default includes
+DEFAULT_INCLUDES=
diff --git a/sid/sidplay-libs-2.1.0/libsidplay/src/sidtune/Makefile.in b/sid/sidplay-libs-2.1.0/libsidplay/src/sidtune/Makefile.in
new file mode 100644
index 00000000..bb5a7c27
--- /dev/null
+++ b/sid/sidplay-libs-2.1.0/libsidplay/src/sidtune/Makefile.in
@@ -0,0 +1,446 @@
+# Makefile.in generated by automake 1.7.1 from Makefile.am.
+# @configure_input@
+
+# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002
+# 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@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+top_builddir = ../..
+
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+INSTALL = @INSTALL@
+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 = :
+host_triplet = @host@
+ACLOCAL = @ACLOCAL@
+ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@
+AMDEP_FALSE = @AMDEP_FALSE@
+AMDEP_TRUE = @AMDEP_TRUE@
+AMTAR = @AMTAR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO = @ECHO@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIBVERSION = @LIBVERSION@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+RANLIB = @RANLIB@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SID_HAVE_BOOL = @SID_HAVE_BOOL@
+SID_HAVE_STDBOOL_H = @SID_HAVE_STDBOOL_H@
+SID_SIZEOF_CHAR = @SID_SIZEOF_CHAR@
+SID_SIZEOF_INT = @SID_SIZEOF_INT@
+SID_SIZEOF_LONG_INT = @SID_SIZEOF_LONG_INT@
+SID_SIZEOF_SHORT_INT = @SID_SIZEOF_SHORT_INT@
+SID_WORDS_ENDIANESS = @SID_WORDS_ENDIANESS@
+STRIP = @STRIP@
+VERSION = @VERSION@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_RANLIB = @ac_ct_RANLIB@
+ac_ct_STRIP = @ac_ct_STRIP@
+am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
+am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
+am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
+am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@
+am__include = @am__include@
+am__quote = @am__quote@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builders = @builders@
+datadir = @datadir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+oldincludedir = @oldincludedir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+
+noinst_LTLIBRARIES = libsidtune.la
+
+libsidtune_la_SOURCES = IconInfo.cpp \
+InfoFile.cpp \
+MUS.cpp \
+PP20.cpp \
+PP20.h \
+PP20_Defs.h \
+PSID.cpp \
+SidTune.cpp \
+SidTuneCfg.h \
+SidTuneTools.cpp \
+SidTuneTools.h
+
+
+# Remove bad default includes
+DEFAULT_INCLUDES =
+subdir = src/sidtune
+mkinstalldirs = $(SHELL) $(top_srcdir)/unix/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/unix/config.h
+CONFIG_CLEAN_FILES =
+LTLIBRARIES = $(noinst_LTLIBRARIES)
+
+libsidtune_la_LDFLAGS =
+libsidtune_la_LIBADD =
+am_libsidtune_la_OBJECTS = IconInfo.lo InfoFile.lo MUS.lo PP20.lo \
+ PSID.lo SidTune.lo SidTuneTools.lo
+libsidtune_la_OBJECTS = $(am_libsidtune_la_OBJECTS)
+depcomp = $(SHELL) $(top_srcdir)/unix/depcomp
+am__depfiles_maybe = depfiles
+@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/IconInfo.Plo \
+@AMDEP_TRUE@ ./$(DEPDIR)/InfoFile.Plo ./$(DEPDIR)/MUS.Plo \
+@AMDEP_TRUE@ ./$(DEPDIR)/PP20.Plo ./$(DEPDIR)/PSID.Plo \
+@AMDEP_TRUE@ ./$(DEPDIR)/SidTune.Plo \
+@AMDEP_TRUE@ ./$(DEPDIR)/SidTuneTools.Plo
+CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+LTCXXCOMPILE = $(LIBTOOL) --mode=compile $(CXX) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CXXFLAGS) $(CXXFLAGS)
+CXXLD = $(CXX)
+CXXLINK = $(LIBTOOL) --mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) \
+ $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+DIST_SOURCES = $(libsidtune_la_SOURCES)
+DIST_COMMON = Makefile.am Makefile.in
+SOURCES = $(libsidtune_la_SOURCES)
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .cpp .lo .o .obj
+$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.ac $(ACLOCAL_M4)
+ cd $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/sidtune/Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)
+
+clean-noinstLTLIBRARIES:
+ -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+ @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" = "$$p" && dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libsidtune.la: $(libsidtune_la_OBJECTS) $(libsidtune_la_DEPENDENCIES)
+ $(CXXLINK) $(libsidtune_la_LDFLAGS) $(libsidtune_la_OBJECTS) $(libsidtune_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT) core *.core
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/IconInfo.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/InfoFile.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MUS.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PP20.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PSID.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SidTune.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SidTuneTools.Plo@am__quote@
+
+distclean-depend:
+ -rm -rf ./$(DEPDIR)
+
+.cpp.o:
+@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \
+@am__fastdepCXX_TRUE@ -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$<; \
+@am__fastdepCXX_TRUE@ then mv "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \
+@am__fastdepCXX_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \
+@am__fastdepCXX_TRUE@ fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$<
+
+.cpp.obj:
+@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \
+@am__fastdepCXX_TRUE@ -c -o $@ `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'`; \
+@am__fastdepCXX_TRUE@ then mv "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \
+@am__fastdepCXX_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \
+@am__fastdepCXX_TRUE@ fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'`
+
+.cpp.lo:
+@am__fastdepCXX_TRUE@ if $(LTCXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \
+@am__fastdepCXX_TRUE@ -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$<; \
+@am__fastdepCXX_TRUE@ then mv "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; \
+@am__fastdepCXX_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \
+@am__fastdepCXX_TRUE@ fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ depfile='$(DEPDIR)/$*.Plo' tmpdepfile='$(DEPDIR)/$*.TPlo' @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LTCXXCOMPILE) -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+distclean-libtool:
+ -rm -f libtool
+uninstall-info-am:
+
+ETAGS = etags
+ETAGSFLAGS =
+
+CTAGS = ctags
+CTAGSFLAGS =
+
+tags: TAGS
+
+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; } \
+ END { for (i in files) print i; }'`; \
+ mkid -fID $$unique
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ 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; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(ETAGS_ARGS)$$tags$$unique" \
+ || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$tags $$unique
+
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ 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; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(CTAGS_ARGS)$$tags$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$tags $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && cd $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+
+top_distdir = ../..
+distdir = $(top_distdir)/$(PACKAGE)-$(VERSION)
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
+ list='$(DISTFILES)'; for file in $$list; do \
+ case $$file in \
+ $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
+ $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
+ esac; \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+ dir="/$$dir"; \
+ $(mkinstalldirs) "$(distdir)$$dir"; \
+ else \
+ dir=''; \
+ fi; \
+ if test -d $$d/$$file; then \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+ fi; \
+ cp -pR $$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 $(LTLIBRARIES)
+
+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:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -rm -f Makefile $(CONFIG_CLEAN_FILES)
+
+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-noinstLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+
+distclean-am: clean-am distclean-compile distclean-depend \
+ distclean-generic distclean-libtool distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-exec-am:
+
+install-info: install-info-am
+
+install-man:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+
+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: uninstall-info-am
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-noinstLTLIBRARIES ctags distclean \
+ distclean-compile distclean-depend distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am info \
+ info-am install install-am install-data install-data-am \
+ install-exec install-exec-am install-info install-info-am \
+ install-man 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 uninstall-info-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/sid/sidplay-libs-2.1.0/libsidplay/src/sidtune/PP20.cpp b/sid/sidplay-libs-2.1.0/libsidplay/src/sidtune/PP20.cpp
new file mode 100644
index 00000000..8bec5cfe
--- /dev/null
+++ b/sid/sidplay-libs-2.1.0/libsidplay/src/sidtune/PP20.cpp
@@ -0,0 +1,289 @@
+/*
+ * /home/ms/files/source/libsidtune/RCS/PP20.cpp,v
+ *
+ * PowerPacker (AMIGA) "PP20" format decompressor.
+ * Copyright (C) Michael Schwendt <mschwendt@yahoo.com>
+ *
+ * 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 "PP20.h"
+
+#include <string.h>
+#ifdef PP20_HAVE_EXCEPTIONS
+#include <new>
+#endif
+
+/* Read a big-endian 32-bit word from four bytes in memory.
+ No endian-specific optimizations applied. */
+inline udword_ppt readBEdword(const ubyte_ppt ptr[4])
+{
+ return ( (((udword_ppt)ptr[0])<<24) + (((udword_ppt)ptr[1])<<16) +
+ (((udword_ppt)ptr[2])<<8) + ((udword_ppt)ptr[3]) );
+}
+
+const char _pp20_txt_packeddatacorrupt[] = "PowerPacker: Packed data is corrupt";
+const char _pp20_txt_unrecognized[] = "PowerPacker: Unrecognized compression method";
+const char _pp20_txt_uncompressed[] = "Not compressed with PowerPacker (PP20)";
+const char _pp20_txt_notenoughmemory[] = "Not enough free memory";
+const char _pp20_txt_fast[] = "PowerPacker: fast compression";
+const char _pp20_txt_mediocre[] = "PowerPacker: mediocre compression";
+const char _pp20_txt_good[] = "PowerPacker: good compression";
+const char _pp20_txt_verygood[] = "PowerPacker: very good compression";
+const char _pp20_txt_best[] = "PowerPacker: best compression";
+const char _pp20_txt_na[] = "N/A";
+
+const char* PP20::PP_ID = "PP20";
+
+PP20::PP20()
+{
+ statusString = _pp20_txt_uncompressed;
+}
+
+bool PP20::isCompressed(const void* source, const udword_ppt size)
+{
+ // Check minimum input size, PP20 ID, and efficiency table.
+ if ( size<8 )
+ {
+ return false;
+ }
+ // We hope that every file with a valid signature and a valid
+ // efficiency table is PP-compressed actually.
+ const char* idPtr = (const char*)source;
+ if ( strncmp(idPtr,PP_ID,4) != 0 )
+ {
+ statusString = _pp20_txt_uncompressed;
+ return false;
+ }
+ return checkEfficiency(idPtr+4);
+}
+
+bool PP20::checkEfficiency(const void* source)
+{
+ const udword_ppt PP_BITS_FAST = 0x09090909;
+ const udword_ppt PP_BITS_MEDIOCRE = 0x090a0a0a;
+ const udword_ppt PP_BITS_GOOD = 0x090a0b0b;
+ const udword_ppt PP_BITS_VERYGOOD = 0x090a0c0c;
+ const udword_ppt PP_BITS_BEST = 0x090a0c0d;
+
+ // Copy efficiency table.
+ memcpy(efficiency,(const ubyte_ppt*)source,4);
+ udword_ppt eff = readBEdword(efficiency);
+ if (( eff != PP_BITS_FAST ) &&
+ ( eff != PP_BITS_MEDIOCRE ) &&
+ ( eff != PP_BITS_GOOD ) &&
+ ( eff != PP_BITS_VERYGOOD ) &&
+ ( eff != PP_BITS_BEST ))
+ {
+ statusString = _pp20_txt_unrecognized;
+ return false;
+ }
+
+ // Define string describing compression encoding used.
+ switch ( eff)
+ {
+ case PP_BITS_FAST:
+ statusString = _pp20_txt_fast;
+ break;
+ case PP_BITS_MEDIOCRE:
+ statusString = _pp20_txt_mediocre;
+ break;
+ case PP_BITS_GOOD:
+ statusString = _pp20_txt_good;
+ break;
+ case PP_BITS_VERYGOOD:
+ statusString = _pp20_txt_verygood;
+ break;
+ case PP_BITS_BEST:
+ statusString = _pp20_txt_best;
+ break;
+ }
+
+ return true;
+}
+
+// Move four bytes to Motorola big-endian double-word.
+inline void PP20::bytesTOdword()
+{
+ readPtr -= 4;
+ if ( readPtr < sourceBeg )
+ {
+ statusString = _pp20_txt_packeddatacorrupt;
+ globalError = true;
+ }
+ else
+ {
+ current = readBEdword(readPtr);
+ }
+}
+
+inline udword_ppt PP20::readBits(int count)
+{
+ udword_ppt data = 0;
+ // read 'count' bits of packed data
+ for (; count > 0; count--)
+ {
+ // equal to shift left
+ data += data;
+ // merge bit 0
+ data |= (current&1);
+ current >>= 1;
+ if (--bits == 0)
+ {
+ bytesTOdword();
+ bits = 32;
+ }
+ }
+ return data;
+}
+
+inline void PP20::bytes()
+{
+ udword_ppt count, add;
+ count = (add = readBits(2));
+ while (add == 3)
+ {
+ add = readBits(2);
+ count += add;
+ }
+ for ( ++count; count > 0 ; count--)
+ {
+ if (writePtr > destBeg)
+ {
+ *(--writePtr) = (ubyte_ppt)readBits(8);
+ }
+ else
+ {
+ statusString = _pp20_txt_packeddatacorrupt;
+ globalError = true;
+ }
+ }
+}
+
+inline void PP20::sequence()
+{
+ udword_ppt offset, add;
+ udword_ppt length = readBits(2); // is length-2
+ int offsetBitLen = (int)efficiency[length];
+ length += 2;
+ if ( length != 5 )
+ offset = readBits( offsetBitLen );
+ else
+ {
+ if ( readBits(1) == 0 )
+ offsetBitLen = 7;
+ offset = readBits( offsetBitLen );
+ add = readBits(3);
+ length += add;
+ while ( add == 7 )
+ {
+ add = readBits(3);
+ length += add;
+ }
+ }
+ for ( ; length > 0 ; length-- )
+ {
+ if ( writePtr > destBeg )
+ {
+ --writePtr;
+ *writePtr = *(writePtr+1+offset);
+ }
+ else
+ {
+ statusString = _pp20_txt_packeddatacorrupt;
+ globalError = true;
+ }
+ }
+}
+
+udword_ppt PP20::decompress(const void* source,
+ udword_ppt size,
+ ubyte_ppt** destRef)
+{
+ globalError = false; // assume no error
+
+ sourceBeg = (const ubyte_ppt*)source;
+ readPtr = sourceBeg;
+
+ if ( !isCompressed(readPtr,size) )
+ {
+ return 0;
+ }
+
+ // Uncompressed size is stored at end of source file.
+ // Backwards decompression.
+ readPtr += (size-4);
+
+ udword_ppt lastDword = readBEdword(readPtr);
+ // Uncompressed length in bits 31-8 of last dword.
+ udword_ppt outputLen = lastDword>>8;
+
+ // Allocate memory for output data.
+ ubyte_ppt* dest;
+#ifdef PP20_HAVE_EXCEPTIONS
+ if (( dest = new(std::nothrow) ubyte_ppt[outputLen]) == 0 )
+#else
+ if (( dest = new ubyte_ppt[outputLen]) == 0 )
+#endif
+ {
+ statusString = _pp20_txt_notenoughmemory;
+ return 0;
+ }
+
+ // Lowest dest. address for range-checks.
+ destBeg = dest;
+ // Put destptr to end of uncompressed data.
+ writePtr = dest+outputLen;
+
+ // Read number of unused bits in 1st data dword
+ // from lowest bits 7-0 of last dword.
+ bits = 32 - (lastDword&0xFF);
+
+ // Main decompression loop.
+ bytesTOdword();
+ if ( bits != 32 )
+ current >>= (32-bits);
+ do
+ {
+ if ( readBits(1) == 0 )
+ bytes();
+ if ( writePtr > dest )
+ sequence();
+ if ( globalError )
+ {
+ // statusString already set.
+ outputLen = 0; // unsuccessful decompression
+ break;
+ }
+ } while ( writePtr > dest );
+
+ // Finished.
+
+ if (outputLen > 0) // successful
+ {
+ // Free any previously existing destination buffer.
+ if ( *destRef != 0 )
+ {
+ delete[] *destRef;
+ }
+ *destRef = dest;
+ }
+ else
+ {
+ delete[] dest;
+ }
+
+ return outputLen;
+}
diff --git a/sid/sidplay-libs-2.1.0/libsidplay/src/sidtune/PP20.h b/sid/sidplay-libs-2.1.0/libsidplay/src/sidtune/PP20.h
new file mode 100644
index 00000000..74e7f5f7
--- /dev/null
+++ b/sid/sidplay-libs-2.1.0/libsidplay/src/sidtune/PP20.h
@@ -0,0 +1,70 @@
+/*
+ * /home/ms/files/source/libsidtune/RCS/PP20.h,v
+ *
+ * PowerPacker (AMIGA) "PP20" format decompressor.
+ * Copyright (C) Michael Schwendt <mschwendt@yahoo.com>
+ *
+ * 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 PP_DECOMPRESSOR_H
+#define PP_DECOMPRESSOR_H
+
+#include "PP20_Defs.h"
+
+class PP20
+{
+ public:
+
+ PP20();
+
+ bool isCompressed(const void* source, const udword_ppt size);
+
+ // If successful, allocates a new buffer containing the
+ // uncompresse data and returns the uncompressed length.
+ // Else, returns 0.
+ udword_ppt decompress(const void* source,
+ udword_ppt size,
+ ubyte_ppt** destRef);
+
+ const char* getStatusString() { return statusString; }
+
+ private:
+ bool checkEfficiency(const void* source);
+
+ void bytesTOdword();
+ udword_ppt readBits(int count);
+ void bytes();
+ void sequence();
+
+ static const char* PP_ID;
+
+ ubyte_ppt efficiency[4];
+
+ const ubyte_ppt* sourceBeg;
+ const ubyte_ppt* readPtr;
+
+ const ubyte_ppt* destBeg;
+ ubyte_ppt* writePtr;
+
+ udword_ppt current; // compressed data longword
+ int bits; // number of bits in 'current' to evaluate
+
+ bool globalError; // exception-free version of code
+
+ const char* statusString;
+};
+
+#endif /* PP_DECOMPRESSOR_H */
diff --git a/sid/sidplay-libs-2.1.0/libsidplay/src/sidtune/PP20_Defs.h b/sid/sidplay-libs-2.1.0/libsidplay/src/sidtune/PP20_Defs.h
new file mode 100644
index 00000000..9e3b345b
--- /dev/null
+++ b/sid/sidplay-libs-2.1.0/libsidplay/src/sidtune/PP20_Defs.h
@@ -0,0 +1,39 @@
+/*
+ * /home/ms/files/source/libsidtune/RCS/PP20_Defs.h,v
+ *
+ * PowerPacker (AMIGA) "PP20" format decompressor.
+ * Copyright (C) Michael Schwendt <mschwendt@yahoo.com>
+ *
+ * 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 PP_DECOMPRESSOR_DEFS_H
+#define PP_DECOMPRESSOR_DEFS_H
+
+#include "sidtypes.h"
+
+#ifdef HAVE_EXCEPTIONS
+ #define PP20_HAVE_EXCEPTIONS
+#else
+ #undef PP20_HAVE_EXCEPTIONS
+#endif
+
+// Wanted: 8-bit unsigned.
+typedef uint_least8_t ubyte_ppt;
+
+// Wanted: 32-bit unsigned.
+typedef uint_least32_t udword_ppt;
+
+#endif /* PP_DECOMPRESSOR_DEFS_H */
diff --git a/sid/sidplay-libs-2.1.0/libsidplay/src/sidtune/PSID.cpp b/sid/sidplay-libs-2.1.0/libsidplay/src/sidtune/PSID.cpp
new file mode 100644
index 00000000..0cc96969
--- /dev/null
+++ b/sid/sidplay-libs-2.1.0/libsidplay/src/sidtune/PSID.cpp
@@ -0,0 +1,313 @@
+/*
+ * /home/ms/files/source/libsidtune/RCS/PSID.cpp,v
+ *
+ * PlaySID one-file format support.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "config.h"
+#include "SidTuneCfg.h"
+#include "SidTune.h"
+#include "sidendian.h"
+
+#define PSID_ID 0x50534944
+#define RSID_ID 0x52534944
+
+// Header has been extended for 'RSID' format
+// The following changes are present:
+// id = 'RSID'
+// version = 2 only
+// play, load and speed reserved 0
+// psidspecific flag reserved 0
+// init cannot be under ROMS/IO
+// load cannot be less than 0x0801 (start of basic)
+
+struct psidHeader // all values big-endian
+{
+ char id[4]; // 'PSID' (ASCII)
+ uint8_t version[2]; // 0x0001 or 0x0002
+ uint8_t data[2]; // 16-bit offset to binary data in file
+ uint8_t load[2]; // 16-bit C64 address to load file to
+ uint8_t init[2]; // 16-bit C64 address of init subroutine
+ uint8_t play[2]; // 16-bit C64 address of play subroutine
+ uint8_t songs[2]; // number of songs
+ uint8_t start[2]; // start song out of [1..256]
+ uint8_t speed[4]; // 32-bit speed info
+ // bit: 0=50 Hz, 1=CIA 1 Timer A (default: 60 Hz)
+ char name[32]; // ASCII strings, 31 characters long and
+ char author[32]; // terminated by a trailing zero
+ char released[32]; //
+ uint8_t flags[2]; // only version 0x0002
+ uint8_t relocStartPage; // only version 0x0002B
+ uint8_t relocPages; // only version 0x0002B
+ uint8_t reserved[2]; // only version 0x0002
+};
+
+enum
+{
+ PSID_MUS = 1 << 0,
+ PSID_SPECIFIC = 1 << 1,
+ PSID_CLOCK = 3 << 2,
+ PSID_SIDMODEL = 3 << 4
+};
+
+enum
+{
+ PSID_CLOCK_UNKNOWN = 0,
+ PSID_CLOCK_PAL = 1 << 2,
+ PSID_CLOCK_NTSC = 1 << 3,
+ PSID_CLOCK_ANY = PSID_CLOCK_PAL | PSID_CLOCK_NTSC
+};
+
+enum
+{
+ PSID_SIDMODEL_UNKNOWN = 0,
+ PSID_SIDMODEL_6581 = 1 << 4,
+ PSID_SIDMODEL_8580 = 1 << 5,
+ PSID_SIDMODEL_ANY = PSID_SIDMODEL_6581 | PSID_SIDMODEL_8580
+};
+
+static const char _sidtune_format_psid[] = "PlaySID one-file format (PSID)";
+static const char _sidtune_format_rsid[] = "Real C64 one-file format (RSID)";
+static const char _sidtune_unknown_psid[] = "Unsupported PSID version";
+static const char _sidtune_unknown_rsid[] = "Unsupported RSID version";
+static const char _sidtune_truncated[] = "ERROR: File is most likely truncated";
+static const char _sidtune_invalid[] = "ERROR: File contains invalid data";
+
+const int _sidtune_psid_maxStrLen = 31;
+
+
+bool SidTune::PSID_fileSupport(const void* buffer, const uint_least32_t bufLen)
+{
+ int clock, compatibility;
+ uint_least32_t speed;
+#ifdef SIDTUNE_PSID2NG
+ clock = SIDTUNE_CLOCK_UNKNOWN;
+#else
+ clock = info.clockSpeed;
+#endif
+ compatibility = SIDTUNE_COMPATIBILITY_C64;
+
+ // Require minimum size to allow access to the first few bytes.
+ // Require a valid ID and version number.
+ const psidHeader* pHeader = (const psidHeader*)buffer;
+
+ // File format check
+ if (bufLen<6)
+ return false;
+ if (endian_big32((const uint_least8_t*)pHeader->id)==PSID_ID)
+ {
+ if (endian_big16(pHeader->version) >= 3)
+ {
+ info.formatString = _sidtune_unknown_psid;
+ return false;
+ }
+ info.formatString = _sidtune_format_psid;
+ }
+ else if (endian_big32((const uint_least8_t*)pHeader->id)==RSID_ID)
+ {
+ if (endian_big16(pHeader->version) != 2)
+ {
+ info.formatString = _sidtune_unknown_rsid;
+ return false;
+ }
+ info.formatString = _sidtune_format_rsid;
+ compatibility = SIDTUNE_COMPATIBILITY_R64;
+ }
+ else
+ {
+ return false;
+ }
+
+ // Due to security concerns, input must be at least as long as version 1
+ // header plus 16-bit C64 load address. That is the area which will be
+ // accessed.
+ if ( bufLen < (sizeof(psidHeader)+2) )
+ {
+ info.formatString = _sidtune_truncated;
+ return false;
+ }
+
+ fileOffset = endian_big16(pHeader->data);
+ info.loadAddr = endian_big16(pHeader->load);
+ info.initAddr = endian_big16(pHeader->init);
+ info.playAddr = endian_big16(pHeader->play);
+ info.songs = endian_big16(pHeader->songs);
+ info.startSong = endian_big16(pHeader->start);
+ info.sidChipBase1 = 0xd400;
+ info.sidChipBase2 = 0;
+ info.compatibility = compatibility;
+ speed = endian_big32(pHeader->speed);
+
+ if (info.songs > SIDTUNE_MAX_SONGS)
+ {
+ info.songs = SIDTUNE_MAX_SONGS;
+ }
+
+ info.musPlayer = false;
+ info.sidModel = SIDTUNE_SIDMODEL_UNKNOWN;
+ info.relocPages = 0;
+ info.relocStartPage = 0;
+ if ( endian_big16(pHeader->version) >= 2 )
+ {
+ uint_least16_t flags = endian_big16(pHeader->flags);
+ if (flags & PSID_MUS)
+ { // MUS tunes run at any speed
+ clock = SIDTUNE_CLOCK_ANY;
+ info.musPlayer = true;
+ }
+
+#ifdef SIDTUNE_PSID2NG
+ if (flags & PSID_SPECIFIC)
+ info.compatibility = SIDTUNE_COMPATIBILITY_PSID;
+
+ if (flags & PSID_CLOCK_PAL)
+ clock |= SIDTUNE_CLOCK_PAL;
+ if (flags & PSID_CLOCK_NTSC)
+ clock |= SIDTUNE_CLOCK_NTSC;
+ info.clockSpeed = clock;
+
+ info.sidModel = SIDTUNE_SIDMODEL_UNKNOWN;
+ if (flags & PSID_SIDMODEL_6581)
+ info.sidModel |= SIDTUNE_SIDMODEL_6581;
+ if (flags & PSID_SIDMODEL_8580)
+ info.sidModel |= SIDTUNE_SIDMODEL_8580;
+
+ info.relocStartPage = pHeader->relocStartPage;
+ info.relocPages = pHeader->relocPages;
+#endif // SIDTUNE_PSID2NG
+ }
+
+ // Reserved meaning for possible future use
+ if ( info.playAddr == 0xffff )
+ info.playAddr = 0;
+
+ // Check reserved fields to force real c64 compliance
+ if (compatibility == SIDTUNE_COMPATIBILITY_R64)
+ {
+ if (checkRealC64Info (speed) == false)
+ {
+ info.formatString = _sidtune_invalid;
+ return false;
+ }
+ // Real C64 tunes appear as CIA
+ speed = ~0;
+ }
+ // Create the speed/clock setting table.
+ convertOldStyleSpeedToTables(speed, clock);
+
+ if ( info.loadAddr == 0 )
+ {
+ uint_least8_t* pData = (uint_least8_t*)buffer + fileOffset;
+ info.loadAddr = endian_16( *(pData+1), *pData );
+ fileOffset += 2;
+ }
+
+ info.c64dataLen = bufLen - fileOffset;
+ if ( resolveAddrs((uint_least8_t*)buffer + fileOffset) == false )
+ return false;
+
+ if ( checkRelocInfo() == false )
+ return false;
+
+ // Copy info strings, so they will not get lost.
+ info.numberOfInfoStrings = 3;
+ // Name
+ strncpy(&infoString[0][0],pHeader->name,_sidtune_psid_maxStrLen);
+ info.infoString[0] = &infoString[0][0];
+ // Author
+ strncpy(&infoString[1][0],pHeader->author,_sidtune_psid_maxStrLen);
+ info.infoString[1] = &infoString[1][0];
+ // Released
+ strncpy(&infoString[2][0],pHeader->released,_sidtune_psid_maxStrLen);
+ info.infoString[2] = &infoString[2][0];
+ return true;
+}
+
+
+bool SidTune::PSID_fileSupportSave(std::ofstream& fMyOut, const uint_least8_t* dataBuffer)
+{
+ psidHeader myHeader;
+ endian_big32((uint_least8_t*)myHeader.id,PSID_ID);
+ endian_big16(myHeader.version,2);
+ endian_big16(myHeader.data,sizeof(psidHeader));
+ endian_big16(myHeader.load,0);
+ endian_big16(myHeader.init,info.initAddr);
+ endian_big16(myHeader.play,info.playAddr);
+ endian_big16(myHeader.songs,info.songs);
+ endian_big16(myHeader.start,info.startSong);
+
+ uint_least32_t speed = 0, check = 0;
+ uint_least32_t maxBugSongs = ((info.songs <= 32) ? info.songs : 32);
+ for (uint_least32_t s = 0; s < maxBugSongs; s++)
+ {
+ if (songSpeed[s] == SIDTUNE_SPEED_CIA_1A)
+ speed |= (1<<s);
+ check |= (1<<s);
+ }
+ endian_big32(myHeader.speed,speed);
+
+ uint_least16_t tmpFlags = 0;
+ if ( info.musPlayer )
+ tmpFlags |= PSID_MUS;
+
+ if (info.compatibility == SIDTUNE_COMPATIBILITY_PSID)
+ tmpFlags |= PSID_SPECIFIC;
+
+ tmpFlags |= (info.clockSpeed << 2);
+ tmpFlags |= (info.sidModel << 4);
+ endian_big16(myHeader.flags,tmpFlags);
+ endian_big16(myHeader.reserved,0);
+ myHeader.relocStartPage = info.relocStartPage;
+ myHeader.relocPages = info.relocPages;
+
+ for ( uint i = 0; i < 32; i++ )
+ {
+ myHeader.name[i] = 0;
+ myHeader.author[i] = 0;
+ myHeader.released[i] = 0;
+ }
+ strncpy( myHeader.name, info.infoString[0], _sidtune_psid_maxStrLen);
+ strncpy( myHeader.author, info.infoString[1], _sidtune_psid_maxStrLen);
+ strncpy( myHeader.released, info.infoString[2], _sidtune_psid_maxStrLen);
+
+ if (info.compatibility == SIDTUNE_COMPATIBILITY_R64)
+ {
+ endian_big32((uint_least8_t*)myHeader.id,RSID_ID);
+ endian_big16(myHeader.play,0);
+ endian_big32(myHeader.speed,0);
+ }
+
+ fMyOut.write( (char*)&myHeader, sizeof(psidHeader) );
+
+ // Save C64 lo/hi load address (little-endian).
+ uint_least8_t saveAddr[2];
+ saveAddr[0] = info.loadAddr & 255;
+ saveAddr[1] = info.loadAddr >> 8;
+ fMyOut.write( (char*)saveAddr, 2 ); // !cast!
+
+ // Data starts at: bufferaddr + fileoffset
+ // Data length: datafilelen - fileoffset
+ fMyOut.write( (const char*)dataBuffer + fileOffset, info.dataFileLen - fileOffset ); // !cast!
+ if ( !fMyOut )
+ return false;
+ else
+ return true;
+}
diff --git a/sid/sidplay-libs-2.1.0/libsidplay/src/sidtune/SidTune.cpp b/sid/sidplay-libs-2.1.0/libsidplay/src/sidtune/SidTune.cpp
new file mode 100644
index 00000000..29638775
--- /dev/null
+++ b/sid/sidplay-libs-2.1.0/libsidplay/src/sidtune/SidTune.cpp
@@ -0,0 +1,1150 @@
+/*
+ * /home/ms/files/source/libsidtune/RCS/SidTune.cpp,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
+ */
+
+#define _SidTune_cpp_
+
+#include "config.h"
+#include "SidTuneCfg.h"
+#include "SidTune.h"
+#include "SidTuneTools.h"
+#include "sidendian.h"
+#include "PP20.h"
+
+#ifdef HAVE_EXCEPTIONS
+# include <new>
+#endif
+#include <iostream>
+#include <iomanip>
+#include <string.h>
+#include <limits.h>
+
+#if defined(HAVE_IOS_OPENMODE)
+ typedef std::ios::openmode openmode;
+#else
+ typedef int openmode;
+#endif
+
+// Used in address resolution procedure
+#define SIDTUNE_BASIC_START 0x0801
+
+const char* SidTune::txt_songNumberExceed = "SIDTUNE WARNING: Selected song number was too high";
+const char* SidTune::txt_empty = "SIDTUNE ERROR: No data to load";
+const char* SidTune::txt_unrecognizedFormat = "SIDTUNE ERROR: Could not determine file format";
+const char* SidTune::txt_noDataFile = "SIDTUNE ERROR: Did not find the corresponding data file";
+const char* SidTune::txt_notEnoughMemory = "SIDTUNE ERROR: Not enough free memory";
+const char* SidTune::txt_cantLoadFile = "SIDTUNE ERROR: Could not load input file";
+const char* SidTune::txt_cantOpenFile = "SIDTUNE ERROR: Could not open file for binary input";
+const char* SidTune::txt_fileTooLong = "SIDTUNE ERROR: Input data too long";
+const char* SidTune::txt_dataTooLong = "SIDTUNE ERROR: Size of music data exceeds C64 memory";
+const char* SidTune::txt_cantCreateFile = "SIDTUNE ERROR: Could not create output file";
+const char* SidTune::txt_fileIoError = "SIDTUNE ERROR: File I/O error";
+const char* SidTune::txt_VBI = "VBI";
+const char* SidTune::txt_CIA = "CIA 1 Timer A";
+const char* SidTune::txt_noErrors = "No errors";
+const char* SidTune::txt_na = "N/A";
+const char* SidTune::txt_badAddr = "SIDTUNE ERROR: Bad address data";
+const char* SidTune::txt_badReloc = "SIDTUNE ERROR: Bad reloc data";
+
+// Default sidtune file name extensions. This selection can be overriden
+// by specifying a custom list in the constructor.
+const char* defaultFileNameExt[] =
+{
+ // Preferred default file extension for single-file sidtunes
+ // or sidtune description files in SIDPLAY INFOFILE format.
+ ".sid",
+ // Common file extension for single-file sidtunes due to SIDPLAY/DOS
+ // displaying files *.DAT in its file selector by default.
+ // Originally this was intended to be the extension of the raw data file
+ // of two-file sidtunes in SIDPLAY INFOFILE format.
+ ".dat",
+ // Extension of Amiga Workbench tooltype icon info files, which
+ // have been cut to MS-DOS file name length (8.3).
+ ".inf",
+ // No extension for the raw data file of two-file sidtunes in
+ // PlaySID Amiga Workbench tooltype icon info format.
+ "",
+ // Common upper-case file extensions from MS-DOS (unconverted).
+ ".DAT", ".SID", ".INF",
+ // File extensions used (and created) by various C64 emulators and
+ // related utilities. These extensions are recommended to be used as
+ // a replacement for ".dat" in conjunction with two-file sidtunes.
+ ".c64", ".prg", ".C64", ".PRG",
+ // Uncut extensions from Amiga.
+ ".info", ".INFO", ".data", ".DATA",
+ // Stereo Sidplayer (.mus/.MUS ought not be included because
+ // these must be loaded first; it sometimes contains the first
+ // credit lines of a MUS/STR pair).
+ ".str", ".STR", ".mus", ".MUS",
+ // End.
+ 0
+};
+
+const char** SidTune::fileNameExtensions = defaultFileNameExt;
+
+inline void SidTune::setFileNameExtensions(const char **fileNameExt)
+{
+ fileNameExtensions = ((fileNameExt!=0)?fileNameExt:defaultFileNameExt);
+}
+
+SidTune::SidTune(const char* fileName, const char **fileNameExt,
+ const bool separatorIsSlash)
+{
+ init();
+ isSlashedFileName = separatorIsSlash;
+ setFileNameExtensions(fileNameExt);
+#if !defined(SIDTUNE_NO_STDIN_LOADER)
+ // Filename ``-'' is used as a synonym for standard input.
+ if ( fileName!=0 && (strcmp(fileName,"-")==0) )
+ {
+ getFromStdIn();
+ }
+ else
+#endif
+ if (fileName != 0)
+ {
+ getFromFiles(fileName);
+ }
+}
+
+SidTune::SidTune(const uint_least8_t* data, const uint_least32_t dataLen)
+{
+ init();
+ getFromBuffer(data,dataLen);
+}
+
+SidTune::~SidTune()
+{
+ cleanup();
+}
+
+bool SidTune::load(const char* fileName, const bool separatorIsSlash)
+{
+ cleanup();
+ init();
+ isSlashedFileName = separatorIsSlash;
+ getFromFiles(fileName);
+ return status;
+}
+
+bool SidTune::read(const uint_least8_t* data, uint_least32_t dataLen)
+{
+ cleanup();
+ init();
+ getFromBuffer(data,dataLen);
+ return status;
+}
+
+const SidTuneInfo& SidTune::operator[](const uint_least16_t songNum)
+{
+ selectSong(songNum);
+ return info;
+}
+
+void SidTune::getInfo(SidTuneInfo& outInfo)
+{
+ outInfo = info; // copy
+}
+
+const SidTuneInfo& SidTune::getInfo()
+{
+ return info;
+}
+
+// First check, whether a song is valid. Then copy any song-specific
+// variable information such a speed/clock setting to the info structure.
+uint_least16_t SidTune::selectSong(const uint_least16_t selectedSong)
+{
+ if ( !status )
+ return 0;
+ else
+ info.statusString = SidTune::txt_noErrors;
+
+ uint_least16_t song = selectedSong;
+ // Determine and set starting song number.
+ if (selectedSong == 0)
+ song = info.startSong;
+ if (selectedSong>info.songs || selectedSong>SIDTUNE_MAX_SONGS)
+ {
+ song = info.startSong;
+ info.statusString = SidTune::txt_songNumberExceed;
+ }
+ info.currentSong = song;
+ info.songLength = songLength[song-1];
+ // Retrieve song speed definition.
+ info.songSpeed = songSpeed[song-1];
+ info.clockSpeed = clockSpeed[song-1];
+ // Assign song speed description string depending on clock speed.
+ // Final speed description is available only after song init.
+ if (info.songSpeed == SIDTUNE_SPEED_VBI)
+ info.speedString = txt_VBI;
+ else
+ info.speedString = txt_CIA;
+ return info.currentSong;
+}
+
+void SidTune::fixLoadAddress(bool force, uint_least16_t init, uint_least16_t play)
+{
+ if (info.fixLoad || force)
+ {
+ info.fixLoad = false;
+ info.loadAddr += 2;
+ fileOffset += 2;
+
+ if (force)
+ {
+ info.initAddr = init;
+ info.playAddr = play;
+ }
+ }
+}
+
+// ------------------------------------------------- private member functions
+
+bool SidTune::placeSidTuneInC64mem(uint_least8_t* c64buf)
+{
+ if ( status && c64buf!=0 )
+ {
+ uint_least32_t endPos = info.loadAddr + info.c64dataLen;
+ if (endPos <= SIDTUNE_MAX_MEMORY)
+ {
+ // Copy data from cache to the correct destination.
+ memcpy(c64buf+info.loadAddr,cache.get()+fileOffset,info.c64dataLen);
+ info.statusString = SidTune::txt_noErrors;
+ }
+ else
+ {
+ // Security - cut data which would exceed the end of the C64
+ // memory. Memcpy could not detect this.
+ //
+ // NOTE: In libsidplay1 the rest gets wrapped to the beginning
+ // of the C64 memory. It is an undocumented hack most likely not
+ // used by any sidtune. Here we no longer do it like that, set
+ // an error message, and hope the modified behaviour will find
+ // a few badly ripped sids.
+ memcpy(c64buf+info.loadAddr,cache.get()+fileOffset,info.c64dataLen-(endPos-SIDTUNE_MAX_MEMORY));
+ info.statusString = SidTune::txt_dataTooLong;
+ }
+ if (info.musPlayer)
+ {
+ MUS_installPlayer(c64buf);
+ }
+ }
+ return ( status && c64buf!=0 );
+}
+
+bool SidTune::loadFile(const char* fileName, Buffer_sidtt<const uint_least8_t>& bufferRef)
+{
+ Buffer_sidtt<uint_least8_t> fileBuf;
+ uint_least32_t fileLen = 0;
+
+ // This sucks big time
+ //openmode createAtrr = std::ios::in;
+ std::_Ios_Openmode createAtrr = std::ios::in;
+#ifdef HAVE_IOS_NOCREATE
+ createAtrr |= std::ios::nocreate;
+#endif
+ // Open binary input file stream at end of file.
+#if defined(HAVE_IOS_BIN)
+ createAtrr |= std::ios::bin;
+#else
+ createAtrr |= std::ios::binary;
+#endif
+
+ std::fstream myIn(fileName,createAtrr);
+ // As a replacement for !is_open(), bad() and the NOT-operator don't seem
+ // to work on all systems.
+#if defined(DONT_HAVE_IS_OPEN)
+ if ( !myIn )
+#else
+ if ( !myIn.is_open() )
+#endif
+ {
+ info.statusString = SidTune::txt_cantOpenFile;
+ return false;
+ }
+ else
+ {
+#if defined(HAVE_SEEKG_OFFSET)
+ fileLen = (myIn.seekg(0,std::ios::end)).offset();
+#else
+ myIn.seekg(0,std::ios::end);
+ fileLen = (uint_least32_t)myIn.tellg();
+#endif
+#ifdef HAVE_EXCEPTIONS
+ if ( !fileBuf.assign(new(std::nothrow) uint_least8_t[fileLen],fileLen) )
+#else
+ if ( !fileBuf.assign(new uint_least8_t[fileLen],fileLen) )
+#endif
+ {
+ info.statusString = SidTune::txt_notEnoughMemory;
+ return false;
+ }
+ myIn.seekg(0,std::ios::beg);
+ uint_least32_t restFileLen = fileLen;
+ // 16-bit compatible loading. Is this really necessary?
+ while ( restFileLen > INT_MAX )
+ {
+ myIn.read((char*)fileBuf.get()+(fileLen-restFileLen),INT_MAX); // !cast!
+ restFileLen -= INT_MAX;
+ }
+ if ( restFileLen > 0 )
+ {
+ myIn.read((char*)fileBuf.get()+(fileLen-restFileLen),restFileLen); // !cast!
+ }
+ if ( myIn.bad() )
+ {
+ info.statusString = SidTune::txt_cantLoadFile;
+ return false;
+ }
+ else
+ {
+ info.statusString = SidTune::txt_noErrors;
+ }
+ }
+ myIn.close();
+ if ( fileLen==0 )
+ {
+ info.statusString = SidTune::txt_empty;
+ return false;
+ }
+
+ // Check for PowerPacker compression: load and decompress, if PP20 file.
+ PP20 myPP;
+ if ( myPP.isCompressed(fileBuf.get(),fileBuf.len()) )
+ {
+ uint_least8_t* destBufRef = 0;
+ if ( 0 == (fileLen = myPP.decompress(fileBuf.get(),fileBuf.len(),
+ &destBufRef)) )
+ {
+ info.statusString = myPP.getStatusString();
+ return false;
+ }
+ else
+ {
+ info.statusString = myPP.getStatusString();
+ // Replace compressed buffer with uncompressed buffer.
+ fileBuf.assign(destBufRef,fileLen);
+ }
+ }
+
+ bufferRef.assign(fileBuf.xferPtr(),fileBuf.xferLen());
+
+ return true;
+}
+
+void SidTune::deleteFileNameCopies()
+{
+ // When will it be fully safe to call delete[](0) on every system?
+ if ( info.dataFileName != 0 )
+ delete[] info.dataFileName;
+ if ( info.infoFileName != 0 )
+ delete[] info.infoFileName;
+ if ( info.path != 0 )
+ delete[] info.path;
+ info.dataFileName = 0;
+ info.infoFileName = 0;
+ info.path = 0;
+}
+
+void SidTune::init()
+{
+ // Initialize the object with some safe defaults.
+ status = false;
+
+ info.statusString = SidTune::txt_na;
+ info.path = info.infoFileName = info.dataFileName = 0;
+ info.dataFileLen = info.c64dataLen = 0;
+ info.formatString = SidTune::txt_na;
+ info.speedString = SidTune::txt_na;
+ info.loadAddr = ( info.initAddr = ( info.playAddr = 0 ));
+ info.songs = ( info.startSong = ( info.currentSong = 0 ));
+ info.sidChipBase1 = 0xd400;
+ info.sidChipBase2 = 0;
+ info.musPlayer = false;
+ info.fixLoad = false;
+ info.songSpeed = SIDTUNE_SPEED_VBI;
+#ifdef SIDTUNE_PSID2NG
+ info.clockSpeed = SIDTUNE_CLOCK_UNKNOWN;
+ info.sidModel = SIDTUNE_SIDMODEL_UNKNOWN;
+#else
+ info.clockSpeed = SIDTUNE_CLOCK_PAL;
+ info.sidModel = SIDTUNE_SIDMODEL_6581;
+#endif
+ info.compatibility = SIDTUNE_COMPATIBILITY_C64;
+ info.songLength = 0;
+ info.relocStartPage = 0;
+ info.relocPages = 0;
+
+ for ( uint_least16_t si = 0; si < SIDTUNE_MAX_SONGS; si++ )
+ {
+ songSpeed[si] = info.songSpeed;
+ clockSpeed[si] = info.clockSpeed;
+ songLength[si] = 0;
+ }
+
+ fileOffset = 0;
+ musDataLen = 0;
+
+ for ( uint_least16_t sNum = 0; sNum < SIDTUNE_MAX_CREDIT_STRINGS; sNum++ )
+ {
+ for ( uint_least16_t sPos = 0; sPos < SIDTUNE_MAX_CREDIT_STRLEN; sPos++ )
+ {
+ infoString[sNum][sPos] = 0;
+ }
+ }
+ info.numberOfInfoStrings = 0;
+
+ // Not used!!!
+ info.numberOfCommentStrings = 1;
+#ifdef HAVE_EXCEPTIONS
+ info.commentString = new(std::nothrow) char* [info.numberOfCommentStrings];
+#else
+ info.commentString = new char* [info.numberOfCommentStrings];
+#endif
+ if (info.commentString != 0)
+ info.commentString[0] = SidTuneTools::myStrDup("--- SAVED WITH SIDPLAY ---");
+ else
+ info.commentString[0] = 0;
+}
+
+void SidTune::cleanup()
+{
+ // Remove copy of comment field.
+ uint_least32_t strNum = 0;
+ // Check and remove every available line.
+ while (info.numberOfCommentStrings-- > 0)
+ {
+ if (info.commentString[strNum] != 0)
+ {
+ delete[] info.commentString[strNum];
+ info.commentString[strNum] = 0;
+ }
+ strNum++; // next string
+ };
+ delete[] info.commentString; // free the array pointer
+
+ deleteFileNameCopies();
+
+ status = false;
+}
+
+#if !defined(SIDTUNE_NO_STDIN_LOADER)
+
+void SidTune::getFromStdIn()
+{
+ // Assume a failure, so we can simply return.
+ status = false;
+ // Assume the memory allocation to fail.
+ info.statusString = SidTune::txt_notEnoughMemory;
+ uint_least8_t* fileBuf;
+#ifdef HAVE_EXCEPTIONS
+ if ( 0 == (fileBuf = new(std::nothrow) uint_least8_t[SIDTUNE_MAX_FILELEN]) )
+#else
+ if ( 0 == (fileBuf = new uint_least8_t[SIDTUNE_MAX_FILELEN]) )
+#endif
+ {
+ return;
+ }
+ // We only read as much as fits in the buffer.
+ // This way we avoid choking on huge data.
+ uint_least32_t i = 0;
+ char datb;
+ while (std::cin.get(datb) && i<SIDTUNE_MAX_FILELEN)
+ fileBuf[i++] = (uint_least8_t) datb;
+ info.dataFileLen = i;
+ getFromBuffer(fileBuf,info.dataFileLen);
+ delete[] fileBuf;
+}
+
+#endif
+
+void SidTune::getFromBuffer(const uint_least8_t* const buffer, const uint_least32_t bufferLen)
+{
+ // Assume a failure, so we can simply return.
+ status = false;
+
+ if (buffer==0 || bufferLen==0)
+ {
+ info.statusString = SidTune::txt_empty;
+ return;
+ }
+ else if (bufferLen > SIDTUNE_MAX_FILELEN)
+ {
+ info.statusString = SidTune::txt_fileTooLong;
+ return;
+ }
+
+ uint_least8_t* tmpBuf;
+#ifdef HAVE_EXCEPTIONS
+ if ( 0 == (tmpBuf = new(std::nothrow) uint_least8_t[bufferLen]) )
+#else
+ if ( 0 == (tmpBuf = new uint_least8_t[bufferLen]) )
+#endif
+ {
+ info.statusString = SidTune::txt_notEnoughMemory;
+ return;
+ }
+ memcpy(tmpBuf,buffer,bufferLen);
+
+ Buffer_sidtt<const uint_least8_t> buf1(tmpBuf,bufferLen);
+ Buffer_sidtt<const uint_least8_t> buf2; // empty
+
+ bool foundFormat = false;
+ // Here test for the possible single file formats. --------------
+ if ( PSID_fileSupport( buffer, bufferLen ))
+ {
+ foundFormat = true;
+ }
+ else if ( MUS_fileSupport(buf1,buf2) )
+ {
+ foundFormat = MUS_mergeParts(buf1,buf2);
+ }
+ else
+ {
+ // No further single-file-formats available.
+ info.statusString = SidTune::txt_unrecognizedFormat;
+ }
+ if ( foundFormat )
+ {
+ status = acceptSidTune("-","-",buf1);
+ }
+}
+
+bool SidTune::acceptSidTune(const char* dataFileName, const char* infoFileName,
+ Buffer_sidtt<const uint_least8_t>& buf)
+{
+ deleteFileNameCopies();
+ // Make a copy of the data file name and path, if available.
+ if ( dataFileName != 0 )
+ {
+ info.path = SidTuneTools::myStrDup(dataFileName);
+ if (isSlashedFileName)
+ {
+ info.dataFileName = SidTuneTools::myStrDup(SidTuneTools::slashedFileNameWithoutPath(info.path));
+ *SidTuneTools::slashedFileNameWithoutPath(info.path) = 0; // path only
+ }
+ else
+ {
+ info.dataFileName = SidTuneTools::myStrDup(SidTuneTools::fileNameWithoutPath(info.path));
+ *SidTuneTools::fileNameWithoutPath(info.path) = 0; // path only
+ }
+ if ((info.path==0) || (info.dataFileName==0))
+ {
+ info.statusString = SidTune::txt_notEnoughMemory;
+ return false;
+ }
+ }
+ else
+ {
+ // Provide empty strings.
+ info.path = SidTuneTools::myStrDup("");
+ info.dataFileName = SidTuneTools::myStrDup("");
+ }
+ // Make a copy of the info file name, if available.
+ if ( infoFileName != 0 )
+ {
+ char* tmp = SidTuneTools::myStrDup(infoFileName);
+ if (isSlashedFileName)
+ info.infoFileName = SidTuneTools::myStrDup(SidTuneTools::slashedFileNameWithoutPath(tmp));
+ else
+ info.infoFileName = SidTuneTools::myStrDup(SidTuneTools::fileNameWithoutPath(tmp));
+ if ((tmp==0) || (info.infoFileName==0))
+ {
+ info.statusString = SidTune::txt_notEnoughMemory;
+ return false;
+ }
+ delete[] tmp;
+ }
+ else
+ {
+ // Provide empty string.
+ info.infoFileName = SidTuneTools::myStrDup("");
+ }
+ // Fix bad sidtune set up.
+ if (info.songs > SIDTUNE_MAX_SONGS)
+ info.songs = SIDTUNE_MAX_SONGS;
+ else if (info.songs == 0)
+ info.songs++;
+ if (info.startSong > info.songs)
+ info.startSong = 1;
+ else if (info.startSong == 0)
+ info.startSong++;
+
+ if ( info.musPlayer )
+ MUS_setPlayerAddress();
+
+ info.dataFileLen = buf.len();
+ info.c64dataLen = buf.len() - fileOffset;
+
+ if (info.dataFileLen >= 2)
+ {
+ // We only detect an offset of two. Some position independent
+ // sidtunes contain a load address of 0xE000, but are loaded
+ // to 0x0FFE and call player at 0x1000.
+ info.fixLoad = (endian_little16(buf.get()+fileOffset)==(info.loadAddr+2));
+ }
+
+ // Check the size of the data.
+ if ( info.c64dataLen > SIDTUNE_MAX_MEMORY )
+ {
+ info.statusString = SidTune::txt_dataTooLong;
+ return false;
+ }
+ else if ( info.c64dataLen == 0 )
+ {
+ info.statusString = SidTune::txt_empty;
+ return false;
+ }
+
+ cache.assign(buf.xferPtr(),buf.xferLen());
+
+ info.statusString = SidTune::txt_noErrors;
+ return true;
+}
+
+bool SidTune::createNewFileName(Buffer_sidtt<char>& destString,
+ const char* sourceName,
+ const char* sourceExt)
+{
+ Buffer_sidtt<char> newBuf;
+ uint_least32_t newLen = strlen(sourceName)+strlen(sourceExt)+1;
+ // Get enough memory, so we can appended the extension.
+#ifdef HAVE_EXCEPTIONS
+ newBuf.assign(new(std::nothrow) char[newLen],newLen);
+#else
+ newBuf.assign(new char[newLen],newLen);
+#endif
+ if ( newBuf.isEmpty() )
+ {
+ info.statusString = SidTune::txt_notEnoughMemory;
+ return (status = false);
+ }
+ strcpy(newBuf.get(),sourceName);
+ strcpy(SidTuneTools::fileExtOfPath(newBuf.get()),sourceExt);
+ destString.assign(newBuf.xferPtr(),newBuf.xferLen());
+ return true;
+}
+
+// Initializing the object based upon what we find in the specified file.
+
+void SidTune::getFromFiles(const char* fileName)
+{
+ // Assume a failure, so we can simply return.
+ status = false;
+
+ Buffer_sidtt<const uint_least8_t> fileBuf1, fileBuf2;
+ Buffer_sidtt<char> fileName2;
+
+ // Try to load the single specified file.
+ if ( loadFile(fileName,fileBuf1) )
+ {
+ // File loaded. Now check if it is in a valid single-file-format.
+ if ( PSID_fileSupport(fileBuf1.get(),fileBuf1.len()) )
+ {
+ status = acceptSidTune(fileName,0,fileBuf1);
+ return;
+ }
+ else if ( MUS_fileSupport(fileBuf1,fileBuf2) )
+ {
+ // Try to find second file.
+ int n = 0;
+ while (fileNameExtensions[n] != 0)
+ {
+ if ( !createNewFileName(fileName2,fileName,fileNameExtensions[n]) )
+ return;
+ // 1st data file was loaded into ``fileBuf1'',
+ // so we load the 2nd one into ``fileBuf2''.
+ // Do not load the first file again if names are equal.
+ if ( MYSTRICMP(fileName,fileName2.get())!=0 &&
+ loadFile(fileName2.get(),fileBuf2) )
+ {
+ if ( MUS_fileSupport(fileBuf1,fileBuf2) )
+ {
+ if ( MUS_mergeParts(fileBuf1,fileBuf2) )
+ {
+ status = acceptSidTune(fileName,fileName2.get(),
+ fileBuf1);
+ }
+ return; // in either case
+ }
+ }
+ n++;
+ };
+ // No second file.
+ status = acceptSidTune(fileName,0,fileBuf1);
+ return;
+ }
+
+// -------------------------------------- Support for multiple-files formats.
+ else
+ {
+// We cannot simply try to load additional files, if a description file was
+// specified. It would work, but is error-prone. Imagine a filename mismatch
+// or more than one description file (in another) format. Any other file
+// with an appropriate file name can be the C64 data file.
+
+// First we see if ``fileName'' could be a raw data file. In that case we
+// have to find the corresponding description file.
+
+ // Right now we do not have a second file. Hence the (0, 0, ...)
+ // parameters are set for the data buffer. This will not hurt the
+ // file support procedures.
+
+ // Make sure that ``fileBuf1'' does not contain a description file.
+ if ( !SID_fileSupport(0,0,fileBuf1.get(),fileBuf1.len()) &&
+ !INFO_fileSupport(0,0,fileBuf1.get(),fileBuf1.len()) )
+ {
+ // Assuming ``fileName'' to hold the name of the raw data file,
+ // we now create the name of a description file (=fileName2) by
+ // appending various filename extensions.
+
+// ------------------------------------------ Looking for a description file.
+
+ int n = 0;
+ while (fileNameExtensions[n] != 0)
+ {
+ if ( !createNewFileName(fileName2,fileName,fileNameExtensions[n]) )
+ return;
+ // 1st data file was loaded into ``fileBuf1'',
+ // so we load the 2nd one into ``fileBuf2''.
+ // Do not load the first file again if names are equal.
+ if ( MYSTRICMP(fileName,fileName2.get())!=0 &&
+ loadFile(fileName2.get(),fileBuf2) )
+ {
+ if ( SID_fileSupport(fileBuf1.get(),fileBuf1.len(),
+ fileBuf2.get(),fileBuf2.len())
+ || INFO_fileSupport(fileBuf1.get(),fileBuf1.len(),
+ fileBuf2.get(),fileBuf2.len())
+ )
+ {
+ status = acceptSidTune(fileName,fileName2.get(),
+ fileBuf1);
+ return;
+ }
+ }
+ n++;
+ };
+
+// --------------------------------------- Could not find a description file.
+
+ info.statusString = SidTune::txt_unrecognizedFormat;
+ return;
+ }
+
+// -------------------------------------------------------------------------
+// Still unsuccessful ? Probably one put a description file name into
+// ``fileName''. Assuming ``fileName'' to hold the name of a description
+// file, we now create the name of the data file and swap both used memory
+// buffers - fileBuf1 and fileBuf2 - when calling the format support.
+// If it works, the second file is the data file ! If it is not, but does
+// exist, we are out of luck, since we cannot detect data files.
+
+ // Make sure ``fileBuf1'' contains a description file.
+ else if ( SID_fileSupport(0,0,fileBuf1.get(),fileBuf1.len()) ||
+ INFO_fileSupport(0,0,fileBuf1.get(),fileBuf1.len()) )
+ {
+
+// --------------------- Description file found. --- Looking for a data file.
+
+ int n = 0;
+ while (fileNameExtensions[n] != 0)
+ {
+ if ( !createNewFileName(fileName2,fileName,fileNameExtensions[n]) )
+ return;
+ // 1st info file was loaded into ``fileBuf'',
+ // so we load the 2nd one into ``fileBuf2''.
+ // Do not load the first file again if names are equal.
+ if ( MYSTRICMP(fileName,fileName2.get())!=0 &&
+
+ loadFile(fileName2.get(),fileBuf2) )
+ {
+// -------------- Some data file found, now identifying the description file.
+
+ if ( SID_fileSupport(fileBuf2.get(),fileBuf2.len(),
+ fileBuf1.get(),fileBuf1.len())
+ || INFO_fileSupport(fileBuf2.get(),fileBuf2.len(),
+ fileBuf1.get(),fileBuf1.len())
+ )
+ {
+ status = acceptSidTune(fileName2.get(),fileName,
+ fileBuf2);
+ return;
+ }
+ }
+ n++;
+ };
+
+// ---------------------------------------- No corresponding data file found.
+
+ info.statusString = SidTune::txt_noDataFile;
+ return;
+ } // end else if ( = is description file )
+
+// --------------------------------- Neither description nor data file found.
+
+ else
+ {
+ info.statusString = SidTune::txt_unrecognizedFormat;
+ return;
+ }
+ } // end else ( = is no singlefile )
+
+// ---------------------------------------------------------- File I/O error.
+
+ } // if loaddatafile
+ else
+ {
+ // returned fileLen was 0 = error. The info.statusString is
+ // already set then.
+ return;
+ }
+}
+
+void SidTune::convertOldStyleSpeedToTables(uint_least32_t speed, int clock)
+{
+ // Create the speed/clock setting tables.
+ //
+ // This does not take into account the PlaySID bug upon evaluating the
+ // SPEED field. It would most likely break compatibility to lots of
+ // sidtunes, which have been converted from .SID format and vice versa.
+ // The .SID format does the bit-wise/song-wise evaluation of the SPEED
+ // value correctly, like it is described in the PlaySID documentation.
+
+ int toDo = ((info.songs <= SIDTUNE_MAX_SONGS) ? info.songs : SIDTUNE_MAX_SONGS);
+ for (int s = 0; s < toDo; s++)
+ {
+ clockSpeed[s] = clock;
+ if (( (speed>>(s&31)) & 1 ) == 0 )
+ songSpeed[s] = SIDTUNE_SPEED_VBI;
+ else
+ songSpeed[s] = SIDTUNE_SPEED_CIA_1A;
+ }
+}
+
+//
+// File format conversion ---------------------------------------------------
+//
+
+bool SidTune::saveToOpenFile(std::ofstream& toFile, const uint_least8_t* buffer,
+ uint_least32_t bufLen )
+{
+ uint_least32_t lenToWrite = bufLen;
+ while ( lenToWrite > INT_MAX )
+ {
+ toFile.write((char*)buffer+(bufLen-lenToWrite),INT_MAX);
+ lenToWrite -= INT_MAX;
+ }
+ if ( lenToWrite > 0 )
+ toFile.write((char*)buffer+(bufLen-lenToWrite),lenToWrite);
+ if ( toFile.bad() )
+ {
+ info.statusString = SidTune::txt_fileIoError;
+ return false;
+ }
+ else
+ {
+ info.statusString = SidTune::txt_noErrors;
+ return true;
+ }
+}
+
+bool SidTune::saveC64dataFile( const char* fileName, bool overWriteFlag )
+{
+ bool success = false; // assume error
+ // This prevents saving from a bad object.
+ if ( status )
+ {
+ // Open binary output file stream.
+ //openmode createAttr = std::ios::out;
+ std::_Ios_Openmode createAttr = std::ios::out;
+#if defined(HAVE_IOS_BIN)
+ createAttr |= std::ios::bin;
+#else
+ createAttr |= std::ios::binary;
+#endif
+ if ( overWriteFlag )
+ createAttr |= std::ios::trunc;
+ else
+ createAttr |= std::ios::app;
+ std::ofstream fMyOut( fileName, createAttr );
+ if ( !fMyOut || fMyOut.tellp()>0 )
+ {
+ info.statusString = SidTune::txt_cantCreateFile;
+ }
+ else
+ {
+ // Save c64 lo/hi load address.
+ uint_least8_t saveAddr[2];
+ saveAddr[0] = info.loadAddr & 255;
+ saveAddr[1] = info.loadAddr >> 8;
+ fMyOut.write((char*)saveAddr,2);
+ // Data starts at: bufferaddr + fileOffset
+ // Data length: info.dataFileLen - fileOffset
+ if ( !saveToOpenFile( fMyOut,cache.get()+fileOffset, info.dataFileLen - fileOffset ) )
+ {
+ info.statusString = SidTune::txt_fileIoError;
+ }
+ else
+ {
+ info.statusString = SidTune::txt_noErrors;
+ success = true;
+ }
+ fMyOut.close();
+ }
+ }
+ return success;
+}
+
+bool SidTune::saveSIDfile( const char* fileName, bool overWriteFlag )
+{
+ bool success = false; // assume error
+ // This prevents saving from a bad object.
+ if ( status )
+ {
+ // Open ASCII output file stream.
+// openmode createAttr = std::ios::out;
+ std::_Ios_Openmode createAttr = std::ios::out;
+ if ( overWriteFlag )
+ createAttr |= std::ios::trunc;
+ else
+ createAttr |= std::ios::app;
+ std::ofstream fMyOut( fileName, createAttr );
+ if ( !fMyOut || fMyOut.tellp()>0 )
+ {
+ info.statusString = SidTune::txt_cantCreateFile;
+ }
+ else
+ {
+ if ( !SID_fileSupportSave( fMyOut ) )
+ {
+ info.statusString = SidTune::txt_fileIoError;
+ }
+ else
+ {
+ info.statusString = SidTune::txt_noErrors;
+ success = true;
+ }
+ fMyOut.close();
+ }
+ }
+ return success;
+}
+
+bool SidTune::savePSIDfile( const char* fileName, bool overWriteFlag )
+{
+ bool success = false; // assume error
+ // This prevents saving from a bad object.
+ if ( status )
+ {
+ // Open binary output file stream.
+ //openmode createAttr = std::ios::out;
+ std::_Ios_Openmode createAttr = std::ios::out;
+#if defined(HAVE_IOS_BIN)
+ createAttr |= std::ios::bin;
+#else
+ createAttr |= std::ios::binary;
+#endif
+ if ( overWriteFlag )
+ createAttr |= std::ios::trunc;
+ else
+ createAttr |= std::ios::app;
+ std::ofstream fMyOut( fileName, createAttr );
+ if ( !fMyOut || fMyOut.tellp()>0 )
+ {
+ info.statusString = SidTune::txt_cantCreateFile;
+ }
+ else
+ {
+ if ( !PSID_fileSupportSave( fMyOut,cache.get() ) )
+ {
+ info.statusString = SidTune::txt_fileIoError;
+ }
+ else
+ {
+ info.statusString = SidTune::txt_noErrors;
+ success = true;
+ }
+ fMyOut.close();
+ }
+ }
+ return success;
+}
+
+bool SidTune::checkRealC64Info (uint_least32_t speed)
+{
+ if (info.loadAddr != 0)
+ return false;
+ if (info.playAddr != 0)
+ return false;
+ if (speed != 0)
+ return false;
+ if (info.compatibility == SIDTUNE_COMPATIBILITY_PSID)
+ return false;
+ return true;
+}
+
+bool SidTune::checkRealC64Init (void)
+{
+ if (info.initAddr == 0)
+ info.initAddr = info.loadAddr;
+
+ // Check valid init address
+ switch (info.initAddr >> 12)
+ {
+ case 0x0F:
+ case 0x0E:
+ case 0x0D:
+ case 0x0B:
+ case 0x0A:
+ return false;
+ default:
+ if ( (info.initAddr < info.loadAddr) ||
+ (info.initAddr > (info.loadAddr + info.c64dataLen - 1)) )
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool SidTune::checkRelocInfo (void)
+{
+ uint_least8_t startp, endp;
+
+ // Fix relocation information
+ if (info.relocStartPage == 0xFF)
+ {
+ info.relocPages = 0;
+ return true;
+ }
+ else if (info.relocPages == 0)
+ {
+ info.relocStartPage = 0;
+ return true;
+ }
+
+ // Calculate start/end page
+ startp = info.relocStartPage;
+ endp = (startp + info.relocPages - 1) & 0xff;
+ if (endp < startp)
+ {
+ info.formatString = txt_badReloc;
+ return false;
+ }
+
+ { // Check against load range
+ uint_least8_t startlp, endlp;
+ startlp = (uint_least8_t) (info.loadAddr >> 8);
+ endlp = startlp;
+ endlp += (uint_least8_t) ((info.c64dataLen - 1) >> 8);
+
+ if ( ((startp <= startlp) && (endp >= startlp)) ||
+ ((startp <= endlp) && (endp >= endlp)) )
+ {
+ info.formatString = txt_badReloc;
+ return false;
+ }
+ }
+
+ // Check that the relocation information does not use the following
+ // memory areas: 0x0000-0x03FF, 0xA000-0xBFFF and 0xD000-0xFFFF
+ if ((startp < 0x04)
+ || ((0xa0 <= startp) && (startp <= 0xbf))
+ || (startp >= 0xd0)
+ || ((0xa0 <= endp) && (endp <= 0xbf))
+ || (endp >= 0xd0))
+ {
+ info.formatString = txt_badReloc;
+ return false;
+ }
+ return true;
+}
+
+bool SidTune::resolveAddrs (const uint_least8_t* c64data)
+{
+ if ( info.compatibility == SIDTUNE_COMPATIBILITY_R64 )
+ {
+ bool initAddrCheck = true;
+
+ // Check tune is loadable on a real C64
+ if ( info.loadAddr < SIDTUNE_R64_MIN_LOAD_ADDR )
+ {
+ info.formatString = txt_badAddr;
+ return false;
+ }
+
+ if ( (info.initAddr == 0) && (info.loadAddr == SIDTUNE_BASIC_START) )
+ { // Scan basic for a sys call
+ const uint_least8_t* pData = c64data;
+ uint_least16_t addr = 0;
+ uint_least16_t next = endian_little16(pData);
+ uint_least16_t init = 0;
+
+ while (next)
+ { // skip addr & line number
+ const uint_least8_t *p = &pData[addr + 4];
+
+SidTune_resolveAddrs_basic:
+ // Check for SYS
+ if (*p++ != 0x9e)
+ { // Check for ':' instruction seperator before
+ // jumping to next basic line
+ while (*p != '\0')
+ {
+ if (*p++ == ':')
+ { // Skip spaces
+ while (*p == ' ')
+ p++;
+ // Make sure havent hit end of line
+ if (*p != '\0')
+ goto SidTune_resolveAddrs_basic;
+ }
+ }
+ // Not a sys so jump to next intruction
+ addr = next;
+ // Get addr of next line of basic
+ next = endian_little16(&pData[addr]);
+ continue;
+ }
+ // Skip spaces
+ while (*p == ' ')
+ p++;
+ // Found a sys, extract all numbers
+ while ( (*p >= '0') && (*p <= '9') )
+ {
+ init *= 10;
+ init += *p++ - '0';
+ }
+ info.initAddr = init;
+ // Assume address is legal otherwise
+ // a real c64 would crash
+ initAddrCheck = false;
+ break;
+ }
+ }
+
+ if ( checkRealC64Init() == false )
+ {
+ info.formatString = txt_badAddr;
+ return false;
+ }
+ }
+ else if ( info.initAddr == 0 )
+ info.initAddr = info.loadAddr;
+ return true;
+}
diff --git a/sid/sidplay-libs-2.1.0/libsidplay/src/sidtune/SidTuneCfg.h b/sid/sidplay-libs-2.1.0/libsidplay/src/sidtune/SidTuneCfg.h
new file mode 100644
index 00000000..7b184156
--- /dev/null
+++ b/sid/sidplay-libs-2.1.0/libsidplay/src/sidtune/SidTuneCfg.h
@@ -0,0 +1,35 @@
+/* SidTuneCfg.h (template) */
+
+#ifndef SIDTUNECFG_H
+#define SIDTUNECFG_H
+
+#include "config.h"
+
+/* Define to add PSID2NG support */
+#define SIDTUNE_PSID2NG
+
+/* Minimum load address for real c64 only tunes */
+#define SIDTUNE_R64_MIN_LOAD_ADDR 0x07e8
+
+/* --------------------------------------------------------------------------
+ * Don't touch these!
+ * --------------------------------------------------------------------------
+ */
+#undef SIDTUNE_NO_STDIN_LOADER
+#undef SIDTUNE_REJECT_UNKNOWN_FIELDS
+
+
+/* Define the file/path separator(s) that your filesystem uses:
+ SID_FS_IS_COLON_AND_BACKSLASH, SID_FS_IS_COLON_AND_SLASH,
+ SID_FS_IS_BACKSLASH, SID_FS_IS_COLON, SID_FS_IS_SLASH */
+#if defined(HAVE_MSWINDOWS) || defined(HAVE_MSDOS) || defined(HAVE_OS2)
+ #define SID_FS_IS_COLON_AND_BACKSLASH_AND_SLASH
+#elif defined(HAVE_MACOS)
+ #define SID_FS_IS_COLON
+#elif defined(HAVE_AMIGAOS)
+ #define SID_FS_IS_COLON_AND_SLASH
+#else
+ #define SID_FS_IS_SLASH
+#endif
+
+#endif /* SIDTUNECFG_H */
diff --git a/sid/sidplay-libs-2.1.0/libsidplay/src/sidtune/SidTuneTools.cpp b/sid/sidplay-libs-2.1.0/libsidplay/src/sidtune/SidTuneTools.cpp
new file mode 100644
index 00000000..79bf1597
--- /dev/null
+++ b/sid/sidplay-libs-2.1.0/libsidplay/src/sidtune/SidTuneTools.cpp
@@ -0,0 +1,215 @@
+/*
+ * /home/ms/files/source/libsidtune/RCS/SidTuneTools.cpp,v
+ *
+ * Copyright (C) Michael Schwendt <mschwendt@yahoo.com>
+ *
+ * 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 "SidTuneTools.h"
+
+#ifdef HAVE_EXCEPTIONS
+# include <new>
+#endif
+#include <ctype.h>
+#include <string.h>
+
+// Own version of strdup, which uses new instead of malloc.
+char* SidTuneTools::myStrDup(const char *source)
+{
+ char *dest;
+#ifdef HAVE_EXCEPTIONS
+ if ( (dest = new(std::nothrow) char[strlen(source)+1]) != 0)
+#else
+ if ( (dest = new char[strlen(source)+1]) != 0)
+#endif
+ {
+ strcpy(dest,source);
+ }
+ return dest;
+}
+
+// Return pointer to file name position in complete path.
+char* SidTuneTools::fileNameWithoutPath(char* s)
+{
+ int last_slash_pos = -1;
+ for ( uint_least32_t pos = 0; pos < strlen(s); pos++ )
+ {
+#if defined(SID_FS_IS_COLON_AND_BACKSLASH_AND_SLASH)
+ if ( s[pos] == ':' || s[pos] == '\\' ||
+ s[pos] == '/' )
+#elif defined(SID_FS_IS_COLON_AND_SLASH)
+ if ( s[pos] == ':' || s[pos] == '/' )
+#elif defined(SID_FS_IS_SLASH)
+ if ( s[pos] == '/' )
+#elif defined(SID_FS_IS_BACKSLASH)
+ if ( s[pos] == '\\' )
+#elif defined(SID_FS_IS_COLON)
+ if ( s[pos] == ':' )
+#else
+#error Missing file/path separator definition.
+#endif
+ {
+ last_slash_pos = pos;
+ }
+ }
+ return( &s[last_slash_pos +1] );
+}
+
+// Return pointer to file name position in complete path.
+// Special version: file separator = forward slash.
+char* SidTuneTools::slashedFileNameWithoutPath(char* s)
+{
+ int last_slash_pos = -1;
+ for ( uint_least32_t pos = 0; pos < strlen(s); pos++ )
+ {
+ if ( s[pos] == '/' )
+ {
+ last_slash_pos = pos;
+ }
+ }
+ return( &s[last_slash_pos +1] );
+}
+
+// Return pointer to file name extension in path.
+// The backwards-version.
+char* SidTuneTools::fileExtOfPath(char* s)
+{
+ uint_least32_t last_dot_pos = strlen(s); // assume no dot and append
+ for ( int pos = last_dot_pos; pos >= 0; --pos )
+ {
+ if ( s[pos] == '.' )
+ {
+ last_dot_pos = pos;
+ break;
+ }
+ }
+ return( &s[last_dot_pos] );
+}
+
+// Parse input string stream. Read and convert a hexa-decimal number up
+// to a ``,'' or ``:'' or ``\0'' or end of stream.
+uint_least32_t SidTuneTools::readHex( std::istrstream& hexin )
+{
+ uint_least32_t hexLong = 0;
+ char c;
+ do
+ {
+ hexin >> c;
+ if ( !hexin )
+ break;
+ if (( c != ',') && ( c != ':' ) && ( c != 0 ))
+ {
+ // machine independed to_upper
+ c &= 0xdf;
+ ( c < 0x3a ) ? ( c &= 0x0f ) : ( c -= ( 0x41 - 0x0a ));
+ hexLong <<= 4;
+ hexLong |= (uint_least32_t)c;
+ }
+ else
+ {
+ if ( c == 0 )
+ hexin.putback(c);
+ break;
+ }
+ } while ( hexin );
+ return hexLong;
+}
+
+// Parse input string stream. Read and convert a decimal number up
+// to a ``,'' or ``:'' or ``\0'' or end of stream.
+uint_least32_t SidTuneTools::readDec( std::istrstream& decin )
+{
+ uint_least32_t hexLong = 0;
+ char c;
+ do
+ {
+ decin >> c;
+ if ( !decin )
+ break;
+ if (( c != ',') && ( c != ':' ) && ( c != 0 ))
+ {
+ c &= 0x0f;
+ hexLong *= 10;
+ hexLong += (uint_least32_t)c;
+ }
+ else
+ {
+ if ( c == 0 )
+ decin.putback(c);
+ break;
+ }
+ } while ( decin );
+ return hexLong;
+}
+
+// Search terminated string for next newline sequence.
+// Skip it and return pointer to start of next line.
+const char* SidTuneTools::returnNextLine(const char* s)
+{
+ // Unix: LF = 0x0A
+ // Windows, DOS: CR,LF = 0x0D,0x0A
+ // Mac: CR = 0x0D
+ char c;
+ while ((c = *s) != 0)
+ {
+ s++; // skip read character
+ if (c == 0x0A)
+ {
+ break; // LF found
+ }
+ else if (c == 0x0D)
+ {
+ if (*s == 0x0A)
+ {
+ s++; // CR,LF found, skip LF
+ }
+ break; // CR or CR,LF found
+ }
+ }
+ if (*s == 0) // end of string ?
+ {
+ return 0; // no next line available
+ }
+ return s; // next line available
+}
+
+// Skip any characters in an input string stream up to '='.
+void SidTuneTools::skipToEqu( std::istrstream& parseStream )
+{
+ char c;
+ do
+ {
+ parseStream >> c;
+ }
+ while ( c != '=' );
+}
+
+void SidTuneTools::copyStringValueToEOL(const char* pSourceStr, char* pDestStr, int DestMaxLen )
+{
+ // Start at first character behind '='.
+ while ( *pSourceStr != '=' )
+ {
+ pSourceStr++;
+ }
+ pSourceStr++; // Skip '='.
+ while (( DestMaxLen > 0 ) && ( *pSourceStr != 0 )
+ && ( *pSourceStr != '\n' ) && ( *pSourceStr != '\r' ))
+ {
+ *pDestStr++ = *pSourceStr++;
+ DestMaxLen--;
+ }
+ *pDestStr++ = 0;
+}
diff --git a/sid/sidplay-libs-2.1.0/libsidplay/src/sidtune/SidTuneTools.h b/sid/sidplay-libs-2.1.0/libsidplay/src/sidtune/SidTuneTools.h
new file mode 100644
index 00000000..bc67fa93
--- /dev/null
+++ b/sid/sidplay-libs-2.1.0/libsidplay/src/sidtune/SidTuneTools.h
@@ -0,0 +1,85 @@
+/*
+ * /home/ms/files/source/libsidtune/RCS/SidTuneTools.h,v
+ *
+ * Copyright (C) Michael Schwendt <mschwendt@yahoo.com>
+ *
+ * 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 TOOLS_H
+#define TOOLS_H
+
+#include "SidTuneCfg.h"
+#include "sidtypes.h"
+
+#include <string.h>
+#include <strstream>
+
+#define MYSTRICMP stricmp
+#if defined(HAVE_STRCASECMP)
+ #undef MYSTRICMP
+ #define MYSTRICMP strcasecmp
+#endif
+
+#define MYSTRNICMP strnicmp
+#if defined(HAVE_STRNCASECMP)
+ #undef MYSTRNICMP
+ #define MYSTRNICMP strncasecmp
+#endif
+
+class SidTuneTools
+{
+ public:
+
+ // Wrapper for ``strnicmp'' without third argument.
+ static int myStrNcaseCmp(const char* s1, const char* s2)
+ {
+ return MYSTRNICMP(s1,s2,strlen(s2));
+ }
+
+ // Own version of strdup, which uses new instead of malloc.
+ static char* myStrDup(const char *source);
+
+ // Return pointer to file name position in complete path.
+ static char* fileNameWithoutPath(char* s);
+
+ // Return pointer to file name position in complete path.
+ // Special version: file separator = forward slash.
+ static char* slashedFileNameWithoutPath(char* s);
+
+ // Return pointer to file name extension in path.
+ // Searching backwards until first dot is found.
+ static char* fileExtOfPath(char* s);
+
+ // Parse input string stream. Read and convert a hexa-decimal number up
+ // to a ``,'' or ``:'' or ``\0'' or end of stream.
+ static uint_least32_t readHex(std::istrstream& parseStream);
+
+ // Parse input string stream. Read and convert a decimal number up
+ // to a ``,'' or ``:'' or ``\0'' or end of stream.
+ static uint_least32_t readDec(std::istrstream& parseStream);
+
+ // Search terminated string for next newline sequence.
+ // Skip it and return pointer to start of next line.
+ static const char* returnNextLine(const char* pBuffer);
+
+ // Skip any characters in an input string stream up to '='.
+ static void skipToEqu(std::istrstream& parseStream);
+
+ // Start at first character behind '=' and copy rest of string.
+ static void copyStringValueToEOL(const char* pSourceStr, char* pDestStr, int destMaxLen);
+};
+
+#endif /* TOOLS_H */