ref: 8950a756e1e732b610ec4e2c6b2f9cb7d1fe960d
parent: 6c56bc97933ef5a50092cff22b0f98033bbf2d30
author: Olav Sørensen <olav.sorensen@live.no>
date: Thu Dec 30 17:19:41 EST 2021
Pushed v1.38 code
--- a/release/macos/protracker.ini
+++ b/release/macos/protracker.ini
@@ -11,6 +11,25 @@
; ENTRY=VALUE (only strings can have spaces!)
;
+[SAMPLE LENGTH LIMIT]
+; Limit samples to 64kB (65534/$FFFE), like intended in ProTracker
+; Syntax: TRUE or FALSE
+; Default value: TRUE
+; Comment: Setting it to FALSE will remove the 64kB (65534/$FFFE) sample
+; length limit and support 128kB samples (131070/$1FFFE).
+; Keep in mind that >64kB samples are not officially supported in most
+; ProTracker trackers and replayers, and will often result in bugs.
+;
+; CAUTION: The 9xx command (Set Sample Offset) doesn't work at all if
+; the sample length is above 65534/$FFFE. This is a known bug
+; in all ProTracker versions. I am not fixing this bug as I
+; want to keep the ProTracker 2.3D replayer quirks.
+;
+; Please do not change this setting unless you're aware of the problems
+; you might face when creating >64k-sample PT MODs!
+;
+64K_LIMIT=TRUE
+
[VIDEO SETTINGS]
; Video scaling factor
; Syntax: 1X, 2X, 3X ... 9X
--- a/release/other/protracker.ini
+++ b/release/other/protracker.ini
@@ -11,6 +11,25 @@
; ENTRY=VALUE (only strings can have spaces!)
;
+[SAMPLE LENGTH LIMIT]
+; Limit samples to 64kB (65534/$FFFE), like intended in ProTracker
+; Syntax: TRUE or FALSE
+; Default value: TRUE
+; Comment: Setting it to FALSE will remove the 64kB (65534/$FFFE) sample
+; length limit and support 128kB samples (131070/$1FFFE).
+; Keep in mind that >64kB samples are not officially supported in most
+; ProTracker trackers and replayers, and will often result in bugs.
+;
+; CAUTION: The 9xx command (Set Sample Offset) doesn't work at all if
+; the sample length is above 65534/$FFFE. This is a known bug
+; in all ProTracker versions. I am not fixing this bug as I
+; want to keep the ProTracker 2.3D replayer quirks.
+;
+; Please do not change this setting unless you're aware of the problems
+; you might face when creating >64k-sample PT MODs!
+;
+64K_LIMIT=TRUE
+
[VIDEO SETTINGS]
; Video scaling factor
; Syntax: 1X, 2X, 3X ... 9X
--- a/release/win32/protracker.ini
+++ b/release/win32/protracker.ini
@@ -11,6 +11,25 @@
; ENTRY=VALUE (only strings can have spaces!)
;
+[SAMPLE LENGTH LIMIT]
+; Limit samples to 64kB (65534/$FFFE), like intended in ProTracker
+; Syntax: TRUE or FALSE
+; Default value: TRUE
+; Comment: Setting it to FALSE will remove the 64kB (65534/$FFFE) sample
+; length limit and support 128kB samples (131070/$1FFFE).
+; Keep in mind that >64kB samples are not officially supported in most
+; ProTracker trackers and replayers, and will often result in bugs.
+;
+; CAUTION: The 9xx command (Set Sample Offset) doesn't work at all if
+; the sample length is above 65534/$FFFE. This is a known bug
+; in all ProTracker versions. I am not fixing this bug as I
+; want to keep the ProTracker 2.3D replayer quirks.
+;
+; Please do not change this setting unless you're aware of the problems
+; you might face when creating >64k-sample PT MODs!
+;
+64K_LIMIT=TRUE
+
[VIDEO SETTINGS]
; Video scaling factor
; Syntax: 1X, 2X, 3X ... 9X
--- a/release/win64/protracker.ini
+++ b/release/win64/protracker.ini
@@ -11,6 +11,25 @@
; ENTRY=VALUE (only strings can have spaces!)
;
+[SAMPLE LENGTH LIMIT]
+; Limit samples to 64kB (65534/$FFFE), like intended in ProTracker
+; Syntax: TRUE or FALSE
+; Default value: TRUE
+; Comment: Setting it to FALSE will remove the 64kB (65534/$FFFE) sample
+; length limit and support 128kB samples (131070/$1FFFE).
+; Keep in mind that >64kB samples are not officially supported in most
+; ProTracker trackers and replayers, and will often result in bugs.
+;
+; CAUTION: The 9xx command (Set Sample Offset) doesn't work at all if
+; the sample length is above 65534/$FFFE. This is a known bug
+; in all ProTracker versions. I am not fixing this bug as I
+; want to keep the ProTracker 2.3D replayer quirks.
+;
+; Please do not change this setting unless you're aware of the problems
+; you might face when creating >64k-sample PT MODs!
+;
+64K_LIMIT=TRUE
+
[VIDEO SETTINGS]
; Video scaling factor
; Syntax: 1X, 2X, 3X ... 9X
--- a/src/gfx/pt2_gfx_editop.c
+++ b/src/gfx/pt2_gfx_editop.c
@@ -1,5 +1,28 @@
#include <stdint.h>
+// Final unpack length: 352
+// Decoded length: 88 (first four bytes of buffer)
+const uint8_t fix128KPosPackedBMP[81] =
+{
+ 0x00,0x00,0x00,0x58,0xCC,0x05,0x55,0x95,0x55,0x6A,0xCC,0x04,0xAA,0xDA,0xAA,0x6A,0xCC,0x04,0xAA,0xDA,
+ 0xAA,0x65,0x56,0xA5,0x5A,0x95,0x5A,0xDA,0xAA,0x65,0xF5,0x97,0xD6,0x5F,0xFE,0xDA,0xAA,0x65,0x57,0xD7,
+ 0x97,0x95,0x6A,0xDA,0xAA,0x65,0xFF,0x97,0x97,0xAF,0x5A,0xDA,0xAA,0x65,0xEA,0xA5,0x5F,0x55,0x7E,0xDA,
+ 0xAA,0x6B,0xEA,0xAB,0xFE,0xBF,0xFA,0xDA,0xAA,0x6A,0xCC,0x04,0xAA,0xDA,0xAA,0xBF,0xCC,0x04,0xFF,0xEF,
+ 0xFF
+};
+
+// Final unpack length: 528
+// Decoded length: 132 (first four bytes of buffer)
+const uint8_t fix128KChordPackedBMP[110] =
+{
+ 0x00,0x00,0x00,0x84,0xCC,0x08,0x55,0x65,0x55,0x55,0x6A,0xCC,0x07,0xAA,0xB6,0xAA,0xAA,0x6A,0xCC,0x07,
+ 0xAA,0xB6,0xAA,0xAA,0x6A,0xA9,0x6A,0xA5,0x55,0x96,0x96,0xAA,0xAA,0xB6,0xAA,0xAA,0x6A,0xA9,0x7A,0xA5,
+ 0xFF,0xD5,0x97,0xAA,0xAA,0xB6,0xAA,0xAA,0x6A,0xA9,0x7A,0xA5,0x5A,0x95,0x57,0xAA,0xAA,0xB6,0xAA,0xAA,
+ 0x6A,0xA9,0x7A,0xA5,0xFE,0x97,0x57,0x5A,0xAA,0xB6,0xAA,0xAA,0x6A,0xA9,0x55,0x65,0x55,0x97,0x97,0x5E,
+ 0xAA,0xB6,0xAA,0xAA,0x6A,0xAA,0xFF,0xFB,0xFF,0xEF,0xAF,0xBE,0xAA,0xB6,0xAA,0xAA,0x6A,0xCC,0x07,0xAA,
+ 0xB6,0xAA,0xAA,0xBF,0xCC,0x07,0xFF,0xFB,0xFF,0xFF
+};
+
// Final unpack length: 336
// Decoded length: 84 (first four bytes of buffer)
const uint8_t editOpModeCharsPackedBMP[88] =
--- a/src/gfx/pt2_gfx_tracker.c
+++ b/src/gfx/pt2_gfx_tracker.c
@@ -1,5 +1,30 @@
#include <stdint.h>
+// Final unpack length: 2108
+// Decoded length: 527 (first four bytes of buffer)
+const uint8_t tracker128KFixPackedBMP[363] =
+{
+ 0x00,0x00,0x02,0x0F,0xCC,0x0C,0xAA,0xFF,0xFF,0xEA,0xCC,0x0B,0xAA,0xAD,0x55,0x55,0xCC,0x0C,0xAA,0xDA,
+ 0xAA,0xAA,0xA9,0x6A,0xA5,0x55,0x96,0x96,0x95,0x59,0x55,0x65,0xA5,0xAA,0xAD,0xAA,0xAA,0xAA,0x97,0xAA,
+ 0x5F,0xFD,0x59,0x75,0xFF,0xED,0x7F,0x5E,0x5E,0xAA,0xDA,0xAA,0xAA,0xA9,0x7A,0xA5,0x56,0x95,0x57,0x5D,
+ 0x5A,0x97,0xA5,0x55,0xEA,0xAD,0xAA,0xAA,0xAA,0x97,0xAA,0x5F,0xF9,0x75,0x75,0xE5,0xE9,0x7A,0x5F,0x5E,
+ 0xAA,0xDA,0xAA,0xAA,0xA9,0x55,0x65,0x55,0x97,0x97,0x95,0x5E,0x97,0xA5,0xE5,0xEA,0xAD,0xAA,0xAA,0xAA,
+ 0xAF,0xFF,0xBF,0xFE,0xFA,0xFA,0xFF,0xEA,0xFA,0xBE,0xBE,0xAA,0xDA,0xCC,0x0D,0xAA,0xAD,0xCC,0x0E,0xAA,
+ 0xDA,0xCC,0x0D,0xAA,0xAE,0xFF,0xFF,0xCC,0x0C,0xAA,0xD5,0x55,0x5A,0xCC,0x0B,0xAA,0xAD,0xAA,0xAA,0xAA,
+ 0x95,0x5A,0x55,0x59,0x55,0xA5,0x55,0xA5,0x5A,0x55,0x5A,0xAA,0xDA,0xAA,0xAA,0xA9,0x7D,0x65,0xFF,0xD7,
+ 0xD6,0x5F,0xFD,0x7D,0x6B,0x5F,0xEA,0xAD,0xAA,0xAA,0xAA,0x95,0x5F,0x55,0x69,0x55,0xF5,0x56,0x95,0x57,
+ 0xA5,0xEA,0xAA,0xDA,0xAA,0xAA,0xA9,0x75,0xE5,0xFF,0x97,0xFE,0x5F,0xF9,0x7D,0x7A,0x5E,0xAA,0xAD,0xAA,
+ 0xAA,0xAA,0x97,0x96,0x55,0x59,0x7A,0xA5,0x55,0x97,0x97,0xA5,0xEA,0xAA,0xDA,0xAA,0xAA,0xAA,0xFA,0xFB,
+ 0xFF,0xEF,0xAA,0xBF,0xFE,0xFA,0xFA,0xBE,0xAA,0xAD,0xCC,0x0E,0xAA,0xDA,0xCC,0x0D,0xAA,0xAD,0xCC,0x0E,
+ 0xAA,0xEF,0xFF,0xFA,0xCC,0x0B,0xAA,0xAD,0x55,0x55,0xCC,0x0C,0xAA,0xDA,0xAA,0xAA,0xA9,0x55,0xA5,0x55,
+ 0x95,0x5A,0x5A,0xA9,0x55,0x65,0xA5,0xAA,0xAD,0xAA,0xAA,0xAA,0x97,0xD6,0x5F,0xFD,0x7D,0x65,0xEA,0x97,
+ 0xFF,0x56,0x5E,0xAA,0xDA,0xAA,0xAA,0xA9,0x55,0xF5,0x56,0x95,0x5F,0x5E,0xA9,0x55,0xA5,0x55,0xEA,0xAD,
+ 0xAA,0xAA,0xAA,0x97,0x5E,0x5F,0xF9,0x7F,0xE5,0xEA,0x97,0xFE,0x5D,0x5E,0xAA,0xDA,0xAA,0xAA,0xA9,0x79,
+ 0x65,0x55,0x97,0xAA,0x55,0x59,0x55,0x65,0xE5,0xEA,0xAD,0xAA,0xAA,0xAA,0xAF,0xAF,0xBF,0xFE,0xFA,0xAB,
+ 0xFF,0xEF,0xFF,0xBE,0xBE,0xAA,0xDA,0xCC,0x0D,0xAA,0xAD,0xCC,0x0E,0xAA,0xDA,0xAA,0xAF,0xCC,0x0B,0xFF,
+ 0xFE,0xFF,0xFF
+};
+
// Final unpack length: 81600
// Decoded length: 20400 (first four bytes of buffer)
const uint8_t trackerFramePackedBMP[8486] =
--- a/src/pt2_audio.c
+++ b/src/pt2_audio.c
@@ -34,6 +34,7 @@
#include "pt2_rcfilter.h"
#include "pt2_ledfilter.h"
#include "pt2_downsample2x.h"
+#include "pt2_hpc.h"
#define STEREO_NORM_FACTOR 0.5 /* cumulative mid/side normalization factor (1/sqrt(2))*(1/sqrt(2)) */
@@ -129,14 +130,13 @@
const double dAudioLatencySecs = audioBufferSize / (double)audioFreq;
- dFrac = modf(dAudioLatencySecs * editor.dPerfFreq, &dInt);
+ dFrac = modf(dAudioLatencySecs * hpcFreq.dFreq, &dInt);
// integer part
- audLatencyPerfValInt = (int32_t)dInt;
+ audLatencyPerfValInt = (uint32_t)dInt;
// fractional part (scaled to 0..2^32-1)
- dFrac *= UINT32_MAX+1.0;
- audLatencyPerfValFrac = (uint32_t)dFrac;
+ audLatencyPerfValFrac = (uint32_t)((dFrac * (UINT32_MAX+1.0)) + 0.5); // rounded
}
void setSyncTickTimeLen(uint32_t timeLen, uint32_t timeLenFrac)
@@ -181,7 +181,7 @@
const moduleSample_t *s = &song->samples[editor.currSample];
paulaSetData(i, ch->n_start + s->loopStart);
- paulaSetLength(i, s->loopLength >> 1);
+ paulaSetLength(i, (uint16_t)(s->loopLength >> 1));
}
}
@@ -335,7 +335,7 @@
paulaVoice_t *v = &paula[ch];
if (src == NULL)
- src = &song->sampleData[RESERVED_SAMPLE_OFFSET]; // 128K reserved sample
+ src = &song->sampleData[config.reservedSampleOffset]; // 128K reserved sample
v->AUD_LC = src;
@@ -362,7 +362,7 @@
paulaVoice_t *v = &paula[ch];
if (v->AUD_LC == NULL)
- v->AUD_LC = &song->sampleData[RESERVED_SAMPLE_OFFSET]; // 128K reserved sample
+ v->AUD_LC = &song->sampleData[config.reservedSampleOffset]; // 128K reserved sample
/* This is not really accurate to what happens on Paula
** during DMA start, but it's good enough.
@@ -801,8 +801,8 @@
// render to sample (PAT2SMP)
int32_t samplesTodo = numSamples;
- if (editor.pat2SmpPos+samplesTodo > MAX_SAMPLE_LEN)
- samplesTodo = MAX_SAMPLE_LEN-editor.pat2SmpPos;
+ if (editor.pat2SmpPos+samplesTodo > config.maxSampleLength)
+ samplesTodo = config.maxSampleLength-editor.pat2SmpPos;
// mix channels (with 2x oversampling, PAT2SMP needs it)
mixChannels(samplesTodo*2);
@@ -821,7 +821,7 @@
}
editor.pat2SmpPos += samplesTodo;
- if (editor.pat2SmpPos >= MAX_SAMPLE_LEN)
+ if (editor.pat2SmpPos >= config.maxSampleLength)
{
editor.smpRenderingDone = true;
updateWindowTitle(MOD_IS_MODIFIED);
@@ -1127,10 +1127,10 @@
// BPM -> Hz -> tick length for performance counter (syncing visuals to audio)
double dTimeInt;
- double dTimeFrac = modf(editor.dPerfFreq / dHz, &dTimeInt);
+ double dTimeFrac = modf(hpcFreq.dFreq / dHz, &dTimeInt);
const int32_t timeInt = (int32_t)dTimeInt;
- dTimeFrac = floor((UINT32_MAX+1.0) * dTimeFrac); // fractional part (scaled to 0..2^32-1)
+ dTimeFrac = floor((dTimeFrac * (UINT32_MAX+1.0)) + 0.5); // fractional part (scaled to 0..2^32-1)
audio.tickLengthTable[bpm-32] = ((uint64_t)timeInt << 32) | (uint32_t)dTimeFrac;
}
--- a/src/pt2_bmp.c
+++ b/src/pt2_bmp.c
@@ -20,6 +20,11 @@
uint32_t *yesNoDialogBMP = NULL, *bigYesNoDialogBMP = NULL, *sampleMonitorBMP = NULL;
uint32_t *samplingBoxBMP = NULL;
+// fix-bitmaps for 128K sample mode
+uint32_t *fix128KTrackerBMP = NULL;
+uint32_t *fix128KPosBMP = NULL;
+uint32_t *fix128KChordBMP = NULL;
+
void createBitmaps(void)
{
uint8_t r8, g8, b8, r8_2, g8_2, b8_2;
@@ -161,6 +166,9 @@
void freeBMPs(void)
{
+ if (fix128KChordBMP != NULL) free(fix128KChordBMP);
+ if (fix128KPosBMP != NULL) free(fix128KPosBMP);
+ if (fix128KTrackerBMP != NULL) free(fix128KTrackerBMP);
if (trackerFrameBMP != NULL) free(trackerFrameBMP);
if (samplerScreenBMP != NULL) free(samplerScreenBMP);
if (samplerVolumeBMP != NULL) free(samplerVolumeBMP);
@@ -189,17 +197,19 @@
const uint8_t *packSrc;
uint8_t *tmpBuffer, *packDst, byteIn;
int16_t count;
- uint32_t *dst, decodedLength, i;
+ uint32_t *dst;
+
+ int32_t decodedLength, i;
// RLE decode
decodedLength = (src[0] << 24) | (src[1] << 16) | (src[2] << 8) | src[3];
// 2-bit to 8-bit conversion
- dst = (uint32_t *)malloc((decodedLength * 4) * sizeof (int32_t));
+ dst = (uint32_t *)malloc(((decodedLength * 4) * sizeof (int32_t)) + 8);
if (dst == NULL)
return NULL;
- tmpBuffer = (uint8_t *)malloc(decodedLength + 512); // some margin is needed, the packer is buggy
+ tmpBuffer = (uint8_t *)malloc(decodedLength + 128); // some margin is needed, the packer is buggy
if (tmpBuffer == NULL)
{
free(dst);
@@ -206,10 +216,10 @@
return NULL;
}
- packSrc = src + 4;
+ packSrc = src + 4; // skip "length" field
packDst = tmpBuffer;
- i = packedLen - 4;
+ i = packedLen - 4; // subtract "length" field
while (i > 0)
{
byteIn = *packSrc++;
@@ -256,6 +266,9 @@
bool unpackBMPs(void)
{
+ fix128KChordBMP = unpackBMP(fix128KChordPackedBMP, sizeof (fix128KChordPackedBMP));
+ fix128KPosBMP = unpackBMP(fix128KPosPackedBMP, sizeof (fix128KPosPackedBMP));
+ fix128KTrackerBMP = unpackBMP(tracker128KFixPackedBMP, sizeof (tracker128KFixPackedBMP));
trackerFrameBMP = unpackBMP(trackerFramePackedBMP, sizeof (trackerFramePackedBMP));
samplerScreenBMP = unpackBMP(samplerScreenPackedBMP, sizeof (samplerScreenPackedBMP));
samplerVolumeBMP = unpackBMP(samplerVolumePackedBMP, sizeof (samplerVolumePackedBMP));
@@ -278,13 +291,14 @@
sampleMonitorBMP = unpackBMP(sampleMonitorPackedBMP, sizeof (sampleMonitorPackedBMP));
samplingBoxBMP = unpackBMP(samplingBoxPackedBMP, sizeof (samplingBoxPackedBMP));
- if (trackerFrameBMP == NULL || samplerScreenBMP == NULL || samplerVolumeBMP == NULL ||
- clearDialogBMP == NULL || diskOpScreenBMP == NULL || mod2wavBMP == NULL ||
- posEdBMP == NULL || spectrumVisualsBMP == NULL || yesNoDialogBMP == NULL ||
- editOpScreen1BMP == NULL || editOpScreen2BMP == NULL || editOpScreen3BMP == NULL ||
- editOpScreen4BMP == NULL || aboutScreenBMP == NULL || muteButtonsBMP == NULL ||
- editOpModeCharsBMP == NULL || samplerFiltersBMP == NULL || yesNoDialogBMP == NULL ||
- bigYesNoDialogBMP == NULL || sampleMonitorBMP == NULL || samplingBoxBMP == NULL)
+ if (fix128KTrackerBMP == NULL || fix128KPosBMP == NULL || fix128KChordBMP == NULL ||
+ trackerFrameBMP == NULL || samplerScreenBMP == NULL || samplerVolumeBMP == NULL ||
+ clearDialogBMP == NULL || diskOpScreenBMP == NULL || mod2wavBMP == NULL ||
+ posEdBMP == NULL || spectrumVisualsBMP == NULL || yesNoDialogBMP == NULL ||
+ editOpScreen1BMP == NULL || editOpScreen2BMP == NULL || editOpScreen3BMP == NULL ||
+ editOpScreen4BMP == NULL || aboutScreenBMP == NULL || muteButtonsBMP == NULL ||
+ editOpModeCharsBMP == NULL || samplerFiltersBMP == NULL || yesNoDialogBMP == NULL ||
+ bigYesNoDialogBMP == NULL || sampleMonitorBMP == NULL || samplingBoxBMP == NULL)
{
showErrorMsgBox("Out of memory!");
return false; // BMPs are free'd in cleanUp()
--- a/src/pt2_bmp.h
+++ b/src/pt2_bmp.h
@@ -21,6 +21,8 @@
extern const uint8_t aboutScreenPackedBMP[1408];
extern const uint8_t clearDialogPackedBMP[525];
extern const uint8_t diskOpScreenPackedBMP[1898];
+extern const uint8_t fix128KChordPackedBMP[110];
+extern const uint8_t fix128KPosPackedBMP[81];
extern const uint8_t editOpModeCharsPackedBMP[88];
extern const uint8_t editOpScreen1PackedBMP[1481];
extern const uint8_t editOpScreen2PackedBMP[1502];
@@ -34,6 +36,7 @@
extern const uint8_t samplerFiltersPackedBMP[933];
extern const uint8_t samplerScreenPackedBMP[3076];
extern const uint8_t spectrumVisualsPackedBMP[2217];
+extern const uint8_t tracker128KFixPackedBMP[363];
extern const uint8_t trackerFramePackedBMP[8486];
extern const uint8_t yesNoDialogPackedBMP[476];
extern const uint8_t bigYesNoDialogPackedBMP[472];
@@ -67,6 +70,11 @@
extern uint32_t *pat2SmpDialogBMP;
extern uint32_t *sampleMonitorBMP;
extern uint32_t *samplingBoxBMP;
+
+// fix-bitmaps for 128K sample mode
+extern uint32_t *fix128KTrackerBMP;
+extern uint32_t *fix128KPosBMP;
+extern uint32_t *fix128KChordBMP;
bool unpackBMPs(void);
void createBitmaps(void);
--- a/src/pt2_chordmaker.c
+++ b/src/pt2_chordmaker.c
@@ -7,6 +7,7 @@
#include <stdint.h>
#include <stdbool.h>
#include "pt2_header.h"
+#include "pt2_config.h"
#include "pt2_mouse.h"
#include "pt2_textout.h"
#include "pt2_visuals.h"
@@ -111,10 +112,10 @@
sortNotes();
removeDuplicateNotes();
- ui.updateNote1Text = true;
- ui.updateNote2Text = true;
- ui.updateNote3Text = true;
- ui.updateNote4Text = true;
+ ui.updateChordNote1Text = true;
+ ui.updateChordNote2Text = true;
+ ui.updateChordNote3Text = true;
+ ui.updateChordNote4Text = true;
// setup some variables
smpLoopStart = s->loopStart;
@@ -151,7 +152,7 @@
editor.currSample = (int8_t)i;
}
- double *dMixData = (double *)calloc(MAX_SAMPLE_LEN*2, sizeof (double));
+ double *dMixData = (double *)calloc(config.maxSampleLength*2, sizeof (double));
if (dMixData == NULL)
{
statusOutOfMemory();
@@ -158,7 +159,7 @@
return;
}
- s->length = smpLoopFlag ? MAX_SAMPLE_LEN : editor.chordLength; // if sample loops, set max length
+ s->length = smpLoopFlag ? config.maxSampleLength : editor.chordLength; // if sample loops, set max length
s->loopLength = 2;
s->loopStart = 0;
s->text[21] = '!'; // chord sample indicator
@@ -189,7 +190,7 @@
if (!v->active || v->dDelta == 0.0)
continue;
- for (int32_t j = 0; j < MAX_SAMPLE_LEN*2; j++)
+ for (int32_t j = 0; j < config.maxSampleLength*2; j++)
{
double dSmp = smpData[v->pos] * (1.0 / 128.0);
@@ -247,8 +248,8 @@
free(dMixData);
// clear unused sample data (if sample is not full already)
- if (s->length < MAX_SAMPLE_LEN)
- memset(&song->sampleData[s->offset + s->length], 0, MAX_SAMPLE_LEN - s->length);
+ if (s->length < config.maxSampleLength)
+ memset(&song->sampleData[s->offset + s->length], 0, config.maxSampleLength - s->length);
// we're done
@@ -294,14 +295,14 @@
else
{
len = (s->length * periodTable[(37 * s->fineTune) + note]) / periodTable[24];
- if (len > MAX_SAMPLE_LEN)
- len = MAX_SAMPLE_LEN;
+ if (len > config.maxSampleLength)
+ len = config.maxSampleLength;
- editor.chordLength = len & 0xFFFE;
+ editor.chordLength = len & config.maxSampleLength;
}
if (ui.editOpScreenShown && ui.editOpScreen == 3)
- ui.updateLengthText = true;
+ ui.updateChordLengthText = true;
}
void resetChord(void)
@@ -313,10 +314,10 @@
editor.chordLengthMin = false;
- ui.updateNote1Text = true;
- ui.updateNote2Text = true;
- ui.updateNote3Text = true;
- ui.updateNote4Text = true;
+ ui.updateChordNote1Text = true;
+ ui.updateChordNote2Text = true;
+ ui.updateChordNote3Text = true;
+ ui.updateChordNote4Text = true;
recalcChordLength();
}
@@ -328,10 +329,10 @@
editor.note3 = editor.oldNote3;
editor.note4 = editor.oldNote4;
- ui.updateNote1Text = true;
- ui.updateNote2Text = true;
- ui.updateNote3Text = true;
- ui.updateNote4Text = true;
+ ui.updateChordNote1Text = true;
+ ui.updateChordNote2Text = true;
+ ui.updateChordNote3Text = true;
+ ui.updateChordNote4Text = true;
recalcChordLength();
}
@@ -363,9 +364,9 @@
editor.note4 = 36;
- ui.updateNote2Text = true;
- ui.updateNote3Text = true;
- ui.updateNote4Text = true;
+ ui.updateChordNote2Text = true;
+ ui.updateChordNote3Text = true;
+ ui.updateChordNote4Text = true;
recalcChordLength();
}
@@ -388,9 +389,9 @@
editor.note4 = 36;
- ui.updateNote2Text = true;
- ui.updateNote3Text = true;
- ui.updateNote4Text = true;
+ ui.updateChordNote2Text = true;
+ ui.updateChordNote3Text = true;
+ ui.updateChordNote4Text = true;
recalcChordLength();
}
@@ -413,9 +414,9 @@
editor.note4 = 36;
- ui.updateNote2Text = true;
- ui.updateNote3Text = true;
- ui.updateNote4Text = true;
+ ui.updateChordNote2Text = true;
+ ui.updateChordNote3Text = true;
+ ui.updateChordNote4Text = true;
recalcChordLength();
}
@@ -438,9 +439,9 @@
if (editor.note3 >= 36) editor.note3 -= 12;
if (editor.note4 >= 36) editor.note4 -= 12;
- ui.updateNote2Text = true;
- ui.updateNote3Text = true;
- ui.updateNote4Text = true;
+ ui.updateChordNote2Text = true;
+ ui.updateChordNote3Text = true;
+ ui.updateChordNote4Text = true;
recalcChordLength();
}
@@ -463,9 +464,9 @@
if (editor.note3 >= 36) editor.note3 -= 12;
if (editor.note4 >= 36) editor.note4 -= 12;
- ui.updateNote2Text = true;
- ui.updateNote3Text = true;
- ui.updateNote4Text = true;
+ ui.updateChordNote2Text = true;
+ ui.updateChordNote3Text = true;
+ ui.updateChordNote4Text = true;
recalcChordLength();
}
@@ -488,9 +489,9 @@
if (editor.note3 >= 36) editor.note3 -= 12;
if (editor.note4 >= 36) editor.note4 -= 12;
- ui.updateNote2Text = true;
- ui.updateNote3Text = true;
- ui.updateNote4Text = true;
+ ui.updateChordNote2Text = true;
+ ui.updateChordNote3Text = true;
+ ui.updateChordNote4Text = true;
recalcChordLength();
}
@@ -513,9 +514,9 @@
if (editor.note3 >= 36) editor.note3 -= 12;
if (editor.note4 >= 36) editor.note4 -= 12;
- ui.updateNote2Text = true;
- ui.updateNote3Text = true;
- ui.updateNote4Text = true;
+ ui.updateChordNote2Text = true;
+ ui.updateChordNote3Text = true;
+ ui.updateChordNote4Text = true;
recalcChordLength();
}
@@ -533,7 +534,7 @@
pointerSetMode(POINTER_MODE_MSG1, NO_CARRY);
}
- ui.updateNote1Text = true;
+ ui.updateChordNote1Text = true;
}
void selectChordNote2(void)
@@ -549,7 +550,7 @@
pointerSetMode(POINTER_MODE_MSG1, NO_CARRY);
}
- ui.updateNote2Text = true;
+ ui.updateChordNote2Text = true;
}
void selectChordNote3(void)
@@ -565,7 +566,7 @@
pointerSetMode(POINTER_MODE_MSG1, NO_CARRY);
}
- ui.updateNote3Text = true;
+ ui.updateChordNote3Text = true;
}
void selectChordNote4(void)
@@ -581,7 +582,7 @@
pointerSetMode(POINTER_MODE_MSG1, NO_CARRY);
}
- ui.updateNote4Text = true;
+ ui.updateChordNote4Text = true;
}
void makeChord(void)
--- a/src/pt2_config.c
+++ b/src/pt2_config.c
@@ -68,6 +68,9 @@
config.integerScaling = true;
config.audioInputFrequency = 44100;
+ config.maxSampleLength = 65534;
+ config.reservedSampleOffset = (MOD_SAMPLES+1) * config.maxSampleLength;
+
#ifndef _WIN32
getcwd(oldCwd, PATH_MAX);
#endif
@@ -192,6 +195,21 @@
{
configLine = strtok(NULL, "\n");
continue;
+ }
+
+ // 64K_LIMIT
+ else if (!_strnicmp(configLine, "64K_LIMIT=", 10))
+ {
+ if (!_strnicmp(&configLine[10], "TRUE", 4))
+ {
+ config.maxSampleLength = 65534;
+ config.reservedSampleOffset = (MOD_SAMPLES+1) * config.maxSampleLength;
+ }
+ else if (!_strnicmp(&configLine[10], "FALSE", 5))
+ {
+ config.maxSampleLength = 131070;
+ config.reservedSampleOffset = (MOD_SAMPLES+1) * config.maxSampleLength;
+ }
}
// NO_DWNSMP_ON_SMP_LOAD (no dialog for 2x downsample after >22kHz sample load)
--- a/src/pt2_config.h
+++ b/src/pt2_config.h
@@ -19,7 +19,8 @@
int8_t stereoSeparation, videoScaleFactor, accidental;
uint8_t pixelFilter, filterModel;
uint16_t quantizeValue;
- uint32_t soundFrequency, soundBufferSize, audioInputFrequency;
+ int32_t maxSampleLength;
+ uint32_t soundFrequency, soundBufferSize, audioInputFrequency, reservedSampleOffset;
} config_t;
extern config_t config; // pt2_config.c
--- a/src/pt2_edit.c
+++ b/src/pt2_edit.c
@@ -240,7 +240,10 @@
if (updateValue)
{
- editor.samplePos = ui.tmpDisp16;
+ editor.samplePos = ui.tmpDisp32;
+ if (editor.samplePos > config.maxSampleLength)
+ editor.samplePos = config.maxSampleLength;
+
if (editor.samplePos > song->samples[editor.currSample].length)
editor.samplePos = song->samples[editor.currSample].length;
@@ -499,7 +502,9 @@
if (updateValue)
{
- tmp32 = ui.tmpDisp16 & 0xFFFE; // even'ify
+ tmp32 = ui.tmpDisp32 & ~1; // even'ify
+ if (tmp32 > config.maxSampleLength)
+ tmp32 = config.maxSampleLength;
if (s->loopStart+s->loopLength > 2)
{
@@ -507,12 +512,12 @@
tmp32 = s->loopStart+s->loopLength;
}
- tmp32 &= 0xFFFE;
+ tmp32 &= ~1;
if (s->length != tmp32)
{
turnOffVoices();
- s->length = (uint16_t)tmp32;
+ s->length = tmp32;
ui.updateCurrSampleLength = true;
ui.updateSongSize = true;
@@ -534,7 +539,9 @@
if (updateValue)
{
- tmp32 = ui.tmpDisp16 & 0xFFFE; // even'ify
+ tmp32 = ui.tmpDisp32 & ~1; // even'ify
+ if (tmp32 > config.maxSampleLength)
+ tmp32 = config.maxSampleLength;
if (s->length >= s->loopLength)
{
@@ -546,18 +553,18 @@
tmp32 = 0;
}
- tmp32 &= 0xFFFE;
+ tmp32 &= ~1;
if (s->loopStart != tmp32)
{
turnOffVoices();
- s->loopStart = (uint16_t)tmp32;
+ s->loopStart = tmp32;
mixerUpdateLoops();
ui.updateCurrSampleRepeat = true;
if (ui.editOpScreenShown && ui.editOpScreen == 3)
- ui.updateLengthText = true;
+ ui.updateChordLengthText = true;
if (ui.samplerScreenShown)
setLoopSprites();
@@ -574,7 +581,9 @@
if (updateValue)
{
- tmp32 = ui.tmpDisp16 & 0xFFFE; // even'ify
+ tmp32 = ui.tmpDisp32 & ~1; // even'ify
+ if (tmp32 > config.maxSampleLength)
+ tmp32 = config.maxSampleLength;
if (s->length >= s->loopStart)
{
@@ -586,7 +595,7 @@
tmp32 = 2;
}
- tmp32 &= 0xFFFE;
+ tmp32 &= ~1;
if (tmp32 < 2)
tmp32 = 2;
@@ -594,12 +603,12 @@
if (s->loopLength != tmp32)
{
turnOffVoices();
- s->loopLength = (uint16_t)tmp32;
+ s->loopLength = tmp32;
mixerUpdateLoops();
ui.updateCurrSampleReplen = true;
if (ui.editOpScreenShown && ui.editOpScreen == 3)
- ui.updateLengthText = true;
+ ui.updateChordLengthText = true;
if (ui.samplerScreenShown)
setLoopSprites();
@@ -923,7 +932,7 @@
const int8_t *n_start = &song->sampleData[s->offset];
const int8_t vol = 64;
- const uint16_t n_length = s->length >> 1;
+ const uint16_t n_length = (uint16_t)(s->length >> 1);
const uint16_t period = periodTable[((s->fineTune & 0xF) * 37) + noteVal];
paulaSetVolume(ch, vol);
@@ -980,9 +989,9 @@
chn->n_volume = s->volume;
chn->n_period = tempPeriod;
chn->n_start = &song->sampleData[s->offset];
- chn->n_length = (s->loopStart > 0) ? (s->loopStart + s->loopLength) >> 1 : s->length >> 1;
+ chn->n_length = (uint16_t)((s->loopStart > 0) ? (s->loopStart + s->loopLength) >> 1 : s->length >> 1);
chn->n_loopstart = &song->sampleData[s->offset + s->loopStart];
- chn->n_replen = s->loopLength >> 1;
+ chn->n_replen = (uint16_t)(s->loopLength >> 1);
if (chn->n_length == 0)
chn->n_length = 1;
@@ -1145,7 +1154,7 @@
smpTo->loopLengthDisp = &smpTo->loopLength;
// copy sample data
- memcpy(&song->sampleData[smpTo->offset], &song->sampleData[smpFrom->offset], MAX_SAMPLE_LEN);
+ memcpy(&song->sampleData[smpTo->offset], &song->sampleData[smpFrom->offset], config.maxSampleLength);
updateCurrSample();
ui.updateSongSize = true;
@@ -1187,7 +1196,8 @@
void exchSampleTrack(void)
{
int8_t smp;
- uint32_t i, tmpOffset;
+ int32_t i;
+ uint32_t tmpOffset;
moduleSample_t *smpFrom, *smpTo, smpTmp;
note_t *noteSrc;
@@ -1228,7 +1238,7 @@
smpTo->loopLengthDisp = &smpTo->loopLength;
// swap sample data
- for (i = 0; i < MAX_SAMPLE_LEN; i++)
+ for (i = 0; i < config.maxSampleLength; i++)
{
smp = song->sampleData[smpFrom->offset+i];
song->sampleData[smpFrom->offset+i] = song->sampleData[smpTo->offset+i];
--- a/src/pt2_header.h
+++ b/src/pt2_header.h
@@ -14,7 +14,7 @@
#include "pt2_unicode.h"
#include "pt2_palette.h"
-#define PROG_VER_STR "1.37"
+#define PROG_VER_STR "1.38"
#ifdef _WIN32
#define DIR_DELIMITER '\\'
@@ -38,7 +38,7 @@
/* Scopes are clocked at 64Hz instead of 60Hz to prevent the small +/- Hz
** interference from monitors not being exactly 60Hz (and unstable non-vsync mode).
-** Sadly, the scopes might midly flicker from this in some cases.
+** Sadly, the scopes might mildly flicker from this in some cases.
*/
#define SCOPE_HZ 64
@@ -49,11 +49,6 @@
#define MOD_SAMPLES 31
#define MOD_ORDERS 128
#define MAX_PATTERNS 100
-
-#define MAX_SAMPLE_LEN 65534
-
-// for NULL pointers
-#define RESERVED_SAMPLE_OFFSET ((31+1) * MAX_SAMPLE_LEN)
#define AMIGA_VOICES 4
#define SCOPE_WIDTH 40
--- a/src/pt2_helpers.c
+++ b/src/pt2_helpers.c
@@ -21,44 +21,6 @@
#include "pt2_structs.h"
#include "pt2_config.h"
-// used for Windows usleep() implementation
-#ifdef _WIN32
-static NTSTATUS (__stdcall *NtDelayExecution)(BOOL Alertable, PLARGE_INTEGER DelayInterval);
-#endif
-
-// usleep() implementation for Windows
-#ifdef _WIN32
-void usleep(uint32_t usec)
-{
- LARGE_INTEGER lpDueTime;
-
- if (NtDelayExecution == NULL)
- {
- // NtDelayExecution() is not available (shouldn't happen), use regular sleep()
- Sleep(usec / 1000);
- }
- else
- {
- // this prevents a 64-bit MUL (will not overflow with typical values anyway)
- lpDueTime.HighPart = 0xFFFFFFFF;
- lpDueTime.LowPart = (DWORD)(-10 * (int32_t)usec);
-
- NtDelayExecution(false, &lpDueTime);
- }
-}
-
-void setupWin32Usleep(void)
-{
- NtDelayExecution = (NTSTATUS (__stdcall *)(BOOL, PLARGE_INTEGER))GetProcAddress(GetModuleHandle("ntdll.dll"), "NtDelayExecution");
- timeBeginPeriod(0); // enter highest timer resolution
-}
-
-void freeWin32Usleep(void)
-{
- timeEndPeriod(0); // exit highest timer resolution
-}
-#endif
-
void showErrorMsgBox(const char *fmt, ...)
{
char strBuf[1024];
--- a/src/pt2_helpers.h
+++ b/src/pt2_helpers.h
@@ -53,13 +53,6 @@
void showErrorMsgBox(const char *fmt, ...);
-#ifdef _WIN32
-// Windows usleep() implementation
-void usleep(uint32_t usec);
-void setupWin32Usleep(void);
-void freeWin32Usleep(void);
-#endif
-
void sanitizeFilenameChar(char *chr);
bool sampleNameIsEmpty(char *name);
bool moduleNameIsEmpty(char *name);
--- /dev/null
+++ b/src/pt2_hpc.c
@@ -1,0 +1,121 @@
+/*
+** High Performance Counter delay routines
+*/
+
+#ifdef _WIN32
+#define WIN32_MEAN_AND_LEAN
+#include <windows.h>
+#else
+#include <unistd.h>
+#endif
+#include <SDL2/SDL.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include "pt2_hpc.h"
+
+hpcFreq_t hpcFreq;
+
+#ifdef _WIN32 // Windows usleep() implementation
+
+static NTSTATUS (__stdcall *NtDelayExecution)(BOOL Alertable, PLARGE_INTEGER DelayInterval);
+static NTSTATUS (__stdcall *NtQueryTimerResolution)(PULONG MinimumResolution, PULONG MaximumResolution, PULONG ActualResolution);
+static NTSTATUS (__stdcall *NtSetTimerResolution)(ULONG DesiredResolution, BOOLEAN SetResolution, PULONG CurrentResolution);
+
+static void (*usleep)(int32_t usec);
+
+static void usleepGood(int32_t usec)
+{
+ LARGE_INTEGER delayInterval;
+
+ // NtDelayExecution() delays in 100ns-units, and negative value = delay from current time
+ usec *= -10;
+
+ delayInterval.HighPart = 0xFFFFFFFF;
+ delayInterval.LowPart = usec;
+ NtDelayExecution(false, &delayInterval);
+}
+
+static void usleepWeak(int32_t usec) // fallback if no NtDelayExecution()
+{
+ Sleep((usec + 500) / 1000);
+}
+
+static void windowsSetupUsleep(void)
+{
+ NtDelayExecution = (NTSTATUS (__stdcall *)(BOOL, PLARGE_INTEGER))GetProcAddress(GetModuleHandle("ntdll.dll"), "NtDelayExecution");
+ NtQueryTimerResolution = (NTSTATUS (__stdcall *)(PULONG, PULONG, PULONG))GetProcAddress(GetModuleHandle("ntdll.dll"), "NtQueryTimerResolution");
+ NtSetTimerResolution = (NTSTATUS (__stdcall *)(ULONG, BOOLEAN, PULONG))GetProcAddress(GetModuleHandle("ntdll.dll"), "NtSetTimerResolution");
+
+ usleep = (NtDelayExecution != NULL) ? usleepGood : usleepWeak;
+}
+#endif
+
+void hpc_Init(void)
+{
+#ifdef _WIN32
+ windowsSetupUsleep();
+#endif
+ hpcFreq.freq64 = SDL_GetPerformanceFrequency();
+ hpcFreq.dFreq = (double)hpcFreq.freq64;
+ hpcFreq.dFreqMulMicro = (1000.0 * 1000.0) / hpcFreq.dFreq;
+}
+
+void hpc_SetDurationInHz(hpc_t *hpc, const double dHz)
+{
+ const double dDuration = hpcFreq.dFreq / dHz;
+
+ // break down duration into integer and frac parts
+ double dDurationInt;
+ double dDurationFrac = modf(dDuration, &dDurationInt);
+
+ // set 64:32 values
+ hpc->duration64Int = (uint64_t)floor(dDurationInt);
+ hpc->duration64Frac = (uint64_t)((dDurationFrac * (UINT32_MAX+1.0)) + 0.5); // rounded
+}
+
+void hpc_ResetEndTime(hpc_t *hpc)
+{
+ hpc->endTime64Int = SDL_GetPerformanceCounter() + hpc->duration64Int;
+ hpc->endTime64Frac = hpc->duration64Frac;
+}
+
+void hpc_Wait(hpc_t *hpc)
+{
+#ifdef _WIN32 // set resolution to 0.5ms (safest minium) - this is confirmed to improve NtDelayExecution() and Sleep()
+ ULONG originalTimerResolution, minRes, maxRes, curRes;
+
+ if (NtQueryTimerResolution != NULL && NtSetTimerResolution != NULL)
+ {
+ if (!NtQueryTimerResolution(&minRes, &maxRes, &originalTimerResolution))
+ {
+ if (originalTimerResolution != 5000 && maxRes <= 5000)
+ NtSetTimerResolution(5000, TRUE, &curRes); // set to 0.5ms (safest minimum)
+ }
+ }
+#endif
+
+ const uint64_t currTime64 = SDL_GetPerformanceCounter();
+ if (currTime64 < hpc->endTime64Int)
+ {
+ uint64_t timeLeft64 = hpc->endTime64Int - currTime64;
+ if (timeLeft64 > INT32_MAX)
+ timeLeft64 = INT32_MAX;
+
+ const int32_t timeLeft32 = (int32_t)timeLeft64;
+
+ int32_t microSecsLeft = (int32_t)((timeLeft32 * hpcFreq.dFreqMulMicro) + 0.5); // rounded
+ if (microSecsLeft > 0)
+ usleep(microSecsLeft);
+ }
+
+ // set next end time
+
+ hpc->endTime64Int += hpc->duration64Int;
+
+ hpc->endTime64Frac += hpc->duration64Frac;
+ if (hpc->endTime64Frac > UINT32_MAX)
+ {
+ hpc->endTime64Frac &= UINT32_MAX;
+ hpc->endTime64Int++;
+ }
+}
--- /dev/null
+++ b/src/pt2_hpc.h
@@ -1,0 +1,23 @@
+#pragma once
+
+#include <stdint.h>
+#include <stdbool.h>
+
+typedef struct
+{
+ uint64_t freq64;
+ double dFreq, dFreqMulMicro;
+} hpcFreq_t;
+
+typedef struct
+{
+ uint64_t duration64Int, duration64Frac;
+ uint64_t endTime64Int, endTime64Frac;
+} hpc_t;
+
+extern hpcFreq_t hpcFreq;
+
+void hpc_Init(void);
+void hpc_SetDurationInHz(hpc_t *hpc, double dHz);
+void hpc_ResetEndTime(hpc_t *hpc);
+void hpc_Wait(hpc_t *hpc);
--- a/src/pt2_keyboard.c
+++ b/src/pt2_keyboard.c
@@ -3586,22 +3586,22 @@
if (ui.changingChordNote == 1)
{
editor.note1 = rawKey;
- ui.updateNote1Text = true;
+ ui.updateChordNote1Text = true;
}
else if (ui.changingChordNote == 2)
{
editor.note2 = rawKey;
- ui.updateNote2Text = true;
+ ui.updateChordNote2Text = true;
}
else if (ui.changingChordNote == 3)
{
editor.note3 = rawKey;
- ui.updateNote3Text = true;
+ ui.updateChordNote3Text = true;
}
else if (ui.changingChordNote == 4)
{
editor.note4 = rawKey;
- ui.updateNote4Text = true;
+ ui.updateChordNote4Text = true;
}
ui.changingChordNote = false;
@@ -4094,15 +4094,28 @@
else if (textChar <= 'f')
textChar -= 'a'-10;
- if (ui.numBits == 16)
+ if (ui.numBits == 17)
{
- *ui.numPtr16 &= ~(0xF000 >> (ui.dstPos << 2));
- *ui.numPtr16 |= (textChar << (12 - (ui.dstPos << 2)));
+ *ui.numPtr32 &= ~(0xF0000 >> (ui.dstPos << 2));
+ *ui.numPtr32 |= textChar << (16 - (ui.dstPos << 2));
}
+ else if (ui.numBits == 16)
+ {
+ if (ui.force32BitNumPtr)
+ {
+ *ui.numPtr32 &= ~(0xF000 >> (ui.dstPos << 2));
+ *ui.numPtr32 |= textChar << (12 - (ui.dstPos << 2));
+ }
+ else
+ {
+ *ui.numPtr16 &= ~(0xF000 >> (ui.dstPos << 2));
+ *ui.numPtr16 |= textChar << (12 - (ui.dstPos << 2));
+ }
+ }
else if (ui.numBits == 8)
{
*ui.numPtr8 &= ~(0xF0 >> (ui.dstPos << 2));
- *ui.numPtr8 |= (textChar << (4 - (ui.dstPos << 2)));
+ *ui.numPtr8 |= textChar << (4 - (ui.dstPos << 2));
}
textMarkerMoveRight();
--- a/src/pt2_main.c
+++ b/src/pt2_main.c
@@ -36,6 +36,7 @@
#include "pt2_bmp.h"
#include "pt2_sync.h"
#include "pt2_sampling.h"
+#include "pt2_hpc.h"
#define CRASH_TEXT "Oh no!\nThe ProTracker 2 clone has crashed...\n\nA backup .mod was hopefully " \
"saved to the current module directory.\n\nPlease report this bug if you can.\n" \
@@ -181,7 +182,6 @@
return 0;
}
- setupWin32Usleep();
disableWasapi(); // disable problematic WASAPI SDL2 audio driver on Windows (causes clicks/pops sometimes...)
// 13.03.2020: This is still needed with SDL 2.0.12...
#endif
@@ -233,6 +233,9 @@
makeSureDirIsProgramDir();
#endif
+ hpc_Init();
+ hpc_SetDurationInHz(&video.vblankHpc, VBLANK_HZ);
+
if (!initializeVars() || !initKaiserTable())
{
cleanUp();
@@ -261,8 +264,6 @@
SDL_EventState(SDL_SYSWMEVENT, SDL_ENABLE);
#endif
- setupPerfFreq();
-
if (!setupAudio() || !unpackBMPs())
{
cleanUp();
@@ -329,7 +330,7 @@
SDL_EventState(SDL_DROPFILE, SDL_ENABLE);
- setupWaitVBL();
+ hpc_ResetEndTime(&video.vblankHpc);
while (editor.programRunning)
{
sinkVisualizerBars();
@@ -370,20 +371,11 @@
else if (event.window.event == SDL_WINDOWEVENT_SHOWN)
video.windowHidden = false;
- if (video.vsync60HzPresent)
- {
- /* if we minimize the window and vsync is present, vsync is temporarily turned off.
- ** recalc waitVBL() vars so that it can sleep properly in said mode.
- */
- if (event.window.event == SDL_WINDOWEVENT_MINIMIZED ||
- event.window.event == SDL_WINDOWEVENT_FOCUS_LOST)
- {
- setupWaitVBL();
- }
- }
+ // reset vblank end time if we minimize window
+ if (event.window.event == SDL_WINDOWEVENT_MINIMIZED || event.window.event == SDL_WINDOWEVENT_FOCUS_LOST)
+ hpc_ResetEndTime(&video.vblankHpc);
}
-
#ifdef _WIN32
handleSysMsg(event);
#endif
@@ -485,13 +477,10 @@
config.defModulesDir = (char *)calloc(PATH_MAX + 1, sizeof (char));
config.defSamplesDir = (char *)calloc(PATH_MAX + 1, sizeof (char));
- editor.tempSample = (int8_t *)calloc(MAX_SAMPLE_LEN, 1);
+ editor.tempSample = (int8_t *)calloc(131070, 1);
- if (config.defModulesDir == NULL || config.defSamplesDir == NULL ||
- editor.tempSample == NULL)
- {
+ if (config.defModulesDir == NULL || config.defSamplesDir == NULL || editor.tempSample == NULL)
goto oom;
- }
turnOffVoices();
@@ -906,7 +895,6 @@
if (editor.tempSample != NULL) free(editor.tempSample);
#ifdef _WIN32
- freeWin32Usleep();
#ifndef _DEBUG
UnhookWindowsHookEx(g_hKeyboardHook);
#endif
--- a/src/pt2_module_loader.c
+++ b/src/pt2_module_loader.c
@@ -17,6 +17,7 @@
#include <sys/stat.h>
#include "pt2_mouse.h"
#include "pt2_header.h"
+#include "pt2_config.h"
#include "pt2_sampler.h"
#include "pt2_textout.h"
#include "pt2_audio.h"
@@ -312,7 +313,7 @@
}
realSampleLengths[i] = ((mgetc(m) << 8) | mgetc(m)) * 2;
- s->length = (realSampleLengths[i] > MAX_SAMPLE_LEN) ? MAX_SAMPLE_LEN : (uint16_t)realSampleLengths[i];
+ s->length = (realSampleLengths[i] > config.maxSampleLength) ? config.maxSampleLength : realSampleLengths[i];
/* Only late versions of Ultimate SoundTracker could have samples larger than 9999 bytes.
** If found, we know for sure that this is a late STK module.
@@ -338,8 +339,8 @@
if (loopLength < 2)
loopLength = 2; // fixes empty samples in .MODs saved from FT2
- // we don't support samples bigger than 65534 bytes, disable uncompatible loops
- if (loopStart > MAX_SAMPLE_LEN || loopStart+loopLength > MAX_SAMPLE_LEN)
+ // we don't support samples bigger than 65534 (or 128kB) bytes, disable uncompatible loops
+ if (loopStart > config.maxSampleLength || loopStart+loopLength > config.maxSampleLength)
{
s->loopStart = 0;
s->loopLength = 2;
@@ -346,8 +347,8 @@
}
else
{
- s->loopStart = (uint16_t)loopStart;
- s->loopLength = (uint16_t)loopLength;
+ s->loopStart = loopStart;
+ s->loopLength = loopLength;
}
// in The Ultimate SoundTracker, sample loop start is in bytes, not words
@@ -596,7 +597,7 @@
// set sample data offsets (sample data = one huge buffer to rule them all)
for (i = 0; i < MOD_SAMPLES; i++)
- newMod->samples[i].offset = MAX_SAMPLE_LEN * i;
+ newMod->samples[i].offset = config.maxSampleLength * i;
// load sample data
numSamples = (modFormat == FORMAT_STK) ? 15 : 31;
@@ -617,11 +618,11 @@
** so skip overflown data in .MOD file if present.
*/
int32_t bytesToSkip = 0;
- if (realSampleLengths[i] > MAX_SAMPLE_LEN)
- bytesToSkip = realSampleLengths[i] - MAX_SAMPLE_LEN;
+ if (realSampleLengths[i] > config.maxSampleLength)
+ bytesToSkip = realSampleLengths[i] - config.maxSampleLength;
// For Ultimate SoundTracker modules, don't load sample data after loop end
- uint16_t loopEnd = s->loopStart + s->loopLength;
+ int32_t loopEnd = s->loopStart + s->loopLength;
if (modFormat == FORMAT_STK && loopEnd > 2 && s->length > loopEnd)
{
bytesToSkip += s->length-loopEnd;
@@ -643,9 +644,9 @@
if (s->length > 0 && s->loopLength > 2 && s->loopStart+s->loopLength > s->length)
{
loopOverflowVal = (s->loopStart + s->loopLength) - s->length;
- if (s->length+loopOverflowVal <= MAX_SAMPLE_LEN)
+ if (s->length+loopOverflowVal <= config.maxSampleLength)
{
- s->length = (uint16_t)(s->length + loopOverflowVal); // this is safe, we're allocating 65534 bytes per sample slot
+ s->length += loopOverflowVal; // this is safe, we're allocating 65534 bytes per sample slot
}
else
{
@@ -1205,7 +1206,7 @@
moduleSample_t *s = newMod->samples;
for (i = 0; i < MOD_SAMPLES; i++, s++)
{
- s->offset = MAX_SAMPLE_LEN * i;
+ s->offset = config.maxSampleLength * i;
s->loopLength = 2;
// setup GUI text pointers
--- a/src/pt2_module_saver.c
+++ b/src/pt2_module_saver.c
@@ -42,8 +42,8 @@
fputc(s->fineTune & 0xF, f);
fputc(((uint8_t)s->volume > 64) ? 64 : s->volume, f);
- uint16_t loopStart = s->loopStart;
- uint16_t loopLength = s->loopLength;
+ int32_t loopStart = s->loopStart;
+ int32_t loopLength = s->loopLength;
if (loopLength < 2)
loopLength = 2;
@@ -54,11 +54,11 @@
loopLength = 2;
}
- loopLength = SWAP16(loopLength >> 1);
- loopStart = SWAP16(loopStart >> 1);
+ uint16_t loopStart16 = SWAP16(loopStart >> 1);
+ uint16_t loopLength16 = SWAP16(loopLength >> 1);
- fwrite(&loopStart, sizeof (int16_t), 1, f);
- fwrite(&loopLength, sizeof (int16_t), 1, f);
+ fwrite(&loopStart16, sizeof (int16_t), 1, f);
+ fwrite(&loopLength16, sizeof (int16_t), 1, f);
}
fputc((uint8_t)song->header.numOrders, f);
--- a/src/pt2_mouse.c
+++ b/src/pt2_mouse.c
@@ -457,7 +457,7 @@
if (editor.note1 > 36)
editor.note1 = 36;
- ui.updateNote1Text = true;
+ ui.updateChordNote1Text = true;
recalcChordLength();
}
@@ -471,7 +471,7 @@
if (editor.note1 < 0)
editor.note1 = 0;
- ui.updateNote1Text = true;
+ ui.updateChordNote1Text = true;
recalcChordLength();
}
@@ -485,7 +485,7 @@
if (editor.note2 > 36)
editor.note2 = 36;
- ui.updateNote2Text = true;
+ ui.updateChordNote2Text = true;
recalcChordLength();
}
@@ -499,7 +499,7 @@
if (editor.note2 < 0)
editor.note2 = 0;
- ui.updateNote2Text = true;
+ ui.updateChordNote2Text = true;
recalcChordLength();
}
@@ -513,7 +513,7 @@
if (editor.note3 > 36)
editor.note3 = 36;
- ui.updateNote3Text = true;
+ ui.updateChordNote3Text = true;
recalcChordLength();
}
@@ -527,7 +527,7 @@
if (editor.note3 < 0)
editor.note3 = 0;
- ui.updateNote3Text = true;
+ ui.updateChordNote3Text = true;
recalcChordLength();
}
@@ -541,7 +541,7 @@
if (editor.note4 > 36)
editor.note4 = 36;
- ui.updateNote4Text = true;
+ ui.updateChordNote4Text = true;
recalcChordLength();
}
@@ -555,7 +555,7 @@
if (editor.note4 < 0)
editor.note4 = 0;
- ui.updateNote4Text = true;
+ ui.updateChordNote4Text = true;
recalcChordLength();
}
@@ -565,17 +565,17 @@
{
if (fast)
{
- if (editor.samplePos <= 0xFFFF-64)
+ if (editor.samplePos <= config.maxSampleLength-64)
editor.samplePos += 64;
else
- editor.samplePos = 0xFFFF;
+ editor.samplePos = config.maxSampleLength;
}
else
{
- if (editor.samplePos <= 0xFFFF-16)
+ if (editor.samplePos <= config.maxSampleLength-16)
editor.samplePos += 16;
else
- editor.samplePos = 0xFFFF;
+ editor.samplePos = config.maxSampleLength;
}
}
else
@@ -582,17 +582,17 @@
{
if (fast)
{
- if (editor.samplePos <= 0xFFFF-64)
+ if (editor.samplePos <= config.maxSampleLength-64)
editor.samplePos += 64;
else
- editor.samplePos = 0xFFFF;
+ editor.samplePos = config.maxSampleLength;
}
else
{
- if (editor.samplePos < 0xFFFF)
+ if (editor.samplePos < config.maxSampleLength)
editor.samplePos++;
else
- editor.samplePos = 0xFFFF;
+ editor.samplePos = config.maxSampleLength;
}
}
@@ -794,7 +794,7 @@
{
int32_t val;
- if (song->samples[editor.currSample].length == MAX_SAMPLE_LEN)
+ if (song->samples[editor.currSample].length == config.maxSampleLength)
return;
val = song->samples[editor.currSample].length;
@@ -813,10 +813,10 @@
val += 2;
}
- if (val > MAX_SAMPLE_LEN)
- val = MAX_SAMPLE_LEN;
+ if (val > config.maxSampleLength)
+ val = config.maxSampleLength;
- song->samples[editor.currSample].length = (uint16_t)val;
+ song->samples[editor.currSample].length = val;
ui.updateCurrSampleLength = true;
}
@@ -862,7 +862,7 @@
val = s->loopStart+s->loopLength;
}
- s->length = (uint16_t)val;
+ s->length = val;
ui.updateCurrSampleLength = true;
}
@@ -899,7 +899,7 @@
if (val > len-loopLen)
val = len-loopLen;
- song->samples[editor.currSample].loopStart = (uint16_t)val;
+ song->samples[editor.currSample].loopStart = val;
ui.updateCurrSampleRepeat = true;
mixerUpdateLoops();
@@ -908,7 +908,7 @@
setLoopSprites();
if (ui.editOpScreenShown && ui.editOpScreen == 3) // sample chord editor
- ui.updateLengthText = true;
+ ui.updateChordLengthText = true;
}
void sampleRepeatDownButton(bool fast)
@@ -942,7 +942,7 @@
if (val < 0)
val = 0;
- song->samples[editor.currSample].loopStart = (uint16_t)val;
+ song->samples[editor.currSample].loopStart = val;
ui.updateCurrSampleRepeat = true;
mixerUpdateLoops();
@@ -951,7 +951,7 @@
setLoopSprites();
if (ui.editOpScreenShown && ui.editOpScreen == 3) // sample chord editor
- ui.updateLengthText = true;
+ ui.updateChordLengthText = true;
}
void sampleRepeatLengthUpButton(bool fast)
@@ -986,7 +986,7 @@
if (val > len-loopStart)
val = len-loopStart;
- song->samples[editor.currSample].loopLength = (uint16_t)val;
+ song->samples[editor.currSample].loopLength = val;
ui.updateCurrSampleReplen = true;
mixerUpdateLoops();
@@ -995,7 +995,7 @@
setLoopSprites();
if (ui.editOpScreenShown && ui.editOpScreen == 3) // sample chord editor
- ui.updateLengthText = true;
+ ui.updateChordLengthText = true;
}
void sampleRepeatLengthDownButton(bool fast)
@@ -1029,7 +1029,7 @@
if (val < 2)
val = 2;
- song->samples[editor.currSample].loopLength = (uint16_t)val;
+ song->samples[editor.currSample].loopLength = val;
ui.updateCurrSampleReplen = true;
mixerUpdateLoops();
@@ -1038,7 +1038,7 @@
setLoopSprites();
if (ui.editOpScreenShown && ui.editOpScreen == 3) // sample chord editor
- ui.updateLengthText = true;
+ ui.updateChordLengthText = true;
}
void tempoUpButton(void)
@@ -1721,7 +1721,7 @@
}
else
{
- memcpy(&song->sampleData[s->offset], editor.tempSample, MAX_SAMPLE_LEN);
+ memcpy(&song->sampleData[s->offset], editor.tempSample, config.maxSampleLength);
redrawSample();
updateWindowTitle(MOD_IS_MODIFIED);
renderSamplerFiltersBox();
@@ -2270,10 +2270,10 @@
ui.changingDrumPadNote = false;
ui.updateResampleNote = true;
- ui.updateNote1Text = true;
- ui.updateNote2Text = true;
- ui.updateNote3Text = true;
- ui.updateNote4Text = true;
+ ui.updateChordNote1Text = true;
+ ui.updateChordNote2Text = true;
+ ui.updateChordNote3Text = true;
+ ui.updateChordNote4Text = true;
setPrevStatusMessage();
pointerSetPreviousMode();
@@ -2402,6 +2402,8 @@
int32_t smp32, j, modPos, oldVal, tmp32;
double dSmp;
moduleSample_t *s;
+
+ ui.force32BitNumPtr = false;
switch (button)
{
@@ -2656,7 +2658,7 @@
break;
}
- ptr8_1 = (int8_t *)malloc(MAX_SAMPLE_LEN);
+ ptr8_1 = (int8_t *)malloc(config.maxSampleLength);
if (ptr8_1 == NULL)
{
statusOutOfMemory();
@@ -2663,7 +2665,7 @@
return true;
}
- memcpy(ptr8_1, &song->sampleData[s->offset], MAX_SAMPLE_LEN);
+ memcpy(ptr8_1, &song->sampleData[s->offset], config.maxSampleLength);
ptr8_2 = &song->sampleData[s->offset+editor.samplePos];
ptr8_3 = &song->sampleData[s->offset+s->length-1];
@@ -2791,6 +2793,9 @@
case PTB_EO_POS_NUM:
{
+ if (config.maxSampleLength == 65534 && mouse.x < 244) // yuck!
+ break;
+
if (mouse.rightButtonPressed)
{
editor.samplePos = 0;
@@ -2798,12 +2803,25 @@
}
else
{
- ui.tmpDisp16 = editor.samplePos;
- editor.samplePosDisp = &ui.tmpDisp16;
- ui.numPtr16 = &ui.tmpDisp16;
- ui.numLen = 4;
- ui.numBits = 16;
- ui.editTextPos = 2391; // (y * 40) + x
+ ui.force32BitNumPtr = true;
+
+ ui.tmpDisp32 = editor.samplePos;
+ editor.samplePosDisp = &ui.tmpDisp32;
+ ui.numPtr32 = &ui.tmpDisp32;
+
+ if (config.maxSampleLength == 65534)
+ {
+ ui.numLen = 4;
+ ui.numBits = 16;
+ ui.editTextPos = 2391; // (y * 40) + x
+ }
+ else
+ {
+ ui.numLen = 5;
+ ui.numBits = 17;
+ ui.editTextPos = 2390; // (y * 40) + x
+ }
+
getNumLine(TEXT_EDIT_HEX, PTB_EO_POS_NUM);
}
}
@@ -2891,7 +2909,7 @@
ptr8_1 = &song->sampleData[s->offset];
- ptr8_3 = (int8_t *)malloc(MAX_SAMPLE_LEN);
+ ptr8_3 = (int8_t *)malloc(config.maxSampleLength);
if (ptr8_3 == NULL)
{
statusOutOfMemory();
@@ -2900,7 +2918,7 @@
ptr8_2 = ptr8_3;
- memcpy(ptr8_2, ptr8_1, MAX_SAMPLE_LEN);
+ memcpy(ptr8_2, ptr8_1, config.maxSampleLength);
editor.modulateOffset = 0;
editor.modulatePos = 0;
@@ -3047,8 +3065,8 @@
turnOffVoices();
- memcpy(&song->sampleData[s->offset], &song->sampleData[s->offset + editor.samplePos], MAX_SAMPLE_LEN - editor.samplePos);
- memset(&song->sampleData[s->offset + (MAX_SAMPLE_LEN - editor.samplePos)], 0, editor.samplePos);
+ memcpy(&song->sampleData[s->offset], &song->sampleData[s->offset + editor.samplePos], config.maxSampleLength - editor.samplePos);
+ memset(&song->sampleData[s->offset + (config.maxSampleLength - editor.samplePos)], 0, editor.samplePos);
if (editor.samplePos > s->loopStart)
{
@@ -3057,10 +3075,10 @@
}
else
{
- s->loopStart = (s->loopStart - editor.samplePos) & 0xFFFE;
+ s->loopStart = (s->loopStart - editor.samplePos) & config.maxSampleLength;
}
- s->length = (s->length - editor.samplePos) & 0xFFFE;
+ s->length = (s->length - editor.samplePos) & config.maxSampleLength;
editor.samplePos = 0;
fixSampleBeep(s);
@@ -3277,7 +3295,16 @@
case PTB_EO_NOTE4_DOWN: edNote4DownButton(); break;
case PTB_EO_RESET: resetChord(); break;
case PTB_EO_UNDO: undoChord(); break;
- case PTB_EO_LENGTH: toggleChordLength(); break;
+
+ case PTB_EO_LENGTH:
+ {
+ if (config.maxSampleLength != 65534 && mouse.x > 157) // yuck!
+ break;
+
+ toggleChordLength();
+ }
+ break;
+
case PTB_EO_MAJOR: setChordMajor(); break;
case PTB_EO_MINOR: setChordMinor(); break;
case PTB_EO_SUS4: setChordSus4(); break;
@@ -3515,6 +3542,9 @@
case PTB_SLENGTHS:
{
+ if (config.maxSampleLength == 65534 && mouse.x < 62) // yuck!
+ break;
+
if (editor.sampleZero)
{
statusNotSampleZero();
@@ -3545,12 +3575,25 @@
}
else
{
- ui.tmpDisp16 = song->samples[editor.currSample].length;
- song->samples[editor.currSample].lengthDisp = &ui.tmpDisp16;
- ui.numPtr16 = &ui.tmpDisp16;
- ui.numLen = 4;
- ui.numBits = 16;
- ui.editTextPos = 2808; // (y * 40) + x
+ ui.force32BitNumPtr = true;
+
+ ui.tmpDisp32 = song->samples[editor.currSample].length;
+ song->samples[editor.currSample].lengthDisp = &ui.tmpDisp32;
+ ui.numPtr32 = &ui.tmpDisp32;
+
+ if (config.maxSampleLength == 65534)
+ {
+ ui.numLen = 4;
+ ui.numBits = 16;
+ ui.editTextPos = 2808; // (y * 40) + x
+ }
+ else
+ {
+ ui.numLen = 5;
+ ui.numBits = 17;
+ ui.editTextPos = 2807; // (y * 40) + x
+ }
+
getNumLine(TEXT_EDIT_HEX, PTB_SLENGTHS);
}
}
@@ -3558,6 +3601,9 @@
case PTB_SREPEATS:
{
+ if (config.maxSampleLength == 65534 && mouse.x < 62) // yuck!
+ break;
+
if (editor.sampleZero)
{
statusNotSampleZero();
@@ -3581,7 +3627,7 @@
ui.updateCurrSampleRepeat = true;
if (ui.editOpScreenShown && ui.editOpScreen == 3)
- ui.updateLengthText = true;
+ ui.updateChordLengthText = true;
if (ui.samplerScreenShown)
setLoopSprites();
@@ -3591,12 +3637,25 @@
}
else
{
- ui.tmpDisp16 = song->samples[editor.currSample].loopStart;
- song->samples[editor.currSample].loopStartDisp = &ui.tmpDisp16;
- ui.numPtr16 = &ui.tmpDisp16;
- ui.numLen = 4;
- ui.numBits = 16;
- ui.editTextPos = 3248; // (y * 40) + x
+ ui.force32BitNumPtr = true;
+
+ ui.tmpDisp32 = song->samples[editor.currSample].loopStart;
+ song->samples[editor.currSample].loopStartDisp = &ui.tmpDisp32;
+ ui.numPtr32 = &ui.tmpDisp32;
+
+ if (config.maxSampleLength == 65534)
+ {
+ ui.numLen = 4;
+ ui.numBits = 16;
+ ui.editTextPos = 3248; // (y * 40) + x
+ }
+ else
+ {
+ ui.numLen = 5;
+ ui.numBits = 17;
+ ui.editTextPos = 3247; // (y * 40) + x
+ }
+
getNumLine(TEXT_EDIT_HEX, PTB_SREPEATS);
}
}
@@ -3604,6 +3663,9 @@
case PTB_SREPLENS:
{
+ if (config.maxSampleLength == 65534 && mouse.x < 62) // yuck!
+ break;
+
if (editor.sampleZero)
{
statusNotSampleZero();
@@ -3630,7 +3692,7 @@
ui.updateCurrSampleReplen = true;
if (ui.editOpScreenShown && ui.editOpScreen == 3)
- ui.updateLengthText = true;
+ ui.updateChordLengthText = true;
if (ui.samplerScreenShown)
setLoopSprites();
@@ -3640,12 +3702,25 @@
}
else
{
- ui.tmpDisp16 = song->samples[editor.currSample].loopLength;
- song->samples[editor.currSample].loopLengthDisp = &ui.tmpDisp16;
- ui.numPtr16 = &ui.tmpDisp16;
- ui.numLen = 4;
- ui.numBits = 16;
- ui.editTextPos = 3688; // (y * 40) + x
+ ui.force32BitNumPtr = true;
+
+ ui.tmpDisp32 = song->samples[editor.currSample].loopLength;
+ song->samples[editor.currSample].loopLengthDisp = &ui.tmpDisp32;
+ ui.numPtr32 = &ui.tmpDisp32;
+
+ if (config.maxSampleLength == 0xFFFE)
+ {
+ ui.numLen = 4;
+ ui.numBits = 16;
+ ui.editTextPos = 3688; // (y * 40) + x
+ }
+ else
+ {
+ ui.numLen = 5;
+ ui.numBits = 17;
+ ui.editTextPos = 3687; // (y * 40) + x
+ }
+
getNumLine(TEXT_EDIT_HEX, PTB_SREPLENS);
}
}
@@ -4402,7 +4477,7 @@
case PTB_SLENGTHU:
{
- if (!editor.sampleZero && song->samples[editor.currSample].length < MAX_SAMPLE_LEN)
+ if (!editor.sampleZero && song->samples[editor.currSample].length < config.maxSampleLength)
{
sampleLengthUpButton(INCREMENT_SLOW);
updateWindowTitle(MOD_IS_MODIFIED);
--- a/src/pt2_pat2smp.c
+++ b/src/pt2_pat2smp.c
@@ -6,6 +6,7 @@
#include <stdint.h>
#include <stdbool.h>
#include "pt2_header.h"
+#include "pt2_config.h"
#include "pt2_helpers.h"
#include "pt2_visuals.h"
#include "pt2_mouse.h"
@@ -31,7 +32,7 @@
return;
}
- editor.dPat2SmpBuf = (double *)malloc(MAX_SAMPLE_LEN * sizeof (double));
+ editor.dPat2SmpBuf = (double *)malloc(config.maxSampleLength * sizeof (double));
if (editor.dPat2SmpBuf == NULL)
{
statusOutOfMemory();
@@ -101,8 +102,8 @@
free(editor.dPat2SmpBuf);
// clear the rest of the sample (if not full)
- if (renderLength < MAX_SAMPLE_LEN)
- memset(&song->sampleData[s->offset+renderLength], 0, MAX_SAMPLE_LEN - renderLength);
+ if (renderLength < config.maxSampleLength)
+ memset(&song->sampleData[s->offset+renderLength], 0, config.maxSampleLength - renderLength);
if (editor.pat2SmpHQ)
{
@@ -115,7 +116,7 @@
s->fineTune = 0;
}
- s->length = (uint16_t)renderLength;
+ s->length = renderLength;
s->volume = 64;
s->loopStart = 0;
s->loopLength = 2;
--- a/src/pt2_replayer.c
+++ b/src/pt2_replayer.c
@@ -37,21 +37,10 @@
int8_t *allocMemForAllSamples(void)
{
- /* Allocate memory for all sample data blocks.
- **
- ** We need three extra sample slots:
- ** The 1st is extra safety padding since setting a Paula length of 0
- ** results in reading (1+65535)*2 bytes. The 2nd and 3rd (64K*2 = 1x 128K)
- ** are reserved for NULL pointers. This is needed for emulating a PT quirk.
- **
- ** We have a padding of 4 bytes at the end for length=0 quirk safety.
- **
- ** PS: I don't really know if it's possible for ProTracker to set a Paula
- ** length of 0, but I fully support this Paula behavior just in case.
- */
- const size_t allocLen = ((MOD_SAMPLES + 3) * MAX_SAMPLE_LEN) + 4;
+ // allocate memory for all sample data blocks (+ 2 extra, for quirk + safety)
+ const size_t allocLen = (MOD_SAMPLES + 2) * config.maxSampleLength;
- return (int8_t *)calloc(1, allocLen);
+ return (int8_t *)calloc(allocLen, 1);
}
void modSetSpeed(int32_t speed)
@@ -668,7 +657,7 @@
uint16_t newOffset = ch->n_sampleoffset << 7;
// this signed test is the reason for the 9xx "sample >64kB = silence" bug
- if ((int16_t)newOffset < ch->n_length)
+ if ((int16_t)newOffset < (int16_t)ch->n_length)
{
ch->n_length -= newOffset;
ch->n_start += newOffset << 1;
@@ -871,10 +860,10 @@
ch->n_start = &song->sampleData[s->offset];
ch->n_finetune = s->fineTune & 0xF;
ch->n_volume = s->volume;
- ch->n_length = s->length >> 1;
- ch->n_replen = s->loopLength >> 1;
+ ch->n_length = (uint16_t)(s->length >> 1);
+ ch->n_replen = (uint16_t)(s->loopLength >> 1);
- const uint16_t repeat = s->loopStart >> 1;
+ const uint16_t repeat = (uint16_t)(s->loopStart >> 1);
if (repeat > 0)
{
ch->n_loopstart = ch->n_start + (repeat << 1);
@@ -889,7 +878,7 @@
// non-PT2 requirement (set safe sample space for uninitialized voices - f.ex. "the ultimate beeper.mod")
if (ch->n_length == 0)
- ch->n_loopstart = ch->n_wavestart = &song->sampleData[RESERVED_SAMPLE_OFFSET]; // 128K reserved sample
+ ch->n_loopstart = ch->n_wavestart = &song->sampleData[config.reservedSampleOffset]; // 128K reserved sample
}
if ((ch->n_note & 0xFFF) > 0)
@@ -1491,7 +1480,7 @@
memset(s->text, 0, sizeof (s->text));
}
- memset(song->sampleData, 0, (MOD_SAMPLES + 1) * MAX_SAMPLE_LEN);
+ memset(song->sampleData, 0, (MOD_SAMPLES + 1) * config.maxSampleLength);
editor.currSample = 0;
editor.hiLowInstr = 0;
--- a/src/pt2_sample_loader.c
+++ b/src/pt2_sample_loader.c
@@ -58,11 +58,11 @@
uint8_t *audioDataU8;
int16_t *audioDataS16, tempVol;
uint16_t audioFormat, numChannels, bitsPerSample;
- int32_t *audioDataS32, smp32;
- uint32_t *audioDataU32, i, nameLen, chunkID, chunkSize;
- uint32_t sampleLength, sampleRate, filesize, loopFlags;
- uint32_t loopStart, loopEnd, dataPtr, dataLen, fmtPtr, endOfChunk, bytesRead;
- uint32_t fmtLen, inamPtr, inamLen, smplPtr, smplLen, xtraPtr, xtraLen;
+ int32_t *audioDataS32, smp32, sampleLength, loopStart, loopEnd, inamLen, nameLen, i;
+ uint32_t *audioDataU32, chunkID, chunkSize;
+ uint32_t sampleRate, filesize, loopFlags;
+ uint32_t dataPtr, dataLen, fmtPtr, endOfChunk, bytesRead;
+ uint32_t fmtLen, inamPtr, smplPtr, smplLen, xtraPtr, xtraLen;
float *fAudioDataFloat;
double *dAudioDataDouble;
FILE *f;
@@ -204,7 +204,7 @@
sampleLength = dataLen;
// ---------------------------
- if (sampleRate == 0 || sampleLength == 0 || sampleLength >= filesize*(bitsPerSample/8))
+ if (sampleRate == 0 || sampleLength == 0 || sampleLength >= (int32_t)filesize*(bitsPerSample/8))
{
fclose(f);
displayErrorMsg("WAV CORRUPT !");
@@ -256,12 +256,12 @@
// ---- READ SAMPLE DATA ----
fseek(f, dataPtr, SEEK_SET);
- int8_t *smpPtr = &song->sampleData[editor.currSample * MAX_SAMPLE_LEN];
+ int8_t *smpPtr = &song->sampleData[editor.currSample * config.maxSampleLength];
if (bitsPerSample == 8) // 8-BIT INTEGER SAMPLE
{
- if (sampleLength > MAX_SAMPLE_LEN*4)
- sampleLength = MAX_SAMPLE_LEN*4;
+ if (sampleLength > config.maxSampleLength*4)
+ sampleLength = config.maxSampleLength*4;
audioDataU8 = (uint8_t *)malloc(sampleLength * sizeof (uint8_t));
if (audioDataU8 == NULL)
@@ -272,7 +272,7 @@
}
// read sample data
- if (fread(audioDataU8, 1, sampleLength, f) != sampleLength)
+ if (fread(audioDataU8, 1, sampleLength, f) != (size_t)sampleLength)
{
fclose(f);
free(audioDataU8);
@@ -299,8 +299,8 @@
sampleLength >>= 1;
}
- if (sampleLength > MAX_SAMPLE_LEN)
- sampleLength = MAX_SAMPLE_LEN;
+ if (sampleLength > config.maxSampleLength)
+ sampleLength = config.maxSampleLength;
turnOffVoices();
for (i = 0; i < sampleLength; i++)
@@ -311,8 +311,8 @@
else if (bitsPerSample == 16) // 16-BIT INTEGER SAMPLE
{
sampleLength >>= 1;
- if (sampleLength > MAX_SAMPLE_LEN*4)
- sampleLength = MAX_SAMPLE_LEN*4;
+ if (sampleLength > config.maxSampleLength*4)
+ sampleLength = config.maxSampleLength*4;
audioDataS16 = (int16_t *)malloc(sampleLength * sizeof (int16_t));
if (audioDataS16 == NULL)
@@ -323,7 +323,7 @@
}
// read sample data
- if (fread(audioDataS16, 2, sampleLength, f) != sampleLength)
+ if (fread(audioDataS16, 2, sampleLength, f) != (size_t)sampleLength)
{
fclose(f);
free(audioDataS16);
@@ -346,8 +346,8 @@
sampleLength >>= 1;
}
- if (sampleLength > MAX_SAMPLE_LEN)
- sampleLength = MAX_SAMPLE_LEN;
+ if (sampleLength > config.maxSampleLength)
+ sampleLength = config.maxSampleLength;
double dAmp = 1.0;
if (forceDownSampling) // we already normalized
@@ -374,8 +374,8 @@
else if (bitsPerSample == 24) // 24-BIT INTEGER SAMPLE
{
sampleLength /= 3;
- if (sampleLength > MAX_SAMPLE_LEN*4)
- sampleLength = MAX_SAMPLE_LEN*4;
+ if (sampleLength > config.maxSampleLength*4)
+ sampleLength = config.maxSampleLength*4;
audioDataS32 = (int32_t *)malloc(sampleLength * sizeof (int32_t));
if (audioDataS32 == NULL)
@@ -412,8 +412,8 @@
sampleLength >>= 1;
}
- if (sampleLength > MAX_SAMPLE_LEN)
- sampleLength = MAX_SAMPLE_LEN;
+ if (sampleLength > config.maxSampleLength)
+ sampleLength = config.maxSampleLength;
double dAmp = 1.0;
if (forceDownSampling) // we already normalized
@@ -440,8 +440,8 @@
else if (audioFormat == WAV_FORMAT_PCM && bitsPerSample == 32) // 32-BIT INTEGER SAMPLE
{
sampleLength >>= 2;
- if (sampleLength > MAX_SAMPLE_LEN*4)
- sampleLength = MAX_SAMPLE_LEN*4;
+ if (sampleLength > config.maxSampleLength*4)
+ sampleLength = config.maxSampleLength*4;
audioDataS32 = (int32_t *)malloc(sampleLength * sizeof (int32_t));
if (audioDataS32 == NULL)
@@ -452,7 +452,7 @@
}
// read sample data
- if (fread(audioDataS32, 4, sampleLength, f) != sampleLength)
+ if (fread(audioDataS32, 4, sampleLength, f) != (size_t)sampleLength)
{
fclose(f);
free(audioDataS32);
@@ -478,8 +478,8 @@
sampleLength >>= 1;
}
- if (sampleLength > MAX_SAMPLE_LEN)
- sampleLength = MAX_SAMPLE_LEN;
+ if (sampleLength > config.maxSampleLength)
+ sampleLength = config.maxSampleLength;
double dAmp = 1.0;
if (forceDownSampling) // we already normalized
@@ -506,8 +506,8 @@
else if (audioFormat == WAV_FORMAT_IEEE_FLOAT && bitsPerSample == 32) // 32-BIT FLOATING POINT SAMPLE
{
sampleLength >>= 2;
- if (sampleLength > MAX_SAMPLE_LEN*4)
- sampleLength = MAX_SAMPLE_LEN*4;
+ if (sampleLength > config.maxSampleLength*4)
+ sampleLength = config.maxSampleLength*4;
audioDataU32 = (uint32_t *)malloc(sampleLength * sizeof (uint32_t));
if (audioDataU32 == NULL)
@@ -518,7 +518,7 @@
}
// read sample data
- if (fread(audioDataU32, 4, sampleLength, f) != sampleLength)
+ if (fread(audioDataU32, 4, sampleLength, f) != (size_t)sampleLength)
{
fclose(f);
free(audioDataU32);
@@ -543,8 +543,8 @@
sampleLength >>= 1;
}
- if (sampleLength > MAX_SAMPLE_LEN)
- sampleLength = MAX_SAMPLE_LEN;
+ if (sampleLength > config.maxSampleLength)
+ sampleLength = config.maxSampleLength;
float fAmp = 1.0f;
const float fPeak = getFloatPeak(fAudioDataFloat, sampleLength);
@@ -564,8 +564,8 @@
else if (audioFormat == WAV_FORMAT_IEEE_FLOAT && bitsPerSample == 64) // 64-BIT FLOATING POINT SAMPLE
{
sampleLength >>= 3;
- if (sampleLength > MAX_SAMPLE_LEN*4)
- sampleLength = MAX_SAMPLE_LEN*4;
+ if (sampleLength > config.maxSampleLength*4)
+ sampleLength = config.maxSampleLength*4;
audioDataU32 = (uint32_t *)malloc(sampleLength * (sizeof (uint32_t) * 2));
if (audioDataU32 == NULL)
@@ -576,7 +576,7 @@
}
// read sample data
- if (fread(audioDataU32, 8, sampleLength, f) != sampleLength)
+ if (fread(audioDataU32, 8, sampleLength, f) != (size_t)sampleLength)
{
fclose(f);
free(audioDataU32);
@@ -601,8 +601,8 @@
sampleLength >>= 1;
}
- if (sampleLength > MAX_SAMPLE_LEN)
- sampleLength = MAX_SAMPLE_LEN;
+ if (sampleLength > config.maxSampleLength)
+ sampleLength = config.maxSampleLength;
double dAmp = 1.0;
const double dPeak = getDoublePeak(dAudioDataDouble, sampleLength);
@@ -620,17 +620,17 @@
free(audioDataU32);
}
- if (sampleLength < MAX_SAMPLE_LEN) // clear rest of sample data
- memset(&song->sampleData[s->offset + sampleLength], 0, MAX_SAMPLE_LEN - sampleLength);
+ if (sampleLength < config.maxSampleLength) // clear rest of sample data
+ memset(&song->sampleData[s->offset + sampleLength], 0, config.maxSampleLength - sampleLength);
// set sample length
if (sampleLength & 1)
{
- if (++sampleLength > MAX_SAMPLE_LEN)
- sampleLength = MAX_SAMPLE_LEN;
+ if (++sampleLength > config.maxSampleLength)
+ sampleLength = config.maxSampleLength;
}
- s->length = (uint16_t)sampleLength;
+ s->length = sampleLength;
s->fineTune = 0;
s->volume = 64;
s->loopStart = 0;
@@ -654,15 +654,15 @@
loopEnd >>= 1;
}
- loopStart &= 0xFFFFFFFE;
- loopEnd &= 0xFFFFFFFE;
+ loopStart &= ~1;
+ loopEnd &= ~1;
if (loopFlags)
{
if (loopStart+(loopEnd-loopStart) <= s->length)
{
- s->loopStart = (uint16_t)loopStart;
- s->loopLength = (uint16_t)(loopEnd - loopStart);
+ s->loopStart = loopStart;
+ s->loopLength = loopEnd - loopStart;
if (s->loopLength < 2)
{
@@ -716,7 +716,7 @@
// copy over sample name
if (!wavSampleNameFound)
{
- nameLen = (uint32_t)strlen(entryName);
+ nameLen = (int32_t)strlen(entryName);
for (i = 0; i < 21; i++)
s->text[i] = (i < nameLen) ? (char)entryName[i] : '\0';
@@ -755,9 +755,9 @@
int16_t *ptr16;
int32_t filesize, smp32;
uint16_t sampleRate;
- uint32_t i, sampleLength, sampleLoopStart, sampleLoopLength;
+ int32_t i, sampleLength, sampleLoopStart, sampleLoopLength, nameLen;
uint32_t sampleVolume, blockName, blockSize;
- uint32_t vhdrPtr, vhdrLen, bodyPtr, bodyLen, namePtr, nameLen;
+ uint32_t vhdrPtr, vhdrLen, bodyPtr, bodyLen, namePtr;
FILE *f;
moduleSample_t *s;
@@ -898,7 +898,7 @@
forceDownSampling = false;
}
- uint32_t maxSampleLength = MAX_SAMPLE_LEN;
+ int32_t maxSampleLength = config.maxSampleLength;
if (is16Bit)
maxSampleLength *= 2;
@@ -944,8 +944,8 @@
sampleLength >>= 1;
}
- if (sampleLength > MAX_SAMPLE_LEN)
- sampleLength = MAX_SAMPLE_LEN;
+ if (sampleLength > config.maxSampleLength)
+ sampleLength = config.maxSampleLength;
double dAmp = 1.0;
if (forceDownSampling) // we already normalized
@@ -978,8 +978,8 @@
sampleLength >>= 1;
}
- if (sampleLength > MAX_SAMPLE_LEN)
- sampleLength = MAX_SAMPLE_LEN;
+ if (sampleLength > config.maxSampleLength)
+ sampleLength = config.maxSampleLength;
memcpy(&song->sampleData[s->offset], sampleData, sampleLength);
}
@@ -986,18 +986,18 @@
free(sampleData);
- if (sampleLength < MAX_SAMPLE_LEN) // clear rest of sample data
- memset(&song->sampleData[s->offset + sampleLength], 0, MAX_SAMPLE_LEN - sampleLength);
+ if (sampleLength < config.maxSampleLength) // clear rest of sample data
+ memset(&song->sampleData[s->offset + sampleLength], 0, config.maxSampleLength - sampleLength);
// set sample length
if (sampleLength & 1)
{
- if (++sampleLength > MAX_SAMPLE_LEN)
- sampleLength = MAX_SAMPLE_LEN;
+ if (++sampleLength > config.maxSampleLength)
+ sampleLength = config.maxSampleLength;
}
- sampleLoopStart &= 0xFFFFFFFE;
- sampleLoopLength &= 0xFFFFFFFE;
+ sampleLoopStart &= ~1;
+ sampleLoopLength &= ~1;
if (sampleLoopLength < 2)
{
@@ -1026,9 +1026,9 @@
// set sample attributes
s->volume = (int8_t)sampleVolume;
s->fineTune = 0;
- s->length = (uint16_t)sampleLength;
- s->loopStart = (uint16_t)sampleLoopStart;
- s->loopLength = (uint16_t)sampleLoopLength;
+ s->length = sampleLength;
+ s->loopStart = sampleLoopStart;
+ s->loopLength = sampleLoopLength;
// read name
if (namePtr != 0 && nameLen > 0)
@@ -1090,7 +1090,7 @@
bool loadRAWSample(UNICHAR *fileName, char *entryName)
{
uint8_t i;
- uint32_t nameLen, fileSize;
+ int32_t nameLen, fileSize;
FILE *f;
moduleSample_t *s;
@@ -1107,9 +1107,9 @@
fileSize = ftell(f);
fseek(f, 0, SEEK_SET);
- fileSize &= 0xFFFFFFFE;
- if (fileSize > MAX_SAMPLE_LEN)
- fileSize = MAX_SAMPLE_LEN;
+ fileSize &= ~1;
+ if (fileSize > config.maxSampleLength)
+ fileSize = config.maxSampleLength;
turnOffVoices();
@@ -1116,13 +1116,13 @@
fread(&song->sampleData[s->offset], 1, fileSize, f);
fclose(f);
- if (fileSize < MAX_SAMPLE_LEN)
- memset(&song->sampleData[s->offset + fileSize], 0, MAX_SAMPLE_LEN - fileSize);
+ if (fileSize < config.maxSampleLength)
+ memset(&song->sampleData[s->offset + fileSize], 0, config.maxSampleLength - fileSize);
// set sample attributes
s->volume = 64;
s->fineTune = 0;
- s->length = (uint16_t)fileSize;
+ s->length = fileSize;
s->loopStart = 0;
s->loopLength = 2;
@@ -1179,8 +1179,8 @@
uint8_t *audioDataU8, sampleRateBytes[10];
int16_t *audioDataS16;
uint16_t bitDepth, numChannels;
- int32_t filesize, *audioDataS32, smp32;
- uint32_t nameLen, i, offset, sampleRate, sampleLength, blockName, blockSize;
+ int32_t i, filesize, *audioDataS32, smp32, sampleLength, nameLen;
+ uint32_t offset, sampleRate, blockName, blockSize;
uint32_t commPtr, commLen, ssndPtr, ssndLen;
FILE *f;
moduleSample_t *s;
@@ -1336,12 +1336,12 @@
forceDownSampling = false;
}
- int8_t *smpPtr = &song->sampleData[editor.currSample * MAX_SAMPLE_LEN];
+ int8_t *smpPtr = &song->sampleData[editor.currSample * config.maxSampleLength];
if (bitDepth == 8) // 8-BIT INTEGER SAMPLE
{
- if (sampleLength > MAX_SAMPLE_LEN*4)
- sampleLength = MAX_SAMPLE_LEN*4;
+ if (sampleLength > config.maxSampleLength*4)
+ sampleLength = config.maxSampleLength*4;
audioDataS8 = (int8_t *)malloc(sampleLength * sizeof (int8_t));
if (audioDataS8 == NULL)
@@ -1352,7 +1352,7 @@
}
// read sample data
- if (fread(audioDataS8, 1, sampleLength, f) != sampleLength)
+ if (fread(audioDataS8, 1, sampleLength, f) != (size_t)sampleLength)
{
fclose(f);
free(audioDataS8);
@@ -1381,8 +1381,8 @@
sampleLength >>= 1;
}
- if (sampleLength > MAX_SAMPLE_LEN)
- sampleLength = MAX_SAMPLE_LEN;
+ if (sampleLength > config.maxSampleLength)
+ sampleLength = config.maxSampleLength;
turnOffVoices();
for (i = 0; i < sampleLength; i++)
@@ -1393,8 +1393,8 @@
else if (bitDepth == 16) // 16-BIT INTEGER SAMPLE
{
sampleLength >>= 1;
- if (sampleLength > MAX_SAMPLE_LEN*4)
- sampleLength = MAX_SAMPLE_LEN*4;
+ if (sampleLength > config.maxSampleLength*4)
+ sampleLength = config.maxSampleLength*4;
audioDataS16 = (int16_t *)malloc(sampleLength * sizeof (int16_t));
if (audioDataS16 == NULL)
@@ -1405,7 +1405,7 @@
}
// read sample data
- if (fread(audioDataS16, 2, sampleLength, f) != sampleLength)
+ if (fread(audioDataS16, 2, sampleLength, f) != (size_t)sampleLength)
{
fclose(f);
free(audioDataS16);
@@ -1432,8 +1432,8 @@
sampleLength >>= 1;
}
- if (sampleLength > MAX_SAMPLE_LEN)
- sampleLength = MAX_SAMPLE_LEN;
+ if (sampleLength > config.maxSampleLength)
+ sampleLength = config.maxSampleLength;
double dAmp = 1.0;
if (forceDownSampling) // we already normalized
@@ -1460,8 +1460,8 @@
else if (bitDepth == 24) // 24-BIT INTEGER SAMPLE
{
sampleLength /= 3;
- if (sampleLength > MAX_SAMPLE_LEN*4)
- sampleLength = MAX_SAMPLE_LEN*4;
+ if (sampleLength > config.maxSampleLength*4)
+ sampleLength = config.maxSampleLength*4;
audioDataS32 = (int32_t *)malloc(sampleLength * sizeof (int32_t));
if (audioDataS32 == NULL)
@@ -1472,7 +1472,7 @@
}
// read sample data
- if (fread(&audioDataS32[sampleLength >> 2], 3, sampleLength, f) != sampleLength)
+ if (fread(&audioDataS32[sampleLength >> 2], 3, sampleLength, f) != (size_t)sampleLength)
{
fclose(f);
free(audioDataS32);
@@ -1506,8 +1506,8 @@
sampleLength >>= 1;
}
- if (sampleLength > MAX_SAMPLE_LEN)
- sampleLength = MAX_SAMPLE_LEN;
+ if (sampleLength > config.maxSampleLength)
+ sampleLength = config.maxSampleLength;
double dAmp = 1.0;
if (forceDownSampling) // we already normalized
@@ -1533,8 +1533,8 @@
else if (bitDepth == 32) // 32-BIT INTEGER SAMPLE
{
sampleLength >>= 2;
- if (sampleLength > MAX_SAMPLE_LEN*4)
- sampleLength = MAX_SAMPLE_LEN*4;
+ if (sampleLength > config.maxSampleLength*4)
+ sampleLength = config.maxSampleLength*4;
audioDataS32 = (int32_t *)malloc(sampleLength * sizeof (int32_t));
if (audioDataS32 == NULL)
@@ -1545,7 +1545,7 @@
}
// read sample data
- if (fread(audioDataS32, 4, sampleLength, f) != sampleLength)
+ if (fread(audioDataS32, 4, sampleLength, f) != (size_t)sampleLength)
{
fclose(f);
free(audioDataS32);
@@ -1575,8 +1575,8 @@
sampleLength >>= 1;
}
- if (sampleLength > MAX_SAMPLE_LEN)
- sampleLength = MAX_SAMPLE_LEN;
+ if (sampleLength > config.maxSampleLength)
+ sampleLength = config.maxSampleLength;
double dAmp = 1.0;
if (forceDownSampling) // we already normalized
@@ -1600,17 +1600,17 @@
free(audioDataS32);
}
- if (sampleLength < MAX_SAMPLE_LEN) // clear rest of sample data
- memset(&song->sampleData[s->offset + sampleLength], 0, MAX_SAMPLE_LEN - sampleLength);
+ if (sampleLength < config.maxSampleLength) // clear rest of sample data
+ memset(&song->sampleData[s->offset + sampleLength], 0, config.maxSampleLength - sampleLength);
// set sample length
if (sampleLength & 1)
{
- if (++sampleLength > MAX_SAMPLE_LEN)
- sampleLength = MAX_SAMPLE_LEN;
+ if (++sampleLength > config.maxSampleLength)
+ sampleLength = config.maxSampleLength;
}
- s->length = (uint16_t)sampleLength;
+ s->length = sampleLength;
s->fineTune = 0;
s->volume = 64;
s->loopStart = 0;
@@ -1619,7 +1619,7 @@
fclose(f);
// copy over sample name
- nameLen = (uint32_t)strlen(entryName);
+ nameLen = (int32_t)strlen(entryName);
for (i = 0; i < 21; i++)
s->text[i] = (i < nameLen) ? (char)entryName[i] : '\0';
--- a/src/pt2_sample_saver.c
+++ b/src/pt2_sample_saver.c
@@ -161,8 +161,8 @@
const int8_t *sampleData = &song->sampleData[s->offset];
const uint32_t sampleLength = s->length;
- const uint32_t loopStart = s->loopStart & 0xFFFE;
- const uint32_t loopLength = s->loopLength & 0xFFFE;
+ const uint32_t loopStart = s->loopStart & ~1;
+ const uint32_t loopLength = s->loopLength & ~1;
switch (diskop.smpSaveType)
{
--- a/src/pt2_sampler.c
+++ b/src/pt2_sampler.c
@@ -55,7 +55,7 @@
moduleSample_t *s = &song->samples[editor.currSample];
- uint32_t newLength = (s->length >> 1) & 0xFFFE;
+ int32_t newLength = (s->length >> 1) & config.maxSampleLength;
if (newLength < 2)
return;
@@ -63,16 +63,16 @@
// upsample
int8_t *ptr8 = &song->sampleData[s->offset];
- for (uint32_t i = 0; i < newLength; i++)
+ for (int32_t i = 0; i < newLength; i++)
ptr8[i] = ptr8[i << 1];
// clear junk after shrunk sample
- if (newLength < MAX_SAMPLE_LEN)
- memset(&ptr8[newLength], 0, MAX_SAMPLE_LEN - newLength);
+ if (newLength < config.maxSampleLength)
+ memset(&ptr8[newLength], 0, config.maxSampleLength - newLength);
- s->length = (uint16_t)newLength;
- s->loopStart = (s->loopStart >> 1) & 0xFFFE;
- s->loopLength = (s->loopLength >> 1) & 0xFFFE;
+ s->length = newLength;
+ s->loopStart = (s->loopStart >> 1) & ~1;
+ s->loopLength = (s->loopLength >> 1) & ~1;
if (s->loopLength < 2)
{
@@ -97,9 +97,9 @@
moduleSample_t *s = &song->samples[editor.currSample];
- uint32_t newLength = s->length << 1;
- if (newLength > MAX_SAMPLE_LEN)
- newLength = MAX_SAMPLE_LEN;
+ int32_t newLength = s->length << 1;
+ if (newLength > config.maxSampleLength)
+ newLength = config.maxSampleLength;
turnOffVoices();
@@ -113,12 +113,12 @@
ptr8_2[i<<1] = ptr8_2[i];
}
- s->length = (uint16_t)newLength;
+ s->length = newLength;
if (s->loopLength > 2)
{
- uint32_t loopStart = s->loopStart << 1;
- uint32_t loopLength = s->loopLength << 1;
+ int32_t loopStart = s->loopStart << 1;
+ int32_t loopLength = s->loopLength << 1;
if (loopStart+loopLength > s->length)
{
@@ -126,8 +126,8 @@
loopLength = 2;
}
- s->loopStart = (uint16_t)loopStart;
- s->loopLength = (uint16_t)loopLength;
+ s->loopStart = loopStart;
+ s->loopLength = loopLength;
}
fixSampleBeep(s);
@@ -372,7 +372,7 @@
}
// render sample data
- if (sampler.samDisplay >= 0 && sampler.samDisplay <= MAX_SAMPLE_LEN)
+ if (sampler.samDisplay >= 0 && sampler.samDisplay <= config.maxSampleLength)
{
y1 = SAMPLE_AREA_Y_CENTER - getScaledSample(scr2SmpPos(0));
@@ -426,10 +426,21 @@
return;
// render "sample display" text
- if (sampler.samStart == sampler.blankSample)
- printFiveDecimalsBg(272, 214, 0, video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
+
+ if (config.maxSampleLength == 0xFFFE)
+ {
+ if (sampler.samStart == sampler.blankSample)
+ printFiveDecimalsBg(272, 214, 0, video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
+ else
+ printFiveDecimalsBg(272, 214, sampler.samDisplay, video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
+ }
else
- printFiveDecimalsBg(272, 214, sampler.samDisplay, video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
+ {
+ if (sampler.samStart == sampler.blankSample)
+ printSixDecimalsBg(270, 214, 0, video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
+ else
+ printSixDecimalsBg(270, 214, sampler.samDisplay, video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
+ }
setDragBar();
setLoopSprites();
@@ -745,12 +756,12 @@
{
memcpy(&song->sampleData[s->offset], editor.smpRedoBuffer[sample], editor.smpRedoLengths[sample]);
- if (editor.smpRedoLengths[sample] < MAX_SAMPLE_LEN)
- memset(&song->sampleData[s->offset + editor.smpRedoLengths[sample]], 0, MAX_SAMPLE_LEN - editor.smpRedoLengths[sample]);
+ if (editor.smpRedoLengths[sample] < config.maxSampleLength)
+ memset(&song->sampleData[s->offset + editor.smpRedoLengths[sample]], 0, config.maxSampleLength - editor.smpRedoLengths[sample]);
}
else
{
- memset(&song->sampleData[s->offset], 0, MAX_SAMPLE_LEN);
+ memset(&song->sampleData[s->offset], 0, config.maxSampleLength);
}
s->fineTune = editor.smpRedoFinetunes[sample];
@@ -804,8 +815,8 @@
bool allocSamplerVars(void)
{
- sampler.copyBuf = (int8_t *)malloc(MAX_SAMPLE_LEN);
- sampler.blankSample = (int8_t *)calloc(MAX_SAMPLE_LEN, 1);
+ sampler.copyBuf = (int8_t *)malloc(131070);
+ sampler.blankSample = (int8_t *)calloc(131070, 1);
if (sampler.copyBuf == NULL || sampler.blankSample == NULL)
return false;
@@ -903,9 +914,9 @@
#define INTRP_LINEAR_TAPS 2
#define INTRP8_LINEAR(s1, s2, f) /* output: -127..128 */ \
s2 -= s1; \
- s2 *= (int32_t)(f); \
+ s2 *= (int32_t)(f >> 16); \
s1 <<= 8; \
- s2 >>= (16 - 8); \
+ s2 >>= 16-8; \
s1 += s2; \
s1 >>= 8; \
@@ -916,7 +927,7 @@
int16_t refPeriod, newPeriod;
int32_t samples[INTRP_LINEAR_TAPS], i, pos, readPos, writePos;
int32_t readLength, writeLength, loopStart, loopLength;
- uint32_t posFrac, delta;
+ uint64_t frac64, delta64;
moduleSample_t *s;
if (editor.sampleZero)
@@ -962,18 +973,18 @@
return;
}
- delta = ((uint32_t)readLength << 16) / (uint32_t)writeLength;
- assert(delta != 0);
+ delta64 = ((uint64_t)readLength << 32) / writeLength;
+ assert(delta64 != 0);
- writeLength = writeLength & 0xFFFFFFFE;
- if (writeLength > MAX_SAMPLE_LEN)
- writeLength = MAX_SAMPLE_LEN;
+ writeLength = writeLength & ~1;
+ if (writeLength > config.maxSampleLength)
+ writeLength = config.maxSampleLength;
memcpy(readData, writeData, readLength);
// resample
- posFrac = 0;
+ frac64 = 0;
turnOffVoices();
while (writePos < writeLength)
@@ -988,28 +999,28 @@
samples[i] = readData[pos];
}
- INTRP8_LINEAR(samples[0], samples[1], posFrac);
+ INTRP8_LINEAR(samples[0], samples[1], frac64);
writeData[writePos++] = (int8_t)samples[0];
- posFrac += delta;
- readPos += posFrac >> 16;
- posFrac &= 0xFFFF;
+ frac64 += delta64;
+ readPos += frac64 >> 32;
+ frac64 &= 0xFFFFFFFF;
}
free(readData);
// wipe non-used data in new sample
- if (writeLength < MAX_SAMPLE_LEN)
- memset(&writeData[writePos], 0, MAX_SAMPLE_LEN - writeLength);
+ if (writeLength < config.maxSampleLength)
+ memset(&writeData[writePos], 0, config.maxSampleLength - writeLength);
// update sample attributes
- s->length = (uint16_t)writeLength;
+ s->length = writeLength;
s->fineTune = 0;
// scale loop points (and deactivate if overflowing)
if ((s->loopStart + s->loopLength) > 2)
{
- loopStart = (int32_t)(((uint32_t)s->loopStart << 16) / delta) & 0xFFFFFFFE;
- loopLength = (int32_t)(((uint32_t)s->loopLength << 16) / delta) & 0xFFFFFFFE;
+ loopStart = (int32_t)(((uint64_t)s->loopStart << 32) / delta64) & ~1;
+ loopLength = (int32_t)(((uint64_t)s->loopLength << 32) / delta64) & ~1;
if (loopStart+loopLength > s->length)
{
@@ -1018,8 +1029,8 @@
}
else
{
- s->loopStart = (uint16_t)loopStart;
- s->loopLength = (uint16_t)loopLength;
+ s->loopStart = loopStart;
+ s->loopLength = loopLength;
}
}
@@ -1120,12 +1131,12 @@
}
memcpy(&song->sampleData[s3->offset], mixPtr, mixLength);
- if (mixLength < MAX_SAMPLE_LEN)
- memset(&song->sampleData[s3->offset + mixLength], 0, MAX_SAMPLE_LEN - mixLength);
+ if (mixLength < config.maxSampleLength)
+ memset(&song->sampleData[s3->offset + mixLength], 0, config.maxSampleLength - mixLength);
free(mixPtr);
- s3->length = (uint16_t)mixLength;
+ s3->length = mixLength;
s3->volume = 64;
s3->fineTune = 0;
s3->loopStart = 0;
@@ -1308,7 +1319,7 @@
}
invertRange();
- editor.samplePos = (uint16_t)editor.markEndOfs;
+ editor.samplePos = editor.markEndOfs;
}
updateSamplePos();
@@ -1347,7 +1358,7 @@
}
invertRange();
- editor.samplePos = (uint16_t)editor.markEndOfs;
+ editor.samplePos = editor.markEndOfs;
}
updateSamplePos();
@@ -1380,7 +1391,7 @@
}
invertRange();
- editor.samplePos = (uint16_t)editor.markEndOfs;
+ editor.samplePos = editor.markEndOfs;
}
updateSamplePos();
@@ -1419,7 +1430,7 @@
sampler.copyBufSize = editor.markEndOfs - editor.markStartOfs;
- if ((int32_t)(editor.markStartOfs + sampler.copyBufSize) > MAX_SAMPLE_LEN)
+ if ((int32_t)(editor.markStartOfs + sampler.copyBufSize) > config.maxSampleLength)
{
displayErrorMsg("COPY ERROR !");
return;
@@ -1471,7 +1482,7 @@
// if whole sample is marked, wipe it
if (editor.markEndOfs-editor.markStartOfs >= sampleLength)
{
- memset(&song->sampleData[s->offset], 0, MAX_SAMPLE_LEN);
+ memset(&song->sampleData[s->offset], 0, config.maxSampleLength);
invertRange();
editor.markStartOfs = -1;
@@ -1497,7 +1508,7 @@
markStart = editor.markStartOfs;
copyLength = (editor.markStartOfs + sampleLength) - markEnd;
- if (copyLength < 2 || copyLength > MAX_SAMPLE_LEN)
+ if (copyLength < 2 || copyLength > config.maxSampleLength)
{
displayErrorMsg("SAMPLE CUT FAIL !");
return;
@@ -1520,8 +1531,8 @@
// nuke sample data and copy over the result
memcpy(&song->sampleData[s->offset], tmpBuf, copyLength);
- if (copyLength < MAX_SAMPLE_LEN)
- memset(&song->sampleData[s->offset+copyLength], 0, MAX_SAMPLE_LEN - copyLength);
+ if (copyLength < config.maxSampleLength)
+ memset(&song->sampleData[s->offset+copyLength], 0, config.maxSampleLength - copyLength);
free(tmpBuf);
@@ -1556,11 +1567,11 @@
if (markStart < s->loopStart+s->loopLength)
{
// we cut data inside the loop, increase loop length
- val32 = (s->loopLength - (markEnd - markStart)) & 0xFFFFFFFE;
+ val32 = (s->loopLength - (markEnd - markStart)) & ~1;
if (val32 < 2)
val32 = 2;
- s->loopLength = (uint16_t)val32;
+ s->loopLength = val32;
}
// we cut data after the loop, don't modify loop points
@@ -1568,7 +1579,7 @@
else
{
// we cut data before the loop, adjust loop start point
- val32 = (s->loopStart - (markEnd - markStart)) & 0xFFFFFFFE;
+ val32 = (s->loopStart - (markEnd - markStart)) & ~1;
if (val32 < 0)
{
s->loopStart = 0;
@@ -1576,12 +1587,12 @@
}
else
{
- s->loopStart = (uint16_t)val32;
+ s->loopStart = val32;
}
}
}
- s->length = copyLength & 0xFFFE;
+ s->length = copyLength & ~1;
if (sampler.samDisplay <= 2)
{
@@ -1604,7 +1615,7 @@
invertRange();
}
- editor.samplePos = (uint16_t)editor.markStartOfs;
+ editor.samplePos = editor.markStartOfs;
fixSampleBeep(s);
updateSamplePos();
recalcChordLength();
@@ -1651,13 +1662,13 @@
if (s->length == 0)
markStart = 0;
- if (s->length+sampler.copyBufSize > MAX_SAMPLE_LEN)
+ if (s->length+sampler.copyBufSize > config.maxSampleLength)
{
displayErrorMsg("NOT ENOUGH ROOM");
return;
}
- tmpBuf = (int8_t *)malloc(MAX_SAMPLE_LEN);
+ tmpBuf = (int8_t *)malloc(config.maxSampleLength);
if (tmpBuf == NULL)
{
statusOutOfMemory();
@@ -1687,11 +1698,11 @@
memcpy(&tmpBuf[readPos], &song->sampleData[s->offset+markStart], s->length - markStart);
}
- int32_t newLength = (s->length + sampler.copyBufSize) & 0xFFFFFFFE;
- if (newLength > MAX_SAMPLE_LEN)
- newLength = MAX_SAMPLE_LEN;
+ int32_t newLength = (s->length + sampler.copyBufSize) & ~1;
+ if (newLength > config.maxSampleLength)
+ newLength = config.maxSampleLength;
- sampler.samLength = s->length = (uint16_t)newLength;
+ sampler.samLength = s->length = newLength;
if (s->loopLength > 2) // loop enabled?
{
@@ -1701,7 +1712,7 @@
{
// we pasted data inside the loop, increase loop length
- if (s->loopLength+sampler.copyBufSize > MAX_SAMPLE_LEN)
+ if (s->loopLength+sampler.copyBufSize > config.maxSampleLength)
{
s->loopStart = 0;
s->loopLength = 2;
@@ -1708,7 +1719,7 @@
}
else
{
- s->loopLength = (uint16_t)(s->loopLength + sampler.copyBufSize) & 0xFFFE;
+ s->loopLength = (s->loopLength + sampler.copyBufSize) & config.maxSampleLength;
if (s->loopStart+s->loopLength > s->length)
{
s->loopStart = 0;
@@ -1722,7 +1733,7 @@
else
{
// we pasted data before the loop, adjust loop start point
- if (s->loopStart+sampler.copyBufSize > MAX_SAMPLE_LEN)
+ if (s->loopStart+sampler.copyBufSize > config.maxSampleLength)
{
s->loopStart = 0;
s->loopLength = 2;
@@ -1729,7 +1740,7 @@
}
else
{
- s->loopStart = (uint16_t)(s->loopStart + sampler.copyBufSize) & 0xFFFE;
+ s->loopStart = (s->loopStart + sampler.copyBufSize) & config.maxSampleLength;
if (s->loopStart+s->loopLength > s->length)
{
s->loopStart = 0;
@@ -1742,8 +1753,8 @@
memcpy(&song->sampleData[s->offset], tmpBuf, s->length);
// clear data after sample's length (if present)
- if (s->length < MAX_SAMPLE_LEN)
- memset(&song->sampleData[s->offset+s->length], 0, MAX_SAMPLE_LEN - s->length);
+ if (s->length < config.maxSampleLength)
+ memset(&song->sampleData[s->offset+s->length], 0, config.maxSampleLength - s->length);
free(tmpBuf);
@@ -1786,9 +1797,9 @@
if (playWaveformFlag)
{
ch->n_start = &song->sampleData[s->offset];
- ch->n_length = (s->loopStart > 0) ? (uint32_t)(s->loopStart + s->loopLength) >> 1 : s->length >> 1;
+ ch->n_length = (uint16_t)((s->loopStart > 0) ? (s->loopStart + s->loopLength) >> 1 : s->length >> 1);
ch->n_loopstart = &song->sampleData[s->offset + s->loopStart];
- ch->n_replen = s->loopLength >> 1;
+ ch->n_replen = (uint16_t)(s->loopLength >> 1);
}
else
{
@@ -2357,9 +2368,9 @@
{
sampler.lastMouseX = mouseX;
- tmpPos = (scr2SmpPos(mouseX - 1) - s->loopStart) & 0xFFFFFFFE;
- if (tmpPos > MAX_SAMPLE_LEN)
- tmpPos = MAX_SAMPLE_LEN;
+ tmpPos = (scr2SmpPos(mouseX - 1) - s->loopStart) & ~1;
+ if (tmpPos > config.maxSampleLength)
+ tmpPos = config.maxSampleLength;
if (s->loopStart+tmpPos >= (s->loopStart+s->loopLength)-2)
{
@@ -2368,10 +2379,10 @@
}
else
{
- s->loopStart = (uint16_t)(s->loopStart + tmpPos);
+ s->loopStart = s->loopStart + tmpPos;
if (s->loopLength-tmpPos > 2)
- s->loopLength -= (uint16_t)tmpPos;
+ s->loopLength -= tmpPos;
else
s->loopLength = 2;
}
@@ -2395,10 +2406,10 @@
s = &song->samples[editor.currSample];
- tmpPos = (scr2SmpPos(mouseX - 4) - s->loopStart) & 0xFFFFFFFE;
- tmpPos = CLAMP(tmpPos, 2, MAX_SAMPLE_LEN);
+ tmpPos = (scr2SmpPos(mouseX - 4) - s->loopStart) & ~1;
+ tmpPos = CLAMP(tmpPos, 2, config.maxSampleLength);
- s->loopLength = (uint16_t)tmpPos;
+ s->loopLength = tmpPos;
ui.updateCurrSampleRepeat = true;
ui.updateCurrSampleReplen = true;
@@ -2445,7 +2456,7 @@
if (tmpPos > s->length)
tmpPos = s->length;
- editor.samplePos = (uint16_t)tmpPos;
+ editor.samplePos = tmpPos;
}
updateSamplePos();
@@ -2457,7 +2468,7 @@
if (mouseX != sampler.lastSamPos)
{
- sampler.lastSamPos = (uint16_t)mouseX;
+ sampler.lastSamPos = mouseX;
invertRange();
if (s->length == 0)
@@ -2494,7 +2505,7 @@
if (tmpPos > s->length)
tmpPos = s->length;
- editor.samplePos = (uint16_t)tmpPos;
+ editor.samplePos = tmpPos;
}
updateSamplePos();
@@ -2539,8 +2550,8 @@
}
else
{
- s->loopStart = (uint16_t)sampler.tmpLoopStart;
- s->loopLength = (uint16_t)sampler.tmpLoopLength;
+ s->loopStart = sampler.tmpLoopStart;
+ s->loopLength = sampler.tmpLoopLength;
if (s->loopStart+s->loopLength > s->length)
{
--- a/src/pt2_sampler.h
+++ b/src/pt2_sampler.h
@@ -11,8 +11,7 @@
int16_t loopStartPos, loopEndPos;
uint16_t dragStart, dragEnd;
int32_t samPointWidth, samOffset, samDisplay, samLength, saveMouseX, lastSamPos;
- int32_t lastMouseX, lastMouseY, tmpLoopStart, tmpLoopLength;
- uint32_t copyBufSize;
+ int32_t lastMouseX, lastMouseY, tmpLoopStart, tmpLoopLength, copyBufSize;
} sampler_t;
extern sampler_t sampler; // pt2_sampler.c
--- a/src/pt2_sampling.c
+++ b/src/pt2_sampling.c
@@ -29,6 +29,7 @@
#include "pt2_config.h"
#include "pt2_sampling.h"
#include "pt2_math.h" // PT2_PI
+#include "pt2_hpc.h"
enum
{
@@ -478,6 +479,7 @@
{
changeStatusText("PLEASE WAIT ...");
flipFrame();
+ hpc_ResetEndTime(&video.vblankHpc);
editor.sampleZero = false;
editor.blockMarkFlag = false;
@@ -604,7 +606,7 @@
assert(roundedOutputFrequency > 0);
- maxSamplingLength = (int32_t)(ceil(((double)MAX_SAMPLE_LEN*inputFrequency) / dOutputFrequency)) + 1;
+ maxSamplingLength = (int32_t)(ceil(((double)config.maxSampleLength*inputFrequency) / dOutputFrequency)) + 1;
const int32_t allocLen = (SINC_TAPS/2) + maxSamplingLength + (SINC_TAPS/2);
dSamplingBufferOrig = (double *)malloc(allocLen * sizeof (double));
@@ -637,8 +639,8 @@
const double dRatio = dOutputFrequency / inputFrequency;
int32_t writeLength = (int32_t)(readLength * dRatio);
- if (writeLength > MAX_SAMPLE_LEN)
- writeLength = MAX_SAMPLE_LEN;
+ if (writeLength > config.maxSampleLength)
+ writeLength = config.maxSampleLength;
double *dBuffer = (double *)malloc(writeLength * sizeof (double));
if (dBuffer == NULL)
@@ -726,7 +728,7 @@
}
moduleSample_t *s = &song->samples[editor.currSample];
- s->length = (uint16_t)newLength;
+ s->length = newLength;
s->fineTune = samplingFinetune;
s->loopStart = 0;
s->loopLength = 2;
--- a/src/pt2_scopes.c
+++ b/src/pt2_scopes.c
@@ -11,12 +11,12 @@
#include "pt2_tables.h"
#include "pt2_structs.h"
#include "pt2_config.h"
+#include "pt2_hpc.h"
// this uses code that is not entirely thread safe, but I have never had any issues so far...
static volatile bool scopesUpdatingFlag, scopesDisplayingFlag;
-static uint32_t scopeTimeLen, scopeTimeLenFrac;
-static uint64_t timeNext64, timeNext64Frac;
+static hpc_t scopeHpc;
static SDL_Thread *scopeThread;
scope_t scope[AMIGA_VOICES]; // global
@@ -36,7 +36,7 @@
{
assert(song != NULL);
const int8_t *sampleData = song->sampleData;
- const int32_t sampleSlotSize = MAX_SAMPLE_LEN;
+ const int32_t sampleSlotSize = config.maxSampleLength;
if (sampleData == NULL) // shouldn't really happen, but just in case
return -1;
@@ -118,7 +118,7 @@
const int8_t *newData = tempState.newData;
if (newData == NULL)
- newData = &song->sampleData[RESERVED_SAMPLE_OFFSET]; // 128K reserved sample
+ newData = &song->sampleData[config.reservedSampleOffset]; // 128K reserved sample
int32_t newLength = tempState.newLength; // in bytes, not words
if (newLength < 2)
@@ -320,9 +320,8 @@
// this is needed for scope stability (confirmed)
SDL_SetThreadPriority(SDL_THREAD_PRIORITY_HIGH);
- // set next frame time
- timeNext64 = SDL_GetPerformanceCounter() + scopeTimeLen;
- timeNext64Frac = scopeTimeLenFrac;
+ hpc_SetDurationInHz(&scopeHpc, SCOPE_HZ);
+ hpc_ResetEndTime(&scopeHpc);
while (editor.programRunning)
{
@@ -331,31 +330,7 @@
updateScopes();
- uint64_t time64 = SDL_GetPerformanceCounter();
- if (time64 < timeNext64)
- {
- time64 = timeNext64 - time64;
- if (time64 > UINT32_MAX)
- time64 = UINT32_MAX;
-
- const uint32_t diff32 = (uint32_t)time64;
-
- // convert to microseconds and round to integer
- const int32_t time32 = (int32_t)((diff32 * editor.dPerfFreqMulMicro) + 0.5);
-
- // delay until we have reached the next frame
- if (time32 > 0)
- usleep(time32);
- }
-
- // update next tick time
- timeNext64 += scopeTimeLen;
- timeNext64Frac += scopeTimeLenFrac;
- if (timeNext64Frac > 0xFFFFFFFF)
- {
- timeNext64Frac &= 0xFFFFFFFF;
- timeNext64++;
- }
+ hpc_Wait(&scopeHpc);
}
(void)ptr;
@@ -364,18 +339,6 @@
bool initScopes(void)
{
- double dInt, dFrac;
-
- // calculate scope time for performance counters and split into int/frac
- dFrac = modf(editor.dPerfFreq / SCOPE_HZ, &dInt);
-
- // integer part
- scopeTimeLen = (int32_t)dInt;
-
- // fractional part (scaled to 0..2^32-1)
- dFrac *= UINT32_MAX+1.0;
- scopeTimeLenFrac = (uint32_t)dFrac;
-
resetCachedScopePeriod();
scopeThread = SDL_CreateThread(scopeThreadFunc, NULL, NULL);
--- a/src/pt2_structs.h
+++ b/src/pt2_structs.h
@@ -8,6 +8,7 @@
#include <stdint.h>
#include <stdbool.h>
#include "pt2_header.h"
+#include "pt2_hpc.h"
// for .WAV sample loading/saving
typedef struct wavHeader_t
@@ -57,12 +58,11 @@
typedef struct moduleSample_t
{
volatile int8_t *volumeDisp;
- volatile uint16_t *lengthDisp, *loopStartDisp, *loopLengthDisp;
+ volatile int32_t *lengthDisp, *loopStartDisp, *loopLengthDisp;
char text[22 + 1];
int8_t volume;
uint8_t fineTune;
- uint16_t length, loopStart, loopLength;
- int32_t offset;
+ int32_t offset, length, loopStart, loopLength;
} moduleSample_t;
typedef struct moduleChannel_t
@@ -131,6 +131,7 @@
int32_t renderX, renderY, renderW, renderH, displayW, displayH;
int32_t xScale, yScale;
float fMouseXMul, fMouseYMul;
+ hpc_t vblankHpc;
SDL_PixelFormat *pixelFormat;
uint32_t *frameBuffer, *frameBufferUnaligned;
@@ -153,7 +154,7 @@
volatile uint16_t *quantizeValueDisp, *metroSpeedDisp, *metroChannelDisp, *sampleVolDisp;
volatile uint16_t *vol1Disp, *vol2Disp, *currEditPatternDisp, *currPosDisp, *currPatternDisp;
volatile uint16_t *currPosEdPattDisp, *currLengthDisp, *lpCutOffDisp, *hpCutOffDisp;
- volatile uint16_t *samplePosDisp, *chordLengthDisp;
+ volatile int32_t *samplePosDisp, *chordLengthDisp;
char mixText[16];
char *entryNameTmp, *currPath, *dropTempFileName;
@@ -174,13 +175,12 @@
uint8_t tuningNote, resampleNote, initialTempo, initialSpeed, editMoveAdd;
int16_t modulateSpeed;
- uint16_t metroSpeed, metroChannel, sampleVol, samplePos, chordLength;
+ uint16_t metroSpeed, metroChannel, sampleVol;
uint16_t effectMacros[10], currPlayNote, vol1, vol2, lpCutOff, hpCutOff;
- uint16_t smpRedoLoopStarts[MOD_SAMPLES], smpRedoLoopLengths[MOD_SAMPLES], smpRedoLengths[MOD_SAMPLES];
- int32_t oldTempo, modulatePos, modulateOffset, markStartOfs, markEndOfs, pat2SmpPos;
- uint32_t vblankTimeLen, vblankTimeLenFrac;
+ int32_t smpRedoLoopStarts[MOD_SAMPLES], smpRedoLoopLengths[MOD_SAMPLES], smpRedoLengths[MOD_SAMPLES];
+ int32_t oldTempo, modulatePos, modulateOffset, markStartOfs, markEndOfs, pat2SmpPos, samplePos, chordLength;
uint64_t musicTime64;
- double dPerfFreq, dPerfFreqMulMicro, *dPat2SmpBuf;
+ double *dPat2SmpBuf;
note_t trackBuffer[MOD_ROWS], cmdsBuffer[MOD_ROWS], blockBuffer[MOD_ROWS];
note_t patternBuffer[MOD_ROWS * AMIGA_VOICES], undoBuffer[MOD_ROWS * AMIGA_VOICES];
SDL_Thread *mod2WavThread, *pat2SmpThread;
@@ -214,6 +214,7 @@
bool changingSamplingNote;
+ bool force32BitNumPtr;
int8_t *numPtr8, tmpDisp8, pointerMode, editOpScreen, editTextType, askScreenType;
int8_t visualizerMode, previousPointerMode, forceVolDrag, changingChordNote;
uint8_t numLen, numBits;
@@ -230,10 +231,10 @@
bool updateMixText, updatePosText, updateModText, updateVolText;
// edit op. #4 (sample chord editor)
- bool updateLengthText, updateNote1Text, updateNote2Text;
- bool updateNote3Text, updateNote4Text;
+ bool updateChordLengthText, updateChordNote1Text, updateChordNote2Text;
+ bool updateChordNote3Text, updateChordNote4Text;
- //sampler
+ // sampler
bool updateResampleNote, updateVolFromText, updateVolToText, updateLPText;
bool updateHPText, updateNormFlag, update9xxPos;
@@ -256,7 +257,7 @@
int16_t lineCurX, lineCurY, editObject, sampleMarkingPos;
uint16_t *numPtr16, tmpDisp16, *dstOffset, dstPos, textLength, editTextPos;
uint16_t dstOffsetEnd, lastSampleOffset, diskOpPathTextOffset;
- int32_t askTempData;
+ int32_t askTempData, *numPtr32, tmpDisp32;
} ui_t;
extern keyb_t keyb;
--- a/src/pt2_tables.c
+++ b/src/pt2_tables.c
@@ -265,15 +265,15 @@
{ 98, 55,108, 65, PTB_SVOLUMEU},
{109, 55,119, 65, PTB_SVOLUMED},
- { 62, 66, 97, 76, PTB_SLENGTHS},
+ { 54, 66, 97, 76, PTB_SLENGTHS},
{ 98, 66,108, 76, PTB_SLENGTHU},
{109, 66,119, 76, PTB_SLENGTHD},
- { 62, 77, 97, 87, PTB_SREPEATS},
+ { 54, 77, 97, 87, PTB_SREPEATS},
{ 98, 77,108, 87, PTB_SREPEATU},
{109, 77,119, 87, PTB_SREPEATD},
- { 62, 88, 97, 98, PTB_SREPLENS},
+ { 54, 88, 97, 98, PTB_SREPLENS},
{ 98, 88,108, 98, PTB_SREPLENU},
{109, 88,119, 98, PTB_SREPLEND}
};
@@ -395,8 +395,8 @@
{120, 55,165, 65, PTB_EO_MIX},
{166, 55,212, 65, PTB_EO_ECHO},
- {213, 55,243, 65, PTB_DUMMY},
- {244, 55,283, 65, PTB_EO_POS_NUM},
+ {213, 55,237, 65, PTB_DUMMY},
+ {238, 55,283, 65, PTB_EO_POS_NUM},
{284, 55,294, 65, PTB_EO_POS_UP},
{295, 55,305, 65, PTB_EO_POS_DOWN},
{306, 55,319, 65, PTB_EO_1},
@@ -454,8 +454,8 @@
{295, 77,305, 87, PTB_EO_NOTE3_DOWN},
{306, 77,319, 87, PTB_EO_3},
- {120, 88,157, 98, PTB_EO_LENGTH},
- {158, 88,204, 98, PTB_DUMMY},
+ {120, 88,165, 98, PTB_EO_LENGTH},
+ {166, 88,204, 98, PTB_DUMMY},
{205, 88,251, 98, PTB_EO_MINOR6},
{251, 88,283, 98, PTB_EO_NOTE4},
{284, 88,294, 98, PTB_EO_NOTE4_UP},
--- a/src/pt2_textout.h
+++ b/src/pt2_textout.h
@@ -34,11 +34,12 @@
void printFiveHex(uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor);
void printOneHexBig(uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor);
void printTwoHexBig(uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor);
-void printSixDecimals(uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor);
+
void printTwoDecimals(uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor);
+void printThreeDecimals(uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor);
void printFourDecimals(uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor);
void printFiveDecimals(uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor);
-void printThreeDecimals(uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor);
+void printSixDecimals(uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor);
void printTwoDecimalsBig(uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor);
void printOneHexBg(uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor, uint32_t backColor);
void printTwoHexBg(uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor, uint32_t backColor);
@@ -49,9 +50,9 @@
void printTwoHexBigBg(uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor, uint32_t backColor);
void printSixDecimalsBg(uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor, uint32_t backColor);
void printTwoDecimalsBg(uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor, uint32_t backColor);
+void printThreeDecimalsBg(uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor, uint32_t backColor);
void printFourDecimalsBg(uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor, uint32_t backColor);
void printFiveDecimalsBg(uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor, uint32_t backColor);
-void printThreeDecimalsBg(uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor, uint32_t backColor);
void printTwoDecimalsBigBg(uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor, uint32_t backColor);
void setPrevStatusMessage(void);
--- a/src/pt2_visuals.c
+++ b/src/pt2_visuals.c
@@ -42,6 +42,7 @@
#include "pt2_bmp.h"
#include "pt2_sampling.h"
#include "pt2_chordmaker.h"
+#include "pt2_hpc.h"
typedef struct sprite_t
{
@@ -53,7 +54,6 @@
} sprite_t;
static uint32_t vuMetersBg[4 * (10 * 48)];
-static uint64_t timeNext64, timeNext64Frac;
sprite_t sprites[SPRITE_NUM]; // globalized
@@ -200,64 +200,6 @@
displayErrorMsg("NOT SAMPLE 0 !");
}
-void setupPerfFreq(void)
-{
- uint64_t perfFreq64;
- double dInt, dFrac;
-
- perfFreq64 = SDL_GetPerformanceFrequency(); assert(perfFreq64 != 0);
- editor.dPerfFreq = (double)perfFreq64;
- editor.dPerfFreqMulMicro = 1000000.0 / editor.dPerfFreq;
-
- // calculate vblank time for performance counters and split into int/frac
- dFrac = modf(editor.dPerfFreq / VBLANK_HZ, &dInt);
-
- // integer part
- editor.vblankTimeLen = (int32_t)dInt;
-
- // fractional part (scaled to 0..2^32-1)
- dFrac *= UINT32_MAX+1.0;
- editor.vblankTimeLenFrac = (uint32_t)dFrac;
-}
-
-void setupWaitVBL(void)
-{
- // set next frame time
- timeNext64 = SDL_GetPerformanceCounter() + editor.vblankTimeLen;
- timeNext64Frac = editor.vblankTimeLenFrac;
-}
-
-void waitVBL(void)
-{
- // this routine almost never delays if we have 60Hz vsync, but it's still needed in some occasions
-
- uint64_t time64 = SDL_GetPerformanceCounter();
- if (time64 < timeNext64)
- {
- time64 = timeNext64 - time64;
- if (time64 > UINT32_MAX)
- time64 = UINT32_MAX;
-
- const uint32_t diff32 = (uint32_t)time64;
-
- // convert to microseconds and round to integer
- const int32_t time32 = (int32_t)((diff32 * editor.dPerfFreqMulMicro) + 0.5);
-
- // delay until we have reached the next frame
- if (time32 > 0)
- usleep(time32);
- }
-
- // update next tick time
- timeNext64 += editor.vblankTimeLen;
- timeNext64Frac += editor.vblankTimeLenFrac;
- if (timeNext64Frac > 0xFFFFFFFF)
- {
- timeNext64Frac &= 0xFFFFFFFF;
- timeNext64++;
- }
-}
-
void renderFrame(void)
{
updateMOD2WAVDialog(); // must be first to avoid flickering issues
@@ -491,19 +433,30 @@
{
ui.updateCurrSampleLength = false;
if (!editor.isWAVRendering)
- printFourHexBg(64, 69, *currSample->lengthDisp, video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
+ {
+ if (config.maxSampleLength == 0xFFFE)
+ printFourHexBg(64, 69, *currSample->lengthDisp, video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
+ else
+ printFiveHexBg(56, 69, *currSample->lengthDisp, video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
+ }
}
if (ui.updateCurrSampleRepeat)
{
ui.updateCurrSampleRepeat = false;
- printFourHexBg(64, 80, *currSample->loopStartDisp, video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
+ if (config.maxSampleLength == 0xFFFE)
+ printFourHexBg(64, 80, *currSample->loopStartDisp, video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
+ else
+ printFiveHexBg(56, 80, *currSample->loopStartDisp, video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
}
if (ui.updateCurrSampleReplen)
{
ui.updateCurrSampleReplen = false;
- printFourHexBg(64, 91, *currSample->loopLengthDisp, video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
+ if (config.maxSampleLength == 0xFFFE)
+ printFourHexBg(64, 91, *currSample->loopLengthDisp, video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
+ else
+ printFiveHexBg(56, 91, *currSample->loopLengthDisp, video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
}
}
@@ -712,9 +665,7 @@
{
if (!ui.samplerVolBoxShown && !ui.samplerFiltersBoxShown && s->length > 0)
{
- tmpSampleOffset = (scr2SmpPos(mouse.x-3) + (1 << 7)) >> 8; // rounded
- tmpSampleOffset = 0x900 + CLAMP(tmpSampleOffset, 0x00, 0xFF);
-
+ tmpSampleOffset = 0x900 + (scr2SmpPos(mouse.x-3) >> 8);
if (tmpSampleOffset != ui.lastSampleOffset)
{
ui.lastSampleOffset = (uint16_t)tmpSampleOffset;
@@ -727,7 +678,10 @@
if (ui.update9xxPos)
{
ui.update9xxPos = false;
- printThreeHexBg(288, 247, ui.lastSampleOffset, video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
+ if (ui.lastSampleOffset <= 0x900 || ui.lastSampleOffset > 0x9FF)
+ textOutBg(288, 247, "---", video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
+ else
+ printThreeHexBg(288, 247, ui.lastSampleOffset, video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
}
if (ui.updateResampleNote)
@@ -1239,6 +1193,15 @@
blit32(120, 44, 200, 55, srcPtr);
+ // fix graphics in 128K sample mode
+ if (config.maxSampleLength != 65534)
+ {
+ if (ui.editOpScreen == 2)
+ blit32(213, 55, 32, 11, fix128KPosBMP);
+ else if (ui.editOpScreen == 3)
+ blit32(120, 88, 48, 11, fix128KChordBMP);
+ }
+
renderEditOpMode();
// render text and content
@@ -1271,11 +1234,11 @@
{
textOut(128, 47, " SAMPLE CHORD EDITOR ", video.palette[PAL_GENTXT]);
- ui.updateLengthText = true;
- ui.updateNote1Text = true;
- ui.updateNote2Text = true;
- ui.updateNote3Text = true;
- ui.updateNote4Text = true;
+ ui.updateChordLengthText = true;
+ ui.updateChordNote1Text = true;
+ ui.updateChordNote2Text = true;
+ ui.updateChordNote3Text = true;
+ ui.updateChordNote4Text = true;
}
}
@@ -1414,7 +1377,10 @@
if (ui.updatePosText)
{
ui.updatePosText = false;
- printFourHexBg(248, 58, *editor.samplePosDisp, video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
+ if (config.maxSampleLength == 0xFFFE)
+ printFourHexBg(248, 58, *editor.samplePosDisp, video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
+ else
+ printFiveHexBg(240, 58, *editor.samplePosDisp, video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
}
if (ui.updateModText)
@@ -1438,14 +1404,18 @@
}
else if (ui.editOpScreen == 3)
{
- if (ui.updateLengthText)
+ if (ui.updateChordLengthText)
{
- ui.updateLengthText = false;
+ ui.updateChordLengthText = false;
// clear background
- textOutBg(168, 91, " ", video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
- charOut(198, 91, ':', video.palette[PAL_GENBKG]);
+ if (config.maxSampleLength != 65534)
+ textOutBg(160, 91, " ", video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
+ else
+ textOutBg(168, 91, " ", video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
+ charOut(198, 91, ':', video.palette[PAL_GENBKG]);
+
if (song->samples[editor.currSample].loopLength > 2 || song->samples[editor.currSample].loopStart >= 2)
{
textOut(168, 91, "LOOP", video.palette[PAL_GENTXT]);
@@ -1452,14 +1422,18 @@
}
else
{
- printFourHex(168, 91, *editor.chordLengthDisp, video.palette[PAL_GENTXT]); // chord max length
+ if (config.maxSampleLength == 0xFFFE)
+ printFourHex(168, 91, *editor.chordLengthDisp, video.palette[PAL_GENTXT]); // chord max length
+ else
+ printFiveHex(160, 91, *editor.chordLengthDisp, video.palette[PAL_GENTXT]); // chord max length
+
charOut(198, 91, (editor.chordLengthMin) ? '.' : ':', video.palette[PAL_GENTXT]); // min/max flag
}
}
- if (ui.updateNote1Text)
+ if (ui.updateChordNote1Text)
{
- ui.updateNote1Text = false;
+ ui.updateChordNote1Text = false;
if (editor.note1 > 35)
textOutBg(256, 58, "---", video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
else
@@ -1467,9 +1441,9 @@
video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
}
- if (ui.updateNote2Text)
+ if (ui.updateChordNote2Text)
{
- ui.updateNote2Text = false;
+ ui.updateChordNote2Text = false;
if (editor.note2 > 35)
textOutBg(256, 69, "---", video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
else
@@ -1477,9 +1451,9 @@
video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
}
- if (ui.updateNote3Text)
+ if (ui.updateChordNote3Text)
{
- ui.updateNote3Text = false;
+ ui.updateChordNote3Text = false;
if (editor.note3 > 35)
textOutBg(256, 80, "---", video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
else
@@ -1487,9 +1461,9 @@
video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
}
- if (ui.updateNote4Text)
+ if (ui.updateChordNote4Text)
{
- ui.updateNote4Text = false;
+ ui.updateChordNote4Text = false;
if (editor.note4 > 35)
textOutBg(256, 91, "---", video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
else
@@ -1524,14 +1498,26 @@
if (ui.samplerScreenShown)
{
if (!ui.diskOpScreenShown)
+ {
blit32(0, 0, 320, 121, trackerFrameBMP);
+
+ if (config.maxSampleLength != 65534)
+ blit32(1, 65, 62, 34, fix128KTrackerBMP); // fix for 128kB support mode
+ }
}
else
{
if (!ui.diskOpScreenShown)
+ {
blit32(0, 0, 320, 255, trackerFrameBMP);
+
+ if (config.maxSampleLength != 65534)
+ blit32(1, 65, 62, 34, fix128KTrackerBMP); // fix for 128kB support mode
+ }
else
+ {
blit32(0, 121, 320, 134, &trackerFrameBMP[121 * SCREEN_W]);
+ }
ui.updateSongBPM = true;
ui.updateCurrPattText = true;
@@ -1759,7 +1745,7 @@
s->loopLength = 2;
memset(s->text, 0, sizeof (s->text));
- memset(&song->sampleData[(editor.currSample * MAX_SAMPLE_LEN)], 0, MAX_SAMPLE_LEN);
+ memset(&song->sampleData[(editor.currSample * config.maxSampleLength)], 0, config.maxSampleLength);
editor.samplePos = 0;
updateCurrSample();
@@ -2121,7 +2107,8 @@
if (!video.vsync60HzPresent)
{
- waitVBL(); // we have no VSync, do crude thread sleeping to sync to ~60Hz
+ // we have no VSync, do crude thread sleeping to sync to ~60Hz
+ hpc_Wait(&video.vblankHpc);
}
else
{
@@ -2131,14 +2118,14 @@
#ifdef __APPLE__
// macOS: VSync gets disabled if the window is 100% covered by another window. Let's add a (crude) fix:
if (minimized || !(windowFlags & SDL_WINDOW_INPUT_FOCUS))
- waitVBL();
+ hpc_Wait(&video.vblankHpc);
#elif __unix__
// *NIX: VSync gets disabled in fullscreen mode (at least on some distros/systems). Let's add a fix:
if (minimized || video.fullscreen)
- waitVBL();
+ hpc_Wait(&video.vblankHpc);
#else
if (minimized)
- waitVBL();
+ hpc_Wait(&video.vblankHpc);
#endif
}
}
--- a/src/pt2_visuals.h
+++ b/src/pt2_visuals.h
@@ -3,6 +3,7 @@
#include <stdint.h>
#include <stdbool.h>
#include "pt2_header.h"
+#include "pt2_hpc.h"
enum
{
@@ -35,9 +36,6 @@
void statusNotSampleZero(void);
void changeStatusText(const char *text);
-void setupPerfFreq(void);
-void setupWaitVBL(void);
-void waitVBL(void);
void resetAllScreens(void);
void handleAskNo(void);
void handleAskYes(void);
--- a/vs2019_project/pt2-clone/protracker.ini
+++ b/vs2019_project/pt2-clone/protracker.ini
@@ -11,6 +11,25 @@
; ENTRY=VALUE (only strings can have spaces!)
;
+[SAMPLE LENGTH LIMIT]
+; Limit samples to 64kB (65534/$FFFE), like intended in ProTracker
+; Syntax: TRUE or FALSE
+; Default value: TRUE
+; Comment: Setting it to FALSE will remove the 64kB (65534/$FFFE) sample
+; length limit and support 128kB samples (131070/$1FFFE).
+; Keep in mind that >64kB samples are not officially supported in most
+; ProTracker trackers and replayers, and will often result in bugs.
+;
+; CAUTION: The 9xx command (Set Sample Offset) doesn't work at all if
+; the sample length is above 65534/$FFFE. This is a known bug
+; in all ProTracker versions. I am not fixing this bug as I
+; want to keep the ProTracker 2.3D replayer quirks.
+;
+; Please do not change this setting unless you're aware of the problems
+; you might face when creating >64k-sample PT MODs!
+;
+64K_LIMIT=TRUE
+
[VIDEO SETTINGS]
; Video scaling factor
; Syntax: 1X, 2X, 3X ... 9X
--- a/vs2019_project/pt2-clone/pt2-clone.vcxproj
+++ b/vs2019_project/pt2-clone/pt2-clone.vcxproj
@@ -246,6 +246,7 @@
<ClInclude Include="..\..\src\pt2_edit.h" />
<ClInclude Include="..\..\src\pt2_header.h" />
<ClInclude Include="..\..\src\pt2_helpers.h" />
+ <ClInclude Include="..\..\src\pt2_hpc.h" />
<ClInclude Include="..\..\src\pt2_keyboard.h" />
<ClInclude Include="..\..\src\pt2_ledfilter.h" />
<ClInclude Include="..\..\src\pt2_math.h" />
@@ -297,6 +298,7 @@
<ClCompile Include="..\..\src\pt2_diskop.c" />
<ClCompile Include="..\..\src\pt2_edit.c" />
<ClCompile Include="..\..\src\pt2_helpers.c" />
+ <ClCompile Include="..\..\src\pt2_hpc.c" />
<ClCompile Include="..\..\src\pt2_keyboard.c" />
<ClCompile Include="..\..\src\pt2_ledfilter.c" />
<ClCompile Include="..\..\src\pt2_main.c" />
--- a/vs2019_project/pt2-clone/pt2-clone.vcxproj.filters
+++ b/vs2019_project/pt2-clone/pt2-clone.vcxproj.filters
@@ -105,6 +105,9 @@
<ClInclude Include="..\..\src\pt2_math.h">
<Filter>headers</Filter>
</ClInclude>
+ <ClInclude Include="..\..\src\pt2_hpc.h">
+ <Filter>headers</Filter>
+ </ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\src\pt2_audio.c" />
@@ -194,6 +197,7 @@
<ClCompile Include="..\..\src\pt2_chordmaker.c" />
<ClCompile Include="..\..\src\pt2_downsample2x.c" />
<ClCompile Include="..\..\src\pt2_math.c" />
+ <ClCompile Include="..\..\src\pt2_hpc.c" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="..\..\src\pt2-clone.rc" />