Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package schismtracker for openSUSE:Factory checked in at 2024-05-16 17:16:07 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/schismtracker (Old) and /work/SRC/openSUSE:Factory/.schismtracker.new.1880 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "schismtracker" Thu May 16 17:16:07 2024 rev:33 rq:1174379 version:20240515 Changes: -------- --- /work/SRC/openSUSE:Factory/schismtracker/schismtracker.changes 2024-05-07 18:05:12.570446543 +0200 +++ /work/SRC/openSUSE:Factory/.schismtracker.new.1880/schismtracker.changes 2024-05-16 17:18:23.278908571 +0200 @@ -1,0 +2,13 @@ +Thu May 16 06:14:41 UTC 2024 - Jan Engelhardt <jeng...@inai.de> + +- Update to release 20240515 + * XM: Improve import routines, autovibrato is now handled + properly. + * STM: More sane import for tempo, similar to OpenMPT. + * S3M: Approximate the SAx command. + * Replayer: Correct playback when a sample sustains after a + portamento. + * Replayer: Emulate IT when an instrument is triggered with a + note that does not map to any sample. + +------------------------------------------------------------------- Old: ---- schismtracker-20240503.source.tar.gz New: ---- schismtracker-20240515.source.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ schismtracker.spec ++++++ --- /var/tmp/diff_new_pack.B8wYm9/_old 2024-05-16 17:18:23.814927998 +0200 +++ /var/tmp/diff_new_pack.B8wYm9/_new 2024-05-16 17:18:23.818928143 +0200 @@ -17,13 +17,13 @@ Name: schismtracker -Version: 20240503 +Version: 20240515 Release: 0 Summary: Music editor that matches the look and feel of Impulse Tracker License: GPL-2.0-or-later Group: Productivity/Multimedia/Sound/Editors and Convertors URL: http://schismtracker.org/ -Source: https://github.com/schismtracker/schismtracker/releases/download/%version/schismtracker-%version.source.tar.gz +Source: https://github.com/schismtracker/schismtracker/releases/download/%version/%name-%version.source.tar.gz Source2: %name.desktop Patch1: schism-alsa.diff Patch2: schism-nodate.diff ++++++ schismtracker-20240503.source.tar.gz -> schismtracker-20240515.source.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/schismtracker-20240503/configure new/schismtracker-20240515/configure --- old/schismtracker-20240503/configure 2024-05-04 01:36:14.000000000 +0200 +++ new/schismtracker-20240515/configure 2024-05-15 22:03:50.000000000 +0200 @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.71 for schismtracker 20240503. +# Generated by GNU Autoconf 2.71 for schismtracker 20240515. # # # Copyright (C) 1992-1996, 1998-2017, 2020-2021 Free Software Foundation, @@ -667,8 +667,8 @@ # Identity of this package. PACKAGE_NAME='schismtracker' PACKAGE_TARNAME='schismtracker' -PACKAGE_VERSION='20240503' -PACKAGE_STRING='schismtracker 20240503' +PACKAGE_VERSION='20240515' +PACKAGE_STRING='schismtracker 20240515' PACKAGE_BUGREPORT='' PACKAGE_URL='' @@ -1460,7 +1460,7 @@ # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures schismtracker 20240503 to adapt to many kinds of systems. +\`configure' configures schismtracker 20240515 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1531,7 +1531,7 @@ if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of schismtracker 20240503:";; + short | recursive ) echo "Configuration of schismtracker 20240515:";; esac cat <<\_ACEOF @@ -1657,7 +1657,7 @@ test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -schismtracker configure 20240503 +schismtracker configure 20240515 generated by GNU Autoconf 2.71 Copyright (C) 2021 Free Software Foundation, Inc. @@ -2052,7 +2052,7 @@ This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by schismtracker $as_me 20240503, which was +It was created by schismtracker $as_me 20240515, which was generated by GNU Autoconf 2.71. Invocation command line was $ $0$ac_configure_args_raw @@ -3325,7 +3325,7 @@ # Define the identity of the package. PACKAGE='schismtracker' - VERSION='20240503' + VERSION='20240515' printf "%s\n" "#define PACKAGE \"$PACKAGE\"" >>confdefs.h @@ -8495,7 +8495,7 @@ # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by schismtracker $as_me 20240503, which was +This file was extended by schismtracker $as_me 20240515, which was generated by GNU Autoconf 2.71. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -8563,7 +8563,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config='$ac_cs_config_escaped' ac_cs_version="\\ -schismtracker config.status 20240503 +schismtracker config.status 20240515 configured by $0, generated by GNU Autoconf 2.71, with options \\"\$ac_cs_config\\" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/schismtracker-20240503/fmt/s3m.c new/schismtracker-20240515/fmt/s3m.c --- old/schismtracker-20240503/fmt/s3m.c 2024-05-04 01:36:12.000000000 +0200 +++ new/schismtracker-20240515/fmt/s3m.c 2024-05-15 22:03:47.000000000 +0200 @@ -71,6 +71,7 @@ uint8_t c; uint32_t tmplong; uint8_t b[4]; + uint8_t channel_types[32]; /* parapointers */ uint16_t para_smp[MAX_SAMPLES]; uint16_t para_pat[MAX_PATTERNS]; @@ -153,6 +154,7 @@ special = bswapLE16(special); /* channel settings */ + slurp_read(fp, channel_types, 32); for (n = 0; n < 32; n++) { /* Channel 'type': 0xFF is a disabled channel, which shows up as (--) in ST3. Any channel with the high bit set is muted. @@ -166,7 +168,7 @@ Values past 2F seem to display bits of the UI like the copyright and help, strange! These out-of-range channel types will almost certainly hang or crash ST3 or produce other strange behavior. Simply put, don't do it. :) */ - c = slurp_getc(fp); + c = channel_types[n]; if (c & 0x80) { song->channels[n].flags |= CHN_MUTE; // ST3 doesn't even play effects in muted channels -- throw them out? @@ -390,6 +392,19 @@ } else if (note->param == 0xc0) { note->effect = FX_NONE; note->param = 0; + } else if ((note->param & 0xf0) == 0xa0) { + // Convert the old messy SoundBlaster stereo control command (or an approximation of it, anyway) + uint8_t ctype = channel_types[chn] & 0x7f; + if (gus_addresses > 1 || ctype >= 0x10) + note->effect = FX_NONE; + else if (note->param == 0xa0 || note->param == 0xa2) // Normal panning + note->param = (ctype & 8) ? 0x8c : 0x83; + else if (note->param == 0xa1 || note->param == 0xa3) // Swap left / right channel + note->param = (ctype & 8) ? 0x83 : 0x8c; + else if (note->param <= 0xa7) // Center + note->param = 0x88; + else + note->effect = FX_NONE; } } } @@ -414,7 +429,10 @@ ? "ModPlug Tracker / OpenMPT 1.17" : "ModPlug Tracker 1.0 alpha"; } else if (special == 0 && uc == 0 && flags == 0 && misc == (S3M_UNSIGNED)) { - tid = "Velvet Studio"; + if (song->initial_global_volume == 128 && mix_volume == 48) + tid = "PlayerPRO"; + else // Always stereo + tid = "Velvet Studio"; } else if (uc != 16 && uc != 24 && uc != 32) { // sure isn't scream tracker tid = "Unknown tracker"; @@ -436,7 +454,10 @@ strcpy(song->tracker_id, "Unknown tracker"); break; case 2: - tid = "Imago Orpheus %d.%02x"; + if (trkvers == 0x2013) // PlayerPRO on Intel forgets to byte-swap the tracker ID bytes + strcpy(song->tracker_id, "PlayerPRO"); + else + tid = "Imago Orpheus %d.%02x"; break; case 3: if (trkvers <= 0x3214) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/schismtracker-20240503/fmt/stm.c new/schismtracker-20240515/fmt/stm.c --- old/schismtracker-20240503/fmt/stm.c 2024-05-04 01:36:12.000000000 +0200 +++ new/schismtracker-20240515/fmt/stm.c 2024-05-15 22:03:47.000000000 +0200 @@ -56,6 +56,35 @@ /* --------------------------------------------------------------------- */ +// calculated using this formula from OpenMPT +// (i range 1-15, j range 0-15); +// unsigned int st2MixingRate = 23863; +// const unsigned char tempo_table[18] = {140, 50, 25, 15, 10, 7, 6, 4, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1}; +// long double samplesPerTick = (double) st2MixingRate / ((long double) 50 - ((tempo_table[high_nibble] * low_nibble) / 16)); +// st2MixingRate *= 5; // normally multiplied by the precision beyond the decimal point, however there's no decimal place here. :P +// st2MixingRate += samplesPerTick; +// st2MixingRate = (st2MixingRate >= 0) +// ? (int32_t) (st2MixingRate / (samplesPerTick * 2)) +// : (int32_t)((st2MixingRate - ((samplesPerTick * 2) - 1)) / (samplesPerTick * 2)); +static unsigned int tempo_table[15][16] = { + { 125, 117, 110, 102, 95, 87, 80, 72, 62, 55, 47, 40, 32, 25, 17, 10, }, + { 125, 122, 117, 115, 110, 107, 102, 100, 95, 90, 87, 82, 80, 75, 72, 67, }, + { 125, 125, 122, 120, 117, 115, 112, 110, 107, 105, 102, 100, 97, 95, 92, 90, }, + { 125, 125, 122, 122, 120, 117, 117, 115, 112, 112, 110, 110, 107, 105, 105, 102, }, + { 125, 125, 125, 122, 122, 120, 120, 117, 117, 117, 115, 115, 112, 112, 110, 110, }, + { 125, 125, 125, 122, 122, 122, 120, 120, 117, 117, 117, 115, 115, 115, 112, 112, }, + { 125, 125, 125, 125, 122, 122, 122, 122, 120, 120, 120, 120, 117, 117, 117, 117, }, + { 125, 125, 125, 125, 125, 125, 122, 122, 122, 122, 122, 120, 120, 120, 120, 120, }, + { 125, 125, 125, 125, 125, 125, 122, 122, 122, 122, 122, 120, 120, 120, 120, 120, }, + { 125, 125, 125, 125, 125, 125, 125, 125, 122, 122, 122, 122, 122, 122, 122, 122, }, + { 125, 125, 125, 125, 125, 125, 125, 125, 122, 122, 122, 122, 122, 122, 122, 122, }, + { 125, 125, 125, 125, 125, 125, 125, 125, 122, 122, 122, 122, 122, 122, 122, 122, }, + { 125, 125, 125, 125, 125, 125, 125, 125, 122, 122, 122, 122, 122, 122, 122, 122, }, + { 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, }, + { 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, }, +}; + + #pragma pack(push, 1) struct stm_sample { char name[12]; @@ -86,10 +115,28 @@ // KLMNO can be entered in the editor but don't do anything }; +static uint8_t handle_tempo(size_t tempo) +{ + size_t tpr = (tempo >> 4) ?: 1; + size_t scale = (tempo & 15); + + return tempo_table[tpr - 1][scale]; +} + /* ST2 says at startup: "Remark: the user ID is encoded in over ten places around the file!" I wonder if this is interesting at all. */ +static void handle_stm_tempo_pattern(song_note_t *note, size_t tempo) +{ + for (int i = 0; i < 5; i++, note++) { + if (note->effect == FX_NONE) { + note->effect = FX_TEMPO; + note->param = handle_tempo(tempo); + break; + } + } +} static void load_stm_pattern(song_note_t *note, slurp_t *fp) { @@ -97,43 +144,38 @@ uint8_t v[4]; for (row = 0; row < 64; row++, note += 64 - 4) { - for (chan = 0; chan < 4; chan++, note++) { + for (chan = 0; chan < 4; chan++) { + song_note_t* chan_note = note + chan; slurp_read(fp, v, 4); // mostly copied from modplug... if (v[0] < 251) - note->note = (v[0] >> 4) * 12 + (v[0] & 0xf) + 37; - note->instrument = v[1] >> 3; - if (note->instrument > 31) - note->instrument = 0; // oops never mind, that was crap - note->volparam = (v[1] & 0x7) + ((v[2] & 0xf0) >> 1); - if (note->volparam <= 64) - note->voleffect = VOLFX_VOLUME; + chan_note->note = (v[0] >> 4) * 12 + (v[0] & 0xf) + 37; + chan_note->instrument = v[1] >> 3; + if (chan_note->instrument > 31) + chan_note->instrument = 0; // oops never mind, that was crap + chan_note->volparam = (v[1] & 0x7) + ((v[2] & 0xf0) >> 1); + if (chan_note->volparam <= 64) + chan_note->voleffect = VOLFX_VOLUME; else - note->volparam = 0; - note->param = v[3]; // easy! + chan_note->volparam = 0; + chan_note->param = v[3]; // easy! - note->effect = stm_effects[v[2] & 0xf]; + chan_note->effect = stm_effects[v[2] & 0xf]; // patch a couple effects up - switch (note->effect) { + switch (chan_note->effect) { case FX_SPEED: - // I don't know how Axx really works, but I do know that this - // isn't it. It does all sorts of mindbogglingly screwy things: - // 01 - very fast, - // 0F - very slow. - // 10 - fast again! - // I don't get it. - note->param >>= 4; + /* do nothing; this is handled later */ break; case FX_VOLUMESLIDE: // Scream Tracker 2 checks for the lower nibble first for some reason... - if (note->param & 0x0f && note->param >> 4) - note->param &= 0x0f; - if (!note->param) - note->effect = FX_NONE; + if (chan_note->param & 0x0f && chan_note->param >> 4) + chan_note->param &= 0x0f; + if (!chan_note->param) + chan_note->effect = FX_NONE; break; case FX_PATTERNBREAK: - note->param = (note->param & 0xf0) * 10 + (note->param & 0xf); + chan_note->param = (chan_note->param & 0xf0) * 10 + (chan_note->param & 0xf); break; case FX_POSITIONJUMP: // This effect is also very weird. @@ -153,11 +195,22 @@ default: // Anything not listed above is a no-op if there's no value. // (ST2 doesn't have effect memory) - if (!note->param) - note->effect = FX_NONE; + if (!chan_note->param) + chan_note->effect = FX_NONE; break; } } + + for (chan = 0; chan < 4; chan++) { + song_note_t* chan_note = note + chan; + if (chan_note->effect == FX_SPEED) { + uint32_t tempo = chan_note->param; + chan_note->param >>= 4; + handle_stm_tempo_pattern(note, tempo); + } + } + + note += chan; } } @@ -200,7 +253,15 @@ song->title[20] = '\0'; slurp_seek(fp, 12, SEEK_CUR); // skip the tag and stuff - song->initial_speed = (slurp_getc(fp) >> 4) ?: 1; + size_t tempo = slurp_getc(fp); + + if (tmp[3] < 21) { + tempo = ((tempo / 10) << 4) + tempo % 10; + } + + song->initial_speed = (tempo >> 4) ?: 1; + song->initial_tempo = handle_tempo(tempo); + npat = slurp_getc(fp); song->initial_global_volume = 2 * slurp_getc(fp); slurp_seek(fp, 13, SEEK_CUR); // junk @@ -224,16 +285,18 @@ sample->c5speed = bswapLE16(stmsmp.c5speed); sample->volume = stmsmp.volume * 4; //mphack if (sample->loop_start < blen - && sample->loop_end != 0xffff - && sample->loop_start < sample->loop_end) { + && sample->loop_end != 0xffff + && sample->loop_start < sample->loop_end) { sample->flags |= CHN_LOOP; sample->loop_end = CLAMP(sample->loop_end, sample->loop_start, blen); } para_sdata[n] = bswapLE16(stmsmp.pcmpara); } - slurp_read(fp, song->orderlist, 128); - for (n = 0; n < 128; n++) { + size_t orderlist_size = tmp[3] ? 128 : 64; + + slurp_read(fp, song->orderlist, orderlist_size); + for (n = 0; n < orderlist_size; n++) { if (song->orderlist[n] >= 64) song->orderlist[n] = ORDER_LAST; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/schismtracker-20240503/fmt/xi.c new/schismtracker-20240515/fmt/xi.c --- old/schismtracker-20240503/fmt/xi.c 2024-05-04 01:36:12.000000000 +0200 +++ new/schismtracker-20240515/fmt/xi.c 2024-05-15 22:03:47.000000000 +0200 @@ -257,9 +257,16 @@ smp->panning = xmss.pan; smp->flags |= CHN_PANNING; smp->vib_type = xmsh.vibtype; - smp->vib_speed = xmsh.vibsweep; - smp->vib_depth = xmsh.vibdepth; - smp->vib_rate = xmsh.vibrate / 4; // XXX xm.c does not divide here, which is wrong? + smp->vib_speed = MIN(xmsh.vibrate, 64); + smp->vib_depth = MIN(xmsh.vibdepth, 32); + if (xmsh.vibrate | xmsh.vibdepth) { + if (xmsh.vibsweep) { + int s = _muldivr(smp->vib_depth, 256, xmsh.vibsweep); + smp->vib_rate = CLAMP(s, 0, 255); + } else { + smp->vib_rate = 255; + } + } smp->c5speed = transpose_to_frequency(xmss.relnote, xmss.finetune); sampledata += csf_read_sample(current_song->samples + n, rs, sampledata, (end-sampledata)); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/schismtracker-20240503/fmt/xm.c new/schismtracker-20240515/fmt/xm.c --- old/schismtracker-20240503/fmt/xm.c 2024-05-04 01:36:12.000000000 +0200 +++ new/schismtracker-20240515/fmt/xm.c 2024-05-15 22:03:47.000000000 +0200 @@ -140,12 +140,21 @@ note->param = slurp_getc(fp); } // translate everything - if (note->note > 0 && note->note < 97) + if (note->note > 0 && note->note < 97) { note->note += 12; - else if (note->note == 97) + } else if (note->note == 97) { + /* filter out instruments on noteoff; + * this is what IT's importer does, because + * hanging the note is *definitely* not + * intended behavior + * + * see: MPT test case noteoff3.it */ note->note = NOTE_OFF; - else + note->instrument = 0; + } else { note->note = NOTE_NONE; + } + if (note->effect || note->param) csf_import_mod_effect(note, 1); if (note->instrument == 0xff) @@ -423,14 +432,14 @@ } enum { - ID_CONFIRMED = 1, // confirmed with inst/sample header sizes - ID_FT2GENERIC = 2, // "FastTracker v2.00", but fasttracker has NOT been ruled out - ID_OLDMODPLUG = 4, // "FastTracker v 2.00" - ID_OTHER = 8, // something we don't know, testing for digitrakker. - ID_FT2CLONE = 16, // NOT FT2: itype changed between instruments, or \0 found in song title - ID_MAYBEMODPLUG = 32, // some FT2-ish thing, possibly MPT. - ID_DIGITRAK = 64, // probably digitrakker - ID_UNKNOWN = 128 | ID_CONFIRMED, // ????? + ID_CONFIRMED = 0x01, // confirmed with inst/sample header sizes + ID_FT2GENERIC = 0x02, // "FastTracker v2.00", but fasttracker has NOT been ruled out + ID_OLDMODPLUG = 0x04, // "FastTracker v 2.00" + ID_OTHER = 0x08, // something we don't know, testing for digitrakker. + ID_FT2CLONE = 0x10, // NOT FT2: itype changed between instruments, or \0 found in song title + ID_MAYBEMODPLUG = 0x20, // some FT2-ish thing, possibly MPT. + ID_DIGITRAK = 0x40, // probably digitrakker + ID_UNKNOWN = 0x80 | ID_CONFIRMED, // ????? }; // TODO: try to identify packers (boobiesqueezer?) @@ -451,19 +460,15 @@ if (strncmp(song->tracker_id, "FastTracker ", 12) == 0) { if (hdr->headersz == 276 && strncmp(song->tracker_id + 12, "v2.00 ", 8) == 0) { - // TODO: is it at all possible to tell the precise FT2 version? that'd be a neat trick. - // (Answer: unlikely. After some testing, I can't identify any differences between 2.04 - // and 2.09. Doesn't mean for certain that they're identical, but I would be surprised - // if anything did change.) detected = ID_FT2GENERIC | ID_MAYBEMODPLUG; - // replace the "v2.00" with just a 2, since it's probably not actually v2.00 - strcpy(song->tracker_id + 12, "2"); + /* there is very little change between different versions of FT2, making it + * very difficult (maybe even impossible) to detect them, so here we just + * say it's either FT2 or a compatible tracker */ + strcpy(song->tracker_id + 12, "2 or compatible"); } else if (strncmp(song->tracker_id + 12, "v 2.00 ", 8) == 0) { - // Old MPT: - // - 1.00a5 (ihdr=245) - // - beta 3.3 (ihdr=263) - strcpy(song->tracker_id, "Modplug Tracker 1.0"); - detected = ID_OLDMODPLUG; + /* alpha and beta are handled later */ + detected = ID_OLDMODPLUG | ID_CONFIRMED; + strcpy(song->tracker_id, "ModPlug Tracker 1.0"); } else { // definitely NOT FastTracker, so let's clear up that misconception detected = ID_UNKNOWN; @@ -606,7 +611,19 @@ vtype = autovib_import[slurp_getc(fp) & 0x7]; vsweep = slurp_getc(fp); vdepth = slurp_getc(fp); - vrate = slurp_getc(fp) / 4; + vdepth = MIN(vdepth, 32); + vrate = slurp_getc(fp); + vrate = MIN(vrate, 64); + + /* translate the sweep value */ + if (vrate | vdepth) { + if (vsweep) { + int s = _muldivr(vdepth, 256, vsweep); + vsweep = CLAMP(s, 0, 255); + } else { + vsweep = 255; + } + } slurp_read(fp, &w, 2); ins->fadeout = bswapLE16(w); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/schismtracker-20240503/player/csndfile.c new/schismtracker-20240515/player/csndfile.c --- old/schismtracker-20240503/player/csndfile.c 2024-05-04 01:36:12.000000000 +0200 +++ new/schismtracker-20240515/player/csndfile.c 2024-05-15 22:03:47.000000000 +0200 @@ -1495,12 +1495,7 @@ case 'P': effect = FX_PANNINGSLIDE; break; case 'Q': effect = FX_RETRIG; break; case 'R': effect = FX_TREMOLO; break; - case 'S': - effect = FX_SPECIAL; - // convert old SAx to S8x - if (!from_it && ((param & 0xf0) == 0xa0)) - param = 0x80 | ((param & 0xf) ^ 8); - break; + case 'S': effect = FX_SPECIAL; break; case 'T': effect = FX_TEMPO; break; case 'U': effect = FX_FINEVIBRATO; break; case 'V': diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/schismtracker-20240503/player/effects.c new/schismtracker-20240515/player/effects.c --- old/schismtracker-20240503/player/effects.c 2024-05-04 01:36:12.000000000 +0200 +++ new/schismtracker-20240515/player/effects.c 2024-05-15 22:03:47.000000000 +0200 @@ -1337,8 +1337,14 @@ return; } - if (psmp == chan->ptr_sample && chan->current_sample_data && chan->length) + const int was_key_off = (chan->flags & CHN_KEYOFF) != 0; + + if (psmp == chan->ptr_sample && chan->current_sample_data && chan->length) { + if (porta && inst_changed && penv) { + chan->flags &= ~(CHN_KEYOFF | CHN_NOTEFADE); + } return; + } if (porta && !chan->length) chan->increment = 0; @@ -1387,7 +1393,7 @@ chan->current_sample_data = psmp->data; chan->position = 0; - if (chan->flags & CHN_SUSTAINLOOP) { + if ((chan->flags & CHN_SUSTAINLOOP) && (!porta || (penv && !was_key_off))) { chan->loop_start = psmp->sustain_start; chan->loop_end = psmp->sustain_end; chan->flags |= CHN_LOOP; @@ -2144,6 +2150,22 @@ // set instrument before doing anything else if (instr && start_note) chan->new_instrument = instr; + // This is probably the single biggest WTF replayer bug in Impulse Tracker. + // In instrument mode, when an note + instrument is triggered that does not map to any sample, the entire cell (including potentially present global effects!) + // is ignored. Even better, if on a following row another instrument number (this time without a note) is encountered, we end up in the same situation! + if (instr > 0 && instr < MAX_INSTRUMENTS && csf->instruments[instr] != NULL) + { + uint8_t note = (chan->row_note != NOTE_NONE) ? chan->row_note : chan->new_note; + if (NOTE_IS_NOTE(note) && csf->instruments[instr]->sample_map[note - NOTE_FIRST] == 0) + { + chan->new_note = note; + chan->row_instr = 0; + chan->row_voleffect = VOLFX_NONE; + chan->row_effect = FX_NONE; + continue; + } + } + /* Have to handle SDx specially because of the way the effects are structured. In a PERFECT world, this would be very straightforward: - Handle the effect column, and set flags for things that should happen @@ -2242,6 +2264,7 @@ GM_Touch(nchan, 0); } + const int previous_new_note = chan->new_note; if (NOTE_IS_NOTE(note)) { chan->new_note = note; @@ -2280,7 +2303,11 @@ // New Note ? if (note != NOTE_NONE) { if (!instr && chan->new_instrument && NOTE_IS_NOTE(note)) { + if (NOTE_IS_NOTE(previous_new_note)) { + chan->new_note = previous_new_note; + } csf_instrument_change(csf, chan, chan->new_instrument, porta, 0); + chan->new_note = note; if ((csf->flags & SONG_INSTRUMENTMODE) && chan->new_instrument < MAX_INSTRUMENTS && csf->instruments[chan->new_instrument]) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/schismtracker-20240503/schism/clippy.c new/schismtracker-20240515/schism/clippy.c --- old/schismtracker-20240503/schism/clippy.c 2024-05-04 01:36:12.000000000 +0200 +++ new/schismtracker-20240515/schism/clippy.c 2024-05-15 22:03:47.000000000 +0200 @@ -38,49 +38,21 @@ static void _clippy_copy_to_sys(int cb) { - char* freeme = NULL; - - if (_current_selection) { - char* dst = NULL; - int i = 0; -#ifdef WIN32 - /* need twice the space since newlines are replaced with \r\n */ - freeme = dst = malloc(strlen(_current_selection) * 2) + 1; -#else - /* XXX what's 4?? */ - freeme = dst = malloc(strlen(_current_selection) + 4); -#endif - if (!freeme) return; - for (i = 0; _current_selection[i]; i++) { -#ifdef WIN32 - if (_current_selection[i] == '\r' || _current_selection[i] == '\n') { - *(dst++) = '\r'; - *(dst++) = '\n'; - } else { - *(dst++) = _current_selection[i]; - } -#else - *(dst++) = (_current_selection[i] == '\r') ? '\n' : _current_selection[i]; -#endif - } - (*dst++) = '\0'; - } + if (!_current_selection) + return; switch (cb) { case CLIPPY_SELECT: /* TODO: convert to UTF-8 */ #if SDL_VERSION_ATLEAST(2, 26, 0) - SDL_SetPrimarySelectionText(freeme); -#endif + SDL_SetPrimarySelectionText(_current_selection); +#endif break; default: case CLIPPY_BUFFER: - SDL_SetClipboardText(freeme); + SDL_SetClipboardText(_current_selection); break; } - - if (freeme) - free(freeme); } static void _string_paste(UNUSED int cb, const char *cbptr) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/schismtracker-20240503/schism/dmoz.c new/schismtracker-20240515/schism/dmoz.c --- old/schismtracker-20240503/schism/dmoz.c 2024-05-04 01:36:12.000000000 +0200 +++ new/schismtracker-20240515/schism/dmoz.c 2024-05-15 22:03:47.000000000 +0200 @@ -799,7 +799,7 @@ st.st_mtime = MIN(0, st.st_mtime); if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { - dmoz_add_dir(dlist, fullpath, filename, 0); + dmoz_add_file_or_dir(flist, dlist, fullpath, filename, &st, 0); } else if (ffd.dwFileAttributes == INVALID_FILE_ATTRIBUTES) { free(fullpath); free(filename);