diff --git a/GNUmakefile b/GNUmakefile index b4f3202f7..f39cf1386 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -75,6 +75,7 @@ libxmplite_objs := \ s3m_load.c \ sample.c \ xm_load.c \ + win32.c \ libxmplite_root := $(source)/$(libxmplite) libxmplite_src := $(libxmplite_root)/src diff --git a/platform/Windows/libxmp-lite.vcxproj b/platform/Windows/libxmp-lite.vcxproj index 8983938e0..68f2bb018 100644 --- a/platform/Windows/libxmp-lite.vcxproj +++ b/platform/Windows/libxmp-lite.vcxproj @@ -66,6 +66,7 @@ + diff --git a/platform/Windows/libxmp-lite.vcxproj.filters b/platform/Windows/libxmp-lite.vcxproj.filters index 59bcb767a..24ba72930 100644 --- a/platform/Windows/libxmp-lite.vcxproj.filters +++ b/platform/Windows/libxmp-lite.vcxproj.filters @@ -149,5 +149,6 @@ Source Files + \ No newline at end of file diff --git a/source/libxmp-lite/include/libxmp-lite/xmp.h b/source/libxmp-lite/include/libxmp-lite/xmp.h index 799deb28d..33076f650 100644 --- a/source/libxmp-lite/include/libxmp-lite/xmp.h +++ b/source/libxmp-lite/include/libxmp-lite/xmp.h @@ -5,30 +5,30 @@ extern "C" { #endif -#define XMP_VERSION "4.4.2" -#define XMP_VERCODE 0x040402 +#define XMP_VERSION "4.5.0" +#define XMP_VERCODE 0x040500 #define XMP_VER_MAJOR 4 -#define XMP_VER_MINOR 4 -#define XMP_VER_RELEASE 2 +#define XMP_VER_MINOR 5 +#define XMP_VER_RELEASE 0 #if defined(_WIN32) && !defined(__CYGWIN__) # if defined(BUILDING_STATIC) -# define EXPORT +# define LIBXMP_EXPORT # elif defined(BUILDING_DLL) -# define EXPORT __declspec(dllexport) +# define LIBXMP_EXPORT __declspec(dllexport) # else -# define EXPORT __declspec(dllimport) +# define LIBXMP_EXPORT __declspec(dllimport) # endif #elif defined(__OS2__) && defined(__WATCOMC__) && defined(__SW_BD) -# define EXPORT __declspec(dllexport) +# define LIBXMP_EXPORT __declspec(dllexport) #elif (defined(__GNUC__) || defined(__clang__) || defined(__HP_cc)) && defined(XMP_SYM_VISIBILITY) -# define EXPORT __attribute__((visibility ("default"))) +# define LIBXMP_EXPORT __attribute__((visibility ("default"))) #elif defined(__SUNPRO_C) && defined(XMP_LDSCOPE_GLOBAL) -# define EXPORT __global +# define LIBXMP_EXPORT __global #elif defined(EMSCRIPTEN) -# define EXPORT EMSCRIPTEN_KEEPALIVE +# define LIBXMP_EXPORT EMSCRIPTEN_KEEPALIVE #else -# define EXPORT +# define LIBXMP_EXPORT #endif #define XMP_NAME_SIZE 64 /* Size of module name and type */ @@ -172,35 +172,36 @@ struct xmp_envelope { }; struct xmp_subinstrument { - int vol; /* Default volume */ - int gvl; /* Global volume */ - int pan; /* Pan */ - int xpo; /* Transpose */ - int fin; /* Finetune */ - int vwf; /* Vibrato waveform */ - int vde; /* Vibrato depth */ - int vra; /* Vibrato rate */ - int vsw; /* Vibrato sweep */ - int rvv; /* Random volume/pan variation (IT) */ - int sid; /* Sample number */ + int vol; /* Default volume */ + int gvl; /* Global volume */ + int pan; /* Pan */ + int xpo; /* Transpose */ + int fin; /* Finetune */ + int vwf; /* Vibrato waveform */ + int vde; /* Vibrato depth */ + int vra; /* Vibrato rate */ + int vsw; /* Vibrato sweep */ + int rvv; /* Random volume/pan variation (IT) */ + int sid; /* Sample number */ #define XMP_INST_NNA_CUT 0x00 #define XMP_INST_NNA_CONT 0x01 #define XMP_INST_NNA_OFF 0x02 #define XMP_INST_NNA_FADE 0x03 - int nna; /* New note action */ + int nna; /* New note action */ #define XMP_INST_DCT_OFF 0x00 #define XMP_INST_DCT_NOTE 0x01 #define XMP_INST_DCT_SMP 0x02 #define XMP_INST_DCT_INST 0x03 - int dct; /* Duplicate check type */ + int dct; /* Duplicate check type */ #define XMP_INST_DCA_CUT XMP_INST_NNA_CUT #define XMP_INST_DCA_OFF XMP_INST_NNA_OFF #define XMP_INST_DCA_FADE XMP_INST_NNA_FADE - int dca; /* Duplicate check action */ - int ifc; /* Initial filter cutoff */ - int ifr; /* Initial filter resonance */ + int dca; /* Duplicate check action */ + int ifc; /* Initial filter cutoff */ + int ifr; /* Initial filter resonance */ }; + struct xmp_instrument { char name[32]; /* Instrument name */ int vol; /* Instrument volume */ @@ -215,7 +216,7 @@ struct xmp_instrument { signed char xpo; /* Instrument transpose for each key */ } map[XMP_MAX_KEYS]; - struct xmp_subinstrument *sub; + struct xmp_subinstrument *sub; void *extra; /* Extra fields */ }; @@ -279,18 +280,19 @@ struct xmp_module_info { }; struct xmp_channel_info { /* Current channel information */ - unsigned int period; /* Sample period (* 4096) */ - unsigned int position; /* Sample position */ - short pitchbend; /* Linear bend from base note*/ - unsigned char note; /* Current base note number */ - unsigned char instrument; /* Current instrument number */ - unsigned char sample; /* Current sample number */ - unsigned char volume; /* Current volume */ - unsigned char pan; /* Current stereo pan */ - unsigned char reserved; /* Reserved */ - struct xmp_event event; /* Current track event */ + unsigned int period; /* Sample period (* 4096) */ + unsigned int position; /* Sample position */ + short pitchbend; /* Linear bend from base note*/ + unsigned char note; /* Current base note number */ + unsigned char instrument; /* Current instrument number */ + unsigned char sample; /* Current sample number */ + unsigned char volume; /* Current volume */ + unsigned char pan; /* Current stereo pan */ + unsigned char reserved; /* Reserved */ + struct xmp_event event; /* Current track event */ }; + struct xmp_frame_info { /* Current frame information */ int pos; /* Current position */ int pattern; /* Current pattern */ @@ -317,51 +319,52 @@ struct xmp_frame_info { /* Current frame information */ typedef char *xmp_context; -EXPORT extern const char *xmp_version; -EXPORT extern const unsigned int xmp_vercode; +LIBXMP_EXPORT extern const char *xmp_version; +LIBXMP_EXPORT extern const unsigned int xmp_vercode; -EXPORT xmp_context xmp_create_context (void); -EXPORT void xmp_free_context (xmp_context); +LIBXMP_EXPORT xmp_context xmp_create_context (void); +LIBXMP_EXPORT void xmp_free_context (xmp_context); #ifdef EDUKE32_DISABLED -EXPORT int xmp_test_module (char *, struct xmp_test_info *); -EXPORT int xmp_load_module (xmp_context, char *); +LIBXMP_EXPORT int xmp_test_module (char *, struct xmp_test_info *); +LIBXMP_EXPORT int xmp_load_module (xmp_context, char *); #endif -EXPORT void xmp_scan_module (xmp_context); -EXPORT void xmp_release_module (xmp_context); -EXPORT int xmp_start_player (xmp_context, int, int); -EXPORT int xmp_play_frame (xmp_context); -EXPORT int xmp_play_buffer (xmp_context, void *, int, int); -EXPORT void xmp_get_frame_info (xmp_context, struct xmp_frame_info *); -EXPORT void xmp_end_player (xmp_context); -EXPORT void xmp_inject_event (xmp_context, int, struct xmp_event *); -EXPORT void xmp_get_module_info (xmp_context, struct xmp_module_info *); -EXPORT const char**xmp_get_format_list (void); -EXPORT int xmp_next_position (xmp_context); -EXPORT int xmp_prev_position (xmp_context); -EXPORT int xmp_set_position (xmp_context, int); -EXPORT void xmp_stop_module (xmp_context); -EXPORT void xmp_restart_module (xmp_context); -EXPORT int xmp_seek_time (xmp_context, int); -EXPORT int xmp_channel_mute (xmp_context, int, int); -EXPORT int xmp_channel_vol (xmp_context, int, int); -EXPORT int xmp_set_player (xmp_context, int, int); -EXPORT int xmp_get_player (xmp_context, int); -EXPORT int xmp_set_instrument_path (xmp_context, char *); -EXPORT int xmp_load_module_from_memory (xmp_context, void *, long); +LIBXMP_EXPORT void xmp_scan_module (xmp_context); +LIBXMP_EXPORT void xmp_release_module (xmp_context); +LIBXMP_EXPORT int xmp_start_player (xmp_context, int, int); +LIBXMP_EXPORT int xmp_play_frame (xmp_context); +LIBXMP_EXPORT int xmp_play_buffer (xmp_context, void *, int, int); +LIBXMP_EXPORT void xmp_get_frame_info (xmp_context, struct xmp_frame_info *); +LIBXMP_EXPORT void xmp_end_player (xmp_context); +LIBXMP_EXPORT void xmp_inject_event (xmp_context, int, struct xmp_event *); +LIBXMP_EXPORT void xmp_get_module_info (xmp_context, struct xmp_module_info *); +LIBXMP_EXPORT const char **xmp_get_format_list (void); +LIBXMP_EXPORT int xmp_next_position (xmp_context); +LIBXMP_EXPORT int xmp_prev_position (xmp_context); +LIBXMP_EXPORT int xmp_set_position (xmp_context, int); +LIBXMP_EXPORT int xmp_set_row (xmp_context, int); +LIBXMP_EXPORT int xmp_set_tempo_factor(xmp_context, double); +LIBXMP_EXPORT void xmp_stop_module (xmp_context); +LIBXMP_EXPORT void xmp_restart_module (xmp_context); +LIBXMP_EXPORT int xmp_seek_time (xmp_context, int); +LIBXMP_EXPORT int xmp_channel_mute (xmp_context, int, int); +LIBXMP_EXPORT int xmp_channel_vol (xmp_context, int, int); +LIBXMP_EXPORT int xmp_set_player (xmp_context, int, int); +LIBXMP_EXPORT int xmp_get_player (xmp_context, int); +LIBXMP_EXPORT int xmp_set_instrument_path (xmp_context, char *); +LIBXMP_EXPORT int xmp_load_module_from_memory (xmp_context, void *, long); #ifdef EDUKE32_DISABLED -EXPORT int xmp_load_module_from_file (xmp_context, void *, long); +LIBXMP_EXPORT int xmp_load_module_from_file (xmp_context, void *, long); #endif - /* External sample mixer API */ -EXPORT int xmp_start_smix (xmp_context, int, int); -EXPORT void xmp_end_smix (xmp_context); -EXPORT int xmp_smix_play_instrument(xmp_context, int, int, int, int); -EXPORT int xmp_smix_play_sample (xmp_context, int, int, int, int); -EXPORT int xmp_smix_channel_pan (xmp_context, int, int); +LIBXMP_EXPORT int xmp_start_smix (xmp_context, int, int); +LIBXMP_EXPORT void xmp_end_smix (xmp_context); +LIBXMP_EXPORT int xmp_smix_play_instrument(xmp_context, int, int, int, int); +LIBXMP_EXPORT int xmp_smix_play_sample (xmp_context, int, int, int, int); +LIBXMP_EXPORT int xmp_smix_channel_pan (xmp_context, int, int); #ifdef EDUKE32_DISABLED -EXPORT int xmp_smix_load_sample (xmp_context, int, char *); +LIBXMP_EXPORT int xmp_smix_load_sample (xmp_context, int, char *); #endif -EXPORT int xmp_smix_release_sample (xmp_context, int); +LIBXMP_EXPORT int xmp_smix_release_sample (xmp_context, int); #ifdef __cplusplus } diff --git a/source/libxmp-lite/src/common.c b/source/libxmp-lite/src/common.c index 4ca28e90b..ed38442c1 100644 --- a/source/libxmp-lite/src/common.c +++ b/source/libxmp-lite/src/common.c @@ -1,5 +1,5 @@ /* Extended Module Player - * Copyright (C) 1996-2016 Claudio Matsuoka and Hipolito Carraro Jr + * Copyright (C) 1996-2018 Claudio Matsuoka and Hipolito Carraro Jr * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), diff --git a/source/libxmp-lite/src/common.h b/source/libxmp-lite/src/common.h index 2290606d1..44634251d 100644 --- a/source/libxmp-lite/src/common.h +++ b/source/libxmp-lite/src/common.h @@ -145,10 +145,7 @@ void __inline CLIB_DECL D_(const char *text, ...) { do {} while (0); } #define close _close #define unlink _unlink #endif -#if defined(_MSC_VER) -#define snprintf _snprintf -#define vsnprintf _vsnprintf -#elif defined(__WATCOMC__) /* in win32.c */ +#if defined(_WIN32) || defined(__WATCOMC__) /* in win32.c */ int libxmp_vsnprintf(char *, size_t, const char *, va_list); int libxmp_snprintf (char *, size_t, const char *, ...); #define snprintf libxmp_snprintf @@ -296,28 +293,40 @@ struct module_data { }; struct pattern_loop { - int start; - int count; + int start; + int count; }; + struct flow_control { - int pbreak; - int jump; - int delay; - int jumpline; - int loop_chn; - - struct pattern_loop *loop; - - int num_rows; - int end_point; - int rowdelay; /* For IT pattern row delay */ - int rowdelay_set; + int pbreak; + int jump; + int delay; + int jumpline; + int loop_chn; + + struct pattern_loop *loop; + + int num_rows; + int end_point; + int rowdelay; /* For IT pattern row delay */ + int rowdelay_set; }; struct virt_channel { - int count; - int map; + int count; + int map; +}; + +struct virt_control { + int num_tracks; /* Number of tracks */ + int virt_channels; /* Number of virtual channels */ + int virt_used; /* Number of voices currently in use */ + int maxvoc; /* Number of sound card voices */ + + struct virt_channel *virt_channel; + + struct mixer_voice *voice_array; }; struct player_data { @@ -342,7 +351,7 @@ struct player_data { int master_vol; /* Music volume */ int gvol; - struct flow_control flow; + struct flow_control flow; struct { int time; /* replay time in ms */ @@ -356,16 +365,7 @@ struct player_data { int channel_vol[XMP_MAX_CHANNELS]; char channel_mute[XMP_MAX_CHANNELS]; - struct virt_control { - int num_tracks; /* Number of tracks */ - int virt_channels; /* Number of virtual channels */ - int virt_used; /* Number of voices currently in use */ - int maxvoc; /* Number of sound card voices */ - - struct virt_channel *virt_channel; - - struct mixer_voice *voice_array; - } virt; + struct virt_control virt; struct xmp_event inject_event[XMP_MAX_CHANNELS]; diff --git a/source/libxmp-lite/src/control.c b/source/libxmp-lite/src/control.c index 342fee819..8102c9f4c 100644 --- a/source/libxmp-lite/src/control.c +++ b/source/libxmp-lite/src/control.c @@ -1,5 +1,5 @@ /* Extended Module Player - * Copyright (C) 1996-2016 Claudio Matsuoka and Hipolito Carraro Jr + * Copyright (C) 1996-2018 Claudio Matsuoka and Hipolito Carraro Jr * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -174,6 +174,37 @@ int xmp_set_position(xmp_context opaque, int pos) return p->pos; } +int xmp_set_row(xmp_context opaque, int row) +{ + struct context_data *ctx = (struct context_data *)opaque; + struct player_data *p = &ctx->p; + struct module_data *m = &ctx->m; + struct xmp_module *mod = &m->mod; + struct flow_control *f = &p->flow; + int pos = p->pos; + int pattern = mod->xxo[pos]; + + if (pos < 0 || pos >= mod->len) { + pos = 0; + } + + if (ctx->state < XMP_STATE_PLAYING) + return -XMP_ERROR_STATE; + + if (row >= mod->xxp[pattern]->rows) + return -XMP_ERROR_INVALID; + + /* See set_position. */ + if (p->pos < 0) + p->pos = 0; + p->ord = p->pos; + p->row = row; + p->frame = -1; + f->num_rows = mod->xxp[mod->xxo[p->ord]]->rows; + + return row; +} + void xmp_stop_module(xmp_context opaque) { struct context_data *ctx = (struct context_data *)opaque; @@ -275,12 +306,12 @@ int xmp_channel_vol(xmp_context opaque, int chn, int vol) } #ifdef USE_VERSIONED_SYMBOLS -EXPORT extern int xmp_set_player_v40__(xmp_context, int, int); -EXPORT extern int xmp_set_player_v41__(xmp_context, int, int) +LIBXMP_EXPORT extern int xmp_set_player_v40__(xmp_context, int, int); +LIBXMP_EXPORT extern int xmp_set_player_v41__(xmp_context, int, int) __attribute__((alias("xmp_set_player_v40__"))); -EXPORT extern int xmp_set_player_v43__(xmp_context, int, int) +LIBXMP_EXPORT extern int xmp_set_player_v43__(xmp_context, int, int) __attribute__((alias("xmp_set_player_v40__"))); -EXPORT extern int xmp_set_player_v44__(xmp_context, int, int) +LIBXMP_EXPORT extern int xmp_set_player_v44__(xmp_context, int, int) __attribute__((alias("xmp_set_player_v40__"))); asm(".symver xmp_set_player_v40__, xmp_set_player@XMP_4.0"); @@ -393,14 +424,14 @@ int xmp_set_player__(xmp_context opaque, int parm, int val) } #ifdef USE_VERSIONED_SYMBOLS -EXPORT extern int xmp_get_player_v40__(xmp_context, int); -EXPORT extern int xmp_get_player_v41__(xmp_context, int) +LIBXMP_EXPORT extern int xmp_get_player_v40__(xmp_context, int); +LIBXMP_EXPORT extern int xmp_get_player_v41__(xmp_context, int) __attribute__((alias("xmp_get_player_v40__"))); -EXPORT extern int xmp_get_player_v42__(xmp_context, int) +LIBXMP_EXPORT extern int xmp_get_player_v42__(xmp_context, int) __attribute__((alias("xmp_get_player_v40__"))); -EXPORT extern int xmp_get_player_v43__(xmp_context, int) +LIBXMP_EXPORT extern int xmp_get_player_v43__(xmp_context, int) __attribute__((alias("xmp_get_player_v40__"))); -EXPORT extern int xmp_get_player_v44__(xmp_context, int) +LIBXMP_EXPORT extern int xmp_get_player_v44__(xmp_context, int) __attribute__((alias("xmp_get_player_v40__"))); asm(".symver xmp_get_player_v40__, xmp_get_player@XMP_4.0"); @@ -527,3 +558,25 @@ int xmp_set_instrument_path(xmp_context opaque, char *path) return 0; } + +int xmp_set_tempo_factor(xmp_context opaque, double val) +{ + struct context_data *ctx = (struct context_data *)opaque; + struct player_data *p = &ctx->p; + struct module_data *m = &ctx->m; + struct mixer_data *s = &ctx->s; + int ticksize; + + if (val <= 0.0) { + return -1; + } + + val *= 10; + ticksize = s->freq * m->time_factor * m->rrate / p->bpm / 1000 * sizeof(int); + if (ticksize > XMP_MAX_FRAMESIZE) { + return -1; + } + m->time_factor = val; + + return 0; +} diff --git a/source/libxmp-lite/src/dataio.c b/source/libxmp-lite/src/dataio.c index c4c2253e9..002c0a4a7 100644 --- a/source/libxmp-lite/src/dataio.c +++ b/source/libxmp-lite/src/dataio.c @@ -1,5 +1,5 @@ /* Extended Module Player - * Copyright (C) 1996-2016 Claudio Matsuoka and Hipolito Carraro Jr + * Copyright (C) 1996-2018 Claudio Matsuoka and Hipolito Carraro Jr * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), diff --git a/source/libxmp-lite/src/effects.c b/source/libxmp-lite/src/effects.c index 5d128020f..79a898fa3 100644 --- a/source/libxmp-lite/src/effects.c +++ b/source/libxmp-lite/src/effects.c @@ -1,5 +1,5 @@ /* Extended Module Player - * Copyright (C) 1996-2016 Claudio Matsuoka and Hipolito Carraro Jr + * Copyright (C) 1996-2018 Claudio Matsuoka and Hipolito Carraro Jr * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -540,9 +540,11 @@ void libxmp_process_fx(struct context_data *ctx, struct channel_data *xc, int ch #ifndef LIBXMP_CORE_DISABLE_IT case FX_IT_BPM: /* Set IT BPM */ - if (MSN(fxp) == 0) { /* T0x - Tempo slide down by x */ + if (MSN(fxp) == 0) { SET(TEMPO_SLIDE); + if (LSN(fxp)) /* T0x - Tempo slide down by x */ xc->tempo.slide = -LSN(fxp); + /* T00 - Repeat previous slide */ } else if (MSN(fxp) == 1) { /* T1x - Tempo slide up by x */ SET(TEMPO_SLIDE); xc->tempo.slide = LSN(fxp); @@ -586,8 +588,11 @@ void libxmp_process_fx(struct context_data *ctx, struct channel_data *xc, int ch xc->vol.fslide2 = -fxp; break; case FX_IT_BREAK: /* Pattern break with hex parameter */ + if (!f->loop_chn) + { p->flow.pbreak = 1; p->flow.jumpline = fxp; + } break; #endif @@ -684,10 +689,10 @@ void libxmp_process_fx(struct context_data *ctx, struct channel_data *xc, int ch EFFECT_MEMORY_S3M(fxp); if (fxp) { xc->retrig.val = fxp; + xc->retrig.type = MSN(xc->retrig.val); } if (note) { xc->retrig.count = LSN(xc->retrig.val) + 1; - xc->retrig.type = MSN(xc->retrig.val); } SET(RETRIG); break; diff --git a/source/libxmp-lite/src/hio.c b/source/libxmp-lite/src/hio.c index e2356421d..91328ad89 100644 --- a/source/libxmp-lite/src/hio.c +++ b/source/libxmp-lite/src/hio.c @@ -1,5 +1,5 @@ /* Extended Module Player - * Copyright (C) 1996-2016 Claudio Matsuoka and Hipolito Carraro Jr + * Copyright (C) 1996-2018 Claudio Matsuoka and Hipolito Carraro Jr * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), diff --git a/source/libxmp-lite/src/it.h b/source/libxmp-lite/src/it.h index b574c67e8..5c6fc63ef 100644 --- a/source/libxmp-lite/src/it.h +++ b/source/libxmp-lite/src/it.h @@ -1,5 +1,5 @@ /* Extended Module Player - * Copyright (C) 1996-2016 Claudio Matsuoka and Hipolito Carraro Jr + * Copyright (C) 1996-2018 Claudio Matsuoka and Hipolito Carraro Jr * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), diff --git a/source/libxmp-lite/src/it_load.c b/source/libxmp-lite/src/it_load.c index e41e6dc1a..ea7858ce2 100644 --- a/source/libxmp-lite/src/it_load.c +++ b/source/libxmp-lite/src/it_load.c @@ -1,5 +1,5 @@ /* Extended Module Player - * Copyright (C) 1996-2016 Claudio Matsuoka and Hipolito Carraro Jr + * Copyright (C) 1996-2018 Claudio Matsuoka and Hipolito Carraro Jr * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -42,19 +42,22 @@ 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 -struct tm *localtime_r(const time_t * timep, struct tm *result) +#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) { @@ -280,14 +283,7 @@ static int read_envelope(struct xmp_envelope *ei, struct it_envelope *env, } env->flg = buf[0]; - env->num = buf[1]; - - /* Sanity check */ - if (env->num >= XMP_MAX_ENV_POINTS) { - env->flg = 0; - env->num = 0; - return -1; - } + env->num = MIN(buf[1], 25); /* Clamp to IT max */ env->lpb = buf[2]; env->lpe = buf[3]; @@ -1140,7 +1136,6 @@ static int it_load(struct module_data *m, HIO_HANDLE *f, const int start) } if (ifh.chpan[i] & 0x80) { /* Channel mute */ - ifh.chvol[i] = 0; xxc->flg |= XMP_CHANNEL_MUTE; } @@ -1348,7 +1343,7 @@ static int it_load(struct module_data *m, HIO_HANDLE *f, const int start) D_(D_INFO "Message length : %d", ifh.msglen); - for (j = 0; j < ifh.msglen - 1; j++) { + for (j = 0; j + 1 < ifh.msglen; j++) { int b = hio_read8(f); if (b == '\r') { b = '\n'; @@ -1360,7 +1355,7 @@ static int it_load(struct module_data *m, HIO_HANDLE *f, const int start) } if (ifh.msglen > 0) { - m->comment[j-1] = 0; + m->comment[j] = 0; } } } diff --git a/source/libxmp-lite/src/lfo.c b/source/libxmp-lite/src/lfo.c index 5cdf4fb25..72911c1cd 100644 --- a/source/libxmp-lite/src/lfo.c +++ b/source/libxmp-lite/src/lfo.c @@ -1,5 +1,5 @@ /* Extended Module Player - * Copyright (C) 1996-2016 Claudio Matsuoka and Hipolito Carraro Jr + * Copyright (C) 1996-2018 Claudio Matsuoka and Hipolito Carraro Jr * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), diff --git a/source/libxmp-lite/src/load.c b/source/libxmp-lite/src/load.c index ee873d933..fa1002d4b 100644 --- a/source/libxmp-lite/src/load.c +++ b/source/libxmp-lite/src/load.c @@ -1,5 +1,5 @@ /* Extended Module Player - * Copyright (C) 1996-2016 Claudio Matsuoka and Hipolito Carraro Jr + * Copyright (C) 1996-2018 Claudio Matsuoka and Hipolito Carraro Jr * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -34,9 +34,6 @@ #include "format.h" #include "list.h" #include "hio.h" -#ifndef LIBXMP_CORE_PLAYER -#include "tempfile.h" -#endif #ifndef LIBXMP_CORE_PLAYER #if !defined(HAVE_POPEN) && defined(WIN32) diff --git a/source/libxmp-lite/src/load_helpers.c b/source/libxmp-lite/src/load_helpers.c index 37738121b..40cafe5db 100644 --- a/source/libxmp-lite/src/load_helpers.c +++ b/source/libxmp-lite/src/load_helpers.c @@ -1,5 +1,5 @@ /* Extended Module Player - * Copyright (C) 1996-2016 Claudio Matsuoka and Hipolito Carraro Jr + * Copyright (C) 1996-2018 Claudio Matsuoka and Hipolito Carraro Jr * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), diff --git a/source/libxmp-lite/src/memio.c b/source/libxmp-lite/src/memio.c index 7646f5540..5112d12c8 100644 --- a/source/libxmp-lite/src/memio.c +++ b/source/libxmp-lite/src/memio.c @@ -1,5 +1,5 @@ /* Extended Module Player - * Copyright (C) 1996-2016 Claudio Matsuoka and Hipolito Carraro Jr + * Copyright (C) 1996-2018 Claudio Matsuoka and Hipolito Carraro Jr * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), diff --git a/source/libxmp-lite/src/mix_all.c b/source/libxmp-lite/src/mix_all.c index cd5cda520..11ae8f691 100644 --- a/source/libxmp-lite/src/mix_all.c +++ b/source/libxmp-lite/src/mix_all.c @@ -1,5 +1,5 @@ /* Extended Module Player - * Copyright (C) 1996-2016 Claudio Matsuoka and Hipolito Carraro Jr + * Copyright (C) 1996-2018 Claudio Matsuoka and Hipolito Carraro Jr * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), diff --git a/source/libxmp-lite/src/mixer.c b/source/libxmp-lite/src/mixer.c index d4a3e6644..22020f47b 100644 --- a/source/libxmp-lite/src/mixer.c +++ b/source/libxmp-lite/src/mixer.c @@ -1,5 +1,5 @@ /* Extended Module Player - * Copyright (C) 1996-2016 Claudio Matsuoka and Hipolito Carraro Jr + * Copyright (C) 1996-2018 Claudio Matsuoka and Hipolito Carraro Jr * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), diff --git a/source/libxmp-lite/src/mod.h b/source/libxmp-lite/src/mod.h index 707d47cf2..8208c58e2 100644 --- a/source/libxmp-lite/src/mod.h +++ b/source/libxmp-lite/src/mod.h @@ -1,5 +1,5 @@ /* Extended Module Player - * Copyright (C) 1996-2016 Claudio Matsuoka and Hipolito Carraro Jr + * Copyright (C) 1996-2018 Claudio Matsuoka and Hipolito Carraro Jr * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), diff --git a/source/libxmp-lite/src/mtm_load.c b/source/libxmp-lite/src/mtm_load.c index d48401973..d4bc76068 100644 --- a/source/libxmp-lite/src/mtm_load.c +++ b/source/libxmp-lite/src/mtm_load.c @@ -1,5 +1,5 @@ /* Extended Module Player - * Copyright (C) 1996-2016 Claudio Matsuoka and Hipolito Carraro Jr + * Copyright (C) 1996-2018 Claudio Matsuoka and Hipolito Carraro Jr * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), diff --git a/source/libxmp-lite/src/period.c b/source/libxmp-lite/src/period.c index 7728902a0..582eba0df 100644 --- a/source/libxmp-lite/src/period.c +++ b/source/libxmp-lite/src/period.c @@ -1,5 +1,5 @@ /* Extended Module Player - * Copyright (C) 1996-2016 Claudio Matsuoka and Hipolito Carraro Jr + * Copyright (C) 1996-2018 Claudio Matsuoka and Hipolito Carraro Jr * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -138,10 +138,12 @@ static uint16 pt_period_table[16][36] = { #define M_LN2 0.69314718055994530942 #endif #if !defined(HAVE_ROUND) || defined(_MSC_VER) || defined(__WATCOMC__) -static inline double round(double val) +static inline double libxmp_round(double val) { return (val >= 0.0)? floor(val + 0.5) : ceil(val - 0.5); } +#else +#define libxmp_round round #endif #ifdef LIBXMP_PAULA_SIMULATOR @@ -219,7 +221,7 @@ int libxmp_period_to_note(int p) return 0; } - return (int)round(12.0 * log(PERIOD_BASE / p) / M_LN2) + 1; + return libxmp_round(12.0 * log(PERIOD_BASE / p) / M_LN2) + 1; } /* Get pitchbend from base note and amiga period */ @@ -237,11 +239,11 @@ int libxmp_period_to_bend(struct context_data *ctx, double p, int n, double adj) return (int) (100 * (8 * (((240 - n) << 4) - p))); case PERIOD_CSPD: d = libxmp_note_to_period(ctx, n, 0, adj); - return (int) round(100.0 * (1536.0 / M_LN2) * log(p / d)); + return libxmp_round(100.0 * (1536.0 / M_LN2) * log(p / d)); default: /* Amiga */ d = libxmp_note_to_period(ctx, n, 0, adj); - return (int) round(100.0 * (1536.0 / M_LN2) * log(d / p)); + return libxmp_round(100.0 * (1536.0 / M_LN2) * log(d / p)); } } diff --git a/source/libxmp-lite/src/player.c b/source/libxmp-lite/src/player.c index a75b6d368..834c03095 100644 --- a/source/libxmp-lite/src/player.c +++ b/source/libxmp-lite/src/player.c @@ -1,5 +1,5 @@ /* Extended Module Player - * Copyright (C) 1996-2016 Claudio Matsuoka and Hipolito Carraro Jr + * Copyright (C) 1996-2018 Claudio Matsuoka and Hipolito Carraro Jr * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -1502,8 +1502,13 @@ int xmp_start_player(xmp_context opaque, int rate, int format) p->loop_count = 0; p->sequence = 0; - /* Unmute all channels and set default volume */ - for (i = 0; i < XMP_MAX_CHANNELS; i++) { + /* Set default volume and mute status */ + for (i = 0; i < mod->chn; i++) { + if (mod->xxc[i].flg & XMP_CHANNEL_MUTE) + p->channel_mute[i] = 1; + p->channel_vol[i] = 100; + } + for (i = mod->chn; i < XMP_MAX_CHANNELS; i++) { p->channel_mute[i] = 0; p->channel_vol[i] = 100; } @@ -1553,6 +1558,9 @@ int xmp_start_player(xmp_context opaque, int rate, int format) goto err1; } + /* Reset our buffer pointers */ + xmp_play_buffer(opaque, NULL, 0, 0); + #ifndef LIBXMP_CORE_PLAYER for (i = 0; i < p->virt.virt_channels; i++) { struct channel_data *xc = &p->xc_data[i]; diff --git a/source/libxmp-lite/src/read_event.c b/source/libxmp-lite/src/read_event.c index 168f95d44..55a7f9bf3 100644 --- a/source/libxmp-lite/src/read_event.c +++ b/source/libxmp-lite/src/read_event.c @@ -1,5 +1,5 @@ /* Extended Module Player - * Copyright (C) 1996-2016 Claudio Matsuoka and Hipolito Carraro Jr + * Copyright (C) 1996-2018 Claudio Matsuoka and Hipolito Carraro Jr * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), diff --git a/source/libxmp-lite/src/s3m.h b/source/libxmp-lite/src/s3m.h index 122e2d711..56717c57a 100644 --- a/source/libxmp-lite/src/s3m.h +++ b/source/libxmp-lite/src/s3m.h @@ -1,5 +1,5 @@ /* Extended Module Player - * Copyright (C) 1996-2016 Claudio Matsuoka and Hipolito Carraro Jr + * Copyright (C) 1996-2018 Claudio Matsuoka and Hipolito Carraro Jr * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), diff --git a/source/libxmp-lite/src/s3m_load.c b/source/libxmp-lite/src/s3m_load.c index 66a580dbd..611fb0bd6 100644 --- a/source/libxmp-lite/src/s3m_load.c +++ b/source/libxmp-lite/src/s3m_load.c @@ -1,5 +1,5 @@ /* Extended Module Player - * Copyright (C) 1996-2016 Claudio Matsuoka and Hipolito Carraro Jr + * Copyright (C) 1996-2018 Claudio Matsuoka and Hipolito Carraro Jr * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), diff --git a/source/libxmp-lite/src/sample.c b/source/libxmp-lite/src/sample.c index 3eb31dc98..a81939e57 100644 --- a/source/libxmp-lite/src/sample.c +++ b/source/libxmp-lite/src/sample.c @@ -1,5 +1,5 @@ /* Extended Module Player - * Copyright (C) 1996-2016 Claudio Matsuoka and Hipolito Carraro Jr + * Copyright (C) 1996-2018 Claudio Matsuoka and Hipolito Carraro Jr * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), diff --git a/source/libxmp-lite/src/scan.c b/source/libxmp-lite/src/scan.c index 42b310659..f3358c3fc 100644 --- a/source/libxmp-lite/src/scan.c +++ b/source/libxmp-lite/src/scan.c @@ -1,5 +1,5 @@ /* Extended Module Player - * Copyright (C) 1996-2016 Claudio Matsuoka and Hipolito Carraro Jr + * Copyright (C) 1996-2018 Claudio Matsuoka and Hipolito Carraro Jr * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), diff --git a/source/libxmp-lite/src/smix.c b/source/libxmp-lite/src/smix.c index bf501d7c3..878d35970 100644 --- a/source/libxmp-lite/src/smix.c +++ b/source/libxmp-lite/src/smix.c @@ -1,5 +1,5 @@ /* Extended Module Player - * Copyright (C) 1996-2016 Claudio Matsuoka and Hipolito Carraro Jr + * Copyright (C) 1996-2018 Claudio Matsuoka and Hipolito Carraro Jr * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -251,7 +251,7 @@ int xmp_smix_load_sample(xmp_context opaque, int num, char *path) retval = -XMP_ERROR_SYSTEM; goto err2; } - size = hio_read32l(h) / (bits / 8); + size = hio_read32l(h); if (size == 0) { retval = -XMP_ERROR_FORMAT; goto err2; @@ -264,11 +264,17 @@ int xmp_smix_load_sample(xmp_context opaque, int num, char *path) xxs->lpe = 0; xxs->flg = bits == 16 ? XMP_SAMPLE_16BIT : 0; - xxs->data = (unsigned char *)malloc(size); + xxs->data = malloc(size + 8); if (xxs->data == NULL) { retval = -XMP_ERROR_SYSTEM; goto err2; } + + /* ugly hack to make the interpolator happy */ + memset(xxs->data, 0, 4); + memset(xxs->data + 4 + size, 0, 4); + xxs->data += 4; + if (hio_seek(h, 44, SEEK_SET) < 0) { retval = -XMP_ERROR_SYSTEM; goto err2; @@ -300,7 +306,9 @@ int xmp_smix_release_sample(xmp_context opaque, int num) return -XMP_ERROR_INVALID; } - free(smix->xxs[num].data); + if (smix->xxs[num].data != NULL) { + free(smix->xxs[num].data - 4); + } free(smix->xxi[num].sub); smix->xxs[num].data = NULL; @@ -322,3 +330,4 @@ void xmp_end_smix(xmp_context opaque) free(smix->xxs); free(smix->xxi); } + diff --git a/source/libxmp-lite/src/virtual.c b/source/libxmp-lite/src/virtual.c index 4fa5cb1b1..77bcb6014 100644 --- a/source/libxmp-lite/src/virtual.c +++ b/source/libxmp-lite/src/virtual.c @@ -1,5 +1,5 @@ /* Extended Module Player - * Copyright (C) 1996-2016 Claudio Matsuoka and Hipolito Carraro Jr + * Copyright (C) 1996-2018 Claudio Matsuoka and Hipolito Carraro Jr * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), diff --git a/source/libxmp-lite/src/xm_load.c b/source/libxmp-lite/src/xm_load.c index 7ccbc6ac8..e310f5d17 100644 --- a/source/libxmp-lite/src/xm_load.c +++ b/source/libxmp-lite/src/xm_load.c @@ -1,5 +1,5 @@ /* Extended Module Player - * Copyright (C) 1996-2016 Claudio Matsuoka and Hipolito Carraro Jr + * Copyright (C) 1996-2018 Claudio Matsuoka and Hipolito Carraro Jr * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -351,6 +351,7 @@ static int load_instruments(struct module_data *m, int version, HIO_HANDLE * f) struct xm_instrument xi; struct xm_sample_header xsh[16]; int sample_num = 0; + long total_sample_size; int i, j; uint8 buf[208]; @@ -363,6 +364,7 @@ static int load_instruments(struct module_data *m, int version, HIO_HANDLE * f) return -1; for (i = 0; i < mod->ins; i++) { + long instr_pos = hio_tell(f); struct xmp_instrument *xxi = &mod->xxi[i]; /* Modules converted with MOD2XM 1.0 always say we have 31 @@ -571,6 +573,7 @@ static int load_instruments(struct module_data *m, int version, HIO_HANDLE * f) xxs->flg |= xsh[j].type & XM_LOOP_PINGPONG ? XMP_SAMPLE_LOOP | XMP_SAMPLE_LOOP_BIDIR : 0; } + total_sample_size = 0; for (j = 0; j < xxi->nsm; j++) { struct xmp_subinstrument *sub = &xxi->sub[j]; int flags; @@ -595,7 +598,19 @@ static int load_instruments(struct module_data *m, int version, HIO_HANDLE * f) if (libxmp_load_sample(m, f, flags, &mod->xxs[sub->sid], NULL) < 0) { return -1; } + if (flags & SAMPLE_FLAG_ADPCM) { + total_sample_size += 16 + ((xsh[j].length + 1) >> 1); + } else { + total_sample_size += xsh[j].length; + } } + } + + /* Reposition correctly in case of 16-bit sample having odd in-file length. + * See "Lead Lined for '99", reported by Dennis Mulleneers. + */ + if (hio_seek(f, instr_pos + xih.size + 40 * xih.samples + total_sample_size, SEEK_SET) < 0) { + return -1; } }