ref: f8c0ccfded8a6d486a63061a31e39156332a21c7
parent: f1d002c3f3a0e7792aca42f6731899d8cba02f50
author: Olav Sørensen <[email protected]>
date: Wed May 13 08:52:16 EDT 2020
Pushed v1.24 code - Fixed a bug with saving looping 16-bit samples as .RAW/.IFF/.WAV. Two sample points somewhere in the waveform would be set to wrong values. - Linux: Fixed the mouse not working with KMSDRM (hopefully)
--- a/src/ft2_header.h
+++ b/src/ft2_header.h
@@ -12,7 +12,7 @@
#endif
#include "ft2_replayer.h"
-#define PROG_VER_STR "1.23"
+#define PROG_VER_STR "1.24"
// do NOT change these! It will only mess things up...
--- a/src/ft2_mouse.c
+++ b/src/ft2_mouse.c
@@ -784,8 +784,8 @@
void updateMouseScaling(void)
{
- if (video.renderW > 0.0) video.dMouseXMul = (double)SCREEN_W / video.renderW;
- if (video.renderH > 0.0) video.dMouseYMul = (double)SCREEN_H / video.renderH;
+ if (video.renderW > 0.0) video.fMouseXMul = (float)SCREEN_W / video.renderW;
+ if (video.renderH > 0.0) video.fMouseYMul = (float)SCREEN_H / video.renderH;
}
void readMouseXY(void)
@@ -801,7 +801,10 @@
return;
}
- mouse.buttonState = SDL_GetGlobalMouseState(&mx, &my);
+ if (video.useDesktopMouseCoords)
+ mouse.buttonState = SDL_GetGlobalMouseState(&mx, &my);
+ else
+ mouse.buttonState = SDL_GetMouseState(&mx, &my);
if (video.fullscreen)
{
@@ -848,7 +851,7 @@
my -= video.renderY;
}
}
- else
+ else if (video.useDesktopMouseCoords)
{
// convert desktop coords to window coords
@@ -860,8 +863,8 @@
}
// multiply coords by video upscaling factors (don't round)
- mouse.x = (int32_t)(mx * video.dMouseXMul);
- mouse.y = (int32_t)(my * video.dMouseYMul);
+ mouse.x = (int32_t)(mx * video.fMouseXMul);
+ mouse.y = (int32_t)(my * video.fMouseYMul);
if (config.specialFlags2 & HARDWARE_MOUSE)
{
--- a/src/ft2_sample_ed.c
+++ b/src/ft2_sample_ed.c
@@ -76,7 +76,7 @@
if (len < 2)
return;
- len /= 2;
+ len >>= 1;
ptr16 = (int16_t *)s->pek;
// write new values
@@ -112,8 +112,8 @@
if (s->repL < 2)
return;
- loopStart = s->repS / 2;
- loopEnd = (s->repS + s->repL) / 2;
+ loopStart = s->repS >> 1;
+ loopEnd = (s->repS + s->repL) >> 1;
ptr16 = (int16_t *)s->pek;
@@ -163,8 +163,8 @@
if (s->repL < 2)
return;
- loopStart = s->repS / 2;
- loopLen = s->repL/ 2;
+ loopStart = s->repS >> 1;
+ loopLen = s->repL >> 1;
loopEnd = loopStart + loopLen;
ptr16 = (int16_t *)s->pek;
@@ -229,7 +229,7 @@
assert(s->pek != NULL);
s->fixed = false;
- // clear pre-start bytes
+ // clear pre-start bytes (this is safe, we have allocated room on the left for this)
s->pek[-4] = 0;
s->pek[-3] = 0;
s->pek[-2] = 0;
--- a/src/ft2_sample_saver.c
+++ b/src/ft2_sample_saver.c
@@ -54,7 +54,7 @@
// used to restore mixer interpolation fix .RAW/.IFF/.WAV files after save
static bool fileRestoreSampleData(UNICHAR *filenameU, int32_t sampleDataOffset, sampleTyp *smp)
{
- int8_t fixSpar8;
+ int8_t fixedSmp;
FILE *f;
if (!smp->fixed)
@@ -67,15 +67,15 @@
if (smp->typ & 16)
{
// 16-bit sample
- if (smp->fixedPos < smp->len/2)
+ if (smp->fixedPos < smp->len)
{
- fseek(f, sampleDataOffset + (smp->fixedPos * 2), SEEK_SET);
+ fseek(f, sampleDataOffset + smp->fixedPos, SEEK_SET);
fwrite(&smp->fixedSmp1, sizeof (int16_t), 1, f);
}
- if (smp->fixedPos+2 < smp->len/2)
+ if (smp->fixedPos+2 < smp->len)
{
- fseek(f, sampleDataOffset + ((smp->fixedPos + 2) * 2), SEEK_SET);
+ fseek(f, sampleDataOffset + (smp->fixedPos + 2), SEEK_SET);
fwrite(&smp->fixedSmp2, sizeof (int16_t), 1, f);
}
}
@@ -86,11 +86,11 @@
{
fseek(f, sampleDataOffset + smp->fixedPos, SEEK_SET);
- fixSpar8 = (int8_t)smp->fixedSmp1;
+ fixedSmp = (int8_t)smp->fixedSmp1;
if (editor.sampleSaveMode == SMP_SAVE_MODE_WAV) // on 8-bit WAVs the sample data is unsigned
- fixSpar8 ^= 0x80;
+ fixedSmp ^= 0x80;
- fwrite(&fixSpar8, sizeof (int8_t), 1, f);
+ fwrite(&fixedSmp, sizeof (int8_t), 1, f);
}
if (smp->fixedPos+1 < smp->len)
@@ -97,11 +97,11 @@
{
fseek(f, sampleDataOffset + (smp->fixedPos + 1), SEEK_SET);
- fixSpar8 = (int8_t)smp->fixedSmp2;
+ fixedSmp = (int8_t)smp->fixedSmp2;
if (editor.sampleSaveMode == SMP_SAVE_MODE_WAV) // on 8-bit WAVs the sample data is unsigned
- fixSpar8 ^= 0x80;
+ fixedSmp ^= 0x80;
- fwrite(&fixSpar8, sizeof (int8_t), 1, f);
+ fwrite(&fixedSmp, sizeof (int8_t), 1, f);
}
}
@@ -181,6 +181,17 @@
fwrite(&value, sizeof (int16_t), 1, f);
}
+static void iffWriteUint8(FILE *f, const uint8_t value)
+{
+ fwrite(&value, sizeof (int8_t), 1, f);
+}
+
+static void iffWriteChunkData(FILE *f, const void *data, size_t length)
+{
+ fwrite(data, sizeof (int8_t), length, f);
+ if (length & 1) fputc(0, f); // write pad byte if chunk size is uneven
+}
+
static bool saveIFFSample(UNICHAR *filenameU, bool saveRangedData)
{
char *smpNamePtr;
@@ -239,12 +250,11 @@
// samplesPerSec
tmp32 = getSampleMiddleCRate(smp);
- if (tmp32 == 0 || tmp32 > 65535)
- tmp32 = 16726;
- iffWriteUint16(f, tmp32 & 0xFFFF);
+ if (tmp32 == 0 || tmp32 > 65535) tmp32 = 16726;
+ iffWriteUint16(f, (uint16_t)tmp32);
- fputc(1, f); // ctOctave (number of samples)
- fputc(0, f); // sCompression
+ iffWriteUint8(f, 1); // ctOctave (number of samples)
+ iffWriteUint8(f, 0); // sCompression
iffWriteUint32(f, smp->vol * 1024); // volume (max: 65536/0x10000)
// "NAME" chunk
@@ -268,38 +278,33 @@
}
}
- if (smpNameLen > 0)
+ // "NAME" chunk
+ chunkLen = smpNameLen;
+ if (chunkLen > 0)
{
- chunkLen = smpNameLen;
iffWriteChunkHeader(f, "NAME", chunkLen);
- fwrite(smpNamePtr, 1, chunkLen, f);
- if (chunkLen & 1) fputc(0, f); // write pad byte if chunk size is uneven
+ iffWriteChunkData(f, smpNamePtr, chunkLen);
}
// "ANNO" chunk (we put the program name here)
- if (PROG_NAME_STR[0] != '\0')
- {
- chunkLen = sizeof (PROG_NAME_STR) - 1;
- iffWriteChunkHeader(f, "ANNO", chunkLen);
- fwrite(PROG_NAME_STR, 1, chunkLen, f);
- if (chunkLen & 1) fputc(0, f); // write pad byte if chunk size is uneven
- }
+ chunkLen = sizeof (PROG_NAME_STR) - 1;
+ iffWriteChunkHeader(f, "ANNO", chunkLen);
+ iffWriteChunkData(f, PROG_NAME_STR, chunkLen);
// "BODY" chunk
chunkLen = sampleLen;
iffWriteChunkHeader(f, "BODY", chunkLen);
sampleDataPos = ftell(f);
- fwrite(samplePtr, 1, chunkLen, f);
- if (chunkLen & 1) fputc(0, f); // write pad byte if chunk size is uneven
+ iffWriteChunkData(f, samplePtr, chunkLen);
// go back and fill in "FORM" chunk size
- tmp32 = ftell(f) - 8;
+ chunkLen = ftell(f) - 8;
fseek(f, 4, SEEK_SET);
- iffWriteUint32(f, tmp32);
+ iffWriteUint32(f, chunkLen);
fclose(f);
- // restore mixer interpolation fix
+ // restore interpolation sample fix (was used for audio mixer)
fileRestoreSampleData(filenameU, sampleDataPos, smp);
editor.diskOpReadDir = true; // force diskop re-read
@@ -395,7 +400,7 @@
samplerChunk.chunkID = 0x6C706D73; // "smpl"
samplerChunk.chunkSize = sizeof (samplerChunk) - 4 - 4;
samplerChunk.dwSamplePeriod = 1000000000 / wavHeader.sampleRate;
- samplerChunk.dwMIDIUnityNote = 60; // 60 = C-4
+ samplerChunk.dwMIDIUnityNote = 60; // 60 = MIDI middle-C
samplerChunk.cSampleLoops = 1;
samplerChunk.loop.dwType = (smp->typ & 3) - 1; // 0 = forward, 1 = ping-pong
@@ -424,7 +429,7 @@
mptExtraChunk.chunkID = 0x61727478; // "xtra"
mptExtraChunk.chunkSize = sizeof (mptExtraChunk) - 4 - 4;
- mptExtraChunk.flags = 0x20; // set pan flag - used when loading .WAVs in OpenMPT
+ mptExtraChunk.flags = 0x20; // set pan flag
mptExtraChunk.defaultPan = smp->pan; // 0..255
mptExtraChunk.defaultVolume = smp->vol * 4; // 0..256
mptExtraChunk.globalVolume = 64; // 0..64
--- a/src/ft2_scopes.c
+++ b/src/ft2_scopes.c
@@ -368,12 +368,13 @@
}
// these has to be read
- tempState.active = true;
tempState.wasCleared = sc->wasCleared;
tempState.SFrq = sc->SFrq;
tempState.DFrq = sc->DFrq;
tempState.SVol = sc->SVol;
+ tempState.active = true;
+
/* Update live scope now.
** In theory it -can- be written to in the middle of a cached read,
** then the read thread writes its own non-updated cached copy back and
@@ -581,10 +582,6 @@
static int32_t SDLCALL scopeThreadFunc(void *ptr)
{
- int32_t time32;
- uint32_t diff32;
- uint64_t time64;
-
// this is needed for scope stability (confirmed)
SDL_SetThreadPriority(SDL_THREAD_PRIORITY_HIGH);
@@ -598,16 +595,19 @@
updateScopes();
editor.scopeThreadMutex = false;
- time64 = SDL_GetPerformanceCounter();
+ uint64_t time64 = SDL_GetPerformanceCounter();
if (time64 < timeNext64)
{
- assert(timeNext64-time64 <= 0xFFFFFFFFULL);
- diff32 = (uint32_t)(timeNext64 - time64);
+ time64 = timeNext64 - time64;
+ if (time64 > UINT32_MAX)
+ time64 = UINT32_MAX;
+ const uint32_t diff32 = (uint32_t)time64;
+
// convert to microseconds and round to integer
- time32 = (int32_t)((diff32 * editor.dPerfFreqMulMicro) + 0.5);
+ const int32_t time32 = (int32_t)((diff32 * editor.dPerfFreqMulMicro) + 0.5);
- // delay until we have reached next tick
+ // delay until we have reached the next frame
if (time32 > 0)
usleep(time32);
}
--- a/src/ft2_video.c
+++ b/src/ft2_video.c
@@ -743,20 +743,20 @@
void waitVBL(void)
{
// this routine almost never delays if we have 60Hz vsync, but it's still needed in some occasions
- int32_t time32;
- uint32_t diff32;
- uint64_t time64;
- time64 = SDL_GetPerformanceCounter();
+ uint64_t time64 = SDL_GetPerformanceCounter();
if (time64 < timeNext64)
{
- assert(timeNext64-time64 <= 0xFFFFFFFFULL);
- diff32 = (uint32_t)(timeNext64 - time64);
+ time64 = timeNext64 - time64;
+ if (time64 > UINT32_MAX)
+ time64 = UINT32_MAX;
+ const uint32_t diff32 = (uint32_t)time64;
+
// convert and round to microseconds
- time32 = (int32_t)((diff32 * editor.dPerfFreqMulMicro) + 0.5);
+ const int32_t time32 = (int32_t)((diff32 * editor.dPerfFreqMulMicro) + 0.5);
- // delay until we have reached next frame
+ // delay until we have reached the next frame
if (time32 > 0)
usleep(time32);
}
@@ -1029,6 +1029,12 @@
SDL_ShowCursor(SDL_TRUE);
else
SDL_ShowCursor(SDL_FALSE);
+
+ // Workaround: SDL_GetGlobalMouseState() doesn't work with KMSDRM
+ video.useDesktopMouseCoords = true;
+ const char *videoDriver = SDL_GetCurrentVideoDriver();
+ if (videoDriver != NULL && strcmp("KMSDRM", videoDriver) == 0)
+ video.useDesktopMouseCoords = false;
return true;
}
--- a/src/ft2_video.h
+++ b/src/ft2_video.h
@@ -18,7 +18,7 @@
typedef struct video_t
{
- bool fullscreen, showFPSCounter;
+ bool fullscreen, showFPSCounter, useDesktopMouseCoords;
uint32_t xScale, yScale;
uint32_t *frameBuffer, palette[PAL_NUM], vblankTimeLen, vblankTimeLenFrac;
#ifdef _WIN32
@@ -25,7 +25,8 @@
HWND hWnd;
#endif
SDL_Window *window;
- double dMonitorRefreshRate, dMouseXMul, dMouseYMul;
+ double dMonitorRefreshRate;
+ float fMouseXMul, fMouseYMul;
uint8_t upscaleFactor;
bool vsync60HzPresent, windowHidden;
int32_t renderX, renderY, renderW, renderH, displayW, displayH;