Implemented basic residfp support

CQTexperiment
Chris Moeller 2014-12-07 22:26:31 -08:00
parent 540069c019
commit 08dc22009d
1287 changed files with 249400 additions and 6 deletions

View File

@ -142,6 +142,7 @@
835CBC8118DA7A520087A03E /* modplay.bundle in CopyFiles */ = {isa = PBXBuildFile; fileRef = 835CBC7618DA79F80087A03E /* modplay.bundle */; };
8360EF6D17F92E56005208A4 /* HighlyComplete.bundle in CopyFiles */ = {isa = PBXBuildFile; fileRef = 8360EF0517F92B24005208A4 /* HighlyComplete.bundle */; };
836D28A818086386005B7299 /* MiniModeMenuTitleTransformer.m in Sources */ = {isa = PBXBuildFile; fileRef = 836D28A718086386005B7299 /* MiniModeMenuTitleTransformer.m */; };
836F5BF91A357A01002730CC /* sidplay.bundle in CopyFiles */ = {isa = PBXBuildFile; fileRef = 8314D6411A354DFF00EEE8E6 /* sidplay.bundle */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
836F706218BDD1230095E648 /* vgmstream.bundle in CopyFiles */ = {isa = PBXBuildFile; fileRef = 836F6B2E18BDB80E0095E648 /* vgmstream.bundle */; };
836FB5A718206F2500B3AD2D /* Hively.bundle in CopyFiles */ = {isa = PBXBuildFile; fileRef = 836FB5471820538800B3AD2D /* Hively.bundle */; };
8375B36517FFEF130092A79F /* Opus.bundle in CopyFiles */ = {isa = PBXBuildFile; fileRef = 8375B05717FFEA410092A79F /* Opus.bundle */; };
@ -423,6 +424,13 @@
remoteGlobalIDString = 99B989F40CC7E10400C256E9;
remoteInfo = "APL Plugin";
};
8314D6401A354DFF00EEE8E6 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 8314D63B1A354DFE00EEE8E6 /* sidplay.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 8314D6311A354DFE00EEE8E6;
remoteInfo = sidplay;
};
8359FF3017FEF35D0060F3ED /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 8359FF2C17FEF35C0060F3ED /* ArchiveSource.xcodeproj */;
@ -444,6 +452,13 @@
remoteGlobalIDString = 8360EEE417F92AC8005208A4;
remoteInfo = HighlyComplete;
};
836F5BED1A3579F5002730CC /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 8314D63B1A354DFE00EEE8E6 /* sidplay.xcodeproj */;
proxyType = 1;
remoteGlobalIDString = 8314D6301A354DFE00EEE8E6;
remoteInfo = sidplay;
};
836F6B2D18BDB80E0095E648 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 836F6B2518BDB80D0095E648 /* vgmstream.xcodeproj */;
@ -651,6 +666,7 @@
dstPath = "";
dstSubfolderSpec = 13;
files = (
836F5BF91A357A01002730CC /* sidplay.bundle in CopyFiles */,
839BD010196521E600947767 /* BASSMODS.bundle in CopyFiles */,
835CBC8118DA7A520087A03E /* modplay.bundle in CopyFiles */,
836F706218BDD1230095E648 /* vgmstream.bundle in CopyFiles */,
@ -892,6 +908,7 @@
56DB084B0D6717DC00453B6A /* NSNumber+CogSort.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSNumber+CogSort.m"; path = "Spotlight/NSNumber+CogSort.m"; sourceTree = "<group>"; };
56DB08530D67185300453B6A /* NSArray+CogSort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSArray+CogSort.h"; path = "Spotlight/NSArray+CogSort.h"; sourceTree = "<group>"; };
56DB08540D67185300453B6A /* NSArray+CogSort.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSArray+CogSort.m"; path = "Spotlight/NSArray+CogSort.m"; sourceTree = "<group>"; };
8314D63B1A354DFE00EEE8E6 /* sidplay.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = sidplay.xcodeproj; path = Plugins/sidplay/sidplay.xcodeproj; sourceTree = "<group>"; };
832C1252180BD1E2005507C1 /* Cog.help */ = {isa = PBXFileReference; lastKnownFileType = folder; path = Cog.help; sourceTree = "<group>"; };
8355D6B4180612F300D05687 /* NSData+MD5.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSData+MD5.h"; sourceTree = "<group>"; };
8355D6B5180612F300D05687 /* NSData+MD5.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSData+MD5.m"; sourceTree = "<group>"; };
@ -1261,6 +1278,7 @@
836FB5421820538700B3AD2D /* Hively.xcodeproj */,
836F6B2518BDB80D0095E648 /* vgmstream.xcodeproj */,
839BCFE71965133E00947767 /* BASSMODS.xcodeproj */,
8314D63B1A354DFE00EEE8E6 /* sidplay.xcodeproj */,
);
name = PlugIns;
sourceTree = "<group>";
@ -1575,6 +1593,14 @@
name = Categories;
sourceTree = "<group>";
};
8314D63C1A354DFE00EEE8E6 /* Products */ = {
isa = PBXGroup;
children = (
8314D6411A354DFF00EEE8E6 /* sidplay.bundle */,
);
name = Products;
sourceTree = "<group>";
};
8359FF2D17FEF35C0060F3ED /* Products */ = {
isa = PBXGroup;
children = (
@ -1679,9 +1705,9 @@
children = (
83E6B759181612FD00D4576D /* Sparkle.framework */,
83E6B75B181612FD00D4576D /* Sparkle Test App.app */,
83E6B75D181612FD00D4576D /* Sparkle Unit Tests.octest */,
83E6B75D181612FD00D4576D /* Sparkle Unit Tests.xctest */,
83E6B75F181612FD00D4576D /* BinaryDelta */,
83E6B761181612FD00D4576D /* finish_installation.app */,
83E6B761181612FD00D4576D /* Autoupdate.app */,
);
name = Products;
sourceTree = "<group>";
@ -1818,6 +1844,7 @@
buildRules = (
);
dependencies = (
836F5BEE1A3579F5002730CC /* PBXTargetDependency */,
839BD012196521FD00947767 /* PBXTargetDependency */,
836FB5A618206F1500B3AD2D /* PBXTargetDependency */,
83A0F4E21816DBE800119DB4 /* PBXTargetDependency */,
@ -1973,6 +2000,10 @@
ProductGroup = 17C808A80C3BD1BA005707C4 /* Products */;
ProjectRef = 17C808A70C3BD1BA005707C4 /* Shorten.xcodeproj */;
},
{
ProductGroup = 8314D63C1A354DFE00EEE8E6 /* Products */;
ProjectRef = 8314D63B1A354DFE00EEE8E6 /* sidplay.xcodeproj */;
},
{
ProductGroup = 83E6B751181612FD00D4576D /* Products */;
ProjectRef = 83E6B750181612FD00D4576D /* Sparkle.xcodeproj */;
@ -2107,6 +2138,13 @@
remoteRef = 566D321A0D538550004466A5 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
8314D6411A354DFF00EEE8E6 /* sidplay.bundle */ = {
isa = PBXReferenceProxy;
fileType = wrapper.cfbundle;
path = sidplay.bundle;
remoteRef = 8314D6401A354DFF00EEE8E6 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
8359FF3117FEF35D0060F3ED /* ArchiveSource.bundle */ = {
isa = PBXReferenceProxy;
fileType = wrapper.cfbundle;
@ -2191,10 +2229,10 @@
remoteRef = 83E6B75A181612FD00D4576D /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
83E6B75D181612FD00D4576D /* Sparkle Unit Tests.octest */ = {
83E6B75D181612FD00D4576D /* Sparkle Unit Tests.xctest */ = {
isa = PBXReferenceProxy;
fileType = wrapper.cfbundle;
path = "Sparkle Unit Tests.octest";
path = "Sparkle Unit Tests.xctest";
remoteRef = 83E6B75C181612FD00D4576D /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
@ -2205,10 +2243,10 @@
remoteRef = 83E6B75E181612FD00D4576D /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
83E6B761181612FD00D4576D /* finish_installation.app */ = {
83E6B761181612FD00D4576D /* Autoupdate.app */ = {
isa = PBXReferenceProxy;
fileType = wrapper.application;
path = finish_installation.app;
path = Autoupdate.app;
remoteRef = 83E6B760181612FD00D4576D /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
@ -2510,6 +2548,11 @@
name = General;
targetProxy = 17F5623A0C3BD9280019975C /* PBXContainerItemProxy */;
};
836F5BEE1A3579F5002730CC /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
name = sidplay;
targetProxy = 836F5BED1A3579F5002730CC /* PBXContainerItemProxy */;
};
836FB5A618206F1500B3AD2D /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
name = Hively;

View File

@ -8,14 +8,23 @@
<string>811E8515-6C50-44FF-ACDB-088BB9917E26</string>
<key>IDESourceControlProjectOriginsDictionary</key>
<dict>
<key>75748be7-0387-4326-94c7-f41ce0883d2c++505</key>
<string>svn://svn.code.sf.net/p/sidplay-residfp/code/trunk</string>
<key>EF1CF5E1F342919DE309B5C9DAEDDCF1D12D0402</key>
<string>https://github.com/andymatuschak/Sparkle.git</string>
</dict>
<key>IDESourceControlProjectRelativeInstallPathDictionary</key>
<dict>
<key>75748be7-0387-4326-94c7-f41ce0883d2c++505</key>
<string>libsidplay/sidplay-residfp-code/</string>
<key>EF1CF5E1F342919DE309B5C9DAEDDCF1D12D0402</key>
<string>Sparkle/</string>
</dict>
<key>IDESourceControlProjectRepositoryRootDictionary</key>
<dict>
<key>75748be7-0387-4326-94c7-f41ce0883d2c++505</key>
<string>svn://svn.code.sf.net/p/sidplay-residfp/code</string>
</dict>
<key>IDESourceControlProjectURL</key>
<string>https://github.com/andymatuschak/Sparkle.git</string>
<key>IDESourceControlProjectVersion</key>
@ -24,6 +33,14 @@
<string>EF1CF5E1F342919DE309B5C9DAEDDCF1D12D0402</string>
<key>IDESourceControlProjectWCConfigurations</key>
<array>
<dict>
<key>IDESourceControlRepositoryExtensionIdentifierKey</key>
<string>public.vcs.subversion</string>
<key>IDESourceControlWCCIdentifierKey</key>
<string>75748be7-0387-4326-94c7-f41ce0883d2c++505</string>
<key>IDESourceControlWCCName</key>
<string>sidplay-residfp-code</string>
</dict>
<dict>
<key>IDESourceControlRepositoryExtensionIdentifierKey</key>
<string>public.vcs.git</string>

View File

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>org.cogx.$(PRODUCT_NAME:rfc1034identifier)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>NSHumanReadableCopyright</key>
<string>Copyright © 2014 Christopher Snowhill. All rights reserved.</string>
<key>NSPrincipalClass</key>
<string></string>
</dict>
</plist>

View File

@ -0,0 +1 @@
12

View File

@ -0,0 +1 @@
12

View File

@ -0,0 +1,157 @@
/*
* This file is part of libsidplayfp, a SID player engine.
*
* Copyright 2011-2014 Leandro Nini <drfiemost@users.sourceforge.net>
* Copyright 2007-2010 Antti Lankila
* Copyright 2001-2002 by Jarno Paananen
* Copyright 2000-2002 Simon White
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef HARDSID_EMU_H
#define HARDSID_EMU_H
#include "sidplayfp/event.h"
#include "sidemu.h"
#include "EventScheduler.h"
#include "sidplayfp/siddefs.h"
#include "sidcxx11.h"
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
class sidbuilder;
#ifdef _WIN32
#include <windows.h>
#define HSID_VERSION_MIN (WORD) 0x0200
#define HSID_VERSION_204 (WORD) 0x0204
#define HSID_VERSION_207 (WORD) 0x0207
//**************************************************************************
// Version 2 Interface
typedef void (CALLBACK* HsidDLL2_Delay_t) (BYTE deviceID, WORD cycles);
typedef BYTE (CALLBACK* HsidDLL2_Devices_t) ();
typedef void (CALLBACK* HsidDLL2_Filter_t) (BYTE deviceID, BOOL filter);
typedef void (CALLBACK* HsidDLL2_Flush_t) (BYTE deviceID);
typedef void (CALLBACK* HsidDLL2_Mute_t) (BYTE deviceID, BYTE channel, BOOL mute);
typedef void (CALLBACK* HsidDLL2_MuteAll_t) (BYTE deviceID, BOOL mute);
typedef void (CALLBACK* HsidDLL2_Reset_t) (BYTE deviceID);
typedef BYTE (CALLBACK* HsidDLL2_Read_t) (BYTE deviceID, WORD cycles, BYTE SID_reg);
typedef void (CALLBACK* HsidDLL2_Sync_t) (BYTE deviceID);
typedef void (CALLBACK* HsidDLL2_Write_t) (BYTE deviceID, WORD cycles, BYTE SID_reg, BYTE data);
typedef WORD (CALLBACK* HsidDLL2_Version_t) ();
// Version 2.04 Extensions
typedef BOOL (CALLBACK* HsidDLL2_Lock_t) (BYTE deviceID);
typedef void (CALLBACK* HsidDLL2_Unlock_t) (BYTE deviceID);
typedef void (CALLBACK* HsidDLL2_Reset2_t) (BYTE deviceID, BYTE volume);
// Version 2.07 Extensions
typedef void (CALLBACK* HsidDLL2_Mute2_t) (BYTE deviceID, BYTE channel, BOOL mute, BOOL manual);
struct HsidDLL2
{
HINSTANCE Instance;
HsidDLL2_Delay_t Delay;
HsidDLL2_Devices_t Devices;
HsidDLL2_Filter_t Filter;
HsidDLL2_Flush_t Flush;
HsidDLL2_Lock_t Lock;
HsidDLL2_Unlock_t Unlock;
HsidDLL2_Mute_t Mute;
HsidDLL2_Mute2_t Mute2;
HsidDLL2_MuteAll_t MuteAll;
HsidDLL2_Reset_t Reset;
HsidDLL2_Reset2_t Reset2;
HsidDLL2_Read_t Read;
HsidDLL2_Sync_t Sync;
HsidDLL2_Write_t Write;
WORD Version;
};
#endif // _WIN32
#define HARDSID_VOICES 3
// Approx 60ms
#define HARDSID_DELAY_CYCLES 60000
/***************************************************************************
* HardSID SID Specialisation
***************************************************************************/
class HardSID : public sidemu, private Event
{
private:
friend class HardSIDBuilder;
// HardSID specific data
#ifndef _WIN32
static bool m_sidFree[16];
int m_handle;
#endif
static const unsigned int voices;
static unsigned int sid;
// Must stay in this order
bool muted[HARDSID_VOICES];
unsigned int m_instance;
public:
static const char* getCredits();
public:
HardSID(sidbuilder *builder);
~HardSID();
bool getStatus() const { return m_status; }
// Standard component functions
void reset() override { sidemu::reset(); }
uint8_t read(uint_least8_t addr) override;
void write(uint_least8_t addr, uint8_t data) override;
// c64sid functions
void reset(uint8_t volume) override;
// Standard SID functions
void clock() override;
void model(SidConfig::sid_model_t) override {}
void voice(unsigned int num, bool mute) override;
// HardSID specific
void flush();
void filter(bool enable);
// Must lock the SID before using the standard functions.
bool lock(EventContext *env) override;
void unlock() override;
private:
// Fixed interval timer delay to prevent sidplay2
// shoot to 100% CPU usage when song nolonger
// writes to SID.
void event() override;
};
#endif // HARDSID_EMU_H

View File

@ -0,0 +1,84 @@
/*
* This file is part of sidplayfp, a console SID player.
*
* Copyright 2013-2014 Leandro Nini
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "utils.h"
#include <cstdlib>
#ifdef _WIN32
# include <windows.h>
# include <shlobj.h>
#ifdef UNICODE
# define _tgetenv _wgetenv
#else
# define _tgetenv getenv
#endif
SID_STRING utils::getPath()
{
SID_STRING returnPath;
TCHAR szPath[MAX_PATH];
if (SHGetFolderPath(NULL, CSIDL_APPDATA|CSIDL_FLAG_CREATE, NULL, 0, szPath)!=S_OK)
{
TCHAR *path = _tgetenv(TEXT("USERPROFILE"));
if (!path)
throw error();
returnPath.append(path).append(TEXT("\\Application Data"));
}
else
{
returnPath.append(szPath);
}
return returnPath;
}
SID_STRING utils::getDataPath() { return getPath(); }
SID_STRING utils::getConfigPath() { return getPath(); }
#else
SID_STRING utils::getPath(const char* id, const char* def)
{
SID_STRING returnPath;
char *path = getenv(id);
if (!path)
{
path = getenv("HOME");
if (!path)
throw error();
returnPath.append(path).append(def);
}
else
returnPath.append(path);
return returnPath;
}
SID_STRING utils::getDataPath() { return getPath("XDG_DATA_HOME", "/.local/share"); }
SID_STRING utils::getConfigPath() { return getPath("XDG_CONFIG_HOME", "/.config"); }
#endif

View File

@ -0,0 +1,92 @@
/*
* This file is part of libsidplayfp, a SID player engine.
*
* Copyright 2011-2013 Leandro Nini <drfiemost@users.sourceforge.net>
* Copyright 2007-2010 Antti Lankila
* Copyright 2004,2010 Dag Lem <resid@nimrod.no>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "Dac.h"
namespace reSIDfp
{
void Dac::kinkedDac(double* dac, int dacLength, double _2R_div_R, bool term)
{
const double R_INFINITY = 1e6;
// Calculate voltage contribution by each individual bit in the R-2R ladder.
for (int set_bit = 0; set_bit < dacLength; set_bit++)
{
double Vn = 1.; // Normalized bit voltage.
double R = 1.; // Normalized R
const double _2R = _2R_div_R * R; // 2R
double Rn = term ? // Rn = 2R for correct termination,
_2R : R_INFINITY; // INFINITY for missing termination.
int bit;
// Calculate DAC "tail" resistance by repeated parallel substitution.
for (bit = 0; bit < set_bit; bit++)
{
Rn = (Rn == R_INFINITY) ?
R + _2R :
R + _2R * Rn / (_2R + Rn); // R + 2R || Rn
}
// Source transformation for bit voltage.
if (Rn == R_INFINITY)
{
Rn = _2R;
}
else
{
Rn = _2R * Rn / (_2R + Rn); // 2R || Rn
Vn = Vn * Rn / _2R;
}
// Calculate DAC output voltage by repeated source transformation from
// the "tail".
for (++bit; bit < dacLength; bit++)
{
Rn += R;
const double I = Vn / Rn;
Rn = _2R * Rn / (_2R + Rn); // 2R || Rn
Vn = Rn * I;
}
dac[set_bit] = Vn;
}
// Normalize to integerish behavior
double Vsum = 0.;
for (int i = 0; i < dacLength; i ++)
{
Vsum += dac[i];
}
Vsum /= 1 << dacLength;
for (int i = 0; i < dacLength; i ++)
{
dac[i] /= Vsum;
}
}
} // namespace reSIDfp

View File

@ -0,0 +1,56 @@
// ---------------------------------------------------------------------------
// This file is part of reSID, a MOS6581 SID emulator engine.
// Copyright (C) 1999 Dag Lem <resid@nimrod.no>
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
// ---------------------------------------------------------------------------
#ifndef SIDDEFS_FP_H
#define SIDDEFS_FP_H
#ifndef M_PI
# define M_PI 3.14159265358979323846
#endif
// Branch prediction macros, lifted off the Linux kernel.
#if RESID_BRANCH_HINTS && HAVE_BUILTIN_EXPECT
# define likely(x) __builtin_expect(!!(x), 1)
# define unlikely(x) __builtin_expect(!!(x), 0)
#else
# define likely(x) (x)
# define unlikely(x) (x)
#endif
namespace reSIDfp {
typedef enum { MOS6581=1, MOS8580 } ChipModel;
typedef enum { DECIMATE=1, RESAMPLE } SamplingMethod;
}
extern "C"
{
#ifndef __VERSION_CC__
extern const char* residfp_version_string;
#else
const char* residfp_version_string = "@PACKAGE_VERSION@";
#endif
}
// Inlining on/off.
#define RESID_INLINING @RESID_INLINING@
#define RESID_INLINE @RESID_INLINE@
#endif // SIDDEFS_FP_H

View File

@ -0,0 +1,256 @@
/*
* This file is part of libsidplayfp, a SID player engine.
*
* Copyright 2011-2013 Leandro Nini <drfiemost@users.sourceforge.net>
* Copyright 2007-2010 Antti Lankila
* Copyright 2004 Dag Lem <resid@nimrod.no>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "SincResampler.h"
#include <cassert>
#include <cstring>
#include <cmath>
#include <iostream>
#include <sstream>
#include "siddefs-fp.h"
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#ifdef HAVE_MMINTRIN_H
# include <mmintrin.h>
#endif
namespace reSIDfp
{
typedef std::map<std::string, matrix_t> fir_cache_t;
/// Cache for the expensive FIR table computation results.
fir_cache_t FIR_CACHE;
/// Maximum error acceptable in I0 is 1e-6, or ~96 dB.
const double I0E = 1e-6;
const int BITS = 16;
/**
* I0() computes the 0th order modified Bessel function of the first kind.
* This function is originally from resample-1.5/filterkit.c by J. O. Smith.
* It is used to build the Kaiser window for resampling.
*
* @param x evaluate I0 at x
* @return value of I0 at x.
*/
double I0(double x)
{
double sum = 1., u = 1., n = 1.;
const double halfx = x / 2.;
do
{
const double temp = halfx / n;
u *= temp * temp;
sum += u;
n += 1.;
}
while (u >= I0E * sum);
return sum;
}
/**
* Calculate convolution with sample and sinc.
*
* @param a sample buffer input
* @param b sinc
* @param bLength length of the sinc buffer
* @return convolved result
*/
int convolve(const short* a, const short* b, int bLength)
{
#ifdef HAVE_MMINTRIN_H
__m64 acc = _mm_setzero_si64();
const int n = bLength / 4;
for (int i = 0; i < n; i++)
{
const __m64 tmp = _mm_madd_pi16(*(__m64*)a, *(__m64*)b);
acc = _mm_add_pi16(acc, tmp);
a += 4;
b += 4;
}
int out = _mm_cvtsi64_si32(acc) + _mm_cvtsi64_si32(_mm_srli_si64(acc, 32));
_mm_empty();
bLength &= 3;
#else
int out = 0;
#endif
for (int i = 0; i < bLength; i++)
{
out += *a++ * *b++;
}
return (out + (1 << 14)) >> 15;
}
int SincResampler::fir(int subcycle)
{
// find the first of the nearest fir tables close to the phase
int firTableFirst = (subcycle * firRES >> 10);
const int firTableOffset = (subcycle * firRES) & 0x3ff;
// find firN most recent samples, plus one extra in case the FIR wraps.
int sampleStart = sampleIndex - firN + RINGSIZE - 1;
const int v1 = convolve(sample + sampleStart, (*firTable)[firTableFirst], firN);
// Use next FIR table, wrap around to first FIR table using
// previous sample.
if (unlikely(++firTableFirst == firRES))
{
firTableFirst = 0;
++sampleStart;
}
const int v2 = convolve(sample + sampleStart, (*firTable)[firTableFirst], firN);
// Linear interpolation between the sinc tables yields good
// approximation for the exact value.
return v1 + (firTableOffset * (v2 - v1) >> 10);
}
SincResampler::SincResampler(double clockFrequency, double samplingFrequency, double highestAccurateFrequency) :
sampleIndex(0),
cyclesPerSample(static_cast<int>(clockFrequency / samplingFrequency * 1024.)),
sampleOffset(0),
outputValue(0)
{
// 16 bits -> -96dB stopband attenuation.
const double A = -20. * log10(1.0 / (1 << BITS));
// A fraction of the bandwidth is allocated to the transition band, which we double
// because we design the filter to transition halfway at nyquist.
const double dw = (1. - 2.*highestAccurateFrequency / samplingFrequency) * M_PI * 2.;
// For calculation of beta and N see the reference for the kaiserord
// function in the MATLAB Signal Processing Toolbox:
// http://www.mathworks.com/access/helpdesk/help/toolbox/signal/kaiserord.html
const double beta = 0.1102 * (A - 8.7);
const double I0beta = I0(beta);
const double cyclesPerSampleD = clockFrequency / samplingFrequency;
{
// The filter order will maximally be 124 with the current constraints.
// N >= (96.33 - 7.95)/(2 * pi * 2.285 * (maxfreq - passbandfreq) >= 123
// The filter order is equal to the number of zero crossings, i.e.
// it should be an even number (sinc is symmetric about x = 0).
int N = static_cast<int>((A - 7.95) / (2.285 * dw) + 0.5);
N += N & 1;
// The filter length is equal to the filter order + 1.
// The filter length must be an odd number (sinc is symmetric about
// x = 0).
firN = static_cast<int>(N * cyclesPerSampleD) + 1;
firN |= 1;
// Check whether the sample ring buffer would overflow.
assert(firN < RINGSIZE);
// Error is bounded by err < 1.234 / L^2, so L = sqrt(1.234 / (2^-16)) = sqrt(1.234 * 2^16).
firRES = static_cast<int>(ceil(sqrt(1.234 * (1 << BITS)) / cyclesPerSampleD));
// firN*firRES represent the total resolution of the sinc sampling. JOS
// recommends a length of 2^BITS, but we don't quite use that good a filter.
// The filter test program indicates that the filter performs well, though. */
}
std::ostringstream o;
o << firN << "," << firRES << "," << cyclesPerSampleD;
const std::string firKey = o.str();
fir_cache_t::iterator lb = FIR_CACHE.lower_bound(firKey);
// The FIR computation is expensive and we set sampling parameters often, but
// from a very small set of choices. Thus, caching is used to speed initialization.
if (lb != FIR_CACHE.end() && !(FIR_CACHE.key_comp()(firKey, lb->first)))
{
firTable = &(lb->second);
}
else
{
// Allocate memory for FIR tables.
matrix_t tempTable(firRES, firN);
firTable = &(FIR_CACHE.insert(lb, fir_cache_t::value_type(firKey, tempTable))->second);
// The cutoff frequency is midway through the transition band, in effect the same as nyquist.
const double wc = M_PI;
// Calculate the sinc tables.
const double scale = 32768.0 * wc / cyclesPerSampleD / M_PI;
for (int i = 0; i < firRES; i++)
{
const double jPhase = (double) i / firRES + firN / 2;
for (int j = 0; j < firN; j++)
{
const double x = j - jPhase;
const double xt = x / (firN / 2);
const double kaiserXt = fabs(xt) < 1. ? I0(beta * sqrt(1. - xt * xt)) / I0beta : 0.;
const double wt = wc * x / cyclesPerSampleD;
const double sincWt = fabs(wt) >= 1e-8 ? sin(wt) / wt : 1.;
(*firTable)[i][j] = static_cast<short>(scale * sincWt * kaiserXt);
}
}
}
}
bool SincResampler::input(int input)
{
bool ready = false;
sample[sampleIndex] = sample[sampleIndex + RINGSIZE] = input;
sampleIndex = (sampleIndex + 1) & (RINGSIZE - 1);
if (sampleOffset < 1024)
{
outputValue = fir(sampleOffset);
ready = true;
sampleOffset += cyclesPerSample;
}
sampleOffset -= 1024;
return ready;
}
void SincResampler::reset()
{
memset(sample, 0, RINGSIZE * 2 * sizeof(sample[0]));
sampleOffset = 0;
}
} // namespace reSIDfp

View File

@ -0,0 +1,724 @@
=encoding utf8
=head1 NAME
stilview - command-line program to help you retrieve the entries stored
in STIL.
=head1 SYNOPSIS
B<stilview> [-b] [-d] [-e entry] [-f field] [-i] [-l HVSC base dir] [-m]
[-o] [-s] [-t tune number]
B<stilview> {[-h] | [-v]}
=head1 DESCRIPTION
B<STILView> is a command-line driven program to help you retrieve the
entries stored in STIL fast and accurately. STILView uses the STIL C++
class heavily to do this, and in fact, the primary purpose of this
command-line program is to test that class (which is, BTW, used in many
GUI-based SID players, most notably in SIDPlay for Windows and XSIDPLAY
for Unix systems). However, it is user-friendly enough to be used by
non-programmers, too.
=head1 GLOSSARY
Some terms and STIL-related lingo in alphabetical order:
=over
=item B<BUG ENTRY>
There exists a special file in HVSC (F</DOCUMENTS/BUGlist.txt>) that
lists all known bugs in SID tunes in HVSC. See the top of that file
for details about what's in it exactly. A BUG entry is like a
STIL entry, but it is contained in this BUGlist.txt file.
=item B<FIELD>
The smallest piece of information in a STIL entry. Currently
valid field names are NAME, TITLE, ARTIST and COMMENT.
=item B<FILE-GLOBAL COMMENT>
A special COMMENT field in a STIL entry for a
multi-tune SID file that refers to the whole SID, not just one tune in
it. These usually contain general information about the SID file
itself.
Example:
/Hubbard_Rob/Gerry_the_Germ.sid
COMMENT: In Rob's own demo of this music, the tunes are named after the levels
in the original game.
(#1)
TITLE: Lungs
(#2)
TITLE: Kidney
(#7)
TITLE: End
=item B<HVSC>
High Voltage SID Collection. If you don't know what this is, you
downloaded the wrong program. :)
=item B<HVSC-RELATIVE PATHNAME>
The pathname plus filename of a SID file that can be found in your
HVSC, relative to the base directory of HVSC. It is always in
UNIX-style format, eg.: /Hubbard_Rob/Commando.sid refers to
Rob Hubbard's Commando.sid file within HVSC (which may actually be
found as C:\Music\HVSC\Hubbard_Rob\Commando.sid on your Windows PC).
=item B<MULTI-TUNE ENTRY>
A STIL entry that is referring to a SID file that has many tunes in it.
Each tune might have its own STIL block, which are separated by a
so-called tune designation in the form of "(#x)", where x = the
tune number. Consult the STIL.FAQ in HVSC for a detailed description.
Example:
/Hubbard_Rob/Gerry_the_Germ.sid
COMMENT: In Rob's own demo of this music, the tunes are named after the levels
in the original game.
(#1)
TITLE: Lungs
(#2)
TITLE: Kidney
(#7)
TITLE: End
=item B<SECTION>
A part of STIL that belongs to one composer (ie. every STIL entry
referring to SID files that are in one subdirectory in HVSC).
Sections in STIL are always separated by a line in the form of: "###
Composer's name ########".
=item B<SECTION-GLOBAL COMMENT>
A special STIL entry that refers not to an individual SID file,
but to a whole subdirectory. These usually contain info about the
composer himself, or about all the SID file he/she ever composed,
and are always indexed in the form of "/Subdir/" (note the trailing
slash!).
Example:
/Hubbard_Rob/
COMMENT: All of these tunes have been confirmed by Hubbard to be his. People
have often stolen Hubbard's routine causing some tunes to be falsely
credited to him.
Hubbard's own comments are denoted by (RH).
=item B<SINGLE-TUNE ENTRY>
A STIL entry that has no tune designation in it in the form of "(#x)",
where x is a number. (Note, that a single-tune entry might still refer
to a SID file which has many tunes in it, ie. when a single-tune entry
has nothing but a COMMENT field in it!)
Example:
/Hubbard_Rob/Chain_Reaction.sid
TITLE: Zoolook (remix) [from Zoolook]
ARTIST: Jean Michel Jarre
Another example (the SID this is refering to has many tunes in it!):
/Barrett_Steve/Magic_Land_Dizzy.sid
COMMENT: Also used in the game "Wacky Darts" (c) 1990 Codemasters.
=item B<STIL>
SID Tune Information List, essentially a text-file database that
can be found in your HVSC in the /DOCUMENTS/ subdirectory.
=item B<STIL ENTRY>
All of the pieces of information in STIL relating to one SID file
of the HVSC. They are always indexed by the HVSC-relative pathname.
=item B<TUNE>
One of the compositions in a SID. Most SID files have only one tune
in them, but many have more than one (eg. one for the title score
of the game, and one for the hi-score music).
=back
=head1 OPTIONS
=over
=item B<-b>
Do B<not> print BUG entries
Default value: Not specified (ie. do print BUG entries)
Example: C<stilview -e=/Hubbard_Rob/Commando.sid -b>
When this option is specified, BUG entries will not be printed for
the given SID tune. At a minimum, the -e option has to be specified
for this option to work.
=item B<-d>
Default value: Not specified (ie. debug mode is off)
Example: C<stilview -e=/Hubbard_Rob/Commando.sid -d>
Turns on debug mode in STILView. This will result in an extensive
output, with the debugging messages going to STDERR. If you
encounter any problem or strange behavior with STILView, run
STILView with the exact same options as you did when you
encountered the problem, with this -d option added to them. Capture
the complete output of this run, and send it to me with a detailed
explanation of the problem (see email address at the top of this
file).
=item B<-e>=I<entry>
Default: NONE (you have to give an HVSC-relative pathname to this
option)
Example #1: C<stilview -e=/Hubbard_Rob/Commando.sid>
Example #2: C<stilview -e=/Hubbard_Rob/>
This is where you specify the STIL entry you are looking for, given
as an HVSC-relative pathname. If there exists no STIL entry for the
given filename, STILView will print out nothing. Otherwise, you'll
get the STIL entry (or parts of it, as you may have specified it by
other options). HVSC-relative pathnames are case-insensitive, so
/HUBBARD_ROB/Commando.sid is the same as /Hubbard_Rob/Commando.sid.
Example #1 is the most frequent way of retrieving STIL entries, and
it will return all of the STIL entry for Commando.sid, as well as
the section-global comment for /Hubbard_Rob/. Example #2 is another
valid thing to do: this will return only the section-global comment
for /Hubbard_Rob/.
=item B<-h>
Default: NONE Example: stilview -h
Prints a brief help screen listing the available options. All other
options that are also specified on the command-line are ignored.
=item B<-f>=I<field>
Default: all
Valid values for <field> are: all, name, author, title, artist,
comment
Example #1: C<stilview -l -e=/Hubbard_Rob/Delta.sid -f=comment>
Example #2: C<stilview -l -e=/Hubbard_Rob/Delta.sid -t=1 -f=title>
Example #3: C<stilview -l -e=/Hubbard_Rob/Delta.sid -t=12 -f=all -s -b>
Asks for one particular field in a STIL entry. Combined with the -t
option, these two options can retrieve any portion of a STIL entry,
including a single field in a specific subtune's entry. Below is
full and complete explanation of what the different possible
combinations of the -t and -f options retrieve:
C<-t=0 -f=all> : All of the STIL entry is printed.
C<-t=0 -f=comment> : The file-global comment is printed. For
single-tune entries that have nothing but a COMMENT field in them,
this prints that COMMENT. For single-tune entries that have other
fields in them, this prints nothing. (This is because single-tune
entries with nothing but a COMMENT field are assumed to be
file-global comments.)
C<< -t=0 -f=<name/author/title/artist> >> : Nothing is printed. This
combination of these options is invalid.
C<< -t=<x> -f=all >> : (Where x is anything but 0.) All fields from the
portion of the STIL entry for the given tune number <x> are
printed. For single-tune entries, asking for -t=1 -f=all is
equivalent to saying -t=0 -f=all, since by definition, the whole
entry refers to only one tune. (However, specifying -t with any
other number than 1 will print nothing!) Note that if there's a
file-global comment in the STIL entry (which also means that if a
single-tune entry has nothing but a COMMENT field in it), that is
B<not> printed with these combinations of options.
C<< -t=<x> -f=<name/author/title/artist/comment> >> : (Where x is anything
but 0.) The specific field from the portion of the STIL entry for
the given tune number is printed. For single-tune entries that have
nothing but a COMMENT in them, this returns nothing.
Of course, if the STIL entry or any portion of it asked with these
options does not exist, STILView will print nothing. Also, unless
otherwise specified with the -o, -s and -b options, the
section-global comment and the BUG entry of the given SID file will
also get printed (provided they exist).
In example #1, the file-global comment for /Hubbard_Rob/Delta.sid
is printed, since -t is not specified and is assumed to be 0. Also
printed are the section- global comment and the BUG entry for the
same SID file (if they exist). In example #2, the TITLE field of
the STIL entry for tune #1 of /Hubbard_Rob/Delta.sid is printed
along with the section-global comment and the BUG entry for the
same SID file (if they exist). In example #3, all of the STIL entry
for tune #12 of /Hubbard_Rob/Delta.sid is printed, but nothing
else.
=item B<-i>
Default: NONE
Example: C<stilview -i>
Starts STILView in interactive mode, ignoring all other options
specified on the command-line, except -l, -d and -m. In interactive
mode, you can look for STIL entries by typing them in. You will get
prompted for the desired STIL entry (which has to be specified with
an HVSC-relative pathname), for the tune number requested (which
should be any non-negative number, but this is not enforced), and
finally for the specific STIL field you want to retrieve.
=item B<-l>=I<HVSC base dir>
Default: The value of the HVSC_BASE environment variable
Example #1: C<stilview -l=C:\Music\HVSC\ -e=/Hubbard_Rob/Commando.sid>
Example #2: C<stilview -l=../HVSC/ =-e=/Hubbard_Rob/Commando.sid>
Example #3: C<stilview -l -e=/Hubbard_Rob/Commando.sid>
This is where you tell STILView where it can find the HVSC base
directory (the path to the directory has to be specified in the
form required by your operating system, eg. C:\Music\HVSC under
Windows, /home/lala/HVSC under UNIX). STILView will then try to
locate the STIL.txt file in the /DOCUMENTS/ subdirectory of that
directory. If this option is not specified (or if -l is specified
without a base directory), STILView will try to extract the path of
the HVSC base directory from the HVSC_BASE environment variable. If
that environment variable doesn't exist or is pointing to a
location where there's no STIL.txt file in a DOCUMENTS directory,
STILView fails. If the HVSC_BASE environment variable exists and is
valid, and this option is specified, the directory specified with
this option is used as the HVSC base directory instead of the
environment variable.
In example #1 the HVSC base directory is located in C:\Music\HVSC\
on the hard drive of a Windows PC, in example #2 it is located in
the HVSC directory of the current directory's parent directory of a
UNIX system. In example #3 the HVSC base directory is not specified
with the option, so it is assumed that the HVSC_BASE environment
variable contains the path to it. In reality, specifying the -l
option in example #3 is redundant, and can be omitted.
=item B<-m>
Demo mode
Default: NONE
Example #1: C<stilview -m>
Example #2: C<stilview -e=/Hubbard_Rob/Commando.sid -m -i>
When specified, it prints out a whole bunch of things that a) test
most of the functionality of STILView, and b) show what STILView is
capable of retrieving from STIL. In example #1, the demo is printed
with the STIL info coming from a default STIL entry, then STILView
quits. In example #2, the demo is printed taking the STIL info from
the specified STIL entry of /Hubbard_Rob/Commando.sid (instead of
the default SID file), then interactive mode is entered.
=item B<-o>
Do B<not> print STIL entries
Default value: Not specified (ie. do print STIL entries)
Example #1: C<stilview -e=/Hubbard_Rob/Delta.sid -o>
Example #2: C<stilview -e=/Hubbard_Rob/Delta.sid -o -s>
When this option is specified, STIL entries will not be printed for
the given SID tune (but section-global entries and BUG entries will
be printed, provided they exist and other options did not turn
their output off). At a minimum, the -e option has to be specified
for this option to work. Example #1 will print out the
section-global comment and the BUG entry for
/Hubbard_Rob/Delta.sid, example #2 will print out just the
section-global comment for the same SID.
=item B<-s>
Do B<not> print section-global comments
Default value: Not specified (ie. do print section-global entries)
Example: C<stilview -e=/Hubbard_Rob/Delta.sid -s>
When this option is specified, section-global entries will not be
printed for the given SID tune. At a minimum, the -e option has to
be specified for this option to work.
=item B<-t>=I<tune number>
Default value: 0
Example #1: C<stilview -e=/Hubbard_Rob/Commando.sid -t=0>
Example #2: C<stilview -e=/Hubbard_Rob/Delta.sid -t=1 -f=title -s -b>
Example #3: C<stilview -e=/Hubbard_Rob/Delta.sid -t=12>
Asks for the portion of a STIL entry referring to one particular
tune. If tune number 0 is given, it retrieves all of the entry.
Combined with the -f option, these two options can retrieve any
portion of a STIL entry, including a single field in a specific
subtune's entry.
For further details about this option, see the explanation of the
-f option.
Example #1 retrieves all of the STIL entry for
/Hubbard_Rob/Commando.sid, including the section-global comment and
the BUG entry (if any), but since the default value for this option
is 0, it might as well be omitted in this example. Example #2
retrieves only the TITLE field of the first subtune's entry for
/Hubbard_Rob/Delta.sid (and not the section- global comment or the
BUG entry), while example #3 retrieves all of the STIL entry for
tune #12 of the same SID file (including the section-global comment
and the BUG entry, if any).
=item B<-v>
Print version numbers
Default value: Not specified (ie. do *not* print version numbers)
Example #1: C<stilview -v>
Example #2: C<stilview -e=/Hubbard_Rob/Commando.sid -v>
When this option is specified, the version number of the STILView
program and the version number of the STIL.txt file used by it is
printed out. In example #1 this is the only piece of info that gets
printed on the screen, in example #2 the version numbers are
printed out, then the STIL entry for /Hubbard_Rob/Commando.sid is
also printed out.
=back
=head1 ENVIRONMENT
=over
=item B<HVSC_BASE>
Specifies the location of the HVSC base directory.
=back
=head1 EXAMPLES
All of the examples below assume that the HVSC_BASE environment is set
to a valid HVSC base directory (where the F<$HVSC_BASE/DOCUMENTS/STIL.txt>
and F<$HVSC_BASE/DOCUMENTS/BUGlist.txt> files exist), and the examples
also assume the presence of the following entries in these files:
--- In STIL.txt ---
/Hubbard_Rob/
COMMENT: All of these tunes have been confirmed by Hubbard to be his. People
have often stolen Hubbard's routine causing some tunes to be falsely
credited to him.
/Hubbard_Rob/Action_Biker.sid
COMMENT: "Action B was a very early game and very conservative in it's approach
- it was my idea of giving them what I thought they wanted, a simple
cute tune....." (RH)
/Hubbard_Rob/Commando.sid
COMMENT: Tunes #1 and #3 have been converted from arcade version.
/Hubbard_Rob/Delta.sid
COMMENT: According to Hubbard, Kentilla and Delta were the most complicated one
to compose, they took the longest time to do and they both drove him
insane.
(#1)
TITLE: On the Run [from the Dark Side of the Moon]
ARTIST: Pink Floyd
COMMENT: It is more inspired by it than a remix of it.
(#12)
TITLE: Koyaanisqatsi [from the movie]
ARTIST: Philip Glass
COMMENT: "Inspired by Philip Glass and Pink Floyd." (RH)
/Hubbard_Rob/International_Karate.sid
TITLE: Merry Christmas, Mr. Lawrence [from the movie] (0:42-1:16)
ARTIST: Ryuichi Sakamoto
COMMENT: "[...] I started exploring pentatonic things in B flat minor over
different bass notes, B flat, D flat, G flat and A flat. The middle
section went into F (I think) at double tempo to liven things up. I
was pleased with the tune......" (RH)
/Hubbard_Rob/Rasputin.sid
(#1)
TITLE: Katjusha (0:07-0:36)
ARTIST: Matvei Blanter, M. Isakovski
TITLE: Katjusha (2:20)
ARTIST: Matvei Blanter, M. Isakovski
TITLE: Kaljinka (2:41-2:51)
ARTIST: Traditional
COMMENT: Russian folk song.
TITLE: Kaljinka (3:12-3:22)
ARTIST: Traditional
COMMENT: Russian folk song.
(#2)
COMMENT: Russian folk song.
--- In BUGlist.txt ---
/Hubbard_Rob/Commando.sid
BUG: This is just for demo.
/Hubbard_Rob/Delta.sid
(#12)
BUG: Demo entry.
Given these entries, following are the printouts you can expect from
STILView. ($> denotes a command-line prompt given by your operating
system.)
Everything related to a SID file is printed:
$> stilview -e=/Hubbard_Rob/Commando.sid
---- GLOBAL COMMENT ----
COMMENT: All of these tunes have been confirmed by Hubbard to be his. People
have often stolen Hubbard's routine causing some tunes to be falsely
credited to him.
------ STIL ENTRY ------
COMMENT: Tunes #1 and #3 have been converted from arcade version.
---------- BUG ----------
BUG: This is just for demo.
$>
Ask for just the section-global comment:
$> stilview -e=/Hubbard_Rob/
/Hubbard_Rob/
COMMENT: All of these tunes have been confirmed by Hubbard to be his. People
have often stolen Hubbard's routine causing some tunes to be falsely
credited to him.
$>
Note that this can also be retrieved with:
$> stilview -e=/Hubbard_Rob/Commando.sid -o -b
COMMENT: All of these tunes have been confirmed by Hubbard to be his. People
have often stolen Hubbard's routine causing some tunes to be falsely
credited to him.
$>
This prints out nothing, as single-tune entries do not have file-global
comments:
$> stilview -e=/Hubbard_Rob/International_Karate.sid -t=0 -f=comment -s -b
$>
...Except if the only field in them is a COMMENT (in which case that
comment is assumed to be a file-global comment):
$> stilview -e=/Hubbard_Rob/Action_Biker.sid -t=0 -f=comment -s -b
COMMENT: "Action B was a very early game and very conservative in it's approach
- it was my idea of giving them what I thought they wanted, a simple
cute tune....." (RH)
$>
Also note that single-tune entries have only one tune, so asking for
the STIL entry of tune #3 is pointless:
$> stilview -e=/Hubbard_Rob/International_Karate.sid -t=3 -s -b
$>
Print out the file-global comment for the given SID file:
$> stilview -e=/Hubbard_Rob/Delta.sid -t=0 -f=comment -s -b
COMMENT: According to Hubbard, Kentilla and Delta were the most complicated one
to compose, they took the longest time to do and they both drove him
insane.
$>
Print out the ARTIST field of tune #12 of the given SID file, plus
print out everything else related to the SID file:
$> stilview -e=/Hubbard_Rob/Delta.sid -t=12 -f=artist
---- GLOBAL COMMENT ----
COMMENT: All of these tunes have been confirmed by Hubbard to be his. People
have often stolen Hubbard's routine causing some tunes to be falsely
credited to him.
------ STIL ENTRY ------
ARTIST: Philip Glass
---------- BUG ----------
BUG: Demo entry.
$>
Note that the current version of STILView is capable to retrieve only
the first specified field of a tune that covers multiple songs! See
below:
$> stilview -e=/Hubbard_Rob/Rasputin.sid -t=1 -f=title -s
TITLE: Katjusha (0:07-0:36)
$>
Section-global comments are printed out even if the STIL entry for the
given SID file does not exist:
$> stilview -e=/Hubbard_Rob/This_doesnt_exist.sid
COMMENT: All of these tunes have been confirmed by Hubbard to be his. People
have often stolen Hubbard's routine causing some tunes to be falsely
credited to him.
$>
The following 4 steps depict how to have STILView print out everything
related to a given SID file's given tune number one by one:
1) This prints out just the section-global comment:
$> stilview -e=/Hubbard_Rob/Delta.sid -o -b
COMMENT: All of these tunes have been confirmed by Hubbard to be his. People
have often stolen Hubbard's routine causing some tunes to be falsely
credited to him.
$>
2) This prints out just the file-global comment:
$> stilview -e=/Hubbard_Rob/Delta.sid -t=0 -f=comment -s -b
COMMENT: According to Hubbard, Kentilla and Delta were the most complicated one
to compose, they took the longest time to do and they both drove him
insane.
$>
3) This prints out all of the STIL entry for the given tune number:
$> stilview -e=/Hubbard_Rob/Delta.sid -t=12 -f=all -s -b
TITLE: Koyaanisqatsi [from the movie]
ARTIST: Philip Glass
COMMENT: "Inspired by Philip Glass and Pink Floyd." (RH)
$>
4) And this prints out just the BUG entry for the same tune number:
$> stilview -e=/Hubbard_Rob/Delta.sid -t=12 -s -o
BUG: Demo entry.
$>
The following 3 steps depict how to have STILView print out everything
related to a given SID file:
1) This prints out just the section-global comment:
$> stilview -e=/Hubbard_Rob/Delta.sid -o -b
COMMENT: All of these tunes have been confirmed by Hubbard to be his. People
have often stolen Hubbard's routine causing some tunes to be falsely
credited to him.
$>
2) This prints out all of the STIL entry:
$> stilview -e=/Hubbard_Rob/Delta.sid -s -b
COMMENT: "[...] The Delta music loader and ingame music was Gary Liddon's idea.
[...] He was the producer at Thalamus at the time. He told Rob Hubbard
to make the ingame music like the 2nd track from Dark Side of the Moon
by Pink Floyd." (Info from Matt Furniss.)
"The small jingles are all small clips from Sanxion and Romeo/Juliet
music. They were all supposed to be for short stingers such as end of
level, extra life etc..."
"Delta was based on this minimalist composition technique inspired by
Glass and a bit of Pink Floyd. It was quite hard too do and required
some custom code to the driver to do it. The music was tedious to
debug. The other Delta stuff was more conventional - I quite liked the
other tunes. Delta was spread over a 2 week period....." (RH)
According to Hubbard, Kentilla and Delta were the most complicated one
to compose, they took the longest time to do and they both drove him
insane.
(#1)
TITLE: On the Run [from the Dark Side of the Moon]
ARTIST: Pink Floyd
COMMENT: It is more inspired by it than a remix of it.
(#12)
TITLE: Koyaanisqatsi [from the movie]
ARTIST: Philip Glass
COMMENT: "Inspired by Philip Glass and Pink Floyd." (RH)
$>
3) And this prints out all of the BUG entry:
$> stilview -e=/Hubbard_Rob/Delta.sid -s -o
(#12)
BUG: Demo entry.
$>
=head1 AUTHORS
=over
=item B<LaLa> <LaLa@C64.org>
Original author.
=item B<Leandro Nini> <drfiemost@users.sourceforge.net>
Current maintainer.
=back
=head1 RESOURCES
=over
=item SourceForge project: L<http://sourceforge.net/projects/sidplay-residfp/>
=item High Voltage Sid Collection (HVSC): L<http://hvsc.c64.org/>
=back
=head1 COPYING
=over
=item Copyright (C) 1998, 2002 LaLa
=item Copyright (C) 2012-2014 Leandro Nini
=back
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.

View File

@ -0,0 +1,337 @@
/*
* This file is part of libsidplayfp, a SID player engine.
*
* Copyright 2011-2013 Leandro Nini <drfiemost@users.sourceforge.net>
* Copyright 2007-2010 Antti Lankila
* Copyright 2000 Simon White
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef OPCODES_H
#define OPCODES_H
#define OPCODE_MAX 0x100
/* HLT
case 0x02: case 0x12: case 0x22: case 0x32: case 0x42: case 0x52:
case 0x62: case 0x72: case 0x92: case 0xb2: case 0xd2: case 0xf2:
case 0x02: case 0x12: case 0x22: case 0x32: case 0x42: case 0x52:
case 0x62: case 0x72: case 0x92: case 0xb2: case 0xd2: case 0xf2:
*/
#define BRKn 0x00
#define JSRw 0x20
#define RTIn 0x40
#define RTSn 0x60
#define NOPb 0x80
#define NOPb_ NOPb: case 0x82: case 0xC2: case 0xE2: case 0x89
#define LDYb 0xA0
#define CPYb 0xC0
#define CPXb 0xE0
#define ORAix 0x01
#define ANDix 0x21
#define EORix 0x41
#define ADCix 0x61
#define STAix 0x81
#define LDAix 0xA1
#define CMPix 0xC1
#define SBCix 0xE1
#define LDXb 0xA2
#define SLOix 0x03
#define RLAix 0x23
#define SREix 0x43
#define RRAix 0x63
#define SAXix 0x83
#define LAXix 0xA3
#define DCPix 0xC3
#define ISBix 0xE3
#define NOPz 0x04
#define NOPz_ NOPz: case 0x44: case 0x64
#define BITz 0x24
#define STYz 0x84
#define LDYz 0xA4
#define CPYz 0xC4
#define CPXz 0xE4
#define ORAz 0x05
#define ANDz 0x25
#define EORz 0x45
#define ADCz 0x65
#define STAz 0x85
#define LDAz 0xA5
#define CMPz 0xC5
#define SBCz 0xE5
#define ASLz 0x06
#define ROLz 0x26
#define LSRz 0x46
#define RORz 0x66
#define STXz 0x86
#define LDXz 0xA6
#define DECz 0xC6
#define INCz 0xE6
#define SLOz 0x07
#define RLAz 0x27
#define SREz 0x47
#define RRAz 0x67
#define SAXz 0x87
#define LAXz 0xA7
#define DCPz 0xC7
#define ISBz 0xE7
#define PHPn 0x08
#define PLPn 0x28
#define PHAn 0x48
#define PLAn 0x68
#define DEYn 0x88
#define TAYn 0xA8
#define INYn 0xC8
#define INXn 0xE8
#define ORAb 0x09
#define ANDb 0x29
#define EORb 0x49
#define ADCb 0x69
#define LDAb 0xA9
#define CMPb 0xC9
#define SBCb 0xE9
#define SBCb_ SBCb: case 0XEB
#define ASLn 0x0A
#define ROLn 0x2A
#define LSRn 0x4A
#define RORn 0x6A
#define TXAn 0x8A
#define TAXn 0xAA
#define DEXn 0xCA
#define NOPn 0xEA
#define NOPn_ NOPn: case 0x1A: case 0x3A: case 0x5A: case 0x7A: case 0xDA: case 0xFA
#define ANCb 0x0B
#define ANCb_ ANCb: case 0x2B
#define ASRb 0x4B
#define ARRb 0x6B
#define ANEb 0x8B
#define XAAb 0x8B
#define LXAb 0xAB
#define SBXb 0xCB
#define NOPa 0x0C
#define BITa 0x2C
#define JMPw 0x4C
#define JMPi 0x6C
#define STYa 0x8C
#define LDYa 0xAC
#define CPYa 0xCC
#define CPXa 0xEC
#define ORAa 0x0D
#define ANDa 0x2D
#define EORa 0x4D
#define ADCa 0x6D
#define STAa 0x8D
#define LDAa 0xAD
#define CMPa 0xCD
#define SBCa 0xED
#define ASLa 0x0E
#define ROLa 0x2E
#define LSRa 0x4E
#define RORa 0x6E
#define STXa 0x8E
#define LDXa 0xAE
#define DECa 0xCE
#define INCa 0xEE
#define SLOa 0x0F
#define RLAa 0x2F
#define SREa 0x4F
#define RRAa 0x6F
#define SAXa 0x8F
#define LAXa 0xAF
#define DCPa 0xCF
#define ISBa 0xEF
#define BPLr 0x10
#define BMIr 0x30
#define BVCr 0x50
#define BVSr 0x70
#define BCCr 0x90
#define BCSr 0xB0
#define BNEr 0xD0
#define BEQr 0xF0
#define ORAiy 0x11
#define ANDiy 0x31
#define EORiy 0x51
#define ADCiy 0x71
#define STAiy 0x91
#define LDAiy 0xB1
#define CMPiy 0xD1
#define SBCiy 0xF1
#define SLOiy 0x13
#define RLAiy 0x33
#define SREiy 0x53
#define RRAiy 0x73
#define SHAiy 0x93
#define LAXiy 0xB3
#define DCPiy 0xD3
#define ISBiy 0xF3
#define NOPzx 0x14
#define NOPzx_ NOPzx: case 0x34: case 0x54: case 0x74: case 0xD4: case 0xF4
#define STYzx 0x94
#define LDYzx 0xB4
#define ORAzx 0x15
#define ANDzx 0x35
#define EORzx 0x55
#define ADCzx 0x75
#define STAzx 0x95
#define LDAzx 0xB5
#define CMPzx 0xD5
#define SBCzx 0xF5
#define ASLzx 0x16
#define ROLzx 0x36
#define LSRzx 0x56
#define RORzx 0x76
#define STXzy 0x96
#define LDXzy 0xB6
#define DECzx 0xD6
#define INCzx 0xF6
#define SLOzx 0x17
#define RLAzx 0x37
#define SREzx 0x57
#define RRAzx 0x77
#define SAXzy 0x97
#define LAXzy 0xB7
#define DCPzx 0xD7
#define ISBzx 0xF7
#define CLCn 0x18
#define SECn 0x38
#define CLIn 0x58
#define SEIn 0x78
#define TYAn 0x98
#define CLVn 0xB8
#define CLDn 0xD8
#define SEDn 0xF8
#define ORAay 0x19
#define ANDay 0x39
#define EORay 0x59
#define ADCay 0x79
#define STAay 0x99
#define LDAay 0xB9
#define CMPay 0xD9
#define SBCay 0xF9
#define TXSn 0x9A
#define TSXn 0xBA
#define SLOay 0x1B
#define RLAay 0x3B
#define SREay 0x5B
#define RRAay 0x7B
#define SHSay 0x9B
#define TASay 0x9B
#define LASay 0xBB
#define DCPay 0xDB
#define ISBay 0xFB
#define NOPax 0x1C
#define NOPax_ NOPax: case 0x3C: case 0x5C: case 0x7C: case 0xDC: case 0xFC
#define SHYax 0x9C
#define LDYax 0xBC
#define ORAax 0x1D
#define ANDax 0x3D
#define EORax 0x5D
#define ADCax 0x7D
#define STAax 0x9D
#define LDAax 0xBD
#define CMPax 0xDD
#define SBCax 0xFD
#define ASLax 0x1E
#define ROLax 0x3E
#define LSRax 0x5E
#define RORax 0x7E
#define SHXay 0x9E
#define LDXay 0xBE
#define DECax 0xDE
#define INCax 0xFE
#define SLOax 0x1F
#define RLAax 0x3F
#define SREax 0x5F
#define RRAax 0x7F
#define SHAay 0x9F
#define LAXay 0xBF
#define DCPax 0xDF
#define ISBax 0xFF
// Instruction Aliases
#define ASOix SLOix
#define LSEix SREix
#define AXSix SAXix
#define DCMix DCPix
#define INSix ISBix
#define ASOz SLOz
#define LSEz SREz
#define AXSz SAXz
#define DCMz DCPz
#define INSz ISBz
#define ALRb ASRb
#define OALb LXAb
#define ASOa SLOa
#define LSEa SREa
#define AXSa SAXa
#define DCMa DCPa
#define INSa ISBa
#define ASOiy SLOiy
#define LSEiy SREiy
#define AXAiy SHAiy
#define DCMiy DCPiy
#define INSiy ISBiy
#define ASOzx SLOzx
#define LSEzx SREzx
#define AXSzy SAXzy
#define DCMzx DCPzx
#define INSzx ISBzx
#define ASOay SLOay
#define LSEay SREay
#define DCMay DCPay
#define INSay ISBay
#define SAYax SHYax
#define XASay SHXay
#define ASOax SLOax
#define LSEax SREax
#define AXAay SHAay
#define DCMax DCPax
#define INSax ISBax
#define SKBn NOPb
#define SKWn NOPa
#endif // OPCODES_H

View File

@ -0,0 +1,35 @@
/* SidTuneCfg.h (template) */
#ifndef SIDTUNECFG_H
#define SIDTUNECFG_H
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
/* 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(_WIN32) || defined(_MSDOS) || defined(_OS2)
#define SID_FS_IS_COLON_AND_BACKSLASH_AND_SLASH
#elif defined(__APPLE__) && defined(__MACH__)
#define SID_FS_IS_COLON
#elif defined(AMIGA)
#define SID_FS_IS_COLON_AND_SLASH
#else
#define SID_FS_IS_SLASH
#endif
#endif /* SIDTUNECFG_H */

View File

@ -0,0 +1,89 @@
dnl Process this file with autoconf to produce a configure script.
AC_INIT([sidplayfp], [1.4.0alpha], [], [], [http://sourceforge.net/projects/sidplay-residfp/])
AC_CONFIG_SRCDIR([src/main.cpp])
AC_CONFIG_AUX_DIR([build-aux])
AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_HEADERS([config.h])
AM_INIT_AUTOMAKE
AC_CANONICAL_HOST
AC_PROG_RANLIB
dnl Checks for programs.
AC_PROG_CXX
dnl Use C++ for tests.
AC_LANG([C++])
dnl Checks for typedefs, structures, and compiler characteristics.
AC_C_BIGENDIAN
dnl Audio subsystem
AUDIO_LDFLAGS=""
PKG_CHECK_MODULES(ALSA,
[alsa >= 1.0],
[AC_DEFINE([HAVE_ALSA], 1, [Define to 1 if you have libasound (-lasound).])],
[AC_MSG_WARN([$ALSA_PKG_ERRORS])]
)
PKG_CHECK_MODULES(PULSE,
[libpulse-simple >= 1.0],
[AC_DEFINE([HAVE_PULSE], 1, [Define to 1 if you have libpulse-simple (-lpulse-simple).])],
[AC_MSG_WARN([$PULSE_PKG_ERRORS])]
)
dnl Checks what version of Unix we have and soundcard support
AC_CHECK_HEADERS([sys/ioctl.h linux/soundcard.h machine/soundcard.h \
sys/soundcard.h soundcard.h])
AC_CHECK_HEADERS([dsound.h mmsystem.h], [], [], [#include <windows.h>])
AS_IF([test "$ac_cv_header_dsound_h" = "yes"],
[AUDIO_LDFLAGS="$AUDIO_LDFLAGS -ldsound -ldxguid"]
)
AS_IF([test "$ac_cv_header_mmsystem_h" = "yes"],
[AUDIO_LDFLAGS="$AUDIO_LDFLAGS -lwinmm"]
)
# NetBSD/OpenBSD OSS audio emulation
AS_IF([test "x$ac_cv_header_soundcard_h" = "xyes"],
[AUDIO_LDFLAGS="$AUDIO_LDFLAGS -lossaudio"]
)
AC_SUBST(AUDIO_LDFLAGS)
AC_CHECK_FUNCS([strncasecmp strcasecmp])
PKG_CHECK_MODULES(SIDPLAYFP, [libsidplayfp >= 1.0])
PKG_CHECK_MODULES(STILVIEW, [libstilview >= 1.0])
# hack?
saveCPPFLAGS=$CPPFLAGS
CPPFLAGS="$CPPFLAGS $SIDPLAYFP_CFLAGS"
AC_CHECK_HEADERS([sidplayfp/builders/residfp.h sidplayfp/builders/resid.h sidplayfp/builders/hardsid.h])
CPPFLAGS=$saveCPPFLAGS
AC_MSG_CHECKING([for debugging])
AC_ARG_ENABLE(debug, [AS_HELP_STRING([--enable-debug], [compile for debugging @<:@no/yes, default=no@:>@])],
[], [enable_debug=no])
AS_IF([test "x$enable_debug" = "xno"],
[AC_MSG_RESULT([Build without debugging messages]); debug_flags=-DNDEBUG]
)
AC_CONFIG_FILES([
Makefile
])
AC_OUTPUT

View File

@ -0,0 +1,37 @@
0x01, 0x00, 0x6f, 0x36, 0x35, 0x00, 0x00, 0x00,
0x00, 0x10, 0xcf, 0x00, 0x00, 0x04, 0x00, 0x00,
0x00, 0x40, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x1b, 0x10, 0xc5, 0x10, 0xce,
0x10, 0xce, 0x10, 0x8c, 0x10, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x6c, 0x0e, 0x10, 0x6c, 0x0c, 0x10, 0x78, 0xa9,
0x00, 0x8d, 0x1a, 0xd0, 0xad, 0x19, 0xd0, 0x8d,
0x19, 0xd0, 0xa9, 0x7f, 0x8d, 0x0d, 0xdc, 0x8d,
0x0d, 0xdd, 0xad, 0x0d, 0xdc, 0xad, 0x0d, 0xdd,
0xa9, 0x0f, 0x8d, 0x18, 0xd4, 0xad, 0x12, 0x10,
0xf0, 0x07, 0xa2, 0x25, 0xa0, 0x40, 0x4c, 0x4a,
0x10, 0xa2, 0x95, 0xa0, 0x42, 0x8e, 0x04, 0xdc,
0x8c, 0x05, 0xdc, 0xa2, 0x9b, 0xa0, 0x37, 0x4d,
0x13, 0x10, 0x0d, 0x10, 0x10, 0xf0, 0x04, 0xa2,
0x1b, 0xa0, 0x00, 0x8e, 0x11, 0xd0, 0x8c, 0x12,
0xd0, 0xad, 0x10, 0x10, 0xf0, 0x0a, 0xad, 0x11,
0x10, 0xf0, 0x05, 0xa2, 0xb2, 0x8e, 0x14, 0x03,
0xad, 0x0b, 0x10, 0xd0, 0x08, 0xa9, 0x81, 0x8d,
0x1a, 0xd0, 0x4c, 0x8c, 0x10, 0xa9, 0x81, 0xa2,
0x01, 0x8d, 0x0d, 0xdc, 0x8e, 0x0e, 0xdc, 0xad,
0x10, 0x10, 0xd0, 0x02, 0xa9, 0x37, 0x85, 0x01,
0xad, 0x14, 0x10, 0x48, 0xad, 0x0a, 0x10, 0x28,
0x20, 0x18, 0x10, 0xad, 0x10, 0x10, 0xf0, 0x0a,
0xad, 0x11, 0x10, 0xf0, 0x04, 0xa9, 0x37, 0x85,
0x01, 0x58, 0x4c, 0xaf, 0x10, 0xa5, 0x01, 0x48,
0xad, 0x11, 0x10, 0x85, 0x01, 0xa9, 0x00, 0x20,
0x15, 0x10, 0x68, 0x85, 0x01, 0xce, 0x19, 0xd0,
0xad, 0x0d, 0xdc, 0x68, 0xa8, 0x68, 0xaa, 0x68,
0x40, 0x02, 0x00, 0x00, 0x01, 0x82, 0x02, 0x82,
0x02, 0x82, 0x02, 0x82, 0x02, 0x82, 0x0e, 0x82,
0x03, 0x82, 0x22, 0x82, 0x09, 0x82, 0x11, 0x82,
0x03, 0x82, 0x0f, 0x82, 0x05, 0x82, 0x05, 0x22,
0x05, 0x82, 0x0a, 0x82, 0x0d, 0x82, 0x09, 0x82,
0x04, 0x82, 0x04, 0x82, 0x03, 0x82, 0x05, 0x82,
0x0a, 0x82, 0x06, 0x82, 0x07, 0x82, 0x00, 0x00,
0x00, 0x00,

View File

@ -0,0 +1,10 @@
* Refine the MOS 6581 filter model / parameters. Build an accurate MOS
8580 filter model.
* Expose an interface for tunable filter parameters.
* Write documentation. Possibly a paper describing how SID was reverse
engineered.
* Implement a SID tune player. A PSID player, VSID, is partly
implemented in VICE.

View File

@ -0,0 +1,50 @@
/**
@mainpage libsidplayfp
A library to play Commodore 64 music derived from libsidplay2.<br/>
<br/>
Libsidplayfp (and its console frontend sidplayfp) is a fork of sidplay2
born with the aim to improve the quality of emulating the 6581, 8580 chips
and the surrounding C64 system in order to play SID music better.<br/>
Copyright (c) 2000-2001 Simon White<br/>
Copyright (c) 2007-2010 Antti Lankila<br/>
Copyright (c) 2010-2014 Leandro Nini &lt;drfiemost@users.sourceforge.net&gt;<br/>
<br/>
STILView (or more precisely, the STIL class written in C++) is intended to be
compiled with the various SID emulators available on many platforms to provide
the capability of showing STIL and BUG information along with the given SID
that is currently being played in the emulator. It requires HVSC v2.6
(post-update #12) or later to function correctly, but it will work with
earlier versions to a limited extent.
Copyright (C) 1998, 2002 LaLa<br/>
Copyright (C) 2012-2013 Leandro Nini &lt;drfiemost@users.sourceforge.net&gt;<br/>
<br/>
Home page:<br/>
http://sourceforge.net/projects/sidplay-residfp/
-----------------------------------------------------------------------------
This program is free software; you can redistribute it and/or modify<br/>
it under the terms of the GNU General Public License as published by<br/>
the Free Software Foundation; either version 2 of the License, or<br/>
(at your option) any later version.
This program is distributed in the hope that it will be useful,<br/>
but WITHOUT ANY WARRANTY; without even the implied warranty of<br/>
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the<br/>
GNU General Public License for more details.
You should have received a copy of the GNU General Public License<br/>
along with this program; if not, write to the Free Software<br/>
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-----------------------------------------------------------------------------
\example demo.cpp
*/

View File

@ -0,0 +1,35 @@
AUTOMAKE_OPTIONS = foreign subdir-objects
if ENABLE_TEST
AM_CPPFLAGS = \
-I $(top_builddir)/src/builders/residfp-builder/residfp
TESTS = \
TestEnvelopeGenerator \
TestSpline \
TestDac
check_PROGRAMS = $(TESTS)
TestEnvelopeGenerator_SOURCES = \
Main.cpp \
TestEnvelopeGenerator.cpp
TestEnvelopeGenerator_LDADD = -lUnitTest++ \
$(top_builddir)/src/builders/residfp-builder/residfp/EnvelopeGenerator.o \
$(top_builddir)/src/builders/residfp-builder/residfp/Dac.o
TestSpline_SOURCES = \
Main.cpp \
TestSpline.cpp
TestSpline_LDADD = -lUnitTest++\
$(top_builddir)/src/builders/residfp-builder/residfp/Spline.o
TestDac_SOURCES = \
Main.cpp \
TestDac.cpp
TestDac_LDADD = -lUnitTest++\
$(top_builddir)/src/builders/residfp-builder/residfp/Dac.o
endif

View File

@ -0,0 +1,109 @@
// ---------------------------------------------------------------------------
// This file is part of reSID, a MOS6581 SID emulator engine.
// Copyright (C) 2010 Dag Lem <resid@nimrod.no>
//
// 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 RESID_VOICE_H
#define RESID_VOICE_H
#include "resid-config.h"
#include "wave.h"
#include "envelope.h"
namespace reSID
{
class Voice
{
public:
Voice();
void set_chip_model(chip_model model);
void set_sync_source(Voice*);
void reset();
void writeCONTROL_REG(reg8);
// Amplitude modulated waveform output.
// Range [-2048*255, 2047*255].
int output();
WaveformGenerator wave;
EnvelopeGenerator envelope;
protected:
// Waveform D/A zero level.
short wave_zero;
friend class SID;
};
// ----------------------------------------------------------------------------
// Inline functions.
// The following function is defined inline because it is called every
// time a sample is calculated.
// ----------------------------------------------------------------------------
#if RESID_INLINING || defined(RESID_VOICE_CC)
// ----------------------------------------------------------------------------
// Amplitude modulated waveform output (20 bits).
// Ideal range [-2048*255, 2047*255].
// ----------------------------------------------------------------------------
// The output for a voice is produced by a multiplying DAC, where the
// waveform output modulates the envelope output.
//
// As noted by Bob Yannes: "The 8-bit output of the Envelope Generator was then
// sent to the Multiplying D/A converter to modulate the amplitude of the
// selected Oscillator Waveform (to be technically accurate, actually the
// waveform was modulating the output of the Envelope Generator, but the result
// is the same)".
//
// 7 6 5 4 3 2 1 0 VGND
// | | | | | | | | | Missing
// 2R 2R 2R 2R 2R 2R 2R 2R 2R termination
// | | | | | | | | |
// --R---R---R---R---R---R---R-- ---
// | _____
// __|__ __|__ |
// ----- ===== |
// | | | | |
// 12V --- ----- ------- GND
// |
// vout
//
// Bit on: wout (see figure in wave.h)
// Bit off: 5V (VGND)
//
// As is the case with all MOS 6581 DACs, the termination to (virtual) ground
// at bit 0 is missing. The MOS 8580 has correct termination.
//
RESID_INLINE
int Voice::output()
{
// Multiply oscillator output with envelope output.
return (wave.output() - wave_zero)*envelope.output();
}
#endif // RESID_INLINING || defined(RESID_VOICE_CC)
} // namespace reSID
#endif // not RESID_VOICE_H

View File

@ -0,0 +1,22 @@
## Process this file with automake to create Makefile.in
AR = @AR@
noinst_LIBRARIES = libresid.a
libresid_a_SOURCES = sid.cc voice.cc wave.cc envelope.cc filter.cc dac.cc extfilt.cc pot.cc version.cc
BUILT_SOURCES = $(noinst_DATA:.dat=.h)
noinst_HEADERS = sid.h voice.h wave.h envelope.h filter.h dac.h extfilt.h pot.h spline.h resid-config.h $(noinst_DATA:.dat=.h)
noinst_DATA = wave6581_PST.dat wave6581_PS_.dat wave6581_P_T.dat wave6581__ST.dat wave8580_PST.dat wave8580_PS_.dat wave8580_P_T.dat wave8580__ST.dat
noinst_SCRIPTS = samp2src.pl
EXTRA_DIST = $(noinst_HEADERS) $(noinst_DATA) $(noinst_SCRIPTS) README.VICE
SUFFIXES = .dat
.dat.h:
$(PERL) $(srcdir)/samp2src.pl $* $< $(srcdir)/$@

View File

@ -0,0 +1,131 @@
/*
* This file is part of libsidplayfp, a SID player engine.
*
* Copyright 2011-2014 Leandro Nini <drfiemost@users.sourceforge.net>
* Copyright 2007-2010 Antti Lankila
* Copyright 2001 Simon White
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef C64CIA_H
#define C64CIA_H
// The CIA emulations are very generic and here we need to effectively
// wire them into the computer (like adding a chip to a PCB).
#include "Banks/Bank.h"
#include "c64/c64env.h"
#include "sidendian.h"
#include "CIA/mos6526.h"
#include "sidcxx11.h"
namespace libsidplayfp
{
/**
* CIA 1
*
* Generates IRQs
*
* Located at $DC00-$DCFF
*/
class c64cia1: public MOS6526, public Bank
{
private:
c64env &m_env;
uint_least16_t last_ta;
protected:
void interrupt(bool state) override
{
m_env.interruptIRQ(state);
}
void portB() override
{
m_env.lightpen((prb | ~ddrb) & 0x10);
}
public:
c64cia1(c64env *env) :
MOS6526(&(env->context())),
m_env(*env) {}
void poke(uint_least16_t address, uint8_t value) override
{
write(endian_16lo8(address), value);
// Save the value written to Timer A
if (address == 0xDC04 || address == 0xDC05)
{
if (timerA.getTimer() != 0)
last_ta = timerA.getTimer();
}
}
uint8_t peek(uint_least16_t address) override
{
return read(endian_16lo8(address));
}
void reset() override
{
last_ta = 0;
MOS6526::reset();
}
uint_least16_t getTimerA() const { return last_ta; }
};
/**
* CIA 2
*
* Generates NMIs
*
* Located at $DD00-$DDFF
*/
class c64cia2: public MOS6526, public Bank
{
private:
c64env &m_env;
protected:
void interrupt(bool state) override
{
if (state)
m_env.interruptNMI();
}
public:
c64cia2(c64env *env) :
MOS6526(&(env->context())),
m_env(*env) {}
void poke(uint_least16_t address, uint8_t value) override
{
write(address, value);
}
uint8_t peek(uint_least16_t address) override
{
return read(address);
}
};
}
#endif // C64CIA_H

View File

@ -0,0 +1,107 @@
/*
* This file is part of libsidplayfp, a SID player engine.
*
* Copyright 2011-2014 Leandro Nini <drfiemost@users.sourceforge.net>
* Copyright 2007-2010 Antti Lankila
* Copyright 2004,2010 Dag Lem
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef OPAMP_H
#define OPAMP_H
#include <memory>
#include "Spline.h"
namespace reSIDfp
{
/**
* Find output voltage in inverting gain and inverting summer SID op-amp
* circuits, using a combination of Newton-Raphson and bisection.
*
* ---R2--
* | |
* vi ---R1-----[A>----- vo
* vx
*
* From Kirchoff's current law it follows that
*
* IR1f + IR2r = 0
*
* Substituting the triode mode transistor model K*W/L*(Vgst^2 - Vgdt^2)
* for the currents, we get:
*
* n*((Vddt - vx)^2 - (Vddt - vi)^2) + (Vddt - vx)^2 - (Vddt - vo)^2 = 0
*
* Our root function f can thus be written as:
*
* f = (n + 1)*(Vddt - vx)^2 - n*(Vddt - vi)^2 - (Vddt - vo)^2 = 0
*
* Using substitution constants
*
* a = n + 1
* b = Vddt
* c = n*(Vddt - vi)^2
*
* the equations for the root function and its derivative can be written as:
*
* f = a*(b - vx)^2 - c - (b - vo)^2
* df = 2*((b - vo)*dvo - a*(b - vx))
*/
class OpAmp
{
private:
/// Current root position (cached as guess to speed up next iteration)
double x;
const double kVddt, vmin, vmax;
std::auto_ptr<Spline> const opamp;
public:
/**
* Opamp input -> output voltage conversion
*
* @param opamp opamp mapping table as pairs of points (in -> out)
* @param opamplength length of the opamp array
* @param kVddt transistor dt parameter (in volts)
*/
OpAmp(const Spline::Point opamp[], int opamplength, double kVddt) :
x(0.),
kVddt(kVddt),
vmin(opamp[0].x),
vmax(opamp[opamplength - 1].x),
opamp(new Spline(opamp, opamplength)) {}
void reset()
{
x = vmin;
}
/**
* Solve the opamp equation for input vi in loading context n
*
* @param n the ratio of input/output loading
* @param vi input
* @return vo
*/
double solve(double n, double vi);
};
} // namespace reSIDfp
#endif

View File

@ -0,0 +1,71 @@
/*
* This file is part of libsidplayfp, a SID player engine.
*
* Copyright 2011-2013 Leandro Nini <drfiemost@users.sourceforge.net>
* Copyright 2007-2010 Antti Lankila
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef RESAMPLER_H
#define RESAMPLER_H
namespace reSIDfp
{
/**
* Abstraction of a resampling process. Given enough input, produces output.
* Constructors take additional arguments that configure these objects.
*/
class Resampler
{
protected:
virtual int output() const = 0;
Resampler() {}
public:
virtual ~Resampler() {}
/**
* Input a sample into resampler. Output "true" when resampler is ready with new sample.
*
* @param sample input sample
* @return true when a sample is ready
*/
virtual bool input(int sample) = 0;
/**
* Output a sample from resampler.
*
* @return resampled sample
*/
short getOutput() const
{
int value = output();
// Clip signed integer value into the -32768,32767 range.
if (value < -32768) value = -32768;
if (value > 32767) value = 32767;
return value;
}
virtual void reset() = 0;
};
} // namespace reSIDfp
#endif

View File

@ -0,0 +1,83 @@
// ---------------------------------------------------------------------------
// This file is part of reSID, a MOS6581 SID emulator engine.
// Copyright (C) 2010 Dag Lem <resid@nimrod.no>
//
// 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 RESID_SIDDEFS_H
#define RESID_SIDDEFS_H
// Compilation configuration.
#define RESID_INLINING @RESID_INLINING@
#define RESID_INLINE @RESID_INLINE@
#define RESID_BRANCH_HINTS @RESID_BRANCH_HINTS@
// Compiler specifics.
#define HAVE_BOOL @RESID_HAVE_BOOL@
#define HAVE_BUILTIN_EXPECT @HAVE_BUILTIN_EXPECT@
// Define bool, true, and false for C++ compilers that lack these keywords.
#if !HAVE_BOOL
typedef int bool;
const bool true = 1;
const bool false = 0;
#endif
// Branch prediction macros, lifted off the Linux kernel.
#if RESID_BRANCH_HINTS && HAVE_BUILTIN_EXPECT
#define likely(x) __builtin_expect(!!(x), 1)
#define unlikely(x) __builtin_expect(!!(x), 0)
#else
#define likely(x) (x)
#define unlikely(x) (x)
#endif
namespace reSID {
// We could have used the smallest possible data type for each SID register,
// however this would give a slower engine because of data type conversions.
// An int is assumed to be at least 32 bits (necessary in the types reg24
// and cycle_count). GNU does not support 16-bit machines
// (GNU Coding Standards: Portability between CPUs), so this should be
// a valid assumption.
typedef unsigned int reg4;
typedef unsigned int reg8;
typedef unsigned int reg12;
typedef unsigned int reg16;
typedef unsigned int reg24;
typedef int cycle_count;
typedef short short_point[2];
typedef double double_point[2];
enum chip_model { MOS6581, MOS8580 };
enum sampling_method { SAMPLE_FAST, SAMPLE_INTERPOLATE,
SAMPLE_RESAMPLE, SAMPLE_RESAMPLE_FASTMEM };
} // namespace reSID
extern "C"
{
#ifndef RESID_VERSION_CC
extern const char* resid_version_string;
#else
const char* resid_version_string = "1.0-pre2";
#endif
}
#endif // not RESID_SIDDEFS_H

View File

@ -0,0 +1,9 @@
[Filter]
DistortionAttenuation=0.50
DistortionNonlinearity=3.3e6
VoiceNonlinearity =1.80
Type3BaseResistance =1.1e6
Type3Offset =8e6
Type3Steepness =1.0052
Type3MinimumFETResistance=1.7e4

View File

@ -0,0 +1,59 @@
/*
* This file is part of libsidplayfp, a SID player engine.
*
* Copyright 2014 Leandro Nini <drfiemost@users.sourceforge.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef MD5_FACTORY_H
#define MD5_FACTORY_H
#include "iMd5.h"
#include "sidcxx11.h"
#include <memory>
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#ifdef HAVE_LIBGCRYPT
# include "md5Gcrypt.h"
#else
# include "md5Internal.h"
#endif
namespace libsidplayfp
{
namespace md5Factory
{
static std::unique_ptr<iMd5> get()
{
return std::unique_ptr<iMd5>(
#ifdef HAVE_LIBGCRYPT
new md5Gcrypt()
#else
new md5Internal()
#endif
);
}
}
}
#endif // MD5_FACTORY_H

View File

@ -0,0 +1,51 @@
/*
* This file is part of sidplayfp, a console SID player.
*
* Copyright 2014 Leandro Nini
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef TYPES_H
#define TYPES_H
#include "sidfstream.h"
# define SID_WIFSTREAM sid_wifstream
# define SID_WOFSTREAM sid_wofstream
# define SID_IFSTREAM sid_ifstream
# define SID_OFSTREAM sid_ofstream
#if defined(_WIN32) && defined(UNICODE)
# define SID_STRING std::wstring
# define SID_STRINGTREAM std::wstringstream
# define SID_COUT std::wcout
#else
# define SID_STRING std::string
# define SID_STRINGTREAM std::stringstream
# define SID_COUT std::cout
#endif
#ifndef _WIN32
# define TCHAR char
# define TEXT(x) x
# define SEPARATOR "/"
#else
# include <windows.h>
# define SEPARATOR TEXT("\\")
#endif
#endif

View File

@ -0,0 +1,36 @@
// ---------------------------------------------------------------------------
// This file is part of reSID, a MOS6581 SID emulator engine.
// Copyright (C) 2010 Dag Lem <resid@nimrod.no>
//
// 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 RESID_POT_H
#define RESID_POT_H
#include "resid-config.h"
namespace reSID
{
class Potentiometer
{
public:
reg8 readPOT();
};
} // namespace reSID
#endif

View File

@ -0,0 +1,78 @@
/*
* This file is part of libsidplayfp, a SID player engine.
*
* Copyright 2011-2014 Leandro Nini <drfiemost@users.sourceforge.net>
* Copyright 2007-2010 Antti Lankila
* Copyright 2001 Simon White
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef RESIDFP_EMU_H
#define RESIDFP_EMU_H
#include <stdint.h>
#include "residfp/SID.h"
#include "sidplayfp/SidConfig.h"
#include "sidemu.h"
#include "sidplayfp/event.h"
#include "sidcxx11.h"
class sidbuilder;
#define RESID_NAMESPACE reSIDfp
class ReSIDfp: public sidemu
{
private:
RESID_NAMESPACE::SID &m_sid;
public:
static const char* getCredits();
public:
ReSIDfp(sidbuilder *builder);
~ReSIDfp();
bool getStatus() const { return m_status; }
// Standard component functions
void reset() override { sidemu::reset(); }
uint8_t read(uint_least8_t addr) override;
void write(uint_least8_t addr, uint8_t data) override;
// c64sid functions
void reset(uint8_t volume) override;
// Standard SID emu functions
void clock() override;
void sampling(float systemclock, float freq,
SidConfig::sampling_method_t method, bool) override;
void voice(unsigned int num, bool mute) override { m_sid.mute(num, mute); }
void model(SidConfig::sid_model_t model) override;
// Specific to resid
void filter(bool enable);
void filter6581Curve(double filterCurve);
void filter8580Curve(double filterCurve);
};
#endif // RESIDFP_EMU_H

View File

@ -0,0 +1,84 @@
/*
* This file is part of libsidplayfp, a SID player engine.
*
* Copyright 2011-2013 Leandro Nini <drfiemost@users.sourceforge.net>
* Copyright 2007-2010 Antti Lankila
* Copyright 2000 Simon White
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "mmu.h"
namespace libsidplayfp
{
class Bank;
MMU::MMU(EventContext *context, Bank* ioBank) :
context(*context),
loram(false),
hiram(false),
charen(false),
ioBank(ioBank),
zeroRAMBank(this, &ramBank)
{
cpuReadMap[0] = &zeroRAMBank;
cpuWriteMap[0] = &zeroRAMBank;
for (int i = 1; i < 16; i++)
{
cpuReadMap[i] = &ramBank;
cpuWriteMap[i] = &ramBank;
}
}
void MMU::setCpuPort(int state)
{
loram = (state & 1) != 0;
hiram = (state & 2) != 0;
charen = (state & 4) != 0;
updateMappingPHI2();
}
void MMU::updateMappingPHI2()
{
cpuReadMap[0xe] = cpuReadMap[0xf] = hiram ? (Bank*)&kernalRomBank : &ramBank;
cpuReadMap[0xa] = cpuReadMap[0xb] = (loram && hiram) ? (Bank*)&basicRomBank : &ramBank;
if (charen && (loram || hiram))
{
cpuReadMap[0xd] = cpuWriteMap[0xd] = ioBank;
}
else
{
cpuReadMap[0xd] = (!charen && (loram || hiram)) ? (Bank*)&characterRomBank : &ramBank;
cpuWriteMap[0xd] = &ramBank;
}
}
void MMU::reset()
{
ramBank.reset();
zeroRAMBank.reset();
// Reset the ROMs to undo the hacks applied
kernalRomBank.reset();
basicRomBank.reset();
updateMappingPHI2();
}
}

View File

@ -0,0 +1,257 @@
# MOS 8580R5 1489 25 HONG KONG HH112217 HC-30
0 0
8 0
16 0
24 140
32 190
40 235
48 284
56 335
64 395
72 442
80 478
88 526
96 578
104 626
112 665
120 710
128 759
136 815
144 852
152 917
160 963
168 1003
176 1051
184 1080
192 1143
200 1200
208 1260
216 1297
224 1343
232 1354
240 1419
248 1494
256 1583
264 1592
272 1651
280 1666
288 1736
296 1786
304 1841
312 1892
320 1921
328 1993
336 2016
344 2048
352 2099
360 2140
368 2214
376 2248
384 2321
392 2356
400 2382
408 2471
416 2497
424 2520
432 2556
440 2636
448 2696
456 2711
464 2776
472 2824
480 2891
488 2899
496 2952
504 2969
512 3039
520 3115
528 3169
536 3188
544 3242
552 3307
560 3330
568 3394
576 3440
584 3470
592 3483
600 3543
608 3571
616 3658
624 3697
632 3730
640 3763
648 3850
656 3833
664 3960
672 3983
680 3987
688 4065
696 4091
704 4162
712 4144
720 4207
728 4257
736 4347
744 4320
752 4377
760 4429
768 4490
776 4556
784 4558
792 4711
800 4683
808 4722
816 4768
824 4851
832 4884
840 4987
848 5037
856 5079
864 5114
872 5173
880 5166
888 5228
896 5359
904 5352
912 5332
920 5418
928 5415
936 5514
944 5487
952 5557
960 5668
968 5618
976 5658
984 5738
992 5759
1000 5850
1008 5828
1016 5859
1024 5905
1032 6027
1040 5994
1048 5983
1056 6172
1064 6122
1072 6153
1080 6220
1088 6270
1096 6334
1104 6369
1112 6441
1120 6431
1128 6566
1136 6569
1144 6612
1152 6664
1160 6723
1168 6800
1176 6775
1184 6829
1192 6893
1200 6934
1208 6918
1216 6962
1224 7123
1232 7079
1240 7144
1248 7185
1256 7315
1264 7304
1272 7344
1280 7402
1288 7409
1296 7431
1304 7512
1312 7562
1320 7562
1328 7662
1336 7657
1344 7719
1352 7779
1360 7773
1368 7829
1376 7857
1384 7933
1392 7983
1400 7977
1408 8025
1416 8079
1424 8142
1432 8210
1440 8175
1448 8258
1456 8284
1464 8405
1472 8382
1480 8402
1488 8406
1496 8496
1504 8537
1512 8589
1520 8580
1528 8630
1536 8713
1544 8728
1552 8810
1560 8765
1568 8806
1576 8920
1584 8922
1592 8959
1600 9017
1608 9106
1616 9092
1624 9187
1632 9199
1640 9230
1648 9199
1656 9280
1664 9389
1672 9329
1680 9423
1688 9466
1696 9486
1704 9588
1712 9578
1720 9605
1728 9683
1736 9696
1744 9766
1752 9860
1760 9883
1768 9994
1776 9958
1784 10074
1792 10075
1800 10068
1808 10283
1816 10286
1824 10287
1832 10384
1840 10348
1848 10541
1856 10484
1864 10582
1872 10475
1880 10521
1888 10609
1896 10667
1904 10685
1912 10699
1920 10769
1928 10806
1936 10859
1944 10842
1952 10912
1960 10956
1968 11060
1976 11065
1984 11120
1992 11083
2000 11191
2008 11187
2016 11182
2024 11251
2032 11285
2040 11325

View File

@ -0,0 +1,9 @@
[Filter]
DistortionAttenuation=0.50
DistortionNonlinearity=3.3e6
VoiceNonlinearity =1.80
Type3BaseResistance=1522171.922983084
Type3Offset=21729926.667291082
Type3Steepness=1.004994802537475
Type3MinimumFETResistance=14299.149638099827

View File

@ -0,0 +1,400 @@
/*
* This file is part of libsidplayfp, a SID player engine.
*
* Copyright 2012-2014 Leandro Nini <drfiemost@users.sourceforge.net>
* Copyright 2007-2010 Antti Lankila
* Copyright 2000-2001 Simon White
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "PSID.h"
#include <cstring>
#include <string>
#include <memory>
#include "sidplayfp/SidTuneInfo.h"
#include "sidendian.h"
#include "sidmd5.h"
#include "sidcxx11.h"
namespace libsidplayfp
{
#define PSID_MAXSTRLEN 32
// Header has been extended for 'RSID' format
// The following changes are present:
// id = 'RSID'
// version = 2 and 3 only
// play, load and speed reserved 0
// psidspecific flag is called C64BASIC flag
// init cannot be under ROMS/IO memory area
// load address cannot be less than $07E8
// info strings may be 32 characters long without trailing zero
struct psidHeader // all values are big-endian
{
uint32_t id; // 'PSID' or 'RSID' (ASCII)
uint16_t version; // 1, 2 or 3 only
uint16_t data; // 16-bit offset to binary data in file
uint16_t load; // 16-bit C64 address to load file to
uint16_t init; // 16-bit C64 address of init subroutine
uint16_t play; // 16-bit C64 address of play subroutine
uint16_t songs; // number of songs
uint16_t start; // start song out of [1..256]
uint32_t speed; // 32-bit speed info
// bit: 0=50 Hz, 1=CIA 1 Timer A (default: 60 Hz)
char name[PSID_MAXSTRLEN]; // ASCII strings, 31 characters long and
char author[PSID_MAXSTRLEN]; // terminated by a trailing zero
char released[PSID_MAXSTRLEN]; //
uint16_t flags; // only version >= 2
uint8_t relocStartPage; // only version >= 2ng
uint8_t relocPages; // only version >= 2ng
uint8_t sidChipBase2; // only version >= 3
uint8_t reserved; // only version >= 2
};
enum
{
PSID_MUS = 1 << 0,
PSID_SPECIFIC = 1 << 1, // These two are mutally exclusive
PSID_BASIC = 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_SIDMODEL1_UNKNOWN = 0,
PSID_SIDMODEL1_6581 = 1 << 4,
PSID_SIDMODEL1_8580 = 1 << 5,
PSID_SIDMODEL1_ANY = PSID_SIDMODEL1_6581 | PSID_SIDMODEL1_8580
};
enum
{
PSID_SIDMODEL2_UNKNOWN = 0,
PSID_SIDMODEL2_6581 = 1 << 6,
PSID_SIDMODEL2_8580 = 1 << 7,
PSID_SIDMODEL2_ANY = PSID_SIDMODEL2_6581 | PSID_SIDMODEL2_8580
};
// Format strings
const char TXT_FORMAT_PSID[] = "PlaySID one-file format (PSID)";
const char TXT_FORMAT_RSID[] = "Real C64 one-file format (RSID)";
const char TXT_UNKNOWN_PSID[] = "Unsupported PSID version";
const char TXT_UNKNOWN_RSID[] = "Unsupported RSID version";
const int psid_headerSize = 118;
const int psidv2_headerSize = psid_headerSize + 6;
// Magic fields
const uint32_t PSID_ID = 0x50534944;
const uint32_t RSID_ID = 0x52534944;
SidTuneBase* PSID::load(buffer_t& dataBuf)
{
// File format check
if (dataBuf.size() < 4
|| ((endian_big32(&dataBuf[0]) != PSID_ID)
&& (endian_big32(&dataBuf[0]) != RSID_ID)))
{
return nullptr;
}
psidHeader pHeader;
readHeader(dataBuf, pHeader);
std::unique_ptr<PSID> tune(new PSID());
tune->tryLoad(pHeader);
return tune.release();
}
void PSID::readHeader(const buffer_t &dataBuf, psidHeader &hdr)
{
// 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 (dataBuf.size() < (psid_headerSize + 2))
{
throw loadError(ERR_TRUNCATED);
}
// Read v1 fields
hdr.id = endian_big32(&dataBuf[0]);
hdr.version = endian_big16(&dataBuf[4]);
hdr.data = endian_big16(&dataBuf[6]);
hdr.load = endian_big16(&dataBuf[8]);
hdr.init = endian_big16(&dataBuf[10]);
hdr.play = endian_big16(&dataBuf[12]);
hdr.songs = endian_big16(&dataBuf[14]);
hdr.start = endian_big16(&dataBuf[16]);
hdr.speed = endian_big32(&dataBuf[18]);
memcpy(hdr.name, &dataBuf[22], PSID_MAXSTRLEN);
memcpy(hdr.author, &dataBuf[54], PSID_MAXSTRLEN);
memcpy(hdr.released, &dataBuf[86], PSID_MAXSTRLEN);
if (hdr.version >= 2)
{
if (dataBuf.size() < (psidv2_headerSize + 2))
{
throw loadError(ERR_TRUNCATED);
}
// Read v2/3 fields
hdr.flags = endian_big16(&dataBuf[118]);
hdr.relocStartPage = dataBuf[120];
hdr.relocPages = dataBuf[121];
hdr.sidChipBase2 = dataBuf[122];
hdr.reserved = dataBuf[123];
}
}
void PSID::tryLoad(const psidHeader &pHeader)
{
SidTuneInfo::compatibility_t compatibility = SidTuneInfo::COMPATIBILITY_C64;
// Require a valid ID and version number.
if (pHeader.id == PSID_ID)
{
switch (pHeader.version)
{
case 1:
compatibility = SidTuneInfo::COMPATIBILITY_PSID;
break;
case 2:
case 3:
break;
default:
throw loadError(TXT_UNKNOWN_PSID);
}
info->m_formatString = TXT_FORMAT_PSID;
}
else if (pHeader.id == RSID_ID)
{
switch (pHeader.version)
{
case 2:
case 3:
break;
default:
throw loadError(TXT_UNKNOWN_RSID);
}
info->m_formatString = TXT_FORMAT_RSID;
compatibility = SidTuneInfo::COMPATIBILITY_R64;
}
fileOffset = pHeader.data;
info->m_loadAddr = pHeader.load;
info->m_initAddr = pHeader.init;
info->m_playAddr = pHeader.play;
info->m_songs = pHeader.songs;
info->m_startSong = pHeader.start;
info->m_sidChipBase1 = 0xd400;
info->m_sidChipBase2 = 0;
info->m_compatibility = compatibility;
info->m_sidModel1 = SidTuneInfo::SIDMODEL_UNKNOWN;
info->m_sidModel2 = SidTuneInfo::SIDMODEL_UNKNOWN;
info->m_relocPages = 0;
info->m_relocStartPage = 0;
uint_least32_t speed = pHeader.speed;
SidTuneInfo::clock_t clock = SidTuneInfo::CLOCK_UNKNOWN;
if (info->m_songs > MAX_SONGS)
{
info->m_songs = MAX_SONGS;
}
bool musPlayer = false;
if (pHeader.version >= 2)
{
const uint_least16_t flags = pHeader.flags;
if (flags & PSID_MUS)
{ // MUS tunes run at any speed
clock = SidTuneInfo::CLOCK_ANY;
musPlayer = true;
}
// This flags is only available for the appropriate
// file formats
switch (compatibility)
{
case SidTuneInfo::COMPATIBILITY_C64:
if (flags & PSID_SPECIFIC)
info->m_compatibility = SidTuneInfo::COMPATIBILITY_PSID;
break;
case SidTuneInfo::COMPATIBILITY_R64:
if (flags & PSID_BASIC)
info->m_compatibility = SidTuneInfo::COMPATIBILITY_BASIC;
break;
default:
break;
}
if ((flags & PSID_CLOCK_ANY) == PSID_CLOCK_ANY)
clock = SidTuneInfo::CLOCK_ANY;
else if (flags & PSID_CLOCK_PAL)
clock = SidTuneInfo::CLOCK_PAL;
else if (flags & PSID_CLOCK_NTSC)
clock = SidTuneInfo::CLOCK_NTSC;
info->m_clockSpeed = clock;
if ((flags & PSID_SIDMODEL1_ANY) == PSID_SIDMODEL1_ANY)
info->m_sidModel1 = SidTuneInfo::SIDMODEL_ANY;
else if (flags & PSID_SIDMODEL1_6581)
info->m_sidModel1 = SidTuneInfo::SIDMODEL_6581;
else if (flags & PSID_SIDMODEL1_8580)
info->m_sidModel1 = SidTuneInfo::SIDMODEL_8580;
info->m_relocStartPage = pHeader.relocStartPage;
info->m_relocPages = pHeader.relocPages;
if (pHeader.version >= 3)
{
// Only even values are valid. Ranges $00-$41 ($D000-$D410) and
// $80-$DF ($D800-$DDF0) are invalid. Any invalid value means that no second SID
// is used, like $00.
if (pHeader.sidChipBase2 & 1
|| (pHeader.sidChipBase2 >= 0x00 && pHeader.sidChipBase2 <= 0x41)
|| (pHeader.sidChipBase2 >= 0x80 && pHeader.sidChipBase2 <= 0xdf))
{
info->m_sidChipBase2 = 0;
}
else
{
info->m_sidChipBase2 = 0xd000 | (pHeader.sidChipBase2 << 4);
if ((flags & PSID_SIDMODEL2_ANY) == PSID_SIDMODEL2_ANY)
info->m_sidModel2 = SidTuneInfo::SIDMODEL_ANY;
else if (flags & PSID_SIDMODEL2_6581)
info->m_sidModel2 = SidTuneInfo::SIDMODEL_6581;
else if (flags & PSID_SIDMODEL2_8580)
info->m_sidModel2 = SidTuneInfo::SIDMODEL_8580;
}
}
}
// Check reserved fields to force real c64 compliance
// as required by the RSID specification
if (compatibility == SidTuneInfo::COMPATIBILITY_R64)
{
if ((info->m_loadAddr != 0)
|| (info->m_playAddr != 0)
|| (speed != 0))
{
throw loadError(ERR_INVALID);
}
// Real C64 tunes appear as CIA
speed = ~0;
}
// Create the speed/clock setting table.
convertOldStyleSpeedToTables(speed, clock);
// Copy info strings.
info->m_infoString.push_back(std::string(pHeader.name, PSID_MAXSTRLEN));
info->m_infoString.push_back(std::string(pHeader.author, PSID_MAXSTRLEN));
info->m_infoString.push_back(std::string(pHeader.released, PSID_MAXSTRLEN));
if (musPlayer)
throw loadError("Compute!'s Sidplayer MUS data is not supported yet"); // TODO
}
const char *PSID::createMD5(char *md5)
{
if (md5 == nullptr)
md5 = m_md5;
*md5 = '\0';
try
{
// Include C64 data.
sidmd5 myMD5;
uint8_t tmp[2];
myMD5.append(&cache[fileOffset], info->m_c64dataLen);
// Include INIT and PLAY address.
endian_little16(tmp,info->m_initAddr);
myMD5.append(tmp,sizeof(tmp));
endian_little16(tmp,info->m_playAddr);
myMD5.append(tmp,sizeof(tmp));
// Include number of songs.
endian_little16(tmp,info->m_songs);
myMD5.append(tmp,sizeof(tmp));
{ // Include song speed for each song.
const unsigned int currentSong = info->m_currentSong;
for (unsigned int s = 1; s <= info->m_songs; s++)
{
selectSong (s);
const uint_least8_t songSpeed = (uint_least8_t)info->m_songSpeed;
myMD5.append (&songSpeed,sizeof(songSpeed));
}
// Restore old song
selectSong (currentSong);
}
// Deal with PSID v2NG clock speed flags: Let only NTSC
// clock speed change the MD5 fingerprint. That way the
// fingerprint of a PAL-speed sidtune in PSID v1, v2, and
// PSID v2NG format is the same.
if (info->m_clockSpeed == SidTuneInfo::CLOCK_NTSC)
{
const uint_least8_t ntsc_val = 2;
myMD5.append (&ntsc_val,sizeof(ntsc_val));
}
// NB! If the fingerprint is used as an index into a
// song-lengths database or cache, modify above code to
// allow for PSID v2NG files which have clock speed set to
// SIDTUNE_CLOCK_ANY. If the SID player program fully
// supports the SIDTUNE_CLOCK_ANY setting, a sidtune could
// either create two different fingerprints depending on
// the clock speed chosen by the player, or there could be
// two different values stored in the database/cache.
myMD5.finish();
// Get fingerprint.
myMD5.getDigest().copy(md5, SidTune::MD5_LENGTH);
md5[SidTune::MD5_LENGTH] ='\0';
}
catch (md5Error const &) {}
return md5;
}
}

View File

@ -0,0 +1,153 @@
/*
* This file is part of libsidplayfp, a SID player engine.
*
* Copyright 2011-2013 Leandro Nini <drfiemost@users.sourceforge.net>
* Copyright 2007-2010 Antti Lankila
* Copyright 2000-2001 Simon White
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef SIDBUILDER_H
#define SIDBUILDER_H
#include <set>
#include <string>
#include "sidplayfp/SidConfig.h"
class sidemu;
class EventContext;
/**
* Base class for sid builders.
*/
class sidbuilder
{
protected:
typedef std::set<sidemu*> emuset_t;
private:
const char * const m_name;
protected:
std::string m_errorBuffer;
emuset_t sidobjs;
bool m_status;
protected:
/**
* Utility class for setting emu parameters in builders.
*/
template<class Temu, typename Tparam>
class applyParameter
{
protected:
Tparam m_param;
void (Temu::*m_method)(Tparam);
public:
applyParameter(void (Temu::*method)(Tparam), Tparam param) :
m_param(param),
m_method(method) {}
void operator() (sidemu *e) { (static_cast<Temu*>(e)->*m_method)(m_param); }
};
public:
sidbuilder(const char * const name) :
m_name(name),
m_errorBuffer("N/A"),
m_status(true) {}
virtual ~sidbuilder() {}
/**
* The number of used devices.
*
* @return number of used sids, 0 if none.
*/
unsigned int usedDevices() const { return sidobjs.size(); }
/**
* Available devices.
*
* @return the number of available sids, 0 = endless.
*/
virtual unsigned int availDevices() const = 0;
/**
* Create the sid emu.
*
* @param sids the number of required sid emu
*/
virtual unsigned int create(unsigned int sids) = 0;
/**
* Find a free SID of the required specs
*
* @param env the event context
* @param model the required sid model
* @return pointer to the locked sid emu
*/
sidemu *lock(EventContext *env, SidConfig::sid_model_t model);
/**
* Release this SID.
*
* @param device the sid emu to unlock
*/
void unlock(sidemu *device);
/** Remove all SID emulations. */
void remove();
/**
* Get the builder's name.
*
* @return the name
*/
const char *name() const { return m_name; }
/**
* Error message.
*
* @return string error message.
*/
const char *error() const { return m_errorBuffer.c_str(); }
/**
* Determine current state of object.
*
* @return true = okay, false = error
*/
bool getStatus() const { return m_status; }
/**
* Get the builder's credits.
*
* @return credits
*/
virtual const char *credits() const = 0;
/**
* Toggle sid filter emulation.
*
* @param enable true = enable, false = disable
*/
virtual void filter(bool enable) = 0;
};
#endif // SIDBUILDER_H

View File

@ -0,0 +1,9 @@
[Filter]
DistortionAttenuation=0.50
DistortionNonlinearity=3.3e6
VoiceNonlinearity =1.80
Type3BaseResistance =1.3e6
Type3Offset =3.7e8
Type3Steepness =1.0066
Type3MinimumFETResistance=1.8e4

View File

@ -0,0 +1,223 @@
/*
* This file is part of libsidplayfp, a SID player engine.
*
* Copyright 2011-2014 Leandro Nini <drfiemost@users.sourceforge.net>
* Copyright 2009-2014 VICE Project
* Copyright 2007-2010 Antti Lankila
* Copyright 2000 Simon White
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "tod.h"
#include <cstring>
#include "mos6526.h"
namespace libsidplayfp
{
void Tod::reset()
{
cycles = 0;
memset(clock, 0, sizeof(clock));
clock[HOURS] = 1; // the most common value
memcpy(latch, clock, sizeof(latch));
memset(alarm, 0, sizeof(alarm));
isLatched = false;
isStopped = true;
event_context.schedule(*this, 0, EVENT_CLOCK_PHI1);
}
uint8_t Tod::read(uint_least8_t reg)
{
// TOD clock is latched by reading Hours, and released
// upon reading Tenths of Seconds. The counter itself
// keeps ticking all the time.
// Also note that this latching is different from the input one.
if (!isLatched)
memcpy(latch, clock, sizeof(latch));
if (reg == TENTHS)
isLatched = false;
else if (reg == HOURS)
isLatched = true;
return latch[reg];
}
void Tod::write(uint_least8_t reg, uint8_t data)
{
switch (reg)
{
case TENTHS: // Time Of Day clock 1/10 s
data &= 0x0f;
break;
case SECONDS: // Time Of Day clock sec
// deliberate run on
case MINUTES: // Time Of Day clock min
data &= 0x7f;
break;
case HOURS: // Time Of Day clock hour
// force bits 6-5 = 0
data &= 0x9f;
// Flip AM/PM on hour 12
// Flip AM/PM only when writing time, not when writing alarm
if ((data & 0x1f) == 0x12 && !(crb & 0x80))
data ^= 0x80;
break;
}
bool changed = false;
if (crb & 0x80)
{
// set alarm
if (alarm[reg] != data)
{
changed = true;
alarm[reg] = data;
}
}
else
{
// set time
if (reg == TENTHS)
{
// apparently the tickcounter is reset to 0 when the clock
// is not running and then restarted by writing to the 10th
// seconds register.
if (isStopped)
{
cycles = 0;
isStopped = false;
}
}
else if (reg == HOURS)
{
isStopped = true;
}
if (clock[reg] != data)
{
changed = true;
clock[reg] = data;
}
}
// check alarm
if (changed)
{
checkAlarm();
}
}
void Tod::event()
{
// Reload divider according to 50/60 Hz flag
// Only performed on expiry according to Frodo
cycles += period * (cra & 0x80 ? 5 : 6);
// Fixed precision 25.7
event_context.schedule(*this, cycles >> 7);
cycles &= 0x7F; // Just keep the decimal part
if (!isStopped)
{
// advance the counters.
// - individual counters are all 4 bit
uint8_t t0 = clock[TENTHS] & 0x0f;
uint8_t t1 = clock[SECONDS] & 0x0f;
uint8_t t2 = (clock[SECONDS] >> 4) & 0x0f;
uint8_t t3 = clock[MINUTES] & 0x0f;
uint8_t t4 = (clock[MINUTES] >> 4) & 0x0f;
uint8_t t5 = clock[HOURS] & 0x0f;
uint8_t t6 = (clock[HOURS] >> 4) & 0x01;
uint8_t pm = clock[HOURS] & 0x80;
// tenth seconds (0-9)
t0 = (t0 + 1) & 0x0f;
if (t0 == 10)
{
t0 = 0;
// seconds (0-59)
t1 = (t1 + 1) & 0x0f; // x0...x9
if (t1 == 10)
{
t1 = 0;
t2 = (t2 + 1) & 0x07; // 0x...5x
if (t2 == 6)
{
t2 = 0;
// minutes (0-59)
t3 = (t3 + 1) & 0x0f; // x0...x9
if (t3 == 10)
{
t3 = 0;
t4 = (t4 + 1) & 0x07; // 0x...5x
if (t4 == 6)
{
t4 = 0;
// hours (1-12)
t5 = (t5 + 1) & 0x0f;
if (t6)
{
// toggle the am/pm flag when going from 11 to 12 (!)
if (t5 == 2)
{
pm ^= 0x80;
}
// wrap 12h -> 1h (FIXME: when hour became x3 ?)
if (t5 == 3)
{
t5 = 1;
t6 = 0;
}
}
else
{
if (t5 == 10)
{
t5 = 0;
t6 = 1;
}
}
}
}
}
}
}
clock[TENTHS] = t0;
clock[SECONDS] = t1 | (t2 << 4);
clock[MINUTES] = t3 | (t4 << 4);
clock[HOURS] = t5 | (t6 << 4) | pm;
checkAlarm();
}
}
void Tod::checkAlarm()
{
if (!memcmp(alarm, clock, sizeof(alarm)))
{
parent->todInterrupt();
}
}
}

View File

@ -0,0 +1,276 @@
// ---------------------------------------------------------------------------
// This file is part of reSID, a MOS6581 SID emulator engine.
// Copyright (C) 2010 Dag Lem <resid@nimrod.no>
//
// 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 RESID_SPLINE_H
#define RESID_SPLINE_H
namespace reSID
{
// Our objective is to construct a smooth interpolating single-valued function
// y = f(x).
//
// Catmull-Rom splines are widely used for interpolation, however these are
// parametric curves [x(t) y(t) ...] and can not be used to directly calculate
// y = f(x).
// For a discussion of Catmull-Rom splines see Catmull, E., and R. Rom,
// "A Class of Local Interpolating Splines", Computer Aided Geometric Design.
//
// Natural cubic splines are single-valued functions, and have been used in
// several applications e.g. to specify gamma curves for image display.
// These splines do not afford local control, and a set of linear equations
// including all interpolation points must be solved before any point on the
// curve can be calculated. The lack of local control makes the splines
// more difficult to handle than e.g. Catmull-Rom splines, and real-time
// interpolation of a stream of data points is not possible.
// For a discussion of natural cubic splines, see e.g. Kreyszig, E., "Advanced
// Engineering Mathematics".
//
// Our approach is to approximate the properties of Catmull-Rom splines for
// piecewice cubic polynomials f(x) = ax^3 + bx^2 + cx + d as follows:
// Each curve segment is specified by four interpolation points,
// p0, p1, p2, p3.
// The curve between p1 and p2 must interpolate both p1 and p2, and in addition
// f'(p1.x) = k1 = (p2.y - p0.y)/(p2.x - p0.x) and
// f'(p2.x) = k2 = (p3.y - p1.y)/(p3.x - p1.x).
//
// The constraints are expressed by the following system of linear equations
//
// [ 1 xi xi^2 xi^3 ] [ d ] [ yi ]
// [ 1 2*xi 3*xi^2 ] * [ c ] = [ ki ]
// [ 1 xj xj^2 xj^3 ] [ b ] [ yj ]
// [ 1 2*xj 3*xj^2 ] [ a ] [ kj ]
//
// Solving using Gaussian elimination and back substitution, setting
// dy = yj - yi, dx = xj - xi, we get
//
// a = ((ki + kj) - 2*dy/dx)/(dx*dx);
// b = ((kj - ki)/dx - 3*(xi + xj)*a)/2;
// c = ki - (3*xi*a + 2*b)*xi;
// d = yi - ((xi*a + b)*xi + c)*xi;
//
// Having calculated the coefficients of the cubic polynomial we have the
// choice of evaluation by brute force
//
// for (x = x1; x <= x2; x += res) {
// y = ((a*x + b)*x + c)*x + d;
// plot(x, y);
// }
//
// or by forward differencing
//
// y = ((a*x1 + b)*x1 + c)*x1 + d;
// dy = (3*a*(x1 + res) + 2*b)*x1*res + ((a*res + b)*res + c)*res;
// d2y = (6*a*(x1 + res) + 2*b)*res*res;
// d3y = 6*a*res*res*res;
//
// for (x = x1; x <= x2; x += res) {
// plot(x, y);
// y += dy; dy += d2y; d2y += d3y;
// }
//
// See Foley, Van Dam, Feiner, Hughes, "Computer Graphics, Principles and
// Practice" for a discussion of forward differencing.
//
// If we have a set of interpolation points p0, ..., pn, we may specify
// curve segments between p0 and p1, and between pn-1 and pn by using the
// following constraints:
// f''(p0.x) = 0 and
// f''(pn.x) = 0.
//
// Substituting the results for a and b in
//
// 2*b + 6*a*xi = 0
//
// we get
//
// ki = (3*dy/dx - kj)/2;
//
// or by substituting the results for a and b in
//
// 2*b + 6*a*xj = 0
//
// we get
//
// kj = (3*dy/dx - ki)/2;
//
// Finally, if we have only two interpolation points, the cubic polynomial
// will degenerate to a straight line if we set
//
// ki = kj = dy/dx;
//
#if SPLINE_BRUTE_FORCE
#define interpolate_segment interpolate_brute_force
#else
#define interpolate_segment interpolate_forward_difference
#endif
// ----------------------------------------------------------------------------
// Calculation of coefficients.
// ----------------------------------------------------------------------------
inline
void cubic_coefficients(double x1, double y1, double x2, double y2,
double k1, double k2,
double& a, double& b, double& c, double& d)
{
double dx = x2 - x1, dy = y2 - y1;
a = ((k1 + k2) - 2*dy/dx)/(dx*dx);
b = ((k2 - k1)/dx - 3*(x1 + x2)*a)/2;
c = k1 - (3*x1*a + 2*b)*x1;
d = y1 - ((x1*a + b)*x1 + c)*x1;
}
// ----------------------------------------------------------------------------
// Evaluation of cubic polynomial by brute force.
// ----------------------------------------------------------------------------
template<class PointPlotter>
inline
void interpolate_brute_force(double x1, double y1, double x2, double y2,
double k1, double k2,
PointPlotter plot, double res)
{
double a, b, c, d;
cubic_coefficients(x1, y1, x2, y2, k1, k2, a, b, c, d);
// Calculate each point.
for (double x = x1; x <= x2; x += res) {
double y = ((a*x + b)*x + c)*x + d;
plot(x, y);
}
}
// ----------------------------------------------------------------------------
// Evaluation of cubic polynomial by forward differencing.
// ----------------------------------------------------------------------------
template<class PointPlotter>
inline
void interpolate_forward_difference(double x1, double y1, double x2, double y2,
double k1, double k2,
PointPlotter plot, double res)
{
double a, b, c, d;
cubic_coefficients(x1, y1, x2, y2, k1, k2, a, b, c, d);
double y = ((a*x1 + b)*x1 + c)*x1 + d;
double dy = (3*a*(x1 + res) + 2*b)*x1*res + ((a*res + b)*res + c)*res;
double d2y = (6*a*(x1 + res) + 2*b)*res*res;
double d3y = 6*a*res*res*res;
// Calculate each point.
for (double x = x1; x <= x2; x += res) {
plot(x, y);
y += dy; dy += d2y; d2y += d3y;
}
}
template<class PointIter>
inline
double x(PointIter p)
{
return (*p)[0];
}
template<class PointIter>
inline
double y(PointIter p)
{
return (*p)[1];
}
// ----------------------------------------------------------------------------
// Evaluation of complete interpolating function.
// Note that since each curve segment is controlled by four points, the
// end points will not be interpolated. If extra control points are not
// desirable, the end points can simply be repeated to ensure interpolation.
// Note also that points of non-differentiability and discontinuity can be
// introduced by repeating points.
// ----------------------------------------------------------------------------
template<class PointIter, class PointPlotter>
inline
void interpolate(PointIter p0, PointIter pn, PointPlotter plot, double res)
{
double k1, k2;
// Set up points for first curve segment.
PointIter p1 = p0; ++p1;
PointIter p2 = p1; ++p2;
PointIter p3 = p2; ++p3;
// Draw each curve segment.
for (; p2 != pn; ++p0, ++p1, ++p2, ++p3) {
// p1 and p2 equal; single point.
if (x(p1) == x(p2)) {
continue;
}
// Both end points repeated; straight line.
if (x(p0) == x(p1) && x(p2) == x(p3)) {
k1 = k2 = (y(p2) - y(p1))/(x(p2) - x(p1));
}
// p0 and p1 equal; use f''(x1) = 0.
else if (x(p0) == x(p1)) {
k2 = (y(p3) - y(p1))/(x(p3) - x(p1));
k1 = (3*(y(p2) - y(p1))/(x(p2) - x(p1)) - k2)/2;
}
// p2 and p3 equal; use f''(x2) = 0.
else if (x(p2) == x(p3)) {
k1 = (y(p2) - y(p0))/(x(p2) - x(p0));
k2 = (3*(y(p2) - y(p1))/(x(p2) - x(p1)) - k1)/2;
}
// Normal curve.
else {
k1 = (y(p2) - y(p0))/(x(p2) - x(p0));
k2 = (y(p3) - y(p1))/(x(p3) - x(p1));
}
interpolate_segment(x(p1), y(p1), x(p2), y(p2), k1, k2, plot, res);
}
}
// ----------------------------------------------------------------------------
// Class for plotting integers into an array.
// ----------------------------------------------------------------------------
template<class F>
class PointPlotter
{
protected:
F* f;
public:
PointPlotter(F* arr) : f(arr)
{
}
void operator ()(double x, double y)
{
// Clamp negative values to zero.
if (y < 0) {
y = 0;
}
f[int(x)] = F(y + 0.5);
}
};
} // namespace reSID
#endif // not RESID_SPLINE_H

View File

@ -0,0 +1,469 @@
2010-??-?? Dag Lem <resid@nimrod.no>
* Version 1.0 released.
* configure.ac: Updated to current autoconf/automake standards.
New option --enable-arch for gcc architecture specific
optimizations, including vectorization. New option
--enable-branch-hints for branch prediction optimizations.
* Makefile.am, samp2src.pl: Generate header files instead of
source files for waveform samples. Added dac.h, dac.cc.
* siddefs.h.in: Sampling method names now better reflect their
operation (SAMPLE_RESAMPLE_INTERPOLATE -> SAMPLE_RESAMPLE,
SAMPLE_RESAMPLE_FAST -> SAMPLE_RESAMPLE_FASTMEM).
New macros for branch prediction: likely / unlikely.
* dac.h: New file; accurate emulation of non-monotonic MOS 6581
D/A converters.
* dac.cc: New file; accurate emulation of non-monotonic MOS 6581
D/A converters.
* envelope.h (EnvelopeGenerator::clock): Emulation of one cycle
pipeline delay in the exponential frequency divider.
(EnvelopeGenerator::output): Emulation of non-ideal DAC output.
(EnvelopeGenerator::set_chip_model): New function; for emulation
of DAC imperfections.
(EnvelopeGenerator::set_exponential_counter): New function;
modularization of exponential counter update.
* envelope.cc (EnvelopeGenerator::EnvelopeGenerator):
Initialization of DAC lookup tables.
(EnvelopeGenerator::readENV): Return envelope_counter directly, in
order to allow EnvelopeGenerator::output to emulate DAC
imperfections.
(EnvelopeGenerator::reset): Initialization of new
variables.
(EnvelopeGenerator::set_chip_model): New function; for emulation
of DAC imperfections.
(EnvelopeGenerator::writeCONTROL_REG): Flush of exponential
frequency divider pipeline on attack.
* extfilt.h (ExternalFilter::clock): Cutoff frequency fixed point
accuracy is traded off for for vastly improved filter signal
fixed point accuracy.
(ExternalFilter::output): Output range reduced from 20 to 16
bits.
* extfilt.cc (ExternalFilter::ExternalFilter): Assumes audio
equipment impedance of 10kOhm, yielding a high-pass 3-dB frequency
of 1.6Hz (changed from 16Hz). Cutoff frequency fixed point accuracy
is traded off for for vastly improved filter signal fixed point
accuracy.
(ExternalFilter::set_chip_model): Removed. Remaining DC levels can
only be canceled by enabling the external filter (or by similar
post processing).
* filter.h: Major rewrite implementing an accurate model of the
actual filter and output stage topology, including models for
op-amps, input and feedback NMOS FET "resistors", and voltage
controlled resistors (VCRs).
(Filter::input): New interface to set external input level.
(Filter::output): Output range reduced from 20 to 16 bits.
(Filter::set_voice_mask): New function. Emulation of physical
connection of EXT IN, and voice muting for test purposes.
(Filter::solve_gain): New function; iterative solver using
Newton-Raphson and bisection to calculate gain for SID op-amp
gains and summers using NMOS FETs as input and feedback "resistors".
(Filter::solve_integrate): New function; one-step fixpoint solver
to calculate output from SID op-amp integrators using VCRs built
from four NMOS FETs as inputs.
* filter.cc: Major rewrite implementing an accurate model of the
actual filter and output stage topology, including models for
op-amps, input and feedback NMOS FET "resistors", and voltage
controlled resistors (VCRs).
(Filter::set_voice_mask): New function. Emulation of physical
connection of EXT IN, and voice muting for test purposes.
* sid.h: Resampling constants declared in enum.
(SID::State): Added voice_mask, shift_register_reset,
shift_pipeline, pulse_output, floating_output_ttl,
envelope_pipeline.
(SID::output): 16 bit output range only, n-bit interface
removed.
(SID::clock_resample): Renamed from
SID::clock_resample_interpolate.
(SID::clock_resample_fastmem): Renamed from
SID::clock_resample_fast.
* sid.cc (SID::clock): Emulation of one cycle pipeline write delay
for the MOS8580.
(SID::clock_resample): Renamed from SID::clock_resample_interpolate.
Corrected bug in FIR table wraparound, courtesy of Antti Lankila.
(SID::clock_resample_fastmem): Renamed from
SID::clock_resample_fast.
(SID::input): Hand off all processing of the external input to the
filter.
(SID::output): 16 bit output range only, n-bit output interface
removed.
(SID::read): Aging time for bus value increased from 0x2000 to
0x4000 cycles.
(SID::read_state, SID::write_state): Added voice_mask,
shift_register_reset, shift_pipeline, pulse_output,
floating_output_ttl, envelope_pipeline.
(SID::set_voice_mask): New function. Emulation of physical
connection of EXT IN, and voice muting for test purposes.
(SID::write): Emulation of one cycle pipeline write delay for the
MOS8580.
(SID::write_pipeline): New function. Emulation of one cycle
pipeline write delay for the MOS8580.
* spline.h (PointPlotter::operator()): Rounding to nearest
integer.
* voice.h (Voice::output): Handling of DC for waveform "zero"
level moved to Filter::clock.
* voice.cc (Voice::set_chip_model): Call set_chip_model for
envelope generator. Handling of DC for "zero" level moved to
Filter::set_chip_model.
* wave.h (WaveformGenerator::clock): Corrected shift register
model. Emulation of reset time for the shift register. Emulation
of two cycle pipeline delay for accumulator bit 19 to shift the
shift register.
(WaveformGenerator::clock_shift_register)
(WaveformGenerator::write_shift_register)
(WaveformGenerator::reset_shift_register)
(WaveformGenerator::set_noise_output): New functions. Emulation
of writes to the shift register by combined waveforms.
(WaveformGenerator::set_waveform_output): New function. Emulation
of floating DAC input with aging. Emulation of one cycle pipeline
delay for the pulse width comparator to change the pulse
level. Emulation of writes to the shift register by combined
waveforms. Highly optimized waveform calculation using nearly
branch-free table lookup for all waveforms; replaces 16 previous
waveform functions named WaveformGenerator::outputXXXX.
(WaveformGenerator::output): Emulation of non-ideal DAC output.
* wave.cc (WaveformGenerator::WaveformGenerator): Initialization
of lookup tables for basic waveforms and DACs.
(WaveformGenerator::readOSC): Return waveform_output directly, in
order to allow WaveformGenerator::output to emulate DAC
imperfections.
(WaveformGenerator::set_chip_model): Update pointer to current
waveform table.
(WaveformGenerator::writePW_LO, WaveformGenerator::writePW_HI):
Push next pulse level into pulse level pipeline.
(WaveformGenerator::writeCONTROL_REG): Emulation of the effects of
the test bit on the shift register (shifting, reset time).
Emulation of fading time for floating DAC input (waveform 0).
Update pointer to current waveform table.
(WaveformGenerator::reset): Initialization of new variables.
2004-06-11 Dag Lem <resid@nimrod.no>
* Version 0.16 released.
* envelope.h (EnvelopeGenerator::clock): Corrected off-by-one
error in check for ADSR delay bug in delta_t cycle interface.
* filter.cc (Filter::set_chip_model): Initialize filter cutoff
mappings before call to set_chip_model.
* sid.cc (SID::set_sampling_parameters): Build shifted FIR tables
with samples according to the sampling frequency.
(SID::clock_resample_interpolate): New function; factorized linear
interpolation out from filter convolutions, and made convolutions
vectorizable.
(SID::clock_resample_fast): New function; single convolution, same
accuracy as with interpolation by using more filter tables.
(SID::State, SID::read_state, SID::write_state): Read and write
rate_counter_period and exponential_counter_period. Read sustain
value.
2003-10-20 Dag Lem <resid@nimrod.no>
* Version 0.15 released.
* envelope.h (EnvelopeGenerator): Added public State enum.
(EnvelopeGenerator::clock): Rate counter is 15 bits, count
rate_period - 1 after wrapping from 0x8000 to 0 in ADSR delay bug.
* sid.cc, sid.h (SID::State): Added envelope_state.
(SID::State::write_state): Restore register 0x18.
(SID::set_sampling_parameters): Scale resampling filter to avoid
clipping.
(SID::clock_resample): Saturated arithmetics to avoid clipping.
2002-12-31 Dag Lem <resid@nimrod.no>
* Version 0.14 released.
* envelope.h (EnvelopeGenerator::clock): Corrected one cycle error
in ADSR delay bug. Only load the exponential counter period at the
envelope counter values 255, 93, 54, 26, 14, 6, 0.
* filter.cc (Filter::set_chip_model): Call set_w0() and set_Q() to
update filter settings.
(Filter::set_w0): Limit cutoff frequency for both 1 cycle and
delta_t cycle filter.
* filter.h (Filter::clock): Mix in external audio input.
* sid.cc, sid.h (SID::input): New function; accepts external audio
input sample.
* spline.h (PointPlotter::operator ()): Clamp negative values to
zero.
* voice.cc, voice.h: Changed misleading name wave_DC to wave_zero.
* wave.h (WaveformGenerator::clock): Corrected bug in check for
accumulator bit 19 in noise register shift.
2002-01-19 Dag Lem <resid@nimrod.no>
* Version 0.13 released.
* configure.in: Replaced AC_TRY_COMPILER with AC_TRY_COMPILE,
removed AC_PROG_RANLIB.
* envelope.h (EnvelopeGenerator::clock): Reset rate_step on state
change.
* extfilt.cc (ExternalFilter::set_chip_model): New calculation of
maximum mixer DC level.
* filter.cc (Filter::set_chip_model): Moved calculation of
voice_DC to voice.cc, corrected calculation of mixer_DC.
* filter.h (Filter::output): Mixer output is not inverted.
* sid.cc (SID::set_chip_model): Call voice.set_chip_model instead
of voice.wave.set_chip_model.
* voice.cc (Voice::Voice): Call set_chip_model.
(Voice::set_chip_model): New function; model both waveform D/A
converter and envelope multiplying D/A converter DC offsets.
* voice.h (Voice::output): Add both waveform D/A converter and
envelope multiplying D/A converter DC offsets.
* wave.h (WaveformGenerator::output____): Reverted to output
minimum wave level when no waveform is selected. The maximum and
minimum wave output levels are interchanged in C= Hacking Issue #20.
2001-10-20 Dag Lem <resid@nimrod.no>
* Version 0.12 released.
* envelope.cc, envelope.h, filter.cc, filter.h, wave.cc, wave.h:
Removed bool usage. This avoids unnecessary conversion to 1/0.
* filter.cc (Filter::set_chip_model): New function; selects voice
and mixer DC offsets and mapping from the FC registers to filter
cutoff frequency. The voice and mixer DC offsets for the MOS6581 are
calculated from measurements made by Hársfalvi, Levente in
C= Hacking Issue #20.
(Filter::Filter): Call set_chip_model.
(Filter::f0_6581, Filter::f0_8580): Separate FC mapping tables.
(Filter::f0_points_6581, Filter::f0_points_8580): Separate FC mapping
points.
* extfilt.cc, extfilt.h (ExternalFilter::set_chip_model): New
function supporting separate DC correction for MOS6581 and MOS8580.
* sid.cc, sid.h (SID::adjust_sampling_frequency): New function for
on-the-fly adjustment of sampling frequency.
(SID::clock_fast): Corrected sample calculation.
(SID::set_chip_model): Set filter chip model.
(SID::output): Added audio clipping.
(SID::clock, SID::clock_fast, SID::clock_interpolate,
SID::clock_resample): Added sample interleaving.
* spline.h (interpolate): Generalized to accept repeated points to
introduce points of non-differentiability and discontinuity.
* wave.h (WaveformGenerator::output____): No selected waveform
yields maximum wave output level. This was found by Hársfalvi,
Levente in C= Hacking Issue #20.
(WaveformGenerator::clock): Optimized for speed (no division).
2001-03-10 Dag Lem <resid@nimrod.no>
* Version 0.11 released.
* configure.in: Disable building of shared library by default.
Control inlining with RESID_INLINING (0 or 1) and RESID_INLINE
(blank or "inline").
* envelope.h, extfilt.h, filter.h, voice.h, wave.h: inline keyword
in both function declarations and function definitions.
* samp2src.pl: Beautified Perl code.
* sid.h, sid.cc: Replaced voice variables with array. Removed
filter variables from SID::State.
(SID::clock): New audio sample generating interface. Three
clocking methods are available; clocking at output sample
frequency, clocking at cycle frequency with linear sample
interpolation, and clocking at cycle frequency with audio
resampling.
(SID::clock_fast, SID::clock_interpolate, SID::clock_resample):
New functions called by SID::clock.
(SID::set_sampling_parameters): New function to set up SID for
sample generation. The FIR table used in SID::clock_resample is
calculated here.
(SID::I0): 0th order modified Bessel function to calculate Kaiser
window.
* siddefs.h: Control inlining with RESID_INLINING (0 or 1) and
RESID_INLINE (blank or "inline"). Added enum sampling_method.
* voice.h, voice.cc (Voice::set_sync_source): Moved setting of
sync source from constructor.
* wave.h, wave.cc (WaveformGenerator::set_sync_source): Moved
setting of sync source from constructor.
2000-11-22 Dag Lem <resid@nimrod.no>
* Version 0.10 released.
* configure.in, Makefile.am: Use libtool to build library. The
hack to "disable" install is removed.
* extfilt.h, filter.h: Moved filter stability code from sid.cc.
* sid.cc (SID::clock): Moved filter stability code to
extfilt.h/filter.h. Don't clock the rest of the chip more
frequently than necessary.
* wave.cc: Typecast for pedantic (and probably incorrect)
compilers.
2000-05-18 Dag Lem <resid@nimrod.no>
* Version 0.9 released.
* filter.h (Filter::output): The sum of the filter outputs is no
longer weighted.
1999-06-24 Dag Lem <resid@nimrod.no>
* Version 0.8 released.
* filter.h, filter.cc, wave.h, wave.cc: Typecasts for pedantic
compilers.
* filter.h (Filter::clock): Voice 3 is only silenced by voice3off
if it is not routed through the filter.
* sid.cc (SID::State): Added constructor for proper initalization.
* spline.h: Inlined template functions to avoid problems at link
time with certain compilers.
1999-02-25 Dag Lem <resid@nimrod.no>
* Version 0.7 released.
* configure.in: Check whether compiler supports bool.
* extfilt.h, extfilt.cc: Implementation of C64 filter, external to
the SID chip.
* filter.h (Filter::clock): Optimized filter routing using a switch.
(Filter::output): Optimized filter mixing using a switch, avoiding
integer division. Corrected sign of filtered output, which is
inverted compared to unfiltered output.
* filter.cc (Filter::set_w0): Removed use of M_PI and math.h
functions. Use spline table to map fc to w0.
(Filter::fc_default): Return array of FC spline interpolation points.
(Filter::fc_plotter): Return FC spline plotter object.
* sid.h (SID::enable_external_filter): Enable/disable external
filter.
(SID::fc_default): Return array of FC spline interpolation points.
(SID::fc_plotter): Return FC spline plotter object.
(SID::State, SID::read_state, SID::write_state): Read and write
complete SID state.
* sid.cc (SID::clock): Age bus value. Clock external filter.
(SID::enable_external_filter): Enable/disable external filter.
* spline.h: Spline implementation. Used to specify mapping from
the FC register to filter cutoff frequency.
1998-11-14 Dag Lem <resid@nimrod.no>
* Version 0.6 released.
* configure.in: Allow compilation in a separate directory.
* wave.h (WaveformGenerator::synchronize): Handle special case when a
sync source is synced itself on the same cycle as its MSB is set
high.
* sid.cc (SID::clock): Only clock on MSB on/off for hard sync.
1998-09-06 Dag Lem <resid@nimrod.no>
* Version 0.5 released.
* version.cc (resid_version_string): Version string with C linkage.
* wave.cc (WaveformGenerator::set_chip_model): Emulation of MOS8580
combined waveforms.
1998-08-28 Dag Lem <resid@nimrod.no>
* Version 0.4 released.
* envelope.h (EnvelopeGenerator::clock): Count up to rate_period twice
during ADSR delay bug, and add one extra rate counter step.
* filter.cc (Filter::bsd_copysign): Renamed copysign function for
compilation on platforms where copysign is implemented as a macro.
1998-08-23 Dag Lem <resid@nimrod.no>
* Version 0.3 released.
* envelope.h (EnvelopeGenerator::clock): Handle ADSR boundary bug.
* envelope.cc (EnvelopeGenerator::rate_counter_period,
EnvelopeGenerator::exponential_counter_period): Corrected counter
periods.
* filter.h (Filter::clock): Optimized for speed (division by shifting).
* sid.h (SID::clock): New one-cycle optimized overload of the clock()
function.
* wave.h (WaveformGenerator::output_P_T): Combined waveform
pulse+triangle indexing corrected.
(WaveformGenerator::output_P__): Check for test bit to handle
pulse+test bit samples.
(WaveformGenerator::output): Optimized for speed (inlining).
1998-07-28 Dag Lem <resid@nimrod.no>
* Version 0.2 released.
* envelope.h (EnvelopeGenerator::clock): Start decay cycle immediately
at envelope counter 0xff. New sustain value is zero if the sustain
level is raised above the current envelope counter value.
(EnvelopeGenerator::step_envelope): Handle ADSR delay bug.
* envelope.cc (EnvelopeGenerator::rate_counter_period,
EnvelopeGenerator::exponential_counter_period): Corrected counter
periods.
(EnvelopeGenerator::writeCONTROL_REG): Do not modify rate counter.
* filter.cc (Filter::set_Q): Constrain Q to keep filter stable.
* sid.h (SID::read, SID::write, SID::bypass_filter): Simplified API
routing register access through the SID class.
* sid.cc (SID::output): Corrected variable-bit audio output return.
(SID::read, SID::write): Allow read of write only registers.
1998-06-09 Dag Lem <resid@nimrod.no>
* Version 0.1 released.

View File

@ -0,0 +1,41 @@
/* addr, off, rle, values */
/*$0003*/ 0x83, 0x04, 0xaa, 0xb1, 0x91, 0xb3, 0x22,
/*$000b*/ 0x03, 0x4c,
/*$000f*/ 0x03, 0x04,
/*$0016*/ 0x86, 0x05, 0x19, 0x16, 0x00, 0x0a, 0x76, 0xa3,
/*$0022*/ 0x86, 0x03, 0x40, 0xa3, 0xb3, 0xbd,
/*$002b*/ 0x85, 0x01, 0x01, 0x08,
/*$0034*/ 0x07, 0xa0,
/*$0038*/ 0x03, 0xa0,
/*$003a*/ 0x01, 0xff,
/*$0042*/ 0x07, 0x08,
/*$0047*/ 0x04, 0x24,
/*$0053*/ 0x8b, 0x01, 0x03, 0x4c,
/*$0061*/ 0x0c, 0x8d,
/*$0063*/ 0x02, 0x10,
/*$0069*/ 0x84, 0x02, 0x8c, 0xff, 0xa0,
/*$0071*/ 0x85, 0x1e, 0x0a, 0xa3, 0xe6, 0x7a, 0xd0, 0x02, 0xe6, 0x7b, 0xad, 0x00, 0x08, 0xc9, 0x3a, 0xb0, 0x0a, 0xc9, 0x20, 0xf0, 0xef, 0x38, 0xe9, 0x30, 0x38, 0xe9, 0xd0, 0x60, 0x80, 0x4f, 0xc7, 0x52, 0x58,
/*$0091*/ 0x01, 0xff,
/*$009a*/ 0x08, 0x03,
/*$00b2*/ 0x97, 0x01, 0x3c, 0x03,
/*$00c2*/ 0x8e, 0x03, 0xa0, 0x30, 0xfd, 0x01,
/*$00c8*/ 0x82, 0x82, 0x03,
/*$00cb*/ 0x80, 0x81, 0x01,
/*$00ce*/ 0x01, 0x20,
/*$00d1*/ 0x82, 0x01, 0x18, 0x05,
/*$00d5*/ 0x82, 0x02, 0x27, 0x07, 0x0d,
/*$00d9*/ 0x81, 0x86, 0x84,
/*$00e0*/ 0x80, 0x85, 0x85,
/*$00e6*/ 0x80, 0x86, 0x86,
/*$00ed*/ 0x80, 0x85, 0x87,
/*$00f3*/ 0x80, 0x03, 0x18, 0xd9, 0x81, 0xeb,
/*$0176*/ 0x7f, 0x00,
/*$01f6*/ 0x7f, 0x00,
/*$0276*/ 0x7f, 0x00,
/*$0282*/ 0x8b, 0x0a, 0x08, 0x00, 0xa0, 0x00, 0x0e, 0x00, 0x04, 0x0a, 0x00, 0x04, 0x10,
/*$028f*/ 0x82, 0x01, 0x48, 0xeb,
/*$0300*/ 0xef, 0x0b, 0x8b, 0xe3, 0x83, 0xa4, 0x7c, 0xa5, 0x1a, 0xa7, 0xe4, 0xa7, 0x86, 0xae,
/*$0310*/ 0x84, 0x02, 0x4c, 0x48, 0xb2,
/*$0314*/ 0x81, 0x1f, 0x31, 0xea, 0x66, 0xfe, 0x47, 0xfe, 0x4a, 0xf3, 0x91, 0xf2, 0x0e, 0xf2, 0x50, 0xf2, 0x33, 0xf3, 0x57, 0xf1, 0xca, 0xf1, 0xed, 0xf6, 0x3e, 0xf1, 0x2f, 0xf3, 0x66, 0xfe, 0xa5, 0xf4, 0xed, 0xf5,
/*Total 217*/

View File

@ -0,0 +1,127 @@
// ---------------------------------------------------------------------------
// This file is part of reSID, a MOS6581 SID emulator engine.
// Copyright (C) 2004 Dag Lem <resid@nimrod.no>
//
// 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 RESID_VOICE_CC
#include "voice.h"
namespace reSID
{
// ----------------------------------------------------------------------------
// Constructor.
// ----------------------------------------------------------------------------
Voice::Voice()
{
set_chip_model(MOS6581);
}
// ----------------------------------------------------------------------------
// Set chip model.
// ----------------------------------------------------------------------------
void Voice::set_chip_model(chip_model model)
{
wave.set_chip_model(model);
envelope.set_chip_model(model);
if (model == MOS6581) {
// The waveform D/A converter introduces a DC offset in the signal
// to the envelope multiplying D/A converter. The "zero" level of
// the waveform D/A converter can be found as follows:
//
// Measure the "zero" voltage of voice 3 on the SID audio output
// pin, routing only voice 3 to the mixer ($d417 = $0b, $d418 =
// $0f, all other registers zeroed).
//
// Then set the sustain level for voice 3 to maximum and search for
// the waveform output value yielding the same voltage as found
// above. This is done by trying out different waveform output
// values until the correct value is found, e.g. with the following
// program:
//
// lda #$08
// sta $d412
// lda #$0b
// sta $d417
// lda #$0f
// sta $d418
// lda #$f0
// sta $d414
// lda #$21
// sta $d412
// lda #$01
// sta $d40e
//
// ldx #$00
// lda #$38 ; Tweak this to find the "zero" level
//l cmp $d41b
// bne l
// stx $d40e ; Stop frequency counter - freeze waveform output
// brk
//
// The waveform output range is 0x000 to 0xfff, so the "zero"
// level should ideally have been 0x800. In the measured chip, the
// waveform output "zero" level was found to be 0x380 (i.e. $d41b
// = 0x38) at an audio output voltage of 5.94V.
//
// With knowledge of the mixer op-amp characteristics, further estimates
// of waveform voltages can be obtained by sampling the EXT IN pin.
// From EXT IN samples, the corresponding waveform output can be found by
// using the model for the mixer.
//
// Such measurements have been done on a chip marked MOS 6581R4AR
// 0687 14, and the following results have been obtained:
// * The full range of one voice is approximately 1.5V.
// * The "zero" level rides at approximately 5.0V.
//
wave_zero = 0x380;
}
else {
// No DC offsets in the MOS8580.
wave_zero = 0x800;
}
}
// ----------------------------------------------------------------------------
// Set sync source.
// ----------------------------------------------------------------------------
void Voice::set_sync_source(Voice* source)
{
wave.set_sync_source(&source->wave);
}
// ----------------------------------------------------------------------------
// Register functions.
// ----------------------------------------------------------------------------
void Voice::writeCONTROL_REG(reg8 control)
{
wave.writeCONTROL_REG(control);
envelope.writeCONTROL_REG(control);
}
// ----------------------------------------------------------------------------
// SID reset.
// ----------------------------------------------------------------------------
void Voice::reset()
{
wave.reset();
envelope.reset();
}
} // namespace reSID

View File

@ -0,0 +1,84 @@
# Test for std c++11 compiler support
#
# trimmed down verision of AX_CXX_COMPILE_STDCXX_11
# from the GNU Autoconf Archive
#
# Copyright (c) 2008 Benjamin Kosnik <bkoz@redhat.com>
# Copyright (c) 2012 Zack Weinberg <zackw@panix.com>
# Copyright (c) 2013 Roy Stogner <roystgnr@ices.utexas.edu>
# Copyright (c) 2014 Alexey Sokolov <sokolov@google.com>
#
# Copying and distribution of this file, with or without modification, are
# permitted in any medium without royalty provided the copyright notice
# and this notice are preserved. This file is offered as-is, without any
# warranty.
m4_define([_AX_CXX_COMPILE_STDCXX_11_testbody], [[
template <typename T>
struct check
{
static_assert(sizeof(int) <= sizeof(T), "not big enough");
};
struct Base {
virtual void f() {}
};
struct Child : public Base {
virtual void f() override {}
};
typedef check<check<bool>> right_angle_brackets;
int a;
decltype(a) b;
typedef check<int> check_type;
check_type c;
check_type&& cr = static_cast<check_type&&>(c);
auto d = a;
auto l = [](){};
]])
AC_DEFUN([SID_CXX_COMPILE_STDCXX_11], [dnl
AC_LANG_PUSH([C++])dnl
ac_success=no
AC_CACHE_CHECK(whether $CXX supports C++11 features by default,
ax_cv_cxx_compile_cxx11,
[AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_11_testbody])],
[ax_cv_cxx_compile_cxx11=yes],
[ax_cv_cxx_compile_cxx11=no])])
if test x$ax_cv_cxx_compile_cxx11 = xyes; then
ac_success=yes
fi
if test x$ac_success = xno; then
cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx11_-std=c++11])
AC_CACHE_CHECK(whether $CXX supports C++11 features with -std=c++11,
$cachevar,
[ac_save_CXXFLAGS="$CXXFLAGS"
CXXFLAGS="$CXXFLAGS -std=c++11"
AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_11_testbody])],
[eval $cachevar=yes],
[eval $cachevar=no])
CXXFLAGS="$ac_save_CXXFLAGS"])
if eval test x\$$cachevar = xyes; then
CXXFLAGS="$CXXFLAGS -std=c++11"
ac_success=yes
break
fi
fi
AC_LANG_POP([C++])
if test x$ac_success = xno; then
HAVE_CXX11=0
AC_MSG_NOTICE([No compiler with C++11 support was found])
else
HAVE_CXX11=1
AC_DEFINE(HAVE_CXX11,1,
[define if the compiler supports basic C++11 syntax])
fi
AC_SUBST(HAVE_CXX11)
])

View File

@ -0,0 +1,256 @@
0 319
8 322
16 315
24 302
32 309
40 315
48 310
56 309
64 309
72 314
80 317
88 302
96 290
104 298
112 303
120 293
128 301
136 306
144 303
152 299
160 300
168 298
176 302
184 298
192 300
200 308
208 293
216 298
224 296
232 297
240 307
248 293
256 293
264 291
272 295
280 300
288 296
296 292
304 299
312 288
320 287
328 299
336 305
344 302
352 294
360 295
368 290
376 290
384 294
392 297
400 280
408 288
416 302
424 306
432 301
440 291
448 296
456 301
464 303
472 290
480 307
488 294
496 302
504 302
512 299
520 297
528 300
536 292
544 300
552 295
560 299
568 291
576 306
584 308
592 308
600 313
608 309
616 303
624 307
632 308
640 309
648 307
656 305
664 316
672 308
680 303
688 323
696 309
704 307
712 318
720 312
728 326
736 327
744 325
752 332
760 346
768 328
776 327
784 339
792 344
800 340
808 347
816 339
824 349
832 343
840 349
848 360
856 357
864 361
872 363
880 368
888 363
896 369
904 373
912 370
920 382
928 384
936 391
944 392
952 415
960 409
968 408
976 431
984 441
992 438
1000 444
1008 461
1016 474
1024 398
1032 414
1040 430
1048 429
1056 435
1064 445
1072 444
1080 452
1088 449
1096 464
1104 472
1112 480
1120 479
1128 490
1136 492
1144 527
1152 521
1160 520
1168 549
1176 556
1184 563
1192 553
1200 588
1208 590
1216 600
1224 607
1232 622
1240 650
1248 670
1256 673
1264 689
1272 713
1280 693
1288 692
1296 716
1304 741
1312 766
1320 763
1328 789
1336 822
1344 810
1352 835
1360 868
1368 901
1376 911
1384 961
1392 989
1400 1028
1408 1035
1416 1081
1424 1116
1432 1153
1440 1199
1448 1263
1456 1353
1464 1401
1472 1422
1480 1477
1488 1603
1496 1633
1504 1718
1512 1815
1520 1878
1528 2065
1536 1725
1544 1791
1552 1850
1560 1956
1568 2040
1576 2141
1584 2249
1592 2396
1600 2459
1608 2563
1616 2683
1624 2842
1632 2973
1640 3133
1648 3276
1656 3459
1664 3425
1672 3585
1680 3714
1688 3906
1696 4011
1704 4194
1712 4366
1720 4616
1728 4735
1736 5003
1744 5209
1752 5439
1760 5619
1768 5848
1776 6111
1784 6405
1792 6121
1800 6343
1808 6597
1816 6795
1824 7033
1832 7312
1840 7499
1848 7816
1856 7961
1864 8181
1872 8463
1880 8671
1888 8988
1896 9251
1904 9593
1912 9950
1920 9990
1928 10290
1936 10590
1944 10910
1952 11173
1960 11465
1968 11770
1976 12103
1984 12272
1992 12635
2000 13012
2008 13357
2016 13614
2024 13973
2032 14315
2040 14871

View File

@ -0,0 +1,256 @@
0 337
8 364
16 360
24 373
32 380
40 392
48 398
56 403
64 413
72 419
80 422
88 420
96 439
104 443
112 451
120 442
128 467
136 462
144 467
152 480
160 483
168 497
176 508
184 517
192 519
200 533
208 554
216 558
224 560
232 561
240 586
248 594
256 563
264 585
272 589
280 608
288 633
296 638
304 659
312 650
320 666
328 673
336 690
344 716
352 711
360 734
368 753
376 772
384 758
392 807
400 797
408 809
416 796
424 834
432 828
440 846
448 847
456 857
464 884
472 884
480 928
488 1006
496 1029
504 1061
512 1022
520 1012
528 1000
536 1044
544 1106
552 1111
560 1105
568 1140
576 1139
584 1177
592 1228
600 1303
608 1316
616 1410
624 1462
632 1565
640 1545
648 1627
656 1668
664 1723
672 1759
680 1796
688 1924
696 1948
704 2027
712 2089
720 2140
728 2229
736 2342
744 2435
752 2611
760 2716
768 2602
776 2735
784 2820
792 2946
800 3062
808 3169
816 3263
824 3391
832 3425
840 3574
848 3694
856 3814
864 3933
872 4019
880 4170
888 4292
896 4252
904 4396
912 4445
920 4586
928 4748
936 4866
944 4966
952 5171
960 5233
968 5310
976 5376
984 5544
992 5633
1000 5695
1008 5826
1016 5954
1024 5324
1032 5448
1040 5492
1048 5643
1056 5658
1064 5792
1072 5846
1080 5914
1088 5981
1096 6062
1104 6200
1112 6261
1120 6322
1128 6493
1136 6563
1144 6665
1152 6681
1160 6720
1168 6828
1176 6942
1184 7015
1192 7195
1200 7242
1208 7290
1216 7415
1224 7498
1232 7585
1240 7796
1248 7874
1256 8118
1264 8224
1272 8446
1280 8379
1288 8484
1296 8563
1304 8742
1312 8877
1320 9168
1328 9343
1336 9535
1344 9644
1352 9926
1360 10144
1368 10517
1376 10706
1384 11055
1392 11329
1400 11664
1408 11564
1416 11824
1424 12037
1432 12326
1440 12416
1448 12644
1456 12997
1464 13345
1472 13466
1480 13742
1488 14084
1496 14330
1504 14593
1512 14841
1520 15163
1528 15494
1536 14783
1544 15022
1552 15224
1560 15508
1568 15680
1576 15944
1584 16121
1592 16456
1600 16559
1608 16812
1616 17005
1624 17294
1632 17533
1640 17745
1648 17886
1656 18137
1664 18136
1672 18454
1680 18555
1688 18701
1696 19005
1704 19116
1712 19354
1720 19640
1728 19688
1736 19989
1744 20189
1752 20368
1760 20593
1768 20763
1776 20961
1784 21119
1792 21076
1800 21227
1808 21378
1816 21385
1824 21562
1832 21691
1840 21870
1848 21966
1856 21997
1864 22122
1872 22255
1880 22442
1888 22409
1896 22546
1904 22642
1912 22585
1920 22588
1928 22646
1936 22698
1944 22799
1952 22807
1960 22796
1968 22919
1976 22888
1984 23022
1992 22928
2000 22954
2008 22896
2016 23017
2024 22917
2032 22763
2040 23139

View File

@ -0,0 +1,217 @@
/*
* This file is part of libsidplayfp, a SID player engine.
*
* Copyright 2011-2014 Leandro Nini <drfiemost@users.sourceforge.net>
* Copyright 2007-2010 Antti Lankila
* Copyright 2000 Simon White
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef SIDTUNEBASE_H
#define SIDTUNEBASE_H
#include <stdint.h>
#include <memory>
#include <vector>
#include <string>
#include "sidplayfp/SidTuneInfo.h"
#include "sidplayfp/siddefs.h"
#include "SidTuneCfg.h"
#include "SmartPtr.h"
#include "SidTuneInfoImpl.h"
#include "sidcxx11.h"
class sidmemory;
template <class T> class SmartPtr_sidtt;
namespace libsidplayfp
{
/**
* loadError
*/
class loadError
{
private:
const char* m_msg;
public:
loadError(const char* msg) : m_msg(msg) {}
const char* message() const { return m_msg; }
};
/**
* SidTuneBaseBase
*/
class SidTuneBase
{
protected:
typedef std::vector<uint_least8_t> buffer_t;
protected:
/// Also PSID file format limit.
static const unsigned int MAX_SONGS = 256;
static const char ERR_NOT_ENOUGH_MEMORY[];
static const char ERR_TRUNCATED[];
static const char ERR_INVALID[];
public: // ----------------------------------------------------------------
virtual ~SidTuneBase() {}
/**
* Load a sidtune from a file.
*
* To retrieve data from standard input pass in filename "-".
* If you want to override the default filename extensions use this
* contructor. Please note, that if the specified "sidTuneFileName"
* does exist and the loader is able to determine its file format,
* this function does not try to append any file name extension.
* See "sidtune.cpp" for the default list of file name extensions.
*/
static SidTuneBase* load(const char* fileName, const char **fileNameExt, bool separatorIsSlash);
/**
* Load a single-file sidtune from a memory buffer.
* Currently supported: PSID format
*/
static SidTuneBase* read(const uint_least8_t* sourceBuffer, uint_least32_t bufferLen);
/**
* Select sub-song (0 = default starting song)
* and return active song number out of [1,2,..,SIDTUNE_MAX_SONGS].
*/
unsigned int selectSong(unsigned int songNum);
/**
* Retrieve sub-song specific information.
*/
const SidTuneInfo* getInfo() const;
/**
* Select sub-song (0 = default starting song)
* and retrieve active song information.
*/
const SidTuneInfo* getInfo(unsigned int songNum);
/**
* Copy sidtune into C64 memory (64 KB).
*/
virtual bool placeSidTuneInC64mem(sidmemory* mem);
/**
* Calculates the MD5 hash of the tune.
* Not providing an md5 buffer will cause the internal one to be used.
* If provided, buffer must be MD5_LENGTH + 1
* @return a pointer to the buffer containing the md5 string.
*/
virtual const char *createMD5(char *) { return 0; }
protected: // -------------------------------------------------------------
std::unique_ptr<SidTuneInfoImpl> info;
uint_least8_t songSpeed[MAX_SONGS];
SidTuneInfo::clock_t clockSpeed[MAX_SONGS];
/// For files with header: offset to real data
uint_least32_t fileOffset;
buffer_t cache;
protected:
SidTuneBase();
/**
* Does not affect status of object, and therefore can be used
* to load files. Error string is put into info.statusString, though.
*/
static void loadFile(const char* fileName,buffer_t& bufferRef);
/**
* Convert 32-bit PSID-style speed word to internal tables.
*/
void convertOldStyleSpeedToTables(uint_least32_t speed,
SidTuneInfo::clock_t clock = SidTuneInfo::CLOCK_PAL);
/**
* Check compatibility details are sensible.
*/
bool checkCompatibility();
/**
* Check for valid relocation information.
*/
bool checkRelocInfo();
/**
* Common address resolution procedure.
*/
void resolveAddrs(const uint_least8_t* c64data);
/**
* Cache the data of a single-file or two-file sidtune and its
* corresponding file names.
*
* @param dataFileName
* @param infoFileName
* @param buf
* @param isSlashedFileName If your opendir() and readdir()->d_name return path names
* that contain the forward slash (/) as file separator, but
* your operating system uses a different character, there are
* extra functions that can deal with this special case. Set
* separatorIsSlash to true if you like path names to be split
* correctly.
* You do not need these extra functions if your systems file
* separator is the forward slash.
*/
virtual void acceptSidTune(const char* dataFileName, const char* infoFileName,
buffer_t& buf, bool isSlashedFileName);
class PetsciiToAscii
{
private:
std::string buffer;
public:
const char* convert(SmartPtr_sidtt<const uint_least8_t>& spPet);
};
private: // ---------------------------------------------------------------
#if !defined(SIDTUNE_NO_STDIN_LOADER)
static SidTuneBase* getFromStdIn();
#endif
static SidTuneBase* getFromFiles(const char* name, const char **fileNameExtensions, bool separatorIsSlash);
/**
* Try to retrieve single-file sidtune from specified buffer.
*/
static SidTuneBase* getFromBuffer(const uint_least8_t* const buffer, uint_least32_t bufferLen);
static void createNewFileName(std::string& destString,
const char* sourceName, const char* sourceExt);
private:
// prevent copying
SidTuneBase(const SidTuneBase&);
SidTuneBase& operator=(SidTuneBase&);
};
}
#endif /* SIDTUNEBASE_H */

View File

@ -0,0 +1,458 @@
/*
* This file is part of libsidplayfp, a SID player engine.
*
* Copyright 2011-2013 Leandro Nini <drfiemost@users.sourceforge.net>
* Copyright 2007-2010 Antti Lankila
* Copyright 2004,2010 Dag Lem <resid@nimrod.no>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef FILTER6581_H
#define FILTER6581_H
#include "siddefs-fp.h"
#include <memory>
#include "Filter.h"
#include "FilterModelConfig.h"
namespace reSIDfp
{
class Integrator;
/**
* The SID filter is modeled with a two-integrator-loop biquadratic filter,
* which has been confirmed by Bob Yannes to be the actual circuit used in
* the SID chip.
*
* Measurements show that excellent emulation of the SID filter is achieved,
* except when high resonance is combined with high sustain levels.
* In this case the SID op-amps are performing less than ideally and are
* causing some peculiar behavior of the SID filter. This however seems to
* have more effect on the overall amplitude than on the color of the sound.
*
* The theory for the filter circuit can be found in "Microelectric Circuits"
* by Adel S. Sedra and Kenneth C. Smith.
* The circuit is modeled based on the explanation found there except that
* an additional inverter is used in the feedback from the bandpass output,
* allowing the summer op-amp to operate in single-ended mode. This yields
* filter outputs with levels independent of Q, which corresponds with the
* results obtained from a real SID.
*
* We have been able to model the summer and the two integrators of the circuit
* to form components of an IIR filter.
* Vhp is the output of the summer, Vbp is the output of the first integrator,
* and Vlp is the output of the second integrator in the filter circuit.
*
* According to Bob Yannes, the active stages of the SID filter are not really
* op-amps. Rather, simple NMOS inverters are used. By biasing an inverter
* into its region of quasi-linear operation using a feedback resistor from
* input to output, a MOS inverter can be made to act like an op-amp for
* small signals centered around the switching threshold.
*
* In 2008, Michael Huth facilitated closer investigation of the SID 6581
* filter circuit by publishing high quality microscope photographs of the die.
* Tommi Lempinen has done an impressive work on re-vectorizing and annotating
* the die photographs, substantially simplifying further analysis of the
* filter circuit.
*
* The filter schematics below are reverse engineered from these re-vectorized
* and annotated die photographs. While the filter first depicted in reSID 0.9
* is a correct model of the basic filter, the schematics are now completed
* with the audio mixer and output stage, including details on intended
* relative resistor values. Also included are schematics for the NMOS FET
* voltage controlled resistors (VCRs) used to control cutoff frequency, the
* DAC which controls the VCRs, the NMOS op-amps, and the output buffer.
*
*
* SID filter / mixer / output
* ---------------------------
* ~~~
* ---------------------------------------------------
* | |
* | --1R1-- \-- D7 |
* | ---R1-- | | |
* | | | |--2R1-- \--| D6 |
* | ------------<A]-----| | $17 |
* | | |--4R1-- \--| D5 1=open | (3.5R1)
* | | | | |
* | | --8R1-- \--| D4 | (7.0R1)
* | | | |
* $17 | | (CAP2B) | (CAP1B) |
* 0=to mixer | --R8-- ---R8-- ---C---| ---C---|
* 1=to filter | | | | | | | |
* ------R8--|-----[A>--|--Rw-----[A>--|--Rw-----[A>--|
* ve (EXT IN) | | | |
* D3 \ ---------------R8--| | | (CAP2A) | (CAP1A)
* | v3 | | vhp | vbp | vlp
* D2 | \ -----------R8--| ----- | |
* | | v2 | | | |
* D1 | | \ -------R8--| | ---------------- |
* | | | v1 | | | |
* D0 | | | \ ---R8-- | | ---------------------------
* | | | | | | |
* R6 R6 R6 R6 R6 R6 R6
* | | | | $18 | | | $18
* | \ | | D7: 1=open \ \ \ D6 - D4: 0=open
* | | | | | | |
* --------------------------------- 12V
* |
* | D3 --/ --1R2-- |
* | ---R8-- | | ---R2-- |
* | | | D2 |--/ --2R2--| | | ||--
* ------[A>---------| |-----[A>-----||
* D1 |--/ --4R2--| (4.25R2) ||--
* $18 | | |
* 0=open D0 --/ --8R2-- (8.75R2) |
*
* vo (AUDIO
* OUT)
*
*
* v1 - voice 1
* v2 - voice 2
* v3 - voice 3
* ve - ext in
* vhp - highpass output
* vbp - bandpass output
* vlp - lowpass output
* vo - audio out
* [A> - single ended inverting op-amp (self-biased NMOS inverter)
* Rn - "resistors", implemented with custom NMOS FETs
* Rw - cutoff frequency resistor (VCR)
* C - capacitor
* ~~~
* Notes:
*
* R2 ~ 2.0*R1
* R6 ~ 6.0*R1
* R8 ~ 8.0*R1
* R24 ~ 24.0*R1
*
* The Rn "resistors" in the circuit are implemented with custom NMOS FETs,
* probably because of space constraints on the SID die. The silicon substrate
* is laid out in a narrow strip or "snake", with a strip length proportional
* to the intended resistance. The polysilicon gate electrode covers the entire
* silicon substrate and is fixed at 12V in order for the NMOS FET to operate
* in triode mode (a.k.a. linear mode or ohmic mode).
*
* Even in "linear mode", an NMOS FET is only an approximation of a resistor,
* as the apparant resistance increases with increasing drain-to-source
* voltage. If the drain-to-source voltage should approach the gate voltage
* of 12V, the NMOS FET will enter saturation mode (a.k.a. active mode), and
* the NMOS FET will not operate anywhere like a resistor.
*
*
*
* NMOS FET voltage controlled resistor (VCR)
* ------------------------------------------
* ~~~
* Vw
*
* |
* |
* R1
* |
* --R1--|
* | __|__
* | -----
* | | |
* vi ---------- -------- vo
* | |
* ----R24----
*
*
* vi - input
* vo - output
* Rn - "resistors", implemented with custom NMOS FETs
* Vw - voltage from 11-bit DAC (frequency cutoff control)
* ~~~
* Notes:
*
* An approximate value for R24 can be found by using the formula for the
* filter cutoff frequency:
*
* FCmin = 1/(2*pi*Rmax*C)
*
* Assuming that a the setting for minimum cutoff frequency in combination with
* a low level input signal ensures that only negligible current will flow
* through the transistor in the schematics above, values for FCmin and C can
* be substituted in this formula to find Rmax.
* Using C = 470pF and FCmin = 220Hz (measured value), we get:
*
* FCmin = 1/(2*pi*Rmax*C)
* Rmax = 1/(2*pi*FCmin*C) = 1/(2*pi*220*470e-12) ~ 1.5MOhm
*
* From this it follows that:
* R24 = Rmax ~ 1.5MOhm
* R1 ~ R24/24 ~ 64kOhm
* R2 ~ 2.0*R1 ~ 128kOhm
* R6 ~ 6.0*R1 ~ 384kOhm
* R8 ~ 8.0*R1 ~ 512kOhm
*
* Note that these are only approximate values for one particular SID chip,
* due to process variations the values can be substantially different in
* other chips.
*
*
*
* Filter frequency cutoff DAC
* ---------------------------
*
* ~~~
* 12V 10 9 8 7 6 5 4 3 2 1 0 VGND
* | | | | | | | | | | | | | Missing
* 2R 2R 2R 2R 2R 2R 2R 2R 2R 2R 2R 2R 2R termination
* | | | | | | | | | | | | |
* Vw ----R---R---R---R---R---R---R---R---R---R---R-- ---
*
*
* Bit on: 12V
* Bit off: 5V (VGND)
* ~~~
* As is the case with all MOS 6581 DACs, the termination to (virtual) ground
* at bit 0 is missing.
*
* Furthermore, the control of the two VCRs imposes a load on the DAC output
* which varies with the input signals to the VCRs. This can be seen from the
* VCR figure above.
*
*
*
* "Op-amp" (self-biased NMOS inverter)
* ------------------------------------
* ~~~
*
* 12V
*
* |
* -----------|
* | |
* | ------|
* | | |
* | | ||--
* | --||
* | ||--
* ||-- |
* vi -----|| |--------- vo
* ||-- | |
* | ||-- |
* |-------|| |
* | ||-- |
* ||-- | |
* --|| | |
* | ||-- | |
* | | | |
* | -----------| |
* | | |
* | |
* | GND |
* | |
* ----------------------
*
*
* vi - input
* vo - output
* ~~~
* Notes:
*
* The schematics above are laid out to show that the "op-amp" logically
* consists of two building blocks; a saturated load NMOS inverter (on the
* right hand side of the schematics) with a buffer / bias input stage
* consisting of a variable saturated load NMOS inverter (on the left hand
* side of the schematics).
*
* Provided a reasonably high input impedance and a reasonably low output
* impedance, the "op-amp" can be modeled as a voltage transfer function
* mapping input voltage to output voltage.
*
*
*
* Output buffer (NMOS voltage follower)
* -------------------------------------
* ~~~
*
* 12V
*
* |
* |
* ||--
* vi -----||
* ||--
* |
* |------ vo
* | (AUDIO
* Rext OUT)
* |
* |
*
* GND
*
* vi - input
* vo - output
* Rext - external resistor, 1kOhm
* ~~~
* Notes:
*
* The external resistor Rext is needed to complete the NMOS voltage follower,
* this resistor has a recommended value of 1kOhm.
*
* Die photographs show that actually, two NMOS transistors are used in the
* voltage follower. However the two transistors are coupled in parallel (all
* terminals are pairwise common), which implies that we can model the two
* transistors as one.
*/
class Filter6581 : public Filter
{
private:
/// Current volume amplifier setting.
unsigned short* currentGain;
/// Current filter/voice mixer setting.
unsigned short* currentMixer;
/// Filter input summer setting.
unsigned short* currentSummer;
/// Filter resonance value.
unsigned short* currentResonance;
const unsigned short* f0_dac;
unsigned short** mixer;
unsigned short** summer;
unsigned short** gain;
/// Filter highpass state.
int Vhp;
/// Filter bandpass state.
int Vbp;
/// Filter lowpass state.
int Vlp;
/// Filter external input.
int ve;
const int voiceScaleS14;
const int voiceDC;
/// VCR + associated capacitor connected to highpass output.
std::auto_ptr<Integrator> const hpIntegrator;
/// VCR + associated capacitor connected to lowpass output.
std::auto_ptr<Integrator> const bpIntegrator;
public:
Filter6581() :
currentGain(0),
currentMixer(0),
currentSummer(0),
currentResonance(0),
f0_dac(FilterModelConfig::getInstance()->getDAC(0.5)),
mixer(FilterModelConfig::getInstance()->getMixer()),
summer(FilterModelConfig::getInstance()->getSummer()),
gain(FilterModelConfig::getInstance()->getGain()),
Vhp(0),
Vbp(0),
Vlp(0),
ve(0),
voiceScaleS14(FilterModelConfig::getInstance()->getVoiceScaleS14()),
voiceDC(FilterModelConfig::getInstance()->getVoiceDC()),
hpIntegrator(FilterModelConfig::getInstance()->buildIntegrator()),
bpIntegrator(FilterModelConfig::getInstance()->buildIntegrator())
{
input(0);
}
~Filter6581();
int clock(int voice1, int voice2, int voice3);
void input(int sample) { ve = (sample * voiceScaleS14 * 3 >> 10) + mixer[0][0]; }
/**
* Set filter cutoff frequency.
*/
void updatedCenterFrequency();
/**
* Set filter resonance.
*
* In the MOS 6581, 1/Q is controlled linearly by res.
*/
void updatedResonance() { currentResonance = gain[~res & 0xf]; }
void updatedMixing();
public:
/**
* Set filter curve type based on single parameter.
*
* @param curvePosition 0 .. 1, where 0 sets center frequency high ("light") and 1 sets it low ("dark"), default is 0.5
*/
void setFilterCurve(double curvePosition);
};
} // namespace reSIDfp
#if RESID_INLINING || defined(FILTER6581_CPP)
#include "Integrator.h"
namespace reSIDfp
{
RESID_INLINE
int Filter6581::clock(int voice1, int voice2, int voice3)
{
voice1 = (voice1 * voiceScaleS14 >> 18) + voiceDC;
voice2 = (voice2 * voiceScaleS14 >> 18) + voiceDC;
voice3 = (voice3 * voiceScaleS14 >> 18) + voiceDC;
int Vi = 0;
int Vo = 0;
(filt1 ? Vi : Vo) += voice1;
(filt2 ? Vi : Vo) += voice2;
// NB! Voice 3 is not silenced by voice3off if it is routed
// through the filter.
if (filt3) Vi += voice3;
else if (!voice3off) Vo += voice3;
(filtE ? Vi : Vo) += ve;
const int oldVhp = Vhp;
Vhp = currentSummer[currentResonance[Vbp] + Vlp + Vi];
Vlp = bpIntegrator->solve(Vbp);
Vbp = hpIntegrator->solve(oldVhp);
if (lp) Vo += Vlp;
if (bp) Vo += Vbp;
if (hp) Vo += Vhp;
return currentGain[currentMixer[Vo]] - (1 << 15);
}
} // namespace reSIDfp
#endif
#endif

View File

@ -0,0 +1,438 @@
/*
* This file is part of libsidplayfp, a SID player engine.
*
* Copyright 2011-2013 Leandro Nini <drfiemost@users.sourceforge.net>
* Copyright 2007-2010 Antti Lankila
* Copyright 2000-2001 Simon White
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef SIDPLAYER_H
#define SIDPLAYER_H
static const uint8_t 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 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
};
#endif

View File

@ -0,0 +1,59 @@
/*
* This file is part of libsidplayfp, a SID player engine.
*
* Copyright 2012-2014 Leandro Nini <drfiemost@users.sourceforge.net>
* Copyright 2010 Antti Lankila
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef NULLSID_H
#define NULLSID_H
#include "c64/c64sid.h"
#include "sidcxx11.h"
namespace libsidplayfp
{
/**
* SID chip placeholder which does nothing and returns 0xff on reading.
*/
class NullSid : public c64sid
{
private:
NullSid() {}
virtual ~NullSid() {}
public:
/**
* Returns singleton instance.
*/
static NullSid *getInstance()
{
static NullSid nullsid;
return &nullsid;
}
void reset(uint8_t) override {}
void write(uint_least8_t, uint8_t) override {}
uint8_t read(uint_least8_t) override { return 0xff; }
};
}
#endif // NULLSID_H

View File

@ -0,0 +1,120 @@
#!/usr/bin/python
import struct, sys, wave
class UnsupportedWaveformat(Exception):
pass
class InvalidArgs(Exception):
pass
class AnalysisError(Exception):
pass
def split_wave(input, pattern, multiplier=8):
wv = wave.open(input, 'r')
if wv.getnchannels() != 1:
raise UnsupportedWaveformat, "mono audio only"
if wv.getsampwidth() != 2:
raise UnsupportedWaveformat, "16-bit pcm only"
readlen = 128
outhandle = None
seqnum = -1
frames = None
sum = 0
# highpass filter
levelcomp_coeff = (50 * 2 * 3.14159) / wv.getframerate()
levelcomp = 0
pos = 0
while True:
# read in chunks, classify as silence or as signal
datachar = wv.readframes(readlen)
pos += readlen
if frames is not None:
frames += readlen
# wave finish?
if len(datachar) < readlen * 2:
if outhandle is not None:
outhandle.writeframes(datachar)
outhandle.close();
cliplen = float(frames) / outhandle.getframerate()
print "End writing wave %d, %.1f s clip" % (seqnum, cliplen)
outhandle = None
break
# get wave values
datatuple = struct.unpack("%sh" % readlen, datachar)
# analyse signal levels.
_sum = 0
_min = 0
_max = 0
for _ in datatuple:
_ /= 32768.
if _ < _min:
_min = _
if _ > _max:
_max = _
levelcomp = _ * levelcomp_coeff + (1 - levelcomp_coeff) * levelcomp
_sum += (_ - levelcomp) ** 2
_sum /= readlen
sum = (sum * 15 + _sum) / 16;
start = _max > 0.2# or sum > 5e-7
end = _min < -0.2# or sum < 1e-7
# trigger silence
if end:
if outhandle is not None:
outhandle.close()
cliplen = float(frames) / outhandle.getframerate()
print "End writing wave %d, %.1f seconds" % (seqnum, cliplen)
if cliplen < 4:
raise AnalysisError, "sound prematurely clipped at %f" % (pos/outhandle.getframerate())
if cliplen > 6:
raise AnalysisError, "sound clipped too late at %f" % (pos/outhandle.getframerate())
outhandle = None
frames = 0
# trigger signal
if start:
if outhandle is None:
seqnum += 1
outhandle = wave.open(pattern % (multiplier * seqnum), "w")
outhandle.setnchannels(1)
outhandle.setframerate(wv.getframerate())
outhandle.setsampwidth(2);
if frames is not None:
cliplen = float(frames) / outhandle.getframerate()
print "Begun writing wave %d after %.1f s silence" % (seqnum, cliplen)
if cliplen < 0.05:
raise AnalysisError, "silence too short";
if cliplen > 1.5:
raise AnalysisError, "silence too long";
frames = 0
continue
# write if we got handle
if outhandle is not None:
outhandle.writeframes(datachar)
if seqnum != 2048 / multiplier - 1:
raise AnalysisError, "Wrong count of waves written. Results are probably invalid."
def main(args):
if len(args) != 2:
raise InvalidArgs, "Usage: program <inputfile> { lp | hp }"
return split_wave(args[0], args[1] + "_%04d.wav")
return 0
if __name__ == '__main__':
main(sys.argv[1:])

View File

@ -0,0 +1,470 @@
/*
* This file is part of sidplayfp, a console SID player.
*
* Copyright 2011-2014 Leandro Nini
* Copyright 2000-2001 Simon White
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "IniConfig.h"
#include <string>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cerrno>
#ifndef _WIN32
# include <sys/types.h>
# include <sys/stat.h> /* mkdir */
# include <dirent.h> /* opendir */
#else
# include <windows.h>
#endif
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#include "utils.h"
#include "ini/dataParser.h"
void debug(const TCHAR *msg)
{
#ifndef NDEBUG
SID_COUT << msg << std::endl;
#endif
}
const TCHAR *IniConfig::DIR_NAME = TEXT("sidplayfp");
const TCHAR *IniConfig::FILE_NAME = TEXT("sidplayfp.ini");
#define SAFE_FREE(p) { if(p) { free (p); (p)=NULL; } }
IniConfig::IniConfig() :
status(true)
{ // Initialise everything else
clear();
}
IniConfig::~IniConfig()
{
clear();
}
void IniConfig::clear()
{
sidplay2_s.version = 1; // INI File Version
sidplay2_s.database.clear();
sidplay2_s.playLength = 0; // INFINITE
sidplay2_s.recordLength = 3 * 60 + 30; // 3.5 minutes
sidplay2_s.kernalRom.clear();
sidplay2_s.basicRom.clear();
sidplay2_s.chargenRom.clear();
console_s.ansi = false;
console_s.topLeft = '+';
console_s.topRight = '+';
console_s.bottomLeft = '+';
console_s.bottomRight = '+';
console_s.vertical = '|';
console_s.horizontal = '-';
console_s.junctionLeft = '+';
console_s.junctionRight = '+';
audio_s.frequency = SidConfig::DEFAULT_SAMPLING_FREQ;
audio_s.playback = SidConfig::MONO;
audio_s.precision = 16;
emulation_s.modelDefault = SidConfig::PAL;
emulation_s.modelForced = false;
emulation_s.sidModel = SidConfig::MOS6581;
emulation_s.forceModel = false;
emulation_s.filter = true;
emulation_s.engine.clear();
emulation_s.bias = 0.0;
emulation_s.filterCurve6581 = 0.0;
emulation_s.filterCurve8580 = 0;
}
bool IniConfig::readDouble(iniHandler &ini, const TCHAR *key, double &result)
{
const TCHAR* value = ini.getValue(key);
if (value == 0)
{ // Doesn't exist, add it
ini.addValue(key, TEXT(""));
return false;
}
try
{
result = dataParser::parseDouble(value);
}
catch (dataParser::parseError const &e)
{
return false;
}
return true;
}
bool IniConfig::readInt(iniHandler &ini, const TCHAR *key, int &result)
{
const TCHAR* value = ini.getValue(key);
if (value == 0)
{ // Doesn't exist, add it
ini.addValue(key, TEXT(""));
return false;
}
try
{
result = dataParser::parseInt(value);
}
catch (dataParser::parseError const &e)
{
return false;
}
return true;
}
bool IniConfig::readString(iniHandler &ini, const TCHAR *key, SID_STRING &result)
{
const TCHAR* value = ini.getValue(key);
if (value == 0)
{ // Doesn't exist, add it
ini.addValue(key, TEXT(""));
return false;
}
result.assign(value);
return true;
}
bool IniConfig::readBool(iniHandler &ini, const TCHAR *key, bool &result)
{
const TCHAR* value = ini.getValue(key);
if (value == 0)
{ // Doesn't exist, add it
ini.addValue(key, TEXT(""));
return false;
}
try
{
result = dataParser::parseBool(value);
}
catch (dataParser::parseError const &e)
{
return false;
}
return true;
}
bool IniConfig::readChar(iniHandler &ini, const TCHAR *key, char &ch)
{
SID_STRING str;
bool ret = readString(ini, key, str);
if (!ret)
return false;
TCHAR c = 0;
// Check if we have an actual chanracter
if (str[0] == '\'')
{
if (str[2] != '\'')
ret = false;
else
c = str[1];
} // Nope is number
else
{
try
{
c = dataParser::parseInt(str.c_str());
}
catch (dataParser::parseError const &e)
{
return false;
}
}
// Clip off special characters
if ((unsigned) c >= 32)
ch = c;
return ret;
}
bool IniConfig::readTime(iniHandler &ini, const TCHAR *key, int &value)
{
SID_STRING str;
bool ret = readString(ini, key, str);
if (!ret)
return false;
int time;
size_t sep = str.find_first_of(':');
try
{
if (sep == SID_STRING::npos)
{ // User gave seconds
time = dataParser::parseInt(str.c_str());
}
else
{ // Read in MM:SS format
str.replace(sep, 1, '\0');
int val = dataParser::parseInt(str.c_str());
if (val < 0 || val > 99)
goto IniCofig_readTime_error;
time = val * 60;
val = dataParser::parseInt(str.c_str()+sep + 1);
if (val < 0 || val > 59)
goto IniCofig_readTime_error;
time += val;
}
}
catch (dataParser::parseError const &e)
{
return false;
}
value = time;
return ret;
IniCofig_readTime_error:
return false;
}
bool IniConfig::readSidplay2(iniHandler &ini)
{
if (!ini.setSection(TEXT("SIDPlayfp")))
ini.addSection(TEXT("SIDPlayfp"));
bool ret = true;
int version = sidplay2_s.version;
ret &= readInt (ini, TEXT("Version"), version);
if (version > 0)
sidplay2_s.version = version;
ret &= readString(ini, TEXT("Songlength Database"), sidplay2_s.database);
#if !defined _WIN32 && defined HAVE_UNISTD_H
if (sidplay2_s.database.empty())
{
char buffer[PATH_MAX];
snprintf(buffer, PATH_MAX, "%sSonglengths.txt", PKGDATADIR);
if (::access(buffer, R_OK) == 0)
sidplay2_s.database.assign(buffer);
}
#endif
int time;
if (readTime (ini, TEXT("Default Play Length"), time))
sidplay2_s.playLength = (uint_least32_t) time;
if (readTime (ini, TEXT("Default Record Length"), time))
sidplay2_s.recordLength = (uint_least32_t) time;
ret &= readString(ini, TEXT("Kernal Rom"), sidplay2_s.kernalRom);
ret &= readString(ini, TEXT("Basic Rom"), sidplay2_s.basicRom);
ret &= readString(ini, TEXT("Chargen Rom"), sidplay2_s.chargenRom);
return ret;
}
bool IniConfig::readConsole(iniHandler &ini)
{
if (!ini.setSection (TEXT("Console")))
ini.addSection(TEXT("Console"));
bool ret = true;
ret &= readBool (ini, TEXT("Ansi"), console_s.ansi);
ret &= readChar (ini, TEXT("Char Top Left"), console_s.topLeft);
ret &= readChar (ini, TEXT("Char Top Right"), console_s.topRight);
ret &= readChar (ini, TEXT("Char Bottom Left"), console_s.bottomLeft);
ret &= readChar (ini, TEXT("Char Bottom Right"), console_s.bottomRight);
ret &= readChar (ini, TEXT("Char Vertical"), console_s.vertical);
ret &= readChar (ini, TEXT("Char Horizontal"), console_s.horizontal);
ret &= readChar (ini, TEXT("Char Junction Left"), console_s.junctionLeft);
ret &= readChar (ini, TEXT("Char Junction Right"), console_s.junctionRight);
return ret;
}
bool IniConfig::readAudio(iniHandler &ini)
{
if (!ini.setSection (TEXT("Audio")))
ini.addSection(TEXT("Audio"));
bool ret = true;
{
int frequency = (int) audio_s.frequency;
ret &= readInt (ini, TEXT("Frequency"), frequency);
audio_s.frequency = (unsigned long) frequency;
}
{
int channels = 0;
ret &= readInt (ini, TEXT("Channels"), channels);
if (channels)
{
audio_s.playback = (channels == 1) ? SidConfig::MONO : SidConfig::STEREO;
}
}
ret &= readInt (ini, TEXT("BitsPerSample"), audio_s.precision);
return ret;
}
bool IniConfig::readEmulation(iniHandler &ini)
{
if (!ini.setSection (TEXT("Emulation")))
ini.addSection(TEXT("Emulation"));
bool ret = true;
ret &= readString (ini, TEXT("Engine"), emulation_s.engine);
{
SID_STRING str;
const bool res = readString (ini, TEXT("C64Model"), str);
if (res)
{
if (str.compare(TEXT("PAL")) == 0)
emulation_s.modelDefault = SidConfig::PAL;
else if (str.compare(TEXT("NTSC")) == 0)
emulation_s.modelDefault = SidConfig::NTSC;
else if (str.compare(TEXT("OLD_NTSC")) == 0)
emulation_s.modelDefault = SidConfig::OLD_NTSC;
else if (str.compare(TEXT("DREAN")) == 0)
emulation_s.modelDefault = SidConfig::DREAN;
}
ret &= res;
}
ret &= readBool (ini, TEXT("ForceC64Model"), emulation_s.modelForced);
{
SID_STRING str;
const bool res = readString (ini, TEXT("SidModel"), str);
if (res)
{
if (str.compare(TEXT("MOS6581")) == 0)
emulation_s.sidModel = SidConfig::MOS6581;
else if (str.compare(TEXT("MOS8580")) == 0)
emulation_s.sidModel = SidConfig::MOS8580;
}
ret &= res;
}
ret &= readBool (ini, TEXT("ForceSidModel"), emulation_s.forceModel);
ret &= readBool (ini, TEXT("UseFilter"), emulation_s.filter);
ret &= readDouble (ini, TEXT("FilterBias"), emulation_s.bias);
ret &= readDouble (ini, TEXT("FilterCurve6581"), emulation_s.filterCurve6581);
ret &= readInt (ini, TEXT("FilterCurve8580"), emulation_s.filterCurve8580);
return ret;
}
void IniConfig::read()
{
clear();
status = false;
SID_STRING configPath;
try
{
configPath = utils::getConfigPath();
}
catch (utils::error const &e)
{
debug(TEXT("Cannot get config path!"));
return;
}
configPath.append(SEPARATOR).append(DIR_NAME);
// Make sure the config path exists
#ifndef _WIN32
if (!opendir(configPath.c_str()))
{
if (mkdir(configPath.c_str(), 0755) < 0)
{
debug(strerror(errno));
return;
}
}
#else
if (GetFileAttributes(configPath.c_str()) == INVALID_FILE_ATTRIBUTES)
{
if (CreateDirectory(configPath.c_str(), NULL) == 0)
{
LPTSTR pBuffer;
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&pBuffer, 0, NULL);
debug(pBuffer);
LocalFree(pBuffer);
return;
}
}
#endif
configPath.append(SEPARATOR).append(FILE_NAME);
//debug(configPath.c_str());
iniHandler ini;
// Opens an existing file or creates a new one
if (!ini.open(configPath.c_str()))
{
debug(TEXT("Error reading config file!"));
return;
}
status = true;
status &= readSidplay2 (ini);
status &= readConsole (ini);
status &= readAudio (ini);
status &= readEmulation (ini);
ini.close();
}

View File

@ -0,0 +1,96 @@
#!/usr/bin/python
import os, sys, math, glob
def read_xy_file(filename, offset):
f = file(filename)
vals = []
for line in f:
x, y = line.split()
x = float(x)
y = float(y)
vals.append([x, y + offset(x, y)])
return vals
def main():
fftdir = sys.argv[1]
fnlp = "%s/lp_%%04d.wav.fft" % fftdir
fnhp = "%s/hp_%%04d.wav.fft" % fftdir
cutoffs = [];
for x in range(0, 2047):
if not os.path.exists(fnlp % x):
continue
cutoffs.append(x)
result = []
for cf in cutoffs:
# no correction function, but we should also dump
# the difference between lp and hp.
lp = read_xy_file(fnlp % cf, lambda x, y: 0)
hp = read_xy_file(fnhp % cf, lambda x, y: 0)
noise_threshold = 3
cf_est = 0
cf_n = 0
lens = range(len(lp))
for i in lens:
if lp[i][0] != hp[i][0]:
raise RuntimeError, "invalid content in cf %d" % cf
# zrx has a weird chip with freq ~ 140 Hz!
if lp[i][0] < 120 or lp[i][0] > 20000:
continue
# disregard video signal spikes and some side spikes, unknown
# origin... the 4900 Hz spike seems to multiply
if lp[i][0] > 4500 and lp[i][0] < 4600:
continue
if lp[i][0] > 4800 and lp[i][0] < 4900:
continue
if lp[i][0] > 6650 and lp[i][0] < 6750:
continue
if lp[i][0] > 9740 and lp[i][0] < 9860:
continue
if lp[i][0] > 15600 and lp[i][0] < 15800:
continue
if lp[i][0] > 19500 and lp[i][0] < 19650:
continue
if lp[i][0] > 20150 and lp[i][0] < 20250:
continue
if lp[i][0] > 10050 and lp[i][0] < 10150:
continue
if abs(lp[i][1] - hp[i][1]) > noise_threshold:
continue
# this is ad-hoc weighing method. The values closer to crossing
# point get more weight. The right model might be logarithmic, not ** 2.
weight = noise_threshold - abs(lp[i][1] - hp[i][1]);
weight = weight ** 2
cf_est += weight * lp[i][0];
cf_n += weight;
# dump average
if cf_n == 0:
cf_n = 1
source = "%d,%d" % (cf, cf_est / cf_n)
result.append(source)
for i in range(len(result)):
print result[i].replace(",", " ")
return
print "[FilterMeasurement]"
print "type=1"
print "points=%d" % len(result)
for i in range(len(result)):
print "point%d=%s" % (i+1, result[i])
if __name__ == '__main__':
main()

View File

@ -0,0 +1,59 @@
/*
* This file is part of libsidplayfp, a SID player engine.
*
* Copyright (C) 2011-2014 Leandro Nini
* Copyright (C) 2009 Antti S. Lankila
* Copyright (C) 2001 Simon White
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "EventScheduler.h"
void EventScheduler::reset()
{
firstEvent = nullptr;
currentTime = 0;
}
void EventScheduler::cancel(Event &event)
{
Event **scan = &firstEvent;
while (*scan != nullptr)
{
if (&event == *scan)
{
*scan = (*scan)->next;
break;
}
scan = &((*scan)->next);
}
}
bool EventScheduler::isPending(Event &event) const
{
Event *scan = firstEvent;
while (scan != nullptr)
{
if (&event == scan)
{
return true;
}
scan = scan->next;
}
return false;
}

View File

@ -0,0 +1,687 @@
/*
* This file is part of libsidplayfp, a SID player engine.
*
* Copyright 2011-2014 Leandro Nini <drfiemost@users.sourceforge.net>
* Copyright 2009-2014 VICE Project
* Copyright 2007-2010 Antti Lankila
* Copyright 2001 Simon White
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
// References below are from:
// The MOS 6567/6569 video controller (VIC-II)
// and its application in the Commodore 64
// http://www.uni-mainz.de/~bauec002/VIC-Article.gz
#include "mos656x.h"
#include <cstring>
#include "sidendian.h"
namespace libsidplayfp
{
/// Cycle # at which the VIC takes the bus in a bad line (BA goes low).
const unsigned int VICII_FETCH_CYCLE = 11;
const unsigned int VICII_SCREEN_TEXTCOLS = 40;
const MOS656X::model_data_t MOS656X::modelData[] =
{
{262, 64, &MOS656X::clockOldNTSC}, // Old NTSC
{263, 65, &MOS656X::clockNTSC}, // NTSC-M
{312, 63, &MOS656X::clockPAL}, // PAL-B
{312, 65, &MOS656X::clockNTSC}, // PAL-N
};
const char *MOS656X::credit =
{
"MOS6567/6569/6572 (VIC II) Emulation:\n"
"\tCopyright (C) 2001 Simon White\n"
"\tCopyright (C) 2007-2010 Antti Lankila\n"
"\tCopyright (C) 2009-2014 VICE Project\n"
"\tCopyright (C) 2011-2014 Leandro Nini\n"
};
MOS656X::MOS656X(EventContext *context) :
Event("VIC Raster"),
event_context(*context),
sprites(regs),
badLineStateChangeEvent("Update AEC signal", *this, &MOS656X::badLineStateChange),
rasterYIRQEdgeDetectorEvent("RasterY changed", *this, &MOS656X::rasterYIRQEdgeDetector)
{
chip(MOS6569);
}
void MOS656X::reset()
{
irqFlags = 0;
irqMask = 0;
yscroll = 0;
rasterY = maxRasters - 1;
lineCycle = 0;
areBadLinesEnabled = false;
isBadLine = false;
rasterYIRQCondition = false;
rasterClk = 0;
vblanking = false;
lpAsserted = false;
memset(regs, 0, sizeof(regs));
lp.reset();
sprites.reset();
event_context.cancel(*this);
event_context.schedule(*this, 0, EVENT_CLOCK_PHI1);
}
void MOS656X::chip(model_t model)
{
maxRasters = modelData[model].rasterLines;
cyclesPerLine = modelData[model].cyclesPerLine;
clock = modelData[model].clock;
lp.setScreenSize(maxRasters, cyclesPerLine);
reset();
}
uint8_t MOS656X::read(uint_least8_t addr)
{
addr &= 0x3f;
// Sync up timers
sync();
switch (addr)
{
case 0x11:
// Control register 1
return (regs[addr] & 0x7f) | ((rasterY & 0x100) >> 1);
case 0x12:
// Raster counter
return rasterY & 0xFF;
case 0x13:
return lp.getX();
case 0x14:
return lp.getY();
case 0x19:
// Interrupt Pending Register
return irqFlags | 0x70;
case 0x1a:
// Interrupt Mask Register
return irqMask | 0xf0;
default:
// for addresses < $20 read from register directly, when < $2f set
// bits of high nibble to 1, for >= $2f return $ff
if (addr < 0x20)
return regs[addr];
if (addr < 0x2f)
return regs[addr] | 0xf0;
return 0xff;
}
}
void MOS656X::write(uint_least8_t addr, uint8_t data)
{
addr &= 0x3f;
regs[addr] = data;
// Sync up timers
sync();
switch (addr)
{
case 0x11: // Control register 1
{
const unsigned int oldYscroll = yscroll;
yscroll = data & 0x7;
// This is the funniest part... handle bad line tricks.
const bool wasBadLinesEnabled = areBadLinesEnabled;
if (rasterY == FIRST_DMA_LINE && lineCycle == 0)
{
areBadLinesEnabled = readDEN();
}
if (oldRasterY() == FIRST_DMA_LINE && readDEN())
{
areBadLinesEnabled = true;
}
if ((oldYscroll != yscroll || areBadLinesEnabled != wasBadLinesEnabled)
&& rasterY >= FIRST_DMA_LINE
&& rasterY <= LAST_DMA_LINE)
{
// Check whether bad line state has changed.
const bool wasBadLine = (wasBadLinesEnabled && (oldYscroll == (rasterY & 7)));
const bool nowBadLine = (areBadLinesEnabled && (yscroll == (rasterY & 7)));
const bool oldBadLine = isBadLine;
if (wasBadLine && !nowBadLine)
{
if (lineCycle < VICII_FETCH_CYCLE)
{
isBadLine = false;
}
}
else if (!wasBadLine && nowBadLine)
{
if (lineCycle >= VICII_FETCH_CYCLE
&& lineCycle < VICII_FETCH_CYCLE + VICII_SCREEN_TEXTCOLS + 3)
{
isBadLine = true;
}
else if (lineCycle <= VICII_FETCH_CYCLE + VICII_SCREEN_TEXTCOLS + 6)
{
// Bad line has been generated after fetch interval, but
// before the raster counter is incremented.
isBadLine = true;
}
}
if (isBadLine != oldBadLine)
event_context.schedule(badLineStateChangeEvent, 0, EVENT_CLOCK_PHI1);
}
}
// fall-through
case 0x12: // Raster counter
// check raster Y irq condition changes at the next PHI1
event_context.schedule(rasterYIRQEdgeDetectorEvent, 0, EVENT_CLOCK_PHI1);
break;
case 0x17:
sprites.lineCrunch(data, lineCycle);
break;
case 0x19:
// VIC Interrupt Flag Register
irqFlags &= (~data & 0x0f) | 0x80;
handleIrqState();
break;
case 0x1a:
// IRQ Mask Register
irqMask = data & 0x0f;
handleIrqState();
break;
}
}
void MOS656X::handleIrqState()
{
// signal an IRQ unless we already signaled it
if ((irqFlags & irqMask & 0x0f) != 0)
{
if ((irqFlags & 0x80) == 0)
{
interrupt(true);
irqFlags |= 0x80;
}
}
else if ((irqFlags & 0x80) != 0)
{
interrupt(false);
irqFlags &= 0x7f;
}
}
void MOS656X::event()
{
const event_clock_t cycles = event_context.getTime(rasterClk, event_context.phase());
event_clock_t delay;
if (cycles)
{
// Update x raster
rasterClk += cycles;
lineCycle += cycles;
lineCycle %= cyclesPerLine;
delay = (this->*clock)();
}
else
delay = 1;
event_context.schedule(*this, delay - event_context.phase(), EVENT_CLOCK_PHI1);
}
event_clock_t MOS656X::clockPAL()
{
event_clock_t delay = 1;
switch (lineCycle)
{
case 0:
checkVblank();
endDma<2>();
break;
case 1:
vblank();
startDma<5>();
// No sprites before next compulsory cycle
if (!sprites.isDma(0xf8))
delay = 10;
break;
case 2:
endDma<3>();
break;
case 3:
startDma<6>();
break;
case 4:
endDma<4>();
break;
case 5:
startDma<7>();
break;
case 6:
endDma<5>();
delay = sprites.isDma(0xc0) ? 2 : 4;
break;
case 7:
break;
case 8:
endDma<6>();
delay = 2;
break;
case 9:
break;
case 10:
sprites.updateMc();
endDma<7>();
break;
case 11:
startBadline();
delay = 4;
break;
case 12:
delay = 3;
break;
case 13:
delay = 2;
break;
case 14:
break;
case 15:
sprites.updateMcBase();
delay = 39;
break;
case 54:
sprites.checkDma(rasterY, regs);
startDma<0>();
break;
case 55:
sprites.checkDma(rasterY, regs);
sprites.checkExp();
startDma<0>();
break;
case 56:
startDma<1>();
break;
case 57:
sprites.checkDisplay();
// No sprites before next compulsory cycle
if (!sprites.isDma(0x1f))
delay = 6;
break;
case 58:
startDma<2>();
break;
case 59:
endDma<0>();
break;
case 60:
startDma<3>();
break;
case 61:
endDma<1>();
break;
case 62:
startDma<4>();
break;
default:
delay = 54 - lineCycle;
}
return delay;
}
event_clock_t MOS656X::clockNTSC()
{
event_clock_t delay = 1;
switch (lineCycle)
{
case 0:
checkVblank();
startDma<5>();
break;
case 1:
vblank();
endDma<3>();
// No sprites before next compulsory cycle
if (!sprites.isDma(0xf8))
delay = 10;
break;
case 2:
startDma<6>();
break;
case 3:
endDma<4>();
break;
case 4:
startDma<7>();
break;
case 5:
endDma<5>();
delay = sprites.isDma(0xc0) ? 2 : 4;
break;
case 6:
break;
case 7:
endDma<6>();
delay = 2;
break;
case 8:
break;
case 9:
sprites.updateMc();
endDma<7>();
delay = 2;
break;
case 10:
break;
case 11:
startBadline();
delay = 4;
break;
case 12:
delay = 3;
break;
case 13:
delay = 2;
break;
case 14:
break;
case 15:
sprites.updateMcBase();
delay = 40;
break;
case 55:
sprites.checkDma(rasterY, regs);
sprites.checkExp();
startDma<0>();
break;
case 56:
sprites.checkDma(rasterY, regs);
startDma<0>();
break;
case 57:
startDma<1>();
break;
case 58:
sprites.checkDisplay();
// No sprites before next compulsory cycle
if (!sprites.isDma(0x1f))
delay = 7;
break;
case 59:
startDma<2>();
break;
case 60:
endDma<0>();
break;
case 61:
startDma<3>();
break;
case 62:
endDma<1>();
break;
case 63:
startDma<4>();
break;
case 64:
endDma<2>();
break;
default:
delay = 55 - lineCycle;
}
return delay;
}
event_clock_t MOS656X::clockOldNTSC()
{
event_clock_t delay = 1;
switch (lineCycle)
{
case 0:
checkVblank();
endDma<2>();
break;
case 1:
vblank();
startDma<5>();
// No sprites before next compulsory cycle
if (!sprites.isDma(0xf8))
delay = 10;
break;
case 2:
endDma<3>();
break;
case 3:
startDma<6>();
break;
case 4:
endDma<4>();
break;
case 5:
startDma<7>();
break;
case 6:
endDma<5>();
delay = sprites.isDma(0xc0) ? 2 : 4;
break;
case 7:
break;
case 8:
endDma<6>();
delay = 2;
break;
case 9:
break;
case 10:
sprites.updateMc();
endDma<7>();
break;
case 11:
startBadline();
delay = 4;
break;
case 12:
delay = 3;
break;
case 13:
delay = 2;
break;
case 14:
break;
case 15:
sprites.updateMcBase();
delay = 40;
break;
case 55:
sprites.checkDma(rasterY, regs);
sprites.checkExp();
startDma<0>();
break;
case 56:
sprites.checkDma(rasterY, regs);
startDma<0>();
break;
case 57:
sprites.checkDisplay();
startDma<1>();
delay = (!sprites.isDma(0x1f)) ? 7 : 2;
break;
case 58:
break;
case 59:
startDma<2>();
break;
case 60:
endDma<0>();
break;
case 61:
startDma<3>();
break;
case 62:
endDma<1>();
break;
case 63:
startDma<4>();
break;
default:
delay = 55 - lineCycle;
}
return delay;
}
void MOS656X::triggerLightpen()
{
// Synchronise simulation
sync();
lpAsserted = true;
if (lp.trigger(lineCycle, rasterY))
{
activateIRQFlag(IRQ_LIGHTPEN);
}
}
void MOS656X::clearLightpen()
{
lpAsserted = false;
}
}

View File

@ -0,0 +1,75 @@
libsidplayfp
============
http://sourceforge.net/projects/sidplay-residfp/
libsidplayfp is a fork of LIBSIDPLAY2, a C64 music player library which
integrates the reSID SID chip emulation into a cycle-based emulator
environment, started with primary purpose to improve emulation of the
C64 system and the SID chips.
Copyright (c) 2000-2001 Simon White
Copyright (c) 2007-2010 Antti Lankila
Copyright (c) 2010-2014 Leandro Nini <drfiemost@users.sourceforge.net>
-----------------------------------------------------------------------------
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-----------------------------------------------------------------------------
* Build
This package uses autotools so the usual ./configure && make is enough to build
the libraries.
In addition to the standard options the following are available:
--enable-debug[=no/yes/full]
compile with debugging messages
disabled by default
--enable-inline
enable inlinig in reSID engine, increases performances at the expense of bigger code size
enabled by default
--enable-branch-hints
enable branch hints in reSID engine so the compiler can produce more optimized code
enabled by default
--enable-mmx
enable some MMX code in reSIDfp that increases performance on old x86 processors which lack
sse2 support
disabled by default
--enable-testsuite=PATH_TO_TESTSUITE
add support for running Lorenz testsuite (in prg format). The testsuite is available
in the svn repository. Intended only for regression tests since it may break normal
code execution. The path to testsuite must include terminal path separator
disabled by default
--enable-tests
enables unit tests. Requires libUnitTest++ installed. Use "make check" to launch the testsuite
disabled by default
If doxygen is installed and detected by the configure script the documentation
can be built by invoking "make doc".
Known bugs/limitations:
* mus data embedded in psid file is not supported
* hardsid support is untested and possibly broken

View File

@ -0,0 +1,163 @@
/*
* This file is part of libsidplayfp, a SID player engine.
*
* Copyright 2011-2014 Leandro Nini <drfiemost@users.sourceforge.net>
* Copyright 2007-2010 Antti Lankila
* Copyright 2001 Simon White
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "residfp-emu.h"
#include <sstream>
#include <string>
#include <algorithm>
#include "residfp/siddefs-fp.h"
#include "sidplayfp/siddefs.h"
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
const char* ReSIDfp::getCredits()
{
if (m_credit.empty())
{
// Setup credits
std::ostringstream ss;
ss << "ReSIDfp V" << VERSION << " Engine:\n";
ss << "\t(C) 1999-2002 Simon White\n";
ss << "MOS6581 (SID) Emulation (ReSIDfp V" << residfp_version_string << "):\n";
ss << "\t(C) 1999-2002 Dag Lem\n";
ss << "\t(C) 2005-2011 Antti S. Lankila\n";
m_credit = ss.str();
}
return m_credit.c_str();
}
ReSIDfp::ReSIDfp(sidbuilder *builder) :
sidemu(builder),
m_sid(*(new RESID_NAMESPACE::SID))
{
m_buffer = new short[OUTPUTBUFFERSIZE];
reset(0);
}
ReSIDfp::~ReSIDfp()
{
delete &m_sid;
delete[] m_buffer;
}
void ReSIDfp::filter6581Curve(double filterCurve)
{
m_sid.setFilter6581Curve(filterCurve);
}
void ReSIDfp::filter8580Curve(double filterCurve)
{
m_sid.setFilter8580Curve(filterCurve);
}
// Standard component options
void ReSIDfp::reset(uint8_t volume)
{
m_accessClk = 0;
m_sid.reset();
m_sid.write(0x18, volume);
}
uint8_t ReSIDfp::read(uint_least8_t addr)
{
clock();
return m_sid.read(addr);
}
void ReSIDfp::write(uint_least8_t addr, uint8_t data)
{
clock();
m_sid.write(addr, data);
}
void ReSIDfp::clock()
{
const event_clock_t cycles = m_context->getTime(m_accessClk, EVENT_CLOCK_PHI1);
m_accessClk += cycles;
m_bufferpos += m_sid.clock(cycles, m_buffer+m_bufferpos);
}
void ReSIDfp::filter(bool enable)
{
m_sid.enableFilter(enable);
}
void ReSIDfp::sampling(float systemclock, float freq,
SidConfig::sampling_method_t method, bool)
{
reSIDfp::SamplingMethod sampleMethod;
switch (method)
{
case SidConfig::INTERPOLATE:
sampleMethod = reSIDfp::DECIMATE;
break;
case SidConfig::RESAMPLE_INTERPOLATE:
sampleMethod = reSIDfp::RESAMPLE;
break;
default:
m_status = false;
m_error = ERR_INVALID_SAMPLING;
return;
}
try
{
// Round half frequency to the nearest multiple of 5000
const int halfFreq = 5000*((static_cast<int>(freq)+5000)/10000);
m_sid.setSamplingParameters(systemclock, sampleMethod, freq, std::min(halfFreq, 20000));
}
catch (RESID_NAMESPACE::SIDError const &)
{
m_status = false;
m_error = ERR_UNSUPPORTED_FREQ;
return;
}
m_status = true;
}
// Set the emulated SID model
void ReSIDfp::model(SidConfig::sid_model_t model)
{
reSIDfp::ChipModel chipModel;
switch (model)
{
case SidConfig::MOS6581:
chipModel = reSIDfp::MOS6581;
break;
case SidConfig::MOS8580:
chipModel = reSIDfp::MOS8580;
break;
default:
m_status = false;
m_error = ERR_INVALID_CHIP;
return;
}
m_sid.setChipModel(chipModel);
m_status = true;
}

View File

@ -0,0 +1,50 @@
/*
* This file is part of libsidplayfp, a SID player engine.
*
* Copyright 2014 Leandro Nini <drfiemost@users.sourceforge.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef MD5_INTERNAL_H
#define MD5_INTERNAL_H
#include "iMd5.h"
#include "MD5/MD5.h"
#include "sidcxx11.h"
namespace libsidplayfp
{
class md5Internal : public iMd5
{
private:
MD5 hd;
public:
void append(const void* data, int nbytes) override { hd.append(data, nbytes); }
void finish() override { hd.finish(); }
const unsigned char* getDigest() override { return hd.getDigest(); }
void reset() override { hd.reset(); }
};
}
#endif

View File

@ -0,0 +1,218 @@
/*
* This file is part of libsidplayfp, a SID player engine.
*
* Copyright 2013 Leandro Nini <drfiemost@users.sourceforge.net>
* Copyright 2007-2010 Antti Lankila
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef PARAMETERS_H
#define PARAMETERS_H
#include <vector>
#include <string>
#include <sstream>
class Parameters
{
public:
enum
{
BIAS,
PULSESTRENGTH,
TOPBIT,
DISTANCE,
STMIX
};
public:
float bias, pulsestrength, topbit, distance, stmix;
public:
Parameters() { reset(); }
void reset()
{
bias = 0.f;
pulsestrength = 0.f;
topbit = 0.f;
distance = 0.f;
stmix = 0.f;
}
float GetValue(int i)
{
switch (i)
{
case BIAS: return bias;
case PULSESTRENGTH: return pulsestrength;
case TOPBIT: return topbit;
case DISTANCE: return distance;
case STMIX: return stmix;
}
}
void SetValue(int i, float v)
{
switch (i)
{
case BIAS: bias = v; break;
case PULSESTRENGTH: pulsestrength = v; break;
case TOPBIT: topbit = v; break;
case DISTANCE: distance = v; break;
case STMIX: stmix = v; break;
}
}
std::string toString()
{
std::ostringstream ss;
ss << "bias = " << bias << std::endl;
ss << "pulsestrength = " << pulsestrength << std::endl;
ss << "topbit = " << topbit << std::endl;
ss << "distance = " << distance << std::endl;
ss << "stmix = " << stmix << std::endl;
return ss.str();
}
private:
void SimulateMix(float bitarray[12], float wa[], bool HasPulse)
{
float tmp[12];
for (int sb = 0; sb < 12; sb ++)
{
float n = 0.f;
float avg = 0.f;
for (int cb = 0; cb < 12; cb ++)
{
const float weight = wa[sb - cb + 12];
avg += bitarray[cb] * weight;
n += weight;
}
if (HasPulse)
{
const float weight = wa[sb - 12 + 12];
avg += pulsestrength * weight;
n += weight;
}
tmp[sb] = (bitarray[sb] + avg / n) * 0.5f;
}
for (int i = 0; i < 12; i ++)
bitarray[i] = tmp[i];
}
int GetScore8(float bitarray[12])
{
int result = 0;
for (int cb = 0; cb < 8; cb ++)
{
if (bitarray[4+cb] > bias)
result |= 1 << cb;
}
return result;
}
static int ScoreResult(int a, int b)
{
// audible error
int v = a ^ b;
return v;
/* int c = 0;
while (v != 0)
{
v &= v - 1;
c ++;
}
return c;
*/
}
public:
int Score(int wave, const std::vector<int> &reference, bool print, int bestscore)
{
int score = 0;
float wa[12 + 12 + 1];
for (int i = 0; i <= 12; i ++)
{
wa[12-i] = wa[12+i] = 1.0f / (1.0f + i * i * distance);
}
for (int j = 4095; j >= 0; j --)
{
/* S */
float bitarray[12];
for (int i = 0; i < 12; i ++)
bitarray[i] = (j & (1 << i)) != 0 ? 1.f : 0.f;
/* T */
if ((wave & 3) == 1)
{
const bool top = (j & 2048) != 0;
for (int i = 11; i > 0; i --)
{
bitarray[i] = top ? 1.f - bitarray[i-1] : bitarray[i-1];
}
bitarray[0] = 0.f;
}
/* ST */
if ((wave & 3) == 3)
{
bitarray[0] *= stmix;
for (int i = 1; i < 12; i ++)
{
bitarray[i] = bitarray[i-1] * (1.f - stmix) + bitarray[i] * stmix;
}
}
bitarray[11] *= topbit;
SimulateMix(bitarray, wa, wave > 4);
const int simval = GetScore8(bitarray);
const int refval = reference[j];
score += ScoreResult(simval, refval);
if (print)
{
float analogval = 0.f;
for (int i = 0; i < 12; i ++)
{
float val = (bitarray[i] - bias) * 512 + 0.5f;
if (val < 0.f)
val = 0.f;
else if (val > 1.f)
val = 1.f;
analogval += val * (1 << i);
}
analogval /= 16.f;
std::cout << j << " "
<< refval << " "
<< simval << " "
<< analogval << " "
<< std::endl;
}
if (score > bestscore)
{
return score;
}
}
return score;
}
};
#endif

View File

@ -0,0 +1,69 @@
#!/usr/bin/python
import math, random
from scipy.fftpack import fft
from scipy import array
import sys
def pow2db(x):
if x < 1e-9:
return -99
return math.log(x) / math.log(10) * 10
Vi = 0
Vbp = 0
Vlp = 0
Vhp = 0
w0 = 0.0628318
distortion_rate = 1
res = 15
def do_filter_combined():
Q = 0.5 + res / 20.
global Vi, Vbp, Vlp, Vhp
Vlp -= w0 * Vbp
Vbp -= w0 * Vhp
Vhp_construction = Vbp / Q - Vlp - Vi
Vhp = Vhp_construction * 0.6
FFT_SIZE = 8192
def main_fft(variable, _res):
global Vi, res
res = _res;
if (variable == 'Vlp'):
def func(): return Vlp
elif (variable == 'Vbp'):
def func(): return Vbp
elif (variable == 'Vhp'):
def func(): return Vhp
elif (variable == 'sum'):
def func(): return Vlp + Vbp + Vhp
elif (variable == 'sum_lo'):
def func(): return Vlp + Vbp
elif (variable == 'sum_hi'):
def func(): return Vbp + Vhp
elif (variable == 'sum_notch'):
def func(): return Vlp + Vhp
else:
raise RuntimeError, "Unknown variable: %s" % variable
tmp1 = []
Vi = 1.0;
for x in range(FFT_SIZE):
do_filter_combined()
tmp1.append(func())
Vi = 0
accum1 = abs(fft(tmp1)) ** 2
for i in range(len(accum1)/2):
print "%f %f" % (float(i) / FFT_SIZE * 1000000, pow2db(accum1[i]))
def main():
return main_fft(sys.argv[1], float(sys.argv[2]))
if __name__ == '__main__':
main()

Some files were not shown because too many files have changed in this diff Show More