mirror of
https://github.com/OldUnreal/libxmp.git
synced 2026-04-02 21:37:43 -07:00
Fix Schism Tracker version date calculation.
Fixes several issues with the calculation of Schism Tracker dates. Schism Tracker date calculation is now handled in a utility function. * The date calculation was using a UTC epoch time but calculating the version date with localtime_r. * The UTC epoch time was wrong (2009-10-01 instead of 2009-10-31). * The S3M loader was not calculating Schism Tracker dates at all. * Added detection for extended Schism Tracker dates (>2020-10-28) to both the S3M and IT loaders. Additionally, the libxmp dependency on localtime_r has been entirely removed in favor of an inline algorithm provided by Saga Musix.
This commit is contained in:
@@ -150,7 +150,7 @@ darwin*)
|
||||
LIBS="${old_LIBS}"
|
||||
;;
|
||||
esac
|
||||
AC_CHECK_FUNCS(popen mkstemp fnmatch umask localtime_r round powf)
|
||||
AC_CHECK_FUNCS(popen mkstemp fnmatch umask round powf)
|
||||
|
||||
AC_CONFIG_FILES([Makefile])
|
||||
AC_CONFIG_FILES([libxmp.pc])
|
||||
|
||||
@@ -149,7 +149,7 @@ darwin*)
|
||||
LIBS="${old_LIBS}"
|
||||
;;
|
||||
esac
|
||||
AC_CHECK_FUNCS(localtime_r round powf)
|
||||
AC_CHECK_FUNCS(round powf)
|
||||
|
||||
AC_CONFIG_FILES([Makefile])
|
||||
AC_CONFIG_FILES([libxmp-lite.pc])
|
||||
|
||||
@@ -364,3 +364,54 @@ void libxmp_set_type(struct module_data *m, const char *fmt, ...)
|
||||
vsnprintf(m->mod.type, XMP_NAME_SIZE, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
static int schism_tracker_date(int year, int month, int day)
|
||||
{
|
||||
int mm = (month + 9) % 12;
|
||||
int yy = year - mm / 10;
|
||||
|
||||
yy = yy * 365 + (yy / 4) - (yy / 100) + (yy / 400);
|
||||
mm = (mm * 306 + 5) / 10;
|
||||
|
||||
return yy + mm + (day - 1);
|
||||
}
|
||||
|
||||
/* Generate a Schism Tracker version string.
|
||||
* Schism Tracker versions are stored as follows:
|
||||
*
|
||||
* s_ver <= 0x50: 0.s_ver
|
||||
* s_ver > 0x50, < 0xfff: days from epoch=(s_ver - 0x50)
|
||||
* s_ver = 0xfff: days from epoch=l_ver
|
||||
*/
|
||||
void libxmp_schism_tracker_string(char *buf, size_t size, int s_ver, int l_ver)
|
||||
{
|
||||
if (s_ver >= 0x50) {
|
||||
/* time_t epoch_sec = 1256947200; */
|
||||
int t = schism_tracker_date(2009, 10, 31);
|
||||
int year, month, day, dayofyear;
|
||||
|
||||
if (s_ver == 0xfff) {
|
||||
t += l_ver;
|
||||
} else
|
||||
t += s_ver - 0x50;
|
||||
|
||||
/* Date algorithm reimplemented from OpenMPT.
|
||||
*/
|
||||
year = (int)(((int64)t * 10000L + 14780) / 3652425);
|
||||
dayofyear = t - (365 * year + (year / 4) - (year / 100) + (year / 400));
|
||||
if (dayofyear < 0) {
|
||||
year--;
|
||||
dayofyear = t - (365 * year + (year / 4) - (year / 100) + (year / 400));
|
||||
}
|
||||
month = (100 * dayofyear + 52) / 3060;
|
||||
day = dayofyear - (month * 306 + 5) / 10 + 1;
|
||||
|
||||
year += (month + 2) / 12;
|
||||
month = (month + 2) % 12 + 1;
|
||||
|
||||
snprintf(buf, size, "Schism Tracker %04d-%02d-%02d",
|
||||
year, month, day);
|
||||
} else {
|
||||
snprintf(buf, size, "Schism Tracker 0.%x", s_ver);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
|
||||
#ifndef LIBXMP_CORE_DISABLE_IT
|
||||
|
||||
#include <time.h>
|
||||
#include "loader.h"
|
||||
#include "it.h"
|
||||
#include "period.h"
|
||||
@@ -41,23 +40,6 @@ const struct format_loader libxmp_loader_it = {
|
||||
it_load
|
||||
};
|
||||
|
||||
#ifndef LIBXMP_CORE_PLAYER /* */
|
||||
#if defined(__WATCOMC__)
|
||||
#undef localtime_r
|
||||
#define localtime_r _localtime
|
||||
|
||||
#elif !defined(HAVE_LOCALTIME_R) || defined(_WIN32)
|
||||
#undef localtime_r
|
||||
#define localtime_r libxmp_localtime_r
|
||||
static struct tm *libxmp_localtime_r(const time_t * timep, struct tm *result)
|
||||
{
|
||||
/* Note: Win32 localtime() is thread-safe */
|
||||
memcpy(result, localtime(timep), sizeof(struct tm));
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
#endif /* ! LIBXMP_CORE_PLAYER */
|
||||
|
||||
static int it_test(HIO_HANDLE * f, char *t, const int start)
|
||||
{
|
||||
if (hio_read32b(f) != MAGIC_IMPM)
|
||||
@@ -373,25 +355,10 @@ static void identify_tracker(struct module_data *m, struct it_file_header *ifh)
|
||||
break;
|
||||
default:
|
||||
switch (ifh->cwt >> 12) {
|
||||
case 0x1:{
|
||||
uint16 cwtv = ifh->cwt & 0x0fff;
|
||||
struct tm version;
|
||||
time_t version_sec;
|
||||
|
||||
if (cwtv > 0x50) {
|
||||
version_sec = ((cwtv - 0x050) * 86400) + 1254355200;
|
||||
if (localtime_r(&version_sec, &version)) {
|
||||
snprintf(tracker_name, 40,
|
||||
"Schism Tracker %04d-%02d-%02d",
|
||||
version.tm_year + 1900,
|
||||
version.tm_mon + 1,
|
||||
version.tm_mday);
|
||||
}
|
||||
} else {
|
||||
snprintf(tracker_name, 40,
|
||||
"Schism Tracker 0.%x", cwtv);
|
||||
}
|
||||
break; }
|
||||
case 0x1:
|
||||
libxmp_schism_tracker_string(tracker_name, 40,
|
||||
(ifh->cwt & 0x0fff), ifh->rsvd);
|
||||
break;
|
||||
case 0x5:
|
||||
snprintf(tracker_name, 40, "OpenMPT %d.%02x",
|
||||
(ifh->cwt & 0x0f00) >> 8, ifh->cwt & 0xff);
|
||||
|
||||
@@ -47,6 +47,7 @@ void libxmp_get_instrument_path (struct module_data *, char *, int);
|
||||
void libxmp_set_type (struct module_data *, const char *, ...);
|
||||
int libxmp_load_sample (struct module_data *, HIO_HANDLE *, int,
|
||||
struct xmp_sample *, const void *);
|
||||
void libxmp_schism_tracker_string (char *, size_t, int, int);
|
||||
|
||||
extern uint8 libxmp_ord_xlat[];
|
||||
extern const int libxmp_arch_vol_table[];
|
||||
|
||||
@@ -271,7 +271,7 @@ static int s3m_load(struct module_data *m, HIO_HANDLE * f, const int start)
|
||||
sfh.mv = buf[51]; /* Master volume */
|
||||
sfh.uc = buf[52]; /* Ultra click removal */
|
||||
sfh.dp = buf[53]; /* Default pan positions if 0xfc */
|
||||
/* 54-61 reserved */
|
||||
memcpy(sfh.rsvd2, buf + 54, 8); /* Reserved */
|
||||
sfh.special = readmem16l(buf + 62); /* Ptr to special custom data */
|
||||
memcpy(sfh.chset, buf + 64, 32); /* Channel settings */
|
||||
|
||||
@@ -418,9 +418,8 @@ static int s3m_load(struct module_data *m, HIO_HANDLE * f, const int start)
|
||||
break;
|
||||
case 4:
|
||||
if (sfh.version != 0x4100) {
|
||||
snprintf(tracker_name, 40, "Schism Tracker %d.%02x",
|
||||
(sfh.version & 0x0f00) >> 8,
|
||||
sfh.version & 0xff);
|
||||
libxmp_schism_tracker_string(tracker_name, 40,
|
||||
(sfh.version & 0x0fff), sfh.rsvd2[0] | (sfh.rsvd2[1] << 8));
|
||||
break;
|
||||
}
|
||||
/* fall through */
|
||||
|
||||
Reference in New Issue
Block a user