ref: 6c3d4b444a9a087946cf974ce394497ffe598872
parent: 6c8bd4efbb4713c2c1e83ded672244219596f4d2
author: Olav Sørensen <[email protected]>
date: Mon Apr 13 18:29:27 EDT 2020
Pushed v1.20 code - x86_64/amd64 users now get 32.32 fixed-point precision in the audio channel mixer, an extra 192kHz mixing frequency mode (may only work with a larger buffer size), and double the amount of phases in the cubic spline table. This will only make an improved outcome in very few cases (like extremely high/low channel rates), so don't expect to hear any difference. Non-x86_64 users now lose 96kHz mode as it was a bit unsuitable with 16.16 fixed-point precision. - The "Volume" function in Smp. Ed. now has more precision and takes less time to complete. Not that it was slow to begin with... - Increased the minimum .WAV rendering frequency from 8kHz to 44.1kHz, because the mixer delta calculations could overflow on such low rates. - Some more small miscellaneous changes not worth of a mention - Code cleanup
--- a/src/ft2_audio.c
+++ b/src/ft2_audio.c
@@ -19,7 +19,7 @@
static int8_t pmpCountDiv, pmpChannels = 2;
static uint16_t smpBuffSize;
-static int32_t masterVol, oldAudioFreq, speedVal, pmpLeft, randSeed = INITIAL_DITHER_SEED;
+static int32_t masterVol, oldAudioFreq, pmpLeft, randSeed = INITIAL_DITHER_SEED;
static int32_t prngStateL, prngStateR;
static uint32_t tickTimeLen, tickTimeLenFrac;
static float fAudioAmpMul;
@@ -45,7 +45,7 @@
}
#endif
-void stopVoice(uint8_t i)
+void stopVoice(int32_t i)
{
voice_t *v;
@@ -71,7 +71,7 @@
// set back old known working settings
config.audioFreq = audio.lastWorkingAudioFreq;
- config.specialFlags &= ~(BITDEPTH_16 + BITDEPTH_24 + BUFFSIZE_512 + BUFFSIZE_1024 + BUFFSIZE_2048);
+ config.specialFlags &= ~(BITDEPTH_16 + BITDEPTH_32 + BUFFSIZE_512 + BUFFSIZE_1024 + BUFFSIZE_2048);
config.specialFlags |= audio.lastWorkingAudioBits;
if (audio.lastWorkingAudioDeviceName != NULL)
@@ -119,7 +119,7 @@
if (bitDepth32Flag)
{
- // 32-bit floating point (24-bit)
+ // 32-bit floating point
fAudioAmpMul = fAudioNorm * (master / 256.0f) * (ampFactor / 32.0f);
}
else
@@ -153,11 +153,11 @@
if (bpm == 0)
return;
- speedVal = ((audio.freq + audio.freq) + (audio.freq >> 1)) / bpm; // (audio.freq * 2.5) / BPM
- if (speedVal > 0) // calculate tick time length for audio/video sync timestamp
+ audio.speedVal = ((audio.freq + audio.freq) + (audio.freq >> 1)) / bpm; // (audio.freq * 2.5) / BPM
+ if (audio.speedVal > 0) // calculate tick time length for audio/video sync timestamp
{
// number of samples per tick -> tick length for performance counter
- dFrac = modf(speedVal * audio.dSpeedValMul, &dInt);
+ dFrac = modf(audio.speedVal * audio.dSpeedValMul, &dInt);
/* - integer part -
** Cast to int32_t so that the compiler will use fast SSE2 float->int instructions.
@@ -167,9 +167,13 @@
// - fractional part (scaled to 0..2^32-1) -
dFrac *= UINT32_MAX;
- tickTimeLenFrac = (uint32_t)(dFrac + 0.5);
+ dFrac += 0.5;
+ if (dFrac > UINT32_MAX)
+ dFrac = UINT32_MAX;
- audio.rampSpeedValMul = 0xFFFFFFFF / speedVal;
+ tickTimeLenFrac = (uint32_t)dFrac;
+
+ audio.rampSpeedValMul = 0xFFFFFFFF / audio.speedVal;
}
}
@@ -262,7 +266,7 @@
}
else
{
- v->SVolIPLen = speedVal;
+ v->SVolIPLen = audio.speedVal;
v->SLVolIP = ((int64_t)destVolL * audio.rampSpeedValMul) >> 32;
v->SRVolIP = ((int64_t)destVolR * audio.rampSpeedValMul) >> 32;
}
@@ -337,7 +341,7 @@
void mix_SaveIPVolumes(void) // for volume ramping
{
voice_t *v = voice;
- for (uint32_t i = 0; i < MAX_VOICES; i++, v++)
+ for (int32_t i = 0; i < song.antChn; i++, v++)
{
v->SLVol2 = v->SLVol1;
v->SRVol2 = v->SRVol1;
@@ -357,24 +361,18 @@
for (int32_t i = 0; i < song.antChn; i++, ch++, v++)
{
status = ch->tmpStatus = ch->status; // ch->tmpStatus is used for audio/video sync queue
- if (status == 0)
- continue;
-
+ if (status == 0) continue;
ch->status = 0;
- // volume change
if (status & IS_Vol)
v->SVol = ch->finalVol;
- // panning change
if (status & IS_Pan)
v->SPan = ch->finalPan;
- // update mixing volumes if vol/pan change
if (status & (IS_Vol + IS_Pan))
voiceUpdateVolumes(i, status);
- // frequency change (received even if the period didn't change!)
if (status & IS_Period)
{
#if defined __amd64__ || defined _WIN64
@@ -397,7 +395,6 @@
#endif
}
- // sample trigger (note)
if (status & IS_NyTon)
voiceTrigger(i, ch->smpPtr, ch->smpStartPos);
}
@@ -590,9 +587,9 @@
{
voice_t *v, *r;
- assert(speedVal <= MAX_WAV_RENDER_SAMPLES_PER_TICK);
- memset(audio.mixBufferL, 0, speedVal * sizeof (int32_t));
- memset(audio.mixBufferR, 0, speedVal * sizeof (int32_t));
+ assert(audio.speedVal <= MAX_WAV_RENDER_SAMPLES_PER_TICK);
+ memset(audio.mixBufferL, 0, audio.speedVal * sizeof (int32_t));
+ memset(audio.mixBufferR, 0, audio.speedVal * sizeof (int32_t));
// mix channels
v = voice; // normal voices
@@ -601,8 +598,8 @@
for (int32_t i = 0; i < song.antChn; i++, v++, r++)
{
// call the mixing routine currently set for the voice
- if (v->mixRoutine != NULL) v->mixRoutine(v, speedVal); // mix normal voice
- if (r->mixRoutine != NULL) r->mixRoutine(r, speedVal); // mix volume ramp voice
+ if (v->mixRoutine != NULL) v->mixRoutine(v, audio.speedVal); // mix normal voice
+ if (r->mixRoutine != NULL) r->mixRoutine(r, audio.speedVal); // mix volume ramp voice
}
// normalize mix buffer and send to audio stream
@@ -609,16 +606,16 @@
if (bitDepth == 16)
{
if (config.specialFlags2 & DITHERED_AUDIO)
- sendSamples16BitDitherStereo(stream, speedVal, 2);
+ sendSamples16BitDitherStereo(stream, audio.speedVal, 2);
else
- sendSamples16BitStereo(stream, speedVal, 2);
+ sendSamples16BitStereo(stream, audio.speedVal, 2);
}
else
{
- sendSamples24BitStereo(stream, speedVal, 2);
+ sendSamples24BitStereo(stream, audio.speedVal, 2);
}
- return speedVal;
+ return audio.speedVal;
}
int32_t pattQueueReadSize(void)
@@ -932,12 +929,12 @@
}
// push channel variables to sync queue
- for (int32_t i = 0; i < song.antChn; i++)
- {
- c = &chSyncData.channels[i];
- s = &stm[i];
- c->voiceDelta = voice[i].SFrq;
+ c = chSyncData.channels;
+ s = stm;
+
+ for (int32_t i = 0; i < song.antChn; i++, c++, s++)
+ {
c->finalPeriod = s->finalPeriod;
c->fineTune = s->fineTune;
c->relTonNr = s->relTonNr;
@@ -960,7 +957,7 @@
audio.tickTime64++;
}
- pmpLeft = speedVal;
+ pmpLeft = audio.speedVal;
replayerBusy = false;
}
@@ -1016,8 +1013,8 @@
if (lockMixer)
lockMixerCallback();
- // force dither off if somehow set with 24-bit float (illegal)
- if ((config.specialFlags2 & DITHERED_AUDIO) && (config.specialFlags & BITDEPTH_24))
+ // force dither off if somehow set with 32-bit float (illegal)
+ if ((config.specialFlags2 & DITHERED_AUDIO) && (config.specialFlags & BITDEPTH_32))
config.specialFlags2 &= ~DITHERED_AUDIO;
if (config.specialFlags2 & DITHERED_AUDIO)
@@ -1062,15 +1059,17 @@
dAudioLatencySecs = haveSamples / dHaveFreq;
- // XXX: haveSamples and haveFreq better not be bogus values...
dFrac = modf(dAudioLatencySecs * editor.dPerfFreq, &dInt);
// integer part
- audio.audLatencyPerfValInt = (uint32_t)dInt;
+ audio.audLatencyPerfValInt = (int32_t)dInt;
// fractional part (scaled to 0..2^32-1)
dFrac *= UINT32_MAX;
- audio.audLatencyPerfValFrac = (uint32_t)(dFrac + 0.5);
+ dFrac += 0.5;
+ if (dFrac > UINT32_MAX)
+ dFrac = UINT32_MAX;
+ audio.audLatencyPerfValFrac = (uint32_t)dFrac;
audio.dAudioLatencyMs = dAudioLatencySecs * 1000.0;
}
@@ -1108,10 +1107,7 @@
closeAudio();
if (config.audioFreq < MIN_AUDIO_FREQ || config.audioFreq > MAX_AUDIO_FREQ)
- {
- // set default rate
- config.audioFreq = 48000;
- }
+ config.audioFreq = 48000; // set default rate
// get audio buffer size from config special flags
@@ -1130,7 +1126,7 @@
// these three may change after opening a device, but our mixer is dealing with it
want.freq = config.audioFreq;
- want.format = (config.specialFlags & BITDEPTH_24) ? AUDIO_F32 : AUDIO_S16;
+ want.format = (config.specialFlags & BITDEPTH_32) ? AUDIO_F32 : AUDIO_S16;
want.channels = 2;
// -------------------------------------------------------------------------------
want.callback = mixCallback;
@@ -1149,7 +1145,7 @@
if (have.format != AUDIO_S16 && have.format != AUDIO_F32)
{
if (showErrorMsg)
- showErrorMsgBox("Couldn't open audio device:\nThe program doesn't support an SDL_AudioFormat of '%d' (not 16-bit or 24-bit float).",
+ showErrorMsgBox("Couldn't open audio device:\nThe program doesn't support an SDL_AudioFormat of '%d' (not 16-bit or 32-bit float).",
(uint32_t)have.format);
closeAudio();
@@ -1157,7 +1153,12 @@
}
// test if the received audio rate is compatible
- if (have.freq != 44100 && have.freq != 48000 && have.freq != 96000)
+
+#if defined _WIN64 || defined __amd64__
+ if (have.freq != 44100 && have.freq != 48000 && have.freq != 96000 && have.freq != 192000)
+#else
+ if (have.freq != 44100 && have.freq != 48000)
+#endif
{
if (showErrorMsg)
showErrorMsgBox("Couldn't open audio device:\nThe program doesn't support an audio output rate of %dHz. Sorry!", have.freq);
@@ -1178,7 +1179,7 @@
// set new bit depth flag
newBitDepth = 16;
- config.specialFlags &= ~BITDEPTH_24;
+ config.specialFlags &= ~BITDEPTH_32;
config.specialFlags |= BITDEPTH_16;
if (have.format == AUDIO_F32)
@@ -1185,7 +1186,7 @@
{
newBitDepth = 24;
config.specialFlags &= ~BITDEPTH_16;
- config.specialFlags |= BITDEPTH_24;
+ config.specialFlags |= BITDEPTH_32;
}
audio.haveFreq = have.freq;
@@ -1209,7 +1210,7 @@
// make a copy of the new known working audio settings
audio.lastWorkingAudioFreq = config.audioFreq;
- audio.lastWorkingAudioBits = config.specialFlags & (BITDEPTH_16 + BITDEPTH_24 + BUFFSIZE_512 + BUFFSIZE_1024 + BUFFSIZE_2048);
+ audio.lastWorkingAudioBits = config.specialFlags & (BITDEPTH_16 + BITDEPTH_32 + BUFFSIZE_512 + BUFFSIZE_1024 + BUFFSIZE_2048);
setLastWorkingAudioDevName();
// update config audio radio buttons if we're on that screen at the moment
@@ -1217,10 +1218,10 @@
showConfigScreen();
updateWavRendererSettings();
- setAudioAmp(config.boostLevel, config.masterVol, (config.specialFlags & BITDEPTH_24) ? true : false);
+ setAudioAmp(config.boostLevel, config.masterVol, (config.specialFlags & BITDEPTH_32) ? true : false);
// don't call stopVoices() in this routine
- for (uint8_t i = 0; i < MAX_VOICES; i++)
+ for (int32_t i = 0; i < MAX_VOICES; i++)
stopVoice(i);
stopAllScopes();
--- a/src/ft2_audio.h
+++ b/src/ft2_audio.h
@@ -11,32 +11,37 @@
FREQ_TABLE_AMIGA = 1,
};
-/* Warning: MIXER_FRAC_BITS must NOT be higher than 22!
-** This can create an overflow in certain calculations.
-**
-** Use 16 on non-x86_64 platforms so that we can avoid a
+/* Use 16 on non-x86_64 platforms so that we can avoid a
** 64-bit division in the outside mixer loop. x86_64 users
-** are lucky and will get higher fractional delta precision.
-** This is beneficial in 96kHz mode, where deltas are lower
-** in value.
+** are lucky and will get double the fractional delta precision.
+** This is beneficial in 96kHz/192kHz mode, where deltas are
+** lower in value.
*/
-#if defined __amd64__ || defined _WIN64
-#define MIXER_FRAC_BITS 22
+#if defined _WIN64 || defined __amd64__
+
+#define MIN_AUDIO_FREQ 44100
+#define MAX_AUDIO_FREQ 192000
+
+#define MIXER_FRAC_BITS 32
+#define MIXER_FRAC_SCALE (1ULL << MIXER_FRAC_BITS)
+#define MIXER_FRAC_MASK (MIXER_FRAC_SCALE-1)
+
#else
+
+#define MIN_AUDIO_FREQ 44100
+#define MAX_AUDIO_FREQ 48000
+
#define MIXER_FRAC_BITS 16
+#define MIXER_FRAC_SCALE (1UL << MIXER_FRAC_BITS)
+#define MIXER_FRAC_MASK (MIXER_FRAC_SCALE-1)
+
#endif
-#define MIXER_FRAC_SCALE (1L << MIXER_FRAC_BITS)
-#define MIXER_FRAC_MASK (MIXER_FRAC_SCALE-1)
+#define MAX_AUDIO_DEVICES 99
// for audio/video sync queue. (2^n-1 - don't change this! Queue buffer is already ~2.7MB in size)
#define SYNC_QUEUE_LEN 4095
-#define MAX_AUDIO_DEVICES 99
-
-#define MIN_AUDIO_FREQ 44100
-#define MAX_AUDIO_FREQ 96000
-
struct audio_t
{
char *currInputDevice, *currOutputDevice, *lastWorkingAudioDeviceName;
@@ -47,7 +52,7 @@
int32_t quickVolSizeVal, *mixBufferL, *mixBufferR, *mixBufferLUnaligned, *mixBufferRUnaligned;
int32_t rampQuickVolMul, rampSpeedValMul;
uint32_t freq;
- uint32_t audLatencyPerfValInt, audLatencyPerfValFrac;
+ uint32_t audLatencyPerfValInt, audLatencyPerfValFrac, speedVal, musicTimeSpeedVal;
uint64_t tickTime64, tickTime64Frac;
double dAudioLatencyMs, dSpeedValMul, dPianoDeltaMul;
SDL_AudioDeviceID dev;
@@ -63,10 +68,12 @@
uint16_t SVol;
int32_t SLVol1, SRVol1, SLVol2, SRVol2, SLVolIP, SRVolIP;
int32_t SPos, SLen, SRepS, SRepL;
- uint32_t SVolIPLen, SPosDec, SFrq;
-
-#if !defined __amd64__ && !defined _WIN64
- uint32_t SFrqRev;
+ uint32_t SVolIPLen;
+
+#if defined _WIN64 || defined __amd64__
+ uint64_t SPosDec, SFrq;
+#else
+ uint32_t SPosDec, SFrq, SFrqRev;
#endif
void (*mixRoutine)(void *, int32_t); // function pointer to mix routine
@@ -109,6 +116,7 @@
int32_t pattQueueWriteSize(void);
bool pattQueuePush(pattSyncData_t t);
bool pattQueuePop(void);
+bool pattQueuePop(void);
pattSyncData_t *pattQueuePeek(void);
uint64_t getPattQueueTimestamp(void);
int32_t chQueueReadSize(void);
@@ -123,7 +131,7 @@
void setSpeed(uint16_t bpm);
void audioSetVolRamp(bool volRamp);
void audioSetInterpolation(bool interpolation);
-void stopVoice(uint8_t i);
+void stopVoice(int32_t i);
bool setupAudio(bool showErrorMsg);
void closeAudio(void);
void pauseAudio(void);
--- a/src/ft2_config.c
+++ b/src/ft2_config.c
@@ -135,8 +135,13 @@
config.recQuantRes = 16;
}
- if (config.audioFreq != 44100 && config.audioFreq != 48000 && config.audioFreq != 96000)
+#if defined __amd64__ || defined _WIN64
+ if (config.audioFreq != 44100 && config.audioFreq != 48000 && config.audioFreq != 96000 && config.audioFreq != 192000)
config.audioFreq = 48000;
+#else
+ if (config.audioFreq != 44100 && config.audioFreq != 48000)
+ config.audioFreq = 48000;
+#endif
if (config.audioInputFreq <= 1) // default value from FT2 (this was cdr_Sync) - set defaults
config.audioInputFreq = INPUT_FREQ_48KHZ;
@@ -154,9 +159,9 @@
if (config.windowFlags == 0) // default value from FT2 (this was ptnDefaultLen byte #2) - set defaults
config.windowFlags = WINSIZE_AUTO;
- // audio bit depth - remove 24-bit flag if both are enabled
- if ((config.specialFlags & BITDEPTH_16) && (config.specialFlags & BITDEPTH_24))
- config.specialFlags &= ~BITDEPTH_24;
+ // audio bit depth - remove 32-bit flag if both are enabled
+ if ((config.specialFlags & BITDEPTH_16) && (config.specialFlags & BITDEPTH_32))
+ config.specialFlags &= ~BITDEPTH_32;
if (audio.dev != 0)
setNewAudioSettings();
@@ -163,7 +168,7 @@
audioSetInterpolation(config.interpolation ? true : false);
audioSetVolRamp((config.specialFlags & NO_VOLRAMP_FLAG) ? false : true);
- setAudioAmp(config.boostLevel, config.masterVol, config.specialFlags & BITDEPTH_24);
+ setAudioAmp(config.boostLevel, config.masterVol, config.specialFlags & BITDEPTH_32);
setMouseShape(config.mouseType);
changeLogoType(config.id_FastLogo);
changeBadgeType(config.id_TritonProd);
@@ -804,7 +809,7 @@
uncheckRadioButtonGroup(RB_GROUP_CONFIG_AUDIO_BIT_DEPTH);
tmpID = RB_CONFIG_AUDIO_16BIT;
- if (config.specialFlags & BITDEPTH_24)
+ if (config.specialFlags & BITDEPTH_32)
tmpID = RB_CONFIG_AUDIO_24BIT;
radioButtons[tmpID].state = RADIOBUTTON_CHECKED;
@@ -813,9 +818,12 @@
uncheckRadioButtonGroup(RB_GROUP_CONFIG_AUDIO_FREQ);
switch (config.audioFreq)
{
- case 44100: tmpID = RB_CONFIG_AUDIO_44KHZ; break;
- default: case 48000: tmpID = RB_CONFIG_AUDIO_48KHZ; break;
- case 96000: tmpID = RB_CONFIG_AUDIO_96KHZ; break;
+ case 44100: tmpID = RB_CONFIG_AUDIO_44KHZ; break;
+ default: case 48000: tmpID = RB_CONFIG_AUDIO_48KHZ; break;
+#if defined __amd64__ || defined _WIN64
+ case 96000: tmpID = RB_CONFIG_AUDIO_96KHZ; break;
+ case 192000: tmpID = RB_CONFIG_AUDIO_192KHZ; break;
+#endif
}
radioButtons[tmpID].state = RADIOBUTTON_CHECKED;
@@ -847,7 +855,7 @@
{
checkBoxes[CB_CONF_INTERPOLATION].checked = config.interpolation;
checkBoxes[CB_CONF_VOL_RAMP].checked = (config.specialFlags & NO_VOLRAMP_FLAG) ? false : true;
- checkBoxes[CB_CONF_DITHER].checked = (config.specialFlags & BITDEPTH_24) ? false : config.specialFlags2 & DITHERED_AUDIO;
+ checkBoxes[CB_CONF_DITHER].checked = (config.specialFlags & BITDEPTH_32) ? false : config.specialFlags2 & DITHERED_AUDIO;
showCheckBox(CB_CONF_INTERPOLATION);
showCheckBox(CB_CONF_VOL_RAMP);
@@ -1134,7 +1142,7 @@
textOutShadow(390, 76, PAL_FORGRND, PAL_DSKTOP2, "Audio bit depth:");
textOutShadow(406, 90, PAL_FORGRND, PAL_DSKTOP2, "16-bit (default)");
- textOutShadow(406, 104, PAL_FORGRND, PAL_DSKTOP2, "24-bit float");
+ textOutShadow(406, 104, PAL_FORGRND, PAL_DSKTOP2, "32-bit float");
textOutShadow(390, 120, PAL_FORGRND, PAL_DSKTOP2, "Mixing device ctrl.:");
textOutShadow(406, 134, PAL_FORGRND, PAL_DSKTOP2, "Interpolation");
@@ -1144,8 +1152,10 @@
textOutShadow(509, 3, PAL_FORGRND, PAL_DSKTOP2, "Mixing frequency:");
textOutShadow(525, 17, PAL_FORGRND, PAL_DSKTOP2, "44100Hz");
textOutShadow(525, 31, PAL_FORGRND, PAL_DSKTOP2, "48000Hz (default)");
+#if defined __amd64__ || defined _WIN64
textOutShadow(525, 45, PAL_FORGRND, PAL_DSKTOP2, "96000Hz");
-
+ textOutShadow(525, 59, PAL_FORGRND, PAL_DSKTOP2, "192000Hz");
+#endif
textOutShadow(509, 76, PAL_FORGRND, PAL_DSKTOP2, "Frequency table:");
textOutShadow(525, 90, PAL_FORGRND, PAL_DSKTOP2, "Amiga freq. table");
textOutShadow(525, 104, PAL_FORGRND, PAL_DSKTOP2, "Linear freq. table");
@@ -1561,7 +1571,7 @@
void rbConfigAudio16bit(void)
{
- config.specialFlags &= ~BITDEPTH_24;
+ config.specialFlags &= ~BITDEPTH_32;
config.specialFlags |= BITDEPTH_16;
setNewAudioSettings();
@@ -1570,9 +1580,9 @@
void rbConfigAudio24bit(void)
{
config.specialFlags &= ~BITDEPTH_16;
- config.specialFlags |= BITDEPTH_24;
+ config.specialFlags |= BITDEPTH_32;
- config.specialFlags2 &= ~DITHERED_AUDIO; // no dither in "24-bit float" mode
+ config.specialFlags2 &= ~DITHERED_AUDIO; // no dither in "32-bit float" mode
checkBoxes[CB_CONF_DITHER].checked = false;
if (editor.currConfigScreen == CONFIG_SCREEN_IO_DEVICES)
@@ -1599,6 +1609,12 @@
setNewAudioSettings();
}
+void rbConfigAudio192kHz(void)
+{
+ config.audioFreq = 192000;
+ setNewAudioSettings();
+}
+
void rbConfigAudioInput44kHz(void)
{
config.audioInputFreq = INPUT_FREQ_44KHZ;
@@ -1650,7 +1666,7 @@
void cbConfigDither(void)
{
- if (config.specialFlags & BITDEPTH_24) // no dither in float mode, force off
+ if (config.specialFlags & BITDEPTH_32) // no dither in float mode, force off
{
config.specialFlags2 &= ~DITHERED_AUDIO;
@@ -2151,7 +2167,7 @@
if (config.boostLevel != (int8_t)pos + 1)
{
config.boostLevel = (int8_t)pos + 1;
- setAudioAmp(config.boostLevel, config.masterVol, config.specialFlags & BITDEPTH_24);
+ setAudioAmp(config.boostLevel, config.masterVol, config.specialFlags & BITDEPTH_32);
configDrawAmp();
updateWavRendererSettings();
}
@@ -2172,7 +2188,7 @@
if (config.masterVol != (int16_t)pos)
{
config.masterVol = (int16_t)pos;
- setAudioAmp(config.boostLevel, config.masterVol, config.specialFlags & BITDEPTH_24);
+ setAudioAmp(config.boostLevel, config.masterVol, config.specialFlags & BITDEPTH_32);
}
}
--- a/src/ft2_config.h
+++ b/src/ft2_config.h
@@ -67,7 +67,7 @@
// specialFlags
NO_VOLRAMP_FLAG = 1,
BITDEPTH_16 = 2,
- BITDEPTH_24 = 4,
+ BITDEPTH_32 = 4,
BUFFSIZE_512 = 8,
BUFFSIZE_1024 = 16,
BUFFSIZE_2048 = 32,
@@ -208,6 +208,7 @@
void rbConfigAudio44kHz(void);
void rbConfigAudio48kHz(void);
void rbConfigAudio96kHz(void);
+void rbConfigAudio192kHz(void);
void rbConfigAudioInput44kHz(void);
void rbConfigAudioInput48kHz(void);
void rbConfigAudioInput96kHz(void);
--- a/src/ft2_gui.c
+++ b/src/ft2_gui.c
@@ -1162,6 +1162,7 @@
textOutShadow(204, 80, PAL_FORGRND, PAL_DSKTOP2, "Time");
charOutShadow(250, 80, PAL_FORGRND, PAL_DSKTOP2, ':');
charOutShadow(270, 80, PAL_FORGRND, PAL_DSKTOP2, ':');
+
drawPlaybackTime();
if (editor.ui.sampleEditorExtShown) drawSampleEditorExt();
--- a/src/ft2_inst_ed.c
+++ b/src/ft2_inst_ed.c
@@ -109,7 +109,7 @@
static uint16_t saveInstrNr;
static SDL_Thread *thread;
-extern const int16_t *note2Period; // ft2_replayer.c
+extern const uint16_t *note2Period; // ft2_replayer.c
void updateInstEditor(void);
void updateNewInstrument(void);
@@ -227,33 +227,24 @@
static void drawMIDICh(void)
{
- char str[8];
instrTyp *ins = getCurDispInstr();
-
assert(ins->midiChannel <= 15);
- uint8_t disp = ins->midiChannel + 1;
- sprintf(str, "%02d", disp);
- textOutFixed(156, 132, PAL_FORGRND, PAL_DESKTOP, str);
+ const uint8_t val = ins->midiChannel + 1;
+ textOutFixed(156, 132, PAL_FORGRND, PAL_DESKTOP, dec2StrTab[val]);
}
static void drawMIDIPrg(void)
{
- char str[8];
instrTyp *ins = getCurDispInstr();
-
assert(ins->midiProgram <= 127);
- sprintf(str, "%03d", ins->midiProgram);
- textOutFixed(149, 146, PAL_FORGRND, PAL_DESKTOP, str);
+ textOutFixed(149, 146, PAL_FORGRND, PAL_DESKTOP, dec3StrTab[ins->midiProgram]);
}
static void drawMIDIBend(void)
{
- char str[8];
instrTyp *ins = getCurDispInstr();
-
assert(ins->midiBend <= 36);
- sprintf(str, "%02d", ins->midiBend);
- textOutFixed(156, 160, PAL_FORGRND, PAL_DESKTOP, str);
+ textOutFixed(156, 160, PAL_FORGRND, PAL_DESKTOP, dec2StrTab[ins->midiBend]);
}
void midiChDown(void)
@@ -384,56 +375,44 @@
static void drawVolEnvSus(void)
{
- char str[8];
instrTyp *ins = getCurDispInstr();
-
- sprintf(str, "%02d", ins->envVSust);
- textOutFixed(382, 206, PAL_FORGRND, PAL_DESKTOP, str);
+ assert(ins->envVSust < 100);
+ textOutFixed(382, 206, PAL_FORGRND, PAL_DESKTOP, dec2StrTab[ins->envVSust]);
}
static void drawVolEnvRepS(void)
{
- char str[8];
instrTyp *ins = getCurDispInstr();
-
- sprintf(str, "%02d", ins->envVRepS);
- textOutFixed(382, 233, PAL_FORGRND, PAL_DESKTOP, str);
+ assert(ins->envVRepS < 100);
+ textOutFixed(382, 233, PAL_FORGRND, PAL_DESKTOP, dec2StrTab[ins->envVRepS]);
}
static void drawVolEnvRepE(void)
{
- char str[8];
instrTyp *ins = getCurDispInstr();
-
- sprintf(str, "%02d", ins->envVRepE);
- textOutFixed(382, 247, PAL_FORGRND, PAL_DESKTOP, str);
+ assert(ins->envVRepE < 100);
+ textOutFixed(382, 247, PAL_FORGRND, PAL_DESKTOP, dec2StrTab[ins->envVRepE]);
}
static void drawPanEnvSus(void)
{
- char str[8];
instrTyp *ins = getCurDispInstr();
-
- sprintf(str, "%02d", ins->envPSust);
- textOutFixed(382, 293, PAL_FORGRND, PAL_DESKTOP, str);
+ assert(ins->envPSust < 100);
+ textOutFixed(382, 293, PAL_FORGRND, PAL_DESKTOP, dec2StrTab[ins->envPSust]);
}
static void drawPanEnvRepS(void)
{
- char str[8];
instrTyp *ins = getCurDispInstr();
-
- sprintf(str, "%02d", ins->envPRepS);
- textOutFixed(382, 320, PAL_FORGRND, PAL_DESKTOP, str);
+ assert(ins->envPRepS < 100);
+ textOutFixed(382, 320, PAL_FORGRND, PAL_DESKTOP, dec2StrTab[ins->envPRepS]);
}
static void drawPanEnvRepE(void)
{
- char str[8];
instrTyp *ins = getCurDispInstr();
-
- sprintf(str, "%02d", ins->envPRepE);
- textOutFixed(382, 334, PAL_FORGRND, PAL_DESKTOP, str);
+ assert(ins->envPRepE < 100);
+ textOutFixed(382, 334, PAL_FORGRND, PAL_DESKTOP, dec2StrTab[ins->envPRepE]);
}
static void drawVolume(void)
@@ -1693,33 +1672,10 @@
return true;
}
-/* 8bitbubsy: This is my new version of FT2's buggy getNote().
-** It's used to convert a channel's period into a piano key number.
-** Or in this case, a voice's frequency into a piano key number.
-**
-** It's probably slower than the original version, but this one is
-** 100% accurate in all (quirky) situations.
-**
-** Warning: This function intentionally doesn't clamp the output value!
-*/
-static int32_t getPianoKey(int32_t voiceDelta, int32_t finetune, int32_t relativeNote)
-{
- finetune >>= 3; // FT2 does this in the replayer internally (-128..127 -> -16..15)
-
- double dTmp = voiceDelta * audio.dPianoDeltaMul;
- dTmp = (log2(dTmp) * 12.0) - (finetune * (1.0 / 16.0));
- int32_t note = (int32_t)(dTmp + 0.5); // rounded
-
- note -= relativeNote;
- // "note" is now the raw piano key number, unaffected by finetune/relativeNote
-
- return note;
-}
-
void drawPiano(chSyncData_t *chSyncData)
{
bool newStatus[96];
- int32_t note;
+ int32_t i, note;
memset(newStatus, 0, sizeof (newStatus));
@@ -1729,11 +1685,11 @@
if (chSyncData != NULL) // song is playing, use replayer channel state
{
syncedChannel_t *c = chSyncData->channels;
- for (int32_t i = 0; i < song.antChn; i++, c++)
+ for (i = 0; i < song.antChn; i++, c++)
{
if (c->instrNr == editor.curInstr && c->envSustainActive)
{
- note = getPianoKey(c->voiceDelta, c->fineTune, c->relTonNr);
+ note = getPianoKey(c->finalPeriod, c->fineTune, c->relTonNr);
if (note >= 0 && note <= 95)
newStatus[note] = true;
}
@@ -1742,12 +1698,11 @@
else // song is not playing (jamming from keyboard/MIDI)
{
stmTyp *c = stm;
- for (int32_t i = 0; i < song.antChn; i++, c++)
+ for (i = 0; i < song.antChn; i++, c++)
{
if (c->instrNr == editor.curInstr && c->envSustainActive)
{
- int32_t voiceDelta = getFrequenceValue(c->finalPeriod);
- note = getPianoKey(voiceDelta, c->fineTune, c->relTonNr);
+ note = getPianoKey(c->finalPeriod, c->fineTune, c->relTonNr);
if (note >= 0 && note <= 95)
newStatus[note] = true;
}
@@ -1756,9 +1711,9 @@
}
// draw keys
- for (int32_t i = 0; i < 96; i++)
+ for (i = 0; i < 96; i++)
{
- bool keyDown = newStatus[i];
+ const bool keyDown = newStatus[i];
if (pianoKeyStatus[i] ^ keyDown)
{
uint8_t key = noteTab1[i];
--- a/src/ft2_intrp_table.c
+++ b/src/ft2_intrp_table.c
@@ -1,12 +1,12 @@
#include <stdint.h>
#include "ft2_intrp_table.h"
-/* 4-tap cubic spline table
-**
-** This table was generated using a modified version of Schism Tracker's lutgen.cpp
-** with 15-bit precision and 8192 phases.
-*/
+// 4-tap cubic spline table
+#if defined __amd64__ || defined _WIN64
+
+// 15-bit precision, 8192 phases (slightly harder on the CPU cache)
+
const int16_t cubicSplineTable[CUBIC_WIDTH * CUBIC_PHASES] =
{
0, 32767, 0, 0, -2, 32767, 2, 0, -4, 32767, 4, 0, -6, 32767, 6, 0,
@@ -2058,3 +2058,141 @@
0, 16, 32767, -16, 0, 14, 32767, -14, 0, 12, 32767, -12, 0, 10, 32767, -10,
0, 8, 32767, -8, 0, 6, 32767, -6, 0, 4, 32767, -4, 0, 2, 32767, -2
};
+
+#else
+
+// for non-x86_64 CPUs: 15-bit precision, 512 phases
+
+const int16_t cubicSplineTable[CUBIC_WIDTH * CUBIC_PHASES] =
+{
+ 0, 32767, 0, 0, -32, 32767, 32, 0, -64, 32767, 65, 0, -95, 32766, 98, -1,
+ -126, 32763, 132, -1, -157, 32761, 166, -2, -188, 32757, 201, -2, -218, 32753, 236, -3,
+ -248, 32748, 272, -4, -278, 32743, 308, -5, -308, 32737, 345, -6, -337, 32730, 382, -7,
+ -366, 32724, 419, -9, -395, 32716, 457, -10, -424, 32708, 496, -12, -452, 32699, 535, -14,
+ -481, 32690, 575, -16, -508, 32679, 614, -17, -536, 32669, 655, -20, -564, 32658, 696, -22,
+ -591, 32646, 737, -24, -618, 32633, 779, -26, -645, 32621, 821, -29, -671, 32607, 864, -32,
+ -698, 32593, 907, -34, -724, 32578, 951, -37, -750, 32563, 995, -40, -775, 32547, 1039, -43,
+ -801, 32531, 1084, -46, -826, 32515, 1129, -50, -851, 32497, 1175, -53, -876, 32479, 1221, -56,
+ -900, 32460, 1268, -60, -924, 32441, 1315, -64, -948, 32420, 1363, -67, -972, 32400, 1411, -71,
+ -996, 32380, 1459, -75, -1019, 32358, 1508, -79, -1042, 32337, 1557, -84, -1065, 32314, 1607, -88,
+ -1088, 32291, 1657, -92, -1110, 32268, 1707, -97, -1133, 32244, 1758, -101, -1155, 32220, 1809, -106,
+ -1176, 32194, 1861, -111, -1198, 32168, 1913, -115, -1219, 32142, 1965, -120, -1241, 32116, 2018, -125,
+ -1262, 32089, 2072, -131, -1282, 32061, 2125, -136, -1303, 32033, 2179, -141, -1323, 32003, 2234, -146,
+ -1343, 31974, 2289, -152, -1363, 31944, 2344, -157, -1383, 31915, 2399, -163, -1402, 31884, 2455, -169,
+ -1421, 31852, 2512, -175, -1440, 31820, 2568, -180, -1459, 31787, 2626, -186, -1478, 31755, 2683, -192,
+ -1496, 31722, 2741, -199, -1515, 31689, 2799, -205, -1533, 31654, 2858, -211, -1550, 31619, 2917, -218,
+ -1568, 31584, 2976, -224, -1585, 31548, 3036, -231, -1603, 31512, 3096, -237, -1620, 31476, 3156, -244,
+ -1636, 31438, 3217, -251, -1653, 31400, 3278, -257, -1669, 31362, 3339, -264, -1686, 31324, 3401, -271,
+ -1702, 31285, 3463, -278, -1717, 31245, 3526, -286, -1733, 31205, 3589, -293, -1748, 31164, 3652, -300,
+ -1764, 31124, 3715, -307, -1779, 31083, 3779, -315, -1793, 31040, 3843, -322, -1808, 30998, 3908, -330,
+ -1823, 30956, 3973, -338, -1837, 30912, 4038, -345, -1851, 30869, 4103, -353, -1865, 30825, 4169, -361,
+ -1878, 30780, 4235, -369, -1892, 30736, 4301, -377, -1905, 30690, 4368, -385, -1918, 30644, 4435, -393,
+ -1931, 30598, 4502, -401, -1944, 30551, 4570, -409, -1956, 30503, 4638, -417, -1969, 30457, 4706, -426,
+ -1981, 30408, 4775, -434, -1993, 30359, 4844, -442, -2005, 30311, 4913, -451, -2017, 30262, 4982, -459,
+ -2028, 30212, 5052, -468, -2039, 30162, 5122, -477, -2050, 30111, 5192, -485, -2061, 30060, 5263, -494,
+ -2072, 30009, 5334, -503, -2083, 29958, 5405, -512, -2093, 29906, 5476, -521, -2103, 29853, 5548, -530,
+ -2113, 29800, 5620, -539, -2123, 29747, 5692, -548, -2133, 29693, 5765, -557, -2142, 29638, 5838, -566,
+ -2152, 29584, 5911, -575, -2161, 29529, 5984, -584, -2170, 29474, 6058, -594, -2179, 29419, 6131, -603,
+ -2188, 29363, 6206, -613, -2196, 29306, 6280, -622, -2204, 29249, 6354, -631, -2213, 29193, 6429, -641,
+ -2221, 29135, 6504, -650, -2228, 29076, 6580, -660, -2236, 29019, 6655, -670, -2244, 28960, 6731, -679,
+ -2251, 28901, 6807, -689, -2258, 28842, 6883, -699, -2265, 28782, 6960, -709, -2272, 28721, 7037, -718,
+ -2279, 28661, 7114, -728, -2285, 28600, 7191, -738, -2292, 28540, 7268, -748, -2298, 28478, 7346, -758,
+ -2304, 28416, 7424, -768, -2310, 28354, 7502, -778, -2316, 28292, 7580, -788, -2321, 28228, 7659, -798,
+ -2327, 28165, 7738, -808, -2332, 28101, 7817, -818, -2337, 28038, 7896, -829, -2342, 27974, 7975, -839,
+ -2347, 27909, 8055, -849, -2352, 27844, 8135, -859, -2356, 27778, 8215, -869, -2361, 27714, 8295, -880,
+ -2365, 27648, 8375, -890, -2369, 27581, 8456, -900, -2373, 27516, 8536, -911, -2377, 27449, 8617, -921,
+ -2381, 27382, 8699, -932, -2384, 27314, 8780, -942, -2387, 27246, 8861, -952, -2391, 27179, 8943, -963,
+ -2394, 27110, 9025, -973, -2397, 27042, 9107, -984, -2399, 26972, 9189, -994, -2402, 26904, 9271, -1005,
+ -2405, 26834, 9354, -1015, -2407, 26764, 9437, -1026, -2409, 26693, 9520, -1036, -2411, 26623, 9603, -1047,
+ -2413, 26553, 9686, -1058, -2415, 26482, 9769, -1068, -2417, 26411, 9853, -1079, -2419, 26340, 9936, -1089,
+ -2420, 26268, 10020, -1100, -2421, 26196, 10104, -1111, -2422, 26123, 10188, -1121, -2424, 26052, 10272, -1132,
+ -2424, 25978, 10357, -1143, -2425, 25905, 10441, -1153, -2426, 25832, 10526, -1164, -2426, 25758, 10611, -1175,
+ -2427, 25684, 10696, -1185, -2427, 25610, 10781, -1196, -2427, 25536, 10866, -1207, -2427, 25461, 10951, -1217,
+ -2427, 25386, 11037, -1228, -2427, 25312, 11122, -1239, -2427, 25236, 11208, -1249, -2426, 25160, 11294, -1260,
+ -2426, 25085, 11380, -1271, -2425, 25008, 11466, -1281, -2424, 24932, 11552, -1292, -2423, 24855, 11638, -1302,
+ -2422, 24779, 11724, -1313, -2421, 24702, 11811, -1324, -2419, 24624, 11897, -1334, -2418, 24547, 11984, -1345,
+ -2416, 24469, 12071, -1356, -2415, 24391, 12158, -1366, -2413, 24314, 12244, -1377, -2411, 24234, 12332, -1387,
+ -2409, 24156, 12419, -1398, -2407, 24077, 12506, -1408, -2405, 23999, 12593, -1419, -2402, 23918, 12681, -1429,
+ -2400, 23840, 12768, -1440, -2397, 23759, 12856, -1450, -2395, 23681, 12943, -1461, -2392, 23600, 13031, -1471,
+ -2389, 23520, 13119, -1482, -2386, 23440, 13206, -1492, -2383, 23360, 13294, -1503, -2380, 23279, 13382, -1513,
+ -2377, 23198, 13470, -1523, -2373, 23117, 13558, -1534, -2370, 23035, 13647, -1544, -2366, 22953, 13735, -1554,
+ -2362, 22872, 13823, -1565, -2359, 22791, 13911, -1575, -2355, 22708, 14000, -1585, -2351, 22626, 14088, -1595,
+ -2347, 22544, 14177, -1606, -2342, 22461, 14265, -1616, -2338, 22378, 14354, -1626, -2334, 22296, 14442, -1636,
+ -2329, 22212, 14531, -1646, -2325, 22130, 14619, -1656, -2320, 22046, 14708, -1666, -2315, 21962, 14797, -1676,
+ -2310, 21879, 14885, -1686, -2305, 21795, 14974, -1696, -2300, 21711, 15063, -1706, -2295, 21626, 15152, -1715,
+ -2290, 21542, 15241, -1725, -2284, 21458, 15329, -1735, -2279, 21374, 15418, -1745, -2274, 21289, 15507, -1754,
+ -2268, 21204, 15596, -1764, -2262, 21119, 15685, -1774, -2257, 21034, 15774, -1783, -2251, 20949, 15863, -1793,
+ -2245, 20863, 15952, -1802, -2239, 20779, 16040, -1812, -2233, 20693, 16129, -1821, -2227, 20607, 16218, -1830,
+ -2220, 20521, 16307, -1840, -2214, 20435, 16396, -1849, -2208, 20349, 16485, -1858, -2201, 20262, 16574, -1867,
+ -2195, 20177, 16662, -1876, -2188, 20091, 16751, -1886, -2181, 20004, 16840, -1895, -2174, 19917, 16929, -1904,
+ -2168, 19831, 17018, -1913, -2161, 19744, 17106, -1921, -2154, 19657, 17195, -1930, -2146, 19569, 17284, -1939,
+ -2139, 19483, 17372, -1948, -2132, 19395, 17461, -1956, -2125, 19309, 17549, -1965, -2117, 19221, 17638, -1974,
+ -2110, 19134, 17726, -1982, -2102, 19046, 17815, -1991, -2095, 18959, 17903, -1999, -2087, 18871, 17991, -2007,
+ -2079, 18783, 18080, -2016, -2072, 18696, 18168, -2024, -2064, 18608, 18256, -2032, -2056, 18520, 18344, -2040,
+ -2048, 18432, 18432, -2048, -2040, 18344, 18520, -2056, -2032, 18256, 18608, -2064, -2024, 18168, 18696, -2072,
+ -2016, 18080, 18783, -2079, -2007, 17991, 18871, -2087, -1999, 17903, 18959, -2095, -1991, 17815, 19046, -2102,
+ -1982, 17726, 19134, -2110, -1974, 17638, 19221, -2117, -1965, 17549, 19309, -2125, -1956, 17461, 19395, -2132,
+ -1948, 17372, 19483, -2139, -1939, 17284, 19569, -2146, -1930, 17195, 19657, -2154, -1921, 17106, 19744, -2161,
+ -1913, 17018, 19831, -2168, -1904, 16929, 19917, -2174, -1895, 16840, 20004, -2181, -1886, 16751, 20091, -2188,
+ -1876, 16662, 20177, -2195, -1867, 16574, 20262, -2201, -1858, 16485, 20349, -2208, -1849, 16396, 20435, -2214,
+ -1840, 16307, 20521, -2220, -1830, 16218, 20607, -2227, -1821, 16129, 20693, -2233, -1812, 16040, 20779, -2239,
+ -1802, 15952, 20863, -2245, -1793, 15863, 20949, -2251, -1783, 15774, 21034, -2257, -1774, 15685, 21119, -2262,
+ -1764, 15596, 21204, -2268, -1754, 15507, 21289, -2274, -1745, 15418, 21374, -2279, -1735, 15329, 21458, -2284,
+ -1725, 15241, 21542, -2290, -1715, 15152, 21626, -2295, -1706, 15063, 21711, -2300, -1696, 14974, 21795, -2305,
+ -1686, 14885, 21879, -2310, -1676, 14797, 21962, -2315, -1666, 14708, 22046, -2320, -1656, 14619, 22130, -2325,
+ -1646, 14531, 22212, -2329, -1636, 14442, 22296, -2334, -1626, 14354, 22378, -2338, -1616, 14265, 22461, -2342,
+ -1606, 14177, 22544, -2347, -1595, 14088, 22626, -2351, -1585, 14000, 22708, -2355, -1575, 13911, 22791, -2359,
+ -1565, 13823, 22872, -2362, -1554, 13735, 22953, -2366, -1544, 13647, 23035, -2370, -1534, 13558, 23117, -2373,
+ -1523, 13470, 23198, -2377, -1513, 13382, 23279, -2380, -1503, 13294, 23360, -2383, -1492, 13206, 23440, -2386,
+ -1482, 13119, 23520, -2389, -1471, 13031, 23600, -2392, -1461, 12943, 23681, -2395, -1450, 12856, 23759, -2397,
+ -1440, 12768, 23840, -2400, -1429, 12681, 23918, -2402, -1419, 12593, 23999, -2405, -1408, 12506, 24077, -2407,
+ -1398, 12419, 24156, -2409, -1387, 12332, 24234, -2411, -1377, 12244, 24314, -2413, -1366, 12158, 24391, -2415,
+ -1356, 12071, 24469, -2416, -1345, 11984, 24547, -2418, -1334, 11897, 24624, -2419, -1324, 11811, 24702, -2421,
+ -1313, 11724, 24779, -2422, -1302, 11638, 24855, -2423, -1292, 11552, 24932, -2424, -1281, 11466, 25008, -2425,
+ -1271, 11380, 25085, -2426, -1260, 11294, 25160, -2426, -1249, 11208, 25236, -2427, -1239, 11122, 25312, -2427,
+ -1228, 11037, 25386, -2427, -1217, 10951, 25461, -2427, -1207, 10866, 25536, -2427, -1196, 10781, 25610, -2427,
+ -1185, 10696, 25684, -2427, -1175, 10611, 25758, -2426, -1164, 10526, 25832, -2426, -1153, 10441, 25905, -2425,
+ -1143, 10357, 25978, -2424, -1132, 10272, 26052, -2424, -1121, 10188, 26123, -2422, -1111, 10104, 26196, -2421,
+ -1100, 10020, 26268, -2420, -1089, 9936, 26340, -2419, -1079, 9853, 26411, -2417, -1068, 9769, 26482, -2415,
+ -1058, 9686, 26553, -2413, -1047, 9603, 26623, -2411, -1036, 9520, 26693, -2409, -1026, 9437, 26764, -2407,
+ -1015, 9354, 26834, -2405, -1005, 9271, 26904, -2402, -994, 9189, 26972, -2399, -984, 9107, 27042, -2397,
+ -973, 9025, 27110, -2394, -963, 8943, 27179, -2391, -952, 8861, 27246, -2387, -942, 8780, 27314, -2384,
+ -932, 8699, 27382, -2381, -921, 8617, 27449, -2377, -911, 8536, 27516, -2373, -900, 8456, 27581, -2369,
+ -890, 8375, 27648, -2365, -880, 8295, 27714, -2361, -869, 8215, 27778, -2356, -859, 8135, 27844, -2352,
+ -849, 8055, 27909, -2347, -839, 7975, 27974, -2342, -829, 7896, 28038, -2337, -818, 7817, 28101, -2332,
+ -808, 7738, 28165, -2327, -798, 7659, 28228, -2321, -788, 7580, 28292, -2316, -778, 7502, 28354, -2310,
+ -768, 7424, 28416, -2304, -758, 7346, 28478, -2298, -748, 7268, 28540, -2292, -738, 7191, 28600, -2285,
+ -728, 7114, 28661, -2279, -718, 7037, 28721, -2272, -709, 6960, 28782, -2265, -699, 6883, 28842, -2258,
+ -689, 6807, 28901, -2251, -679, 6731, 28960, -2244, -670, 6655, 29019, -2236, -660, 6580, 29076, -2228,
+ -650, 6504, 29135, -2221, -641, 6429, 29193, -2213, -631, 6354, 29249, -2204, -622, 6280, 29306, -2196,
+ -613, 6206, 29363, -2188, -603, 6131, 29419, -2179, -594, 6058, 29474, -2170, -584, 5984, 29529, -2161,
+ -575, 5911, 29584, -2152, -566, 5838, 29638, -2142, -557, 5765, 29693, -2133, -548, 5692, 29747, -2123,
+ -539, 5620, 29800, -2113, -530, 5548, 29853, -2103, -521, 5476, 29906, -2093, -512, 5405, 29958, -2083,
+ -503, 5334, 30009, -2072, -494, 5263, 30060, -2061, -485, 5192, 30111, -2050, -477, 5122, 30162, -2039,
+ -468, 5052, 30212, -2028, -459, 4982, 30262, -2017, -451, 4913, 30311, -2005, -442, 4844, 30359, -1993,
+ -434, 4775, 30408, -1981, -426, 4706, 30457, -1969, -417, 4638, 30503, -1956, -409, 4570, 30551, -1944,
+ -401, 4502, 30598, -1931, -393, 4435, 30644, -1918, -385, 4368, 30690, -1905, -377, 4301, 30736, -1892,
+ -369, 4235, 30780, -1878, -361, 4169, 30825, -1865, -353, 4103, 30869, -1851, -345, 4038, 30912, -1837,
+ -338, 3973, 30956, -1823, -330, 3908, 30998, -1808, -322, 3843, 31040, -1793, -315, 3779, 31083, -1779,
+ -307, 3715, 31124, -1764, -300, 3652, 31164, -1748, -293, 3589, 31205, -1733, -286, 3526, 31245, -1717,
+ -278, 3463, 31285, -1702, -271, 3401, 31324, -1686, -264, 3339, 31362, -1669, -257, 3278, 31400, -1653,
+ -251, 3217, 31438, -1636, -244, 3156, 31476, -1620, -237, 3096, 31512, -1603, -231, 3036, 31548, -1585,
+ -224, 2976, 31584, -1568, -218, 2917, 31619, -1550, -211, 2858, 31654, -1533, -205, 2799, 31689, -1515,
+ -199, 2741, 31722, -1496, -192, 2683, 31755, -1478, -186, 2626, 31787, -1459, -180, 2568, 31820, -1440,
+ -175, 2512, 31852, -1421, -169, 2455, 31884, -1402, -163, 2399, 31915, -1383, -157, 2344, 31944, -1363,
+ -152, 2289, 31974, -1343, -146, 2234, 32003, -1323, -141, 2179, 32033, -1303, -136, 2125, 32061, -1282,
+ -131, 2072, 32089, -1262, -125, 2018, 32116, -1241, -120, 1965, 32142, -1219, -115, 1913, 32168, -1198,
+ -111, 1861, 32194, -1176, -106, 1809, 32220, -1155, -101, 1758, 32244, -1133, -97, 1707, 32268, -1110,
+ -92, 1657, 32291, -1088, -88, 1607, 32314, -1065, -84, 1557, 32337, -1042, -79, 1508, 32358, -1019,
+ -75, 1459, 32380, -996, -71, 1411, 32400, -972, -67, 1363, 32420, -948, -64, 1315, 32441, -924,
+ -60, 1268, 32460, -900, -56, 1221, 32479, -876, -53, 1175, 32497, -851, -50, 1129, 32515, -826,
+ -46, 1084, 32531, -801, -43, 1039, 32547, -775, -40, 995, 32563, -750, -37, 951, 32578, -724,
+ -34, 907, 32593, -698, -32, 864, 32607, -671, -29, 821, 32621, -645, -26, 779, 32633, -618,
+ -24, 737, 32646, -591, -22, 696, 32658, -564, -20, 655, 32669, -536, -17, 614, 32679, -508,
+ -16, 575, 32690, -481, -14, 535, 32699, -452, -12, 496, 32708, -424, -10, 457, 32716, -395,
+ -9, 419, 32724, -366, -7, 382, 32730, -337, -6, 345, 32737, -308, -5, 308, 32743, -278,
+ -4, 272, 32748, -248, -3, 236, 32753, -218, -2, 201, 32757, -188, -2, 166, 32761, -157,
+ -1, 132, 32763, -126, -1, 98, 32766, -95, 0, 65, 32767, -64, 0, 32, 32767, -32
+};
+
+#endif
--- a/src/ft2_intrp_table.h
+++ b/src/ft2_intrp_table.h
@@ -5,8 +5,18 @@
#define CUBIC_WIDTH 4
#define CUBIC_WIDTH_BITS 2
+
+#if defined __amd64__ || defined _WIN64
+
#define CUBIC_PHASES 8192
#define CUBIC_PHASES_BITS 13
+
+#else
+
+#define CUBIC_PHASES 512
+#define CUBIC_PHASES_BITS 9
+
+#endif
#define CUBIC_FSHIFT (MIXER_FRAC_BITS-(CUBIC_PHASES_BITS+CUBIC_WIDTH_BITS))
#define CUBIC_FMASK ((CUBIC_WIDTH*CUBIC_PHASES)-CUBIC_WIDTH)
--- a/src/ft2_main.c
+++ b/src/ft2_main.c
@@ -182,7 +182,7 @@
config.audioFreq = 48000;
// try 16-bit audio at 1024 samples (44.1kHz/48kHz)
- config.specialFlags &= ~(BITDEPTH_24 + BUFFSIZE_512 + BUFFSIZE_2048);
+ config.specialFlags &= ~(BITDEPTH_32 + BUFFSIZE_512 + BUFFSIZE_2048);
config.specialFlags |= (BITDEPTH_16 + BUFFSIZE_1024);
setToDefaultAudioOutputDevice();
@@ -308,6 +308,8 @@
editor.diskOpReadOnOpen = true;
editor.programRunning = true;
+
+ audio.linearFreqTable = true;
}
static void cleanUpAndExit(void) // never call this inside the main loop!
@@ -410,7 +412,8 @@
uint64_t perfFreq64;
double dInt, dFrac;
- perfFreq64 = SDL_GetPerformanceFrequency(); assert(perfFreq64 != 0);
+ perfFreq64 = SDL_GetPerformanceFrequency();
+ assert(perfFreq64 != 0);
editor.dPerfFreq = (double)perfFreq64;
editor.dPerfFreqMulMicro = 1000000.0 / editor.dPerfFreq;
editor.dPerfFreqMulMs = 1.0 / (editor.dPerfFreq / 1000.0);
@@ -423,7 +426,11 @@
// fractional part scaled to 0..2^32-1
dFrac *= UINT32_MAX;
- video.vblankTimeLenFrac = (uint32_t)(dFrac + 0.5);
+ dFrac += 0.5;
+ if (dFrac > UINT32_MAX)
+ dFrac = UINT32_MAX;
+
+ video.vblankTimeLenFrac = (uint32_t)dFrac;
}
#ifdef _WIN32
--- a/src/ft2_mix.c
+++ b/src/ft2_mix.c
@@ -8,8 +8,10 @@
** --------------------- 32-bit fixed-point audio channel mixer ---------------------
** (Note: Mixing macros can be found in ft2_mix_macros.h)
**
-** 8bitbubsy: This is mostly ported from the i386-asm 32-bit mixer that was introduced in
-** FT2.08 (MS-DOS). It has been changed and improved quite a bit, though...
+** 8bitbubsy: This is mostly ported from the i386-asm 32-bit mixer that was introduced
+** in FT2.08 (MS-DOS). It has been changed and improved quite a bit, though...
+** Instead of 2-tap linear interpolation, it has 4-tap cubic spline interpolation.
+** For x86_64: Fixed-point precision is 32.32 instead of 16.16
**
** This file has separate routines for EVERY possible sampling variation:
** Interpolation on/off, volume ramping on/off, 8-bit, 16-bit, no loop, loop, pingpong.
@@ -39,13 +41,18 @@
const int8_t *CDA_LinearAdr, *smpPtr;
int32_t realPos, sample, *audioMixL, *audioMixR;
int32_t CDA_LVol, CDA_RVol;
- uint32_t pos, i, samplesToMix, CDA_BytesLeft;
+ uint32_t i, samplesToMix, CDA_BytesLeft;
+#if defined _WIN64 || defined __amd64__
+ uint64_t pos;
+#else
+ uint32_t pos;
+#endif
GET_VOL
if ((CDA_LVol | CDA_RVol) == 0)
{
- VOL0_OPTIMIZATION_NO_LOOP
+ VOL0_MIXING_NO_LOOP
return;
}
@@ -102,13 +109,18 @@
const int8_t *CDA_LinearAdr, *smpPtr;;
int32_t realPos, sample, *audioMixL, *audioMixR;
int32_t CDA_LVol, CDA_RVol;
- uint32_t pos, i, samplesToMix, CDA_BytesLeft;
+ uint32_t i, samplesToMix, CDA_BytesLeft;
+#if defined _WIN64 || defined __amd64__
+ uint64_t pos;
+#else
+ uint32_t pos;
+#endif
GET_VOL
if ((CDA_LVol | CDA_RVol) == 0)
{
- VOL0_OPTIMIZATION_LOOP
+ VOL0_MIXING_LOOP
return;
}
@@ -165,13 +177,18 @@
const int8_t *CDA_LinearAdr, *CDA_LinAdrRev, *smpPtr;
int32_t realPos, sample, *audioMixL, *audioMixR;
int32_t CDA_LVol, CDA_RVol;
- uint32_t pos, delta, i, samplesToMix, CDA_BytesLeft;
+ uint32_t i, samplesToMix, CDA_BytesLeft;
+#if defined _WIN64 || defined __amd64__
+ uint64_t pos, delta;
+#else
+ uint32_t pos, delta;
+#endif
GET_VOL
if ((CDA_LVol | CDA_RVol) == 0)
{
- VOL0_OPTIMIZATION_BIDI_LOOP
+ VOL0_MIXING_BIDI_LOOP
return;
}
@@ -229,13 +246,18 @@
const int8_t *CDA_LinearAdr, *smpPtr;
int32_t realPos, sample, sample2, sample3, sample4, *audioMixL, *audioMixR;
int32_t CDA_LVol, CDA_RVol;
- uint32_t pos, i, samplesToMix, CDA_BytesLeft;
+ uint32_t i, samplesToMix, CDA_BytesLeft;
+#if defined _WIN64 || defined __amd64__
+ uint64_t pos;
+#else
+ uint32_t pos;
+#endif
GET_VOL
if ((CDA_LVol | CDA_RVol) == 0)
{
- VOL0_OPTIMIZATION_NO_LOOP
+ VOL0_MIXING_NO_LOOP
return;
}
@@ -292,13 +314,18 @@
const int8_t *CDA_LinearAdr, *smpPtr;
int32_t realPos, sample, sample2, sample3, sample4, *audioMixL, *audioMixR;
int32_t CDA_LVol, CDA_RVol;
- uint32_t pos, i, samplesToMix, CDA_BytesLeft;
+ uint32_t i, samplesToMix, CDA_BytesLeft;
+#if defined _WIN64 || defined __amd64__
+ uint64_t pos;
+#else
+ uint32_t pos;
+#endif
GET_VOL
if ((CDA_LVol | CDA_RVol) == 0)
{
- VOL0_OPTIMIZATION_LOOP
+ VOL0_MIXING_LOOP
return;
}
@@ -355,13 +382,18 @@
const int8_t *CDA_LinearAdr, *CDA_LinAdrRev, *smpPtr;
int32_t realPos, sample, sample2, sample3, sample4, *audioMixL, *audioMixR;
int32_t CDA_LVol, CDA_RVol;
- uint32_t pos, delta, i, samplesToMix, CDA_BytesLeft;
+ uint32_t i, samplesToMix, CDA_BytesLeft;
+#if defined _WIN64 || defined __amd64__
+ uint64_t pos, delta;
+#else
+ uint32_t pos, delta;
+#endif
GET_VOL
if ((CDA_LVol | CDA_RVol) == 0)
{
- VOL0_OPTIMIZATION_BIDI_LOOP
+ VOL0_MIXING_BIDI_LOOP
return;
}
@@ -420,11 +452,16 @@
const int8_t *CDA_LinearAdr, *smpPtr;
int32_t realPos, sample, *audioMixL, *audioMixR;
int32_t CDA_LVolIP, CDA_RVolIP, CDA_LVol, CDA_RVol;
- uint32_t pos, i, samplesToMix, CDA_BytesLeft;
+ uint32_t i, samplesToMix, CDA_BytesLeft;
+#if defined _WIN64 || defined __amd64__
+ uint64_t pos;
+#else
+ uint32_t pos;
+#endif
if ((v->SLVol1 | v->SRVol1 | v->SLVol2 | v->SRVol2) == 0)
{
- VOL0_OPTIMIZATION_NO_LOOP
+ VOL0_MIXING_NO_LOOP
return;
}
@@ -487,14 +524,19 @@
static void mix8bRampLoop(voice_t *v, uint32_t numSamples)
{
- const int8_t *CDA_LinearAdr, *smpPtr;;
+ const int8_t *CDA_LinearAdr, *smpPtr;
int32_t realPos, sample, *audioMixL, *audioMixR;
int32_t CDA_LVolIP, CDA_RVolIP, CDA_LVol, CDA_RVol;
- uint32_t pos, i, samplesToMix, CDA_BytesLeft;
+ uint32_t i, samplesToMix, CDA_BytesLeft;
+#if defined _WIN64 || defined __amd64__
+ uint64_t pos;
+#else
+ uint32_t pos;
+#endif
if ((v->SLVol1 | v->SRVol1 | v->SLVol2 | v->SRVol2) == 0)
{
- VOL0_OPTIMIZATION_LOOP
+ VOL0_MIXING_LOOP
return;
}
@@ -560,11 +602,16 @@
const int8_t *CDA_LinearAdr, *CDA_LinAdrRev, *smpPtr;
int32_t realPos, sample, *audioMixL, *audioMixR;
int32_t CDA_LVolIP, CDA_RVolIP, CDA_LVol, CDA_RVol;
- uint32_t pos, delta, i, samplesToMix, CDA_BytesLeft;
+ uint32_t i, samplesToMix, CDA_BytesLeft;
+#if defined _WIN64 || defined __amd64__
+ uint64_t pos, delta;
+#else
+ uint32_t pos, delta;
+#endif
if ((v->SLVol1 | v->SRVol1 | v->SLVol2 | v->SRVol2) == 0)
{
- VOL0_OPTIMIZATION_BIDI_LOOP
+ VOL0_MIXING_BIDI_LOOP
return;
}
@@ -632,11 +679,16 @@
const int8_t *CDA_LinearAdr, *smpPtr;
int32_t realPos, sample, sample2, sample3, sample4, *audioMixL, *audioMixR;
int32_t CDA_LVolIP, CDA_RVolIP, CDA_LVol, CDA_RVol;
- uint32_t pos, i, samplesToMix, CDA_BytesLeft;
+ uint32_t i, samplesToMix, CDA_BytesLeft;
+#if defined _WIN64 || defined __amd64__
+ uint64_t pos;
+#else
+ uint32_t pos;
+#endif
if ((v->SLVol1 | v->SRVol1 | v->SLVol2 | v->SRVol2) == 0)
{
- VOL0_OPTIMIZATION_NO_LOOP
+ VOL0_MIXING_NO_LOOP
return;
}
@@ -702,11 +754,16 @@
const int8_t *CDA_LinearAdr, *smpPtr;
int32_t realPos, sample, sample2, sample3, sample4, *audioMixL, *audioMixR;
int32_t CDA_LVolIP, CDA_RVolIP, CDA_LVol, CDA_RVol;
- uint32_t pos, i, samplesToMix, CDA_BytesLeft;
+ uint32_t i, samplesToMix, CDA_BytesLeft;
+#if defined _WIN64 || defined __amd64__
+ uint64_t pos;
+#else
+ uint32_t pos;
+#endif
if ((v->SLVol1 | v->SRVol1 | v->SLVol2 | v->SRVol2) == 0)
{
- VOL0_OPTIMIZATION_LOOP
+ VOL0_MIXING_LOOP
return;
}
@@ -772,11 +829,16 @@
const int8_t *CDA_LinearAdr, *CDA_LinAdrRev, *smpPtr;
int32_t realPos, sample, sample2, sample3, sample4, *audioMixL, *audioMixR;
int32_t CDA_LVolIP, CDA_RVolIP, CDA_LVol, CDA_RVol;
- uint32_t pos, delta, i, samplesToMix, CDA_BytesLeft;
+ uint32_t i, samplesToMix, CDA_BytesLeft;
+#if defined _WIN64 || defined __amd64__
+ uint64_t pos, delta;
+#else
+ uint32_t pos, delta;
+#endif
if ((v->SLVol1 | v->SRVol1 | v->SLVol2 | v->SRVol2) == 0)
{
- VOL0_OPTIMIZATION_BIDI_LOOP
+ VOL0_MIXING_BIDI_LOOP
return;
}
@@ -849,13 +911,18 @@
const int16_t *CDA_LinearAdr, *smpPtr;
int32_t realPos, sample, *audioMixL, *audioMixR;
int32_t CDA_LVol, CDA_RVol;
- uint32_t pos, i, samplesToMix, CDA_BytesLeft;
+ uint32_t i, samplesToMix, CDA_BytesLeft;
+#if defined _WIN64 || defined __amd64__
+ uint64_t pos;
+#else
+ uint32_t pos;
+#endif
GET_VOL
if ((CDA_LVol | CDA_RVol) == 0)
{
- VOL0_OPTIMIZATION_NO_LOOP
+ VOL0_MIXING_NO_LOOP
return;
}
@@ -912,13 +979,18 @@
const int16_t *CDA_LinearAdr, *smpPtr;
int32_t realPos, sample, *audioMixL, *audioMixR;
int32_t CDA_LVol, CDA_RVol;
- uint32_t pos, i, samplesToMix, CDA_BytesLeft;
+ uint32_t i, samplesToMix, CDA_BytesLeft;
+#if defined _WIN64 || defined __amd64__
+ uint64_t pos;
+#else
+ uint32_t pos;
+#endif
GET_VOL
if ((CDA_LVol | CDA_RVol) == 0)
{
- VOL0_OPTIMIZATION_LOOP
+ VOL0_MIXING_LOOP
return;
}
@@ -975,13 +1047,18 @@
const int16_t *CDA_LinearAdr, *CDA_LinAdrRev, *smpPtr;
int32_t realPos, sample, *audioMixL, *audioMixR;
int32_t CDA_LVol, CDA_RVol;
- uint32_t pos, delta, i, samplesToMix, CDA_BytesLeft;
+ uint32_t i, samplesToMix, CDA_BytesLeft;
+#if defined _WIN64 || defined __amd64__
+ uint64_t pos, delta;
+#else
+ uint32_t pos, delta;
+#endif
GET_VOL
if ((CDA_LVol | CDA_RVol) == 0)
{
- VOL0_OPTIMIZATION_BIDI_LOOP
+ VOL0_MIXING_BIDI_LOOP
return;
}
@@ -1040,13 +1117,18 @@
const int16_t *CDA_LinearAdr, *smpPtr;
int32_t realPos, sample, sample2, sample3, sample4, *audioMixL, *audioMixR;
int32_t CDA_LVol, CDA_RVol;
- uint32_t pos, i, samplesToMix, CDA_BytesLeft;
+ uint32_t i, samplesToMix, CDA_BytesLeft;
+#if defined _WIN64 || defined __amd64__
+ uint64_t pos;
+#else
+ uint32_t pos;
+#endif
GET_VOL
if ((CDA_LVol | CDA_RVol) == 0)
{
- VOL0_OPTIMIZATION_NO_LOOP
+ VOL0_MIXING_NO_LOOP
return;
}
@@ -1103,13 +1185,18 @@
const int16_t *CDA_LinearAdr, *smpPtr;
int32_t realPos, sample, sample2, sample3, sample4, *audioMixL, *audioMixR;
int32_t CDA_LVol, CDA_RVol;
- uint32_t pos, i, samplesToMix, CDA_BytesLeft;
+ uint32_t i, samplesToMix, CDA_BytesLeft;
+#if defined _WIN64 || defined __amd64__
+ uint64_t pos;
+#else
+ uint32_t pos;
+#endif
GET_VOL
if ((CDA_LVol| CDA_RVol) == 0)
{
- VOL0_OPTIMIZATION_LOOP
+ VOL0_MIXING_LOOP
return;
}
@@ -1166,13 +1253,18 @@
const int16_t *CDA_LinearAdr, *CDA_LinAdrRev, *smpPtr;
int32_t realPos, sample, sample2, sample3, sample4, *audioMixL, *audioMixR;
int32_t CDA_LVol, CDA_RVol;
- uint32_t pos, delta, i, samplesToMix, CDA_BytesLeft;
+ uint32_t i, samplesToMix, CDA_BytesLeft;
+#if defined _WIN64 || defined __amd64__
+ uint64_t pos, delta;
+#else
+ uint32_t pos, delta;
+#endif
GET_VOL
if ((CDA_LVol | CDA_RVol) == 0)
{
- VOL0_OPTIMIZATION_BIDI_LOOP
+ VOL0_MIXING_BIDI_LOOP
return;
}
@@ -1231,11 +1323,16 @@
const int16_t *CDA_LinearAdr, *smpPtr;
int32_t realPos, sample, *audioMixL, *audioMixR;
int32_t CDA_LVolIP, CDA_RVolIP, CDA_LVol, CDA_RVol;
- uint32_t pos, i, samplesToMix, CDA_BytesLeft;
+ uint32_t i, samplesToMix, CDA_BytesLeft;
+#if defined _WIN64 || defined __amd64__
+ uint64_t pos;
+#else
+ uint32_t pos;
+#endif
if ((v->SLVol1 | v->SRVol1 | v->SLVol2 | v->SRVol2) == 0)
{
- VOL0_OPTIMIZATION_NO_LOOP
+ VOL0_MIXING_NO_LOOP
return;
}
@@ -1301,11 +1398,16 @@
const int16_t *CDA_LinearAdr, *smpPtr;
int32_t realPos, sample, *audioMixL, *audioMixR;
int32_t CDA_LVolIP, CDA_RVolIP, CDA_LVol, CDA_RVol;
- uint32_t pos, i, samplesToMix, CDA_BytesLeft;
+ uint32_t i, samplesToMix, CDA_BytesLeft;
+#if defined _WIN64 || defined __amd64__
+ uint64_t pos;
+#else
+ uint32_t pos;
+#endif
if ((v->SLVol1 | v->SRVol1 | v->SLVol2 | v->SRVol2) == 0)
{
- VOL0_OPTIMIZATION_LOOP
+ VOL0_MIXING_LOOP
return;
}
@@ -1371,11 +1473,16 @@
const int16_t *CDA_LinearAdr, *CDA_LinAdrRev, *smpPtr;
int32_t realPos, sample, *audioMixL, *audioMixR;
int32_t CDA_LVolIP, CDA_RVolIP, CDA_LVol, CDA_RVol;
- uint32_t pos, delta, i, samplesToMix, CDA_BytesLeft;
+ uint32_t i, samplesToMix, CDA_BytesLeft;
+#if defined _WIN64 || defined __amd64__
+ uint64_t pos, delta;
+#else
+ uint32_t pos, delta;
+#endif
if ((v->SLVol1 | v->SRVol1 | v->SLVol2 | v->SRVol2) == 0)
{
- VOL0_OPTIMIZATION_BIDI_LOOP
+ VOL0_MIXING_BIDI_LOOP
return;
}
@@ -1443,11 +1550,16 @@
const int16_t *CDA_LinearAdr, *smpPtr;
int32_t realPos, sample, sample2, sample3, sample4, *audioMixL, *audioMixR;
int32_t CDA_LVolIP, CDA_RVolIP, CDA_LVol, CDA_RVol;
- uint32_t pos, i, samplesToMix, CDA_BytesLeft;
+ uint32_t i, samplesToMix, CDA_BytesLeft;
+#if defined _WIN64 || defined __amd64__
+ uint64_t pos;
+#else
+ uint32_t pos;
+#endif
if ((v->SLVol1 | v->SRVol1 | v->SLVol2 | v->SRVol2) == 0)
{
- VOL0_OPTIMIZATION_NO_LOOP
+ VOL0_MIXING_NO_LOOP
return;
}
@@ -1513,11 +1625,16 @@
const int16_t *CDA_LinearAdr, *smpPtr;
int32_t realPos, sample, sample2, sample3, sample4, *audioMixL, *audioMixR;
int32_t CDA_LVolIP, CDA_RVolIP, CDA_LVol, CDA_RVol;
- uint32_t pos, i, samplesToMix, CDA_BytesLeft;
+ uint32_t i, samplesToMix, CDA_BytesLeft;
+#if defined _WIN64 || defined __amd64__
+ uint64_t pos;
+#else
+ uint32_t pos;
+#endif
if ((v->SLVol1 | v->SRVol1 | v->SLVol2 | v->SRVol2) == 0)
{
- VOL0_OPTIMIZATION_LOOP
+ VOL0_MIXING_LOOP
return;
}
@@ -1583,11 +1700,16 @@
const int16_t *CDA_LinearAdr, *CDA_LinAdrRev, *smpPtr;
int32_t realPos, sample, sample2, sample3, sample4, *audioMixL, *audioMixR;
int32_t CDA_LVolIP, CDA_RVolIP, CDA_LVol, CDA_RVol;
- uint32_t pos, delta, i, samplesToMix, CDA_BytesLeft;
+ uint32_t i, samplesToMix, CDA_BytesLeft;
+#if defined _WIN64 || defined __amd64__
+ uint64_t pos, delta;
+#else
+ uint32_t pos, delta;
+#endif
if ((v->SLVol1 | v->SRVol1 | v->SLVol2 | v->SRVol2) == 0)
{
- VOL0_OPTIMIZATION_BIDI_LOOP
+ VOL0_MIXING_BIDI_LOOP
return;
}
--- a/src/ft2_mix_macros.h
+++ b/src/ft2_mix_macros.h
@@ -15,7 +15,29 @@
v->SLVol2 = CDA_LVol; \
v->SRVol2 = CDA_RVol; \
+#if defined _WIN64 || defined __amd64__
+
#define GET_MIXER_VARS \
+ const uint64_t SFrq = v->SFrq; \
+ audioMixL = audio.mixBufferL; \
+ audioMixR = audio.mixBufferR; \
+ const bool mixInMono = (CDA_LVol == CDA_RVol); \
+ realPos = v->SPos; \
+ pos = v->SPosDec; \
+
+#define GET_MIXER_VARS_RAMP \
+ const uint64_t SFrq = v->SFrq; \
+ audioMixL = audio.mixBufferL; \
+ audioMixR = audio.mixBufferR; \
+ CDA_LVolIP = v->SLVolIP; \
+ CDA_RVolIP = v->SRVolIP; \
+ const bool mixInMono = (v->SLVol2 == v->SRVol2) && (CDA_LVolIP == CDA_RVolIP); \
+ realPos = v->SPos; \
+ pos = v->SPosDec; \
+
+#else
+
+#define GET_MIXER_VARS \
const uint32_t SFrq = v->SFrq; \
audioMixL = audio.mixBufferL; \
audioMixR = audio.mixBufferR; \
@@ -33,6 +55,8 @@
realPos = v->SPos; \
pos = v->SPosDec; \
+#endif
+
#define SET_BASE8 \
CDA_LinearAdr = v->SBase8; \
smpPtr = CDA_LinearAdr + realPos; \
@@ -176,22 +200,40 @@
/* SAMPLES-TO-MIX LIMITING MACROS */
/* ----------------------------------------------------------------------- */
-#if defined __amd64__ || defined _WIN64
+#if defined _WIN64 || defined __amd64__
#define LIMIT_MIX_NUM \
- samplesToMix = UINT32_MAX; \
+ samplesToMix = CDA_BytesLeft; \
i = (v->SLen - 1) - realPos; \
\
- if (SFrq > i>>MIXER_FRAC_BITS) \
+ if (SFrq > 0) \
{ \
- const uint64_t tmp64 = ((uint64_t)i << MIXER_FRAC_BITS) | (pos ^ MIXER_FRAC_MASK); \
- samplesToMix = (uint32_t)(tmp64 / SFrq); \
- samplesToMix++; \
+ uint64_t tmp64 = ((uint64_t)i << MIXER_FRAC_BITS) | (pos ^ MIXER_FRAC_MASK); \
+ samplesToMix = (uint32_t)(tmp64 / SFrq) + 1; \
+ if (samplesToMix > CDA_BytesLeft) \
+ samplesToMix = CDA_BytesLeft; \
} \
\
- if (samplesToMix > CDA_BytesLeft) \
- samplesToMix = CDA_BytesLeft; \
+#define START_BIDI \
+ if (v->backwards) \
+ { \
+ delta = 0 - SFrq; \
+ assert(realPos >= v->SRepS && realPos < v->SLen); \
+ realPos = ~realPos; \
+ smpPtr = CDA_LinAdrRev + realPos; \
+ pos ^= MIXER_FRAC_MASK; \
+ } \
+ else \
+ { \
+ delta = SFrq; \
+ assert(realPos >= 0 && realPos < v->SLen); \
+ smpPtr = CDA_LinearAdr + realPos; \
+ } \
+ \
+ const int32_t CDA_IPValH = (int64_t)delta >> MIXER_FRAC_BITS; \
+ const uint32_t CDA_IPValL = delta & MIXER_FRAC_MASK; \
+
#else
#define LIMIT_MIX_NUM \
@@ -206,6 +248,25 @@
if (samplesToMix > CDA_BytesLeft) \
samplesToMix = CDA_BytesLeft; \
+#define START_BIDI \
+ if (v->backwards) \
+ { \
+ delta = 0 - SFrq; \
+ assert(realPos >= v->SRepS && realPos < v->SLen); \
+ realPos = ~realPos; \
+ smpPtr = CDA_LinAdrRev + realPos; \
+ pos ^= MIXER_FRAC_MASK; \
+ } \
+ else \
+ { \
+ delta = SFrq; \
+ assert(realPos >= 0 && realPos < v->SLen); \
+ smpPtr = CDA_LinearAdr + realPos; \
+ } \
+ \
+ const int32_t CDA_IPValH = (int32_t)delta >> MIXER_FRAC_BITS; \
+ const uint32_t CDA_IPValL = delta & MIXER_FRAC_MASK; \
+
#endif
#define LIMIT_MIX_NUM_RAMP \
@@ -249,25 +310,6 @@
v->backwards ^= 1; \
} \
-#define START_BIDI \
- if (v->backwards) \
- { \
- delta = 0 - SFrq; \
- assert(realPos >= v->SRepS && realPos < v->SLen); \
- realPos = ~realPos; \
- smpPtr = CDA_LinAdrRev + realPos; \
- pos ^= MIXER_FRAC_MASK; \
- } \
- else \
- { \
- delta = SFrq; \
- assert(realPos >= 0 && realPos < v->SLen); \
- smpPtr = CDA_LinearAdr + realPos; \
- } \
- \
- const int32_t CDA_IPValH = (int32_t)delta >> MIXER_FRAC_BITS; \
- const int32_t CDA_IPValL = delta & MIXER_FRAC_MASK; \
-
#define END_BIDI \
if (v->backwards) \
{ \
@@ -281,19 +323,22 @@
\
/* ----------------------------------------------------------------------- */
-/* VOLUME=0 OPTIMIZATION MACROS */
+/* VOLUME=0 MIXING MACROS */
/* ----------------------------------------------------------------------- */
+
+#if defined _WIN64 || defined __amd64__
+
#define VOL0_INC_POS \
- const uint64_t newPos = (uint64_t)v->SFrq * numSamples; \
+ const uint64_t newPos = v->SFrq * (uint64_t)numSamples; \
const uint32_t addPos = (uint32_t)(newPos >> MIXER_FRAC_BITS); \
- uint32_t addFrac = (uint32_t)(newPos & MIXER_FRAC_MASK); \
+ uint64_t addFrac = newPos & MIXER_FRAC_MASK; \
\
addFrac += v->SPosDec; \
- realPos = v->SPos + addPos + (addFrac >> MIXER_FRAC_BITS); \
+ realPos = v->SPos + addPos + (uint32_t)(addFrac >> MIXER_FRAC_BITS); \
pos = addFrac & MIXER_FRAC_MASK; \
-#define VOL0_OPTIMIZATION_NO_LOOP \
+#define VOL0_MIXING_NO_LOOP \
VOL0_INC_POS \
if (realPos >= v->SLen) \
{ \
@@ -303,14 +348,67 @@
\
SET_BACK_MIXER_POS
-#define VOL0_OPTIMIZATION_LOOP \
+#define VOL0_MIXING_LOOP \
VOL0_INC_POS \
+ if (realPos >= v->SLen) \
+ { \
+ if (v->SRepL >= 2) \
+ realPos = v->SRepS + ((realPos - v->SLen) % v->SRepL); \
+ else \
+ realPos = v->SRepS; \
+ } \
+ \
+ SET_BACK_MIXER_POS
+
+#define VOL0_MIXING_BIDI_LOOP \
+ VOL0_INC_POS \
+ if (realPos >= v->SLen) \
+ { \
+ if (v->SRepL >= 2) \
+ { \
+ const int32_t overflow = realPos - v->SLen; \
+ const int32_t cycles = overflow / v->SRepL; \
+ const int32_t phase = overflow % v->SRepL; \
+ \
+ realPos = v->SRepS + phase; \
+ v->backwards ^= !(cycles & 1); \
+ } \
+ else \
+ { \
+ realPos = v->SRepS; \
+ } \
+ } \
+ \
+ SET_BACK_MIXER_POS
+
+#else
+
+#define VOL0_INC_POS \
+ assert(numSamples <= 65536); \
+ \
+ pos = v->SPosDec + ((v->SFrq & 0xFFFF) * numSamples); \
+ realPos = v->SPos + ((v->SFrq >> 16) * numSamples) + (pos >> 16); \
+ pos &= 0xFFFF; \
+
+#define VOL0_MIXING_NO_LOOP \
+ VOL0_INC_POS \
+ if (realPos >= v->SLen) \
+ { \
+ v->mixRoutine = NULL; /* shut down voice */ \
+ return; \
+ } \
+ \
+ SET_BACK_MIXER_POS
+
+#define VOL0_MIXING_LOOP \
+ VOL0_INC_POS \
+ \
while (realPos >= v->SLen) \
realPos -= v->SRepL; \
\
SET_BACK_MIXER_POS
-#define VOL0_OPTIMIZATION_BIDI_LOOP \
+#define VOL0_MIXING_BIDI_LOOP \
VOL0_INC_POS \
while (realPos >= v->SLen) \
{ \
@@ -319,3 +417,5 @@
} \
\
SET_BACK_MIXER_POS
+
+#endif
--- a/src/ft2_module_loader.c
+++ b/src/ft2_module_loader.c
@@ -1747,14 +1747,13 @@
songTmp.len = h.len;
songTmp.repS = h.repS;
songTmp.antChn = (uint8_t)h.antChn;
- songTmp.speed = h.defSpeed ? h.defSpeed : 125;
- songTmp.tempo = h.defTempo ? h.defTempo : 6;
+ songTmp.speed = h.defSpeed;
+ songTmp.tempo = h.defTempo;
songTmp.ver = h.ver;
linearFreqTable = h.flags & 1;
songTmp.speed = CLAMP(songTmp.speed, 32, 255);
- if (songTmp.tempo > 31)
- songTmp.tempo = 31;
+ songTmp.tempo = CLAMP(songTmp.tempo, 1, 31);
songTmp.initialTempo = songTmp.tempo;
@@ -2463,8 +2462,7 @@
resetWavRenderer();
clearPattMark();
resetTrimSizes();
-
- song.musicTime = 0;
+ resetPlaybackTime();
diskOpSetFilename(DISKOP_ITEM_MODULE, editor.tmpFilenameU);
--- a/src/ft2_module_saver.c
+++ b/src/ft2_module_saver.c
@@ -84,7 +84,7 @@
ai--;
h.antInstrs = ai;
- h.flags = linearFrqTab;
+ h.flags = audio.linearFreqTable;
memcpy(h.songTab, song.songTab, sizeof (song.songTab));
if (fwrite(&h, sizeof (h), 1, f) != 1)
@@ -278,7 +278,7 @@
incompatEfx = false;
noteUnderflow = false;
- if (linearFrqTab)
+ if (audio.linearFreqTable)
okBoxThreadSafe(0, "System message", "Linear frequency table used!");
// sanity checking
--- a/src/ft2_nibbles.c
+++ b/src/ft2_nibbles.c
@@ -9,6 +9,7 @@
#include "ft2_gui.h"
#include "ft2_pattern_ed.h"
#include "ft2_bmp.h"
+#include "ft2_tables.h"
#define NI_MAXLEVEL 30
@@ -366,21 +367,15 @@
static void drawScoresLives(void)
{
- char str[8];
-
// player 1
+ assert(NI_P1Lives < 100);
hexOutBg(89, 27, PAL_FORGRND, PAL_DESKTOP, NI_P1Score, 8);
+ textOutFixed(131, 39, PAL_FORGRND, PAL_DESKTOP, dec2StrTab[NI_P1Lives]);
- assert(NI_P1Lives < 100);
- sprintf(str, "%02d", NI_P1Lives);
- textOutFixed(131, 39, PAL_FORGRND, PAL_DESKTOP, str);
-
// player 2
- hexOutBg(89, 75, PAL_FORGRND, PAL_DESKTOP, NI_P2Score, 8);
-
assert(NI_P2Lives < 100);
- sprintf(str, "%02d", NI_P2Lives);
- textOutFixed(131, 87, PAL_FORGRND, PAL_DESKTOP, str);
+ hexOutBg(89, 75, PAL_FORGRND, PAL_DESKTOP, NI_P2Score, 8);
+ textOutFixed(131, 87, PAL_FORGRND, PAL_DESKTOP, dec2StrTab[NI_P2Lives]);
}
static void nibblesDecLives(int16_t l1, int16_t l2)
--- a/src/ft2_pattern_ed.c
+++ b/src/ft2_pattern_ed.c
@@ -37,6 +37,7 @@
static const uint16_t iSwitchExtX[4] = { 221, 262, 303, 344 };
static int32_t lastMouseX, lastMouseY;
+static int32_t last_TimeH, last_TimeM, last_TimeS;
bool allocatePattern(uint16_t nr) // for tracker use only, not in loader!
{
@@ -1679,7 +1680,7 @@
{
bool audioWasntLocked;
- if (song.len == 0)
+ if (song.len <= 1)
return;
audioWasntLocked = !audio.locked;
@@ -2181,24 +2182,20 @@
void drawSongBPM(uint16_t val)
{
- char str[8];
-
if (editor.ui.extended)
return;
- sprintf(str, "%03d", val);
- textOutFixed(145, 36, PAL_FORGRND, PAL_DESKTOP, str);
+ assert(val < 256);
+ textOutFixed(145, 36, PAL_FORGRND, PAL_DESKTOP, dec3StrTab[val]);
}
void drawSongSpeed(uint16_t val)
{
- char str[8];
-
if (editor.ui.extended)
return;
- sprintf(str, "%02d", val);
- textOutFixed(152, 50, PAL_FORGRND, PAL_DESKTOP, str);
+ assert(val < 32);
+ textOutFixed(152, 50, PAL_FORGRND, PAL_DESKTOP, dec2StrTab[val]);
}
void drawEditPattern(uint16_t editPattern)
@@ -2237,55 +2234,43 @@
hexOutBg(x, y, PAL_FORGRND, PAL_DESKTOP, pattLens[editPattern], 3);
}
-void drawGlobalVol(int16_t globalVol)
+void drawGlobalVol(uint16_t val)
{
- char str[8];
-
if (editor.ui.extended)
return;
- assert(globalVol >= 0 && globalVol <= 64);
- sprintf(str, "%02d", globalVol);
- textOutFixed(87, 80, PAL_FORGRND, PAL_DESKTOP, str);
+ assert(val <= 64);
+ textOutFixed(87, 80, PAL_FORGRND, PAL_DESKTOP, dec2StrTab[val]);
}
void drawIDAdd(void)
{
- char str[8];
-
assert(editor.ID_Add <= 16);
- sprintf(str, "%02d", editor.ID_Add);
- textOutFixed(152, 64, PAL_FORGRND, PAL_DESKTOP, str);
+ textOutFixed(152, 64, PAL_FORGRND, PAL_DESKTOP, dec2StrTab[editor.ID_Add]);
}
+void resetPlaybackTime(void)
+{
+ song.musicTime64 = 0;
+ last_TimeH = 0;
+ last_TimeM = 0;
+ last_TimeS = 0;
+}
+
void drawPlaybackTime(void)
{
- char str[2 + 1];
- uint32_t a, MI_TimeH, MI_TimeM, MI_TimeS;
+ if (songPlaying)
+ {
+ uint32_t seconds = song.musicTime64 >> 32;
- a = ((song.musicTime >> 8) * 5) >> 9;
- MI_TimeH = a / 3600;
- a -= (MI_TimeH * 3600);
- MI_TimeM = a / 60;
- MI_TimeS = a - (MI_TimeM * 60);
+ last_TimeH = seconds / 3600; seconds -= last_TimeH * 3600;
+ last_TimeM = seconds / 60; seconds -= last_TimeM * 60;
+ last_TimeS = seconds;
+ }
- // hours
- str[0] = '0' + (char)(MI_TimeH / 10);
- str[1] = '0' + (char)(MI_TimeH % 10);
- str[2] = '\0';
- textOutFixed(235, 80, PAL_FORGRND, PAL_DESKTOP, str);
-
- // minutes
- str[0] = '0' + (char)(MI_TimeM / 10);
- str[1] = '0' + (char)(MI_TimeM % 10);
- str[2] = '\0';
- textOutFixed(255, 80, PAL_FORGRND, PAL_DESKTOP, str);
-
- // seconds
- str[0] = '0' + (char)(MI_TimeS / 10);
- str[1] = '0' + (char)(MI_TimeS % 10);
- str[2] = '\0';
- textOutFixed(275, 80, PAL_FORGRND, PAL_DESKTOP, str);
+ textOutFixed(235, 80, PAL_FORGRND, PAL_DESKTOP, dec2StrTab[last_TimeH]);
+ textOutFixed(255, 80, PAL_FORGRND, PAL_DESKTOP, dec2StrTab[last_TimeM]);
+ textOutFixed(275, 80, PAL_FORGRND, PAL_DESKTOP, dec2StrTab[last_TimeS]);
}
void drawSongName(void)
@@ -2716,10 +2701,10 @@
editor.globalVol = song.globVol;
editor.timer = 1;
- if (songPlaying)
- song.musicTime = 0;
+ resetPlaybackTime();
- setFrqTab(true);
+ if (!audio.linearFreqTable)
+ setFrqTab(true);
clearPattMark();
resetWavRenderer();
--- a/src/ft2_pattern_ed.h
+++ b/src/ft2_pattern_ed.h
@@ -57,6 +57,8 @@
int16_t markX1, markX2, markY1, markY2;
} pattMark;
+void resetPlaybackTime(void);
+
bool allocatePattern(uint16_t nr);
void killPatternIfUnused(uint16_t nr);
uint8_t getMaxVisibleChannels(void);
@@ -133,7 +135,7 @@
void drawSongSpeed(uint16_t val);
void drawEditPattern(uint16_t editPattern);
void drawPatternLength(uint16_t editPattern);
-void drawGlobalVol(int16_t globalVol);
+void drawGlobalVol(uint16_t val);
void drawIDAdd(void);
void drawPlaybackTime(void);
void drawSongName(void);
--- a/src/ft2_pushbuttons.c
+++ b/src/ft2_pushbuttons.c
@@ -335,15 +335,15 @@
// ------ CONFIG MISCELLANEOUS PUSHBUTTONS ------
//x, y, w, h, p, d, text #1, text #2, funcOnDown, funcOnUp
- { 113, 155, 93, 16, 0, 0, editor.ui.fullscreenButtonText, NULL, NULL, toggleFullScreen },
- { 370, 121, 18, 13, 1, 4, ARROW_UP_STRING, NULL, configQuantizeUp, NULL },
- { 387, 121, 18, 13, 1, 4, ARROW_DOWN_STRING, NULL, configQuantizeDown, NULL },
- { 594, 106, 18, 13, 1, 4, ARROW_UP_STRING, NULL, configMIDIChnUp, NULL },
- { 611, 106, 18, 13, 1, 4, ARROW_DOWN_STRING, NULL, configMIDIChnDown, NULL },
- { 594, 120, 18, 13, 1, 4, ARROW_UP_STRING, NULL, configMIDITransUp, NULL },
- { 611, 120, 18, 13, 1, 4, ARROW_DOWN_STRING, NULL, configMIDITransDown, NULL },
- { 556, 158, 22, 13, 1, 4, ARROW_LEFT_STRING, NULL, configMIDISensDown, NULL },
- { 607, 158, 22, 13, 1, 4, ARROW_RIGHT_STRING, NULL, configMIDISensUp, NULL },
+ { 113, 155, 93, 16, 0, 0, editor.ui.fullscreenButtonText, NULL, NULL, toggleFullScreen },
+ { 370, 121, 18, 13, 1, 4, ARROW_UP_STRING, NULL, configQuantizeUp, NULL },
+ { 387, 121, 18, 13, 1, 4, ARROW_DOWN_STRING, NULL, configQuantizeDown, NULL },
+ { 594, 106, 18, 13, 1, 4, ARROW_UP_STRING, NULL, configMIDIChnUp, NULL },
+ { 611, 106, 18, 13, 1, 4, ARROW_DOWN_STRING, NULL, configMIDIChnDown, NULL },
+ { 594, 120, 18, 13, 1, 4, ARROW_UP_STRING, NULL, configMIDITransUp, NULL },
+ { 611, 120, 18, 13, 1, 4, ARROW_DOWN_STRING, NULL, configMIDITransDown, NULL },
+ { 556, 158, 22, 13, 1, 4, ARROW_LEFT_STRING, NULL, configMIDISensDown, NULL },
+ { 607, 158, 22, 13, 1, 4, ARROW_RIGHT_STRING, NULL, configMIDISensUp, NULL },
#ifdef HAS_MIDI
// ------ CONFIG MIDI PUSHBUTTONS ------
@@ -357,7 +357,7 @@
{ 70, 2, 58, 16, 0, 0, "Save", NULL, NULL, pbDiskOpSave },
{ 70, 19, 58, 16, 0, 0, "Delete", NULL, NULL, pbDiskOpDelete },
{ 70, 36, 58, 16, 0, 0, "Rename", NULL, NULL, pbDiskOpRename },
- { 70, 53, 58, 16, 0, 0, "Make dir.", NULL, NULL, pbDiskOpMakeDir },
+ { 70, 53, 58, 16, 0, 0, "Make dir.", NULL, NULL, pbDiskOpMakeDir },
{ 70, 70, 58, 16, 0, 0, "Refresh", NULL, NULL, pbDiskOpRefresh },
{ 70, 87, 58, 16, 0, 0, "Set path", NULL, NULL, pbDiskOpSetPath },
{ 70, 104, 58, 16, 0, 0, "Show all", NULL, NULL, pbDiskOpShowAll },
--- a/src/ft2_radiobuttons.c
+++ b/src/ft2_radiobuttons.c
@@ -87,8 +87,10 @@
//x, y, w, group, funcOnUp
{ 509, 16, 66, RB_GROUP_CONFIG_AUDIO_FREQ, rbConfigAudio44kHz },
{ 509, 30, 121, RB_GROUP_CONFIG_AUDIO_FREQ, rbConfigAudio48kHz },
+#if defined __amd64__ || defined _WIN64
{ 509, 44, 66, RB_GROUP_CONFIG_AUDIO_FREQ, rbConfigAudio96kHz },
-
+ { 509, 58, 73, RB_GROUP_CONFIG_AUDIO_FREQ, rbConfigAudio192kHz },
+#endif
// audio input frequency
//x, y, w, group, funcOnUp
{ 180, 156, 60, RB_GROUP_CONFIG_AUDIO_INPUT_FREQ, rbConfigAudioInput44kHz },
--- a/src/ft2_radiobuttons.h
+++ b/src/ft2_radiobuttons.h
@@ -57,7 +57,10 @@
// AUDIO FREQUENCY
RB_CONFIG_AUDIO_44KHZ,
RB_CONFIG_AUDIO_48KHZ,
+#if defined __amd64__ || defined _WIN64
RB_CONFIG_AUDIO_96KHZ,
+ RB_CONFIG_AUDIO_192KHZ,
+#endif
// AUDIO INPUT FREQUENCY
RB_CONFIG_AUDIO_INPUT_44KHZ,
--- a/src/ft2_replayer.c
+++ b/src/ft2_replayer.c
@@ -22,21 +22,30 @@
/* This is a *huge* mess, directly ported from the original FT2 code (and modified).
** You will experience a lot of headaches if you dig into it...
-** If something looks to be off, it's probably not!
+** If something looks to be off, it probably isn't!
*/
+/* Tables for pre-calculated stuff on run time and when changing freq. and/or linear/amiga mode.
+** FT2 obviously didn't have such big tables.
+*/
+
+static uint32_t musicTimeTab[256-32];
+static uint64_t period2ScopeDeltaTab[65536], scopeLogTab[768], scopeAmigaPeriodDiv;
+#if defined _WIN64 || defined __amd64__
+static uint64_t period2DeltaTab[65536], logTab[768], amigaPeriodDiv;
+#else
+static uint32_t period2DeltaTab[65536], logTab[768], amigaPeriodDiv;
+#endif
+
static bool bxxOverflow;
-static int32_t oldPeriod;
-static uint32_t period2DeltaTab[768][32], oldDelta;
-static double dAmigaPeriodDiv;
static tonTyp nilPatternLine;
// globally accessed
int8_t playMode = 0;
-bool linearFrqTab = false, songPlaying = false, audioPaused = false, musicPaused = false;
+bool songPlaying = false, audioPaused = false, musicPaused = false;
volatile bool replayerBusy = false;
-const int16_t *note2Period = NULL;
+const uint16_t *note2Period = NULL;
int16_t pattLens[MAX_PATTERNS];
stmTyp stm[MAX_VOICES];
songTyp song;
@@ -43,8 +52,6 @@
instrTyp *instr[132];
tonTyp *patt[MAX_PATTERNS];
-// CODE START
-
void fixSongName(void) // removes spaces from right side of song name
{
for (int16_t i = 20; i >= 0; i--)
@@ -216,23 +223,76 @@
return i+1;
}
-void setFrqTab(bool linear)
+// called every time you change linear/amiga mode and mixing frequency
+static void calcDelta2PeriodTabs(void)
{
- linearFrqTab = linear;
+ int32_t baseDelta;
+ uint32_t i;
- if (linearFrqTab)
+ period2DeltaTab[0] = 0; // FT2 converts period 0 to a delta of 0
+
+ if (audio.linearFreqTable)
{
- audio.linearFreqTable = true;
- note2Period = linearPeriods;
+ for (i = 1; i < 65536; i++)
+ {
+ const uint16_t invPeriod = (12 * 192 * 4) - (uint16_t)i; // this intentionally overflows uint16_t to be accurate to FT2
+ const int32_t octave = invPeriod / 768;
+ const int32_t period = invPeriod % 768;
+ const int32_t shift = (14 - octave) & 0x1F; // this is exactly how FT2 does it
+
+#if defined _WIN64 || defined __amd64__
+ uint64_t delta = logTab[period];
+#else
+ uint32_t delta = logTab[period];
+#endif
+ uint64_t scopeDelta = scopeLogTab[period];
+
+ if (shift > 0)
+ {
+ delta >>= shift;
+ scopeDelta >>= shift;
+ }
+
+ period2DeltaTab[i] = delta;
+ period2ScopeDeltaTab[i] = scopeDelta;
+ }
}
else
{
- audio.linearFreqTable = false;
- note2Period = amigaPeriods;
+ // Note: these calculations should remain truncated and not rounded!
+ for (i = 1; i < 65536; i++)
+ {
+ period2DeltaTab[i] = amigaPeriodDiv / i;
+ period2ScopeDeltaTab[i] = scopeAmigaPeriodDiv / i;
+ }
}
- resetCachedFrequencyVars();
+ // for piano in Instr. Ed.
+ // (this delta is small enough to fit in int32_t even with 32.32 deltas)
+ if (audio.linearFreqTable)
+ baseDelta = (int32_t)period2DeltaTab[7680];
+ else
+ baseDelta = (int32_t)period2DeltaTab[1712*16];
+
+ audio.dPianoDeltaMul = 1.0 / baseDelta;
+}
+
+void setFrqTab(bool linear)
+{
+ pauseAudio();
+
+ audio.linearFreqTable = linear;
+
+ if (audio.linearFreqTable)
+ note2Period = linearPeriods;
+ else
+ note2Period = amigaPeriods;
+
+ calcDelta2PeriodTabs();
+
+ resumeAudio();
+
// update "frequency table" radiobutton, if it's shown
if (editor.ui.configScreenShown && editor.currConfigScreen == CONFIG_SCREEN_IO_DEVICES)
setConfigIORadioButtonStates();
@@ -323,76 +383,84 @@
void calcReplayRate(int32_t rate)
{
+ int32_t i;
+
if (rate == 0)
return;
- const double dRateFactor = (double)MIXER_FRAC_SCALE / rate;
+ const double dScopeRateFactor = SCOPE_FRAC_SCALE / (double)SCOPE_HZ;
+ const double dAudioRateFactor = MIXER_FRAC_SCALE / (double)rate;
- // generate period-to-delta table
- const double dMul = dRateFactor * (8363.0 * 256.0);
- for (int32_t i = 0; i < 768; i++)
+ scopeAmigaPeriodDiv = (uint64_t)(((8363.0 * 1712.0) * dScopeRateFactor) + 0.5);
+
+#if defined _WIN64 || defined __amd64__
+ amigaPeriodDiv = (uint64_t)(((8363.0 * 1712.0) * dAudioRateFactor) + 0.5);
+ for (i = 0; i < 768; i++)
{
- const double dDelta = exp2(i * (1.0 / 768.0)) * dMul;
- for (int32_t j = 0; j < 32; j++)
- {
- const double dOut = dDelta * exp2(-j);
- period2DeltaTab[i][j] = (int32_t)(dOut + 0.5);
- }
+ double dHz = exp2(i * (1.0 / 768.0)) * (8363.0 * 256.0);
+ logTab[i] = (uint64_t)((dHz * dAudioRateFactor) + 0.5);
+ scopeLogTab[i] = (uint64_t)((dHz * dScopeRateFactor) + 0.5);
}
+#else
+ amigaPeriodDiv = (uint32_t)(((8363 * 1712) * dAudioRateFactor) + 0.5);
+ for (i = 0; i < 768; i++)
+ {
+ double dHz = exp2(i * (1.0 / 768.0)) * (8363.0 * 256.0);
+ logTab[i] = (uint32_t)((dHz * dAudioRateFactor) + 0.5);
+ scopeLogTab[i] = (uint64_t)((dHz * dScopeRateFactor) + 0.5);
+ }
+#endif
- dAmigaPeriodDiv = dRateFactor * (8363.0 * 1712.0);
-
audio.quickVolSizeVal = rate / 200; // FT2 truncates here
- audio.rampQuickVolMul = (int32_t)round((UINT32_MAX + 1.0) / audio.quickVolSizeVal);
+ audio.rampQuickVolMul = (int32_t)(((UINT32_MAX + 1.0) / audio.quickVolSizeVal) + 0.5);
audio.dSpeedValMul = editor.dPerfFreq / rate; // for audio/video sync
- // exact integer fixed-point delta base for piano in Instr. Ed.
- int32_t deltaBase = (int32_t)round(dAmigaPeriodDiv / (1712 * 16));
- audio.dPianoDeltaMul = 1.0 / deltaBase;
+ // calculate table used to count replayer time (displayed as hours/minutes/seconds)
+ const double dMul = (UINT32_MAX + 1.0) / rate;
+ for (i = 32; i < 256; i++)
+ {
+ uint32_t samplesPerTick = ((rate + rate) + (rate >> 1)) / i; // exactly how setSpeed() calculates it
+ const double dVal = samplesPerTick * dMul;
+ musicTimeTab[i-32] = (int32_t)(dVal + 0.5);
+ }
+
+ calcDelta2PeriodTabs();
}
+#if defined _WIN64 || defined __amd64__
+uint64_t getFrequenceValue(uint16_t period)
+{
+ return period2DeltaTab[period];
+}
+#else
uint32_t getFrequenceValue(uint16_t period)
{
- uint32_t delta;
+ return period2DeltaTab[period];
+}
+#endif
- if (period == 0)
- return 0;
+int32_t getPianoKey(uint16_t period, int32_t finetune, int32_t relativeNote) // for piano in Instr. Ed.
+{
+#if defined _WIN64 || defined __amd64__
+ uint64_t delta = period2DeltaTab[period];
+#else
+ uint32_t delta = period2DeltaTab[period];
+#endif
- if (period == oldPeriod)
- return oldDelta; // we have already calculated this delta
+ finetune >>= 3; // FT2 does this in the replayer internally, so the actual range is -16..15
- if (linearFrqTab)
- {
- const uint16_t invPeriod = (12 * 192 * 4) - period; // this intentionally overflows uint16_t to be accurate to FT2
+ const double dNote = (log2(delta * audio.dPianoDeltaMul) * 12.0) - (finetune * (1.0 / 16.0));
+ int32_t note = (int32_t)(dNote + 0.5);
- const int32_t quotient = invPeriod / 768;
- const int32_t remainder = invPeriod % 768;
-
- const int32_t octave = (14 - quotient) & 0x1F; // this is accurate to FT2 (it can go crazy on very high periods)
+ note -= relativeNote;
- delta = period2DeltaTab[remainder][octave];
- }
- else
- {
- const double dHz = dAmigaPeriodDiv / period;
- delta = (int32_t)(dHz + 0.5); // rounded (don't cast to uint32_t as it will avoid SSE2 usage, and delta is <= 2^31 anyway)
- }
-
- oldPeriod = period;
- oldDelta = delta;
-
- return delta;
+ // "note" is now the raw piano key number, unaffected by finetune/relativeNote
+ return note;
}
-void resetCachedFrequencyVars(void)
+uint64_t getScopeFrequenceValue(uint16_t period)
{
- oldPeriod = -1;
- oldDelta = 0;
-
- resetCachedScopeVars();
-#if !defined __amd64__ && !defined _WIN64
- resetCachedMixerVars();
-#endif
+ return period2ScopeDeltaTab[period];
}
static void startTone(uint8_t ton, uint8_t effTyp, uint8_t eff, stmTyp *ch)
@@ -466,7 +534,7 @@
if (eff)
ch->smpOffset = ch->eff;
- ch->smpStartPos = ch->smpOffset * 256;
+ ch->smpStartPos = ch->smpOffset << 8;
}
else
{
@@ -577,21 +645,18 @@
{
ch->pattPos = song.pattPos & 0x00FF;
}
- else
+ else if (ch->loopCnt == 0)
{
- if (ch->loopCnt == 0)
- {
- ch->loopCnt = ch->eff & 0x0F;
+ ch->loopCnt = ch->eff & 0x0F;
- song.pBreakPos = ch->pattPos;
- song.pBreakFlag = true;
- }
- else if (--ch->loopCnt > 0)
- {
- song.pBreakPos = ch->pattPos;
- song.pBreakFlag = true;
- }
+ song.pBreakPos = ch->pattPos;
+ song.pBreakFlag = true;
}
+ else if (--ch->loopCnt > 0)
+ {
+ song.pBreakPos = ch->pattPos;
+ song.pBreakFlag = true;
+ }
}
// EEx - pattern delay
@@ -613,8 +678,8 @@
ch->fPortaUpSpeed = tmpEff;
- ch->realPeriod -= (tmpEff * 4);
- if (ch->realPeriod < 1)
+ ch->realPeriod -= tmpEff << 2;
+ if ((int16_t)ch->realPeriod < 1)
ch->realPeriod = 1;
ch->outPeriod = ch->realPeriod;
@@ -630,9 +695,9 @@
ch->fPortaDownSpeed = tmpEff;
- ch->realPeriod += (tmpEff * 4);
- if (ch->realPeriod > (32000 - 1))
- ch->realPeriod = 32000 - 1;
+ ch->realPeriod += tmpEff << 2;
+ if ((int16_t)ch->realPeriod > 32000-1)
+ ch->realPeriod = 32000-1;
ch->outPeriod = ch->realPeriod;
ch->status |= IS_Period;
@@ -653,24 +718,18 @@
{
ch->pattPos = song.pattPos & 0xFF;
}
- else
+ else if (ch->loopCnt == 0)
{
- if (ch->loopCnt == 0)
- {
- ch->loopCnt = ch->eff & 0x0F;
+ ch->loopCnt = ch->eff & 0x0F;
- song.pBreakPos = ch->pattPos;
- song.pBreakFlag = true;
- }
- else
- {
- if (--ch->loopCnt > 0)
- {
- song.pBreakPos = ch->pattPos;
- song.pBreakFlag = true;
- }
- }
+ song.pBreakPos = ch->pattPos;
+ song.pBreakFlag = true;
}
+ else if (--ch->loopCnt > 0)
+ {
+ song.pBreakPos = ch->pattPos;
+ song.pBreakFlag = true;
+ }
}
// E7x - set tremolo waveform
@@ -685,10 +744,8 @@
ch->fVolSlideUpSpeed = tmpEff;
- // unsigned clamp
- if (ch->realVol <= (64 - tmpEff))
- ch->realVol += tmpEff;
- else
+ ch->realVol += tmpEff;
+ if (ch->realVol > 64)
ch->realVol = 64;
ch->outVol = ch->realVol;
@@ -704,10 +761,8 @@
ch->fVolSlideDownSpeed = tmpEff;
- // unsigned clamp
- if (ch->realVol >= tmpEff)
- ch->realVol -= tmpEff;
- else
+ ch->realVol -= tmpEff;
+ if ((int8_t)ch->realVol < 0)
ch->realVol = 0;
ch->outVol = ch->realVol;
@@ -743,8 +798,7 @@
}
else
{
- song.tempo = ch->eff;
- song.timer = ch->eff;
+ song.timer = song.tempo = ch->eff;
}
}
@@ -898,7 +952,9 @@
{
uint8_t tmpEff, tmpEffHi, volKol;
- // this one is manipulated by vol column effects, then used for multiretrig (FT2 quirk)
+ /* This one is manipulated by vol column effects,
+ ** then used for multiretrig vol testing (FT2 quirk).
+ */
volKol = ch->volKolVol;
// *** VOLUME COLUMN EFFECTS (TICK 0) ***
@@ -919,13 +975,11 @@
{
volKol = ch->volKolVol & 0x0F;
- // unsigned clamp
- if (ch->realVol >= volKol)
- ch->realVol -= volKol;
- else
+ ch->realVol -= volKol;
+ if ((int8_t)ch->realVol < 0)
ch->realVol = 0;
- ch->outVol = ch->realVol;
+ ch->outVol = ch->realVol;
ch->status |= IS_Vol;
}
@@ -934,13 +988,11 @@
{
volKol = ch->volKolVol & 0x0F;
- // unsigned clamp
- if (ch->realVol <= 64-volKol)
- ch->realVol += volKol;
- else
+ ch->realVol += volKol;
+ if (ch->realVol > 64)
ch->realVol = 64;
- ch->outVol = ch->realVol;
+ ch->outVol = ch->realVol;
ch->status |= IS_Vol;
}
@@ -1017,7 +1069,7 @@
ch->ePortaUpSpeed = tmpEff;
ch->realPeriod -= tmpEff;
- if (ch->realPeriod < 1)
+ if ((int16_t)ch->realPeriod < 1)
ch->realPeriod = 1;
ch->outPeriod = ch->realPeriod;
@@ -1036,7 +1088,7 @@
ch->ePortaDownSpeed = tmpEff;
ch->realPeriod += tmpEff;
- if (ch->realPeriod > 32000-1)
+ if ((int16_t)ch->realPeriod > 32000-1)
ch->realPeriod = 32000-1;
ch->outPeriod = ch->realPeriod;
@@ -1067,7 +1119,7 @@
ch->wantPeriod = note2Period[portaTmp];
if (ch->wantPeriod == ch->realPeriod) ch->portaDir = 0;
- else if (ch->wantPeriod > ch->realPeriod) ch->portaDir = 1;
+ else if (ch->wantPeriod > ch->realPeriod) ch->portaDir = 1;
else ch->portaDir = 2;
}
}
@@ -1208,8 +1260,7 @@
bool envInterpolateFlag, envDidInterpolate;
uint8_t envPos;
int16_t autoVibVal, panTmp;
- uint16_t autoVibAmp, tmpPeriod, envVal;
- int32_t tmp32;
+ uint16_t tmpPeriod, autoVibAmp, envVal;
uint32_t vol;
instrTyp *ins;
@@ -1476,17 +1527,22 @@
if (ins->vibTyp == 1) autoVibVal = (ch->eVibPos > 127) ? 64 : -64; // square
else if (ins->vibTyp == 2) autoVibVal = (((ch->eVibPos >> 1) + 64) & 127) - 64; // ramp up
- else if (ins->vibTyp == 3) autoVibVal = (((0 - (ch->eVibPos >> 1)) + 64) & 127) - 64; // ramp down
+ else if (ins->vibTyp == 3) autoVibVal = ((-(ch->eVibPos >> 1) + 64) & 127) - 64; // ramp down
else autoVibVal = vibSineTab[ch->eVibPos]; // sine
autoVibVal <<= 2;
+ tmpPeriod = (autoVibVal * (int16_t)autoVibAmp) >> 16;
- tmp32 = ((autoVibVal * (int16_t)autoVibAmp) >> 16) & 0x8000FFFF;
- tmpPeriod = ch->outPeriod + (int16_t)tmp32;
+ tmpPeriod += ch->outPeriod;
if (tmpPeriod > 32000-1)
- tmpPeriod = 0;
+ tmpPeriod = 0; // yes, FT2 does this (!)
- ch->finalPeriod = tmpPeriod - ch->midiPitch;
+#ifdef HAS_MIDI
+ if (midi.enable)
+ tmpPeriod -= ch->midiPitch;
+#endif
+
+ ch->finalPeriod = tmpPeriod;
ch->status |= IS_Period;
}
else
@@ -1504,7 +1560,7 @@
}
// for arpeggio and portamento (semitone-slide mode)
-static int16_t relocateTon(int16_t period, uint8_t arpNote, stmTyp *ch)
+static uint16_t relocateTon(uint16_t period, uint8_t arpNote, stmTyp *ch)
{
int32_t fineTune, loPeriod, hiPeriod, tmpPeriod, tableIndex;
@@ -1512,11 +1568,11 @@
hiPeriod = (8 * 12 * 16) * 2;
loPeriod = 0;
- for (int8_t i = 0; i < 8; i++)
+ for (int32_t i = 0; i < 8; i++)
{
tmpPeriod = (((loPeriod + hiPeriod) >> 1) & 0xFFFFFFE0) + fineTune;
- tableIndex = (tmpPeriod - 16) >> 1;
+ tableIndex = (uint32_t)(tmpPeriod - 16) >> 1;
tableIndex = CLAMP(tableIndex, 0, 1935); // 8bitbubsy: added security check
if (period >= note2Period[tableIndex])
@@ -1533,7 +1589,7 @@
if (tmpPeriod >= (8*12*16+15)*2-1) // FT2 bug: off-by-one edge case
tmpPeriod = (8*12*16+15)*2;
- return note2Period[tmpPeriod>>1];
+ return note2Period[(uint32_t)tmpPeriod>>1];
}
static void tonePorta(stmTyp *ch)
@@ -1544,7 +1600,7 @@
if (ch->portaDir > 1)
{
ch->realPeriod -= ch->portaSpeed;
- if (ch->realPeriod <= ch->wantPeriod)
+ if ((int16_t)ch->realPeriod <= (int16_t)ch->wantPeriod)
{
ch->portaDir = 1;
ch->realPeriod = ch->wantPeriod;
@@ -1578,18 +1634,16 @@
if ((tmpEff & 0xF0) == 0)
{
- // unsigned clamp
- if (ch->realVol >= tmpEff)
- ch->realVol -= tmpEff;
- else
+ ch->realVol -= tmpEff;
+ if ((int8_t)ch->realVol < 0)
ch->realVol = 0;
}
else
{
- // unsigned clamp
- if (ch->realVol <= 64-(tmpEff>>4))
- ch->realVol += tmpEff>>4;
- else
+ tmpEff >>= 4;
+
+ ch->realVol += tmpEff;
+ if (ch->realVol > 64)
ch->realVol = 64;
}
@@ -1599,7 +1653,7 @@
static void vibrato2(stmTyp *ch)
{
- uint8_t tmpVib = (ch->vibPos / 4) & 0x1F;
+ uint8_t tmpVib = (ch->vibPos >> 2) & 0x1F;
switch (ch->waveCtrl & 3)
{
@@ -1609,9 +1663,9 @@
// 1: ramp
case 1:
{
- tmpVib *= 8;
- if (ch->vibPos >= 128)
- tmpVib ^= 0xFF;
+ tmpVib <<= 3;
+ if ((int8_t)ch->vibPos < 0)
+ tmpVib = ~tmpVib;
}
break;
@@ -1619,9 +1673,9 @@
default: tmpVib = 255; break;
}
- tmpVib = (tmpVib * ch->vibDepth) / 32;
+ tmpVib = (tmpVib * ch->vibDepth) >> 5; // logical shift (unsigned calc.), not arithmetic shift
- if (ch->vibPos >= 128)
+ if ((int8_t)ch->vibPos < 0)
ch->outPeriod = ch->realPeriod - tmpVib;
else
ch->outPeriod = ch->realPeriod + tmpVib;
@@ -1632,10 +1686,17 @@
static void vibrato(stmTyp *ch)
{
+ uint8_t tmp8;
+
if (ch->eff > 0)
{
- if ((ch->eff & 0x0F) > 0) ch->vibDepth = ch->eff & 0x0F;
- if ((ch->eff & 0xF0) > 0) ch->vibSpeed = (ch->eff >> 4) * 4;
+ tmp8 = ch->eff & 0x0F;
+ if (tmp8 > 0)
+ ch->vibDepth = tmp8;
+
+ tmp8 = (ch->eff & 0xF0) >> 2;
+ if (tmp8 > 0)
+ ch->vibSpeed = tmp8;
}
vibrato2(ch);
@@ -1644,12 +1705,12 @@
static void doEffects(stmTyp *ch)
{
int8_t note;
- uint8_t tmpEff, tremorData, tremorSign, tmpTrem;
- int16_t tremVol;
+ uint8_t tmp8, tmpEff, tremorData, tremorSign, tmpTrem;
+ int16_t tremVol, tmp16;
uint16_t i, tick;
if (ch->stOff)
- return;
+ return; // muted
// *** VOLUME COLUMN EFFECTS (TICKS >0) ***
@@ -1656,10 +1717,8 @@
// volume slide down
if ((ch->volKolVol & 0xF0) == 0x60)
{
- // unsigned clamp
- if (ch->realVol >= (ch->volKolVol & 0x0F))
- ch->realVol -= ch->volKolVol & 0x0F;
- else
+ ch->realVol -= ch->volKolVol & 0x0F;
+ if ((int8_t)ch->realVol < 0)
ch->realVol = 0;
ch->outVol = ch->realVol;
@@ -1669,10 +1728,8 @@
// volume slide up
else if ((ch->volKolVol & 0xF0) == 0x70)
{
- // unsigned clamp
- if (ch->realVol <= 64-(ch->volKolVol & 0x0F))
- ch->realVol += ch->volKolVol & 0x0F;
- else
+ ch->realVol += ch->volKolVol & 0x0F;
+ if (ch->realVol > 64)
ch->realVol = 64;
ch->outVol = ch->realVol;
@@ -1691,12 +1748,11 @@
// pan slide left
else if ((ch->volKolVol & 0xF0) == 0xD0)
{
- // unsigned clamp + a bug when the parameter is 0
- if ((ch->volKolVol & 0x0F) == 0 || ch->outPan < (ch->volKolVol & 0x0F))
- ch->outPan = 0;
- else
- ch->outPan -= ch->volKolVol & 0x0F;
+ tmp16 = (int16_t)ch->outPan - (ch->volKolVol & 0x0F);
+ if (tmp16 < 0 || (ch->volKolVol & 0x0F) == 0) // FT2 bug: param 0 = pan gets set to 0
+ tmp16 = 0;
+ ch->outPan = (uint8_t)tmp16;
ch->status |= IS_Pan;
}
@@ -1703,12 +1759,11 @@
// pan slide right
else if ((ch->volKolVol & 0xF0) == 0xE0)
{
- // unsigned clamp
- if (ch->outPan <= 255-(ch->volKolVol & 0x0F))
- ch->outPan += ch->volKolVol & 0x0F;
- else
- ch->outPan = 255;
+ tmp16 = (int16_t)ch->outPan + (ch->volKolVol & 0x0F);
+ if (tmp16 > 255)
+ tmp16 = 255;
+ ch->outPan = (uint8_t)tmp16;
ch->status |= IS_Pan;
}
@@ -1722,13 +1777,7 @@
// 0xy - Arpeggio
if (ch->effTyp == 0)
{
- tick = song.timer;
-
- // FT2 'out of boundary LUT read' arp simulation
- if (tick < 16) tick %= 3;
- else if (tick == 16) tick = 0;
- else tick = 2;
-
+ tick = arpTab[song.timer & 0x1F]; // 8bitbubsy: AND it for security
if (tick == 0)
{
ch->outPeriod = ch->realPeriod;
@@ -1738,7 +1787,7 @@
if (tick == 1)
note = ch->eff >> 4;
else
- note = ch->eff & 0xF; // tick 2
+ note = ch->eff & 0x0F; // tick 2
ch->outPeriod = relocateTon(ch->realPeriod, note, ch);
}
@@ -1755,8 +1804,8 @@
ch->portaUpSpeed = tmpEff;
- ch->realPeriod -= tmpEff * 4;
- if (ch->realPeriod < 1)
+ ch->realPeriod -= tmpEff << 2;
+ if ((int16_t)ch->realPeriod < 1)
ch->realPeriod = 1;
ch->outPeriod = ch->realPeriod;
@@ -1772,8 +1821,8 @@
ch->portaDownSpeed = tmpEff;
- ch->realPeriod += tmpEff * 4;
- if (ch->realPeriod > 32000-1)
+ ch->realPeriod += tmpEff << 2;
+ if ((int16_t)ch->realPeriod > 32000-1) // FT2 bug, should've been unsigned comparison
ch->realPeriod = 32000-1;
ch->outPeriod = ch->realPeriod;
@@ -1806,11 +1855,16 @@
tmpEff = ch->eff;
if (tmpEff > 0)
{
- if ((tmpEff & 0x0F) > 0) ch->tremDepth = tmpEff & 0x0F;
- if ((tmpEff & 0xF0) > 0) ch->tremSpeed = (tmpEff >> 4) * 4;
+ tmp8 = tmpEff & 0x0F;
+ if (tmp8 > 0)
+ ch->tremDepth = tmp8;
+
+ tmp8 = (tmpEff & 0xF0) >> 2;
+ if (tmp8 > 0)
+ ch->tremSpeed = tmp8;
}
- tmpTrem = (ch->tremPos / 4) & 0x1F;
+ tmpTrem = (ch->tremPos >> 2) & 0x1F;
switch ((ch->waveCtrl >> 4) & 3)
{
// 0: sine
@@ -1819,8 +1873,9 @@
// 1: ramp
case 1:
{
- tmpTrem *= 8;
- if (ch->vibPos >= 128) tmpTrem ^= 0xFF; // FT2 bug, should've been TremPos
+ tmpTrem <<= 3;
+ if ((int8_t)ch->vibPos < 0) // FT2 bug, should've been ch->tremPos
+ tmpTrem = ~tmpTrem;
}
break;
@@ -1827,9 +1882,9 @@
// 2/3: square
default: tmpTrem = 255; break;
}
- tmpTrem = (tmpTrem * ch->tremDepth) / 64;
+ tmpTrem = (tmpTrem * ch->tremDepth) >> 6; // logical shift (unsigned calc.), not arithmetic shift
- if (ch->tremPos >= 128)
+ if ((int8_t)ch->tremPos < 0)
{
tremVol = ch->realVol - tmpTrem;
if (tremVol < 0)
@@ -1842,9 +1897,9 @@
tremVol = 64;
}
- ch->outVol = tremVol & 0xFF;
- ch->tremPos += ch->tremSpeed;
+ ch->outVol = (uint8_t)tremVol;
ch->status |= IS_Vol;
+ ch->tremPos += ch->tremSpeed;
}
// Axy - volume slide
@@ -1891,7 +1946,7 @@
if (ch->volKolVol >= 0x10 && ch->volKolVol <= 0x50)
{
- ch->outVol = ch->volKolVol - 16;
+ ch->outVol = ch->volKolVol - 16;
ch->realVol = ch->outVol;
}
else if (ch->volKolVol >= 0xC0 && ch->volKolVol <= 0xCF)
@@ -1913,18 +1968,16 @@
if ((tmpEff & 0xF0) == 0)
{
- // unsigned clamp
- if (song.globVol >= tmpEff)
- song.globVol -= tmpEff;
- else
+ song.globVol -= tmpEff;
+ if ((int8_t)song.globVol < 0)
song.globVol = 0;
}
else
{
- // unsigned clamp
- if (song.globVol <= 64-(tmpEff >> 4))
- song.globVol += tmpEff >> 4;
- else
+ tmpEff >>= 4;
+
+ song.globVol += tmpEff;
+ if (song.globVol > 64)
song.globVol = 64;
}
@@ -1950,23 +2003,20 @@
if ((tmpEff & 0xF0) == 0)
{
- // unsigned clamp
- if (ch->outPan >= tmpEff)
- ch->outPan -= tmpEff;
- else
- ch->outPan = 0;
+ tmp16 = (int16_t)ch->outPan - tmpEff;
+ if (tmp16 < 0)
+ tmp16 = 0;
}
else
{
tmpEff >>= 4;
- // unsigned clamp
- if (ch->outPan <= 255-tmpEff)
- ch->outPan += tmpEff;
- else
- ch->outPan = 255;
+ tmp16 = (int16_t)ch->outPan + tmpEff;
+ if (tmp16 > 255)
+ tmp16 = 255;
}
-
+
+ ch->outPan = (uint8_t)tmp16;
ch->status |= IS_Pan;
}
@@ -1986,7 +2036,7 @@
tremorData = ch->tremorPos & 0x7F;
tremorData--;
- if ((tremorData & 0x80) > 0)
+ if ((int8_t)tremorData < 0)
{
if (tremorSign == 0x80)
{
@@ -2000,9 +2050,9 @@
}
}
- ch->tremorPos = tremorData | tremorSign;
+ ch->tremorPos = tremorSign | tremorData;
- ch->outVol = tremorSign ? ch->realVol : 0;
+ ch->outVol = (tremorSign == 0x80) ? ch->realVol : 0;
ch->status |= (IS_Vol + IS_QuickVol);
}
}
@@ -2055,7 +2105,6 @@
}
assert(song.songPos <= 255);
-
song.pattNr = song.songTab[song.songPos & 0xFF];
song.pattLen = pattLens[song.pattNr & 0xFF];
}
@@ -2075,7 +2124,7 @@
static void noNewAllChannels(void)
{
- for (uint8_t i = 0; i < song.antChn; i++)
+ for (int32_t i = 0; i < song.antChn; i++)
{
doEffects(&stm[i]);
fixaEnvelopeVibrato(&stm[i]);
@@ -2084,8 +2133,8 @@
void mainPlayer(void) // periodically called from audio callback
{
- uint8_t i;
bool readNewNote;
+ int32_t i;
if (musicPaused || !songPlaying)
{
@@ -2095,8 +2144,8 @@
return;
}
- if (song.speed > 0)
- song.musicTime += 65536 / song.speed; // for playback counter
+ assert(song.speed >= 32 && song.speed <= 2);
+ song.musicTime64 += musicTimeTab[song.speed-32]; // for playback counter
readNewNote = false;
if (--song.timer == 0)
@@ -2106,9 +2155,9 @@
}
// for visuals
- song.curReplayerTimer = (uint8_t)song.timer;
+ song.curReplayerTimer = (uint8_t)song.timer;
song.curReplayerPattPos = (uint8_t)song.pattPos;
- song.curReplayerPattNr = (uint8_t)song.pattNr;
+ song.curReplayerPattNr = (uint8_t)song.pattNr;
song.curReplayerSongPos = (uint8_t)song.songPos;
if (readNewNote)
@@ -2720,7 +2769,9 @@
editor.globalVol = song.globVol = 64;
song.initialTempo = song.tempo;
- setFrqTab(true);
+ audio.linearFreqTable = true;
+ note2Period = linearPeriods;
+
setPos(0, 0, true);
if (!allocateInstr(0))
@@ -2764,10 +2815,11 @@
playMode = mode;
songPlaying = true;
song.globVol = 64;
- song.musicTime = 0;
song.pattDelTime2 = 0;
song.pattDelTime = 0;
+ resetPlaybackTime();
+
// non-FT2 fix: If song speed was 0, set it back to initial speed on play
if (song.tempo == 0)
song.tempo = song.initialTempo;
@@ -3057,7 +3109,9 @@
stopAllScopes();
resetAudioDither();
- resetCachedFrequencyVars();
+#if !defined __amd64__ && !defined _WIN64
+ resetCachedMixerVars();
+#endif
// wait for scope thread to finish, so that we know pointers aren't deprecated
while (editor.scopeThreadMutex);
--- a/src/ft2_replayer.h
+++ b/src/ft2_replayer.h
@@ -49,7 +49,8 @@
#define PROG_NAME_STR "Fasttracker II clone"
/* Some of the following structs must be packed (e.g. not padded) since they
-** are loaded directly into with fread and stuff. */
+** are loaded directly into with fread and stuff.
+*/
#ifdef _MSC_VER
#pragma pack(push)
@@ -198,8 +199,8 @@
uint8_t portaUpSpeed, portaDownSpeed, retrigSpeed, retrigCnt, retrigVol;
uint8_t volKolVol, tonNr, envPPos, eVibPos, envVPos, realVol, oldVol, outVol;
uint8_t oldPan, outPan, finalPan;
- int16_t midiPitch, realPeriod, envVIPValue, envPIPValue;
- uint16_t finalVol, outPeriod, finalPeriod, tonTyp, wantPeriod, portaSpeed;
+ int16_t midiPitch, envVIPValue, envPIPValue;
+ uint16_t finalVol, outPeriod, realPeriod, finalPeriod, tonTyp, wantPeriod, portaSpeed;
uint16_t envVCnt, envVAmp, envPCnt, envPAmp, eVibAmp, eVibSweep;
uint16_t fadeOutAmp, fadeOutSpeed, midiVibDepth;
int32_t smpStartPos;
@@ -216,7 +217,7 @@
int16_t songPos, pattNr, pattPos, pattLen;
int32_t antChn;
uint16_t len, repS, speed, tempo, globVol, timer, ver, initialTempo;
- uint32_t musicTime;
+ uint64_t musicTime64;
} songTyp;
typedef struct tonTyp_t
@@ -231,7 +232,6 @@
uint8_t status, sampleNr, instrNr;
uint16_t finalPeriod, finalVol;
int32_t smpStartPos;
- uint32_t voiceDelta;
} syncedChannel_t;
void fixSongName(void); // removes spaces from right side of song name
@@ -238,10 +238,18 @@
void fixSampleName(int16_t nr); // removes spaces from right side of ins/smp names
void calcReplayRate(int32_t rate);
-void resetCachedFrequencyVars(void);
void tuneSample(sampleTyp *s, int32_t midCFreq);
+
+
+#if defined _WIN64 || defined __amd64__
+uint64_t getFrequenceValue(uint16_t period);
+#else
uint32_t getFrequenceValue(uint16_t period);
+#endif
+uint64_t getScopeFrequenceValue(uint16_t period);
+int32_t getPianoKey(uint16_t period, int32_t finetune, int32_t relativeNote); // for piano in Instr. Ed.
+
bool allocateInstr(int16_t nr);
void freeInstr(int32_t nr);
void freeAllInstr(void);
@@ -291,9 +299,9 @@
// ft2_replayer.c
extern int8_t playMode;
-extern bool linearFrqTab, songPlaying, audioPaused, musicPaused;
+extern bool songPlaying, audioPaused, musicPaused;
extern volatile bool replayerBusy;
-extern const int16_t *note2Period;
+extern const uint16_t *note2Period;
extern int16_t pattLens[MAX_PATTERNS];
extern stmTyp stm[MAX_VOICES];
extern songTyp song;
--- a/src/ft2_sample_ed_features.c
+++ b/src/ft2_sample_ed_features.c
@@ -23,6 +23,7 @@
#include "ft2_inst_ed.h"
#include "ft2_sample_ed.h"
#include "ft2_keyboard.h"
+#include "ft2_tables.h"
static volatile bool stopThread;
@@ -661,20 +662,17 @@
assert(echo_nEcho <= 1024);
- charOut(315 + (0 * 7), 226, PAL_FORGRND, '0' + (echo_nEcho / 1000) % 10);
+ charOut(315 + (0 * 7), 226, PAL_FORGRND, '0' + (char)(echo_nEcho / 1000));
charOut(315 + (1 * 7), 226, PAL_FORGRND, '0' + (echo_nEcho / 100) % 10);
charOut(315 + (2 * 7), 226, PAL_FORGRND, '0' + (echo_nEcho / 10) % 10);
charOut(315 + (3 * 7), 226, PAL_FORGRND, '0' + (echo_nEcho % 10));
- assert((echo_Distance * 16) <= 262144);
+ assert(echo_Distance <= 0x4000);
+ hexOut(308, 240, PAL_FORGRND, (uint32_t)echo_Distance << 4, 5);
- hexOut(308, 240, PAL_FORGRND, echo_Distance * 16, 5);
-
assert(echo_VolChange <= 100);
+ textOutFixed(312, 254, PAL_FORGRND, PAL_BUTTONS, dec3StrTab[echo_VolChange]);
- charOut(312 + (0 * 7), 254, PAL_FORGRND, '0' + (echo_VolChange / 100) % 10);
- charOut(312 + (1 * 7), 254, PAL_FORGRND, '0' + (echo_VolChange / 10) % 10);
- charOut(312 + (2 * 7), 254, PAL_FORGRND, '0' + (echo_VolChange % 10));
charOutShadow(313 + (3 * 7), 254, PAL_FORGRND, PAL_BUTTON2, '%');
}
@@ -1085,10 +1083,7 @@
textOutShadow(198, 246, PAL_FORGRND, PAL_BUTTON2, "Mixing balance");
assert((mix_Balance >= 0) && (mix_Balance <= 100));
-
- charOut(299 + (0 * 7), 246, PAL_FORGRND, '0' + ((mix_Balance / 100) % 10));
- charOut(299 + (1 * 7), 246, PAL_FORGRND, '0' + ((mix_Balance / 10) % 10));
- charOut(299 + (2 * 7), 246, PAL_FORGRND, '0' + (mix_Balance % 10));
+ textOutFixed(299, 246, PAL_FORGRND, PAL_BUTTONS, dec3StrTab[mix_Balance]);
}
static void setupMixBoxWidgets(void)
@@ -1260,9 +1255,10 @@
static int32_t SDLCALL applyVolumeThread(void *ptr)
{
+#define AMP_BITS 15
int8_t *ptr8;
int16_t *ptr16;
- int32_t vol1, vol2, tmp32, x1, x2, len, i;
+ int32_t amp32, x1, x2, len, i;
sampleTyp *s;
if (instr[editor.curInstr] == NULL)
@@ -1270,8 +1266,6 @@
s = &instr[editor.curInstr]->samp[editor.curSmp];
- (void)ptr;
-
if (smpEd_Rx1 < smpEd_Rx2)
{
x1 = smpEd_Rx1;
@@ -1300,8 +1294,8 @@
if (s->typ & 16)
{
- x1 /= 2;
- x2 /= 2;
+ x1 >>= 1;
+ x2 >>= 1;
}
len = x2 - x1;
@@ -1308,22 +1302,28 @@
if (len <= 0)
goto applyVolumeExit;
- pauseAudio();
- restoreSample(s);
+ const double dVol1 = vol_StartVol * ((1 << AMP_BITS) / 100.0);
+ const double dVol2 = vol_EndVol * ((1 << AMP_BITS) / 100.0);
- // scale values for faster math and suitable rounding for PCM waveforms (DIV -> arithmetic bitshift right)
- vol1 = (int32_t)round((vol_StartVol * 256) / 100.0);
- vol2 = (int32_t)round((vol_EndVol * 256) / 100.0) - vol1;
+ /* 8bitbubsy: Rewritten to use 64-bit deltas instead, to
+ ** prevent having to do a 64-bit mul for every output sample.
+ */
+ const int64_t delta64 = (int64_t)round(((dVol2 - dVol1) * (UINT32_MAX+1.0)) / len);
+ int64_t pos64 = (int64_t)dVol1 << 32;
+ pauseAudio();
+ restoreSample(s);
if (s->typ & 16)
{
ptr16 = (int16_t *)s->pek;
for (i = x1; i < x2; i++)
{
- tmp32 = vol1 + (int32_t)(((int64_t)(i - x1) * vol2) / len);
- tmp32 = (ptr16[i] * tmp32) >> 8;
- CLAMP16(tmp32);
- ptr16[i] = (int16_t)tmp32;
+ amp32 = (int32_t)(pos64 >> 32);
+ pos64 += delta64;
+
+ amp32 = (ptr16[i] * amp32) >> AMP_BITS;
+ CLAMP16(amp32);
+ ptr16[i] = (int16_t)amp32;
}
}
else
@@ -1331,20 +1331,24 @@
ptr8 = s->pek;
for (i = x1; i < x2; i++)
{
- tmp32 = vol1 + (int32_t)(((int64_t)(i - x1) * vol2) / len);
- tmp32 = (ptr8[i] * tmp32) >> 8;
- CLAMP8(tmp32);
- ptr8[i] = (int8_t)tmp32;
+ amp32 = (int32_t)(pos64 >> 32);
+ pos64 += delta64;
+
+ amp32 = (ptr8[i] * amp32) >> AMP_BITS;
+ CLAMP8(amp32);
+ ptr8[i] = (int8_t)amp32;
}
}
fixSample(s);
-
resumeAudio();
+
setSongModifiedFlag();
applyVolumeExit:
setMouseBusy(false);
editor.ui.sysReqShown = false;
+
+ (void)ptr;
return true;
}
@@ -1517,7 +1521,7 @@
if (val > 99)
{
charOut(253, 236, PAL_FORGRND, sign);
- charOut(260, 236, PAL_FORGRND, '0' + ((val / 100) % 10));
+ charOut(260, 236, PAL_FORGRND, '0' + (char)(val / 100));
charOut(267, 236, PAL_FORGRND, '0' + ((val / 10) % 10));
charOut(274, 236, PAL_FORGRND, '0' + (val % 10));
}
@@ -1524,13 +1528,13 @@
else if (val > 9)
{
charOut(260, 236, PAL_FORGRND, sign);
- charOut(267, 236, PAL_FORGRND, '0' + ((val / 10) % 10));
+ charOut(267, 236, PAL_FORGRND, '0' + (char)(val / 10));
charOut(274, 236, PAL_FORGRND, '0' + (val % 10));
}
else
{
charOut(267, 236, PAL_FORGRND, sign);
- charOut(274, 236, PAL_FORGRND, '0' + (val % 10));
+ charOut(274, 236, PAL_FORGRND, '0' + (char)val);
}
if (vol_EndVol == 0) sign = ' ';
@@ -1541,7 +1545,7 @@
if (val > 99)
{
charOut(253, 250, PAL_FORGRND, sign);
- charOut(260, 250, PAL_FORGRND, '0' + ((val / 100) % 10));
+ charOut(260, 250, PAL_FORGRND, '0' + (char)(val / 100));
charOut(267, 250, PAL_FORGRND, '0' + ((val / 10) % 10));
charOut(274, 250, PAL_FORGRND, '0' + (val % 10));
}
@@ -1548,13 +1552,13 @@
else if (val > 9)
{
charOut(260, 250, PAL_FORGRND, sign);
- charOut(267, 250, PAL_FORGRND, '0' + ((val / 10) % 10));
+ charOut(267, 250, PAL_FORGRND, '0' + (char)(val / 10));
charOut(274, 250, PAL_FORGRND, '0' + (val % 10));
}
else
{
charOut(267, 250, PAL_FORGRND, sign);
- charOut(274, 250, PAL_FORGRND, '0' + (val % 10));
+ charOut(274, 250, PAL_FORGRND, '0' + (char)val);
}
}
--- a/src/ft2_scopedraw.c
+++ b/src/ft2_scopedraw.c
@@ -7,65 +7,105 @@
/* SCOPE DRAWING MACROS */
/* ----------------------------------------------------------------------- */
-#define SCOPE_REGS \
+#define SCOPE_REGS_NO_LOOP \
+ const int8_t vol = s->SVol; \
+ const int32_t SLen = s->SLen; \
+ const uint32_t scopeDrawDelta = s->DFrq; \
+ const uint32_t scopePixelColor = video.palette[PAL_PATTEXT]; \
+ const uint32_t drawLen = x + w; \
int32_t sample; \
int32_t scopeDrawPos = s->SPos; \
int32_t scopeDrawFrac = 0; \
- uint32_t scopePixelColor = video.palette[PAL_PATTEXT]; \
- uint32_t len = x + w; \
+#define SCOPE_REGS_LOOP \
+ const int8_t vol = s->SVol; \
+ const int32_t SLen = s->SLen; \
+ const int32_t SRepS = s->SRepS; \
+ const int32_t SRepL = s->SRepL; \
+ const uint32_t scopeDrawDelta = s->DFrq; \
+ const uint32_t scopePixelColor = video.palette[PAL_PATTEXT]; \
+ const uint32_t drawLen = x + w; \
+ int32_t sample; \
+ int32_t scopeDrawPos = s->SPos; \
+ int32_t scopeDrawFrac = 0; \
+
#define SCOPE_REGS_PINGPONG \
+ const int8_t vol = s->SVol; \
+ const int32_t SLen = s->SLen; \
+ const int32_t SRepS = s->SRepS; \
+ const int32_t SRepL = s->SRepL; \
+ const uint32_t scopeDrawDelta = s->DFrq; \
+ const uint32_t scopePixelColor = video.palette[PAL_PATTEXT]; \
+ const uint32_t drawLen = x + w; \
int32_t sample; \
int32_t scopeDrawPos = s->SPos; \
int32_t scopeDrawFrac = 0; \
- int32_t drawPosDir = s->SPosDir; \
- uint32_t scopePixelColor = video.palette[PAL_PATTEXT]; \
- uint32_t len = x + w; \
+ int32_t drawPosDir = s->backwards ? -1 : 1; \
-#define LINED_SCOPE_REGS \
+#define LINED_SCOPE_REGS_NO_LOOP \
+ const int8_t vol = s->SVol; \
+ const int32_t SLen = s->SLen; \
+ const uint32_t scopeDrawDelta = s->DFrq; \
+ const uint32_t drawLen = (x + w) - 1; \
int32_t sample; \
int32_t y1, y2; \
int32_t scopeDrawPos = s->SPos; \
int32_t scopeDrawFrac = 0; \
- uint32_t len = (x + w) - 1; \
+#define LINED_SCOPE_REGS_LOOP \
+ const int8_t vol = s->SVol; \
+ const int32_t SLen = s->SLen; \
+ const int32_t SRepS = s->SRepS; \
+ const int32_t SRepL = s->SRepL; \
+ const uint32_t scopeDrawDelta = s->DFrq; \
+ const uint32_t drawLen = (x + w) - 1; \
+ int32_t sample; \
+ int32_t y1, y2; \
+ int32_t scopeDrawPos = s->SPos; \
+ int32_t scopeDrawFrac = 0; \
+
#define LINED_SCOPE_REGS_PINGPONG \
+ const int8_t vol = s->SVol; \
+ const int32_t SLen = s->SLen; \
+ const int32_t SRepS = s->SRepS; \
+ const int32_t SRepL = s->SRepL; \
+ const uint32_t scopeDrawDelta = s->DFrq; \
+ const uint32_t drawLen = (x + w) - 1; \
int32_t sample; \
int32_t y1, y2; \
int32_t scopeDrawPos = s->SPos; \
int32_t scopeDrawFrac = 0; \
- int32_t drawPosDir = s->SPosDir; \
- uint32_t len = (x + w) - 1; \
+ int32_t drawPosDir = s->backwards ? -1 : 1; \
#define SCOPE_GET_SMP8 \
- if (!s->active) \
+ if (s->active) \
{ \
- sample = 0; \
+ assert(scopeDrawPos >= 0 && scopeDrawPos < SLen); \
+ sample = (s->sampleData8[scopeDrawPos] * vol) >> 8; \
} \
else \
{ \
- assert(scopeDrawPos >= 0 && scopeDrawPos < s->SLen); \
- sample = (s->sampleData8[scopeDrawPos] * s->SVol) >> 8; \
+ sample = 0; \
} \
#define SCOPE_GET_SMP16 \
- if (!s->active) \
+ if (s->active) \
{ \
- sample = 0; \
+ assert(scopeDrawPos >= 0 && scopeDrawPos < SLen); \
+ sample = (int8_t)((s->sampleData16[scopeDrawPos] * vol) >> 16); \
} \
else \
{ \
- assert(scopeDrawPos >= 0 && scopeDrawPos < s->SLen); \
- sample = (int8_t)((s->sampleData16[scopeDrawPos] * s->SVol) >> 16); \
+ sample = 0; \
} \
#define SCOPE_UPDATE_DRAWPOS \
- scopeDrawFrac += (uint32_t)(s->SFrq >> (SCOPE_FRAC_BITS - 10)); \
+ scopeDrawFrac += scopeDrawDelta; \
scopeDrawPos += scopeDrawFrac >> 16; \
scopeDrawFrac &= 0xFFFF; \
#define SCOPE_UPDATE_DRAWPOS_PINGPONG \
- scopeDrawFrac += (uint32_t)(s->SFrq >> (SCOPE_FRAC_BITS - 10)); \
+ scopeDrawFrac += scopeDrawDelta; \
scopeDrawPos += (scopeDrawFrac >> 16) * drawPosDir; \
scopeDrawFrac &= 0xFFFF; \
@@ -88,72 +128,69 @@
y1 = y2; \
#define SCOPE_HANDLE_POS_NO_LOOP \
- if (scopeDrawPos >= s->SLen) \
+ if (scopeDrawPos >= SLen) \
s->active = false; \
#define SCOPE_HANDLE_POS_LOOP \
- if (scopeDrawPos >= s->SLen) \
+ if (scopeDrawPos >= SLen) \
{ \
- if (s->SRepL < 2) \
- scopeDrawPos = s->SRepS; \
+ if (SRepL >= 2) \
+ scopeDrawPos = SRepS + ((scopeDrawPos - SLen) % SRepL); \
else \
- scopeDrawPos = s->SRepS + ((scopeDrawPos - s->SLen) % s->SRepL); \
+ scopeDrawPos = SRepS; \
\
- assert(scopeDrawPos >= s->SRepS && scopeDrawPos < s->SLen); \
+ assert(scopeDrawPos >= SRepS && scopeDrawPos < SLen); \
} \
#define SCOPE_HANDLE_POS_PINGPONG \
- if (drawPosDir == -1 && scopeDrawPos < s->SRepS) \
+ if (drawPosDir == -1 && scopeDrawPos < SRepS) \
{ \
drawPosDir = 1; /* change direction to forwards */ \
\
- if (s->SRepL < 2) \
- scopeDrawPos = s->SRepS; \
+ if (SRepL >= 2) \
+ scopeDrawPos = SRepS + ((SRepS - scopeDrawPos - 1) % SRepL); \
else \
- scopeDrawPos = s->SRepS + ((s->SRepS - scopeDrawPos - 1) % s->SRepL); \
+ scopeDrawPos = SRepS; \
\
- assert(scopeDrawPos >= s->SRepS && scopeDrawPos < s->SLen); \
+ assert(scopeDrawPos >= SRepS && scopeDrawPos < SLen); \
} \
- else if (scopeDrawPos >= s->SLen) \
+ else if (scopeDrawPos >= SLen) \
{ \
drawPosDir = -1; /* change direction to backwards */ \
\
- if (s->SRepL < 2) \
- scopeDrawPos = s->SLen - 1; \
+ if (SRepL >= 2) \
+ scopeDrawPos = (SLen - 1) - ((scopeDrawPos - SLen) % SRepL); \
else \
- scopeDrawPos = (s->SLen - 1) - ((scopeDrawPos - s->SLen) % s->SRepL); \
+ scopeDrawPos = SLen - 1; \
\
- assert(scopeDrawPos >= s->SRepS && scopeDrawPos < s->SLen); \
+ assert(scopeDrawPos >= SRepS && scopeDrawPos < SLen); \
} \
assert(scopeDrawPos >= 0); \
static void scopeLine(int32_t x1, int32_t y1, int32_t y2)
{
- int32_t pitch, d, sy, dy;
- uint32_t ay, pixVal, *dst32;
+ const int32_t dy = y2 - y1;
+ const int32_t sy = SGN(dy);
+ const uint32_t color = video.palette[PAL_PATTEXT];
+ const int32_t pitch = sy * SCREEN_W;
- dy = y2 - y1;
- ay = ABS(dy);
- sy = SGN(dy);
+ uint32_t *dst32 = &video.frameBuffer[(y1 * SCREEN_W) + x1];
- pixVal = video.palette[PAL_PATTEXT];
- pitch = sy * SCREEN_W;
+ *dst32 = color; // set first pixel
- dst32 = &video.frameBuffer[(y1 * SCREEN_W) + x1];
- *dst32 = pixVal;
-
+ int32_t ay = ABS(dy);
if (ay <= 1)
{
if (ay != 0)
dst32 += pitch;
- *++dst32 = pixVal;
+ *++dst32 = color;
return;
}
- d = 2 - ay;
+ int32_t d = 1 - ay;
- ay *= 2;
+ ay <<= 1;
while (y1 != y2)
{
if (d >= 0)
@@ -166,7 +203,7 @@
d += 2;
dst32 += pitch;
- *dst32 = pixVal;
+ *dst32 = color;
}
}
@@ -176,9 +213,9 @@
static void scopeDrawNoLoop_8bit(scope_t *s, uint32_t x, uint32_t lineY, uint32_t w)
{
- SCOPE_REGS
+ SCOPE_REGS_NO_LOOP
- for (; x < len; x++)
+ for (; x < drawLen; x++)
{
SCOPE_GET_SMP8
SCOPE_DRAW_SMP
@@ -189,9 +226,9 @@
static void scopeDrawLoop_8bit(scope_t *s, uint32_t x, uint32_t lineY, uint32_t w)
{
- SCOPE_REGS
+ SCOPE_REGS_LOOP
- for (; x < len; x++)
+ for (; x < drawLen; x++)
{
SCOPE_GET_SMP8
SCOPE_DRAW_SMP
@@ -204,7 +241,7 @@
{
SCOPE_REGS_PINGPONG
- for (; x < len; x++)
+ for (; x < drawLen; x++)
{
SCOPE_GET_SMP8
SCOPE_DRAW_SMP
@@ -215,9 +252,9 @@
static void scopeDrawNoLoop_16bit(scope_t *s, uint32_t x, uint32_t lineY, uint32_t w)
{
- SCOPE_REGS
+ SCOPE_REGS_NO_LOOP
- for (; x < len; x++)
+ for (; x < drawLen; x++)
{
SCOPE_GET_SMP16
SCOPE_DRAW_SMP
@@ -228,9 +265,9 @@
static void scopeDrawLoop_16bit(scope_t *s, uint32_t x, uint32_t lineY, uint32_t w)
{
- SCOPE_REGS
+ SCOPE_REGS_LOOP
- for (; x < len; x++)
+ for (; x < drawLen; x++)
{
SCOPE_GET_SMP16
SCOPE_DRAW_SMP
@@ -243,7 +280,7 @@
{
SCOPE_REGS_PINGPONG
- for (; x < len; x++)
+ for (; x < drawLen; x++)
{
SCOPE_GET_SMP16
SCOPE_DRAW_SMP
@@ -258,11 +295,11 @@
static void linedScopeDrawNoLoop_8bit(scope_t *s, uint32_t x, uint32_t lineY, uint32_t w)
{
- LINED_SCOPE_REGS
+ LINED_SCOPE_REGS_NO_LOOP
LINED_SCOPE_PREPARE_SMP8
SCOPE_HANDLE_POS_NO_LOOP
- for (; x < len; x++)
+ for (; x < drawLen; x++)
{
SCOPE_GET_SMP8
LINED_SCOPE_DRAW_SMP
@@ -273,11 +310,11 @@
static void linedScopeDrawLoop_8bit(scope_t *s, uint32_t x, uint32_t lineY, uint32_t w)
{
- LINED_SCOPE_REGS
+ LINED_SCOPE_REGS_LOOP
LINED_SCOPE_PREPARE_SMP8
SCOPE_HANDLE_POS_LOOP
- for (; x < len; x++)
+ for (; x < drawLen; x++)
{
SCOPE_GET_SMP8
LINED_SCOPE_DRAW_SMP
@@ -292,7 +329,7 @@
LINED_SCOPE_PREPARE_SMP8
SCOPE_HANDLE_POS_PINGPONG
- for (; x < len; x++)
+ for (; x < drawLen; x++)
{
SCOPE_GET_SMP8
LINED_SCOPE_DRAW_SMP
@@ -303,11 +340,11 @@
static void linedScopeDrawNoLoop_16bit(scope_t *s, uint32_t x, uint32_t lineY, uint32_t w)
{
- LINED_SCOPE_REGS
+ LINED_SCOPE_REGS_NO_LOOP
LINED_SCOPE_PREPARE_SMP16
SCOPE_HANDLE_POS_NO_LOOP
- for (; x < len; x++)
+ for (; x < drawLen; x++)
{
SCOPE_GET_SMP16
LINED_SCOPE_DRAW_SMP
@@ -318,11 +355,11 @@
static void linedScopeDrawLoop_16bit(scope_t *s, uint32_t x, uint32_t lineY, uint32_t w)
{
- LINED_SCOPE_REGS
+ LINED_SCOPE_REGS_LOOP
LINED_SCOPE_PREPARE_SMP16
SCOPE_HANDLE_POS_LOOP
- for (; x < len; x++)
+ for (; x < drawLen; x++)
{
SCOPE_GET_SMP16
LINED_SCOPE_DRAW_SMP
@@ -337,7 +374,7 @@
LINED_SCOPE_PREPARE_SMP16
SCOPE_HANDLE_POS_PINGPONG
- for (; x < len; x++)
+ for (; x < drawLen; x++)
{
SCOPE_GET_SMP16
LINED_SCOPE_DRAW_SMP
--- a/src/ft2_scopes.c
+++ b/src/ft2_scopes.c
@@ -22,10 +22,6 @@
#include "ft2_scopedraw.h"
#include "ft2_tables.h"
-#if SCOPE_HZ != 64
-#error The SCOPE_HZ definition in ft2_header.h must be 2^n!
-#endif
-
enum
{
LOOP_NONE = 0,
@@ -44,9 +40,8 @@
} scopeState_t;
static volatile bool scopesUpdatingFlag, scopesDisplayingFlag;
-static int32_t oldPeriod;
static uint32_t scopeTimeLen, scopeTimeLenFrac;
-static uint64_t timeNext64, timeNext64Frac, oldSFrq;
+static uint64_t timeNext64, timeNext64Frac;
static volatile scope_t scope[MAX_VOICES];
static SDL_Thread *scopeThread;
static uint8_t *scopeMuteBMP_Ptrs[16];
@@ -53,12 +48,6 @@
lastChInstr_t lastChInstr[MAX_VOICES]; // global
-void resetCachedScopeVars(void)
-{
- oldPeriod = -1;
- oldSFrq = 0;
-}
-
int32_t getSamplePosition(uint8_t ch)
{
volatile bool active, sample16Bit;
@@ -363,7 +352,7 @@
tempState.sample16Bit = sampleIs16Bit;
tempState.loopType = loopType;
- tempState.SPosDir = 1; // forwards
+ tempState.backwards = false;
tempState.SLen = (loopType > 0) ? (loopBegin + loopLength) : length;
tempState.SRepS = loopBegin;
tempState.SRepL = loopLength;
@@ -381,6 +370,7 @@
tempState.active = true;
tempState.wasCleared = sc->wasCleared;
tempState.SFrq = sc->SFrq;
+ tempState.DFrq = sc->DFrq;
tempState.SVol = sc->SVol;
/* Update live scope now.
@@ -410,28 +400,34 @@
// scope position update
tempState.SPosDec += tempState.SFrq;
- tempState.SPos += ((int32_t)(tempState.SPosDec >> SCOPE_FRAC_BITS) * tempState.SPosDir);
+
+ const uint32_t posAdd = tempState.SPosDec >> SCOPE_FRAC_BITS;
+ if (tempState.backwards)
+ tempState.SPos -= posAdd;
+ else
+ tempState.SPos += posAdd;
+
tempState.SPosDec &= SCOPE_FRAC_MASK;
// handle loop wrapping or sample end
- if (tempState.SPosDir == -1 && tempState.SPos < tempState.SRepS) // sampling backwards (definitely pingpong loop)
+ if (tempState.backwards && tempState.SPos < tempState.SRepS) // sampling backwards (definitely pingpong loop)
{
- tempState.SPosDir = 1; // change direction to forwards
+ tempState.backwards = false; // change direction to forwards
- if (tempState.SRepL < 2)
- tempState.SPos = tempState.SRepS;
- else
+ if (tempState.SRepL >= 2)
tempState.SPos = tempState.SRepS + ((tempState.SRepS - tempState.SPos - 1) % tempState.SRepL);
+ else
+ tempState.SPos = tempState.SRepS;
assert(tempState.SPos >= tempState.SRepS && tempState.SPos < tempState.SLen);
}
else if (tempState.SPos >= tempState.SLen)
{
- if (tempState.SRepL < 2)
- loopOverflowVal = 0;
- else
+ if (tempState.SRepL >= 2)
loopOverflowVal = (tempState.SPos - tempState.SLen) % tempState.SRepL;
+ else
+ loopOverflowVal = 0;
if (tempState.loopType == LOOP_NONE)
{
@@ -444,7 +440,7 @@
}
else // pingpong loop
{
- tempState.SPosDir = -1; // change direction to backwards
+ tempState.backwards = true; // change direction to backwards
tempState.SPos = (tempState.SLen - 1) - loopOverflowVal;
assert(tempState.SPos >= tempState.SRepS && tempState.SPos < tempState.SLen);
}
@@ -548,7 +544,6 @@
uint8_t status;
syncedChannel_t *ch;
volatile scope_t *sc;
- sampleTyp *smpPtr;
sc = scope;
ch = chSyncData->channels;
@@ -556,31 +551,22 @@
{
status = scopeUpdateStatus[i];
- // set scope volume
if (status & IS_Vol)
sc->SVol = (int8_t)(((ch->finalVol * SCOPE_HEIGHT) + (1 << 15)) >> 16); // rounded
- // set scope frequency
if (status & IS_Period)
{
- if (ch->finalPeriod != oldPeriod)
- {
- oldPeriod = ch->finalPeriod;
- oldSFrq = (uint64_t)ch->voiceDelta * audio.freq; // this can very well be higher than 2^32
- }
-
- sc->SFrq = oldSFrq;
+ sc->SFrq = getScopeFrequenceValue(ch->finalPeriod);
+ sc->DFrq = (uint32_t)(sc->SFrq >> (SCOPE_FRAC_BITS - 10)); // amount of samples to skip after drawing a pixel
}
- // start scope sample
if (status & IS_NyTon)
{
if (instr[ch->instrNr] != NULL)
{
- smpPtr = &instr[ch->instrNr]->samp[ch->sampleNr];
- scopeTrigger(i, smpPtr, ch->smpStartPos);
+ scopeTrigger(i, &instr[ch->instrNr]->samp[ch->sampleNr], ch->smpStartPos);
- // set stuff used by Smp. Ed. for sampling position line
+ // set some stuff used by Smp. Ed. for sampling position line
if (ch->instrNr == 130 || (ch->instrNr == editor.curInstr && ch->sampleNr == editor.curSmp))
editor.curSmpChannel = (uint8_t)i;
@@ -598,8 +584,6 @@
uint32_t diff32;
uint64_t time64;
- (void)ptr;
-
// this is needed for scope stability (confirmed)
SDL_SetThreadPriority(SDL_THREAD_PRIORITY_HIGH);
@@ -637,6 +621,7 @@
}
}
+ (void)ptr;
return true;
}
@@ -648,11 +633,15 @@
dFrac = modf(editor.dPerfFreq / SCOPE_HZ, &dInt);
// integer part
- scopeTimeLen = (uint32_t)dInt;
+ scopeTimeLen = (int32_t)dInt;
// fractional part (scaled to 0..2^32-1)
dFrac *= UINT32_MAX;
- scopeTimeLenFrac = (uint32_t)(dFrac + 0.5);
+ dFrac += 0.5;
+ if (dFrac > UINT32_MAX)
+ dFrac = UINT32_MAX;
+
+ scopeTimeLenFrac = (uint32_t)dFrac;
// setup scope mute BMP pointers
assert(bmp.scopeMute != NULL);
--- a/src/ft2_scopes.h
+++ b/src/ft2_scopes.h
@@ -5,13 +5,10 @@
#include "ft2_header.h"
#include "ft2_audio.h"
-// 6 = log2(SCOPE_HZ) where SCOPE_HZ is 2^n
-#define SCOPE_FRAC_BITS (MIXER_FRAC_BITS+6)
-
-#define SCOPE_FRAC_SCALE (1L << SCOPE_FRAC_BITS)
+#define SCOPE_FRAC_BITS 32
+#define SCOPE_FRAC_SCALE (1ULL << SCOPE_FRAC_BITS)
#define SCOPE_FRAC_MASK (SCOPE_FRAC_SCALE-1)
-void resetCachedScopeVars(void);
int32_t getSamplePosition(uint8_t ch);
void stopAllScopes(void);
void refreshScopes(void);
@@ -27,9 +24,10 @@
const int8_t *sampleData8;
const int16_t *sampleData16;
int8_t SVol;
- bool wasCleared, sample16Bit;
+ bool wasCleared, sample16Bit, backwards;
uint8_t loopType;
- int32_t SPosDir, SRepS, SRepL, SLen, SPos;
+ int32_t SRepS, SRepL, SLen, SPos;
+ uint32_t DFrq;
uint64_t SFrq, SPosDec;
} scope_t;
--- a/src/ft2_tables.c
+++ b/src/ft2_tables.c
@@ -10,6 +10,14 @@
/* REPLAYER TABLES */
/* ----------------------------------------------------------------------- */
+const uint8_t arpTab[32] =
+{
+ 0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,
+ // the following are overflown values from vibTab in the FT2 replayer code
+ 0,24,49,74,97,120,141,161,180,
+ 197,212,224,235,244,250,253
+};
+
const int8_t vibSineTab[256] = // for auto-vibrato
{
0, -2, -3, -5, -6, -8, -9, -11, -12, -14, -16, -17, -19, -20, -22, -23,
@@ -60,7 +68,7 @@
494, 491, 487, 484, 480, 477, 474, 470, 467, 463, 460, 457
};
-const int16_t linearPeriods[1936] = // bit-exact to FT2 table
+const uint16_t linearPeriods[1936] = // bit-exact to FT2 table
{
7744, 7740, 7736, 7732, 7728, 7724, 7720, 7716, 7712, 7708, 7704, 7700, 7696, 7692, 7688, 7684,
7680, 7676, 7672, 7668, 7664, 7660, 7656, 7652, 7648, 7644, 7640, 7636, 7632, 7628, 7624, 7620,
@@ -185,7 +193,7 @@
64, 60, 56, 52, 48, 44, 40, 36, 32, 28, 24, 20, 16, 12, 8, 4
};
-const int16_t amigaPeriods[1936] = // bit-exact to FT2 table
+const uint16_t amigaPeriods[1936] = // bit-exact to FT2 table
{
29024, 28912, 28800, 28704, 28608, 28496, 28384, 28288, 28192, 28096, 28000, 27888, 27776, 27680, 27584, 27488,
27392, 27296, 27200, 27104, 27008, 26912, 26816, 26720, 26624, 26528, 26432, 26336, 26240, 26144, 26048, 25952,
@@ -339,6 +347,37 @@
/* ----------------------------------------------------------------------- */
/* GUI TABLES */
/* ----------------------------------------------------------------------- */
+
+const char *dec2StrTab[100] =
+{
+ "00","01","02","03","04","05","06","07","08","09","10","11","12","13","14","15",
+ "16","17","18","19","20","21","22","23","24","25","26","27","28","29","30","31",
+ "32","33","34","35","36","37","38","39","40","41","42","43","44","45","46","47",
+ "48","49","50","51","52","53","54","55","56","57","58","59","60","61","62","63",
+ "64","65","66","67","68","69","70","71","72","73","74","75","76","77","78","79",
+ "80","81","82","83","84","85","86","87","88","89","90","91","92","93","94","95",
+ "96","97","98","99"
+};
+
+const char *dec3StrTab[256] =
+{
+ "000","001","002","003","004","005","006","007","008","009","010","011","012","013","014","015",
+ "016","017","018","019","020","021","022","023","024","025","026","027","028","029","030","031",
+ "032","033","034","035","036","037","038","039","040","041","042","043","044","045","046","047",
+ "048","049","050","051","052","053","054","055","056","057","058","059","060","061","062","063",
+ "064","065","066","067","068","069","070","071","072","073","074","075","076","077","078","079",
+ "080","081","082","083","084","085","086","087","088","089","090","091","092","093","094","095",
+ "096","097","098","099","100","101","102","103","104","105","106","107","108","109","110","111",
+ "112","113","114","115","116","117","118","119","120","121","122","123","124","125","126","127",
+ "128","129","130","131","132","133","134","135","136","137","138","139","140","141","142","143",
+ "144","145","146","147","148","149","150","151","152","153","154","155","156","157","158","159",
+ "160","161","162","163","164","165","166","167","168","169","170","171","172","173","174","175",
+ "176","177","178","179","180","181","182","183","184","185","186","187","188","189","190","191",
+ "192","193","194","195","196","197","198","199","200","201","202","203","204","205","206","207",
+ "208","209","210","211","212","213","214","215","216","217","218","219","220","221","222","223",
+ "224","225","226","227","228","229","230","231","232","233","234","235","236","237","238","239",
+ "240","241","242","243","244","245","246","247","248","249","250","251","252","253","254","255"
+};
const uint8_t font1Widths[128] = // normal font
{
--- a/src/ft2_tables.h
+++ b/src/ft2_tables.h
@@ -10,14 +10,18 @@
#define KEY2EFX_ENTRIES (signed)(sizeof (key2EfxTab) / sizeof (SDL_Keycode))
#define KEY2HEX_ENTRIES (signed)(sizeof (key2HexTab) / sizeof (SDL_Keycode))
+extern const uint8_t arpTab[32];
extern const int8_t vibSineTab[256]; // for auto-vibrato
extern const uint8_t vibTab[32];
extern const uint16_t amigaPeriod[12 * 8];
extern const uint16_t amigaFinePeriod[12 * 8];
-extern const int16_t linearPeriods[1936];
-extern const int16_t amigaPeriods[1936];
+extern const uint16_t linearPeriods[1936];
+extern const uint16_t amigaPeriods[1936];
extern const uint32_t panningTab[257];
+
+extern const char *dec2StrTab[100];
+extern const char *dec3StrTab[256];
extern const uint8_t font1Widths[128];
extern const uint8_t font2Widths[128];
--- a/src/ft2_video.c
+++ b/src/ft2_video.c
@@ -49,7 +49,7 @@
// for FPS counter
#define FPS_SCAN_FRAMES 60
-#define FPS_RENDER_W 280
+#define FPS_RENDER_W 285
#define FPS_RENDER_H (((FONT1_CHAR_H + 1) * 8) + 1)
#define FPS_RENDER_X 2
#define FPS_RENDER_Y 2
@@ -1134,11 +1134,8 @@
if (editor.ui.drawReplayerPianoFlag)
{
editor.ui.drawReplayerPianoFlag = false;
- if (editor.ui.instEditorShown)
- {
- if (chSyncEntry != NULL)
- drawPiano(chSyncEntry);
- }
+ if (editor.ui.instEditorShown && chSyncEntry != NULL)
+ drawPiano(chSyncEntry);
}
drawPosText = true;
--- a/src/ft2_wav_renderer.c
+++ b/src/ft2_wav_renderer.c
@@ -38,7 +38,11 @@
static char WAV_SysReqText[192];
static uint8_t WDBitDepth = 16, WDStartPos, WDStopPos, *wavRenderBuffer;
static int16_t WDAmp;
+#if defined __amd64__ || defined _WIN64
+static uint32_t WDFrequency = 96000;
+#else
static uint32_t WDFrequency = 48000;
+#endif
static SDL_Thread *thread;
static void updateWavRenderer(void)
@@ -47,8 +51,13 @@
fillRect(209, 116, 41, 51, PAL_DESKTOP);
+#if defined __amd64__ || defined _WIN64
sprintf(str, "%06d", WDFrequency);
textOut(209, 116, PAL_FORGRND, str);
+#else
+ sprintf(str, "%05d", WDFrequency);
+ textOut(216, 116, PAL_FORGRND, str);
+#endif
sprintf(str, "%02d", WDAmp);
textOut(237, 130, PAL_FORGRND, str);
@@ -70,7 +79,7 @@
textOutShadow(4, 96, PAL_FORGRND, PAL_DSKTOP2, "Harddisk recording:");
textOutShadow(156, 96, PAL_FORGRND, PAL_DSKTOP2, "16-bit");
- textOutShadow(221, 96, PAL_FORGRND, PAL_DSKTOP2, "24-bit float");
+ textOutShadow(221, 96, PAL_FORGRND, PAL_DSKTOP2, "32-bit float");
textOutShadow(85, 116, PAL_FORGRND, PAL_DSKTOP2, "Frequency");
textOutShadow(85, 130, PAL_FORGRND, PAL_DSKTOP2, "Amplification");
@@ -180,7 +189,7 @@
song.globVol = 64;
setSpeed(song.speed);
- song.musicTime = 0;
+ resetPlaybackTime();
return true;
}
@@ -239,7 +248,7 @@
setBackOldAudioFreq();
setSpeed(song.speed);
- setAudioAmp(config.boostLevel, config.masterVol, config.specialFlags & BITDEPTH_24);
+ setAudioAmp(config.boostLevel, config.masterVol, config.specialFlags & BITDEPTH_32);
editor.wavIsRendering = false;
setMouseBusy(false);
@@ -280,12 +289,14 @@
editor.globalVol = song.globVol;
editor.ui.drawPosEdFlag = true;
- editor.ui.drawPattNumLenFlag = true;
+ editor.ui.drawPattNumLenFlag = true;
editor.ui.drawReplayerPianoFlag = true;
editor.ui.drawBPMFlag = true;
editor.ui.drawSpeedFlag = true;
editor.ui.drawGlobVolFlag = true;
editor.ui.updatePatternEditor = true;
+
+ drawPlaybackTime();
}
static int32_t SDLCALL renderWavThread(void *ptr)
@@ -358,7 +369,6 @@
updateVisuals();
dump_Close(f, sampleCounter);
-
resumeAudio();
editor.diskOpReadOnOpen = true;
@@ -432,15 +442,15 @@
{
if (WDFrequency < MAX_WAV_RENDER_FREQ)
{
- if (WDFrequency == 8000) WDFrequency = 11025;
- else if (WDFrequency == 11025) WDFrequency = 16000;
- else if (WDFrequency == 16000) WDFrequency = 22050;
- else if (WDFrequency == 22050) WDFrequency = 32000;
- else if (WDFrequency == 32000) WDFrequency = 44100;
- else if (WDFrequency == 44100) WDFrequency = 48000;
+
+#if defined __amd64__ || defined _WIN64
+ if (WDFrequency == 44100) WDFrequency = 48000;
else if (WDFrequency == 48000) WDFrequency = 96000;
else if (WDFrequency == 96000) WDFrequency = 192000;
-
+#else
+ if (WDFrequency == 44100) WDFrequency = 48000;
+ else if (WDFrequency == 48000) WDFrequency = 96000;
+#endif
updateWavRenderer();
}
}
@@ -449,9 +459,13 @@
{
if (WDFrequency > MIN_WAV_RENDER_FREQ)
{
+#if defined __amd64__ || defined _WIN64
if (WDFrequency == 192000) WDFrequency = 96000;
else if (WDFrequency == 96000) WDFrequency = 48000;
else if (WDFrequency == 48000) WDFrequency = 44100;
+#else
+ if (WDFrequency == 48000) WDFrequency = 44100;
+#endif
updateWavRenderer();
}
--- a/src/ft2_wav_renderer.h
+++ b/src/ft2_wav_renderer.h
@@ -4,7 +4,17 @@
#include "ft2_header.h"
#define MIN_WAV_RENDER_FREQ 44100
+
+#if defined __amd64__ || defined _WIN64
+
#define MAX_WAV_RENDER_FREQ 192000
+
+#else
+
+#define MAX_WAV_RENDER_FREQ 48000
+
+#endif
+
#define MAX_WAV_RENDER_SAMPLES_PER_TICK (((MAX_WAV_RENDER_FREQ * 5) / 2) / MIN_BPM)
void updateWavRendererSettings(void);
--- a/src/helpdata/FT2.HLP
+++ b/src/helpdata/FT2.HLP
@@ -785,8 +785,7 @@
>@X060@C002
Works for 16-bit audio mode only.
Applies random scaled values to the mixed samples before truncating to 16-bit.
-This should in theory lower the quantization noise. 16-bit already has
-a pretty low noise floor, so don't expect any audible difference here.
+This should in theory lower the quantization noise.
Also applies for WAV rendering.
>@X040@C001Amplification:
@@ -913,6 +912,8 @@
>@X010
>@C001Video:
>@C002
+>@X010- Fullscreen mode can be unbearably slow on a Raspberry Pi (even an RPi 4)
+>
>@X010- The scopes can mildly flicker depending on the waveform and pitch.
>@X021This is because their frequency is not clocked to exactly the same rate
>at which the scopes are rendered. It's close, which causes a flicker effect.
--- a/src/helpdata/ft2_help_data.h
+++ b/src/helpdata/ft2_help_data.h
@@ -3,9 +3,9 @@
#include <stdint.h>
-#define HELP_DATA_LEN 27305
+#define HELP_DATA_LEN 27298
-const uint8_t helpData[27305] =
+const uint8_t helpData[27298] =
{
0x4C,0x3B,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,
0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,
@@ -1796,493 +1796,492 @@
0x68,0x65,0x20,0x6D,0x69,0x78,0x65,0x64,0x20,0x73,0x61,0x6D,
0x70,0x6C,0x65,0x73,0x20,0x62,0x65,0x66,0x6F,0x72,0x65,0x20,
0x74,0x72,0x75,0x6E,0x63,0x61,0x74,0x69,0x6E,0x67,0x20,0x74,
- 0x6F,0x20,0x31,0x36,0x2D,0x62,0x69,0x74,0x2E,0x46,0x54,0x68,
+ 0x6F,0x20,0x31,0x36,0x2D,0x62,0x69,0x74,0x2E,0x33,0x54,0x68,
0x69,0x73,0x20,0x73,0x68,0x6F,0x75,0x6C,0x64,0x20,0x69,0x6E,
0x20,0x74,0x68,0x65,0x6F,0x72,0x79,0x20,0x6C,0x6F,0x77,0x65,
0x72,0x20,0x74,0x68,0x65,0x20,0x71,0x75,0x61,0x6E,0x74,0x69,
0x7A,0x61,0x74,0x69,0x6F,0x6E,0x20,0x6E,0x6F,0x69,0x73,0x65,
- 0x2E,0x20,0x31,0x36,0x2D,0x62,0x69,0x74,0x20,0x61,0x6C,0x72,
- 0x65,0x61,0x64,0x79,0x20,0x68,0x61,0x73,0x46,0x61,0x20,0x70,
- 0x72,0x65,0x74,0x74,0x79,0x20,0x6C,0x6F,0x77,0x20,0x6E,0x6F,
- 0x69,0x73,0x65,0x20,0x66,0x6C,0x6F,0x6F,0x72,0x2C,0x20,0x73,
- 0x6F,0x20,0x64,0x6F,0x6E,0x27,0x74,0x20,0x65,0x78,0x70,0x65,
- 0x63,0x74,0x20,0x61,0x6E,0x79,0x20,0x61,0x75,0x64,0x69,0x62,
- 0x6C,0x65,0x20,0x64,0x69,0x66,0x66,0x65,0x72,0x65,0x6E,0x63,
- 0x65,0x20,0x68,0x65,0x72,0x65,0x2E,0x1F,0x41,0x6C,0x73,0x6F,
- 0x20,0x61,0x70,0x70,0x6C,0x69,0x65,0x73,0x20,0x66,0x6F,0x72,
- 0x20,0x57,0x41,0x56,0x20,0x72,0x65,0x6E,0x64,0x65,0x72,0x69,
- 0x6E,0x67,0x2E,0x00,0x19,0x3E,0x40,0x58,0x30,0x34,0x30,0x40,
- 0x43,0x30,0x30,0x31,0x41,0x6D,0x70,0x6C,0x69,0x66,0x69,0x63,
- 0x61,0x74,0x69,0x6F,0x6E,0x3A,0x0B,0x3E,0x40,0x58,0x30,0x36,
- 0x30,0x40,0x43,0x30,0x30,0x32,0x46,0x41,0x6D,0x70,0x6C,0x69,
- 0x66,0x69,0x65,0x73,0x20,0x74,0x68,0x65,0x20,0x76,0x6F,0x6C,
- 0x75,0x6D,0x65,0x20,0x77,0x68,0x65,0x6E,0x20,0x6D,0x69,0x78,
- 0x69,0x6E,0x67,0x2E,0x20,0x49,0x66,0x20,0x79,0x6F,0x75,0x20,
- 0x73,0x65,0x74,0x20,0x74,0x68,0x69,0x73,0x20,0x6F,0x6E,0x65,
- 0x20,0x74,0x6F,0x6F,0x20,0x68,0x69,0x67,0x68,0x2C,0x20,0x79,
- 0x6F,0x75,0x27,0x6C,0x6C,0x3A,0x67,0x65,0x74,0x20,0x64,0x69,
- 0x73,0x74,0x6F,0x72,0x74,0x69,0x6F,0x6E,0x2E,0x20,0x33,0x32,
- 0x58,0x20,0x65,0x71,0x75,0x61,0x6C,0x73,0x20,0x66,0x75,0x6C,
- 0x6C,0x20,0x61,0x6D,0x70,0x6C,0x69,0x74,0x75,0x64,0x65,0x20,
- 0x66,0x6F,0x72,0x20,0x6F,0x6E,0x65,0x20,0x63,0x68,0x61,0x6E,
- 0x6E,0x65,0x6C,0x2E,0x00,0x1B,0x3E,0x40,0x58,0x30,0x34,0x30,
- 0x40,0x43,0x30,0x30,0x31,0x46,0x72,0x65,0x71,0x75,0x65,0x6E,
- 0x63,0x79,0x20,0x74,0x61,0x62,0x6C,0x65,0x3A,0x0B,0x3E,0x40,
- 0x58,0x30,0x36,0x30,0x40,0x43,0x30,0x30,0x32,0x40,0x54,0x68,
- 0x65,0x20,0x6C,0x69,0x6E,0x65,0x61,0x72,0x20,0x66,0x72,0x65,
- 0x71,0x75,0x65,0x6E,0x63,0x79,0x20,0x74,0x61,0x62,0x6C,0x65,
- 0x20,0x6D,0x61,0x6B,0x65,0x73,0x20,0x61,0x6C,0x6C,0x20,0x70,
- 0x69,0x74,0x63,0x68,0x20,0x62,0x65,0x6E,0x64,0x73,0x20,0x72,
- 0x75,0x6E,0x20,0x69,0x6E,0x20,0x63,0x6F,0x6E,0x73,0x74,0x61,
- 0x6E,0x74,0x3F,0x73,0x70,0x65,0x65,0x64,0x2C,0x20,0x69,0x6E,
- 0x64,0x65,0x70,0x65,0x6E,0x64,0x65,0x6E,0x74,0x20,0x6F,0x66,
- 0x20,0x74,0x68,0x65,0x20,0x63,0x75,0x72,0x72,0x65,0x6E,0x74,
- 0x20,0x66,0x72,0x65,0x71,0x75,0x65,0x6E,0x63,0x79,0x2E,0x20,
- 0x49,0x66,0x20,0x79,0x6F,0x75,0x20,0x73,0x77,0x69,0x74,0x63,
- 0x68,0x20,0x74,0x68,0x69,0x73,0x41,0x6F,0x6E,0x65,0x2C,0x20,
- 0x6F,0x6E,0x20,0x61,0x20,0x66,0x69,0x6E,0x69,0x73,0x68,0x65,
- 0x64,0x20,0x73,0x6F,0x6E,0x67,0x2C,0x20,0x69,0x74,0x20,0x6D,
- 0x69,0x67,0x68,0x74,0x20,0x73,0x6F,0x75,0x6E,0x64,0x20,0x73,
- 0x74,0x72,0x61,0x6E,0x67,0x65,0x20,0x69,0x66,0x20,0x74,0x68,
- 0x65,0x20,0x73,0x6F,0x75,0x6E,0x64,0x20,0x75,0x73,0x65,0x73,
- 0x0D,0x70,0x6F,0x72,0x74,0x61,0x6D,0x65,0x6E,0x74,0x6F,0x65,
- 0x73,0x2E,0x00,0x20,0x40,0x58,0x30,0x32,0x30,0x40,0x43,0x30,
- 0x30,0x31,0x43,0x6F,0x6E,0x66,0x69,0x67,0x75,0x72,0x61,0x74,
- 0x69,0x6F,0x6E,0x2C,0x20,0x4C,0x61,0x79,0x6F,0x75,0x74,0x3A,
- 0x01,0x3E,0x29,0x3E,0x40,0x58,0x30,0x34,0x30,0x40,0x43,0x30,
- 0x30,0x31,0x50,0x61,0x74,0x74,0x65,0x72,0x6E,0x20,0x6C,0x61,
- 0x79,0x6F,0x75,0x74,0x2C,0x20,0x68,0x65,0x78,0x20,0x6E,0x75,
- 0x6D,0x62,0x65,0x72,0x69,0x6E,0x67,0x3A,0x0B,0x3E,0x40,0x58,
- 0x30,0x36,0x30,0x40,0x43,0x30,0x30,0x32,0x41,0x49,0x66,0x20,
- 0x79,0x6F,0x75,0x20,0x75,0x73,0x65,0x20,0x70,0x61,0x74,0x74,
- 0x65,0x72,0x6E,0x73,0x20,0x74,0x68,0x61,0x74,0x20,0x61,0x72,
- 0x65,0x20,0x6C,0x6F,0x6E,0x67,0x65,0x72,0x20,0x74,0x68,0x61,
- 0x6E,0x20,0x39,0x39,0x20,0x6C,0x69,0x6E,0x65,0x73,0x2C,0x20,
- 0x79,0x6F,0x75,0x20,0x73,0x68,0x6F,0x75,0x6C,0x64,0x20,0x75,
- 0x73,0x65,0x45,0x68,0x65,0x78,0x20,0x63,0x6F,0x75,0x6E,0x74,
- 0x69,0x6E,0x67,0x20,0x73,0x69,0x6E,0x63,0x65,0x20,0x74,0x68,
- 0x65,0x72,0x65,0x20,0x61,0x72,0x65,0x20,0x6F,0x6E,0x6C,0x79,
- 0x20,0x32,0x20,0x64,0x69,0x67,0x69,0x74,0x73,0x20,0x69,0x6E,
- 0x20,0x74,0x68,0x65,0x20,0x6C,0x69,0x6E,0x65,0x20,0x6E,0x75,
- 0x6D,0x62,0x65,0x72,0x20,0x63,0x6F,0x6C,0x75,0x6D,0x6E,0x2E,
- 0x00,0x12,0x3E,0x40,0x58,0x30,0x34,0x30,0x40,0x43,0x30,0x30,
- 0x31,0x53,0x63,0x6F,0x70,0x65,0x73,0x3A,0x0B,0x3E,0x40,0x58,
- 0x30,0x36,0x30,0x40,0x43,0x30,0x30,0x32,0x43,0x22,0x53,0x74,
- 0x64,0x2E,0x22,0x20,0x28,0x73,0x74,0x61,0x6E,0x64,0x61,0x72,
- 0x64,0x29,0x20,0x77,0x69,0x6C,0x6C,0x20,0x73,0x68,0x6F,0x77,
- 0x20,0x74,0x68,0x65,0x20,0x73,0x61,0x6D,0x70,0x6C,0x65,0x20,
- 0x70,0x6F,0x69,0x6E,0x74,0x73,0x20,0x61,0x73,0x20,0x70,0x69,
- 0x78,0x65,0x6C,0x73,0x20,0x28,0x6C,0x69,0x6B,0x65,0x20,0x46,
- 0x54,0x32,0x29,0x2E,0x41,0x22,0x4C,0x69,0x6E,0x65,0x64,0x22,
- 0x20,0x77,0x69,0x6C,0x6C,0x20,0x64,0x72,0x61,0x77,0x20,0x6C,
- 0x69,0x6E,0x65,0x73,0x20,0x62,0x65,0x74,0x77,0x65,0x65,0x6E,
- 0x20,0x74,0x68,0x65,0x20,0x70,0x6F,0x69,0x6E,0x74,0x73,0x2C,
- 0x20,0x6C,0x69,0x6B,0x65,0x20,0x61,0x6E,0x20,0x6F,0x73,0x63,
- 0x69,0x6C,0x6C,0x6F,0x73,0x63,0x6F,0x70,0x65,0x2E,0x00,0x27,
- 0x40,0x58,0x30,0x32,0x30,0x40,0x43,0x30,0x30,0x31,0x43,0x6F,
- 0x6E,0x66,0x69,0x67,0x75,0x72,0x61,0x74,0x69,0x6F,0x6E,0x2C,
- 0x20,0x4D,0x69,0x73,0x63,0x65,0x6C,0x6C,0x61,0x6E,0x65,0x6F,
- 0x75,0x73,0x3A,0x01,0x3E,0x15,0x3E,0x40,0x58,0x30,0x34,0x30,
- 0x40,0x43,0x30,0x30,0x31,0x56,0x53,0x79,0x6E,0x63,0x20,0x6F,
- 0x66,0x66,0x3A,0x0B,0x3E,0x40,0x58,0x30,0x36,0x30,0x40,0x43,
- 0x30,0x30,0x32,0x3F,0x54,0x65,0x6C,0x6C,0x73,0x20,0x74,0x68,
- 0x65,0x20,0x70,0x72,0x6F,0x67,0x72,0x61,0x6D,0x20,0x74,0x6F,
- 0x20,0x6E,0x6F,0x74,0x20,0x75,0x73,0x65,0x20,0x56,0x53,0x79,
- 0x6E,0x63,0x20,0x66,0x6F,0x72,0x20,0x76,0x69,0x64,0x65,0x6F,
- 0x2E,0x20,0x49,0x66,0x20,0x79,0x6F,0x75,0x72,0x20,0x6D,0x6F,
- 0x6E,0x69,0x74,0x6F,0x72,0x27,0x73,0x40,0x72,0x65,0x66,0x72,
- 0x65,0x73,0x68,0x20,0x72,0x61,0x74,0x65,0x20,0x69,0x73,0x20,
- 0x6E,0x6F,0x74,0x20,0x36,0x30,0x48,0x7A,0x20,0x28,0x6F,0x72,
- 0x20,0x35,0x39,0x48,0x7A,0x29,0x2C,0x20,0x74,0x68,0x65,0x6E,
- 0x20,0x56,0x53,0x79,0x6E,0x63,0x20,0x69,0x73,0x20,0x61,0x6C,
- 0x77,0x61,0x79,0x73,0x20,0x6F,0x66,0x66,0x20,0x66,0x6F,0x72,
- 0x45,0x74,0x68,0x69,0x73,0x20,0x70,0x72,0x6F,0x67,0x72,0x61,
- 0x6D,0x2E,0x20,0x4E,0x6F,0x74,0x20,0x68,0x61,0x76,0x69,0x6E,
- 0x67,0x20,0x56,0x53,0x79,0x6E,0x63,0x20,0x77,0x69,0x6C,0x6C,
- 0x20,0x72,0x65,0x73,0x75,0x6C,0x74,0x20,0x69,0x6E,0x20,0x6C,
- 0x65,0x73,0x73,0x20,0x69,0x6E,0x70,0x75,0x74,0x2F,0x76,0x69,
- 0x64,0x65,0x6F,0x20,0x64,0x65,0x6C,0x61,0x79,0x2C,0x1E,0x62,
- 0x75,0x74,0x20,0x61,0x6C,0x73,0x6F,0x20,0x70,0x6F,0x74,0x65,
- 0x6E,0x74,0x69,0x61,0x6C,0x20,0x73,0x74,0x75,0x74,0x74,0x65,
- 0x72,0x69,0x6E,0x67,0x2E,0x01,0x20,0x18,0x3E,0x40,0x58,0x30,
- 0x34,0x30,0x40,0x43,0x30,0x30,0x31,0x50,0x69,0x78,0x65,0x6C,
- 0x20,0x66,0x69,0x6C,0x74,0x65,0x72,0x3A,0x0B,0x3E,0x40,0x58,
- 0x30,0x36,0x30,0x40,0x43,0x30,0x30,0x32,0x43,0x41,0x70,0x70,
- 0x6C,0x69,0x65,0x73,0x20,0x61,0x20,0x73,0x75,0x62,0x70,0x69,
- 0x78,0x65,0x6C,0x20,0x66,0x69,0x6C,0x74,0x65,0x72,0x20,0x74,
- 0x68,0x61,0x74,0x20,0x69,0x73,0x20,0x75,0x73,0x65,0x64,0x20,
- 0x77,0x68,0x65,0x6E,0x20,0x74,0x68,0x65,0x20,0x77,0x69,0x6E,
- 0x64,0x6F,0x77,0x20,0x69,0x73,0x20,0x75,0x70,0x73,0x63,0x61,
- 0x6C,0x65,0x64,0x2E,0x43,0x54,0x68,0x69,0x73,0x20,0x61,0x6C,
- 0x73,0x6F,0x20,0x6D,0x61,0x6B,0x65,0x73,0x20,0x66,0x75,0x6C,
- 0x6C,0x73,0x63,0x72,0x65,0x65,0x6E,0x20,0x6D,0x6F,0x64,0x65,
- 0x20,0x63,0x6F,0x6D,0x70,0x6C,0x65,0x74,0x65,0x6C,0x79,0x20,
- 0x73,0x74,0x72,0x65,0x74,0x63,0x68,0x20,0x6F,0x75,0x74,0x20,
- 0x69,0x66,0x20,0x69,0x74,0x20,0x64,0x69,0x64,0x6E,0x27,0x74,
- 0x44,0x61,0x6C,0x72,0x65,0x61,0x64,0x79,0x2E,0x20,0x50,0x6C,
- 0x65,0x61,0x73,0x65,0x20,0x6B,0x65,0x65,0x70,0x20,0x69,0x6E,
- 0x20,0x6D,0x69,0x6E,0x64,0x20,0x74,0x68,0x61,0x74,0x20,0x74,
- 0x68,0x69,0x73,0x20,0x77,0x69,0x6C,0x6C,0x20,0x6D,0x61,0x6B,
- 0x65,0x20,0x70,0x69,0x78,0x65,0x6C,0x73,0x20,0x6C,0x6F,0x6F,
- 0x6B,0x20,0x62,0x6C,0x75,0x72,0x72,0x79,0x2E,0x00,0x23,0x40,
- 0x58,0x30,0x32,0x30,0x40,0x43,0x30,0x30,0x31,0x41,0x64,0x76,
- 0x61,0x6E,0x63,0x65,0x64,0x20,0x65,0x64,0x69,0x74,0x20,0x66,
- 0x75,0x6E,0x63,0x74,0x69,0x6F,0x6E,0x73,0x3A,0x20,0x01,0x3E,
- 0x1E,0x3E,0x40,0x58,0x30,0x34,0x30,0x40,0x43,0x30,0x30,0x31,
- 0x43,0x6F,0x70,0x79,0x2F,0x50,0x61,0x73,0x74,0x65,0x20,0x6D,
- 0x61,0x73,0x6B,0x69,0x6E,0x67,0x3A,0x0B,0x3E,0x40,0x58,0x30,
- 0x36,0x30,0x40,0x43,0x30,0x30,0x32,0x37,0x54,0x68,0x65,0x20,
- 0x6D,0x61,0x73,0x6B,0x69,0x6E,0x67,0x20,0x69,0x73,0x20,0x75,
- 0x73,0x65,0x64,0x20,0x66,0x6F,0x72,0x20,0x63,0x6F,0x70,0x79,
- 0x69,0x6E,0x67,0x2F,0x70,0x61,0x73,0x74,0x69,0x6E,0x67,0x20,
- 0x6F,0x6E,0x6C,0x79,0x20,0x70,0x61,0x72,0x74,0x73,0x20,0x6F,
- 0x66,0x20,0x61,0x46,0x22,0x6E,0x6F,0x74,0x65,0x2D,0x63,0x65,
- 0x6C,0x6C,0x22,0x2E,0x20,0x54,0x68,0x65,0x20,0x64,0x69,0x66,
- 0x66,0x65,0x72,0x65,0x6E,0x74,0x20,0x70,0x61,0x72,0x74,0x73,
- 0x20,0x6F,0x66,0x20,0x61,0x20,0x22,0x6E,0x6F,0x74,0x65,0x2D,
- 0x63,0x65,0x6C,0x6C,0x22,0x20,0x69,0x73,0x20,0x4E,0x6F,0x74,
- 0x65,0x2C,0x20,0x49,0x6E,0x73,0x74,0x72,0x2E,0x20,0x6E,0x72,
- 0x2E,0x2C,0x20,0x56,0x6F,0x6C,0x75,0x6D,0x65,0x2C,0x20,0x45,
- 0x66,0x66,0x65,0x63,0x74,0x20,0x6E,0x72,0x20,0x26,0x20,0x45,
- 0x66,0x66,0x65,0x63,0x74,0x20,0x64,0x61,0x74,0x61,0x2E,0x34,
- 0x3E,0x41,0x73,0x20,0x79,0x6F,0x75,0x20,0x63,0x61,0x6E,0x20,
- 0x73,0x65,0x65,0x20,0x69,0x6E,0x20,0x74,0x68,0x65,0x20,0x77,
- 0x69,0x6E,0x64,0x6F,0x77,0x20,0x74,0x68,0x65,0x72,0x65,0x20,
- 0x61,0x72,0x65,0x20,0x33,0x20,0x63,0x6F,0x6C,0x75,0x6D,0x6E,
- 0x73,0x20,0x6F,0x66,0x3D,0x22,0x65,0x6E,0x61,0x62,0x6C,0x65,
- 0x2F,0x64,0x69,0x73,0x61,0x62,0x6C,0x65,0x20,0x62,0x75,0x74,
- 0x74,0x6F,0x6E,0x73,0x22,0x20,0x77,0x68,0x69,0x63,0x68,0x20,
- 0x68,0x61,0x73,0x20,0x74,0x68,0x65,0x20,0x6C,0x65,0x74,0x74,
- 0x65,0x72,0x73,0x20,0x43,0x2C,0x50,0x20,0x26,0x20,0x54,0x20,
- 0x61,0x62,0x6F,0x76,0x65,0x2E,0x45,0x3E,0x43,0x20,0x6D,0x65,
- 0x61,0x6E,0x73,0x20,0x63,0x6F,0x70,0x79,0x2C,0x20,0x69,0x74,
- 0x20,0x63,0x6F,0x6E,0x74,0x72,0x6F,0x6C,0x73,0x20,0x77,0x68,
- 0x69,0x63,0x68,0x20,0x70,0x61,0x72,0x74,0x73,0x20,0x74,0x68,
- 0x61,0x74,0x20,0x67,0x6F,0x65,0x73,0x20,0x69,0x6E,0x74,0x6F,
- 0x20,0x74,0x68,0x65,0x20,0x63,0x6F,0x70,0x79,0x62,0x75,0x66,
- 0x66,0x65,0x72,0x2E,0x3E,0x3E,0x50,0x20,0x6D,0x65,0x61,0x6E,
- 0x73,0x20,0x70,0x61,0x73,0x74,0x65,0x20,0x61,0x6E,0x64,0x20,
- 0x63,0x6F,0x6E,0x74,0x72,0x6F,0x6C,0x73,0x20,0x77,0x68,0x69,
- 0x63,0x68,0x20,0x70,0x61,0x72,0x74,0x73,0x20,0x74,0x68,0x61,
- 0x74,0x20,0x67,0x6F,0x65,0x73,0x20,0x6F,0x75,0x74,0x20,0x66,
- 0x72,0x6F,0x6D,0x20,0x74,0x68,0x65,0x0B,0x63,0x6F,0x70,0x79,
- 0x62,0x75,0x66,0x66,0x65,0x72,0x2E,0x45,0x3E,0x54,0x20,0x6D,
- 0x65,0x61,0x6E,0x73,0x20,0x74,0x72,0x61,0x6E,0x73,0x70,0x61,
- 0x72,0x65,0x6E,0x63,0x79,0x2E,0x20,0x49,0x66,0x20,0x69,0x74,
- 0x27,0x73,0x20,0x65,0x6E,0x61,0x62,0x6C,0x65,0x64,0x2C,0x20,
- 0x74,0x68,0x65,0x20,0x70,0x61,0x73,0x74,0x69,0x6E,0x67,0x20,
- 0x64,0x6F,0x65,0x73,0x6E,0x27,0x74,0x20,0x6F,0x76,0x65,0x72,
- 0x77,0x72,0x69,0x74,0x65,0x3D,0x64,0x61,0x74,0x61,0x20,0x77,
- 0x69,0x74,0x68,0x20,0x6E,0x69,0x6C,0x2D,0x69,0x6E,0x66,0x6F,
- 0x72,0x6D,0x61,0x74,0x69,0x6F,0x6E,0x2C,0x20,0x6F,0x6E,0x6C,
- 0x79,0x20,0x77,0x69,0x74,0x68,0x20,0x61,0x20,0x6E,0x6F,0x74,
- 0x65,0x20,0x6F,0x72,0x20,0x61,0x20,0x6E,0x75,0x6D,0x62,0x65,
- 0x72,0x20,0x3C,0x3E,0x20,0x30,0x2E,0x01,0x3E,0x40,0x3E,0x54,
- 0x68,0x65,0x20,0x63,0x75,0x74,0x20,0x66,0x75,0x6E,0x63,0x74,
- 0x69,0x6F,0x6E,0x73,0x20,0x77,0x6F,0x72,0x6B,0x73,0x20,0x6C,
- 0x69,0x6B,0x65,0x20,0x70,0x61,0x73,0x74,0x69,0x6E,0x67,0x20,
- 0x77,0x69,0x74,0x68,0x20,0x7A,0x65,0x72,0x6F,0x2D,0x64,0x61,
- 0x74,0x61,0x2E,0x20,0x54,0x68,0x69,0x73,0x20,0x6D,0x65,0x61,
- 0x6E,0x73,0x3B,0x74,0x68,0x61,0x74,0x20,0x74,0x68,0x65,0x20,
- 0x63,0x75,0x74,0x74,0x69,0x6E,0x67,0x20,0x69,0x73,0x20,0x63,
- 0x6F,0x6E,0x74,0x72,0x6F,0x6C,0x6C,0x65,0x64,0x20,0x77,0x69,
- 0x74,0x68,0x20,0x50,0x2D,0x63,0x6F,0x6C,0x75,0x6D,0x6E,0x20,
- 0x28,0x6F,0x72,0x20,0x54,0x2D,0x63,0x6F,0x6C,0x75,0x6D,0x6E,
- 0x29,0x2E,0x3C,0x3E,0x57,0x68,0x65,0x6E,0x20,0x79,0x6F,0x75,
- 0x20,0x63,0x6F,0x70,0x79,0x20,0x64,0x61,0x74,0x61,0x20,0x77,
- 0x69,0x74,0x68,0x20,0x6D,0x61,0x73,0x6B,0x69,0x6E,0x67,0x2C,
- 0x20,0x74,0x68,0x65,0x20,0x64,0x69,0x73,0x61,0x62,0x6C,0x65,
- 0x64,0x20,0x70,0x61,0x72,0x74,0x73,0x20,0x61,0x72,0x65,0x20,
- 0x6E,0x6F,0x74,0x43,0x63,0x6C,0x65,0x61,0x72,0x65,0x64,0x20,
- 0x69,0x6E,0x20,0x74,0x68,0x65,0x20,0x63,0x6F,0x70,0x79,0x62,
- 0x75,0x66,0x66,0x65,0x72,0x2E,0x20,0x28,0x4D,0x61,0x6B,0x69,
- 0x6E,0x67,0x20,0x69,0x74,0x20,0x70,0x6F,0x73,0x73,0x69,0x62,
- 0x6C,0x65,0x20,0x74,0x6F,0x20,0x63,0x6F,0x6C,0x6C,0x65,0x63,
- 0x74,0x20,0x64,0x61,0x74,0x61,0x20,0x66,0x72,0x6F,0x6D,0x27,
- 0x73,0x65,0x76,0x65,0x72,0x61,0x6C,0x20,0x6C,0x6F,0x63,0x61,
- 0x74,0x69,0x6F,0x6E,0x73,0x20,0x69,0x6E,0x74,0x6F,0x20,0x74,
- 0x68,0x65,0x20,0x63,0x6F,0x70,0x79,0x62,0x75,0x66,0x66,0x65,
- 0x72,0x2E,0x29,0x00,0x03,0x45,0x4E,0x44,0x4C,0x3B,0x2A,0x2A,
+ 0x2E,0x1F,0x41,0x6C,0x73,0x6F,0x20,0x61,0x70,0x70,0x6C,0x69,
+ 0x65,0x73,0x20,0x66,0x6F,0x72,0x20,0x57,0x41,0x56,0x20,0x72,
+ 0x65,0x6E,0x64,0x65,0x72,0x69,0x6E,0x67,0x2E,0x00,0x19,0x3E,
+ 0x40,0x58,0x30,0x34,0x30,0x40,0x43,0x30,0x30,0x31,0x41,0x6D,
+ 0x70,0x6C,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x3A,
+ 0x0B,0x3E,0x40,0x58,0x30,0x36,0x30,0x40,0x43,0x30,0x30,0x32,
+ 0x46,0x41,0x6D,0x70,0x6C,0x69,0x66,0x69,0x65,0x73,0x20,0x74,
+ 0x68,0x65,0x20,0x76,0x6F,0x6C,0x75,0x6D,0x65,0x20,0x77,0x68,
+ 0x65,0x6E,0x20,0x6D,0x69,0x78,0x69,0x6E,0x67,0x2E,0x20,0x49,
+ 0x66,0x20,0x79,0x6F,0x75,0x20,0x73,0x65,0x74,0x20,0x74,0x68,
+ 0x69,0x73,0x20,0x6F,0x6E,0x65,0x20,0x74,0x6F,0x6F,0x20,0x68,
+ 0x69,0x67,0x68,0x2C,0x20,0x79,0x6F,0x75,0x27,0x6C,0x6C,0x3A,
+ 0x67,0x65,0x74,0x20,0x64,0x69,0x73,0x74,0x6F,0x72,0x74,0x69,
+ 0x6F,0x6E,0x2E,0x20,0x33,0x32,0x58,0x20,0x65,0x71,0x75,0x61,
+ 0x6C,0x73,0x20,0x66,0x75,0x6C,0x6C,0x20,0x61,0x6D,0x70,0x6C,
+ 0x69,0x74,0x75,0x64,0x65,0x20,0x66,0x6F,0x72,0x20,0x6F,0x6E,
+ 0x65,0x20,0x63,0x68,0x61,0x6E,0x6E,0x65,0x6C,0x2E,0x00,0x1B,
+ 0x3E,0x40,0x58,0x30,0x34,0x30,0x40,0x43,0x30,0x30,0x31,0x46,
+ 0x72,0x65,0x71,0x75,0x65,0x6E,0x63,0x79,0x20,0x74,0x61,0x62,
+ 0x6C,0x65,0x3A,0x0B,0x3E,0x40,0x58,0x30,0x36,0x30,0x40,0x43,
+ 0x30,0x30,0x32,0x40,0x54,0x68,0x65,0x20,0x6C,0x69,0x6E,0x65,
+ 0x61,0x72,0x20,0x66,0x72,0x65,0x71,0x75,0x65,0x6E,0x63,0x79,
+ 0x20,0x74,0x61,0x62,0x6C,0x65,0x20,0x6D,0x61,0x6B,0x65,0x73,
+ 0x20,0x61,0x6C,0x6C,0x20,0x70,0x69,0x74,0x63,0x68,0x20,0x62,
+ 0x65,0x6E,0x64,0x73,0x20,0x72,0x75,0x6E,0x20,0x69,0x6E,0x20,
+ 0x63,0x6F,0x6E,0x73,0x74,0x61,0x6E,0x74,0x3F,0x73,0x70,0x65,
+ 0x65,0x64,0x2C,0x20,0x69,0x6E,0x64,0x65,0x70,0x65,0x6E,0x64,
+ 0x65,0x6E,0x74,0x20,0x6F,0x66,0x20,0x74,0x68,0x65,0x20,0x63,
+ 0x75,0x72,0x72,0x65,0x6E,0x74,0x20,0x66,0x72,0x65,0x71,0x75,
+ 0x65,0x6E,0x63,0x79,0x2E,0x20,0x49,0x66,0x20,0x79,0x6F,0x75,
+ 0x20,0x73,0x77,0x69,0x74,0x63,0x68,0x20,0x74,0x68,0x69,0x73,
+ 0x41,0x6F,0x6E,0x65,0x2C,0x20,0x6F,0x6E,0x20,0x61,0x20,0x66,
+ 0x69,0x6E,0x69,0x73,0x68,0x65,0x64,0x20,0x73,0x6F,0x6E,0x67,
+ 0x2C,0x20,0x69,0x74,0x20,0x6D,0x69,0x67,0x68,0x74,0x20,0x73,
+ 0x6F,0x75,0x6E,0x64,0x20,0x73,0x74,0x72,0x61,0x6E,0x67,0x65,
+ 0x20,0x69,0x66,0x20,0x74,0x68,0x65,0x20,0x73,0x6F,0x75,0x6E,
+ 0x64,0x20,0x75,0x73,0x65,0x73,0x0D,0x70,0x6F,0x72,0x74,0x61,
+ 0x6D,0x65,0x6E,0x74,0x6F,0x65,0x73,0x2E,0x00,0x20,0x40,0x58,
+ 0x30,0x32,0x30,0x40,0x43,0x30,0x30,0x31,0x43,0x6F,0x6E,0x66,
+ 0x69,0x67,0x75,0x72,0x61,0x74,0x69,0x6F,0x6E,0x2C,0x20,0x4C,
+ 0x61,0x79,0x6F,0x75,0x74,0x3A,0x01,0x3E,0x29,0x3E,0x40,0x58,
+ 0x30,0x34,0x30,0x40,0x43,0x30,0x30,0x31,0x50,0x61,0x74,0x74,
+ 0x65,0x72,0x6E,0x20,0x6C,0x61,0x79,0x6F,0x75,0x74,0x2C,0x20,
+ 0x68,0x65,0x78,0x20,0x6E,0x75,0x6D,0x62,0x65,0x72,0x69,0x6E,
+ 0x67,0x3A,0x0B,0x3E,0x40,0x58,0x30,0x36,0x30,0x40,0x43,0x30,
+ 0x30,0x32,0x41,0x49,0x66,0x20,0x79,0x6F,0x75,0x20,0x75,0x73,
+ 0x65,0x20,0x70,0x61,0x74,0x74,0x65,0x72,0x6E,0x73,0x20,0x74,
+ 0x68,0x61,0x74,0x20,0x61,0x72,0x65,0x20,0x6C,0x6F,0x6E,0x67,
+ 0x65,0x72,0x20,0x74,0x68,0x61,0x6E,0x20,0x39,0x39,0x20,0x6C,
+ 0x69,0x6E,0x65,0x73,0x2C,0x20,0x79,0x6F,0x75,0x20,0x73,0x68,
+ 0x6F,0x75,0x6C,0x64,0x20,0x75,0x73,0x65,0x45,0x68,0x65,0x78,
+ 0x20,0x63,0x6F,0x75,0x6E,0x74,0x69,0x6E,0x67,0x20,0x73,0x69,
+ 0x6E,0x63,0x65,0x20,0x74,0x68,0x65,0x72,0x65,0x20,0x61,0x72,
+ 0x65,0x20,0x6F,0x6E,0x6C,0x79,0x20,0x32,0x20,0x64,0x69,0x67,
+ 0x69,0x74,0x73,0x20,0x69,0x6E,0x20,0x74,0x68,0x65,0x20,0x6C,
+ 0x69,0x6E,0x65,0x20,0x6E,0x75,0x6D,0x62,0x65,0x72,0x20,0x63,
+ 0x6F,0x6C,0x75,0x6D,0x6E,0x2E,0x00,0x12,0x3E,0x40,0x58,0x30,
+ 0x34,0x30,0x40,0x43,0x30,0x30,0x31,0x53,0x63,0x6F,0x70,0x65,
+ 0x73,0x3A,0x0B,0x3E,0x40,0x58,0x30,0x36,0x30,0x40,0x43,0x30,
+ 0x30,0x32,0x43,0x22,0x53,0x74,0x64,0x2E,0x22,0x20,0x28,0x73,
+ 0x74,0x61,0x6E,0x64,0x61,0x72,0x64,0x29,0x20,0x77,0x69,0x6C,
+ 0x6C,0x20,0x73,0x68,0x6F,0x77,0x20,0x74,0x68,0x65,0x20,0x73,
+ 0x61,0x6D,0x70,0x6C,0x65,0x20,0x70,0x6F,0x69,0x6E,0x74,0x73,
+ 0x20,0x61,0x73,0x20,0x70,0x69,0x78,0x65,0x6C,0x73,0x20,0x28,
+ 0x6C,0x69,0x6B,0x65,0x20,0x46,0x54,0x32,0x29,0x2E,0x41,0x22,
+ 0x4C,0x69,0x6E,0x65,0x64,0x22,0x20,0x77,0x69,0x6C,0x6C,0x20,
+ 0x64,0x72,0x61,0x77,0x20,0x6C,0x69,0x6E,0x65,0x73,0x20,0x62,
+ 0x65,0x74,0x77,0x65,0x65,0x6E,0x20,0x74,0x68,0x65,0x20,0x70,
+ 0x6F,0x69,0x6E,0x74,0x73,0x2C,0x20,0x6C,0x69,0x6B,0x65,0x20,
+ 0x61,0x6E,0x20,0x6F,0x73,0x63,0x69,0x6C,0x6C,0x6F,0x73,0x63,
+ 0x6F,0x70,0x65,0x2E,0x00,0x27,0x40,0x58,0x30,0x32,0x30,0x40,
+ 0x43,0x30,0x30,0x31,0x43,0x6F,0x6E,0x66,0x69,0x67,0x75,0x72,
+ 0x61,0x74,0x69,0x6F,0x6E,0x2C,0x20,0x4D,0x69,0x73,0x63,0x65,
+ 0x6C,0x6C,0x61,0x6E,0x65,0x6F,0x75,0x73,0x3A,0x01,0x3E,0x15,
+ 0x3E,0x40,0x58,0x30,0x34,0x30,0x40,0x43,0x30,0x30,0x31,0x56,
+ 0x53,0x79,0x6E,0x63,0x20,0x6F,0x66,0x66,0x3A,0x0B,0x3E,0x40,
+ 0x58,0x30,0x36,0x30,0x40,0x43,0x30,0x30,0x32,0x3F,0x54,0x65,
+ 0x6C,0x6C,0x73,0x20,0x74,0x68,0x65,0x20,0x70,0x72,0x6F,0x67,
+ 0x72,0x61,0x6D,0x20,0x74,0x6F,0x20,0x6E,0x6F,0x74,0x20,0x75,
+ 0x73,0x65,0x20,0x56,0x53,0x79,0x6E,0x63,0x20,0x66,0x6F,0x72,
+ 0x20,0x76,0x69,0x64,0x65,0x6F,0x2E,0x20,0x49,0x66,0x20,0x79,
+ 0x6F,0x75,0x72,0x20,0x6D,0x6F,0x6E,0x69,0x74,0x6F,0x72,0x27,
+ 0x73,0x40,0x72,0x65,0x66,0x72,0x65,0x73,0x68,0x20,0x72,0x61,
+ 0x74,0x65,0x20,0x69,0x73,0x20,0x6E,0x6F,0x74,0x20,0x36,0x30,
+ 0x48,0x7A,0x20,0x28,0x6F,0x72,0x20,0x35,0x39,0x48,0x7A,0x29,
+ 0x2C,0x20,0x74,0x68,0x65,0x6E,0x20,0x56,0x53,0x79,0x6E,0x63,
+ 0x20,0x69,0x73,0x20,0x61,0x6C,0x77,0x61,0x79,0x73,0x20,0x6F,
+ 0x66,0x66,0x20,0x66,0x6F,0x72,0x45,0x74,0x68,0x69,0x73,0x20,
+ 0x70,0x72,0x6F,0x67,0x72,0x61,0x6D,0x2E,0x20,0x4E,0x6F,0x74,
+ 0x20,0x68,0x61,0x76,0x69,0x6E,0x67,0x20,0x56,0x53,0x79,0x6E,
+ 0x63,0x20,0x77,0x69,0x6C,0x6C,0x20,0x72,0x65,0x73,0x75,0x6C,
+ 0x74,0x20,0x69,0x6E,0x20,0x6C,0x65,0x73,0x73,0x20,0x69,0x6E,
+ 0x70,0x75,0x74,0x2F,0x76,0x69,0x64,0x65,0x6F,0x20,0x64,0x65,
+ 0x6C,0x61,0x79,0x2C,0x1E,0x62,0x75,0x74,0x20,0x61,0x6C,0x73,
+ 0x6F,0x20,0x70,0x6F,0x74,0x65,0x6E,0x74,0x69,0x61,0x6C,0x20,
+ 0x73,0x74,0x75,0x74,0x74,0x65,0x72,0x69,0x6E,0x67,0x2E,0x01,
+ 0x20,0x18,0x3E,0x40,0x58,0x30,0x34,0x30,0x40,0x43,0x30,0x30,
+ 0x31,0x50,0x69,0x78,0x65,0x6C,0x20,0x66,0x69,0x6C,0x74,0x65,
+ 0x72,0x3A,0x0B,0x3E,0x40,0x58,0x30,0x36,0x30,0x40,0x43,0x30,
+ 0x30,0x32,0x43,0x41,0x70,0x70,0x6C,0x69,0x65,0x73,0x20,0x61,
+ 0x20,0x73,0x75,0x62,0x70,0x69,0x78,0x65,0x6C,0x20,0x66,0x69,
+ 0x6C,0x74,0x65,0x72,0x20,0x74,0x68,0x61,0x74,0x20,0x69,0x73,
+ 0x20,0x75,0x73,0x65,0x64,0x20,0x77,0x68,0x65,0x6E,0x20,0x74,
+ 0x68,0x65,0x20,0x77,0x69,0x6E,0x64,0x6F,0x77,0x20,0x69,0x73,
+ 0x20,0x75,0x70,0x73,0x63,0x61,0x6C,0x65,0x64,0x2E,0x43,0x54,
+ 0x68,0x69,0x73,0x20,0x61,0x6C,0x73,0x6F,0x20,0x6D,0x61,0x6B,
+ 0x65,0x73,0x20,0x66,0x75,0x6C,0x6C,0x73,0x63,0x72,0x65,0x65,
+ 0x6E,0x20,0x6D,0x6F,0x64,0x65,0x20,0x63,0x6F,0x6D,0x70,0x6C,
+ 0x65,0x74,0x65,0x6C,0x79,0x20,0x73,0x74,0x72,0x65,0x74,0x63,
+ 0x68,0x20,0x6F,0x75,0x74,0x20,0x69,0x66,0x20,0x69,0x74,0x20,
+ 0x64,0x69,0x64,0x6E,0x27,0x74,0x44,0x61,0x6C,0x72,0x65,0x61,
+ 0x64,0x79,0x2E,0x20,0x50,0x6C,0x65,0x61,0x73,0x65,0x20,0x6B,
+ 0x65,0x65,0x70,0x20,0x69,0x6E,0x20,0x6D,0x69,0x6E,0x64,0x20,
+ 0x74,0x68,0x61,0x74,0x20,0x74,0x68,0x69,0x73,0x20,0x77,0x69,
+ 0x6C,0x6C,0x20,0x6D,0x61,0x6B,0x65,0x20,0x70,0x69,0x78,0x65,
+ 0x6C,0x73,0x20,0x6C,0x6F,0x6F,0x6B,0x20,0x62,0x6C,0x75,0x72,
+ 0x72,0x79,0x2E,0x00,0x23,0x40,0x58,0x30,0x32,0x30,0x40,0x43,
+ 0x30,0x30,0x31,0x41,0x64,0x76,0x61,0x6E,0x63,0x65,0x64,0x20,
+ 0x65,0x64,0x69,0x74,0x20,0x66,0x75,0x6E,0x63,0x74,0x69,0x6F,
+ 0x6E,0x73,0x3A,0x20,0x01,0x3E,0x1E,0x3E,0x40,0x58,0x30,0x34,
+ 0x30,0x40,0x43,0x30,0x30,0x31,0x43,0x6F,0x70,0x79,0x2F,0x50,
+ 0x61,0x73,0x74,0x65,0x20,0x6D,0x61,0x73,0x6B,0x69,0x6E,0x67,
+ 0x3A,0x0B,0x3E,0x40,0x58,0x30,0x36,0x30,0x40,0x43,0x30,0x30,
+ 0x32,0x37,0x54,0x68,0x65,0x20,0x6D,0x61,0x73,0x6B,0x69,0x6E,
+ 0x67,0x20,0x69,0x73,0x20,0x75,0x73,0x65,0x64,0x20,0x66,0x6F,
+ 0x72,0x20,0x63,0x6F,0x70,0x79,0x69,0x6E,0x67,0x2F,0x70,0x61,
+ 0x73,0x74,0x69,0x6E,0x67,0x20,0x6F,0x6E,0x6C,0x79,0x20,0x70,
+ 0x61,0x72,0x74,0x73,0x20,0x6F,0x66,0x20,0x61,0x46,0x22,0x6E,
+ 0x6F,0x74,0x65,0x2D,0x63,0x65,0x6C,0x6C,0x22,0x2E,0x20,0x54,
+ 0x68,0x65,0x20,0x64,0x69,0x66,0x66,0x65,0x72,0x65,0x6E,0x74,
+ 0x20,0x70,0x61,0x72,0x74,0x73,0x20,0x6F,0x66,0x20,0x61,0x20,
+ 0x22,0x6E,0x6F,0x74,0x65,0x2D,0x63,0x65,0x6C,0x6C,0x22,0x20,
+ 0x69,0x73,0x20,0x4E,0x6F,0x74,0x65,0x2C,0x20,0x49,0x6E,0x73,
+ 0x74,0x72,0x2E,0x20,0x6E,0x72,0x2E,0x2C,0x20,0x56,0x6F,0x6C,
+ 0x75,0x6D,0x65,0x2C,0x20,0x45,0x66,0x66,0x65,0x63,0x74,0x20,
+ 0x6E,0x72,0x20,0x26,0x20,0x45,0x66,0x66,0x65,0x63,0x74,0x20,
+ 0x64,0x61,0x74,0x61,0x2E,0x34,0x3E,0x41,0x73,0x20,0x79,0x6F,
+ 0x75,0x20,0x63,0x61,0x6E,0x20,0x73,0x65,0x65,0x20,0x69,0x6E,
+ 0x20,0x74,0x68,0x65,0x20,0x77,0x69,0x6E,0x64,0x6F,0x77,0x20,
+ 0x74,0x68,0x65,0x72,0x65,0x20,0x61,0x72,0x65,0x20,0x33,0x20,
+ 0x63,0x6F,0x6C,0x75,0x6D,0x6E,0x73,0x20,0x6F,0x66,0x3D,0x22,
+ 0x65,0x6E,0x61,0x62,0x6C,0x65,0x2F,0x64,0x69,0x73,0x61,0x62,
+ 0x6C,0x65,0x20,0x62,0x75,0x74,0x74,0x6F,0x6E,0x73,0x22,0x20,
+ 0x77,0x68,0x69,0x63,0x68,0x20,0x68,0x61,0x73,0x20,0x74,0x68,
+ 0x65,0x20,0x6C,0x65,0x74,0x74,0x65,0x72,0x73,0x20,0x43,0x2C,
+ 0x50,0x20,0x26,0x20,0x54,0x20,0x61,0x62,0x6F,0x76,0x65,0x2E,
+ 0x45,0x3E,0x43,0x20,0x6D,0x65,0x61,0x6E,0x73,0x20,0x63,0x6F,
+ 0x70,0x79,0x2C,0x20,0x69,0x74,0x20,0x63,0x6F,0x6E,0x74,0x72,
+ 0x6F,0x6C,0x73,0x20,0x77,0x68,0x69,0x63,0x68,0x20,0x70,0x61,
+ 0x72,0x74,0x73,0x20,0x74,0x68,0x61,0x74,0x20,0x67,0x6F,0x65,
+ 0x73,0x20,0x69,0x6E,0x74,0x6F,0x20,0x74,0x68,0x65,0x20,0x63,
+ 0x6F,0x70,0x79,0x62,0x75,0x66,0x66,0x65,0x72,0x2E,0x3E,0x3E,
+ 0x50,0x20,0x6D,0x65,0x61,0x6E,0x73,0x20,0x70,0x61,0x73,0x74,
+ 0x65,0x20,0x61,0x6E,0x64,0x20,0x63,0x6F,0x6E,0x74,0x72,0x6F,
+ 0x6C,0x73,0x20,0x77,0x68,0x69,0x63,0x68,0x20,0x70,0x61,0x72,
+ 0x74,0x73,0x20,0x74,0x68,0x61,0x74,0x20,0x67,0x6F,0x65,0x73,
+ 0x20,0x6F,0x75,0x74,0x20,0x66,0x72,0x6F,0x6D,0x20,0x74,0x68,
+ 0x65,0x0B,0x63,0x6F,0x70,0x79,0x62,0x75,0x66,0x66,0x65,0x72,
+ 0x2E,0x45,0x3E,0x54,0x20,0x6D,0x65,0x61,0x6E,0x73,0x20,0x74,
+ 0x72,0x61,0x6E,0x73,0x70,0x61,0x72,0x65,0x6E,0x63,0x79,0x2E,
+ 0x20,0x49,0x66,0x20,0x69,0x74,0x27,0x73,0x20,0x65,0x6E,0x61,
+ 0x62,0x6C,0x65,0x64,0x2C,0x20,0x74,0x68,0x65,0x20,0x70,0x61,
+ 0x73,0x74,0x69,0x6E,0x67,0x20,0x64,0x6F,0x65,0x73,0x6E,0x27,
+ 0x74,0x20,0x6F,0x76,0x65,0x72,0x77,0x72,0x69,0x74,0x65,0x3D,
+ 0x64,0x61,0x74,0x61,0x20,0x77,0x69,0x74,0x68,0x20,0x6E,0x69,
+ 0x6C,0x2D,0x69,0x6E,0x66,0x6F,0x72,0x6D,0x61,0x74,0x69,0x6F,
+ 0x6E,0x2C,0x20,0x6F,0x6E,0x6C,0x79,0x20,0x77,0x69,0x74,0x68,
+ 0x20,0x61,0x20,0x6E,0x6F,0x74,0x65,0x20,0x6F,0x72,0x20,0x61,
+ 0x20,0x6E,0x75,0x6D,0x62,0x65,0x72,0x20,0x3C,0x3E,0x20,0x30,
+ 0x2E,0x01,0x3E,0x40,0x3E,0x54,0x68,0x65,0x20,0x63,0x75,0x74,
+ 0x20,0x66,0x75,0x6E,0x63,0x74,0x69,0x6F,0x6E,0x73,0x20,0x77,
+ 0x6F,0x72,0x6B,0x73,0x20,0x6C,0x69,0x6B,0x65,0x20,0x70,0x61,
+ 0x73,0x74,0x69,0x6E,0x67,0x20,0x77,0x69,0x74,0x68,0x20,0x7A,
+ 0x65,0x72,0x6F,0x2D,0x64,0x61,0x74,0x61,0x2E,0x20,0x54,0x68,
+ 0x69,0x73,0x20,0x6D,0x65,0x61,0x6E,0x73,0x3B,0x74,0x68,0x61,
+ 0x74,0x20,0x74,0x68,0x65,0x20,0x63,0x75,0x74,0x74,0x69,0x6E,
+ 0x67,0x20,0x69,0x73,0x20,0x63,0x6F,0x6E,0x74,0x72,0x6F,0x6C,
+ 0x6C,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x50,0x2D,0x63,
+ 0x6F,0x6C,0x75,0x6D,0x6E,0x20,0x28,0x6F,0x72,0x20,0x54,0x2D,
+ 0x63,0x6F,0x6C,0x75,0x6D,0x6E,0x29,0x2E,0x3C,0x3E,0x57,0x68,
+ 0x65,0x6E,0x20,0x79,0x6F,0x75,0x20,0x63,0x6F,0x70,0x79,0x20,
+ 0x64,0x61,0x74,0x61,0x20,0x77,0x69,0x74,0x68,0x20,0x6D,0x61,
+ 0x73,0x6B,0x69,0x6E,0x67,0x2C,0x20,0x74,0x68,0x65,0x20,0x64,
+ 0x69,0x73,0x61,0x62,0x6C,0x65,0x64,0x20,0x70,0x61,0x72,0x74,
+ 0x73,0x20,0x61,0x72,0x65,0x20,0x6E,0x6F,0x74,0x43,0x63,0x6C,
+ 0x65,0x61,0x72,0x65,0x64,0x20,0x69,0x6E,0x20,0x74,0x68,0x65,
+ 0x20,0x63,0x6F,0x70,0x79,0x62,0x75,0x66,0x66,0x65,0x72,0x2E,
+ 0x20,0x28,0x4D,0x61,0x6B,0x69,0x6E,0x67,0x20,0x69,0x74,0x20,
+ 0x70,0x6F,0x73,0x73,0x69,0x62,0x6C,0x65,0x20,0x74,0x6F,0x20,
+ 0x63,0x6F,0x6C,0x6C,0x65,0x63,0x74,0x20,0x64,0x61,0x74,0x61,
+ 0x20,0x66,0x72,0x6F,0x6D,0x27,0x73,0x65,0x76,0x65,0x72,0x61,
+ 0x6C,0x20,0x6C,0x6F,0x63,0x61,0x74,0x69,0x6F,0x6E,0x73,0x20,
+ 0x69,0x6E,0x74,0x6F,0x20,0x74,0x68,0x65,0x20,0x63,0x6F,0x70,
+ 0x79,0x62,0x75,0x66,0x66,0x65,0x72,0x2E,0x29,0x00,0x03,0x45,
+ 0x4E,0x44,0x4C,0x3B,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,
0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,
0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,
0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,
0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,
0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,
+ 0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x4C,0x3B,0x2A,0x2A,0x2A,
0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,
- 0x2A,0x4C,0x3B,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,
0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,
0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,
0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,
0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,
0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,
- 0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x0E,0x40,0x4C,0x50,0x72,0x6F,
- 0x62,0x6C,0x65,0x6D,0x73,0x2F,0x46,0x41,0x51,0x06,0x3E,0x40,
- 0x58,0x30,0x32,0x30,0x41,0x3E,0x40,0x43,0x30,0x30,0x31,0x51,
- 0x3A,0x20,0x43,0x61,0x6E,0x20,0x49,0x20,0x6D,0x61,0x6B,0x65,
- 0x20,0x66,0x75,0x6C,0x6C,0x73,0x63,0x72,0x65,0x65,0x6E,0x20,
- 0x6D,0x6F,0x64,0x65,0x20,0x73,0x74,0x72,0x65,0x74,0x63,0x68,
- 0x20,0x6F,0x75,0x74,0x20,0x74,0x68,0x65,0x20,0x77,0x68,0x6F,
- 0x6C,0x65,0x20,0x73,0x63,0x72,0x65,0x65,0x6E,0x3F,0x3A,0x3E,
- 0x40,0x43,0x30,0x30,0x32,0x41,0x3A,0x20,0x45,0x6E,0x61,0x62,
- 0x6C,0x65,0x20,0x22,0x50,0x69,0x78,0x65,0x6C,0x20,0x66,0x69,
- 0x6C,0x74,0x65,0x72,0x22,0x20,0x69,0x6E,0x20,0x43,0x6F,0x6E,
- 0x66,0x69,0x67,0x20,0x2D,0x3E,0x20,0x4D,0x69,0x73,0x63,0x65,
- 0x6C,0x6C,0x61,0x6E,0x65,0x6F,0x75,0x73,0x2E,0x4D,0x3E,0x40,
- 0x58,0x30,0x33,0x35,0x49,0x74,0x20,0x77,0x6F,0x6E,0x27,0x74,
- 0x20,0x6C,0x6F,0x6F,0x6B,0x20,0x70,0x72,0x65,0x74,0x74,0x79,
- 0x2C,0x20,0x62,0x75,0x74,0x20,0x74,0x6F,0x20,0x73,0x6F,0x6D,
- 0x65,0x20,0x70,0x65,0x6F,0x70,0x6C,0x65,0x20,0x69,0x74,0x27,
- 0x73,0x20,0x6D,0x75,0x63,0x68,0x20,0x62,0x65,0x74,0x74,0x65,
- 0x72,0x20,0x74,0x68,0x61,0x6E,0x20,0x6E,0x6F,0x74,0x68,0x69,
- 0x6E,0x67,0x2E,0x06,0x3E,0x40,0x58,0x30,0x32,0x30,0x27,0x3E,
- 0x40,0x43,0x30,0x30,0x31,0x51,0x3A,0x20,0x49,0x20,0x63,0x61,
- 0x6E,0x27,0x74,0x20,0x75,0x73,0x65,0x20,0x41,0x4C,0x54,0x2B,
- 0x46,0x34,0x20,0x61,0x6E,0x64,0x20,0x41,0x4C,0x54,0x2B,0x46,
- 0x35,0x21,0x4E,0x3E,0x40,0x43,0x30,0x30,0x32,0x41,0x3A,0x20,
- 0x57,0x69,0x6E,0x64,0x6F,0x77,0x73,0x3A,0x20,0x49,0x66,0x20,
- 0x79,0x6F,0x75,0x20,0x68,0x61,0x76,0x65,0x20,0x47,0x65,0x46,
- 0x6F,0x72,0x63,0x65,0x20,0x45,0x78,0x70,0x65,0x72,0x69,0x65,
- 0x6E,0x63,0x65,0x20,0x69,0x6E,0x73,0x74,0x61,0x6C,0x6C,0x65,
- 0x64,0x2C,0x20,0x79,0x6F,0x75,0x20,0x6E,0x65,0x65,0x64,0x20,
- 0x74,0x6F,0x20,0x63,0x68,0x61,0x6E,0x67,0x65,0x2B,0x3E,0x40,
- 0x58,0x30,0x33,0x35,0x74,0x68,0x65,0x20,0x6B,0x65,0x79,0x62,
- 0x69,0x6E,0x64,0x69,0x6E,0x67,0x73,0x20,0x69,0x6E,0x20,0x69,
- 0x74,0x73,0x20,0x73,0x65,0x74,0x74,0x69,0x6E,0x67,0x73,0x20,
- 0x70,0x61,0x67,0x65,0x2E,0x56,0x6D,0x61,0x63,0x4F,0x53,0x2F,
- 0x4F,0x53,0x20,0x58,0x3A,0x20,0x43,0x68,0x61,0x6E,0x67,0x65,
- 0x20,0x41,0x4C,0x54,0x2B,0x46,0x34,0x2F,0x41,0x4C,0x54,0x2B,
- 0x46,0x35,0x20,0x6B,0x65,0x79,0x73,0x20,0x69,0x6E,0x20,0x74,
- 0x68,0x65,0x20,0x4F,0x53,0x20,0x74,0x6F,0x20,0x73,0x6F,0x6D,
- 0x65,0x74,0x68,0x69,0x6E,0x67,0x20,0x65,0x6C,0x73,0x65,0x2E,
- 0x20,0x41,0x6C,0x73,0x6F,0x20,0x66,0x6F,0x72,0x20,0x47,0x4E,
- 0x55,0x2F,0x4C,0x69,0x6E,0x75,0x78,0x2E,0x06,0x3E,0x40,0x58,
- 0x30,0x32,0x30,0x2B,0x3E,0x40,0x43,0x30,0x30,0x31,0x51,0x3A,
- 0x20,0x54,0x68,0x65,0x20,0x6D,0x6F,0x75,0x73,0x65,0x20,0x63,
- 0x75,0x72,0x73,0x6F,0x72,0x20,0x69,0x73,0x20,0x64,0x65,0x6C,
- 0x61,0x79,0x65,0x64,0x2F,0x6C,0x61,0x67,0x67,0x79,0x21,0x44,
- 0x3E,0x40,0x43,0x30,0x30,0x32,0x41,0x3A,0x20,0x4D,0x61,0x6B,
- 0x65,0x20,0x73,0x75,0x72,0x65,0x20,0x22,0x53,0x6F,0x66,0x74,
- 0x77,0x61,0x72,0x65,0x20,0x6D,0x6F,0x75,0x73,0x65,0x22,0x20,
- 0x69,0x73,0x20,0x64,0x69,0x73,0x61,0x62,0x6C,0x65,0x64,0x20,
+ 0x0E,0x40,0x4C,0x50,0x72,0x6F,0x62,0x6C,0x65,0x6D,0x73,0x2F,
+ 0x46,0x41,0x51,0x06,0x3E,0x40,0x58,0x30,0x32,0x30,0x41,0x3E,
+ 0x40,0x43,0x30,0x30,0x31,0x51,0x3A,0x20,0x43,0x61,0x6E,0x20,
+ 0x49,0x20,0x6D,0x61,0x6B,0x65,0x20,0x66,0x75,0x6C,0x6C,0x73,
+ 0x63,0x72,0x65,0x65,0x6E,0x20,0x6D,0x6F,0x64,0x65,0x20,0x73,
+ 0x74,0x72,0x65,0x74,0x63,0x68,0x20,0x6F,0x75,0x74,0x20,0x74,
+ 0x68,0x65,0x20,0x77,0x68,0x6F,0x6C,0x65,0x20,0x73,0x63,0x72,
+ 0x65,0x65,0x6E,0x3F,0x3A,0x3E,0x40,0x43,0x30,0x30,0x32,0x41,
+ 0x3A,0x20,0x45,0x6E,0x61,0x62,0x6C,0x65,0x20,0x22,0x50,0x69,
+ 0x78,0x65,0x6C,0x20,0x66,0x69,0x6C,0x74,0x65,0x72,0x22,0x20,
0x69,0x6E,0x20,0x43,0x6F,0x6E,0x66,0x69,0x67,0x20,0x2D,0x3E,
- 0x20,0x4C,0x61,0x79,0x6F,0x75,0x74,0x2E,0x4B,0x3E,0x40,0x58,
- 0x30,0x33,0x35,0x41,0x6C,0x74,0x65,0x72,0x6E,0x61,0x74,0x69,
- 0x76,0x65,0x6C,0x79,0x2C,0x20,0x79,0x6F,0x75,0x20,0x63,0x61,
- 0x6E,0x20,0x65,0x6E,0x61,0x62,0x6C,0x65,0x20,0x22,0x56,0x53,
- 0x79,0x6E,0x63,0x20,0x6F,0x66,0x66,0x22,0x20,0x69,0x6E,0x20,
- 0x43,0x6F,0x6E,0x66,0x69,0x67,0x20,0x2D,0x3E,0x20,0x4D,0x69,
- 0x73,0x63,0x65,0x6C,0x6C,0x61,0x6E,0x65,0x6F,0x75,0x73,0x2E,
- 0x46,0x3E,0x54,0x68,0x69,0x73,0x20,0x68,0x6F,0x77,0x65,0x76,
- 0x65,0x72,0x2C,0x20,0x77,0x69,0x6C,0x6C,0x20,0x69,0x6E,0x74,
- 0x72,0x6F,0x64,0x75,0x63,0x65,0x20,0x73,0x74,0x75,0x74,0x74,
- 0x65,0x72,0x69,0x6E,0x67,0x20,0x62,0x65,0x63,0x61,0x75,0x73,
- 0x65,0x20,0x74,0x68,0x65,0x20,0x72,0x65,0x6E,0x64,0x65,0x72,
- 0x69,0x6E,0x67,0x20,0x72,0x61,0x74,0x65,0x20,0x69,0x73,0x22,
- 0x3E,0x6E,0x6F,0x74,0x20,0x65,0x78,0x61,0x63,0x74,0x20,0x74,
- 0x6F,0x20,0x79,0x6F,0x75,0x72,0x20,0x6D,0x6F,0x6E,0x69,0x74,
- 0x6F,0x72,0x27,0x73,0x20,0x72,0x61,0x74,0x65,0x2E,0x06,0x3E,
- 0x40,0x58,0x30,0x32,0x30,0x33,0x3E,0x40,0x43,0x30,0x30,0x31,
- 0x51,0x3A,0x20,0x57,0x69,0x6C,0x6C,0x20,0x79,0x6F,0x75,0x20,
- 0x69,0x6D,0x70,0x6C,0x65,0x6D,0x65,0x6E,0x74,0x20,0x4D,0x49,
- 0x44,0x49,0x20,0x6F,0x75,0x74,0x20,0x66,0x75,0x6E,0x63,0x74,
- 0x69,0x6F,0x6E,0x61,0x6C,0x69,0x74,0x79,0x3F,0x4D,0x3E,0x40,
- 0x43,0x30,0x30,0x32,0x41,0x3A,0x20,0x4E,0x6F,0x2C,0x20,0x73,
- 0x6F,0x72,0x72,0x79,0x2E,0x20,0x54,0x68,0x69,0x73,0x20,0x69,
- 0x73,0x20,0x76,0x65,0x72,0x79,0x20,0x64,0x69,0x66,0x66,0x69,
- 0x63,0x75,0x6C,0x74,0x20,0x74,0x6F,0x20,0x69,0x6D,0x70,0x6C,
- 0x65,0x6D,0x65,0x6E,0x74,0x20,0x63,0x6F,0x72,0x72,0x65,0x63,
- 0x74,0x6C,0x79,0x20,0x77,0x68,0x65,0x6E,0x20,0x68,0x61,0x76,
- 0x69,0x6E,0x67,0x3C,0x3E,0x40,0x58,0x30,0x33,0x35,0x68,0x69,
- 0x67,0x68,0x65,0x72,0x20,0x61,0x75,0x64,0x69,0x6F,0x20,0x62,
- 0x75,0x66,0x66,0x65,0x72,0x20,0x73,0x69,0x7A,0x65,0x73,0x20,
- 0x28,0x62,0x75,0x66,0x66,0x65,0x72,0x65,0x64,0x20,0x72,0x65,
- 0x70,0x6C,0x61,0x79,0x65,0x72,0x20,0x74,0x69,0x63,0x6B,0x73,
- 0x29,0x2E,0x2E,0x2E,0x06,0x3E,0x40,0x58,0x30,0x32,0x30,0x30,
- 0x3E,0x40,0x43,0x30,0x30,0x31,0x51,0x3A,0x20,0x57,0x68,0x65,
- 0x72,0x65,0x20,0x69,0x73,0x20,0x74,0x68,0x65,0x20,0x63,0x6F,
- 0x6E,0x66,0x69,0x67,0x75,0x72,0x61,0x74,0x69,0x6F,0x6E,0x20,
- 0x66,0x69,0x6C,0x65,0x20,0x73,0x74,0x6F,0x72,0x65,0x64,0x3F,
- 0x3F,0x3E,0x40,0x43,0x30,0x30,0x32,0x41,0x3A,0x20,0x57,0x69,
- 0x6E,0x64,0x6F,0x77,0x73,0x3A,0x20,0x5C,0x55,0x73,0x65,0x72,
- 0x73,0x5C,0x55,0x53,0x45,0x52,0x5C,0x41,0x70,0x70,0x44,0x61,
- 0x74,0x61,0x5C,0x52,0x6F,0x61,0x6D,0x69,0x6E,0x67,0x5C,0x46,
- 0x54,0x32,0x20,0x63,0x6C,0x6F,0x6E,0x65,0x5C,0x46,0x54,0x32,
- 0x2E,0x43,0x46,0x47,0x45,0x3E,0x40,0x58,0x30,0x33,0x35,0x4F,
- 0x53,0x20,0x58,0x3A,0x20,0x2F,0x55,0x73,0x65,0x72,0x73,0x2F,
- 0x55,0x53,0x45,0x52,0x2F,0x4C,0x69,0x62,0x72,0x61,0x72,0x79,
- 0x2F,0x41,0x70,0x70,0x6C,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,
- 0x20,0x53,0x75,0x70,0x70,0x6F,0x72,0x74,0x2F,0x46,0x54,0x32,
- 0x20,0x63,0x6C,0x6F,0x6E,0x65,0x2F,0x46,0x54,0x32,0x2E,0x43,
- 0x46,0x47,0x2F,0x47,0x4E,0x55,0x2F,0x4C,0x69,0x6E,0x75,0x78,
- 0x3A,0x20,0x2F,0x68,0x6F,0x6D,0x65,0x2F,0x55,0x53,0x45,0x52,
- 0x2F,0x2E,0x63,0x6F,0x6E,0x66,0x69,0x67,0x2F,0x46,0x54,0x32,
- 0x20,0x63,0x6C,0x6F,0x6E,0x65,0x2F,0x46,0x54,0x32,0x2E,0x43,
- 0x46,0x47,0x01,0x3E,0x48,0x49,0x74,0x20,0x77,0x69,0x6C,0x6C,
- 0x20,0x62,0x65,0x20,0x73,0x74,0x6F,0x72,0x65,0x64,0x20,0x69,
- 0x6E,0x20,0x74,0x68,0x65,0x20,0x70,0x72,0x6F,0x67,0x72,0x61,
- 0x6D,0x20,0x64,0x69,0x72,0x65,0x63,0x74,0x6F,0x72,0x79,0x20,
- 0x69,0x66,0x20,0x74,0x68,0x65,0x20,0x70,0x61,0x74,0x68,0x20,
- 0x63,0x6F,0x75,0x6C,0x64,0x6E,0x27,0x74,0x20,0x62,0x65,0x20,
- 0x75,0x73,0x65,0x64,0x2E,0x4D,0x49,0x66,0x20,0x79,0x6F,0x75,
- 0x20,0x70,0x75,0x74,0x20,0x74,0x68,0x65,0x20,0x63,0x6F,0x6E,
- 0x66,0x69,0x67,0x75,0x72,0x61,0x74,0x69,0x6F,0x6E,0x20,0x66,
- 0x69,0x6C,0x65,0x20,0x69,0x6E,0x20,0x74,0x68,0x65,0x20,0x70,
- 0x72,0x6F,0x67,0x72,0x61,0x6D,0x20,0x64,0x69,0x72,0x65,0x63,
- 0x74,0x6F,0x72,0x79,0x2C,0x20,0x69,0x74,0x20,0x77,0x69,0x6C,
- 0x6C,0x20,0x72,0x65,0x61,0x64,0x20,0x74,0x68,0x61,0x74,0x4A,
- 0x6F,0x6E,0x65,0x20,0x61,0x6E,0x64,0x20,0x6E,0x6F,0x74,0x20,
- 0x61,0x74,0x74,0x65,0x6D,0x70,0x74,0x20,0x74,0x6F,0x20,0x63,
- 0x72,0x65,0x61,0x74,0x65,0x20,0x63,0x6F,0x6E,0x66,0x69,0x67,
- 0x20,0x64,0x69,0x72,0x73,0x20,0x66,0x6F,0x72,0x20,0x74,0x68,
- 0x65,0x20,0x4F,0x53,0x20,0x75,0x73,0x65,0x72,0x2E,0x20,0x28,
- 0x70,0x6F,0x72,0x74,0x61,0x62,0x6C,0x65,0x20,0x6D,0x6F,0x64,
- 0x65,0x29,0x06,0x3E,0x40,0x58,0x30,0x32,0x30,0x42,0x3E,0x40,
- 0x43,0x30,0x30,0x31,0x51,0x3A,0x20,0x43,0x61,0x6E,0x20,0x74,
- 0x68,0x65,0x20,0x63,0x6C,0x6F,0x6E,0x65,0x20,0x72,0x65,0x61,
- 0x64,0x20,0x46,0x54,0x32,0x2E,0x43,0x46,0x47,0x20,0x66,0x72,
- 0x6F,0x6D,0x20,0x72,0x65,0x61,0x6C,0x20,0x46,0x54,0x32,0x2C,
- 0x20,0x61,0x6E,0x64,0x20,0x76,0x69,0x63,0x65,0x20,0x76,0x65,
- 0x72,0x73,0x61,0x3F,0x4C,0x3E,0x40,0x43,0x30,0x30,0x32,0x41,
- 0x3A,0x20,0x59,0x65,0x73,0x2C,0x20,0x69,0x74,0x20,0x73,0x68,
- 0x6F,0x75,0x6C,0x64,0x20,0x77,0x6F,0x72,0x6B,0x20,0x6A,0x75,
- 0x73,0x74,0x20,0x66,0x69,0x6E,0x65,0x2E,0x20,0x50,0x75,0x74,
- 0x20,0x69,0x74,0x20,0x69,0x6E,0x20,0x74,0x68,0x65,0x20,0x64,
- 0x69,0x72,0x65,0x63,0x74,0x6F,0x72,0x79,0x20,0x73,0x68,0x6F,
- 0x77,0x6E,0x20,0x61,0x62,0x6F,0x76,0x65,0x2E,0x06,0x3E,0x40,
- 0x58,0x30,0x32,0x30,0x52,0x3E,0x40,0x43,0x30,0x30,0x31,0x51,
- 0x3A,0x20,0x53,0x6D,0x70,0x2E,0x20,0x45,0x64,0x2E,0x3A,0x20,
- 0x57,0x68,0x69,0x6C,0x65,0x20,0x7A,0x6F,0x6F,0x6D,0x69,0x6E,
- 0x67,0x20,0x69,0x6E,0x2C,0x20,0x49,0x20,0x73,0x6F,0x6D,0x65,
- 0x74,0x69,0x6D,0x65,0x73,0x20,0x63,0x61,0x6E,0x27,0x74,0x20,
- 0x6D,0x61,0x72,0x6B,0x20,0x74,0x68,0x65,0x20,0x6C,0x61,0x73,
- 0x74,0x20,0x73,0x61,0x6D,0x70,0x6C,0x65,0x20,0x70,0x6F,0x69,
- 0x6E,0x74,0x21,0x47,0x3E,0x40,0x43,0x30,0x30,0x32,0x41,0x3A,
- 0x20,0x54,0x68,0x69,0x73,0x20,0x69,0x73,0x20,0x6E,0x6F,0x72,
- 0x6D,0x61,0x6C,0x2E,0x20,0x54,0x68,0x69,0x73,0x20,0x69,0x73,
- 0x20,0x61,0x20,0x6C,0x69,0x6D,0x69,0x74,0x61,0x74,0x69,0x6F,
- 0x6E,0x20,0x69,0x6E,0x20,0x74,0x68,0x65,0x20,0x6E,0x61,0x74,
- 0x75,0x72,0x65,0x20,0x6F,0x66,0x20,0x73,0x63,0x61,0x6C,0x69,
- 0x6E,0x67,0x2E,0x06,0x3E,0x40,0x58,0x30,0x32,0x30,0x17,0x3E,
- 0x40,0x43,0x30,0x30,0x31,0x51,0x3A,0x20,0x49,0x20,0x66,0x6F,
- 0x75,0x6E,0x64,0x20,0x61,0x20,0x62,0x75,0x67,0x21,0x4B,0x3E,
- 0x40,0x43,0x30,0x30,0x32,0x41,0x3A,0x20,0x50,0x6C,0x65,0x61,
- 0x73,0x65,0x20,0x73,0x65,0x6E,0x64,0x20,0x61,0x20,0x6D,0x61,
- 0x69,0x6C,0x20,0x74,0x6F,0x20,0x6F,0x6C,0x61,0x76,0x2E,0x73,
- 0x6F,0x72,0x65,0x6E,0x73,0x65,0x6E,0x40,0x6C,0x69,0x76,0x65,
- 0x2E,0x6E,0x6F,0x20,0x61,0x6E,0x64,0x20,0x74,0x72,0x79,0x20,
- 0x74,0x6F,0x20,0x65,0x78,0x70,0x6C,0x61,0x69,0x6E,0x20,0x69,
- 0x74,0x2E,0x00,0x03,0x45,0x4E,0x44,0x4C,0x3B,0x2A,0x2A,0x2A,
+ 0x20,0x4D,0x69,0x73,0x63,0x65,0x6C,0x6C,0x61,0x6E,0x65,0x6F,
+ 0x75,0x73,0x2E,0x4D,0x3E,0x40,0x58,0x30,0x33,0x35,0x49,0x74,
+ 0x20,0x77,0x6F,0x6E,0x27,0x74,0x20,0x6C,0x6F,0x6F,0x6B,0x20,
+ 0x70,0x72,0x65,0x74,0x74,0x79,0x2C,0x20,0x62,0x75,0x74,0x20,
+ 0x74,0x6F,0x20,0x73,0x6F,0x6D,0x65,0x20,0x70,0x65,0x6F,0x70,
+ 0x6C,0x65,0x20,0x69,0x74,0x27,0x73,0x20,0x6D,0x75,0x63,0x68,
+ 0x20,0x62,0x65,0x74,0x74,0x65,0x72,0x20,0x74,0x68,0x61,0x6E,
+ 0x20,0x6E,0x6F,0x74,0x68,0x69,0x6E,0x67,0x2E,0x06,0x3E,0x40,
+ 0x58,0x30,0x32,0x30,0x27,0x3E,0x40,0x43,0x30,0x30,0x31,0x51,
+ 0x3A,0x20,0x49,0x20,0x63,0x61,0x6E,0x27,0x74,0x20,0x75,0x73,
+ 0x65,0x20,0x41,0x4C,0x54,0x2B,0x46,0x34,0x20,0x61,0x6E,0x64,
+ 0x20,0x41,0x4C,0x54,0x2B,0x46,0x35,0x21,0x4E,0x3E,0x40,0x43,
+ 0x30,0x30,0x32,0x41,0x3A,0x20,0x57,0x69,0x6E,0x64,0x6F,0x77,
+ 0x73,0x3A,0x20,0x49,0x66,0x20,0x79,0x6F,0x75,0x20,0x68,0x61,
+ 0x76,0x65,0x20,0x47,0x65,0x46,0x6F,0x72,0x63,0x65,0x20,0x45,
+ 0x78,0x70,0x65,0x72,0x69,0x65,0x6E,0x63,0x65,0x20,0x69,0x6E,
+ 0x73,0x74,0x61,0x6C,0x6C,0x65,0x64,0x2C,0x20,0x79,0x6F,0x75,
+ 0x20,0x6E,0x65,0x65,0x64,0x20,0x74,0x6F,0x20,0x63,0x68,0x61,
+ 0x6E,0x67,0x65,0x2B,0x3E,0x40,0x58,0x30,0x33,0x35,0x74,0x68,
+ 0x65,0x20,0x6B,0x65,0x79,0x62,0x69,0x6E,0x64,0x69,0x6E,0x67,
+ 0x73,0x20,0x69,0x6E,0x20,0x69,0x74,0x73,0x20,0x73,0x65,0x74,
+ 0x74,0x69,0x6E,0x67,0x73,0x20,0x70,0x61,0x67,0x65,0x2E,0x56,
+ 0x6D,0x61,0x63,0x4F,0x53,0x2F,0x4F,0x53,0x20,0x58,0x3A,0x20,
+ 0x43,0x68,0x61,0x6E,0x67,0x65,0x20,0x41,0x4C,0x54,0x2B,0x46,
+ 0x34,0x2F,0x41,0x4C,0x54,0x2B,0x46,0x35,0x20,0x6B,0x65,0x79,
+ 0x73,0x20,0x69,0x6E,0x20,0x74,0x68,0x65,0x20,0x4F,0x53,0x20,
+ 0x74,0x6F,0x20,0x73,0x6F,0x6D,0x65,0x74,0x68,0x69,0x6E,0x67,
+ 0x20,0x65,0x6C,0x73,0x65,0x2E,0x20,0x41,0x6C,0x73,0x6F,0x20,
+ 0x66,0x6F,0x72,0x20,0x47,0x4E,0x55,0x2F,0x4C,0x69,0x6E,0x75,
+ 0x78,0x2E,0x06,0x3E,0x40,0x58,0x30,0x32,0x30,0x2B,0x3E,0x40,
+ 0x43,0x30,0x30,0x31,0x51,0x3A,0x20,0x54,0x68,0x65,0x20,0x6D,
+ 0x6F,0x75,0x73,0x65,0x20,0x63,0x75,0x72,0x73,0x6F,0x72,0x20,
+ 0x69,0x73,0x20,0x64,0x65,0x6C,0x61,0x79,0x65,0x64,0x2F,0x6C,
+ 0x61,0x67,0x67,0x79,0x21,0x44,0x3E,0x40,0x43,0x30,0x30,0x32,
+ 0x41,0x3A,0x20,0x4D,0x61,0x6B,0x65,0x20,0x73,0x75,0x72,0x65,
+ 0x20,0x22,0x53,0x6F,0x66,0x74,0x77,0x61,0x72,0x65,0x20,0x6D,
+ 0x6F,0x75,0x73,0x65,0x22,0x20,0x69,0x73,0x20,0x64,0x69,0x73,
+ 0x61,0x62,0x6C,0x65,0x64,0x20,0x69,0x6E,0x20,0x43,0x6F,0x6E,
+ 0x66,0x69,0x67,0x20,0x2D,0x3E,0x20,0x4C,0x61,0x79,0x6F,0x75,
+ 0x74,0x2E,0x4B,0x3E,0x40,0x58,0x30,0x33,0x35,0x41,0x6C,0x74,
+ 0x65,0x72,0x6E,0x61,0x74,0x69,0x76,0x65,0x6C,0x79,0x2C,0x20,
+ 0x79,0x6F,0x75,0x20,0x63,0x61,0x6E,0x20,0x65,0x6E,0x61,0x62,
+ 0x6C,0x65,0x20,0x22,0x56,0x53,0x79,0x6E,0x63,0x20,0x6F,0x66,
+ 0x66,0x22,0x20,0x69,0x6E,0x20,0x43,0x6F,0x6E,0x66,0x69,0x67,
+ 0x20,0x2D,0x3E,0x20,0x4D,0x69,0x73,0x63,0x65,0x6C,0x6C,0x61,
+ 0x6E,0x65,0x6F,0x75,0x73,0x2E,0x46,0x3E,0x54,0x68,0x69,0x73,
+ 0x20,0x68,0x6F,0x77,0x65,0x76,0x65,0x72,0x2C,0x20,0x77,0x69,
+ 0x6C,0x6C,0x20,0x69,0x6E,0x74,0x72,0x6F,0x64,0x75,0x63,0x65,
+ 0x20,0x73,0x74,0x75,0x74,0x74,0x65,0x72,0x69,0x6E,0x67,0x20,
+ 0x62,0x65,0x63,0x61,0x75,0x73,0x65,0x20,0x74,0x68,0x65,0x20,
+ 0x72,0x65,0x6E,0x64,0x65,0x72,0x69,0x6E,0x67,0x20,0x72,0x61,
+ 0x74,0x65,0x20,0x69,0x73,0x22,0x3E,0x6E,0x6F,0x74,0x20,0x65,
+ 0x78,0x61,0x63,0x74,0x20,0x74,0x6F,0x20,0x79,0x6F,0x75,0x72,
+ 0x20,0x6D,0x6F,0x6E,0x69,0x74,0x6F,0x72,0x27,0x73,0x20,0x72,
+ 0x61,0x74,0x65,0x2E,0x06,0x3E,0x40,0x58,0x30,0x32,0x30,0x33,
+ 0x3E,0x40,0x43,0x30,0x30,0x31,0x51,0x3A,0x20,0x57,0x69,0x6C,
+ 0x6C,0x20,0x79,0x6F,0x75,0x20,0x69,0x6D,0x70,0x6C,0x65,0x6D,
+ 0x65,0x6E,0x74,0x20,0x4D,0x49,0x44,0x49,0x20,0x6F,0x75,0x74,
+ 0x20,0x66,0x75,0x6E,0x63,0x74,0x69,0x6F,0x6E,0x61,0x6C,0x69,
+ 0x74,0x79,0x3F,0x4D,0x3E,0x40,0x43,0x30,0x30,0x32,0x41,0x3A,
+ 0x20,0x4E,0x6F,0x2C,0x20,0x73,0x6F,0x72,0x72,0x79,0x2E,0x20,
+ 0x54,0x68,0x69,0x73,0x20,0x69,0x73,0x20,0x76,0x65,0x72,0x79,
+ 0x20,0x64,0x69,0x66,0x66,0x69,0x63,0x75,0x6C,0x74,0x20,0x74,
+ 0x6F,0x20,0x69,0x6D,0x70,0x6C,0x65,0x6D,0x65,0x6E,0x74,0x20,
+ 0x63,0x6F,0x72,0x72,0x65,0x63,0x74,0x6C,0x79,0x20,0x77,0x68,
+ 0x65,0x6E,0x20,0x68,0x61,0x76,0x69,0x6E,0x67,0x3C,0x3E,0x40,
+ 0x58,0x30,0x33,0x35,0x68,0x69,0x67,0x68,0x65,0x72,0x20,0x61,
+ 0x75,0x64,0x69,0x6F,0x20,0x62,0x75,0x66,0x66,0x65,0x72,0x20,
+ 0x73,0x69,0x7A,0x65,0x73,0x20,0x28,0x62,0x75,0x66,0x66,0x65,
+ 0x72,0x65,0x64,0x20,0x72,0x65,0x70,0x6C,0x61,0x79,0x65,0x72,
+ 0x20,0x74,0x69,0x63,0x6B,0x73,0x29,0x2E,0x2E,0x2E,0x06,0x3E,
+ 0x40,0x58,0x30,0x32,0x30,0x30,0x3E,0x40,0x43,0x30,0x30,0x31,
+ 0x51,0x3A,0x20,0x57,0x68,0x65,0x72,0x65,0x20,0x69,0x73,0x20,
+ 0x74,0x68,0x65,0x20,0x63,0x6F,0x6E,0x66,0x69,0x67,0x75,0x72,
+ 0x61,0x74,0x69,0x6F,0x6E,0x20,0x66,0x69,0x6C,0x65,0x20,0x73,
+ 0x74,0x6F,0x72,0x65,0x64,0x3F,0x3F,0x3E,0x40,0x43,0x30,0x30,
+ 0x32,0x41,0x3A,0x20,0x57,0x69,0x6E,0x64,0x6F,0x77,0x73,0x3A,
+ 0x20,0x5C,0x55,0x73,0x65,0x72,0x73,0x5C,0x55,0x53,0x45,0x52,
+ 0x5C,0x41,0x70,0x70,0x44,0x61,0x74,0x61,0x5C,0x52,0x6F,0x61,
+ 0x6D,0x69,0x6E,0x67,0x5C,0x46,0x54,0x32,0x20,0x63,0x6C,0x6F,
+ 0x6E,0x65,0x5C,0x46,0x54,0x32,0x2E,0x43,0x46,0x47,0x45,0x3E,
+ 0x40,0x58,0x30,0x33,0x35,0x4F,0x53,0x20,0x58,0x3A,0x20,0x2F,
+ 0x55,0x73,0x65,0x72,0x73,0x2F,0x55,0x53,0x45,0x52,0x2F,0x4C,
+ 0x69,0x62,0x72,0x61,0x72,0x79,0x2F,0x41,0x70,0x70,0x6C,0x69,
+ 0x63,0x61,0x74,0x69,0x6F,0x6E,0x20,0x53,0x75,0x70,0x70,0x6F,
+ 0x72,0x74,0x2F,0x46,0x54,0x32,0x20,0x63,0x6C,0x6F,0x6E,0x65,
+ 0x2F,0x46,0x54,0x32,0x2E,0x43,0x46,0x47,0x2F,0x47,0x4E,0x55,
+ 0x2F,0x4C,0x69,0x6E,0x75,0x78,0x3A,0x20,0x2F,0x68,0x6F,0x6D,
+ 0x65,0x2F,0x55,0x53,0x45,0x52,0x2F,0x2E,0x63,0x6F,0x6E,0x66,
+ 0x69,0x67,0x2F,0x46,0x54,0x32,0x20,0x63,0x6C,0x6F,0x6E,0x65,
+ 0x2F,0x46,0x54,0x32,0x2E,0x43,0x46,0x47,0x01,0x3E,0x48,0x49,
+ 0x74,0x20,0x77,0x69,0x6C,0x6C,0x20,0x62,0x65,0x20,0x73,0x74,
+ 0x6F,0x72,0x65,0x64,0x20,0x69,0x6E,0x20,0x74,0x68,0x65,0x20,
+ 0x70,0x72,0x6F,0x67,0x72,0x61,0x6D,0x20,0x64,0x69,0x72,0x65,
+ 0x63,0x74,0x6F,0x72,0x79,0x20,0x69,0x66,0x20,0x74,0x68,0x65,
+ 0x20,0x70,0x61,0x74,0x68,0x20,0x63,0x6F,0x75,0x6C,0x64,0x6E,
+ 0x27,0x74,0x20,0x62,0x65,0x20,0x75,0x73,0x65,0x64,0x2E,0x4D,
+ 0x49,0x66,0x20,0x79,0x6F,0x75,0x20,0x70,0x75,0x74,0x20,0x74,
+ 0x68,0x65,0x20,0x63,0x6F,0x6E,0x66,0x69,0x67,0x75,0x72,0x61,
+ 0x74,0x69,0x6F,0x6E,0x20,0x66,0x69,0x6C,0x65,0x20,0x69,0x6E,
+ 0x20,0x74,0x68,0x65,0x20,0x70,0x72,0x6F,0x67,0x72,0x61,0x6D,
+ 0x20,0x64,0x69,0x72,0x65,0x63,0x74,0x6F,0x72,0x79,0x2C,0x20,
+ 0x69,0x74,0x20,0x77,0x69,0x6C,0x6C,0x20,0x72,0x65,0x61,0x64,
+ 0x20,0x74,0x68,0x61,0x74,0x4A,0x6F,0x6E,0x65,0x20,0x61,0x6E,
+ 0x64,0x20,0x6E,0x6F,0x74,0x20,0x61,0x74,0x74,0x65,0x6D,0x70,
+ 0x74,0x20,0x74,0x6F,0x20,0x63,0x72,0x65,0x61,0x74,0x65,0x20,
+ 0x63,0x6F,0x6E,0x66,0x69,0x67,0x20,0x64,0x69,0x72,0x73,0x20,
+ 0x66,0x6F,0x72,0x20,0x74,0x68,0x65,0x20,0x4F,0x53,0x20,0x75,
+ 0x73,0x65,0x72,0x2E,0x20,0x28,0x70,0x6F,0x72,0x74,0x61,0x62,
+ 0x6C,0x65,0x20,0x6D,0x6F,0x64,0x65,0x29,0x06,0x3E,0x40,0x58,
+ 0x30,0x32,0x30,0x42,0x3E,0x40,0x43,0x30,0x30,0x31,0x51,0x3A,
+ 0x20,0x43,0x61,0x6E,0x20,0x74,0x68,0x65,0x20,0x63,0x6C,0x6F,
+ 0x6E,0x65,0x20,0x72,0x65,0x61,0x64,0x20,0x46,0x54,0x32,0x2E,
+ 0x43,0x46,0x47,0x20,0x66,0x72,0x6F,0x6D,0x20,0x72,0x65,0x61,
+ 0x6C,0x20,0x46,0x54,0x32,0x2C,0x20,0x61,0x6E,0x64,0x20,0x76,
+ 0x69,0x63,0x65,0x20,0x76,0x65,0x72,0x73,0x61,0x3F,0x4C,0x3E,
+ 0x40,0x43,0x30,0x30,0x32,0x41,0x3A,0x20,0x59,0x65,0x73,0x2C,
+ 0x20,0x69,0x74,0x20,0x73,0x68,0x6F,0x75,0x6C,0x64,0x20,0x77,
+ 0x6F,0x72,0x6B,0x20,0x6A,0x75,0x73,0x74,0x20,0x66,0x69,0x6E,
+ 0x65,0x2E,0x20,0x50,0x75,0x74,0x20,0x69,0x74,0x20,0x69,0x6E,
+ 0x20,0x74,0x68,0x65,0x20,0x64,0x69,0x72,0x65,0x63,0x74,0x6F,
+ 0x72,0x79,0x20,0x73,0x68,0x6F,0x77,0x6E,0x20,0x61,0x62,0x6F,
+ 0x76,0x65,0x2E,0x06,0x3E,0x40,0x58,0x30,0x32,0x30,0x52,0x3E,
+ 0x40,0x43,0x30,0x30,0x31,0x51,0x3A,0x20,0x53,0x6D,0x70,0x2E,
+ 0x20,0x45,0x64,0x2E,0x3A,0x20,0x57,0x68,0x69,0x6C,0x65,0x20,
+ 0x7A,0x6F,0x6F,0x6D,0x69,0x6E,0x67,0x20,0x69,0x6E,0x2C,0x20,
+ 0x49,0x20,0x73,0x6F,0x6D,0x65,0x74,0x69,0x6D,0x65,0x73,0x20,
+ 0x63,0x61,0x6E,0x27,0x74,0x20,0x6D,0x61,0x72,0x6B,0x20,0x74,
+ 0x68,0x65,0x20,0x6C,0x61,0x73,0x74,0x20,0x73,0x61,0x6D,0x70,
+ 0x6C,0x65,0x20,0x70,0x6F,0x69,0x6E,0x74,0x21,0x47,0x3E,0x40,
+ 0x43,0x30,0x30,0x32,0x41,0x3A,0x20,0x54,0x68,0x69,0x73,0x20,
+ 0x69,0x73,0x20,0x6E,0x6F,0x72,0x6D,0x61,0x6C,0x2E,0x20,0x54,
+ 0x68,0x69,0x73,0x20,0x69,0x73,0x20,0x61,0x20,0x6C,0x69,0x6D,
+ 0x69,0x74,0x61,0x74,0x69,0x6F,0x6E,0x20,0x69,0x6E,0x20,0x74,
+ 0x68,0x65,0x20,0x6E,0x61,0x74,0x75,0x72,0x65,0x20,0x6F,0x66,
+ 0x20,0x73,0x63,0x61,0x6C,0x69,0x6E,0x67,0x2E,0x06,0x3E,0x40,
+ 0x58,0x30,0x32,0x30,0x17,0x3E,0x40,0x43,0x30,0x30,0x31,0x51,
+ 0x3A,0x20,0x49,0x20,0x66,0x6F,0x75,0x6E,0x64,0x20,0x61,0x20,
+ 0x62,0x75,0x67,0x21,0x4B,0x3E,0x40,0x43,0x30,0x30,0x32,0x41,
+ 0x3A,0x20,0x50,0x6C,0x65,0x61,0x73,0x65,0x20,0x73,0x65,0x6E,
+ 0x64,0x20,0x61,0x20,0x6D,0x61,0x69,0x6C,0x20,0x74,0x6F,0x20,
+ 0x6F,0x6C,0x61,0x76,0x2E,0x73,0x6F,0x72,0x65,0x6E,0x73,0x65,
+ 0x6E,0x40,0x6C,0x69,0x76,0x65,0x2E,0x6E,0x6F,0x20,0x61,0x6E,
+ 0x64,0x20,0x74,0x72,0x79,0x20,0x74,0x6F,0x20,0x65,0x78,0x70,
+ 0x6C,0x61,0x69,0x6E,0x20,0x69,0x74,0x2E,0x00,0x03,0x45,0x4E,
+ 0x44,0x4C,0x3B,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,
0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,
0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,
0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,
0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,
0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,
+ 0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x4C,0x3B,0x2A,0x2A,0x2A,0x2A,
0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,
- 0x4C,0x3B,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,
0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,
0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,
0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,
0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,
- 0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,
- 0x2A,0x2A,0x2A,0x2A,0x2A,0x0C,0x40,0x4C,0x4B,0x6E,0x6F,0x77,
- 0x6E,0x20,0x62,0x75,0x67,0x73,0x06,0x3E,0x40,0x58,0x30,0x31,
- 0x30,0x14,0x3E,0x40,0x43,0x30,0x30,0x31,0x53,0x61,0x6D,0x70,
- 0x6C,0x65,0x20,0x65,0x64,0x69,0x74,0x6F,0x72,0x3A,0x06,0x3E,
- 0x40,0x43,0x30,0x30,0x32,0x4E,0x3E,0x40,0x58,0x30,0x31,0x30,
- 0x2D,0x20,0x57,0x68,0x65,0x6E,0x20,0x61,0x20,0x6C,0x6F,0x6F,
- 0x70,0x65,0x64,0x20,0x73,0x61,0x6D,0x70,0x6C,0x65,0x20,0x69,
- 0x73,0x20,0x7A,0x6F,0x6F,0x6D,0x65,0x64,0x20,0x6F,0x75,0x74,
- 0x20,0x69,0x6E,0x20,0x74,0x68,0x65,0x20,0x73,0x61,0x6D,0x70,
- 0x6C,0x65,0x20,0x65,0x64,0x69,0x74,0x6F,0x72,0x2C,0x20,0x79,
- 0x6F,0x75,0x20,0x63,0x6F,0x75,0x6C,0x64,0x20,0x73,0x65,0x65,
- 0x4D,0x3E,0x40,0x58,0x30,0x32,0x31,0x75,0x6E,0x77,0x61,0x6E,
- 0x74,0x65,0x64,0x20,0x73,0x61,0x6D,0x70,0x6C,0x65,0x20,0x64,
- 0x61,0x74,0x61,0x20,0x61,0x74,0x20,0x74,0x68,0x65,0x20,0x6C,
- 0x6F,0x6F,0x70,0x2D,0x65,0x6E,0x64,0x20,0x70,0x6F,0x69,0x6E,
- 0x74,0x2E,0x20,0x54,0x68,0x69,0x73,0x20,0x69,0x73,0x20,0x62,
- 0x65,0x63,0x61,0x75,0x73,0x65,0x20,0x6F,0x66,0x20,0x61,0x20,
- 0x6B,0x6C,0x75,0x64,0x67,0x65,0x4B,0x66,0x6F,0x72,0x20,0x74,
- 0x68,0x65,0x20,0x72,0x65,0x73,0x61,0x6D,0x70,0x6C,0x69,0x6E,
- 0x67,0x20,0x69,0x6E,0x74,0x65,0x72,0x70,0x6F,0x6C,0x61,0x74,
- 0x69,0x6F,0x6E,0x20,0x74,0x6F,0x20,0x77,0x6F,0x72,0x6B,0x20,
- 0x66,0x61,0x73,0x74,0x65,0x72,0x20,0x69,0x6E,0x20,0x74,0x68,
- 0x65,0x20,0x61,0x75,0x64,0x69,0x6F,0x20,0x6D,0x69,0x78,0x65,
- 0x72,0x2C,0x20,0x61,0x6E,0x64,0x20,0x74,0x68,0x65,0x4B,0x6F,
- 0x72,0x69,0x67,0x69,0x6E,0x61,0x6C,0x20,0x46,0x54,0x32,0x20,
- 0x68,0x61,0x73,0x20,0x74,0x68,0x65,0x20,0x73,0x61,0x6D,0x65,
- 0x20,0x70,0x72,0x6F,0x62,0x6C,0x65,0x6D,0x2E,0x20,0x49,0x20,
- 0x68,0x61,0x76,0x65,0x20,0x6D,0x61,0x64,0x65,0x20,0x69,0x74,
- 0x20,0x73,0x6F,0x20,0x74,0x68,0x61,0x74,0x20,0x69,0x66,0x20,
- 0x79,0x6F,0x75,0x20,0x7A,0x6F,0x6F,0x6D,0x20,0x69,0x6E,0x20,
- 0x74,0x6F,0x3B,0x73,0x65,0x65,0x20,0x74,0x68,0x65,0x20,0x69,
- 0x6E,0x64,0x69,0x76,0x69,0x64,0x75,0x61,0x6C,0x20,0x73,0x61,
- 0x6D,0x70,0x6C,0x65,0x20,0x70,0x6F,0x69,0x6E,0x74,0x73,0x2C,
- 0x20,0x69,0x74,0x20,0x77,0x69,0x6C,0x6C,0x20,0x6C,0x6F,0x6F,
- 0x6B,0x20,0x6C,0x69,0x6B,0x65,0x20,0x6E,0x6F,0x72,0x6D,0x61,
- 0x6C,0x2E,0x06,0x3E,0x40,0x58,0x30,0x31,0x30,0x17,0x3E,0x40,
- 0x43,0x30,0x30,0x31,0x4D,0x6F,0x75,0x73,0x65,0x20,0x2F,0x20,
- 0x6B,0x65,0x79,0x62,0x6F,0x61,0x72,0x64,0x3A,0x01,0x3E,0x43,
- 0x3E,0x40,0x43,0x30,0x30,0x32,0x2D,0x20,0x4C,0x69,0x6E,0x75,
- 0x78,0x3A,0x20,0x54,0x68,0x65,0x20,0x6D,0x6F,0x75,0x73,0x65,
- 0x20,0x63,0x75,0x72,0x73,0x6F,0x72,0x20,0x67,0x72,0x61,0x70,
- 0x68,0x69,0x63,0x73,0x20,0x63,0x61,0x6E,0x20,0x62,0x65,0x20,
- 0x67,0x6C,0x69,0x74,0x63,0x68,0x79,0x20,0x61,0x74,0x20,0x74,
- 0x69,0x6D,0x65,0x73,0x2E,0x2E,0x2E,0x06,0x3E,0x40,0x58,0x30,
- 0x31,0x30,0x4B,0x3E,0x40,0x43,0x30,0x30,0x32,0x2D,0x20,0x54,
- 0x68,0x65,0x20,0x22,0x63,0x6C,0x65,0x61,0x72,0x20,0x73,0x61,
- 0x6D,0x70,0x6C,0x65,0x22,0x20,0x73,0x68,0x6F,0x72,0x74,0x63,
- 0x75,0x74,0x20,0x28,0x73,0x68,0x69,0x66,0x74,0x20,0x2B,0x20,
- 0x6E,0x75,0x6D,0x2D,0x70,0x61,0x64,0x20,0x44,0x65,0x6C,0x2F,
- 0x27,0x2C,0x27,0x29,0x20,0x6F,0x6E,0x6C,0x79,0x20,0x77,0x6F,
- 0x72,0x6B,0x73,0x20,0x69,0x66,0x37,0x3E,0x40,0x58,0x30,0x32,
- 0x31,0x6E,0x75,0x6D,0x20,0x6C,0x6F,0x63,0x6B,0x20,0x69,0x73,
- 0x20,0x6F,0x66,0x66,0x2E,0x20,0x54,0x68,0x65,0x72,0x65,0x27,
- 0x73,0x20,0x6E,0x6F,0x20,0x77,0x61,0x79,0x20,0x49,0x20,0x63,
- 0x61,0x6E,0x20,0x66,0x69,0x78,0x20,0x74,0x68,0x69,0x73,0x2E,
- 0x2E,0x2E,0x06,0x3E,0x40,0x58,0x30,0x31,0x30,0x0C,0x3E,0x40,
- 0x43,0x30,0x30,0x31,0x56,0x69,0x64,0x65,0x6F,0x3A,0x06,0x3E,
- 0x40,0x43,0x30,0x30,0x32,0x4A,0x3E,0x40,0x58,0x30,0x31,0x30,
- 0x2D,0x20,0x54,0x68,0x65,0x20,0x73,0x63,0x6F,0x70,0x65,0x73,
- 0x20,0x63,0x61,0x6E,0x20,0x6D,0x69,0x6C,0x64,0x6C,0x79,0x20,
- 0x66,0x6C,0x69,0x63,0x6B,0x65,0x72,0x20,0x64,0x65,0x70,0x65,
- 0x6E,0x64,0x69,0x6E,0x67,0x20,0x6F,0x6E,0x20,0x74,0x68,0x65,
- 0x20,0x77,0x61,0x76,0x65,0x66,0x6F,0x72,0x6D,0x20,0x61,0x6E,
- 0x64,0x20,0x70,0x69,0x74,0x63,0x68,0x2E,0x4D,0x3E,0x40,0x58,
- 0x30,0x32,0x31,0x54,0x68,0x69,0x73,0x20,0x69,0x73,0x20,0x62,
- 0x65,0x63,0x61,0x75,0x73,0x65,0x20,0x74,0x68,0x65,0x69,0x72,
- 0x20,0x66,0x72,0x65,0x71,0x75,0x65,0x6E,0x63,0x79,0x20,0x69,
- 0x73,0x20,0x6E,0x6F,0x74,0x20,0x63,0x6C,0x6F,0x63,0x6B,0x65,
- 0x64,0x20,0x74,0x6F,0x20,0x65,0x78,0x61,0x63,0x74,0x6C,0x79,
- 0x20,0x74,0x68,0x65,0x20,0x73,0x61,0x6D,0x65,0x20,0x72,0x61,
- 0x74,0x65,0x4D,0x3E,0x61,0x74,0x20,0x77,0x68,0x69,0x63,0x68,
- 0x20,0x74,0x68,0x65,0x20,0x73,0x63,0x6F,0x70,0x65,0x73,0x20,
- 0x61,0x72,0x65,0x20,0x72,0x65,0x6E,0x64,0x65,0x72,0x65,0x64,
- 0x2E,0x20,0x49,0x74,0x27,0x73,0x20,0x63,0x6C,0x6F,0x73,0x65,
- 0x2C,0x20,0x77,0x68,0x69,0x63,0x68,0x20,0x63,0x61,0x75,0x73,
- 0x65,0x73,0x20,0x61,0x20,0x66,0x6C,0x69,0x63,0x6B,0x65,0x72,
- 0x20,0x65,0x66,0x66,0x65,0x63,0x74,0x2E,0x01,0x3E,0x52,0x3E,
- 0x40,0x58,0x30,0x31,0x30,0x2D,0x20,0x4E,0x6F,0x74,0x20,0x61,
- 0x20,0x62,0x75,0x67,0x2C,0x20,0x62,0x75,0x74,0x20,0x69,0x66,
- 0x20,0x79,0x6F,0x75,0x72,0x20,0x6D,0x6F,0x6E,0x69,0x74,0x6F,
- 0x72,0x27,0x73,0x20,0x72,0x65,0x66,0x72,0x65,0x73,0x68,0x20,
- 0x72,0x61,0x74,0x65,0x20,0x69,0x73,0x20,0x6E,0x6F,0x74,0x20,
- 0x73,0x65,0x74,0x20,0x74,0x6F,0x20,0x36,0x30,0x48,0x7A,0x20,
- 0x28,0x6F,0x72,0x20,0x35,0x39,0x48,0x7A,0x29,0x4F,0x3E,0x40,
- 0x58,0x30,0x32,0x31,0x79,0x6F,0x75,0x20,0x6D,0x61,0x79,0x20,
- 0x65,0x78,0x70,0x65,0x72,0x69,0x65,0x6E,0x63,0x65,0x20,0x76,
- 0x69,0x73,0x75,0x61,0x6C,0x20,0x73,0x74,0x75,0x74,0x74,0x65,
- 0x72,0x69,0x6E,0x67,0x20,0x62,0x65,0x63,0x61,0x75,0x73,0x65,
- 0x20,0x56,0x53,0x79,0x6E,0x63,0x20,0x77,0x69,0x6C,0x6C,0x20,
- 0x6E,0x6F,0x74,0x20,0x62,0x65,0x20,0x75,0x73,0x65,0x64,0x20,
- 0x74,0x68,0x65,0x6E,0x2E,0x49,0x49,0x20,0x68,0x69,0x67,0x68,
- 0x6C,0x79,0x20,0x72,0x65,0x63,0x6F,0x6D,0x6D,0x65,0x6E,0x64,
- 0x20,0x72,0x75,0x6E,0x6E,0x69,0x6E,0x67,0x20,0x79,0x6F,0x75,
- 0x72,0x20,0x6D,0x6F,0x6E,0x69,0x74,0x6F,0x72,0x20,0x61,0x74,
- 0x20,0x36,0x30,0x48,0x7A,0x20,0x69,0x66,0x20,0x79,0x6F,0x75,
- 0x27,0x72,0x65,0x20,0x61,0x20,0x68,0x61,0x72,0x64,0x63,0x6F,
- 0x72,0x65,0x20,0x75,0x73,0x65,0x72,0x10,0x6F,0x66,0x20,0x74,
- 0x68,0x69,0x73,0x20,0x70,0x72,0x6F,0x67,0x72,0x61,0x6D,0x2E,
- 0x00,0x03,0x45,0x4E,0x44
+ 0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x0C,
+ 0x40,0x4C,0x4B,0x6E,0x6F,0x77,0x6E,0x20,0x62,0x75,0x67,0x73,
+ 0x06,0x3E,0x40,0x58,0x30,0x31,0x30,0x14,0x3E,0x40,0x43,0x30,
+ 0x30,0x31,0x53,0x61,0x6D,0x70,0x6C,0x65,0x20,0x65,0x64,0x69,
+ 0x74,0x6F,0x72,0x3A,0x06,0x3E,0x40,0x43,0x30,0x30,0x32,0x4E,
+ 0x3E,0x40,0x58,0x30,0x31,0x30,0x2D,0x20,0x57,0x68,0x65,0x6E,
+ 0x20,0x61,0x20,0x6C,0x6F,0x6F,0x70,0x65,0x64,0x20,0x73,0x61,
+ 0x6D,0x70,0x6C,0x65,0x20,0x69,0x73,0x20,0x7A,0x6F,0x6F,0x6D,
+ 0x65,0x64,0x20,0x6F,0x75,0x74,0x20,0x69,0x6E,0x20,0x74,0x68,
+ 0x65,0x20,0x73,0x61,0x6D,0x70,0x6C,0x65,0x20,0x65,0x64,0x69,
+ 0x74,0x6F,0x72,0x2C,0x20,0x79,0x6F,0x75,0x20,0x63,0x6F,0x75,
+ 0x6C,0x64,0x20,0x73,0x65,0x65,0x4D,0x3E,0x40,0x58,0x30,0x32,
+ 0x31,0x75,0x6E,0x77,0x61,0x6E,0x74,0x65,0x64,0x20,0x73,0x61,
+ 0x6D,0x70,0x6C,0x65,0x20,0x64,0x61,0x74,0x61,0x20,0x61,0x74,
+ 0x20,0x74,0x68,0x65,0x20,0x6C,0x6F,0x6F,0x70,0x2D,0x65,0x6E,
+ 0x64,0x20,0x70,0x6F,0x69,0x6E,0x74,0x2E,0x20,0x54,0x68,0x69,
+ 0x73,0x20,0x69,0x73,0x20,0x62,0x65,0x63,0x61,0x75,0x73,0x65,
+ 0x20,0x6F,0x66,0x20,0x61,0x20,0x6B,0x6C,0x75,0x64,0x67,0x65,
+ 0x4B,0x66,0x6F,0x72,0x20,0x74,0x68,0x65,0x20,0x72,0x65,0x73,
+ 0x61,0x6D,0x70,0x6C,0x69,0x6E,0x67,0x20,0x69,0x6E,0x74,0x65,
+ 0x72,0x70,0x6F,0x6C,0x61,0x74,0x69,0x6F,0x6E,0x20,0x74,0x6F,
+ 0x20,0x77,0x6F,0x72,0x6B,0x20,0x66,0x61,0x73,0x74,0x65,0x72,
+ 0x20,0x69,0x6E,0x20,0x74,0x68,0x65,0x20,0x61,0x75,0x64,0x69,
+ 0x6F,0x20,0x6D,0x69,0x78,0x65,0x72,0x2C,0x20,0x61,0x6E,0x64,
+ 0x20,0x74,0x68,0x65,0x4B,0x6F,0x72,0x69,0x67,0x69,0x6E,0x61,
+ 0x6C,0x20,0x46,0x54,0x32,0x20,0x68,0x61,0x73,0x20,0x74,0x68,
+ 0x65,0x20,0x73,0x61,0x6D,0x65,0x20,0x70,0x72,0x6F,0x62,0x6C,
+ 0x65,0x6D,0x2E,0x20,0x49,0x20,0x68,0x61,0x76,0x65,0x20,0x6D,
+ 0x61,0x64,0x65,0x20,0x69,0x74,0x20,0x73,0x6F,0x20,0x74,0x68,
+ 0x61,0x74,0x20,0x69,0x66,0x20,0x79,0x6F,0x75,0x20,0x7A,0x6F,
+ 0x6F,0x6D,0x20,0x69,0x6E,0x20,0x74,0x6F,0x3B,0x73,0x65,0x65,
+ 0x20,0x74,0x68,0x65,0x20,0x69,0x6E,0x64,0x69,0x76,0x69,0x64,
+ 0x75,0x61,0x6C,0x20,0x73,0x61,0x6D,0x70,0x6C,0x65,0x20,0x70,
+ 0x6F,0x69,0x6E,0x74,0x73,0x2C,0x20,0x69,0x74,0x20,0x77,0x69,
+ 0x6C,0x6C,0x20,0x6C,0x6F,0x6F,0x6B,0x20,0x6C,0x69,0x6B,0x65,
+ 0x20,0x6E,0x6F,0x72,0x6D,0x61,0x6C,0x2E,0x06,0x3E,0x40,0x58,
+ 0x30,0x31,0x30,0x17,0x3E,0x40,0x43,0x30,0x30,0x31,0x4D,0x6F,
+ 0x75,0x73,0x65,0x20,0x2F,0x20,0x6B,0x65,0x79,0x62,0x6F,0x61,
+ 0x72,0x64,0x3A,0x01,0x3E,0x43,0x3E,0x40,0x43,0x30,0x30,0x32,
+ 0x2D,0x20,0x4C,0x69,0x6E,0x75,0x78,0x3A,0x20,0x54,0x68,0x65,
+ 0x20,0x6D,0x6F,0x75,0x73,0x65,0x20,0x63,0x75,0x72,0x73,0x6F,
+ 0x72,0x20,0x67,0x72,0x61,0x70,0x68,0x69,0x63,0x73,0x20,0x63,
+ 0x61,0x6E,0x20,0x62,0x65,0x20,0x67,0x6C,0x69,0x74,0x63,0x68,
+ 0x79,0x20,0x61,0x74,0x20,0x74,0x69,0x6D,0x65,0x73,0x2E,0x2E,
+ 0x2E,0x06,0x3E,0x40,0x58,0x30,0x31,0x30,0x4B,0x3E,0x40,0x43,
+ 0x30,0x30,0x32,0x2D,0x20,0x54,0x68,0x65,0x20,0x22,0x63,0x6C,
+ 0x65,0x61,0x72,0x20,0x73,0x61,0x6D,0x70,0x6C,0x65,0x22,0x20,
+ 0x73,0x68,0x6F,0x72,0x74,0x63,0x75,0x74,0x20,0x28,0x73,0x68,
+ 0x69,0x66,0x74,0x20,0x2B,0x20,0x6E,0x75,0x6D,0x2D,0x70,0x61,
+ 0x64,0x20,0x44,0x65,0x6C,0x2F,0x27,0x2C,0x27,0x29,0x20,0x6F,
+ 0x6E,0x6C,0x79,0x20,0x77,0x6F,0x72,0x6B,0x73,0x20,0x69,0x66,
+ 0x37,0x3E,0x40,0x58,0x30,0x32,0x31,0x6E,0x75,0x6D,0x20,0x6C,
+ 0x6F,0x63,0x6B,0x20,0x69,0x73,0x20,0x6F,0x66,0x66,0x2E,0x20,
+ 0x54,0x68,0x65,0x72,0x65,0x27,0x73,0x20,0x6E,0x6F,0x20,0x77,
+ 0x61,0x79,0x20,0x49,0x20,0x63,0x61,0x6E,0x20,0x66,0x69,0x78,
+ 0x20,0x74,0x68,0x69,0x73,0x2E,0x2E,0x2E,0x06,0x3E,0x40,0x58,
+ 0x30,0x31,0x30,0x0C,0x3E,0x40,0x43,0x30,0x30,0x31,0x56,0x69,
+ 0x64,0x65,0x6F,0x3A,0x06,0x3E,0x40,0x43,0x30,0x30,0x32,0x50,
+ 0x3E,0x40,0x58,0x30,0x31,0x30,0x2D,0x20,0x46,0x75,0x6C,0x6C,
+ 0x73,0x63,0x72,0x65,0x65,0x6E,0x20,0x6D,0x6F,0x64,0x65,0x20,
+ 0x63,0x61,0x6E,0x20,0x62,0x65,0x20,0x75,0x6E,0x62,0x65,0x61,
+ 0x72,0x61,0x62,0x6C,0x79,0x20,0x73,0x6C,0x6F,0x77,0x20,0x6F,
+ 0x6E,0x20,0x61,0x20,0x52,0x61,0x73,0x70,0x62,0x65,0x72,0x72,
+ 0x79,0x20,0x50,0x69,0x20,0x28,0x65,0x76,0x65,0x6E,0x20,0x61,
+ 0x6E,0x20,0x52,0x50,0x69,0x20,0x34,0x29,0x01,0x3E,0x4A,0x3E,
+ 0x40,0x58,0x30,0x31,0x30,0x2D,0x20,0x54,0x68,0x65,0x20,0x73,
+ 0x63,0x6F,0x70,0x65,0x73,0x20,0x63,0x61,0x6E,0x20,0x6D,0x69,
+ 0x6C,0x64,0x6C,0x79,0x20,0x66,0x6C,0x69,0x63,0x6B,0x65,0x72,
+ 0x20,0x64,0x65,0x70,0x65,0x6E,0x64,0x69,0x6E,0x67,0x20,0x6F,
+ 0x6E,0x20,0x74,0x68,0x65,0x20,0x77,0x61,0x76,0x65,0x66,0x6F,
+ 0x72,0x6D,0x20,0x61,0x6E,0x64,0x20,0x70,0x69,0x74,0x63,0x68,
+ 0x2E,0x4D,0x3E,0x40,0x58,0x30,0x32,0x31,0x54,0x68,0x69,0x73,
+ 0x20,0x69,0x73,0x20,0x62,0x65,0x63,0x61,0x75,0x73,0x65,0x20,
+ 0x74,0x68,0x65,0x69,0x72,0x20,0x66,0x72,0x65,0x71,0x75,0x65,
+ 0x6E,0x63,0x79,0x20,0x69,0x73,0x20,0x6E,0x6F,0x74,0x20,0x63,
+ 0x6C,0x6F,0x63,0x6B,0x65,0x64,0x20,0x74,0x6F,0x20,0x65,0x78,
+ 0x61,0x63,0x74,0x6C,0x79,0x20,0x74,0x68,0x65,0x20,0x73,0x61,
+ 0x6D,0x65,0x20,0x72,0x61,0x74,0x65,0x4D,0x3E,0x61,0x74,0x20,
+ 0x77,0x68,0x69,0x63,0x68,0x20,0x74,0x68,0x65,0x20,0x73,0x63,
+ 0x6F,0x70,0x65,0x73,0x20,0x61,0x72,0x65,0x20,0x72,0x65,0x6E,
+ 0x64,0x65,0x72,0x65,0x64,0x2E,0x20,0x49,0x74,0x27,0x73,0x20,
+ 0x63,0x6C,0x6F,0x73,0x65,0x2C,0x20,0x77,0x68,0x69,0x63,0x68,
+ 0x20,0x63,0x61,0x75,0x73,0x65,0x73,0x20,0x61,0x20,0x66,0x6C,
+ 0x69,0x63,0x6B,0x65,0x72,0x20,0x65,0x66,0x66,0x65,0x63,0x74,
+ 0x2E,0x01,0x3E,0x52,0x3E,0x40,0x58,0x30,0x31,0x30,0x2D,0x20,
+ 0x4E,0x6F,0x74,0x20,0x61,0x20,0x62,0x75,0x67,0x2C,0x20,0x62,
+ 0x75,0x74,0x20,0x69,0x66,0x20,0x79,0x6F,0x75,0x72,0x20,0x6D,
+ 0x6F,0x6E,0x69,0x74,0x6F,0x72,0x27,0x73,0x20,0x72,0x65,0x66,
+ 0x72,0x65,0x73,0x68,0x20,0x72,0x61,0x74,0x65,0x20,0x69,0x73,
+ 0x20,0x6E,0x6F,0x74,0x20,0x73,0x65,0x74,0x20,0x74,0x6F,0x20,
+ 0x36,0x30,0x48,0x7A,0x20,0x28,0x6F,0x72,0x20,0x35,0x39,0x48,
+ 0x7A,0x29,0x4F,0x3E,0x40,0x58,0x30,0x32,0x31,0x79,0x6F,0x75,
+ 0x20,0x6D,0x61,0x79,0x20,0x65,0x78,0x70,0x65,0x72,0x69,0x65,
+ 0x6E,0x63,0x65,0x20,0x76,0x69,0x73,0x75,0x61,0x6C,0x20,0x73,
+ 0x74,0x75,0x74,0x74,0x65,0x72,0x69,0x6E,0x67,0x20,0x62,0x65,
+ 0x63,0x61,0x75,0x73,0x65,0x20,0x56,0x53,0x79,0x6E,0x63,0x20,
+ 0x77,0x69,0x6C,0x6C,0x20,0x6E,0x6F,0x74,0x20,0x62,0x65,0x20,
+ 0x75,0x73,0x65,0x64,0x20,0x74,0x68,0x65,0x6E,0x2E,0x49,0x49,
+ 0x20,0x68,0x69,0x67,0x68,0x6C,0x79,0x20,0x72,0x65,0x63,0x6F,
+ 0x6D,0x6D,0x65,0x6E,0x64,0x20,0x72,0x75,0x6E,0x6E,0x69,0x6E,
+ 0x67,0x20,0x79,0x6F,0x75,0x72,0x20,0x6D,0x6F,0x6E,0x69,0x74,
+ 0x6F,0x72,0x20,0x61,0x74,0x20,0x36,0x30,0x48,0x7A,0x20,0x69,
+ 0x66,0x20,0x79,0x6F,0x75,0x27,0x72,0x65,0x20,0x61,0x20,0x68,
+ 0x61,0x72,0x64,0x63,0x6F,0x72,0x65,0x20,0x75,0x73,0x65,0x72,
+ 0x10,0x6F,0x66,0x20,0x74,0x68,0x69,0x73,0x20,0x70,0x72,0x6F,
+ 0x67,0x72,0x61,0x6D,0x2E,0x00,0x03,0x45,0x4E,0x44
};
#endif