diff --git a/source/libxmp-lite/README b/source/libxmp-lite/README deleted file mode 100644 index c309e6b08..000000000 --- a/source/libxmp-lite/README +++ /dev/null @@ -1,42 +0,0 @@ - __ _ __ ___ __ - / / (_) / __ __ __ _ ___ ____/ (_) /____ - / /__/ / _ \\ \ // ' \/ _ \/___/ / / __/ -_) -/____/_/_.__/_\_\/_/_/_/ .__/ /_/_/\__/\__/ - /_/ - -Libxmp-lite is a lean and lightweight subset of Libxmp that plays MOD, S3M, -XM, and IT modules and retains full compatibility with the original API. -It's intended for games and small or embedded applications where module -format diversity and file depacking are not required. - -Library size can be further reduced by disabling Impulse Tracker format -support (configure with --disable-it). This option will also disable IT -effects and lowpass filtering. - -Please refer to http://xmp.sf.net/libxmp.html for details on the current -Libxmp API. - - -LICENSE - -Extended Module Player Lite -Copyright (C) 1996-2016 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"), -to deal in the Software without restriction, including without limitation -the rights to use, copy, modify, merge, publish, distribute, sublicense, -and/or sell copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - diff --git a/source/libxmp-lite/include/libxmp-lite/xmp.h b/source/libxmp-lite/include/libxmp-lite/xmp.h deleted file mode 100644 index 74411aedc..000000000 --- a/source/libxmp-lite/include/libxmp-lite/xmp.h +++ /dev/null @@ -1,375 +0,0 @@ -#ifndef XMP_H -#define XMP_H - -#ifdef __cplusplus -extern "C" { -#endif - -#define XMP_VERSION "4.5.0" -#define XMP_VERCODE 0x040500 -#define XMP_VER_MAJOR 4 -#define XMP_VER_MINOR 5 -#define XMP_VER_RELEASE 0 -#define BUILDING_STATIC - - -#if defined(_WIN32) && !defined(__CYGWIN__) -# if defined(BUILDING_STATIC) -# define LIBXMP_EXPORT -# elif defined(BUILDING_DLL) -# define LIBXMP_EXPORT __declspec(dllexport) -# else -# define LIBXMP_EXPORT __declspec(dllimport) -# endif -#elif defined(__OS2__) && defined(__WATCOMC__) && defined(__SW_BD) -# define LIBXMP_EXPORT __declspec(dllexport) -#elif (defined(__GNUC__) || defined(__clang__) || defined(__HP_cc)) && defined(XMP_SYM_VISIBILITY) -# define LIBXMP_EXPORT __attribute__((visibility ("default"))) -#elif defined(__SUNPRO_C) && defined(XMP_LDSCOPE_GLOBAL) -# define LIBXMP_EXPORT __global -#elif defined(EMSCRIPTEN) -# define LIBXMP_EXPORT EMSCRIPTEN_KEEPALIVE -#else -# define LIBXMP_EXPORT -#endif - -#define XMP_NAME_SIZE 64 /* Size of module name and type */ - -#define XMP_KEY_OFF 0x81 /* Note number for key off event */ -#define XMP_KEY_CUT 0x82 /* Note number for key cut event */ -#define XMP_KEY_FADE 0x83 /* Note number for fade event */ - -/* mixer parameter macros */ - -/* sample format flags */ -#define XMP_FORMAT_8BIT (1 << 0) /* Mix to 8-bit instead of 16 */ -#define XMP_FORMAT_UNSIGNED (1 << 1) /* Mix to unsigned samples */ -#define XMP_FORMAT_MONO (1 << 2) /* Mix to mono instead of stereo */ - -/* player parameters */ -#define XMP_PLAYER_AMP 0 /* Amplification factor */ -#define XMP_PLAYER_MIX 1 /* Stereo mixing */ -#define XMP_PLAYER_INTERP 2 /* Interpolation type */ -#define XMP_PLAYER_DSP 3 /* DSP effect flags */ -#define XMP_PLAYER_FLAGS 4 /* Player flags */ -#define XMP_PLAYER_CFLAGS 5 /* Player flags for current module */ -#define XMP_PLAYER_SMPCTL 6 /* Sample control flags */ -#define XMP_PLAYER_VOLUME 7 /* Player module volume */ -#define XMP_PLAYER_STATE 8 /* Internal player state (read only) */ -#define XMP_PLAYER_SMIX_VOLUME 9 /* SMIX volume */ -#define XMP_PLAYER_DEFPAN 10 /* Default pan setting */ -#define XMP_PLAYER_MODE 11 /* Player personality */ -#define XMP_PLAYER_MIXER_TYPE 12 /* Current mixer (read only) */ -#define XMP_PLAYER_VOICES 13 /* Maximum number of mixer voices */ - -/* interpolation types */ -#define XMP_INTERP_NEAREST 0 /* Nearest neighbor */ -#define XMP_INTERP_LINEAR 1 /* Linear (default) */ -#define XMP_INTERP_SPLINE 2 /* Cubic spline */ - -/* dsp effect types */ -#define XMP_DSP_LOWPASS (1 << 0) /* Lowpass filter effect */ -#define XMP_DSP_ALL (XMP_DSP_LOWPASS) - -/* player state */ -#define XMP_STATE_UNLOADED 0 /* Context created */ -#define XMP_STATE_LOADED 1 /* Module loaded */ -#define XMP_STATE_PLAYING 2 /* Module playing */ - -/* player flags */ -#define XMP_FLAGS_VBLANK (1 << 0) /* Use vblank timing */ -#define XMP_FLAGS_FX9BUG (1 << 1) /* Emulate FX9 bug */ -#define XMP_FLAGS_FIXLOOP (1 << 2) /* Emulate sample loop bug */ -#define XMP_FLAGS_A500 (1 << 3) /* Use Paula mixer in Amiga modules */ - -/* player modes */ -#define XMP_MODE_AUTO 0 /* Autodetect mode (default) */ -#define XMP_MODE_MOD 1 /* Play as a generic MOD player */ -#define XMP_MODE_NOISETRACKER 2 /* Play using Noisetracker quirks */ -#define XMP_MODE_PROTRACKER 3 /* Play using Protracker quirks */ -#define XMP_MODE_S3M 4 /* Play as a generic S3M player */ -#define XMP_MODE_ST3 5 /* Play using ST3 bug emulation */ -#define XMP_MODE_ST3GUS 6 /* Play using ST3+GUS quirks */ -#define XMP_MODE_XM 7 /* Play as a generic XM player */ -#define XMP_MODE_FT2 8 /* Play using FT2 bug emulation */ -#define XMP_MODE_IT 9 /* Play using IT quirks */ -#define XMP_MODE_ITSMP 10 /* Play using IT sample mode quirks */ - -/* mixer types */ -#define XMP_MIXER_STANDARD 0 /* Standard mixer */ -#define XMP_MIXER_A500 1 /* Amiga 500 */ -#define XMP_MIXER_A500F 2 /* Amiga 500 with led filter */ - -/* sample flags */ -#define XMP_SMPCTL_SKIP (1 << 0) /* Don't load samples */ - -/* limits */ -#define XMP_MAX_KEYS 121 /* Number of valid keys */ -#define XMP_MAX_ENV_POINTS 32 /* Max number of envelope points */ -#define XMP_MAX_MOD_LENGTH 256 /* Max number of patterns in module */ -#define XMP_MAX_CHANNELS 64 /* Max number of channels in module */ -#define XMP_MAX_SRATE 49170 /* max sampling rate (Hz) */ -#define XMP_MIN_SRATE 4000 /* min sampling rate (Hz) */ -#define XMP_MIN_BPM 20 /* min BPM */ -/* frame rate = (50 * bpm / 125) Hz */ -/* frame size = (sampling rate * channels * size) / frame rate */ -#define XMP_MAX_FRAMESIZE (5 * XMP_MAX_SRATE * 2 / XMP_MIN_BPM) - -/* error codes */ -#define XMP_END 1 -#define XMP_ERROR_INTERNAL 2 /* Internal error */ -#define XMP_ERROR_FORMAT 3 /* Unsupported module format */ -#define XMP_ERROR_LOAD 4 /* Error loading file */ -#define XMP_ERROR_DEPACK 5 /* Error depacking file */ -#define XMP_ERROR_SYSTEM 6 /* System error */ -#define XMP_ERROR_INVALID 7 /* Invalid parameter */ -#define XMP_ERROR_STATE 8 /* Invalid player state */ - -struct xmp_channel { - int pan; /* Channel pan (0x80 is center) */ - int vol; /* Channel volume */ -#define XMP_CHANNEL_SYNTH (1 << 0) /* Channel is synthesized */ -#define XMP_CHANNEL_MUTE (1 << 1) /* Channel is muted */ -#define XMP_CHANNEL_SPLIT (1 << 2) /* Split Amiga channel in bits 5-4 */ -#define XMP_CHANNEL_SURROUND (1 << 4) /* Surround channel */ - int flg; /* Channel flags */ -}; - -struct xmp_pattern { - int rows; /* Number of rows */ - int index[1]; /* Track index */ -}; - -struct xmp_event { - unsigned char note; /* Note number (0 means no note) */ - unsigned char ins; /* Patch number */ - unsigned char vol; /* Volume (0 to basevol) */ - unsigned char fxt; /* Effect type */ - unsigned char fxp; /* Effect parameter */ - unsigned char f2t; /* Secondary effect type */ - unsigned char f2p; /* Secondary effect parameter */ - unsigned char _flag; /* Internal (reserved) flags */ -}; - -struct xmp_track { - int rows; /* Number of rows */ - struct xmp_event event[1]; /* Event data */ -}; - -struct xmp_envelope { -#define XMP_ENVELOPE_ON (1 << 0) /* Envelope is enabled */ -#define XMP_ENVELOPE_SUS (1 << 1) /* Envelope has sustain point */ -#define XMP_ENVELOPE_LOOP (1 << 2) /* Envelope has loop */ -#define XMP_ENVELOPE_FLT (1 << 3) /* Envelope is used for filter */ -#define XMP_ENVELOPE_SLOOP (1 << 4) /* Envelope has sustain loop */ -#define XMP_ENVELOPE_CARRY (1 << 5) /* Don't reset envelope position */ - int flg; /* Flags */ - int npt; /* Number of envelope points */ - int scl; /* Envelope scaling */ - int sus; /* Sustain start point */ - int sue; /* Sustain end point */ - int lps; /* Loop start point */ - int lpe; /* Loop end point */ - short data[XMP_MAX_ENV_POINTS * 2]; -}; - -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 */ -#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 */ -#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 */ -#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 */ -}; - - -struct xmp_instrument { - char name[32]; /* Instrument name */ - int vol; /* Instrument volume */ - int nsm; /* Number of samples */ - int rls; /* Release (fadeout) */ - struct xmp_envelope aei; /* Amplitude envelope info */ - struct xmp_envelope pei; /* Pan envelope info */ - struct xmp_envelope fei; /* Frequency envelope info */ - - struct { - unsigned char ins; /* Instrument number for each key */ - signed char xpo; /* Instrument transpose for each key */ - } map[XMP_MAX_KEYS]; - - struct xmp_subinstrument *sub; - - void *extra; /* Extra fields */ -}; - -struct xmp_sample { - char name[32]; /* Sample name */ - int len; /* Sample length */ - int lps; /* Loop start */ - int lpe; /* Loop end */ -#define XMP_SAMPLE_16BIT (1 << 0) /* 16bit sample */ -#define XMP_SAMPLE_LOOP (1 << 1) /* Sample is looped */ -#define XMP_SAMPLE_LOOP_BIDIR (1 << 2) /* Bidirectional sample loop */ -#define XMP_SAMPLE_LOOP_REVERSE (1 << 3) /* Backwards sample loop */ -#define XMP_SAMPLE_LOOP_FULL (1 << 4) /* Play full sample before looping */ -#define XMP_SAMPLE_SLOOP (1 << 5) /* Sample has sustain loop */ -#define XMP_SAMPLE_SLOOP_BIDIR (1 << 6) /* Bidirectional sustain loop */ -#define XMP_SAMPLE_SYNTH (1 << 15) /* Data contains synth patch */ - int flg; /* Flags */ - unsigned char *data; /* Sample data */ -}; - -struct xmp_sequence { - int entry_point; - int duration; -}; - -struct xmp_module { - char name[XMP_NAME_SIZE]; /* Module title */ - char type[XMP_NAME_SIZE]; /* Module format */ - int pat; /* Number of patterns */ - int trk; /* Number of tracks */ - int chn; /* Tracks per pattern */ - int ins; /* Number of instruments */ - int smp; /* Number of samples */ - int spd; /* Initial speed */ - int bpm; /* Initial BPM */ - int len; /* Module length in patterns */ - int rst; /* Restart position */ - int gvl; /* Global volume */ - - struct xmp_pattern **xxp; /* Patterns */ - struct xmp_track **xxt; /* Tracks */ - struct xmp_instrument *xxi; /* Instruments */ - struct xmp_sample *xxs; /* Samples */ - struct xmp_channel xxc[XMP_MAX_CHANNELS]; /* Channel info */ - unsigned char xxo[XMP_MAX_MOD_LENGTH]; /* Orders */ -}; - -struct xmp_test_info { - char name[XMP_NAME_SIZE]; /* Module title */ - char type[XMP_NAME_SIZE]; /* Module format */ -}; - -struct xmp_module_info { - unsigned char md5[16]; /* MD5 message digest */ - int vol_base; /* Volume scale */ - struct xmp_module *mod; /* Pointer to module data */ - char *comment; /* Comment text, if any */ - int num_sequences; /* Number of valid sequences */ - struct xmp_sequence *seq_data; /* Pointer to sequence data */ -}; - -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 */ -}; - - -struct xmp_frame_info { /* Current frame information */ - int pos; /* Current position */ - int pattern; /* Current pattern */ - int row; /* Current row in pattern */ - int num_rows; /* Number of rows in current pattern */ - int frame; /* Current frame */ - int speed; /* Current replay speed */ - int bpm; /* Current bpm */ - int time; /* Current module time in ms */ - int total_time; /* Estimated replay time in ms*/ - int frame_time; /* Frame replay time in us */ - void *buffer; /* Pointer to sound buffer */ - int buffer_size; /* Used buffer size */ - int total_size; /* Total buffer size */ - int volume; /* Current master volume */ - int loop_count; /* Loop counter */ - int virt_channels; /* Number of virtual channels */ - int virt_used; /* Used virtual channels */ - int sequence; /* Current sequence */ - - struct xmp_channel_info channel_info[XMP_MAX_CHANNELS]; -}; - - -typedef char *xmp_context; - -LIBXMP_EXPORT extern const char *xmp_version; -LIBXMP_EXPORT extern const unsigned int xmp_vercode; - -LIBXMP_EXPORT xmp_context xmp_create_context (void); -LIBXMP_EXPORT void xmp_free_context (xmp_context); -#ifdef EDUKE32_DISABLED -LIBXMP_EXPORT int xmp_test_module (char *, struct xmp_test_info *); -LIBXMP_EXPORT int xmp_load_module (xmp_context, char *); -#endif -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 -LIBXMP_EXPORT int xmp_load_module_from_file (xmp_context, void *, long); -#endif -/* External sample mixer API */ -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 -LIBXMP_EXPORT int xmp_smix_load_sample (xmp_context, int, char *); -#endif -LIBXMP_EXPORT int xmp_smix_release_sample (xmp_context, int); - -#ifdef __cplusplus -} -#endif - -#endif /* XMP_H */ diff --git a/source/libxmp-lite/src/common.c b/source/libxmp-lite/src/common.c deleted file mode 100644 index ed38442c1..000000000 --- a/source/libxmp-lite/src/common.c +++ /dev/null @@ -1,366 +0,0 @@ -/* Extended Module Player - * 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"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include -#include -#include -#ifdef __WATCOMC__ -#include -#elif !defined(_WIN32) -#include -#endif - -#include "xmp.h" -#include "common.h" -#include "period.h" -#include "loader.h" - -int libxmp_init_instrument(struct module_data *m) -{ - struct xmp_module *mod = &m->mod; - - if (mod->ins > 0) { - mod->xxi = (struct xmp_instrument *)calloc(sizeof (struct xmp_instrument), mod->ins); - if (mod->xxi == NULL) - return -1; - } - - if (mod->smp > 0) { - int i; - - mod->xxs = (struct xmp_sample *)calloc(sizeof (struct xmp_sample), mod->smp); - if (mod->xxs == NULL) - return -1; - m->xtra = (struct extra_sample_data *)calloc(sizeof (struct extra_sample_data), mod->smp); - if (m->xtra == NULL) - return -1; - - for (i = 0; i < mod->smp; i++) { - m->xtra[i].c5spd = m->c4rate; - } - } - - return 0; -} - -int libxmp_alloc_subinstrument(struct xmp_module *mod, int i, int num) -{ - if (num == 0) - return 0; - - mod->xxi[i].sub = (struct xmp_subinstrument *)calloc(sizeof (struct xmp_subinstrument), num); - if (mod->xxi[i].sub == NULL) - return -1; - - return 0; -} - -int libxmp_init_pattern(struct xmp_module *mod) -{ - mod->xxt = (struct xmp_track **)calloc(sizeof (struct xmp_track *), mod->trk); - if (mod->xxt == NULL) - return -1; - - mod->xxp = (struct xmp_pattern **)calloc(sizeof (struct xmp_pattern *), mod->pat); - if (mod->xxp == NULL) - return -1; - - return 0; -} - -int libxmp_alloc_pattern(struct xmp_module *mod, int num) -{ - /* Sanity check */ - if (num < 0 || num >= mod->pat || mod->xxp[num] != NULL) - return -1; - - mod->xxp[num] = (struct xmp_pattern *)calloc(1, sizeof (struct xmp_pattern) + - sizeof (int) * (mod->chn - 1)); - if (mod->xxp[num] == NULL) - return -1; - - return 0; -} - -int libxmp_alloc_track(struct xmp_module *mod, int num, int rows) -{ - /* Sanity check */ - if (num < 0 || num >= mod->trk || mod->xxt[num] != NULL || rows <= 0) - return -1; - - mod->xxt[num] = (struct xmp_track *)calloc(sizeof (struct xmp_track) + - sizeof (struct xmp_event) * (rows - 1), 1); - if (mod->xxt[num] == NULL) - return -1; - - mod->xxt[num]->rows = rows; - - return 0; -} - -int libxmp_alloc_tracks_in_pattern(struct xmp_module *mod, int num) -{ - int i; - - D_(D_INFO "Alloc %d tracks of %d rows", mod->chn, mod->xxp[num]->rows); - for (i = 0; i < mod->chn; i++) { - int t = num * mod->chn + i; - int rows = mod->xxp[num]->rows; - - if (libxmp_alloc_track(mod, t, rows) < 0) - return -1; - - mod->xxp[num]->index[i] = t; - } - - return 0; -} - -int libxmp_alloc_pattern_tracks(struct xmp_module *mod, int num, int rows) -{ - /* Sanity check */ - if (rows < 0 || rows > 256) - return -1; - - if (libxmp_alloc_pattern(mod, num) < 0) - return -1; - - mod->xxp[num]->rows = rows; - - if (libxmp_alloc_tracks_in_pattern(mod, num) < 0) - return -1; - - return 0; -} - -/* Sample number adjustment by Vitamin/CAIG */ -struct xmp_sample *libxmp_realloc_samples(struct xmp_sample *buf, int *size, int new_size) -{ - buf = (struct xmp_sample *)realloc(buf, sizeof (struct xmp_sample) * new_size); - if (buf == NULL) - return NULL; - if (new_size > *size) - memset(buf + *size, 0, sizeof (struct xmp_sample) * (new_size - *size)); - *size = new_size; - - return buf; -} - -char *libxmp_instrument_name(struct xmp_module *mod, int i, uint8 *r, int n) -{ - CLAMP(n, 0, 31); - - return libxmp_copy_adjust(mod->xxi[i].name, r, n); -} - -char *libxmp_copy_adjust(char *s, uint8 *r, int n) -{ - int i; - - memset(s, 0, n + 1); - strncpy(s, (char *)r, n); - - for (i = 0; s[i] && i < n; i++) { - if (!isprint((int)s[i]) || ((uint8)s[i] > 127)) - s[i] = '.'; - } - - while (*s && (s[strlen(s) - 1] == ' ')) - s[strlen(s) - 1] = 0; - - return s; -} - -void libxmp_read_title(HIO_HANDLE *f, char *t, int s) -{ - uint8 buf[XMP_NAME_SIZE]; - - if (t == NULL) - return; - - if (s >= XMP_NAME_SIZE) - s = XMP_NAME_SIZE -1; - - memset(t, 0, s + 1); - - hio_read(buf, 1, s, f); /* coverity[check_return] */ - buf[s] = 0; - libxmp_copy_adjust(t, buf, s); -} - -#ifndef LIBXMP_CORE_PLAYER - -int libxmp_test_name(uint8 *s, int n) -{ - int i; - - for (i = 0; i < n; i++) { - if (s[i] > 0x7f) - return -1; - /* ACS_Team2.mod has a backspace in instrument name */ - if (s[i] > 0 && s[i] < 32 && s[i] != 0x08) - return -1; - } - - return 0; -} - -/* - * Honor Noisetracker effects: - * - * 0 - arpeggio - * 1 - portamento up - * 2 - portamento down - * 3 - Tone-portamento - * 4 - Vibrato - * A - Slide volume - * B - Position jump - * C - Set volume - * D - Pattern break - * E - Set filter (keep the led off, please!) - * F - Set speed (now up to $1F) - * - * Pex Tufvesson's notes from http://www.livet.se/mahoney/: - * - * Note that some of the modules will have bugs in the playback with all - * known PC module players. This is due to that in many demos where I synced - * events in the demo with the music, I used commands that these newer PC - * module players erroneously interpret as "newer-version-trackers commands". - * Which they aren't. - */ -void libxmp_decode_noisetracker_event(struct xmp_event *event, uint8 *mod_event) -{ - int fxt; - - memset(event, 0, sizeof (struct xmp_event)); - event->note = libxmp_period_to_note((LSN(mod_event[0]) << 8) + mod_event[1]); - event->ins = ((MSN(mod_event[0]) << 4) | MSN(mod_event[2])); - fxt = LSN(mod_event[2]); - - if (fxt <= 0x06 || (fxt >= 0x0a && fxt != 0x0e)) { - event->fxt = fxt; - event->fxp = mod_event[3]; - } - - libxmp_disable_continue_fx(event); -} -#endif - -void libxmp_decode_protracker_event(struct xmp_event *event, uint8 *mod_event) -{ - int fxt = LSN(mod_event[2]); - - memset(event, 0, sizeof (struct xmp_event)); - event->note = libxmp_period_to_note((LSN(mod_event[0]) << 8) + mod_event[1]); - event->ins = ((MSN(mod_event[0]) << 4) | MSN(mod_event[2])); - - if (fxt != 0x08) { - event->fxt = fxt; - event->fxp = mod_event[3]; - } - - libxmp_disable_continue_fx(event); -} - -void libxmp_disable_continue_fx(struct xmp_event *event) -{ - if (event->fxp == 0) { - switch (event->fxt) { - case 0x05: - event->fxt = 0x03; - break; - case 0x06: - event->fxt = 0x04; - break; - case 0x01: - case 0x02: - case 0x0a: - event->fxt = 0x00; - } - } else if (event->fxt == 0x0e) { - if (event->fxp == 0xa0 || event->fxp == 0xb0) { - event->fxt = event->fxp = 0; - } - } -} - -#ifndef LIBXMP_CORE_PLAYER -#ifndef WIN32 - -/* Given a directory, see if file exists there, ignoring case */ - -int libxmp_check_filename_case(char *dir, char *name, char *new_name, int size) -{ - int found = 0; - DIR *dirfd; - struct dirent *d; - - dirfd = opendir(dir); - if (dirfd == NULL) - return 0; - - while ((d = readdir(dirfd))) { - if (!strcasecmp(d->d_name, name)) { - found = 1; - break; - } - } - - if (found) - strncpy(new_name, d->d_name, size); - - closedir(dirfd); - - return found; -} - -#else - -/* FIXME: implement functionality for Win32 */ - -int libxmp_check_filename_case(char *dir, char *name, char *new_name, int size) -{ - return 0; -} - -#endif - -void libxmp_get_instrument_path(struct module_data *m, char *path, int size) -{ - if (m->instrument_path) { - strncpy(path, m->instrument_path, size); - } else if (getenv("XMP_INSTRUMENT_PATH")) { - strncpy(path, getenv("XMP_INSTRUMENT_PATH"), size); - } else { - strncpy(path, ".", size); - } -} -#endif /* LIBXMP_CORE_PLAYER */ - -void libxmp_set_type(struct module_data *m, const char *fmt, ...) -{ - va_list ap; - va_start(ap, fmt); - - vsnprintf(m->mod.type, XMP_NAME_SIZE, fmt, ap); - va_end(ap); -} diff --git a/source/libxmp-lite/src/common.h b/source/libxmp-lite/src/common.h deleted file mode 100644 index 44634251d..000000000 --- a/source/libxmp-lite/src/common.h +++ /dev/null @@ -1,447 +0,0 @@ -#ifndef LIBXMP_COMMON_H -#define LIBXMP_COMMON_H - -#ifdef __AROS__ -#define __AMIGA__ -#endif - -#include -#include -#include -#include "xmp.h" - -#if (defined(__GNUC__) || defined(__clang__)) && defined(XMP_SYM_VISIBILITY) -#if !defined(WIN32) && !defined(__ANDROID__) && !defined(__APPLE__) && !defined(__AMIGA__) && !defined(__MSDOS__) && !defined(B_BEOS_VERSION) && !defined(__ATHEOS__) && !defined(EMSCRIPTEN) && !defined(__MINT__) -#define USE_VERSIONED_SYMBOLS -#endif -#endif - -/* AmigaOS fixes by Chris Young , Nov 25, 2007 - */ -#if defined B_BEOS_VERSION -# include -#elif defined __amigaos4__ -# include -#else -typedef signed char int8; -typedef signed short int int16; -typedef signed int int32; -typedef unsigned char uint8; -typedef unsigned short int uint16; -typedef unsigned int uint32; -#endif - -#ifdef _MSC_VER /* MSVC++6.0 has no long long */ -typedef signed __int64 int64; -typedef unsigned __int64 uint64; -#elif !defined B_BEOS_VERSION /* BeOS has its own int64 definition */ -typedef unsigned long long uint64; -typedef signed long long int64; -#endif - -#ifndef LIBXMP_CORE_PLAYER -#define LIBXMP_PAULA_SIMULATOR -#endif - -/* Constants */ -#define PAL_RATE 250.0 /* 1 / (50Hz * 80us) */ -#define NTSC_RATE 208.0 /* 1 / (60Hz * 80us) */ -#define C4_PAL_RATE 8287 /* 7093789.2 / period (C4) * 2 */ -#define C4_NTSC_RATE 8363 /* 7159090.5 / period (C4) * 2 */ - -/* [Amiga] PAL color carrier frequency (PCCF) = 4.43361825 MHz */ -/* [Amiga] CPU clock = 1.6 * PCCF = 7.0937892 MHz */ - -#define DEFAULT_AMPLIFY 1 -#define DEFAULT_MIX 100 - -#define MSN(x) (((x)&0xf0)>>4) -#define LSN(x) ((x)&0x0f) -#define SET_FLAG(a,b) ((a)|=(b)) -#define RESET_FLAG(a,b) ((a)&=~(b)) -#define TEST_FLAG(a,b) !!((a)&(b)) - -#define CLAMP(x,a,b) do { \ - if ((x) < (a)) (x) = (a); \ - else if ((x) > (b)) (x) = (b); \ -} while (0) -#define MIN(x,y) ((x) < (y) ? (x) : (y)) -#define MAX(x,y) ((x) > (y) ? (x) : (y)) - -#define TRACK_NUM(a,c) m->mod.xxp[a]->index[c] -#define EVENT(a,c,r) m->mod.xxt[TRACK_NUM((a),(c))]->event[r] - -#ifdef _MSC_VER -#define D_CRIT " Error: " -#define D_WARN "Warning: " -#define D_INFO " Info: " -#ifndef CLIB_DECL -#define CLIB_DECL -#endif -#ifdef DEBUG -#ifndef ATTR_PRINTF -#define ATTR_PRINTF(x,y) -#endif -void CLIB_DECL D_(const char *text, ...) ATTR_PRINTF(1,2); -#else -// VS prior to VC7.1 does not support variadic macros. VC8.0 does not optimize unused parameters passing -#if _MSC_VER < 1400 -void __inline CLIB_DECL D_(const char *text, ...) { do {} while (0); } -#else -#define D_(args, ...) do {} while (0) -#endif -#endif - -#elif defined __ANDROID__ - -#ifdef DEBUG -#include -#define D_CRIT " Error: " -#define D_WARN "Warning: " -#define D_INFO " Info: " -#define D_(args...) do { \ - __android_log_print(ANDROID_LOG_DEBUG, "libxmp", args); \ - } while (0) -#else -#define D_(args...) do {} while (0) -#endif - -#elif defined(__WATCOMC__) -#ifdef DEBUG -#define D_INFO "\x1b[33m" -#define D_CRIT "\x1b[31m" -#define D_WARN "\x1b[36m" -#define D_(...) do { \ - printf("\x1b[33m%s \x1b[37m[%s:%d] " D_INFO, __FUNCTION__, \ - __FILE__, __LINE__); printf (__VA_ARGS__); printf ("\x1b[0m\n"); \ - } while (0) -#else -#define D_(...) do {} while (0) -#endif - -#else - -#ifdef DEBUG -#define D_INFO "\x1b[33m" -#define D_CRIT "\x1b[31m" -#define D_WARN "\x1b[36m" -#define D_(args...) do { \ - printf("\x1b[33m%s \x1b[37m[%s:%d] " D_INFO, __FUNCTION__, \ - __FILE__, __LINE__); printf (args); printf ("\x1b[0m\n"); \ - } while (0) -#else -#define D_(args...) do {} while (0) -#endif - -#endif /* !_MSC_VER */ - -#ifdef _MSC_VER -#define dup _dup -#define fileno _fileno -#define strnicmp _strnicmp -#define strdup _strdup -#define fdopen _fdopen -#define open _open -#define close _close -#define unlink _unlink -#endif -#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 -#define vsnprintf libxmp_vsnprintf -#endif - -/* Quirks */ -#define QUIRK_S3MLOOP (1 << 0) /* S3M loop mode */ -#define QUIRK_ENVFADE (1 << 1) /* Fade at end of envelope */ -#define QUIRK_PROTRACK (1 << 2) /* Use Protracker-specific quirks */ -#define QUIRK_ST3BUGS (1 << 4) /* Scream Tracker 3 bug compatibility */ -#define QUIRK_FINEFX (1 << 5) /* Enable 0xf/0xe for fine effects */ -#define QUIRK_VSALL (1 << 6) /* Volume slides in all frames */ -#define QUIRK_PBALL (1 << 7) /* Pitch bending in all frames */ -#define QUIRK_PERPAT (1 << 8) /* Cancel persistent fx at pat start */ -#define QUIRK_VOLPDN (1 << 9) /* Set priority to volume slide down */ -#define QUIRK_UNISLD (1 << 10) /* Unified pitch slide/portamento */ -#define QUIRK_ITVPOR (1 << 11) /* Disable fine bends in IT vol fx */ -#define QUIRK_FTMOD (1 << 12) /* Flag for multichannel mods */ -/*#define QUIRK_MODRNG (1 << 13)*/ /* Limit periods to MOD range */ -#define QUIRK_INSVOL (1 << 14) /* Use instrument volume */ -#define QUIRK_VIRTUAL (1 << 15) /* Enable virtual channels */ -#define QUIRK_FILTER (1 << 16) /* Enable filter */ -#define QUIRK_IGSTPOR (1 << 17) /* Ignore stray tone portamento */ -#define QUIRK_KEYOFF (1 << 18) /* Keyoff doesn't reset fadeout */ -#define QUIRK_VIBHALF (1 << 19) /* Vibrato is half as deep */ -#define QUIRK_VIBALL (1 << 20) /* Vibrato in all frames */ -#define QUIRK_VIBINV (1 << 21) /* Vibrato has inverse waveform */ -#define QUIRK_PRENV (1 << 22) /* Portamento resets envelope & fade */ -#define QUIRK_ITOLDFX (1 << 23) /* IT old effects mode */ -#define QUIRK_S3MRTG (1 << 24) /* S3M-style retrig when count == 0 */ -#define QUIRK_RTDELAY (1 << 25) /* Delay effect retrigs instrument */ -#define QUIRK_FT2BUGS (1 << 26) /* FT2 bug compatibility */ -#define QUIRK_MARKER (1 << 27) /* Patterns 0xfe and 0xff reserved */ -#define QUIRK_NOBPM (1 << 28) /* Adjust speed only, no BPM */ -#define QUIRK_ARPMEM (1 << 29) /* Arpeggio has memory (S3M_ARPEGGIO) */ -#define QUIRK_RSTCHN (1 << 30) /* Reset channel on sample end */ - -#define HAS_QUIRK(x) (m->quirk & (x)) - - -/* Format quirks */ -#define QUIRKS_ST3 (QUIRK_S3MLOOP | QUIRK_VOLPDN | QUIRK_FINEFX | \ - QUIRK_S3MRTG | QUIRK_MARKER | QUIRK_RSTCHN ) -#define QUIRKS_FT2 (QUIRK_RTDELAY | QUIRK_FINEFX ) -#define QUIRKS_IT (QUIRK_S3MLOOP | QUIRK_FINEFX | QUIRK_VIBALL | \ - QUIRK_ENVFADE | QUIRK_ITVPOR | QUIRK_KEYOFF | \ - QUIRK_VIRTUAL | QUIRK_FILTER | QUIRK_RSTCHN | \ - QUIRK_IGSTPOR | QUIRK_S3MRTG | QUIRK_MARKER ) - -/* DSP effects */ -#define DSP_EFFECT_CUTOFF 0x02 -#define DSP_EFFECT_RESONANCE 0x03 -#define DSP_EFFECT_FILTER_A0 0xb0 -#define DSP_EFFECT_FILTER_B0 0xb1 -#define DSP_EFFECT_FILTER_B1 0xb2 - -/* Time factor */ -#define DEFAULT_TIME_FACTOR 10.0 -#define MED_TIME_FACTOR 2.64 - -#define MAX_SEQUENCES 16 -#define MAX_SAMPLE_SIZE 0x10000000 -#define MAX_SAMPLES 1024 - -#define IS_PLAYER_MODE_MOD() (m->read_event_type == READ_EVENT_MOD) -#define IS_PLAYER_MODE_FT2() (m->read_event_type == READ_EVENT_FT2) -#define IS_PLAYER_MODE_ST3() (m->read_event_type == READ_EVENT_ST3) -#define IS_PLAYER_MODE_IT() (m->read_event_type == READ_EVENT_IT) -#define IS_PLAYER_MODE_MED() (m->read_event_type == READ_EVENT_MED) -#define IS_PERIOD_MODRNG() (m->period_type == PERIOD_MODRNG) -#define IS_PERIOD_LINEAR() (m->period_type == PERIOD_LINEAR) -#define IS_PERIOD_CSPD() (m->period_type == PERIOD_CSPD) - -#define IS_AMIGA_MOD() (IS_PLAYER_MODE_MOD() && IS_PERIOD_MODRNG()) - -struct ord_data { - int speed; - int bpm; - int gvl; - int time; - int start_row; -#ifndef LIBXMP_CORE_PLAYER - int st26_speed; -#endif -}; - - - -/* Context */ - -struct smix_data { - int chn; - int ins; - int smp; - struct xmp_instrument *xxi; - struct xmp_sample *xxs; -}; - -/* This will be added to the sample structure in the next API revision */ -struct extra_sample_data { - double c5spd; -}; - -struct module_data { - struct xmp_module mod; - - char *dirname; /* file dirname */ - char *basename; /* file basename */ - char *filename; /* Module file name */ - char *comment; /* Comments, if any */ - uint8 md5[16]; /* MD5 message digest */ - int size; /* File size */ - double rrate; /* Replay rate */ - double time_factor; /* Time conversion constant */ - int c4rate; /* C4 replay rate */ - int volbase; /* Volume base */ - int gvolbase; /* Global volume base */ - int gvol; /* Global volume */ - int *vol_table; /* Volume translation table */ - int quirk; /* player quirks */ -#define READ_EVENT_MOD 0 -#define READ_EVENT_FT2 1 -#define READ_EVENT_ST3 2 -#define READ_EVENT_IT 3 -#define READ_EVENT_MED 4 - int read_event_type; -#define PERIOD_AMIGA 0 -#define PERIOD_MODRNG 1 -#define PERIOD_LINEAR 2 -#define PERIOD_CSPD 3 - int period_type; - int smpctl; /* sample control flags */ - int defpan; /* default pan setting */ - struct ord_data xxo_info[XMP_MAX_MOD_LENGTH]; - int num_sequences; - struct xmp_sequence seq_data[MAX_SEQUENCES]; - char *instrument_path; - void *extra; /* format-specific extra fields */ - char **scan_cnt; /* scan counters */ - struct extra_sample_data *xtra; -#ifndef LIBXMP_CORE_DISABLE_IT - struct xmp_sample *xsmp; /* sustain loop samples */ -#endif -}; - -struct pattern_loop { - 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; -}; - -struct virt_channel { - 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 { - int ord; - int pos; - int row; - int frame; - int speed; - int bpm; - int mode; - int player_flags; - int flags; - - double current_time; - double frame_time; - - int loop_count; - int sequence; - unsigned char sequence_control[XMP_MAX_MOD_LENGTH]; - - int smix_vol; /* SFX volume */ - int master_vol; /* Music volume */ - int gvol; - - struct flow_control flow; - - struct { - int time; /* replay time in ms */ - int ord; - int row; - int num; - } scan[MAX_SEQUENCES]; - - struct channel_data *xc_data; - - int channel_vol[XMP_MAX_CHANNELS]; - char channel_mute[XMP_MAX_CHANNELS]; - - struct virt_control virt; - - struct xmp_event inject_event[XMP_MAX_CHANNELS]; - - struct { - int consumed; - int in_size; - char *in_buffer; - } buffer_data; - -#ifndef LIBXMP_CORE_PLAYER - int st26_speed; /* For IceTracker speed effect */ -#endif - int filter; /* Amiga led filter */ -}; - -struct mixer_data { - int freq; /* sampling rate */ - int format; /* sample format */ - int amplify; /* amplification multiplier */ - int mix; /* percentage of channel separation */ - int interp; /* interpolation type */ - int dsp; /* dsp effect flags */ - char* buffer; /* output buffer */ - int32* buf32; /* temporary buffer for 32 bit samples */ - int numvoc; /* default softmixer voices number */ - int ticksize; - int dtright; /* anticlick control, right channel */ - int dtleft; /* anticlick control, left channel */ - double pbase; /* period base */ -}; - -struct context_data { - struct player_data p; - struct mixer_data s; - struct module_data m; - struct smix_data smix; - int state; -}; - - -/* Prototypes */ - -char *libxmp_adjust_string (char *); -int libxmp_exclude_match (const char *); -int libxmp_prepare_scan (struct context_data *); -int libxmp_scan_sequences (struct context_data *); -int libxmp_get_sequence (struct context_data *, int); -int libxmp_set_player_mode (struct context_data *); - -#ifdef EDUKE32_DISABLED -int8 read8s (FILE *, int *err); -uint8 read8 (FILE *, int *err); -uint16 read16l (FILE *, int *err); -uint16 read16b (FILE *, int *err); -uint32 read24l (FILE *, int *err); -uint32 read24b (FILE *, int *err); -uint32 read32l (FILE *, int *err); -uint32 read32b (FILE *, int *err); -static inline void write8 (FILE *f, uint8 b) { - fputc(b, f); -} -void write16l (FILE *, uint16); -void write16b (FILE *, uint16); -void write32l (FILE *, uint32); -void write32b (FILE *, uint32); -int move_data (FILE *, FILE *, int); -#endif - -uint16 readmem16l (const uint8 *); -uint16 readmem16b (const uint8 *); -uint32 readmem24l (const uint8 *); -uint32 readmem24b (const uint8 *); -uint32 readmem32l (const uint8 *); -uint32 readmem32b (const uint8 *); - -struct xmp_instrument *libxmp_get_instrument(struct context_data *, int); -struct xmp_sample *libxmp_get_sample(struct context_data *, int); - -#endif /* LIBXMP_COMMON_H */ diff --git a/source/libxmp-lite/src/control.c b/source/libxmp-lite/src/control.c deleted file mode 100644 index 8102c9f4c..000000000 --- a/source/libxmp-lite/src/control.c +++ /dev/null @@ -1,582 +0,0 @@ -/* Extended Module Player - * 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"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include -#include -#include -#include -#include - -#include "format.h" -#include "virtual.h" -#include "mixer.h" - -const char *xmp_version = XMP_VERSION; -const unsigned int xmp_vercode = XMP_VERCODE; - -xmp_context xmp_create_context() -{ - struct context_data *ctx; - - ctx = (struct context_data *)calloc(1, sizeof(struct context_data)); - if (ctx == NULL) { - return NULL; - } - - ctx->state = XMP_STATE_UNLOADED; - ctx->m.defpan = 100; - ctx->s.numvoc = SMIX_NUMVOC; - - return (xmp_context)ctx; -} - -void xmp_free_context(xmp_context opaque) -{ - struct context_data *ctx = (struct context_data *)opaque; - - if (ctx->state > XMP_STATE_UNLOADED) - xmp_release_module(opaque); - - free(opaque); -} - -static void set_position(struct context_data *ctx, int pos, int dir) -{ - 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 seq; - int has_marker; - - /* If dir is 0, we can jump to a different sequence */ - if (dir == 0) { - seq = libxmp_get_sequence(ctx, pos); - } else { - seq = p->sequence; - } - - if (seq == 0xff) { - return; - } - - has_marker = HAS_QUIRK(QUIRK_MARKER); - - if (seq >= 0) { - int start = m->seq_data[seq].entry_point; - - p->sequence = seq; - - if (pos >= 0) { - int pat; - - while (has_marker && mod->xxo[pos] == 0xfe) { - if (dir < 0) { - if (pos > start) { - pos--; - } - } else { - pos++; - } - } - pat = mod->xxo[pos]; - - if (pat < mod->pat) { - if (has_marker && pat == 0xff) { - return; - } - - if (pos > p->scan[seq].ord) { - f->end_point = 0; - } else { - f->num_rows = mod->xxp[pat]->rows; - f->end_point = p->scan[seq].num; - f->jumpline = 0; - } - } - } - - if (pos < mod->len) { - if (pos == 0) { - p->pos = -1; - } else { - p->pos = pos; - } - } - } -} - -int xmp_next_position(xmp_context opaque) -{ - struct context_data *ctx = (struct context_data *)opaque; - struct player_data *p = &ctx->p; - struct module_data *m = &ctx->m; - - if (ctx->state < XMP_STATE_PLAYING) - return -XMP_ERROR_STATE; - - if (p->pos < m->mod.len) - set_position(ctx, p->pos + 1, 1); - - return p->pos; -} - -int xmp_prev_position(xmp_context opaque) -{ - struct context_data *ctx = (struct context_data *)opaque; - struct player_data *p = &ctx->p; - struct module_data *m = &ctx->m; - - if (ctx->state < XMP_STATE_PLAYING) - return -XMP_ERROR_STATE; - - if (p->pos == m->seq_data[p->sequence].entry_point) { - set_position(ctx, -1, -1); - } else if (p->pos > m->seq_data[p->sequence].entry_point) { - set_position(ctx, p->pos - 1, -1); - } - return p->pos < 0 ? 0 : p->pos; -} - -int xmp_set_position(xmp_context opaque, int pos) -{ - struct context_data *ctx = (struct context_data *)opaque; - struct player_data *p = &ctx->p; - struct module_data *m = &ctx->m; - - if (ctx->state < XMP_STATE_PLAYING) - return -XMP_ERROR_STATE; - - if (pos >= m->mod.len) - return -XMP_ERROR_INVALID; - - set_position(ctx, pos, 0); - - 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; - struct player_data *p = &ctx->p; - - if (ctx->state < XMP_STATE_PLAYING) - return; - - p->pos = -2; -} - -void xmp_restart_module(xmp_context opaque) -{ - struct context_data *ctx = (struct context_data *)opaque; - struct player_data *p = &ctx->p; - - if (ctx->state < XMP_STATE_PLAYING) - return; - - p->loop_count = 0; - p->pos = -1; -} - -int xmp_seek_time(xmp_context opaque, int time) -{ - struct context_data *ctx = (struct context_data *)opaque; - struct player_data *p = &ctx->p; - struct module_data *m = &ctx->m; - int i, t; - - if (ctx->state < XMP_STATE_PLAYING) - return -XMP_ERROR_STATE; - - for (i = m->mod.len - 1; i >= 0; i--) { - int pat = m->mod.xxo[i]; - if (pat >= m->mod.pat) { - continue; - } - if (libxmp_get_sequence(ctx, i) != p->sequence) { - continue; - } - t = m->xxo_info[i].time; - if (time >= t) { - set_position(ctx, i, 1); - break; - } - } - if (i < 0) { - xmp_set_position(opaque, 0); - } - - return p->pos < 0 ? 0 : p->pos; -} - -int xmp_channel_mute(xmp_context opaque, int chn, int status) -{ - struct context_data *ctx = (struct context_data *)opaque; - struct player_data *p = &ctx->p; - int ret; - - if (ctx->state < XMP_STATE_PLAYING) - return -XMP_ERROR_STATE; - - if (chn < 0 || chn >= XMP_MAX_CHANNELS) { - return -XMP_ERROR_INVALID; - } - - ret = p->channel_mute[chn]; - - if (status >= 2) { - p->channel_mute[chn] = !p->channel_mute[chn]; - } else if (status >= 0) { - p->channel_mute[chn] = status; - } - - return ret; -} - -int xmp_channel_vol(xmp_context opaque, int chn, int vol) -{ - struct context_data *ctx = (struct context_data *)opaque; - struct player_data *p = &ctx->p; - int ret; - - if (ctx->state < XMP_STATE_PLAYING) - return -XMP_ERROR_STATE; - - if (chn < 0 || chn >= XMP_MAX_CHANNELS) { - return -XMP_ERROR_INVALID; - } - - ret = p->channel_vol[chn]; - - if (vol >= 0 && vol <= 100) { - p->channel_vol[chn] = vol; - } - - return ret; -} - -#ifdef USE_VERSIONED_SYMBOLS -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__"))); -LIBXMP_EXPORT extern int xmp_set_player_v43__(xmp_context, int, int) - __attribute__((alias("xmp_set_player_v40__"))); -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"); -asm(".symver xmp_set_player_v41__, xmp_set_player@XMP_4.1"); -asm(".symver xmp_set_player_v43__, xmp_set_player@XMP_4.3"); -asm(".symver xmp_set_player_v44__, xmp_set_player@@XMP_4.4"); - -#define xmp_set_player__ xmp_set_player_v40__ -#else -#define xmp_set_player__ xmp_set_player -#endif - -int xmp_set_player__(xmp_context opaque, int parm, int 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 ret = -XMP_ERROR_INVALID; - - - if (parm == XMP_PLAYER_SMPCTL || parm == XMP_PLAYER_DEFPAN) { - /* these should be set before loading the module */ - if (ctx->state >= XMP_STATE_LOADED) { - return -XMP_ERROR_STATE; - } - } else if (parm == XMP_PLAYER_VOICES) { - /* these should be set before start playing */ - if (ctx->state >= XMP_STATE_PLAYING) { - return -XMP_ERROR_STATE; - } - } else if (ctx->state < XMP_STATE_PLAYING) { - return -XMP_ERROR_STATE; - } - - switch (parm) { - case XMP_PLAYER_AMP: - if (val >= 0 && val <= 3) { - s->amplify = val; - ret = 0; - } - break; - case XMP_PLAYER_MIX: - if (val >= -100 && val <= 100) { - s->mix = val; - ret = 0; - } - break; - case XMP_PLAYER_INTERP: - if (val >= XMP_INTERP_NEAREST && val <= XMP_INTERP_SPLINE) { - s->interp = val; - ret = 0; - } - break; - case XMP_PLAYER_DSP: - s->dsp = val; - ret = 0; - break; - case XMP_PLAYER_FLAGS: { - p->player_flags = val; - ret = 0; - break; } - - /* 4.1 */ - case XMP_PLAYER_CFLAGS: { - int vblank = p->flags & XMP_FLAGS_VBLANK; - p->flags = val; - if (vblank != (p->flags & XMP_FLAGS_VBLANK)) - libxmp_scan_sequences(ctx); - ret = 0; - break; } - case XMP_PLAYER_SMPCTL: - m->smpctl = val; - ret = 0; - break; - case XMP_PLAYER_VOLUME: - if (val >= 0 && val <= 200) { - p->master_vol = val; - ret = 0; - } - break; - case XMP_PLAYER_SMIX_VOLUME: - if (val >= 0 && val <= 200) { - p->smix_vol = val; - ret = 0; - } - break; - - /* 4.3 */ - case XMP_PLAYER_DEFPAN: - if (val >= 0 && val <= 100) { - m->defpan = val; - ret = 0; - } - break; - - /* 4.4 */ - case XMP_PLAYER_MODE: - p->mode = val; - libxmp_set_player_mode(ctx); - libxmp_scan_sequences(ctx); - ret = 0; - break; - case XMP_PLAYER_VOICES: - s->numvoc = val; - break; - } - - return ret; -} - -#ifdef USE_VERSIONED_SYMBOLS -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__"))); -LIBXMP_EXPORT extern int xmp_get_player_v42__(xmp_context, int) - __attribute__((alias("xmp_get_player_v40__"))); -LIBXMP_EXPORT extern int xmp_get_player_v43__(xmp_context, int) - __attribute__((alias("xmp_get_player_v40__"))); -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"); -asm(".symver xmp_get_player_v41__, xmp_get_player@XMP_4.1"); -asm(".symver xmp_get_player_v42__, xmp_get_player@XMP_4.2"); -asm(".symver xmp_get_player_v43__, xmp_get_player@XMP_4.3"); -asm(".symver xmp_get_player_v44__, xmp_get_player@@XMP_4.4"); - -#define xmp_get_player__ xmp_get_player_v40__ -#else -#define xmp_get_player__ xmp_get_player -#endif - -int xmp_get_player__(xmp_context opaque, int parm) -{ - 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 ret = -XMP_ERROR_INVALID; - - if (parm == XMP_PLAYER_SMPCTL || parm == XMP_PLAYER_DEFPAN) { - // can read these at any time - } else if (parm != XMP_PLAYER_STATE && ctx->state < XMP_STATE_PLAYING) { - return -XMP_ERROR_STATE; - } - - switch (parm) { - case XMP_PLAYER_AMP: - ret = s->amplify; - break; - case XMP_PLAYER_MIX: - ret = s->mix; - break; - case XMP_PLAYER_INTERP: - ret = s->interp; - break; - case XMP_PLAYER_DSP: - ret = s->dsp; - break; - case XMP_PLAYER_FLAGS: - ret = p->player_flags; - break; - - /* 4.1 */ - case XMP_PLAYER_CFLAGS: - ret = p->flags; - break; - case XMP_PLAYER_SMPCTL: - ret = m->smpctl; - break; - case XMP_PLAYER_VOLUME: - ret = p->master_vol; - break; - case XMP_PLAYER_SMIX_VOLUME: - ret = p->smix_vol; - break; - - /* 4.2 */ - case XMP_PLAYER_STATE: - ret = ctx->state; - break; - - /* 4.3 */ - case XMP_PLAYER_DEFPAN: - ret = m->defpan; - break; - - /* 4.4 */ - case XMP_PLAYER_MODE: - ret = p->mode; - break; - case XMP_PLAYER_MIXER_TYPE: - ret = XMP_MIXER_STANDARD; - if (p->flags & XMP_FLAGS_A500) { - if (IS_AMIGA_MOD()) { -#ifdef LIBXMP_PAULA_SIMULATOR - if (p->filter) { - ret = XMP_MIXER_A500F; - } else { - ret = XMP_MIXER_A500; - } -#endif - } - } - break; - case XMP_PLAYER_VOICES: - ret = s->numvoc; - break; - } - - return ret; -} - -const char **xmp_get_format_list() -{ - return format_list(); -} - -void xmp_inject_event(xmp_context opaque, int channel, struct xmp_event *e) -{ - struct context_data *ctx = (struct context_data *)opaque; - struct player_data *p = &ctx->p; - - if (ctx->state < XMP_STATE_PLAYING) - return; - - memcpy(&p->inject_event[channel], e, sizeof(struct xmp_event)); - p->inject_event[channel]._flag = 1; -} - -int xmp_set_instrument_path(xmp_context opaque, char *path) -{ - struct context_data *ctx = (struct context_data *)opaque; - struct module_data *m = &ctx->m; - - if (m->instrument_path != NULL) - free(m->instrument_path); - - m->instrument_path = strdup(path); - if (m->instrument_path == NULL) { - return -XMP_ERROR_SYSTEM; - } - - 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 deleted file mode 100644 index 002c0a4a7..000000000 --- a/source/libxmp-lite/src/dataio.c +++ /dev/null @@ -1,271 +0,0 @@ -/* Extended Module Player - * 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"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include -#include "common.h" - - -#define read_byte(x) do { \ - (x) = fgetc(f); \ - if ((x) < 0) goto error; \ -} while (0) - -#define set_error(x) do { \ - if (err != NULL) *err = (x); \ -} while (0) - - -#ifdef EDUKE32_DISABLED -uint8 read8(FILE *f, int *err) -{ - int a; - - read_byte(a); - set_error(0); - return a; - - error: - set_error(ferror(f) ? errno : EOF); - return 0xff; -} - -int8 read8s(FILE *f, int *err) -{ - int a; - - read_byte(a); - set_error(0); - return (int8)a; - - error: - set_error(ferror(f) ? errno : EOF); - return 0; -} - -uint16 read16l(FILE *f, int *err) -{ - int a, b; - - read_byte(a); - read_byte(b); - - set_error(0); - return ((uint16)b << 8) | a; - - error: - set_error(ferror(f) ? errno : EOF); - return 0xffff; -} - -uint16 read16b(FILE *f, int *err) -{ - int a, b; - - read_byte(a); - read_byte(b); - - set_error(0); - return (a << 8) | b; - - error: - set_error(ferror(f) ? errno : EOF); - return 0xffff; -} - -uint32 read24l(FILE *f, int *err) -{ - int a, b, c; - - read_byte(a); - read_byte(b); - read_byte(c); - - set_error(0); - return (c << 16) | (b << 8) | a; - - error: - set_error(ferror(f) ? errno : EOF); - return 0xffffff; -} - -uint32 read24b(FILE *f, int *err) -{ - int a, b, c; - - read_byte(a); - read_byte(b); - read_byte(c); - - set_error(0); - return (a << 16) | (b << 8) | c; - - error: - set_error(ferror(f) ? errno : EOF); - return 0xffffff; -} - -uint32 read32l(FILE *f, int *err) -{ - int a, b, c, d; - - read_byte(a); - read_byte(b); - read_byte(c); - read_byte(d); - - set_error(0); - return (d << 24) | (c << 16) | (b << 8) | a; - - error: - set_error(ferror(f) ? errno : EOF); - return 0xffffffff; -} - -uint32 read32b(FILE *f, int *err) -{ - int a, b, c, d; - - read_byte(a); - read_byte(b); - read_byte(c); - read_byte(d); - - set_error(0); - return (a << 24) | (b << 16) | (c << 8) | d; - - error: - set_error(ferror(f) ? errno : EOF); - return 0xffffffff; -} -#endif - -uint16 readmem16l(const uint8 *m) -{ - uint32 a, b; - - a = m[0]; - b = m[1]; - - return (b << 8) | a; -} - -uint16 readmem16b(const uint8 *m) -{ - uint32 a, b; - - a = m[0]; - b = m[1]; - - return (a << 8) | b; -} - -uint32 readmem24l(const uint8 *m) -{ - uint32 a, b, c; - - a = m[0]; - b = m[1]; - c = m[2]; - - return (c << 16) | (b << 8) | a; -} - -uint32 readmem24b(const uint8 *m) -{ - uint32 a, b, c; - - a = m[0]; - b = m[1]; - c = m[2]; - - return (a << 16) | (b << 8) | c; -} - -uint32 readmem32l(const uint8 *m) -{ - uint32 a, b, c, d; - - a = m[0]; - b = m[1]; - c = m[2]; - d = m[3]; - - return (d << 24) | (c << 16) | (b << 8) | a; -} - -uint32 readmem32b(const uint8 *m) -{ - uint32 a, b, c, d; - - a = m[0]; - b = m[1]; - c = m[2]; - d = m[3]; - - return (a << 24) | (b << 16) | (c << 8) | d; -} - -#ifndef LIBXMP_CORE_PLAYER - -void write16l(FILE *f, uint16 w) -{ - write8(f, w & 0x00ff); - write8(f, (w & 0xff00) >> 8); -} - -void write16b(FILE *f, uint16 w) -{ - write8(f, (w & 0xff00) >> 8); - write8(f, w & 0x00ff); -} - -void write32l(FILE *f, uint32 w) -{ - write8(f, w & 0x000000ff); - write8(f, (w & 0x0000ff00) >> 8); - write8(f, (w & 0x00ff0000) >> 16); - write8(f, (w & 0xff000000) >> 24); -} - -void write32b(FILE *f, uint32 w) -{ - write8(f, (w & 0xff000000) >> 24); - write8(f, (w & 0x00ff0000) >> 16); - write8(f, (w & 0x0000ff00) >> 8); - write8(f, w & 0x000000ff); -} - -int move_data(FILE *out, FILE *in, int len) -{ - uint8 buf[1024]; - int l; - - do { - l = fread(buf, 1, len > 1024 ? 1024 : len, in); - fwrite(buf, 1, l, out); - len -= l; - } while (l > 0 && len > 0); - - return 0; -} - -#endif diff --git a/source/libxmp-lite/src/effects.c b/source/libxmp-lite/src/effects.c deleted file mode 100644 index 79a898fa3..000000000 --- a/source/libxmp-lite/src/effects.c +++ /dev/null @@ -1,1074 +0,0 @@ -/* Extended Module Player - * 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"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include "common.h" -#include "player.h" -#include "effects.h" -#include "period.h" -#include "virtual.h" -#include "mixer.h" -#ifndef LIBXMP_CORE_PLAYER -#include "extras.h" -#endif - -#define NOT_IMPLEMENTED -#define HAS_QUIRK(x) (m->quirk & (x)) - -#define SET_LFO_NOTZERO(lfo, depth, rate) do { \ - if ((depth) != 0) libxmp_lfo_set_depth(lfo, depth); \ - if ((rate) != 0) libxmp_lfo_set_rate(lfo, rate); \ -} while (0) - -#define EFFECT_MEMORY__(p, m) do { \ - if ((p) == 0) { (p) = (m); } else { (m) = (p); } \ -} while (0) - -/* ST3 effect memory is not a bug, but it's a weird implementation and it's - * unlikely to be supported in anything other than ST3 (or OpenMPT). - */ -#define EFFECT_MEMORY(p, m) do { \ - if (HAS_QUIRK(QUIRK_ST3BUGS)) { \ - EFFECT_MEMORY__((p), xc->vol.memory); \ - } else { \ - EFFECT_MEMORY__((p), (m)); \ - } \ -} while (0) - -#define EFFECT_MEMORY_SETONLY(p, m) do { \ - EFFECT_MEMORY__((p), (m)); \ - if (HAS_QUIRK(QUIRK_ST3BUGS)) { \ - if ((p) != 0) { xc->vol.memory = (p); } \ - } \ -} while (0) - -#define EFFECT_MEMORY_S3M(p) do { \ - if (HAS_QUIRK(QUIRK_ST3BUGS)) { \ - EFFECT_MEMORY__((p), xc->vol.memory); \ - } \ -} while (0) - - -static void do_toneporta(struct context_data *ctx, - struct channel_data *xc, int note) -{ - struct module_data *m = &ctx->m; - struct xmp_instrument *instrument = &m->mod.xxi[xc->ins]; - int mapped = instrument->map[xc->key].ins; - struct xmp_subinstrument *sub; - - if (mapped >= instrument->nsm) { - mapped = 0; - } - - sub = &instrument->sub[mapped]; - - if (note >= 1 && note <= 0x80 && (uint32)xc->ins < m->mod.ins) { - note--; - xc->porta.target = libxmp_note_to_period(ctx, note + sub->xpo + - instrument->map[xc->key_porta].xpo, xc->finetune, - xc->per_adj); - } - xc->porta.dir = xc->period < xc->porta.target ? 1 : -1; -} - -void libxmp_process_fx(struct context_data *ctx, struct channel_data *xc, int chn, - struct xmp_event *e, int fnum) -{ - struct player_data *p = &ctx->p; - struct module_data *m = &ctx->m; - struct xmp_module *mod = &m->mod; - struct flow_control *f = &p->flow; - uint8 note, fxp, fxt; - int h, l; - - /* key_porta is IT only */ - if (m->read_event_type != READ_EVENT_IT) { - xc->key_porta = xc->key; - } - - note = e->note; - if (fnum == 0) { - fxt = e->fxt; - fxp = e->fxp; - } else { - fxt = e->f2t; - fxp = e->f2p; - } - - switch (fxt) { - case FX_ARPEGGIO: - fx_arpeggio: - if (!HAS_QUIRK(QUIRK_ARPMEM) || fxp != 0) { - xc->arpeggio.val[0] = 0; - xc->arpeggio.val[1] = MSN(fxp); - xc->arpeggio.val[2] = LSN(fxp); - xc->arpeggio.size = 3; - } - break; - case FX_S3M_ARPEGGIO: - EFFECT_MEMORY(fxp, xc->arpeggio.memory); - goto fx_arpeggio; - -#ifndef LIBXMP_CORE_PLAYER - case FX_OKT_ARP3: - if (fxp != 0) { - xc->arpeggio.val[0] = -MSN(fxp); - xc->arpeggio.val[1] = 0; - xc->arpeggio.val[2] = LSN(fxp); - xc->arpeggio.size = 3; - } - break; - case FX_OKT_ARP4: - if (fxp != 0) { - xc->arpeggio.val[0] = 0; - xc->arpeggio.val[1] = LSN(fxp); - xc->arpeggio.val[2] = 0; - xc->arpeggio.val[3] = -MSN(fxp); - xc->arpeggio.size = 4; - } - break; - case FX_OKT_ARP5: - if (fxp != 0) { - xc->arpeggio.val[0] = LSN(fxp); - xc->arpeggio.val[1] = LSN(fxp); - xc->arpeggio.val[2] = 0; - xc->arpeggio.size = 3; - } - break; -#endif - case FX_PORTA_UP: /* Portamento up */ - EFFECT_MEMORY(fxp, xc->freq.memory); - - if (HAS_QUIRK(QUIRK_FINEFX) - && (fnum == 0 || !HAS_QUIRK(QUIRK_ITVPOR))) { - switch (MSN(fxp)) { - case 0xf: - fxp &= 0x0f; - goto fx_f_porta_up; - case 0xe: - fxp &= 0x0f; - fxp |= 0x10; - goto fx_xf_porta; - } - } - - SET(PITCHBEND); - - if (fxp != 0) { - xc->freq.slide = -fxp; - if (HAS_QUIRK(QUIRK_UNISLD)) - xc->porta.memory = fxp; - } else if (xc->freq.slide > 0) { - xc->freq.slide *= -1; - } - break; - case FX_PORTA_DN: /* Portamento down */ - EFFECT_MEMORY(fxp, xc->freq.memory); - - if (HAS_QUIRK(QUIRK_FINEFX) - && (fnum == 0 || !HAS_QUIRK(QUIRK_ITVPOR))) { - switch (MSN(fxp)) { - case 0xf: - fxp &= 0x0f; - goto fx_f_porta_dn; - case 0xe: - fxp &= 0x0f; - fxp |= 0x20; - goto fx_xf_porta; - } - } - - SET(PITCHBEND); - - if (fxp != 0) { - xc->freq.slide = fxp; - if (HAS_QUIRK(QUIRK_UNISLD)) - xc->porta.memory = fxp; - } else if (xc->freq.slide < 0) { - xc->freq.slide *= -1; - } - break; - case FX_TONEPORTA: /* Tone portamento */ - EFFECT_MEMORY_SETONLY(fxp, xc->porta.memory); - - if (fxp != 0) { - if (HAS_QUIRK(QUIRK_UNISLD)) /* IT compatible Gxx off */ - xc->freq.memory = fxp; - xc->porta.slide = fxp; - } - - if (HAS_QUIRK(QUIRK_IGSTPOR)) { - if (note == 0 && xc->porta.dir == 0) - break; - } - - if (!IS_VALID_INSTRUMENT(xc->ins)) - break; - - do_toneporta(ctx, xc, note); - - SET(TONEPORTA); - break; - - case FX_VIBRATO: /* Vibrato */ - EFFECT_MEMORY_SETONLY(fxp, xc->vibrato.memory); - - SET(VIBRATO); - SET_LFO_NOTZERO(&xc->vibrato.lfo, LSN(fxp) << 2, MSN(fxp)); - break; - case FX_FINE_VIBRATO: /* Fine vibrato */ - EFFECT_MEMORY_SETONLY(fxp, xc->vibrato.memory); - - SET(VIBRATO); - SET_LFO_NOTZERO(&xc->vibrato.lfo, LSN(fxp), MSN(fxp)); - break; - - case FX_TONE_VSLIDE: /* Toneporta + vol slide */ - if (!IS_VALID_INSTRUMENT(xc->ins)) - break; - do_toneporta(ctx, xc, note); - SET(TONEPORTA); - goto fx_volslide; - case FX_VIBRA_VSLIDE: /* Vibrato + vol slide */ - SET(VIBRATO); - goto fx_volslide; - - case FX_TREMOLO: /* Tremolo */ - EFFECT_MEMORY(fxp, xc->tremolo.memory); - SET(TREMOLO); - SET_LFO_NOTZERO(&xc->tremolo.lfo, LSN(fxp), MSN(fxp)); - break; - - case FX_SETPAN: /* Set pan */ - if (HAS_QUIRK(QUIRK_PROTRACK)) { - break; - } - fx_setpan: - /* From OpenMPT PanOff.xm: - * "Another chapter of weird FT2 bugs: Note-Off + Note Delay - * + Volume Column Panning = Panning effect is ignored." - */ - if (!HAS_QUIRK(QUIRK_FT2BUGS) /* If not FT2 */ - || fnum == 0 /* or not vol column */ - || e->note != XMP_KEY_OFF /* or not keyoff */ - || e->fxt != FX_EXTENDED /* or not delay */ - || MSN(e->fxp) != EX_DELAY) { - xc->pan.val = fxp; - xc->pan.surround = 0; - } - xc->rpv = 0; /* storlek_20: set pan overrides random pan */ - xc->pan.surround = 0; - break; - case FX_OFFSET: /* Set sample offset */ - EFFECT_MEMORY(fxp, xc->offset.memory); - SET(OFFSET); - if (note) { - xc->offset.val &= xc->offset.val & ~0xffff; - xc->offset.val |= fxp << 8; - xc->offset.val2 = fxp << 8; - } - if (e->ins) { - xc->offset.val2 = fxp << 8; - } - break; - case FX_VOLSLIDE: /* Volume slide */ - fx_volslide: - /* S3M file volume slide note: - * DFy Fine volume down by y (...) If y is 0, the command will - * be treated as a volume slide up with a value of f (15). - * If a DFF command is specified, the volume will be slid - * up. - */ - if (HAS_QUIRK(QUIRK_FINEFX)) { - h = MSN(fxp); - l = LSN(fxp); - if (l == 0xf && h != 0) { - xc->vol.memory = fxp; - fxp >>= 4; - goto fx_f_vslide_up; - } else if (h == 0xf && l != 0) { - xc->vol.memory = fxp; - fxp &= 0x0f; - goto fx_f_vslide_dn; - } - } - - /* recover memory */ - if (fxp == 0x00) { - if ((fxp = xc->vol.memory) != 0) - goto fx_volslide; - } - - SET(VOL_SLIDE); - - /* Skaven's 2nd reality (S3M) has volslide parameter D7 => pri - * down. Other trackers only compute volumes if the other - * parameter is 0, Fall from sky.xm has 2C => do nothing. - * Also don't assign xc->vol.memory if fxp is 0, see Guild - * of Sounds.xm - */ - if (fxp) { - xc->vol.memory = fxp; - h = MSN(fxp); - l = LSN(fxp); - if (fxp) { - if (HAS_QUIRK(QUIRK_VOLPDN)) { - xc->vol.slide = l ? -l : h; - } else { - xc->vol.slide = h ? h : -l; - } - } - } - - /* Mirko reports that a S3M with D0F effects created with ST321 - * should process volume slides in all frames like ST300. I - * suspect ST3/IT could be handling D0F effects like this. - */ - if (HAS_QUIRK(QUIRK_FINEFX)) { - if (MSN(xc->vol.memory) == 0xf - || LSN(xc->vol.memory) == 0xf) { - SET(FINE_VOLS); - xc->vol.fslide = xc->vol.slide; - } - } - break; - case FX_VOLSLIDE_2: /* Secondary volume slide */ - SET(VOL_SLIDE_2); - if (fxp) { - h = MSN(fxp); - l = LSN(fxp); - xc->vol.slide2 = h ? h : -l; - } - break; - case FX_JUMP: /* Order jump */ - p->flow.pbreak = 1; - p->flow.jump = fxp; - /* effect B resets effect D in lower channels */ - p->flow.jumpline = 0; - break; - case FX_VOLSET: /* Volume set */ - SET(NEW_VOL); - xc->volume = fxp; - if (xc->split) { - p->xc_data[xc->pair].volume = xc->volume; - } - break; - case FX_BREAK: /* Pattern break */ - p->flow.pbreak = 1; - p->flow.jumpline = 10 * MSN(fxp) + LSN(fxp); - break; - case FX_EXTENDED: /* Extended effect */ - EFFECT_MEMORY_S3M(fxp); - fxt = fxp >> 4; - fxp &= 0x0f; - switch (fxt) { - case EX_FILTER: /* Amiga led filter */ - if (IS_AMIGA_MOD()) { - p->filter = !(fxp & 1); - } - break; - case EX_F_PORTA_UP: /* Fine portamento up */ - EFFECT_MEMORY(fxp, xc->fine_porta.up_memory); - goto fx_f_porta_up; - case EX_F_PORTA_DN: /* Fine portamento down */ - EFFECT_MEMORY(fxp, xc->fine_porta.down_memory); - goto fx_f_porta_dn; - case EX_GLISS: /* Glissando toggle */ - if (fxp) { - SET_NOTE(NOTE_GLISSANDO); - } else { - RESET_NOTE(NOTE_GLISSANDO); - } - break; - case EX_VIBRATO_WF: /* Set vibrato waveform */ - fxp &= 3; - libxmp_lfo_set_waveform(&xc->vibrato.lfo, fxp); - break; - case EX_FINETUNE: /* Set finetune */ - if (!HAS_QUIRK(QUIRK_FT2BUGS) || note > 0) { - xc->finetune = (int8)(fxp << 4); - } - break; - case EX_PATTERN_LOOP: /* Loop pattern */ - if (fxp == 0) { - /* mark start of loop */ - f->loop[chn].start = p->row; - if (HAS_QUIRK(QUIRK_FT2BUGS)) - p->flow.jumpline = p->row; - } else { - /* end of loop */ - if (f->loop[chn].count) { - if (--f->loop[chn].count) { - /* **** H:FIXME **** */ - f->loop_chn = ++chn; - } else { - if (HAS_QUIRK(QUIRK_S3MLOOP)) - f->loop[chn].start = - p->row + 1; - } - } else { - f->loop[chn].count = fxp; - f->loop_chn = ++chn; - } - } - break; - case EX_TREMOLO_WF: /* Set tremolo waveform */ - libxmp_lfo_set_waveform(&xc->tremolo.lfo, fxp & 3); - break; - case EX_SETPAN: - fxp <<= 4; - goto fx_setpan; - case EX_RETRIG: /* Retrig note */ - SET(RETRIG); - xc->retrig.val = fxp; - xc->retrig.count = LSN(xc->retrig.val) + 1; - xc->retrig.type = 0; - break; - case EX_F_VSLIDE_UP: /* Fine volume slide up */ - EFFECT_MEMORY(fxp, xc->fine_vol.up_memory); - goto fx_f_vslide_up; - case EX_F_VSLIDE_DN: /* Fine volume slide down */ - EFFECT_MEMORY(fxp, xc->fine_vol.down_memory); - goto fx_f_vslide_dn; - case EX_CUT: /* Cut note */ - SET(RETRIG); - SET_NOTE(NOTE_CUT); /* for IT cut-carry */ - xc->retrig.val = fxp + 1; - xc->retrig.count = xc->retrig.val; - xc->retrig.type = 0x10; - break; - case EX_DELAY: /* Note delay */ - /* computed at frame loop */ - break; - case EX_PATT_DELAY: /* Pattern delay */ - goto fx_patt_delay; - case EX_INVLOOP: /* Invert loop / funk repeat */ - xc->invloop.speed = fxp; - break; - } - break; - case FX_SPEED: /* Set speed */ - if (HAS_QUIRK(QUIRK_NOBPM) || p->flags & XMP_FLAGS_VBLANK) { - goto fx_s3m_speed; - } - - /* speedup.xm needs BPM = 20 */ - if (fxp < 0x20) { - goto fx_s3m_speed; - } else { - goto fx_s3m_bpm; - } - break; - - case FX_FINETUNE: - xc->finetune = (int16) (fxp - 0x80); - break; - - case FX_F_VSLIDE_UP: /* Fine volume slide up */ - EFFECT_MEMORY(fxp, xc->fine_vol.up_memory); - fx_f_vslide_up: - SET(FINE_VOLS); - xc->vol.fslide = fxp; - break; - case FX_F_VSLIDE_DN: /* Fine volume slide down */ - EFFECT_MEMORY(fxp, xc->fine_vol.up_memory); - fx_f_vslide_dn: - SET(FINE_VOLS); - xc->vol.fslide = -fxp; - break; - - case FX_F_PORTA_UP: /* Fine portamento up */ - fx_f_porta_up: - if (fxp) { - SET(FINE_BEND); - xc->freq.fslide = -fxp; - } - break; - case FX_F_PORTA_DN: /* Fine portamento down */ - fx_f_porta_dn: - if (fxp) { - SET(FINE_BEND); - xc->freq.fslide = fxp; - } - break; - case FX_PATT_DELAY: - fx_patt_delay: - if (m->read_event_type != READ_EVENT_ST3 || !p->flow.delay) { - p->flow.delay = fxp; - } - break; - - case FX_S3M_SPEED: /* Set S3M speed */ - EFFECT_MEMORY_S3M(fxp); - fx_s3m_speed: - if (fxp) { - p->speed = fxp; -#ifndef LIBXMP_CORE_PLAYER - p->st26_speed = 0; -#endif - } - break; - case FX_S3M_BPM: /* Set S3M BPM */ - fx_s3m_bpm: { - /* Lower time factor in MED allows lower BPM values */ - int min_bpm = (int)(0.5 + m->time_factor * XMP_MIN_BPM / 10); - if (fxp < min_bpm) - fxp = min_bpm; - p->bpm = fxp; - p->frame_time = m->time_factor * m->rrate / p->bpm; - break; - } - -#ifndef LIBXMP_CORE_DISABLE_IT - case FX_IT_BPM: /* Set IT BPM */ - 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); - } else { - if (fxp < XMP_MIN_BPM) - fxp = XMP_MIN_BPM; - p->bpm = fxp; - } - p->frame_time = m->time_factor * m->rrate / p->bpm; - break; - case FX_IT_ROWDELAY: - if (!f->rowdelay_set) { - f->rowdelay = fxp; - f->rowdelay_set = 3; - } - break; - - /* From the OpenMPT VolColMemory.it test case: - * "Volume column commands a, b, c and d (volume slide) share one - * effect memory, but it should not be shared with Dxy in the effect - * column. - */ - case FX_VSLIDE_UP_2: /* Fine volume slide up */ - EFFECT_MEMORY(fxp, xc->vol.memory2); - SET(VOL_SLIDE_2); - xc->vol.slide2 = fxp; - break; - case FX_VSLIDE_DN_2: /* Fine volume slide down */ - EFFECT_MEMORY(fxp, xc->vol.memory2); - SET(VOL_SLIDE_2); - xc->vol.slide2 = -fxp; - break; - case FX_F_VSLIDE_UP_2: /* Fine volume slide up */ - EFFECT_MEMORY(fxp, xc->vol.memory2); - SET(FINE_VOLS_2); - xc->vol.fslide2 = fxp; - break; - case FX_F_VSLIDE_DN_2: /* Fine volume slide down */ - EFFECT_MEMORY(fxp, xc->vol.memory2); - SET(FINE_VOLS_2); - 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 - - case FX_GLOBALVOL: /* Set global volume */ - if (fxp > m->gvolbase) { - p->gvol = m->gvolbase; - } else { - p->gvol = fxp; - } - break; - case FX_GVOL_SLIDE: /* Global volume slide */ - fx_gvolslide: - if (fxp) { - SET(GVOL_SLIDE); - xc->gvol.memory = fxp; - h = MSN(fxp); - l = LSN(fxp); - - if (HAS_QUIRK(QUIRK_FINEFX)) { - if (l == 0xf && h != 0) { - xc->gvol.slide = 0; - xc->gvol.fslide = h; - } else if (h == 0xf && l != 0) { - xc->gvol.slide = 0; - xc->gvol.fslide = -l; - } else { - xc->gvol.slide = h ? h : -l; - xc->gvol.fslide = 0; - } - } else { - xc->gvol.slide = h ? h : -l; - xc->gvol.fslide = 0; - } - } else { - if ((fxp = xc->gvol.memory) != 0) { - goto fx_gvolslide; - } - } - break; - case FX_KEYOFF: /* Key off */ - xc->keyoff = fxp + 1; - break; - case FX_ENVPOS: /* Set envelope position */ - /* From OpenMPT SetEnvPos.xm: - * "When using the Lxx effect, Fasttracker 2 only sets the - * panning envelope position if the volume envelope’s sustain - * flag is set. - */ - if (HAS_QUIRK(QUIRK_FT2BUGS)) { - struct xmp_instrument *instrument; - instrument = libxmp_get_instrument(ctx, xc->ins); - if (instrument != NULL) { - if (instrument->aei.flg & XMP_ENVELOPE_SUS) { - xc->p_idx = fxp; - } - } - } else { - xc->p_idx = fxp; - } - xc->v_idx = fxp; - xc->f_idx = fxp; - break; - case FX_PANSLIDE: /* Pan slide (XM) */ - EFFECT_MEMORY(fxp, xc->pan.memory); - SET(PAN_SLIDE); - xc->pan.slide = LSN(fxp) - MSN(fxp); - break; - case FX_PANSL_NOMEM: /* Pan slide (XM volume column) */ - SET(PAN_SLIDE); - xc->pan.slide = LSN(fxp) - MSN(fxp); - break; - -#ifndef LIBXMP_CORE_DISABLE_IT - case FX_IT_PANSLIDE: /* Pan slide w/ fine pan (IT) */ - SET(PAN_SLIDE); - if (fxp) { - if (MSN(fxp) == 0xf) { - xc->pan.slide = 0; - xc->pan.fslide = LSN(fxp); - } else if (LSN(fxp) == 0xf) { - xc->pan.slide = 0; - xc->pan.fslide = -MSN(fxp); - } else { - SET(PAN_SLIDE); - xc->pan.slide = LSN(fxp) - MSN(fxp); - xc->pan.fslide = 0; - } - } - break; -#endif - - case FX_MULTI_RETRIG: /* Multi retrig */ - 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; - } - SET(RETRIG); - break; - case FX_TREMOR: /* Tremor */ - EFFECT_MEMORY(fxp, xc->tremor.memory); - xc->tremor.up = MSN(fxp); - xc->tremor.down = LSN(fxp); - if (IS_PLAYER_MODE_FT2()) { - xc->tremor.count |= 0x80; - } else { - if (xc->tremor.up == 0) { - xc->tremor.up++; - } - if (xc->tremor.down == 0) { - xc->tremor.down++; - } - } - SET(TREMOR); - break; - case FX_XF_PORTA: /* Extra fine portamento */ - fx_xf_porta: - SET(FINE_BEND); - switch (MSN(fxp)) { - case 1: - xc->freq.fslide = -0.25 * LSN(fxp); - break; - case 2: - xc->freq.fslide = 0.25 * LSN(fxp); - break; - } - break; - case FX_SURROUND: - xc->pan.surround = fxp; - break; - -#ifndef LIBXMP_CORE_DISABLE_IT - case FX_TRK_VOL: /* Track volume setting */ - if (fxp <= m->volbase) { - xc->mastervol = fxp; - } - break; - case FX_TRK_VSLIDE: /* Track volume slide */ - if (fxp == 0) { - if ((fxp = xc->trackvol.memory) == 0) - break; - } - - if (HAS_QUIRK(QUIRK_FINEFX)) { - h = MSN(fxp); - l = LSN(fxp); - if (h == 0xf && l != 0) { - xc->trackvol.memory = fxp; - fxp &= 0x0f; - goto fx_trk_fvslide; - } else if (l == 0xf && h != 0) { - xc->trackvol.memory = fxp; - fxp &= 0xf0; - goto fx_trk_fvslide; - } - } - - SET(TRK_VSLIDE); - if (fxp) { - h = MSN(fxp); - l = LSN(fxp); - - xc->trackvol.memory = fxp; - if (HAS_QUIRK(QUIRK_VOLPDN)) { - xc->trackvol.slide = l ? -l : h; - } else { - xc->trackvol.slide = h ? h : -l; - } - } - - break; - case FX_TRK_FVSLIDE: /* Track fine volume slide */ - fx_trk_fvslide: - SET(TRK_FVSLIDE); - if (fxp) { - xc->trackvol.fslide = MSN(fxp) - LSN(fxp); - } - break; - - case FX_IT_INSTFUNC: - switch (fxp) { - case 0: /* Past note cut */ - libxmp_virt_pastnote(ctx, chn, VIRT_ACTION_CUT); - break; - case 1: /* Past note off */ - libxmp_virt_pastnote(ctx, chn, VIRT_ACTION_OFF); - break; - case 2: /* Past note fade */ - libxmp_virt_pastnote(ctx, chn, VIRT_ACTION_FADE); - break; - case 3: /* Set NNA to note cut */ - libxmp_virt_setnna(ctx, chn, XMP_INST_NNA_CUT); - break; - case 4: /* Set NNA to continue */ - libxmp_virt_setnna(ctx, chn, XMP_INST_NNA_CONT); - break; - case 5: /* Set NNA to note off */ - libxmp_virt_setnna(ctx, chn, XMP_INST_NNA_OFF); - break; - case 6: /* Set NNA to note fade */ - libxmp_virt_setnna(ctx, chn, XMP_INST_NNA_FADE); - break; - case 7: /* Turn off volume envelope */ - SET_PER(VENV_PAUSE); - break; - case 8: /* Turn on volume envelope */ - RESET_PER(VENV_PAUSE); - break; - case 9: /* Turn off pan envelope */ - SET_PER(PENV_PAUSE); - break; - case 0xa: /* Turn on pan envelope */ - RESET_PER(PENV_PAUSE); - break; - case 0xb: /* Turn off pitch envelope */ - SET_PER(FENV_PAUSE); - break; - case 0xc: /* Turn on pitch envelope */ - RESET_PER(FENV_PAUSE); - break; - } - break; - case FX_FLT_CUTOFF: - if (fxp < 0xfe || xc->filter.resonance > 0) { - xc->filter.cutoff = fxp; - } - break; - case FX_FLT_RESN: - xc->filter.resonance = fxp; - break; - case FX_PANBRELLO: /* Panbrello */ - SET(PANBRELLO); - SET_LFO_NOTZERO(&xc->panbrello.lfo, LSN(fxp) << 4, MSN(fxp)); - break; - case FX_PANBRELLO_WF: /* Panbrello waveform */ - libxmp_lfo_set_waveform(&xc->panbrello.lfo, fxp & 3); - break; - case FX_HIOFFSET: /* High offset */ - xc->offset.val &= 0xffff; - xc->offset.val |= fxp << 16; - break; -#endif - -#ifndef LIBXMP_CORE_PLAYER - - /* SFX effects */ - case FX_VOL_ADD: - if (!IS_VALID_INSTRUMENT(xc->ins)) { - break; - } - SET(NEW_VOL); - xc->volume = m->mod.xxi[xc->ins].sub[0].vol + fxp; - if (xc->volume > m->volbase) { - xc->volume = m->volbase; - } - break; - case FX_VOL_SUB: - if (!IS_VALID_INSTRUMENT(xc->ins)) { - break; - } - SET(NEW_VOL); - xc->volume = m->mod.xxi[xc->ins].sub[0].vol - fxp; - if (xc->volume < 0) { - xc->volume =0; - } - break; - case FX_PITCH_ADD: - SET_PER(TONEPORTA); - xc->porta.target = libxmp_note_to_period(ctx, note - 1, xc->finetune, 0) - + fxp; - xc->porta.slide = 2; - xc->porta.dir = 1; - break; - case FX_PITCH_SUB: - SET_PER(TONEPORTA); - xc->porta.target = libxmp_note_to_period(ctx, note - 1, xc->finetune, 0) - - fxp; - xc->porta.slide = 2; - xc->porta.dir = -1; - break; - - /* Saga Musix says: - * - * "When both nibbles of an Fxx command are set, SoundTracker 2.6 - * applies the both values alternatingly, first the high nibble, - * then the low nibble on the next row, then the high nibble again... - * If only the high nibble is set, it should act like if only the low - * nibble is set (i.e. F30 is the same as F03). - */ - case FX_ICE_SPEED: - if (fxp) { - if (LSN(fxp)) { - p->st26_speed = (MSN(fxp) << 8) | LSN(fxp); - } else { - p->st26_speed = MSN(fxp); - } - } - break; - - case FX_VOLSLIDE_UP: /* Vol slide with uint8 arg */ - if (HAS_QUIRK(QUIRK_FINEFX)) { - h = MSN(fxp); - l = LSN(fxp); - if (h == 0xf && l != 0) { - fxp &= 0x0f; - goto fx_f_vslide_up; - } - } - - if (fxp) - xc->vol.slide = fxp; - SET(VOL_SLIDE); - break; - case FX_VOLSLIDE_DN: /* Vol slide with uint8 arg */ - if (HAS_QUIRK(QUIRK_FINEFX)) { - h = MSN(fxp); - l = LSN(fxp); - if (h == 0xf && l != 0) { - fxp &= 0x0f; - goto fx_f_vslide_dn; - } - } - - if (fxp) - xc->vol.slide = -fxp; - SET(VOL_SLIDE); - break; - case FX_F_VSLIDE: /* Fine volume slide */ - SET(FINE_VOLS); - if (fxp) { - h = MSN(fxp); - l = LSN(fxp); - xc->vol.fslide = h ? h : -l; - } - break; - case FX_NSLIDE_DN: - case FX_NSLIDE_UP: - case FX_NSLIDE_R_DN: - case FX_NSLIDE_R_UP: - if (fxp != 0) { - if (fxt == FX_NSLIDE_R_DN || fxt == FX_NSLIDE_R_UP) { - xc->retrig.val = MSN(fxp); - xc->retrig.count = MSN(fxp) + 1; - xc->retrig.type = 0; - } - - if (fxt == FX_NSLIDE_UP || fxt == FX_NSLIDE_R_UP) - xc->noteslide.slide = LSN(fxp); - else - xc->noteslide.slide = -LSN(fxp); - - xc->noteslide.count = xc->noteslide.speed = MSN(fxp); - } - if (fxt == FX_NSLIDE_R_DN || fxt == FX_NSLIDE_R_UP) - SET(RETRIG); - SET(NOTE_SLIDE); - break; - case FX_NSLIDE2_DN: - SET(NOTE_SLIDE); - xc->noteslide.slide = -fxp; - xc->noteslide.count = xc->noteslide.speed = 1; - break; - case FX_NSLIDE2_UP: - SET(NOTE_SLIDE); - xc->noteslide.slide = fxp; - xc->noteslide.count = xc->noteslide.speed = 1; - break; - case FX_F_NSLIDE_DN: - SET(FINE_NSLIDE); - xc->noteslide.fslide = -fxp; - break; - case FX_F_NSLIDE_UP: - SET(FINE_NSLIDE); - xc->noteslide.fslide = fxp; - break; - - case FX_PER_VIBRATO: /* Persistent vibrato */ - if (LSN(fxp) != 0) { - SET_PER(VIBRATO); - } else { - RESET_PER(VIBRATO); - } - SET_LFO_NOTZERO(&xc->vibrato.lfo, LSN(fxp) << 2, MSN(fxp)); - break; - case FX_PER_PORTA_UP: /* Persistent portamento up */ - SET_PER(PITCHBEND); - xc->freq.slide = -fxp; - if ((xc->freq.memory = fxp) == 0) - RESET_PER(PITCHBEND); - break; - case FX_PER_PORTA_DN: /* Persistent portamento down */ - SET_PER(PITCHBEND); - xc->freq.slide = fxp; - if ((xc->freq.memory = fxp) == 0) - RESET_PER(PITCHBEND); - break; - case FX_PER_TPORTA: /* Persistent tone portamento */ - if (!IS_VALID_INSTRUMENT(xc->ins)) - break; - SET_PER(TONEPORTA); - do_toneporta(ctx, xc, note); - xc->porta.slide = fxp; - if (fxp == 0) - RESET_PER(TONEPORTA); - break; - case FX_PER_VSLD_UP: /* Persistent volslide up */ - SET_PER(VOL_SLIDE); - xc->vol.slide = fxp; - if (fxp == 0) - RESET_PER(VOL_SLIDE); - break; - case FX_PER_VSLD_DN: /* Persistent volslide down */ - SET_PER(VOL_SLIDE); - xc->vol.slide = -fxp; - if (fxp == 0) - RESET_PER(VOL_SLIDE); - break; - case FX_VIBRATO2: /* Deep vibrato (2x) */ - SET(VIBRATO); - SET_LFO_NOTZERO(&xc->vibrato.lfo, LSN(fxp) << 3, MSN(fxp)); - break; - case FX_SPEED_CP: /* Set speed and ... */ - if (fxp) { - p->speed = fxp; - p->st26_speed = 0; - } - /* fall through */ - case FX_PER_CANCEL: /* Cancel persistent effects */ - xc->per_flags = 0; - break; - - /* 669 effects */ - - case FX_669_PORTA_UP: /* 669 portamento up */ - SET_PER(PITCHBEND); - xc->freq.slide = 80 * fxp; - if ((xc->freq.memory = fxp) == 0) - RESET_PER(PITCHBEND); - break; - case FX_669_PORTA_DN: /* 669 portamento down */ - SET_PER(PITCHBEND); - xc->freq.slide = -80 * fxp; - if ((xc->freq.memory = fxp) == 0) - RESET_PER(PITCHBEND); - break; - case FX_669_TPORTA: /* 669 tone portamento */ - if (!IS_VALID_INSTRUMENT(xc->ins)) - break; - SET_PER(TONEPORTA); - do_toneporta(ctx, xc, note); - xc->porta.slide = 40 * fxp; - if (fxp == 0) - RESET_PER(TONEPORTA); - break; - case FX_669_FINETUNE: /* 669 finetune */ - xc->finetune = 80 * (int8)fxp; - break; - case FX_669_VIBRATO: /* 669 vibrato */ - if (LSN(fxp) != 0) { - libxmp_lfo_set_waveform(&xc->vibrato.lfo, 669); - SET_PER(VIBRATO); - } else { - RESET_PER(VIBRATO); - } - SET_LFO_NOTZERO(&xc->vibrato.lfo, 669, 1); - break; -#endif - - default: -#ifndef LIBXMP_CORE_PLAYER - libxmp_extras_process_fx(ctx, xc, chn, note, fxt, fxp, fnum); -#endif - break; - } -} diff --git a/source/libxmp-lite/src/effects.h b/source/libxmp-lite/src/effects.h deleted file mode 100644 index b269bac43..000000000 --- a/source/libxmp-lite/src/effects.h +++ /dev/null @@ -1,143 +0,0 @@ -#ifndef LIBXMP_EFFECTS_H -#define LIBXMP_EFFECTS_H - -/* Protracker effects */ -#define FX_ARPEGGIO 0x00 -#define FX_PORTA_UP 0x01 -#define FX_PORTA_DN 0x02 -#define FX_TONEPORTA 0x03 -#define FX_VIBRATO 0x04 -#define FX_TONE_VSLIDE 0x05 -#define FX_VIBRA_VSLIDE 0x06 -#define FX_TREMOLO 0x07 -#define FX_OFFSET 0x09 -#define FX_VOLSLIDE 0x0a -#define FX_JUMP 0x0b -#define FX_VOLSET 0x0c -#define FX_BREAK 0x0d -#define FX_EXTENDED 0x0e -#define FX_SPEED 0x0f - -/* Fast tracker effects */ -#define FX_SETPAN 0x08 - -/* Fast Tracker II effects */ -#define FX_GLOBALVOL 0x10 -#define FX_GVOL_SLIDE 0x11 -#define FX_KEYOFF 0x14 -#define FX_ENVPOS 0x15 -#define FX_PANSLIDE 0x19 -#define FX_MULTI_RETRIG 0x1b -#define FX_TREMOR 0x1d -#define FX_XF_PORTA 0x21 - -/* Protracker extended effects */ -#define EX_FILTER 0x00 -#define EX_F_PORTA_UP 0x01 -#define EX_F_PORTA_DN 0x02 -#define EX_GLISS 0x03 -#define EX_VIBRATO_WF 0x04 -#define EX_FINETUNE 0x05 -#define EX_PATTERN_LOOP 0x06 -#define EX_TREMOLO_WF 0x07 -#define EX_SETPAN 0x08 -#define EX_RETRIG 0x09 -#define EX_F_VSLIDE_UP 0x0a -#define EX_F_VSLIDE_DN 0x0b -#define EX_CUT 0x0c -#define EX_DELAY 0x0d -#define EX_PATT_DELAY 0x0e -#define EX_INVLOOP 0x0f - -#ifndef LIBXMP_CORE_PLAYER -/* Oktalyzer effects */ -#define FX_OKT_ARP3 0x70 -#define FX_OKT_ARP4 0x71 -#define FX_OKT_ARP5 0x72 -#define FX_NSLIDE2_DN 0x73 -#define FX_NSLIDE2_UP 0x74 -#define FX_F_NSLIDE_DN 0x75 -#define FX_F_NSLIDE_UP 0x76 - -/* Persistent effects -- for FNK and FAR */ -#define FX_PER_PORTA_DN 0x78 -#define FX_PER_PORTA_UP 0x79 -#define FX_PER_TPORTA 0x7a -#define FX_PER_VIBRATO 0x7b -#define FX_PER_VSLD_UP 0x7c -#define FX_PER_VSLD_DN 0x7d -#define FX_SPEED_CP 0x7e -#define FX_PER_CANCEL 0x7f - -/* 669 frequency based effects */ -#define FX_669_PORTA_UP 0x60 -#define FX_669_PORTA_DN 0x61 -#define FX_669_TPORTA 0x62 -#define FX_669_FINETUNE 0x63 -#define FX_669_VIBRATO 0x64 -#endif - -#ifndef LIBXMP_CORE_DISABLE_IT -/* IT effects */ -#define FX_TRK_VOL 0x80 -#define FX_TRK_VSLIDE 0x81 -#define FX_TRK_FVSLIDE 0x82 -#define FX_IT_INSTFUNC 0x83 -#define FX_FLT_CUTOFF 0x84 -#define FX_FLT_RESN 0x85 -#define FX_IT_BPM 0x87 -#define FX_IT_ROWDELAY 0x88 -#define FX_IT_PANSLIDE 0x89 -#define FX_PANBRELLO 0x8a -#define FX_PANBRELLO_WF 0x8b -#define FX_HIOFFSET 0x8c -#define FX_IT_BREAK 0x8e /* like FX_BREAK with hex parameter */ -#endif - -#ifndef LIBXMP_CORE_PLAYER -/* MED effects */ -#define FX_HOLD_DECAY 0x90 -#define FX_SETPITCH 0x91 -#define FX_VIBRATO2 0x92 - -/* PTM effects */ -#define FX_NSLIDE_DN 0x9c /* IMF/PTM note slide down */ -#define FX_NSLIDE_UP 0x9d /* IMF/PTM note slide up */ -#define FX_NSLIDE_R_UP 0x9e /* PTM note slide down with retrigger */ -#define FX_NSLIDE_R_DN 0x9f /* PTM note slide up with retrigger */ - -/* Extra effects */ -#define FX_VOLSLIDE_UP 0xa0 /* SFX, MDL */ -#define FX_VOLSLIDE_DN 0xa1 -#define FX_F_VSLIDE 0xa5 /* IMF/MDL */ -#define FX_CHORUS 0xa9 /* IMF */ -#define FX_ICE_SPEED 0xa2 -#define FX_REVERB 0xaa /* IMF */ -#define FX_MED_HOLD 0xb1 /* MMD hold/decay */ -#define FX_MEGAARP 0xb2 /* Smaksak effect 7: MegaArp */ -#define FX_VOL_ADD 0xb6 /* SFX change volume up */ -#define FX_VOL_SUB 0xb7 /* SFX change volume down */ -#define FX_PITCH_ADD 0xb8 /* SFX add steps to current note */ -#define FX_PITCH_SUB 0xb9 /* SFX add steps to current note */ -#endif - -#define FX_SURROUND 0x8d /* S3M/IT */ -#define FX_S3M_SPEED 0xa3 /* S3M */ -#define FX_VOLSLIDE_2 0xa4 -#define FX_FINETUNE 0xa6 -#define FX_S3M_BPM 0xab /* S3M */ -#define FX_FINE_VIBRATO 0xac /* S3M/PTM/IMF/LIQ */ -#define FX_F_VSLIDE_UP 0xad /* MMD */ -#define FX_F_VSLIDE_DN 0xae /* MMD */ -#define FX_F_PORTA_UP 0xaf /* MMD */ -#define FX_F_PORTA_DN 0xb0 /* MMD */ -#define FX_PATT_DELAY 0xb3 /* MMD */ -#define FX_S3M_ARPEGGIO 0xb4 -#define FX_PANSL_NOMEM 0xb5 /* XM volume column */ - -#define FX_VSLIDE_UP_2 0xc0 /* IT volume column volume slide */ -#define FX_VSLIDE_DN_2 0xc1 -#define FX_F_VSLIDE_UP_2 0xc2 -#define FX_F_VSLIDE_DN_2 0xc3 - -#endif /* LIBXMP_EFFECTS_H */ diff --git a/source/libxmp-lite/src/filter.c b/source/libxmp-lite/src/filter.c deleted file mode 100644 index d15d89c9e..000000000 --- a/source/libxmp-lite/src/filter.c +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Based on the public domain version by Olivier Lapicque - * Rewritten for libxmp by Claudio Matsuoka - * - * Copyright (C) 2012 Claudio Matsuoka - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#ifndef LIBXMP_CORE_DISABLE_IT -#include -#include "xmp.h" -#include "common.h" -#include "mixer.h" - - -/* LUT for 2 * damping factor */ -static const float resonance_table[128] = { - 1.0000000000000000f, 0.9786446094512940f, 0.9577452540397644f, 0.9372922182083130f, - 0.9172759056091309f, 0.8976871371269226f, 0.8785166740417481f, 0.8597555756568909f, - 0.8413951396942139f, 0.8234267830848694f, 0.8058421611785889f, 0.7886331081390381f, - 0.7717915177345276f, 0.7553095817565918f, 0.7391796708106995f, 0.7233941555023193f, - 0.7079457640647888f, 0.6928272843360901f, 0.6780316829681397f, 0.6635520458221436f, - 0.6493816375732422f, 0.6355138421058655f, 0.6219421625137329f, 0.6086603403091431f, - 0.5956621170043945f, 0.5829415321350098f, 0.5704925656318665f, 0.5583094954490662f, - 0.5463865399360657f, 0.5347182154655457f, 0.5232990980148315f, 0.5121238231658936f, - 0.5011872053146362f, 0.4904841780662537f, 0.4800096750259399f, 0.4697588682174683f, - 0.4597269892692566f, 0.4499093294143677f, 0.4403013288974762f, 0.4308985173702240f, - 0.4216965138912201f, 0.4126909971237183f, 0.4038778245449066f, 0.3952528536319733f, - 0.3868120610713959f, 0.3785515129566193f, 0.3704673945903778f, 0.3625559210777283f, - 0.3548133969306946f, 0.3472362160682678f, 0.3398208320140839f, 0.3325638175010681f, - 0.3254617750644684f, 0.3185114264488220f, 0.3117094635963440f, 0.3050527870655060f, - 0.2985382676124573f, 0.2921628654003143f, 0.2859236001968384f, 0.2798175811767578f, - 0.2738419771194458f, 0.2679939568042755f, 0.2622708380222321f, 0.2566699385643005f, - 0.2511886358261108f, 0.2458244115114212f, 0.2405747324228287f, 0.2354371547698975f, - 0.2304092943668366f, 0.2254888117313385f, 0.2206734120845795f, 0.2159608304500580f, - 0.2113489061594009f, 0.2068354636430740f, 0.2024184018373489f, 0.1980956792831421f, - 0.1938652694225311f, 0.1897251904010773f, 0.1856735348701477f, 0.1817083954811096f, - 0.1778279393911362f, 0.1740303486585617f, 0.1703138649463654f, 0.1666767448186874f, - 0.1631172895431519f, 0.1596338599920273f, 0.1562248021364212f, 0.1528885662555695f, - 0.1496235728263855f, 0.1464282870292664f, 0.1433012634515762f, 0.1402409970760346f, - 0.1372461020946503f, 0.1343151479959488f, 0.1314467936754227f, 0.1286396980285645f, - 0.1258925348520279f, 0.1232040524482727f, 0.1205729842185974f, 0.1179980933666229f, - 0.1154781952500343f, 0.1130121126770973f, 0.1105986908078194f, 0.1082368120551109f, - 0.1059253737330437f, 0.1036632955074310f, 0.1014495193958283f, 0.0992830246686935f, - 0.0971627980470657f, 0.0950878411531448f, 0.0930572077631950f, 0.0910699293017387f, - 0.0891250967979431f, 0.0872217938303947f, 0.0853591337800026f, 0.0835362523794174f, - 0.0817523002624512f, 0.0800064504146576f, 0.0782978758215904f, 0.0766257941722870f, - 0.0749894231557846f, 0.0733879879117012f, 0.0718207582831383f, 0.0702869966626167f, - 0.0687859877943993f, 0.0673170387744904f, 0.0658794566988945f, 0.0644725710153580f, -}; - - -#if !defined(HAVE_POWF) || defined(__DJGPP__) || defined(__WATCOMC__) -#define powf pow /* Watcom doesn't have powf. DJGPP have a C-only implementation in libm. */ -#endif - - -/* - * Simple 2-poles resonant filter - */ -#define FREQ_PARAM_MULT (128.0f / (24.0f * 256.0f)) -void libxmp_filter_setup(int srate, int cutoff, int res, int *a0, int *b0, int *b1) -{ - float fc, fs = (float)srate; - float fg, fb0, fb1; - float r, d, e; - - /* [0-255] => [100Hz-8000Hz] */ - CLAMP(cutoff, 0, 255); - CLAMP(res, 0, 255); - - fc = 110.0f * powf(2.0f, (float)cutoff * FREQ_PARAM_MULT + 0.25f); - if (fc > fs / 2.0f) { - fc = fs / 2.0f; - } - - r = fs / (2.0 * 3.14159265358979f * fc); - d = resonance_table[res >> 1] * (r + 1.0) - 1.0; - e = r * r; - - fg = 1.0 / (1.0 + d + e); - fb0 = (d + e + e) / (1.0 + d + e); - fb1 = -e / (1.0 + d + e); - - *a0 = (int)(fg * (1 << FILTER_SHIFT)); - *b0 = (int)(fb0 * (1 << FILTER_SHIFT)); - *b1 = (int)(fb1 * (1 << FILTER_SHIFT)); -} - -#endif diff --git a/source/libxmp-lite/src/format.c b/source/libxmp-lite/src/format.c deleted file mode 100644 index 8297d386d..000000000 --- a/source/libxmp-lite/src/format.c +++ /dev/null @@ -1,65 +0,0 @@ -/* Extended Module Player - * Copyright (C) 1996-2016 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"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include -#include -#ifndef LIBXMP_CORE_PLAYER -#include "loaders/prowizard/prowiz.h" -#endif -#include "format.h" - -extern const struct format_loader libxmp_loader_xm; -extern const struct format_loader libxmp_loader_mod; -extern const struct format_loader libxmp_loader_it; -extern const struct format_loader libxmp_loader_s3m; -extern const struct format_loader libxmp_loader_mtm; - -extern const struct pw_format *const pw_format[]; - -extern const struct format_loader *const format_loader[]; -const struct format_loader *const format_loader[] = { - &libxmp_loader_xm, - &libxmp_loader_mod, -#ifndef LIBXMP_CORE_DISABLE_IT - &libxmp_loader_it, -#endif - &libxmp_loader_s3m, - &libxmp_loader_mtm, - NULL -}; - -static const char *_farray[sizeof(format_loader)/sizeof(struct format_loader *)] = { NULL }; - -const char **format_list() -{ - int count, i; - - if (_farray[0] == NULL) { - for (count = i = 0; format_loader[i] != NULL; i++) { - _farray[count++] = format_loader[i]->name; - } - - _farray[count] = NULL; - } - - return _farray; -} diff --git a/source/libxmp-lite/src/format.h b/source/libxmp-lite/src/format.h deleted file mode 100644 index b5a1013a8..000000000 --- a/source/libxmp-lite/src/format.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef LIBXMP_FORMAT_H -#define LIBXMP_FORMAT_H - -#include -#include "common.h" -#include "hio.h" - -struct format_loader { - const char *name; - int (*const test)(HIO_HANDLE *, char *, const int); - int (*const loader)(struct module_data *, HIO_HANDLE *, const int); -}; - -const char **format_list(void); - -#ifndef LIBXMP_CORE_PLAYER - -#define NUM_FORMATS 52 -#define NUM_PW_FORMATS 43 - -int pw_test_format(HIO_HANDLE *, char *, const int, struct xmp_test_info *); -#endif - -#endif - diff --git a/source/libxmp-lite/src/hio.c b/source/libxmp-lite/src/hio.c deleted file mode 100644 index 91328ad89..000000000 --- a/source/libxmp-lite/src/hio.c +++ /dev/null @@ -1,428 +0,0 @@ -/* Extended Module Player - * 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"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include -#include -#include -#include -#include "common.h" -#include "hio.h" -#include "mdataio.h" - -#ifdef EDUKE32_DISABLED -static long get_size(FILE *f) -{ - long size, pos; - - pos = ftell(f); - if (pos >= 0) { - if (fseek(f, 0, SEEK_END) < 0) { - return -1; - } - size = ftell(f); - if (fseek(f, pos, SEEK_SET) < 0) { - return -1; - } - return size; - } else { - return pos; - } -} -#endif - -int8 hio_read8s(HIO_HANDLE *h) -{ -#ifdef EDUKE32_DISABLED - int err; -#endif - int8 ret = 0; - - switch (HIO_HANDLE_TYPE(h)) { -#ifdef EDUKE32_DISABLED - case HIO_HANDLE_TYPE_FILE: - ret = read8s(h->handle.file, &err); - if (err != 0) { - h->error = err; - } - break; -#endif - case HIO_HANDLE_TYPE_MEMORY: - ret = mread8s(h->handle.mem); - break; - } - - return ret; -} - -uint8 hio_read8(HIO_HANDLE *h) -{ -#ifdef EDUKE32_DISABLED - int err; -#endif - uint8 ret = 0; - - switch (HIO_HANDLE_TYPE(h)) { -#ifdef EDUKE32_DISABLED - case HIO_HANDLE_TYPE_FILE: - ret = read8(h->handle.file, &err); - if (err != 0) { - h->error = err; - } - break; -#endif - case HIO_HANDLE_TYPE_MEMORY: - ret = mread8(h->handle.mem); - break; - } - - return ret; -} - -uint16 hio_read16l(HIO_HANDLE *h) -{ -#ifdef EDUKE32_DISABLED - int err; -#endif - uint16 ret = 0; - - switch (HIO_HANDLE_TYPE(h)) { -#ifdef EDUKE32_DISABLED - case HIO_HANDLE_TYPE_FILE: - ret = read16l(h->handle.file, &err); - if (err != 0) { - h->error = err; - } - break; -#endif - case HIO_HANDLE_TYPE_MEMORY: - ret = mread16l(h->handle.mem); - break; - } - - return ret; -} - -uint16 hio_read16b(HIO_HANDLE *h) -{ -#ifdef EDUKE32_DISABLED - int err; -#endif - uint16 ret = 0; - - switch (HIO_HANDLE_TYPE(h)) { -#ifdef EDUKE32_DISABLED - case HIO_HANDLE_TYPE_FILE: - ret = read16b(h->handle.file, &err); - if (err != 0) { - h->error = err; - } - break; -#endif - case HIO_HANDLE_TYPE_MEMORY: - ret = mread16b(h->handle.mem); - break; - } - - return ret; -} - -uint32 hio_read24l(HIO_HANDLE *h) -{ -#ifdef EDUKE32_DISABLED - int err; -#endif - uint32 ret = 0; - - switch (HIO_HANDLE_TYPE(h)) { -#ifdef EDUKE32_DISABLED - case HIO_HANDLE_TYPE_FILE: - ret = read24l(h->handle.file, &err); - if (err != 0) { - h->error = err; - } - break; -#endif - case HIO_HANDLE_TYPE_MEMORY: - ret = mread24l(h->handle.mem); - break; - } - - return ret; -} - -uint32 hio_read24b(HIO_HANDLE *h) -{ -#ifdef EDUKE32_DISABLED - int err; -#endif - uint32 ret = 0; - - switch (HIO_HANDLE_TYPE(h)) { -#ifdef EDUKE32_DISABLED - case HIO_HANDLE_TYPE_FILE: - ret = read24b(h->handle.file, &err); - if (err != 0) { - h->error = err; - } - break; -#endif - case HIO_HANDLE_TYPE_MEMORY: - ret = mread24b(h->handle.mem); - break; - } - - return ret; -} - -uint32 hio_read32l(HIO_HANDLE *h) -{ -#ifdef EDUKE32_DISABLED - int err; -#endif - uint32 ret = 0; - - switch (HIO_HANDLE_TYPE(h)) { -#ifdef EDUKE32_DISABLED - case HIO_HANDLE_TYPE_FILE: - ret = read32l(h->handle.file, &err); - if (err != 0) { - h->error = err; - } - break; -#endif - case HIO_HANDLE_TYPE_MEMORY: - ret = mread32l(h->handle.mem); - break; - } - - return ret; -} - -uint32 hio_read32b(HIO_HANDLE *h) -{ -#ifdef EDUKE32_DISABLED - int err; -#endif - uint32 ret = 0; - - switch (HIO_HANDLE_TYPE(h)) { -#ifdef EDUKE32_DISABLED - case HIO_HANDLE_TYPE_FILE: - ret = read32b(h->handle.file, &err); - if (err != 0) { - h->error = err; - } - break; -#endif - case HIO_HANDLE_TYPE_MEMORY: - ret = mread32b(h->handle.mem); - } - - return ret; -} - -size_t hio_read(void *buf, size_t size, size_t num, HIO_HANDLE *h) -{ - size_t ret = 0; - - switch (HIO_HANDLE_TYPE(h)) { -#ifdef EDUKE32_DISABLED - case HIO_HANDLE_TYPE_FILE: - ret = fread(buf, size, num, h->handle.file); - if (ret != num) { - if (ferror(h->handle.file)) { - h->error = errno; - } else { - h->error = feof(h->handle.file) ? EOF : -2; - } - } - break; -#endif - case HIO_HANDLE_TYPE_MEMORY: - ret = mread(buf, size, num, h->handle.mem); - if (ret != num) { - h->error = errno; - } - break; - } - - return ret; -} - -int hio_seek(HIO_HANDLE *h, long offset, int whence) -{ - int ret = -1; - - switch (HIO_HANDLE_TYPE(h)) { -#ifdef EDUKE32_DISABLED - case HIO_HANDLE_TYPE_FILE: - ret = fseek(h->handle.file, offset, whence); - if (ret < 0) { - h->error = errno; - } - break; -#endif - case HIO_HANDLE_TYPE_MEMORY: - ret = mseek(h->handle.mem, offset, whence); - if (ret < 0) { - h->error = errno; - } - break; - } - - return ret; -} - -long hio_tell(HIO_HANDLE *h) -{ - long ret = -1; - - switch (HIO_HANDLE_TYPE(h)) { -#ifdef EDUKE32_DISABLED - case HIO_HANDLE_TYPE_FILE: - ret = ftell(h->handle.file); - if (ret < 0) { - h->error = errno; - } - break; -#endif - case HIO_HANDLE_TYPE_MEMORY: - ret = mtell(h->handle.mem); - if (ret < 0) { - h->error = errno; - } - break; - } - - return ret; -} - -int hio_eof(HIO_HANDLE *h) -{ - switch (HIO_HANDLE_TYPE(h)) { -#ifdef EDUKE32_DISABLED - case HIO_HANDLE_TYPE_FILE: - return feof(h->handle.file); -#endif - case HIO_HANDLE_TYPE_MEMORY: - return meof(h->handle.mem); - default: - return EOF; - } -} - -int hio_error(HIO_HANDLE *h) -{ - int error = h->error; - h->error = 0; - return error; -} - -#ifdef EDUKE32_DISABLED -HIO_HANDLE *hio_open(const void *path, const char *mode) -{ - HIO_HANDLE *h; - - h = (HIO_HANDLE *)malloc(sizeof (HIO_HANDLE)); - if (h == NULL) - goto err; - - h->error = 0; - h->type = HIO_HANDLE_TYPE_FILE; - h->handle.file = fopen((const char *)path, mode); - if (h->handle.file == NULL) - goto err2; - - h->size = get_size(h->handle.file); - if (h->size < 0) - goto err3; - - return h; - - err3: - fclose(h->handle.file); - err2: - free(h); - err: - return NULL; -} -#endif - -HIO_HANDLE *hio_open_mem(const void *ptr, long size) -{ - HIO_HANDLE *h; - - h = (HIO_HANDLE *)malloc(sizeof (HIO_HANDLE)); - if (h == NULL) - return NULL; - - h->error = 0; - h->type = HIO_HANDLE_TYPE_MEMORY; - h->handle.mem = mopen(ptr, size); - h->size = size; - - return h; -} - -#ifdef EDUKE32_DISABLED -HIO_HANDLE *hio_open_file(FILE *f) -{ - HIO_HANDLE *h; - - h = (HIO_HANDLE *)malloc(sizeof (HIO_HANDLE)); - if (h == NULL) - return NULL; - - h->error = 0; - h->type = HIO_HANDLE_TYPE_FILE; - h->handle.file = f /*fdopen(fileno(f), "rb")*/; - h->size = get_size(f); - - return h; -} -#endif - -int hio_close(HIO_HANDLE *h) -{ - int ret; - - switch (HIO_HANDLE_TYPE(h)) { -#ifdef EDUKE32_DISABLED - case HIO_HANDLE_TYPE_FILE: - ret = fclose(h->handle.file); - break; -#endif - case HIO_HANDLE_TYPE_MEMORY: - ret = mclose(h->handle.mem); - break; - default: - ret = -1; - } - - free(h); - return ret; -} - -long hio_size(HIO_HANDLE *h) -{ - return h->size; -} diff --git a/source/libxmp-lite/src/hio.h b/source/libxmp-lite/src/hio.h deleted file mode 100644 index cedcbb6a2..000000000 --- a/source/libxmp-lite/src/hio.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef XMP_HIO_H -#define XMP_HIO_H - -#ifdef EDUKE32_DISABLED -#include -#include -#endif -#include -#include "memio.h" - -#define HIO_HANDLE_TYPE(x) ((x)->type) - -typedef struct { -#ifdef EDUKE32_DISABLED -#define HIO_HANDLE_TYPE_FILE 0 -#endif -#define HIO_HANDLE_TYPE_MEMORY 1 - int type; - long size; - union { -#ifdef EDUKE32_DISABLED - FILE *file; -#endif - MFILE *mem; - } handle; - int error; -} HIO_HANDLE; - -int8 hio_read8s (HIO_HANDLE *); -uint8 hio_read8 (HIO_HANDLE *); -uint16 hio_read16l (HIO_HANDLE *); -uint16 hio_read16b (HIO_HANDLE *); -uint32 hio_read24l (HIO_HANDLE *); -uint32 hio_read24b (HIO_HANDLE *); -uint32 hio_read32l (HIO_HANDLE *); -uint32 hio_read32b (HIO_HANDLE *); -size_t hio_read (void *, size_t, size_t, HIO_HANDLE *); -int hio_seek (HIO_HANDLE *, long, int); -long hio_tell (HIO_HANDLE *); -int hio_eof (HIO_HANDLE *); -int hio_error (HIO_HANDLE *); -#ifdef EDUKE32_DISABLED -HIO_HANDLE *hio_open (const void *, const char *); -#endif -HIO_HANDLE *hio_open_mem (const void *, long); -#ifdef EDUKE32_DISABLED -HIO_HANDLE *hio_open_file (FILE *); -#endif -int hio_close (HIO_HANDLE *); -long hio_size (HIO_HANDLE *); - -#endif diff --git a/source/libxmp-lite/src/it.h b/source/libxmp-lite/src/it.h deleted file mode 100644 index 5c6fc63ef..000000000 --- a/source/libxmp-lite/src/it.h +++ /dev/null @@ -1,181 +0,0 @@ -/* Extended Module Player - * 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"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -/* IT flags */ -#define IT_STEREO 0x01 -#define IT_VOL_OPT 0x02 /* Not recognized */ -#define IT_USE_INST 0x04 -#define IT_LINEAR_FREQ 0x08 -#define IT_OLD_FX 0x10 -#define IT_LINK_GXX 0x20 - -/* IT special */ -#define IT_HAS_MSG 0x01 - -/* IT instrument flags */ -#define IT_INST_SAMPLE 0x01 -#define IT_INST_16BIT 0x02 -#define IT_INST_STEREO 0x04 -#define IT_INST_LOOP 0x10 -#define IT_INST_SLOOP 0x20 -#define IT_INST_BLOOP 0x40 -#define IT_INST_BSLOOP 0x80 - -/* IT sample flags */ -#define IT_SMP_SAMPLE 0x01 -#define IT_SMP_16BIT 0x02 -#define IT_SMP_STEREO 0x04 /* unsupported */ -#define IT_SMP_COMP 0x08 /* unsupported */ -#define IT_SMP_LOOP 0x10 -#define IT_SMP_SLOOP 0x20 -#define IT_SMP_BLOOP 0x40 -#define IT_SMP_BSLOOP 0x80 - -/* IT sample conversion flags */ -#define IT_CVT_SIGNED 0x01 -#define IT_CVT_BIGEND 0x02 /* 'safe to ignore' according to ittech.txt */ -#define IT_CVT_DIFF 0x04 /* Compressed sample flag */ -#define IT_CVT_BYTEDIFF 0x08 /* 'safe to ignore' according to ittech.txt */ -#define IT_CVT_12BIT 0x10 /* 'safe to ignore' according to ittech.txt */ - -/* IT envelope flags */ -#define IT_ENV_ON 0x01 -#define IT_ENV_LOOP 0x02 -#define IT_ENV_SLOOP 0x04 -#define IT_ENV_CARRY 0x08 -#define IT_ENV_FILTER 0x80 - - -struct it_file_header { - uint32 magic; /* 'IMPM' */ - uint8 name[26]; /* ASCIIZ Song name */ - uint8 hilite_min; /* Pattern editor highlight */ - uint8 hilite_maj; /* Pattern editor highlight */ - uint16 ordnum; /* Number of orders (must be even) */ - uint16 insnum; /* Number of instruments */ - uint16 smpnum; /* Number of samples */ - uint16 patnum; /* Number of patterns */ - uint16 cwt; /* Tracker ID and version */ - uint16 cmwt; /* Format version */ - uint16 flags; /* Flags */ - uint16 special; /* More flags */ - uint8 gv; /* Global volume */ - uint8 mv; /* Master volume */ - uint8 is; /* Initial speed */ - uint8 it; /* Initial tempo */ - uint8 sep; /* Panning separation */ - uint8 pwd; /* Pitch wheel depth */ - uint16 msglen; /* Message length */ - uint32 msgofs; /* Message offset */ - uint32 rsvd; /* Reserved */ - uint8 chpan[64]; /* Channel pan settings */ - uint8 chvol[64]; /* Channel volume settings */ -}; - -struct it_instrument1_header { - uint32 magic; /* 'IMPI' */ - uint8 dosname[12]; /* DOS filename */ - uint8 zero; /* Always zero */ - uint8 flags; /* Instrument flags */ - uint8 vls; /* Volume loop start */ - uint8 vle; /* Volume loop end */ - uint8 sls; /* Sustain loop start */ - uint8 sle; /* Sustain loop end */ - uint16 rsvd1; /* Reserved */ - uint16 fadeout; /* Fadeout (release) */ - uint8 nna; /* New note action */ - uint8 dnc; /* Duplicate note check */ - uint16 trkvers; /* Tracker version */ - uint8 nos; /* Number of samples */ - uint8 rsvd2; /* Reserved */ - uint8 name[26]; /* ASCIIZ Instrument name */ - uint8 rsvd3[6]; /* Reserved */ - uint8 keys[240]; - uint8 epoint[200]; - uint8 enode[50]; -}; - -struct it_instrument2_header { - uint32 magic; /* 'IMPI' */ - uint8 dosname[12]; /* DOS filename */ - uint8 zero; /* Always zero */ - uint8 nna; /* New Note Action */ - uint8 dct; /* Duplicate Check Type */ - uint8 dca; /* Duplicate Check Action */ - uint16 fadeout; - uint8 pps; /* Pitch-Pan Separation */ - uint8 ppc; /* Pitch-Pan Center */ - uint8 gbv; /* Global Volume */ - uint8 dfp; /* Default pan */ - uint8 rv; /* Random volume variation */ - uint8 rp; /* Random pan variation */ - uint16 trkvers; /* Not used: tracked version */ - uint8 nos; /* Not used: number of samples */ - uint8 rsvd1; /* Reserved */ - uint8 name[26]; /* ASCIIZ Instrument name */ - uint8 ifc; /* Initial filter cutoff */ - uint8 ifr; /* Initial filter resonance */ - uint8 mch; /* MIDI channel */ - uint8 mpr; /* MIDI program */ - uint16 mbnk; /* MIDI bank */ - uint8 keys[240]; -}; - -struct it_envelope_node { - int8 y; - uint16 x; -}; - -struct it_envelope { - uint8 flg; /* Flags */ - uint8 num; /* Number of node points */ - uint8 lpb; /* Loop beginning */ - uint8 lpe; /* Loop end */ - uint8 slb; /* Sustain loop beginning */ - uint8 sle; /* Sustain loop end */ - struct it_envelope_node node[25]; - uint8 unused; -}; - -struct it_sample_header { - uint32 magic; /* 'IMPS' */ - uint8 dosname[12]; /* DOS filename */ - uint8 zero; /* Always zero */ - uint8 gvl; /* Global volume for instrument */ - uint8 flags; /* Sample flags */ - uint8 vol; /* Volume */ - uint8 name[26]; /* ASCIIZ sample name */ - uint8 convert; /* Sample flags */ - uint8 dfp; /* Default pan */ - uint32 length; /* Length */ - uint32 loopbeg; /* Loop begin */ - uint32 loopend; /* Loop end */ - uint32 c5spd; /* C 5 speed */ - uint32 sloopbeg; /* SusLoop begin */ - uint32 sloopend; /* SusLoop end */ - uint32 sample_ptr; /* Sample pointer */ - uint8 vis; /* Vibrato speed */ - uint8 vid; /* Vibrato depth */ - uint8 vir; /* Vibrato rate */ - uint8 vit; /* Vibrato waveform */ -}; - diff --git a/source/libxmp-lite/src/it_load.c b/source/libxmp-lite/src/it_load.c deleted file mode 100644 index ea7858ce2..000000000 --- a/source/libxmp-lite/src/it_load.c +++ /dev/null @@ -1,1400 +0,0 @@ -/* Extended Module Player - * 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"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#ifndef LIBXMP_CORE_DISABLE_IT - -#include -#include "loader.h" -#include "it.h" -#include "period.h" - -#define MAGIC_IMPM MAGIC4('I','M','P','M') -#define MAGIC_IMPI MAGIC4('I','M','P','I') -#define MAGIC_IMPS MAGIC4('I','M','P','S') - - -static int it_test(HIO_HANDLE *, char *, const int); -static int it_load(struct module_data *, HIO_HANDLE *, const int); - -extern const struct format_loader libxmp_loader_it; -const struct format_loader libxmp_loader_it = { - "Impulse Tracker", - it_test, - 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) - return -1; - - libxmp_read_title(f, t, 26); - - return 0; -} - - -#define FX_NONE 0xff -#define FX_XTND 0xfe -#define L_CHANNELS 64 - - -static const uint8 fx[] = { - /* */ FX_NONE, - /* A */ FX_S3M_SPEED, - /* B */ FX_JUMP, - /* C */ FX_IT_BREAK, - /* D */ FX_VOLSLIDE, - /* E */ FX_PORTA_DN, - /* F */ FX_PORTA_UP, - /* G */ FX_TONEPORTA, - /* H */ FX_VIBRATO, - /* I */ FX_TREMOR, - /* J */ FX_S3M_ARPEGGIO, - /* K */ FX_VIBRA_VSLIDE, - /* L */ FX_TONE_VSLIDE, - /* M */ FX_TRK_VOL, - /* N */ FX_TRK_VSLIDE, - /* O */ FX_OFFSET, - /* P */ FX_IT_PANSLIDE, - /* Q */ FX_MULTI_RETRIG, - /* R */ FX_TREMOLO, - /* S */ FX_XTND, - /* T */ FX_IT_BPM, - /* U */ FX_FINE_VIBRATO, - /* V */ FX_GLOBALVOL, - /* W */ FX_GVOL_SLIDE, - /* X */ FX_SETPAN, - /* Y */ FX_PANBRELLO, - /* Z */ FX_FLT_CUTOFF -}; - - -int itsex_decompress8 (HIO_HANDLE *, uint8 *, int, int); -int itsex_decompress16 (HIO_HANDLE *, int16 *, int, int); - - -static void xlat_fx(int c, struct xmp_event *e, uint8 *last_fxp, int new_fx) -{ - uint8 h = MSN(e->fxp), l = LSN(e->fxp); - - switch (e->fxt = fx[e->fxt]) { - case FX_XTND: /* Extended effect */ - e->fxt = FX_EXTENDED; - - if (h == 0 && e->fxp == 0) { - e->fxp = last_fxp[c]; - h = MSN(e->fxp); - l = LSN(e->fxp); - } else { - last_fxp[c] = e->fxp; - } - - switch (h) { - case 0x1: /* Glissando */ - e->fxp = 0x30 | l; - break; - case 0x2: /* Finetune -- not supported */ - e->fxt = e->fxp = 0; - break; - case 0x3: /* Vibrato wave */ - e->fxp = 0x40 | l; - break; - case 0x4: /* Tremolo wave */ - e->fxp = 0x70 | l; - break; - case 0x5: /* Panbrello wave */ - if (l <= 3) { - e->fxt = FX_PANBRELLO_WF; - e->fxp = l; - } else { - e->fxt = e->fxp = 0; - } - break; - case 0x6: /* Pattern delay */ - e->fxp = 0xe0 | l; - break; - case 0x7: /* Instrument functions */ - e->fxt = FX_IT_INSTFUNC; - e->fxp &= 0x0f; - break; - case 0x8: /* Set pan position */ - e->fxt = FX_SETPAN; - e->fxp = l << 4; - break; - case 0x9: /* 0x91 = set surround */ - e->fxt = FX_SURROUND; - e->fxp = l; - break; - case 0xa: /* High offset */ - e->fxt = FX_HIOFFSET; - e->fxp = l; - break; - case 0xb: /* Pattern loop */ - e->fxp = 0x60 | l; - break; - case 0xc: /* Note cut */ - case 0xd: /* Note delay */ - if ((e->fxp = l) == 0) - e->fxp++; /* SD0 and SC0 become SD1 and SC1 */ - e->fxp |= h << 4; - break; - case 0xe: /* Pattern row delay */ - e->fxt = FX_IT_ROWDELAY; - e->fxp = l; - break; - default: - e->fxt = e->fxp = 0; - } - break; - case FX_FLT_CUTOFF: - if (e->fxp > 0x7f && e->fxp < 0x90) { /* Resonance */ - e->fxt = FX_FLT_RESN; - e->fxp = (e->fxp - 0x80) * 16; - } else { /* Cutoff */ - e->fxp *= 2; - } - break; - case FX_TREMOR: - if (!new_fx && e->fxp != 0) { - e->fxp = ((MSN(e->fxp) + 1) << 4) | (LSN(e->fxp) + 1); - } - break; - case FX_GLOBALVOL: - if (e->fxp > 0x80) { /* See storlek test 16 */ - e->fxt = e->fxp = 0; - } - break; - case FX_NONE: /* No effect */ - e->fxt = e->fxp = 0; - break; - } -} - - -static void xlat_volfx(struct xmp_event *event) -{ - int b; - - b = event->vol; - event->vol = 0; - - if (b <= 0x40) { - event->vol = b + 1; - } else if (b >= 65 && b <= 74) { /* A */ - event->f2t = FX_F_VSLIDE_UP_2; - event->f2p = b - 65; - } else if (b >= 75 && b <= 84) { /* B */ - event->f2t = FX_F_VSLIDE_DN_2; - event->f2p = b - 75; - } else if (b >= 85 && b <= 94) { /* C */ - event->f2t = FX_VSLIDE_UP_2; - event->f2p = b - 85; - } else if (b >= 95 && b <= 104) { /* D */ - event->f2t = FX_VSLIDE_DN_2; - event->f2p = b - 95; - } else if (b >= 105 && b <= 114) { /* E */ - event->f2t = FX_PORTA_DN; - event->f2p = (b - 105) << 2; - } else if (b >= 115 && b <= 124) { /* F */ - event->f2t = FX_PORTA_UP; - event->f2p = (b - 115) << 2; - } else if (b >= 128 && b <= 192) { /* pan */ - if (b == 192) { - event->f2p = 0xff; - } else { - event->f2p = (b - 128) << 2; - } - event->f2t = FX_SETPAN; - } else if (b >= 193 && b <= 202) { /* G */ - uint8 val[10] = { - 0x00, 0x01, 0x04, 0x08, 0x10, - 0x20, 0x40, 0x60, 0x80, 0xff - }; - event->f2t = FX_TONEPORTA; - event->f2p = val[b - 193]; - } else if (b >= 203 && b <= 212) { /* H */ - event->f2t = FX_VIBRATO; - event->f2p = b - 203; - } -} - - -static void fix_name(uint8 *s, int l) -{ - int i; - - /* IT names can have 0 at start of data, replace with space */ - for (l--, i = 0; i < l; i++) { - if (s[i] == 0) - s[i] = ' '; - } - for (i--; i >= 0 && s[i] == ' '; i--) { - if (s[i] == ' ') - s[i] = 0; - } -} - - -static int read_envelope(struct xmp_envelope *ei, struct it_envelope *env, - HIO_HANDLE *f) -{ - int i; - uint8 buf[82]; - - if (hio_read(buf, 1, 82, f) != 82) { - return -1; - } - - env->flg = buf[0]; - env->num = MIN(buf[1], 25); /* Clamp to IT max */ - - env->lpb = buf[2]; - env->lpe = buf[3]; - env->slb = buf[4]; - env->sle = buf[5]; - - for (i = 0; i < 25; i++) { - env->node[i].y = buf[6 + i * 3]; - env->node[i].x = readmem16l(buf + 7 + i * 3); - } - - ei->flg = env->flg & IT_ENV_ON ? XMP_ENVELOPE_ON : 0; - - if (env->flg & IT_ENV_LOOP) { - ei->flg |= XMP_ENVELOPE_LOOP; - } - - if (env->flg & IT_ENV_SLOOP) { - ei->flg |= XMP_ENVELOPE_SUS | XMP_ENVELOPE_SLOOP; - } - - if (env->flg & IT_ENV_CARRY) { - ei->flg |= XMP_ENVELOPE_CARRY; - } - - ei->npt = env->num; - ei->sus = env->slb; - ei->sue = env->sle; - ei->lps = env->lpb; - ei->lpe = env->lpe; - - if (ei->npt > 0 && ei->npt <= 25 /* XMP_MAX_ENV_POINTS */ ) { - for (i = 0; i < ei->npt; i++) { - ei->data[i * 2] = env->node[i].x; - ei->data[i * 2 + 1] = env->node[i].y; - } - } else { - ei->flg &= ~XMP_ENVELOPE_ON; - } - - return 0; -} - -static void identify_tracker(struct module_data *m, struct it_file_header *ifh) -{ -#ifndef LIBXMP_CORE_PLAYER - char tracker_name[40]; - int sample_mode = ~ifh->flags & IT_USE_INST; - - switch (ifh->cwt >> 8) { - case 0x00: - strcpy(tracker_name, "unmo3"); - break; - case 0x01: - case 0x02: /* test from Schism Tracker sources */ - if (ifh->cmwt == 0x0200 && ifh->cwt == 0x0214 - && ifh->flags == 9 && ifh->special == 0 - && ifh->hilite_maj == 0 && ifh->hilite_min == 0 - && ifh->insnum == 0 && ifh->patnum + 1 == ifh->ordnum - && ifh->gv == 128 && ifh->mv == 100 && ifh->is == 1 - && ifh->sep == 128 && ifh->pwd == 0 - && ifh->msglen == 0 && ifh->msgofs == 0 && ifh->rsvd == 0) { - strcpy(tracker_name, "OpenSPC conversion"); - } else if (ifh->cmwt == 0x0200 && ifh->cwt == 0x0217) { - strcpy(tracker_name, "ModPlug Tracker 1.16"); - /* ModPlug Tracker files aren't really IMPM 2.00 */ - ifh->cmwt = sample_mode ? 0x100 : 0x214; - } else if (ifh->cwt == 0x0216) { - strcpy(tracker_name, "Impulse Tracker 2.14v3"); - } else if (ifh->cwt == 0x0217) { - strcpy(tracker_name, "Impulse Tracker 2.14v5"); - } else if (ifh->cwt == 0x0214 && !memcmp(&ifh->rsvd, "CHBI", 4)) { - strcpy(tracker_name, "Chibi Tracker"); - } else { - snprintf(tracker_name, 40, "Impulse Tracker %d.%02x", - (ifh->cwt & 0x0f00) >> 8, ifh->cwt & 0xff); - } - break; - case 0x08: - case 0x7f: - if (ifh->cwt == 0x0888) { - strcpy(tracker_name, "OpenMPT 1.17"); - } else if (ifh->cwt == 0x7fff) { - strcpy(tracker_name, "munch.py"); - } else { - snprintf(tracker_name, 40, "unknown (%04x)", ifh->cwt); - } - 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 0x5: - snprintf(tracker_name, 40, "OpenMPT %d.%02x", - (ifh->cwt & 0x0f00) >> 8, ifh->cwt & 0xff); - if (memcmp(&ifh->rsvd, "OMPT", 4)) - strncat(tracker_name, " (compat.)", 39); - break; - case 0x06: - snprintf(tracker_name, 40, "BeRoTracker %d.%02x", - (ifh->cwt & 0x0f00) >> 8, ifh->cwt & 0xff); - break; - default: - snprintf(tracker_name, 40, "unknown (%04x)", ifh->cwt); - } - } - - libxmp_set_type(m, "%s IT %d.%02x", tracker_name, ifh->cmwt >> 8, - ifh->cmwt & 0xff); -#else - libxmp_set_type(m, "Impulse Tracker"); -#endif -} - -static int load_old_it_instrument(struct xmp_instrument *xxi, HIO_HANDLE *f) -{ - int inst_map[120], inst_rmap[XMP_MAX_KEYS]; - struct it_instrument1_header i1h; - int c, k, j; - uint8 buf[64]; - - if (hio_read(buf, 1, 64, f) != 64) { - return -1; - } - - i1h.magic = readmem32b(buf); - if (i1h.magic != MAGIC_IMPI) { - D_(D_CRIT "bad instrument magic"); - return -1; - } - memcpy(i1h.dosname, buf + 4, 12); - i1h.zero = buf[16]; - i1h.flags = buf[17]; - i1h.vls = buf[18]; - i1h.vle = buf[19]; - i1h.sls = buf[20]; - i1h.sle = buf[21]; - i1h.fadeout = readmem16l(buf + 24); - i1h.nna = buf[26]; - i1h.dnc = buf[27]; - i1h.trkvers = readmem16l(buf + 28); - i1h.nos = buf[30]; - - memcpy(i1h.name, buf + 32, 26); - fix_name(i1h.name, 26); - - if (hio_read(&i1h.keys, 1, 240, f) != 240) { - return -1; - } - if (hio_read(&i1h.epoint, 1, 200, f) != 200) { - return -1; - } - if (hio_read(&i1h.enode, 1, 50, f) != 50) { - return -1; - } - - libxmp_copy_adjust(xxi->name, i1h.name, 25); - - xxi->rls = i1h.fadeout << 7; - - xxi->aei.flg = 0; - if (i1h.flags & IT_ENV_ON) { - xxi->aei.flg |= XMP_ENVELOPE_ON; - } - if (i1h.flags & IT_ENV_LOOP) { - xxi->aei.flg |= XMP_ENVELOPE_LOOP; - } - if (i1h.flags & IT_ENV_SLOOP) { - xxi->aei.flg |= XMP_ENVELOPE_SUS | XMP_ENVELOPE_SLOOP; - } - if (i1h.flags & IT_ENV_CARRY) { - xxi->aei.flg |= XMP_ENVELOPE_SUS | XMP_ENVELOPE_CARRY; - } - xxi->aei.lps = i1h.vls; - xxi->aei.lpe = i1h.vle; - xxi->aei.sus = i1h.sls; - xxi->aei.sue = i1h.sle; - - for (k = 0; k < 25 && i1h.enode[k * 2] != 0xff; k++) ; - - /* Sanity check */ - if (k >= 25 || i1h.enode[k * 2] != 0xff) { - return -1; - } - - for (xxi->aei.npt = k; k--;) { - xxi->aei.data[k * 2] = i1h.enode[k * 2]; - xxi->aei.data[k * 2 + 1] = i1h.enode[k * 2 + 1]; - } - - /* See how many different instruments we have */ - for (j = 0; j < 120; j++) - inst_map[j] = -1; - - for (k = j = 0; j < XMP_MAX_KEYS; j++) { - c = j < 120 ? i1h.keys[j * 2 + 1] - 1 : -1; - if (c < 0 || c >= 120) { - xxi->map[j].ins = 0; - xxi->map[j].xpo = 0; - continue; - } - if (inst_map[c] == -1) { - inst_map[c] = k; - inst_rmap[k] = c; - k++; - } - xxi->map[j].ins = inst_map[c]; - xxi->map[j].xpo = i1h.keys[j * 2] - j; - } - - xxi->nsm = k; - xxi->vol = 0x40; - - if (k) { - xxi->sub = (struct xmp_subinstrument *)calloc(sizeof(struct xmp_subinstrument), k); - if (xxi->sub == NULL) { - return -1; - } - - for (j = 0; j < k; j++) { - struct xmp_subinstrument *sub = &xxi->sub[j]; - - sub->sid = inst_rmap[j]; - sub->nna = i1h.nna; - sub->dct = - i1h.dnc ? XMP_INST_DCT_NOTE : XMP_INST_DCT_OFF; - sub->dca = XMP_INST_DCA_CUT; - sub->pan = -1; - } - } - - D_(D_INFO "[ ] %-26.26s %d %-4.4s %4d %2d %c%c%c %3d", - /*i,*/ i1h.name, - i1h.nna, - i1h.dnc ? "on" : "off", - i1h.fadeout, - xxi->aei.npt, - xxi->aei.flg & XMP_ENVELOPE_ON ? 'V' : '-', - xxi->aei.flg & XMP_ENVELOPE_LOOP ? 'L' : '-', - xxi->aei.flg & XMP_ENVELOPE_SUS ? 'S' : '-', xxi->nsm); - - return 0; -} - -static int load_new_it_instrument(struct xmp_instrument *xxi, HIO_HANDLE *f) -{ - int inst_map[120], inst_rmap[XMP_MAX_KEYS]; - struct it_instrument2_header i2h; - struct it_envelope env; - int dca2nna[] = { 0, 2, 3 }; - int c, k, j; - uint8 buf[64]; - - if (hio_read(buf, 1, 64, f) != 64) { - return -1; - } - - i2h.magic = readmem32b(buf); - if (i2h.magic != MAGIC_IMPI) { - D_(D_CRIT "bad instrument magic"); - return -1; - } - memcpy(i2h.dosname, buf + 4, 12); - i2h.zero = buf[16]; - i2h.nna = buf[17]; - i2h.dct = buf[18]; - i2h.dca = buf[19]; - - /* Sanity check */ - if (i2h.dca > 3) { - /* Northern Sky has an instrument with DCA 3 */ - D_(D_WARN "bad instrument dca: %d", i2h.dca); - i2h.dca = 0; - } - - i2h.fadeout = readmem16l(buf + 20); - i2h.pps = buf[22]; - i2h.ppc = buf[23]; - i2h.gbv = buf[24]; - i2h.dfp = buf[25]; - i2h.rv = buf[26]; - i2h.rp = buf[27]; - i2h.trkvers = readmem16l(buf + 28); - i2h.nos = buf[30]; - - memcpy(i2h.name, buf + 32, 26); - fix_name(i2h.name, 26); - - i2h.ifc = buf[58]; - i2h.ifr = buf[59]; - i2h.mch = buf[60]; - i2h.mpr = buf[61]; - i2h.mbnk = readmem16l(buf + 62); - - if (hio_read(&i2h.keys, 1, 240, f) != 240) { - D_(D_CRIT "key map read error"); - return -1; - } - - libxmp_copy_adjust(xxi->name, i2h.name, 25); - xxi->rls = i2h.fadeout << 6; - - /* Envelopes */ - - if (read_envelope(&xxi->aei, &env, f) < 0) { - return -1; - } - if (read_envelope(&xxi->pei, &env, f) < 0) { - return -1; - } - if (read_envelope(&xxi->fei, &env, f) < 0) { - return -1; - } - - if (xxi->pei.flg & XMP_ENVELOPE_ON) { - for (j = 0; j < xxi->pei.npt; j++) - xxi->pei.data[j * 2 + 1] += 32; - } - - if (xxi->aei.flg & XMP_ENVELOPE_ON && xxi->aei.npt == 0) { - xxi->aei.npt = 1; - } - if (xxi->pei.flg & XMP_ENVELOPE_ON && xxi->pei.npt == 0) { - xxi->pei.npt = 1; - } - if (xxi->fei.flg & XMP_ENVELOPE_ON && xxi->fei.npt == 0) { - xxi->fei.npt = 1; - } - - if (env.flg & IT_ENV_FILTER) { - xxi->fei.flg |= XMP_ENVELOPE_FLT; - for (j = 0; j < env.num; j++) { - xxi->fei.data[j * 2 + 1] += 32; - xxi->fei.data[j * 2 + 1] *= 4; - } - } else { - /* Pitch envelope is *50 to get fine interpolation */ - for (j = 0; j < env.num; j++) - xxi->fei.data[j * 2 + 1] *= 50; - } - - /* See how many different instruments we have */ - for (j = 0; j < 120; j++) - inst_map[j] = -1; - - for (k = j = 0; j < 120; j++) { - c = i2h.keys[j * 2 + 1] - 1; - if (c < 0 || c >= 120) { - xxi->map[j].ins = 0xff; /* No sample */ - xxi->map[j].xpo = 0; - continue; - } - if (inst_map[c] == -1) { - inst_map[c] = k; - inst_rmap[k] = c; - k++; - } - xxi->map[j].ins = inst_map[c]; - xxi->map[j].xpo = i2h.keys[j * 2] - j; - } - - xxi->nsm = k; - xxi->vol = i2h.gbv >> 1; - - if (k) { - xxi->sub = (struct xmp_subinstrument *)calloc(sizeof(struct xmp_subinstrument), k); - if (xxi->sub == NULL) - return -1; - - for (j = 0; j < k; j++) { - struct xmp_subinstrument *sub = &xxi->sub[j]; - - sub->sid = inst_rmap[j]; - sub->nna = i2h.nna; - sub->dct = i2h.dct; - sub->dca = dca2nna[i2h.dca]; - sub->pan = i2h.dfp & 0x80 ? -1 : i2h.dfp * 4; - sub->ifc = i2h.ifc; - sub->ifr = i2h.ifr; - sub->rvv = ((int)i2h.rp << 8) | i2h.rv; - } - } - - D_(D_INFO "[ ] %-26.26s %d %d %d %4d %4d %2x " - "%02x %c%c%c %3d %02x %02x", - /*i,*/ i2h.name, - i2h.nna, i2h.dct, i2h.dca, - i2h.fadeout, - i2h.gbv, - i2h.dfp & 0x80 ? 0x80 : i2h.dfp * 4, - i2h.rv, - xxi->aei.flg & XMP_ENVELOPE_ON ? 'V' : '-', - xxi->pei.flg & XMP_ENVELOPE_ON ? 'P' : '-', - env.flg & 0x01 ? env.flg & 0x80 ? 'F' : 'P' : '-', - xxi->nsm, i2h.ifc, i2h.ifr); - - return 0; -} - -static int load_it_sample(struct module_data *m, int i, int start, - int sample_mode, HIO_HANDLE *f) -{ - struct it_sample_header ish; - struct xmp_module *mod = &m->mod; - struct xmp_sample *xxs, *xsmp; - int j, k; - uint8 buf[80]; - - if (sample_mode) { - mod->xxi[i].sub = (struct xmp_subinstrument *)calloc(sizeof(struct xmp_subinstrument), 1); - if (mod->xxi[i].sub == NULL) { - return -1; - } - } - - if (hio_read(buf, 1, 80, f) != 80) { - return -1; - } - - ish.magic = readmem32b(buf); - /* Changed to continue to allow use-brdg.it and use-funk.it to - * load correctly (both IT 2.04) - */ - if (ish.magic != MAGIC_IMPS) { - return 0; - } - - xxs = &mod->xxs[i]; - xsmp = &m->xsmp[i]; - - memcpy(ish.dosname, buf + 4, 12); - ish.zero = buf[16]; - ish.gvl = buf[17]; - ish.flags = buf[18]; - ish.vol = buf[19]; - - memcpy(ish.name, buf + 20, 26); - fix_name(ish.name, 26); - - ish.convert = buf[46]; - ish.dfp = buf[47]; - ish.length = readmem32l(buf + 48); - ish.loopbeg = readmem32l(buf + 52); - ish.loopend = readmem32l(buf + 56); - ish.c5spd = readmem32l(buf + 60); - ish.sloopbeg = readmem32l(buf + 64); - ish.sloopend = readmem32l(buf + 68); - ish.sample_ptr = readmem32l(buf + 72); - ish.vis = buf[76]; - ish.vid = buf[77]; - ish.vir = buf[78]; - ish.vit = buf[79]; - - if (ish.flags & IT_SMP_16BIT) { - xxs->flg = XMP_SAMPLE_16BIT; - } - xxs->len = ish.length; - - /* Sanity check */ - if (xxs->len > MAX_SAMPLE_SIZE) { - return -1; - } - - xxs->lps = ish.loopbeg; - xxs->lpe = ish.loopend; - xxs->flg |= ish.flags & IT_SMP_LOOP ? XMP_SAMPLE_LOOP : 0; - xxs->flg |= ish.flags & IT_SMP_BLOOP ? XMP_SAMPLE_LOOP_BIDIR : 0; - xxs->flg |= ish.flags & IT_SMP_SLOOP ? XMP_SAMPLE_SLOOP : 0; - xxs->flg |= ish.flags & IT_SMP_BSLOOP ? XMP_SAMPLE_SLOOP_BIDIR : 0; - - if (ish.flags & IT_SMP_SLOOP) { - memcpy(xsmp, xxs, sizeof (struct xmp_sample)); - xsmp->lps = ish.sloopbeg; - xsmp->lpe = ish.sloopend; - xsmp->flg |= XMP_SAMPLE_LOOP; - xsmp->flg &= ~XMP_SAMPLE_LOOP_BIDIR; - if (ish.flags & IT_SMP_BSLOOP) { - xsmp->flg |= XMP_SAMPLE_LOOP_BIDIR; - } - } - - if (sample_mode) { - /* Create an instrument for each sample */ - mod->xxi[i].sub[0].vol = ish.vol; - mod->xxi[i].sub[0].pan = 0x80; - mod->xxi[i].sub[0].sid = i; - mod->xxi[i].nsm = !!(xxs->len); - libxmp_instrument_name(mod, i, ish.name, 25); - } else { - libxmp_copy_adjust(xxs->name, ish.name, 25); - } - - D_(D_INFO "\n[%2X] %-26.26s %05x%c%05x %05x %05x %05x " - "%02x%02x %02x%02x %5d ", - i, sample_mode ? xxs->name : mod->xxi[i].name, - xxs->len, - ish.flags & IT_SMP_16BIT ? '+' : ' ', - MIN(xxs->lps, 0xfffff), MIN(xxs->lpe, 0xfffff), - MIN(ish.sloopbeg, 0xfffff), MIN(ish.sloopend, 0xfffff), - ish.flags, ish.convert, ish.vol, ish.gvl, ish.c5spd); - - /* Convert C5SPD to relnote/finetune - * - * In IT we can have a sample associated with two or more - * instruments, but c5spd is a sample attribute -- so we must - * scan all xmp instruments to set the correct transposition - */ - - for (j = 0; j < mod->ins; j++) { - for (k = 0; k < mod->xxi[j].nsm; k++) { - struct xmp_subinstrument *sub = &mod->xxi[j].sub[k]; - if (sub->sid == i) { - sub->vol = ish.vol; - sub->gvl = ish.gvl; - sub->vra = ish.vis; /* sample to sub-instrument vibrato */ - sub->vde = ish.vid >> 1; - sub->vwf = ish.vit; - sub->vsw = (0xff - ish.vir) >> 1; - - libxmp_c2spd_to_note(ish.c5spd, - &mod->xxi[j].sub[k].xpo, - &mod->xxi[j].sub[k].fin); - - /* Set sample pan (overrides subinstrument) */ - if (ish.dfp & 0x80) { - sub->pan = (ish.dfp & 0x7f) * 4; - } else if (sample_mode) { - sub->pan = -1; - } - } - } - } - - if (ish.flags & IT_SMP_SAMPLE && xxs->len > 1) { - int cvt = 0; - - if (0 != hio_seek(f, start + ish.sample_ptr, SEEK_SET)) - return -1; - - if (xxs->lpe > xxs->len || xxs->lps >= xxs->lpe) - xxs->flg &= ~XMP_SAMPLE_LOOP; - - if (~ish.convert & IT_CVT_SIGNED) - cvt |= SAMPLE_FLAG_UNS; - - /* compressed samples */ - if (ish.flags & IT_SMP_COMP) { - uint8 *buf; - int ret; - - buf = (uint8 *)calloc(1, xxs->len * 2); - if (buf == NULL) - return -1; - - if (ish.flags & IT_SMP_16BIT) { - itsex_decompress16(f, (int16 *)buf, xxs->len, - ish.convert & IT_CVT_DIFF); - -#ifdef WORDS_BIGENDIAN - /* decompression generates native-endian - * samples, but we want little-endian - */ - cvt |= SAMPLE_FLAG_BIGEND; -#endif - } else { - itsex_decompress8(f, (uint8 *)buf, xxs->len, - ish.convert & IT_CVT_DIFF); - } - - if (ish.flags & IT_SMP_SLOOP) { - long pos = hio_tell(f); - if (pos < 0) { - free(buf); - return -1; - } - ret = libxmp_load_sample(m, NULL, SAMPLE_FLAG_NOLOAD | - cvt, &m->xsmp[i], buf); - if (ret < 0) { - free(buf); - return -1; - } - hio_seek(f, pos, SEEK_SET); - } - - ret = libxmp_load_sample(m, NULL, SAMPLE_FLAG_NOLOAD | cvt, - &mod->xxs[i], buf); - if (ret < 0) { - free(buf); - return -1; - } - - free(buf); - } else { - if (ish.flags & IT_SMP_SLOOP) { - long pos = hio_tell(f); - if (pos < 0) { - return -1; - } - if (libxmp_load_sample(m, f, cvt, &m->xsmp[i], NULL) < 0) - return -1; - hio_seek(f, pos, SEEK_SET); - } - - if (libxmp_load_sample(m, f, cvt, &mod->xxs[i], NULL) < 0) - return -1; - } - } - - return 0; -} - -static int load_it_pattern(struct module_data *m, int i, int new_fx, - HIO_HANDLE *f) -{ - struct xmp_module *mod = &m->mod; - struct xmp_event *event, dummy, lastevent[L_CHANNELS]; - uint8 mask[L_CHANNELS]; - uint8 last_fxp[64]; - - int r, c, pat_len; - uint8 b; - - r = 0; - - memset(last_fxp, 0, 64); - memset(lastevent, 0, L_CHANNELS * sizeof(struct xmp_event)); - memset(&dummy, 0, sizeof(struct xmp_event)); - - pat_len = hio_read16l(f) /* - 4 */ ; - mod->xxp[i]->rows = hio_read16l(f); - - if (libxmp_alloc_tracks_in_pattern(mod, i) < 0) { - return -1; - } - - memset(mask, 0, L_CHANNELS); - hio_read16l(f); - hio_read16l(f); - - while (--pat_len >= 0) { - b = hio_read8(f); - if (!b) { - r++; - continue; - } - c = (b - 1) & 63; - - if (b & 0x80) { - mask[c] = hio_read8(f); - pat_len--; - } - /* - * WARNING: we IGNORE events in disabled channels. Disabled - * channels should be muted only, but we don't know the - * real number of channels before loading the patterns and - * we don't want to set it to 64 channels. - */ - if (c >= mod->chn || r >= mod->xxp[i]->rows) { - event = &dummy; - } else { - event = &EVENT(i, c, r); - } - - if (mask[c] & 0x01) { - b = hio_read8(f); - - /* From ittech.txt: - * Note ranges from 0->119 (C-0 -> B-9) - * 255 = note off, 254 = notecut - * Others = note fade (already programmed into IT's player - * but not available in the editor) - */ - switch (b) { - case 0xff: /* key off */ - b = XMP_KEY_OFF; - break; - case 0xfe: /* cut */ - b = XMP_KEY_CUT; - break; - default: - if (b > 119) { /* fade */ - b = XMP_KEY_FADE; - } else { - b++; /* note */ - } - } - lastevent[c].note = event->note = b; - pat_len--; - } - if (mask[c] & 0x02) { - b = hio_read8(f); - lastevent[c].ins = event->ins = b; - pat_len--; - } - if (mask[c] & 0x04) { - b = hio_read8(f); - lastevent[c].vol = event->vol = b; - xlat_volfx(event); - pat_len--; - } - if (mask[c] & 0x08) { - b = hio_read8(f); - if (b > 31) { - D_(D_WARN "invalid effect %#02x", b); - hio_read8(f); - - } else { - event->fxt = b; - event->fxp = hio_read8(f); - - xlat_fx(c, event, last_fxp, new_fx); - lastevent[c].fxt = event->fxt; - lastevent[c].fxp = event->fxp; - } - pat_len -= 2; - } - if (mask[c] & 0x10) { - event->note = lastevent[c].note; - } - if (mask[c] & 0x20) { - event->ins = lastevent[c].ins; - } - if (mask[c] & 0x40) { - event->vol = lastevent[c].vol; - xlat_volfx(event); - } - if (mask[c] & 0x80) { - event->fxt = lastevent[c].fxt; - event->fxp = lastevent[c].fxp; - } - } - - return 0; -} - -static int it_load(struct module_data *m, HIO_HANDLE *f, const int start) -{ - struct xmp_module *mod = &m->mod; - int c, i, j; - struct it_file_header ifh; - int max_ch; - uint32 *pp_ins; /* Pointers to instruments */ - uint32 *pp_smp; /* Pointers to samples */ - uint32 *pp_pat; /* Pointers to patterns */ - int new_fx, sample_mode; - - LOAD_INIT(); - - /* Load and convert header */ - ifh.magic = hio_read32b(f); - if (ifh.magic != MAGIC_IMPM) { - return -1; - } - - hio_read(&ifh.name, 26, 1, f); - ifh.hilite_min = hio_read8(f); - ifh.hilite_maj = hio_read8(f); - - ifh.ordnum = hio_read16l(f); - ifh.insnum = hio_read16l(f); - ifh.smpnum = hio_read16l(f); - ifh.patnum = hio_read16l(f); - - ifh.cwt = hio_read16l(f); - ifh.cmwt = hio_read16l(f); - ifh.flags = hio_read16l(f); - ifh.special = hio_read16l(f); - - ifh.gv = hio_read8(f); - ifh.mv = hio_read8(f); - ifh.is = hio_read8(f); - ifh.it = hio_read8(f); - ifh.sep = hio_read8(f); - ifh.pwd = hio_read8(f); - - /* Sanity check */ - if (ifh.gv > 0x80 || ifh.mv > 0x80) { - goto err; - } - - ifh.msglen = hio_read16l(f); - ifh.msgofs = hio_read32l(f); - ifh.rsvd = hio_read32l(f); - - hio_read(&ifh.chpan, 64, 1, f); - hio_read(&ifh.chvol, 64, 1, f); - - strncpy(mod->name, (char *)ifh.name, XMP_NAME_SIZE); - mod->len = ifh.ordnum; - mod->ins = ifh.insnum; - mod->smp = ifh.smpnum; - mod->pat = ifh.patnum; - - /* Sanity check */ - if (mod->ins > 255 || mod->smp > 255 || mod->pat > 255) { - goto err; - } - - if (mod->ins) { - pp_ins = (uint32 *)calloc(4, mod->ins); - if (pp_ins == NULL) - goto err; - } else { - pp_ins = NULL; - } - - pp_smp = (uint32 *)calloc(4, mod->smp); - if (pp_smp == NULL) - goto err2; - - pp_pat = (uint32 *)calloc(4, mod->pat); - if (pp_pat == NULL) - goto err3; - - mod->spd = ifh.is; - mod->bpm = ifh.it; - - sample_mode = ~ifh.flags & IT_USE_INST; - - if (ifh.flags & IT_LINEAR_FREQ) { - m->period_type = PERIOD_LINEAR; - } - - if (!sample_mode && ifh.cmwt >= 0x200) { - m->quirk |= QUIRK_INSVOL; - } - - for (i = 0; i < 64; i++) { - struct xmp_channel *xxc = &mod->xxc[i]; - - if (ifh.chpan[i] == 100) { /* Surround -> center */ - xxc->flg |= XMP_CHANNEL_SURROUND; - } - - if (ifh.chpan[i] & 0x80) { /* Channel mute */ - xxc->flg |= XMP_CHANNEL_MUTE; - } - - if (ifh.flags & IT_STEREO) { - xxc->pan = (int)ifh.chpan[i] * 0x80 >> 5; - if (xxc->pan > 0xff) - xxc->pan = 0xff; - } else { - xxc->pan = 0x80; - } - - xxc->vol = ifh.chvol[i]; - } - if (mod->len <= XMP_MAX_MOD_LENGTH) { - hio_read(mod->xxo, 1, mod->len, f); - } else { - hio_read(mod->xxo, 1, XMP_MAX_MOD_LENGTH, f); - hio_seek(f, mod->len - XMP_MAX_MOD_LENGTH, SEEK_CUR); - mod->len = XMP_MAX_MOD_LENGTH; - } - - new_fx = ifh.flags & IT_OLD_FX ? 0 : 1; - - for (i = 0; i < mod->ins; i++) - pp_ins[i] = hio_read32l(f); - for (i = 0; i < mod->smp; i++) - pp_smp[i] = hio_read32l(f); - for (i = 0; i < mod->pat; i++) - pp_pat[i] = hio_read32l(f); - - m->c4rate = C4_NTSC_RATE; - - identify_tracker(m, &ifh); - - MODULE_INFO(); - - D_(D_INFO "Instrument/FX mode: %s/%s", - sample_mode ? "sample" : ifh.cmwt >= 0x200 ? - "new" : "old", ifh.flags & IT_OLD_FX ? "old" : "IT"); - - if (sample_mode) - mod->ins = mod->smp; - - if (libxmp_init_instrument(m) < 0) - goto err4; - - /* Alloc extra samples for sustain loop */ - if (mod->smp > 0) { - m->xsmp = (struct xmp_sample *)calloc(sizeof (struct xmp_sample), mod->smp); - if (m->xsmp == NULL) { - goto err4; - } - } - - D_(D_INFO "Instruments: %d", mod->ins); - - for (i = 0; i < mod->ins; i++) { - /* - * IT files can have three different instrument types: 'New' - * instruments, 'old' instruments or just samples. We need a - * different loader for each of them. - */ - - struct xmp_instrument *xxi = &mod->xxi[i]; - - if (!sample_mode && ifh.cmwt >= 0x200) { - /* New instrument format */ - if (hio_seek(f, start + pp_ins[i], SEEK_SET) < 0) { - goto err4; - } - - if (load_new_it_instrument(xxi, f) < 0) { - goto err4; - } - - } else if (!sample_mode) { - /* Old instrument format */ - if (hio_seek(f, start + pp_ins[i], SEEK_SET) < 0) { - goto err4; - } - - if (load_old_it_instrument(xxi, f) < 0) { - goto err4; - } - } - } - - D_(D_INFO "Stored Samples: %d", mod->smp); - - for (i = 0; i < mod->smp; i++) { - - if (hio_seek(f, start + pp_smp[i], SEEK_SET) < 0) { - goto err4; - } - - if (load_it_sample(m, i, start, sample_mode, f) < 0) { - goto err4; - } - } - - D_(D_INFO "Stored patterns: %d", mod->pat); - - /* Effects in muted channels are processed, so scan patterns first to - * see the real number of channels - */ - max_ch = 0; - for (i = 0; i < mod->pat; i++) { - uint8 mask[L_CHANNELS]; - int pat_len; - - /* If the offset to a pattern is 0, the pattern is empty */ - if (pp_pat[i] == 0) - continue; - - hio_seek(f, start + pp_pat[i], SEEK_SET); - pat_len = hio_read16l(f) /* - 4 */ ; - hio_read16l(f); - memset(mask, 0, L_CHANNELS); - hio_read16l(f); - hio_read16l(f); - - while (--pat_len >= 0) { - int b = hio_read8(f); - if (b == 0) - continue; - - c = (b - 1) & 63; - - if (c > max_ch) - max_ch = c; - - if (b & 0x80) { - mask[c] = hio_read8(f); - pat_len--; - } - - if (mask[c] & 0x01) { - hio_read8(f); - pat_len--; - } - if (mask[c] & 0x02) { - hio_read8(f); - pat_len--; - } - if (mask[c] & 0x04) { - hio_read8(f); - pat_len--; - } - if (mask[c] & 0x08) { - hio_read8(f); - hio_read8(f); - pat_len -= 2; - } - } - } - - /* Set the number of channels actually used - */ - mod->chn = max_ch + 1; - mod->trk = mod->pat * mod->chn; - - if (libxmp_init_pattern(mod) < 0) { - goto err4; - } - - /* Read patterns */ - for (i = 0; i < mod->pat; i++) { - - if (libxmp_alloc_pattern(mod, i) < 0) { - goto err4; - } - - /* If the offset to a pattern is 0, the pattern is empty */ - if (pp_pat[i] == 0) { - mod->xxp[i]->rows = 64; - for (j = 0; j < mod->chn; j++) { - int tnum = i * mod->chn + j; - if (libxmp_alloc_track(mod, tnum, 64) < 0) - goto err4; - mod->xxp[i]->index[j] = tnum; - } - continue; - } - - if (hio_seek(f, start + pp_pat[i], SEEK_SET) < 0) { - D_(D_CRIT "error seeking to %d", start + pp_pat[i]); - goto err4; - } - - if (load_it_pattern(m, i, new_fx, f) < 0) { - D_(D_CRIT "error loading pattern %d", i); - goto err4; - } - } - - free(pp_pat); - free(pp_smp); - free(pp_ins); - - /* Song message */ - - if (ifh.special & IT_HAS_MSG) { - if ((m->comment = (char *)malloc(ifh.msglen)) != NULL) { - hio_seek(f, start + ifh.msgofs, SEEK_SET); - - D_(D_INFO "Message length : %d", ifh.msglen); - - for (j = 0; j + 1 < ifh.msglen; j++) { - int b = hio_read8(f); - if (b == '\r') { - b = '\n'; - } else if ((b < 32 || b > 127) && b != '\n' - && b != '\t') { - b = '.'; - } - m->comment[j] = b; - } - - if (ifh.msglen > 0) { - m->comment[j] = 0; - } - } - } - - /* Format quirks */ - - m->quirk |= QUIRKS_IT | QUIRK_ARPMEM; - - if (ifh.flags & IT_LINK_GXX) { - m->quirk |= QUIRK_PRENV; - } else { - m->quirk |= QUIRK_UNISLD; - } - - if (new_fx) { - m->quirk |= QUIRK_VIBHALF | QUIRK_VIBINV; - } else { - m->quirk &= ~QUIRK_VIBALL; - m->quirk |= QUIRK_ITOLDFX; - } - - if (sample_mode) { - m->quirk &= ~(QUIRK_VIRTUAL | QUIRK_RSTCHN); - } - - m->gvolbase = 0x80; - m->gvol = ifh.gv; - m->read_event_type = READ_EVENT_IT; - - return 0; - -err4: - free(pp_pat); -err3: - free(pp_smp); -err2: - free(pp_ins); -err: - return -1; -} - -#endif /* LIBXMP_CORE_DISABLE_IT */ diff --git a/source/libxmp-lite/src/itsex.c b/source/libxmp-lite/src/itsex.c deleted file mode 100644 index 55b93fe30..000000000 --- a/source/libxmp-lite/src/itsex.c +++ /dev/null @@ -1,232 +0,0 @@ -#ifndef LIBXMP_CORE_DISABLE_IT - -/* Public domain IT sample decompressor by Olivier Lapicque */ - -#include "loader.h" - -static inline uint32 read_bits(HIO_HANDLE *ibuf, uint32 *bitbuf, int *bitnum, int n) -{ - uint32 retval = 0; - int i = n; - int bnum = *bitnum, bbuf = *bitbuf; - - if (n > 0) { - do { - if (bnum == 0) { - bbuf = hio_read8(ibuf); - bnum = 8; - } - retval >>= 1; - retval |= bbuf << 31; - bbuf >>= 1; - bnum--; - i--; - } while (i != 0); - - i = n; - - *bitnum = bnum; - *bitbuf = bbuf; - } - - return (retval >> (32 - i)); -} - - -int itsex_decompress8(HIO_HANDLE *src, uint8 *dst, int len, int it215) -{ - /* uint32 size = 0; */ - uint32 block_count = 0; - uint32 bitbuf = 0; - int bitnum = 0; - uint8 left = 0, temp = 0, temp2 = 0; - uint32 d, pos; - - while (len) { - if (!block_count) { - block_count = 0x8000; - /*size =*/ hio_read16l(src); - left = 9; - temp = temp2 = 0; - bitbuf = bitnum = 0; - } - - d = block_count; - if (d > len) - d = len; - - /* Unpacking */ - pos = 0; - do { - uint16 bits = read_bits(src, &bitbuf, &bitnum, left); - if (hio_eof(src)) - return -1; - - if (left < 7) { - uint32 i = 1 << (left - 1); - uint32 j = bits & 0xffff; - if (i != j) - goto unpack_byte; - bits = (read_bits(src, &bitbuf, &bitnum, 3) - + 1) & 0xff; - if (hio_eof(src)) - return -1; - - left = ((uint8)bits < left) ? (uint8)bits : - (uint8)((bits + 1) & 0xff); - goto next; - } - - if (left < 9) { - uint16 i = (0xff >> (9 - left)) + 4; - uint16 j = i - 8; - - if ((bits <= j) || (bits > i)) - goto unpack_byte; - - bits -= j; - left = ((uint8)(bits & 0xff) < left) ? - (uint8)(bits & 0xff) : - (uint8)((bits + 1) & 0xff); - goto next; - } - - if (left >= 10) - goto skip_byte; - - if (bits >= 256) { - left = (uint8) (bits + 1) & 0xff; - goto next; - } - - unpack_byte: - if (left < 8) { - uint8 shift = 8 - left; - signed char c = (signed char)(bits << shift); - c >>= shift; - bits = (uint16) c; - } - bits += temp; - temp = (uint8)bits; - temp2 += temp; - dst[pos] = it215 ? temp2 : temp; - - skip_byte: - pos++; - - next: - /* if (slen <= 0) - return -1 */; - } while (pos < d); - - /* Move On */ - block_count -= d; - len -= d; - dst += d; - } - - return 0; -} - -int itsex_decompress16(HIO_HANDLE *src, int16 *dst, int len, int it215) -{ - /* uint32 size = 0; */ - uint32 block_count = 0; - uint32 bitbuf = 0; - int bitnum = 0; - uint8 left = 0; - int16 temp = 0, temp2 = 0; - uint32 d, pos; - - while (len) { - if (!block_count) { - block_count = 0x4000; - /*size =*/ hio_read16l(src); - left = 17; - temp = temp2 = 0; - bitbuf = bitnum = 0; - } - - d = block_count; - if (d > len) - d = len; - - /* Unpacking */ - pos = 0; - do { - uint32 bits = read_bits(src, &bitbuf, &bitnum, left); - if (hio_eof(src)) - return -1; - - if (left < 7) { - uint32 i = 1 << (left - 1); - uint32 j = bits; - - if (i != j) - goto unpack_byte; - - bits = read_bits(src, &bitbuf, &bitnum, 4) + 1; - - if (hio_eof(src)) - return -1; - - left = ((uint8)(bits & 0xff) < left) ? - (uint8)(bits & 0xff) : - (uint8)((bits + 1) & 0xff); - goto next; - } - - if (left < 17) { - uint32 i = (0xffff >> (17 - left)) + 8; - uint32 j = (i - 16) & 0xffff; - - if ((bits <= j) || (bits > (i & 0xffff))) - goto unpack_byte; - - bits -= j; - left = ((uint8)(bits & 0xff) < left) ? - (uint8)(bits & 0xff) : - (uint8)((bits + 1) & 0xff); - goto next; - } - - if (left >= 18) - goto skip_byte; - - if (bits >= 0x10000) { - left = (uint8)(bits + 1) & 0xff; - goto next; - } - - unpack_byte: - if (left < 16) { - uint8 shift = 16 - left; - int16 c = (int16)(bits << shift); - c >>= shift; - bits = (uint32) c; - } - bits += temp; - temp = (int16)bits; - temp2 += temp; - dst[pos] = (it215) ? temp2 : temp; - - skip_byte: - pos++; - - next: - /* if (slen <= 0) - return -1 */; - } while (pos < d); - - /* Move On */ - block_count -= d; - len -= d; - dst += d; - if (len <= 0) - break; - } - - return 0; -} - -#endif /* LIBXMP_CORE_DISABLE_IT */ diff --git a/source/libxmp-lite/src/lfo.c b/source/libxmp-lite/src/lfo.c deleted file mode 100644 index 72911c1cd..000000000 --- a/source/libxmp-lite/src/lfo.c +++ /dev/null @@ -1,164 +0,0 @@ -/* Extended Module Player - * 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"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include -#include "lfo.h" - -#define WAVEFORM_SIZE 64 - -static const int sine_wave[WAVEFORM_SIZE] = { - 0, 24, 49, 74, 97, 120, 141, 161, 180, 197, 212, 224, - 235, 244, 250, 253, 255, 253, 250, 244, 235, 224, 212, 197, - 180, 161, 141, 120, 97, 74, 49, 24, 0, -24, -49, -74, - -97,-120,-141,-161,-180,-197,-212,-224,-235,-244,-250,-253, - -255,-253,-250,-244,-235,-224,-212,-197,-180,-161,-141,-120, - -97, -74, -49, -24 -}; - -/* LFO */ - -static int get_lfo_mod(struct lfo *lfo) -{ - int val; - - if (lfo->rate == 0) - return 0; - - switch (lfo->type) { - case 0: /* sine */ - val = sine_wave[lfo->phase]; - break; - case 1: /* ramp down */ - val = 255 - (lfo->phase << 3); - break; - case 2: /* square */ - val = lfo->phase < WAVEFORM_SIZE / 2 ? 255 : -255; - break; - case 3: /* random */ - val = ((rand() & 0x1ff) - 256); - break; -#ifndef LIBXMP_CORE_PLAYER - case 669: /* 669 vibrato */ - val = lfo->phase & 1; - break; -#endif - default: - return 0; - } - - return val * lfo->depth; -} - -static int get_lfo_st3(struct lfo *lfo) -{ - if (lfo->rate == 0) { - return 0; - } - - /* S3M square */ - if (lfo->type == 2) { - int val = lfo->phase < WAVEFORM_SIZE / 2 ? 255 : 0; - return val * lfo->depth; - } - - return get_lfo_mod(lfo); -} - -/* From OpenMPT VibratoWaveforms.xm: - * "Generally the vibrato and tremolo tables are identical to those that - * ProTracker uses, but the vibrato’s “ramp down” table is upside down." - */ -static int get_lfo_ft2(struct lfo *lfo) -{ - if (lfo->rate == 0) - return 0; - - /* FT2 ramp */ - if (lfo->type == 1) { - int phase = (lfo->phase + (WAVEFORM_SIZE >> 1)) % WAVEFORM_SIZE; - int val = (phase << 3) - 255; - return val * lfo->depth; - } - - return get_lfo_mod(lfo); -} - -#ifndef LIBXMP_CORE_DISABLE_IT - -static int get_lfo_it(struct lfo *lfo) -{ - if (lfo->rate == 0) - return 0; - - return get_lfo_st3(lfo); -} - -#endif - -int libxmp_lfo_get(struct context_data *ctx, struct lfo *lfo, int is_vibrato) -{ - struct module_data *m = &ctx->m; - - switch (m->read_event_type) { - case READ_EVENT_ST3: - return get_lfo_st3(lfo); - case READ_EVENT_FT2: - if (is_vibrato) { - return get_lfo_ft2(lfo); - } else { - return get_lfo_mod(lfo); - } -#ifndef LIBXMP_CORE_DISABLE_IT - case READ_EVENT_IT: - return get_lfo_it(lfo); -#endif - default: - return get_lfo_mod(lfo); - } -} - - -void libxmp_lfo_update(struct lfo *lfo) -{ - lfo->phase += lfo->rate; - lfo->phase %= WAVEFORM_SIZE; -} - -void libxmp_lfo_set_phase(struct lfo *lfo, int phase) -{ - lfo->phase = phase; -} - -void libxmp_lfo_set_depth(struct lfo *lfo, int depth) -{ - lfo->depth = depth; -} - -void libxmp_lfo_set_rate(struct lfo *lfo, int rate) -{ - lfo->rate = rate; -} - -void libxmp_lfo_set_waveform(struct lfo *lfo, int type) -{ - lfo->type = type; -} diff --git a/source/libxmp-lite/src/lfo.h b/source/libxmp-lite/src/lfo.h deleted file mode 100644 index a269ac3db..000000000 --- a/source/libxmp-lite/src/lfo.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef LIBXMP_LFO_H -#define LIBXMP_LFO_H - -#include "common.h" - -struct lfo { - int type; - int rate; - int depth; - int phase; -}; - -int libxmp_lfo_get(struct context_data *, struct lfo *, int); -void libxmp_lfo_update(struct lfo *); -void libxmp_lfo_set_phase(struct lfo *, int); -void libxmp_lfo_set_depth(struct lfo *, int); -void libxmp_lfo_set_rate(struct lfo *, int); -void libxmp_lfo_set_waveform(struct lfo *, int); - -#endif diff --git a/source/libxmp-lite/src/list.h b/source/libxmp-lite/src/list.h deleted file mode 100644 index e284a5eef..000000000 --- a/source/libxmp-lite/src/list.h +++ /dev/null @@ -1,146 +0,0 @@ -#ifndef LIBXMP_LIST_H -#define LIBXMP_LIST_H - -#ifdef _MSC_VER -#define __inline__ __inline -#endif -#ifdef __WATCOMC__ -#define __inline__ inline -#endif - -/* - * Simple doubly linked list implementation. - * - * Some of the internal functions ("__xxx") are useful when - * manipulating whole lists rather than single entries, as - * sometimes we already know the next/prev entries and we can - * generate better code by using them directly rather than - * using the generic single-entry routines. - */ - -struct list_head { - struct list_head *next, *prev; -}; - -#define LIST_HEAD_INIT(name) { &(name), &(name) } - -#define LIST_HEAD(name) \ - struct list_head name = LIST_HEAD_INIT(name) - -#define INIT_LIST_HEAD(ptr) do { \ - (ptr)->next = (ptr); (ptr)->prev = (ptr); \ -} while (0) - -/* - * Insert a new entry between two known consecutive entries. - * - * This is only for internal list manipulation where we know - * the prev/next entries already! - */ -static __inline__ void __list_add(struct list_head *_new, - struct list_head * prev, - struct list_head * next) -{ - next->prev = _new; - _new->next = next; - _new->prev = prev; - prev->next = _new; -} - -/** - * list_add - add a new entry - * @_new: new entry to be added - * @head: list head to add it after - * - * Insert a new entry after the specified head. - * This is good for implementing stacks. - */ -static __inline__ void list_add(struct list_head *_new, struct list_head *head) -{ - __list_add(_new, head, head->next); -} - -/** - * list_add_tail - add a new entry - * @_new: new entry to be added - * @head: list head to add it before - * - * Insert a new entry before the specified head. - * This is useful for implementing queues. - */ -static __inline__ void list_add_tail(struct list_head *_new, struct list_head *head) -{ - __list_add(_new, head->prev, head); -} - -/* - * Delete a list entry by making the prev/next entries - * point to each other. - * - * This is only for internal list manipulation where we know - * the prev/next entries already! - */ -static __inline__ void __list_del(struct list_head * prev, - struct list_head * next) -{ - next->prev = prev; - prev->next = next; -} - -/** - * list_del - deletes entry from list. - * @entry: the element to delete from the list. - */ -static __inline__ void list_del(struct list_head *entry) -{ - __list_del(entry->prev, entry->next); -} - -/** - * list_empty - tests whether a list is empty - * @head: the list to test. - */ -static __inline__ int list_empty(struct list_head *head) -{ - return head->next == head; -} - -/** - * list_splice - join two lists - * @list: the new list to add. - * @head: the place to add it in the first list. - */ -static __inline__ void list_splice(struct list_head *list, struct list_head *head) -{ - struct list_head *first = list->next; - - if (first != list) { - struct list_head *last = list->prev; - struct list_head *at = head->next; - - first->prev = head; - head->next = first; - - last->next = at; - at->prev = last; - } -} - -/** - * list_entry - get the struct for this entry - * @ptr: the &struct list_head pointer. - * @type: the type of the struct this is embedded in. - * @member: the name of the list_struct within the struct. - */ -#define list_entry(ptr, type, member) \ - ((type *)((char *)(ptr)-(size_t)(&((type *)0)->member))) - -/** - * list_for_each - iterate over a list - * @pos: the &struct list_head to use as a loop counter. - * @head: the head for your list. - */ -#define list_for_each(pos, head) \ - for (pos = (head)->next; pos != (head); pos = pos->next) - -#endif diff --git a/source/libxmp-lite/src/load.c b/source/libxmp-lite/src/load.c deleted file mode 100644 index fa1002d4b..000000000 --- a/source/libxmp-lite/src/load.c +++ /dev/null @@ -1,695 +0,0 @@ -/* Extended Module Player - * 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"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include -#include -#include -#include -#include -#ifdef __native_client__ -#include -#else -#include -#endif - -#include "format.h" -#include "list.h" -#include "hio.h" - -#ifndef LIBXMP_CORE_PLAYER -#if !defined(HAVE_POPEN) && defined(WIN32) -#include "win32/ptpopen.h" -#define HAVE_POPEN 1 -#endif -#if defined(__WATCOMC__) -#define popen _popen -#define pclose _pclose -#define HAVE_POPEN 1 -#endif -#include "md5.h" -#include "extras.h" -#endif - - -extern const struct format_loader *const format_loader[]; - -void libxmp_load_prologue(struct context_data *); -void libxmp_load_epilogue(struct context_data *); -int libxmp_prepare_scan(struct context_data *); - -#ifndef LIBXMP_CORE_PLAYER - -#include "depacker.h" - -static struct depacker *depacker_list[] = { -#if defined __AMIGA__ && !defined __AROS__ - &libxmp_depacker_xfd, -#endif - &libxmp_depacker_zip, - &libxmp_depacker_lha, - &libxmp_depacker_gzip, - &libxmp_depacker_bzip2, - &libxmp_depacker_xz, - &libxmp_depacker_compress, - &libxmp_depacker_pp, - &libxmp_depacker_sqsh, - &libxmp_depacker_arcfs, - &libxmp_depacker_mmcmp, - &libxmp_depacker_muse, - &libxmp_depacker_lzx, - &libxmp_depacker_s404, - &libxmp_depacker_arc, - NULL -}; - -int test_oxm (FILE *); - -#define BUFLEN 16384 - -#ifndef HAVE_POPEN -static int execute_command(const char *cmd, const char *filename, FILE *t) { - return -1; -} -#else -static int execute_command(const char *cmd, const char *filename, FILE *t) -{ - char line[1024], buf[BUFLEN]; - FILE *p; - int n; - - snprintf(line, 1024, cmd, filename); - -#if defined(_WIN32) || defined(__OS2__) || defined(__EMX__) - /* Note: The _popen function returns an invalid file opaque, if - * used in a Windows program, that will cause the program to hang - * indefinitely. _popen works properly in a Console application. - * To create a Windows application that redirects input and output, - * read the section "Creating a Child Process with Redirected Input - * and Output" in the Win32 SDK. -- Mirko - */ - p = popen(line, "rb"); -#else - /* Linux popen fails with "rb" */ - p = popen(line, "r"); -#endif - - if (p == NULL) { - return -1; - } - - while ((n = fread(buf, 1, BUFLEN, p)) > 0) { - fwrite(buf, 1, n, t); - } - - pclose (p); - - return 0; -} -#endif - -static int decrunch(HIO_HANDLE **h, const char *filename, char **temp) -{ - unsigned char b[1024]; - const char *cmd; - FILE *f, *t; - int res; - int headersize; - int i; - struct depacker *depacker = NULL; - - cmd = NULL; - res = 0; - *temp = NULL; - f = (*h)->handle.file; - - headersize = fread(b, 1, 1024, f); - if (headersize < 100) { /* minimum valid file size */ - return 0; - } - - /* Check built-in depackers */ - for (i = 0; depacker_list[i] != NULL; i++) { - if (depacker_list[i]->test(b)) { - depacker = depacker_list[i]; - D_(D_INFO "Use depacker %d", i); - break; - } - } - - /* Check external commands */ - if (depacker == NULL) { - if (b[0] == 'M' && b[1] == 'O' && b[2] == '3') { - /* MO3 */ - D_(D_INFO "mo3"); - cmd = "unmo3 -s \"%s\" STDOUT"; - } else if (memcmp(b, "Rar", 3) == 0) { - /* rar */ - D_(D_INFO "rar"); - cmd = "unrar p -inul -xreadme -x*.diz -x*.nfo -x*.txt " - "-x*.exe -x*.com \"%s\""; - } else if (test_oxm(f) == 0) { - /* oggmod */ - D_(D_INFO "oggmod"); - depacker = &libxmp_depacker_oxm; - } - } - - if (fseek(f, 0, SEEK_SET) < 0) { - goto err; - } - - if (depacker == NULL && cmd == NULL) { - D_(D_INFO "Not packed"); - return 0; - } - -#if defined __ANDROID__ || defined __native_client__ - /* Don't use external helpers in android */ - if (cmd) { - return 0; - } -#endif - - D_(D_WARN "Depacking file... "); - - if ((t = make_temp_file(temp)) == NULL) { - goto err; - } - - /* Depack file */ - if (cmd) { - D_(D_INFO "External depacker: %s", cmd); - if (execute_command(cmd, filename, t) < 0) { - D_(D_CRIT "failed"); - goto err2; - } - } else if (depacker) { - D_(D_INFO "Internal depacker"); - if (depacker->depack(f, t) < 0) { - D_(D_CRIT "failed"); - goto err2; - } - } - - D_(D_INFO "done"); - - if (fseek(t, 0, SEEK_SET) < 0) { - D_(D_CRIT "fseek error"); - goto err2; - } - - hio_close(*h); - *h = hio_open_file(t); - - return res; - - err2: - fclose(t); - err: - return -1; -} - -static void set_md5sum(HIO_HANDLE *f, unsigned char *digest) -{ - unsigned char buf[BUFLEN]; - MD5_CTX ctx; - int bytes_read; - - if (hio_size(f) <= 0) { - memset(digest, 0, 16); - return; - } - - hio_seek(f, 0, SEEK_SET); - - MD5Init(&ctx); - while ((bytes_read = hio_read(buf, 1, BUFLEN, f)) > 0) { - MD5Update(&ctx, buf, bytes_read); - } - MD5Final(digest, &ctx); -} - -static char *get_dirname(char *name) -{ - char *div, *dirname; - int len; - - if ((div = strrchr(name, '/'))) { - len = div - name + 1; - dirname = malloc(len + 1); - if (dirname != NULL) { - memcpy(dirname, name, len); - dirname[len] = 0; - } - } else { - dirname = strdup(""); - } - - return dirname; -} - -static char *get_basename(char *name) -{ - char *div, *basename; - - if ((div = strrchr(name, '/'))) { - basename = strdup(div + 1); - } else { - basename = strdup(name); - } - - return basename; -} -#endif /* LIBXMP_CORE_PLAYER */ - -#ifdef EDUKE32_DISABLED -int xmp_test_module(char *path, struct xmp_test_info *info) -{ - HIO_HANDLE *h; - struct stat st; - char buf[XMP_NAME_SIZE]; - int i; - int ret = -XMP_ERROR_FORMAT; -#ifndef LIBXMP_CORE_PLAYER - char *temp = NULL; -#endif - - if (stat(path, &st) < 0) - return -XMP_ERROR_SYSTEM; - -#ifndef _MSC_VER - if (S_ISDIR(st.st_mode)) { - errno = EISDIR; - return -XMP_ERROR_SYSTEM; - } -#endif - - if ((h = hio_open(path, "rb")) == NULL) - return -XMP_ERROR_SYSTEM; - -#ifndef LIBXMP_CORE_PLAYER - if (decrunch(&h, path, &temp) < 0) { - ret = -XMP_ERROR_DEPACK; - goto err; - } - - /* get size after decrunch */ - if (hio_size(h) < 256) { /* set minimum valid module size */ - ret = -XMP_ERROR_FORMAT; - goto err; - } -#endif - - if (info != NULL) { - *info->name = 0; /* reset name prior to testing */ - *info->type = 0; /* reset type prior to testing */ - } - - for (i = 0; format_loader[i] != NULL; i++) { - hio_seek(h, 0, SEEK_SET); - if (format_loader[i]->test(h, buf, 0) == 0) { - int is_prowizard = 0; - -#ifndef LIBXMP_CORE_PLAYER - if (strcmp(format_loader[i]->name, "prowizard") == 0) { - hio_seek(h, 0, SEEK_SET); - pw_test_format(h, buf, 0, info); - is_prowizard = 1; - } -#endif - - fclose(h->handle.file); - -#ifndef LIBXMP_CORE_PLAYER - unlink_temp_file(temp); -#endif - - if (info != NULL && !is_prowizard) { - strncpy(info->name, buf, XMP_NAME_SIZE - 1); - strncpy(info->type, format_loader[i]->name, - XMP_NAME_SIZE - 1); - } - return 0; - } - } - -#ifndef LIBXMP_CORE_PLAYER - err: - hio_close(h); - unlink_temp_file(temp); -#else - hio_close(h); -#endif - return ret; -} -#endif - -static int load_module(xmp_context opaque, HIO_HANDLE *h) -{ - struct context_data *ctx = (struct context_data *)opaque; - struct module_data *m = &ctx->m; - struct xmp_module *mod = &m->mod; - int i, j, ret; - int test_result, load_result; - - libxmp_load_prologue(ctx); - - D_(D_WARN "load"); - test_result = load_result = -1; - for (i = 0; format_loader[i] != NULL; i++) { - hio_seek(h, 0, SEEK_SET); - - if (hio_error(h)) { - /* reset error flag */ - } - - D_(D_WARN "test %s", format_loader[i]->name); - test_result = format_loader[i]->test(h, NULL, 0); - if (test_result == 0) { - hio_seek(h, 0, SEEK_SET); - D_(D_WARN "load format: %s", format_loader[i]->name); - load_result = format_loader[i]->loader(m, h, 0); - break; - } - } - -#ifndef LIBXMP_CORE_PLAYER - if (test_result == 0 && load_result == 0) - set_md5sum(h, m->md5); -#endif - - if (test_result < 0) { - free(m->basename); - free(m->dirname); - return -XMP_ERROR_FORMAT; - } - - if (load_result < 0) { - goto err_load; - } - - /* Sanity check: number of channels, module length */ - if (mod->chn > XMP_MAX_CHANNELS || mod->len > XMP_MAX_MOD_LENGTH) { - goto err_load; - } - - /* Sanity check: channel pan */ - for (i = 0; i < mod->chn; i++) { - if (mod->xxc[i].vol < 0 || mod->xxc[i].vol > 0xff) { - goto err_load; - } - if (mod->xxc[i].pan < 0 || mod->xxc[i].pan > 0xff) { - goto err_load; - } - } - - /* Sanity check: patterns */ - if (mod->xxp == NULL) { - goto err_load; - } - for (i = 0; i < mod->pat; i++) { - if (mod->xxp[i] == NULL) { - goto err_load; - } - for (j = 0; j < mod->chn; j++) { - int t = mod->xxp[i]->index[j]; - if (t < 0 || t >= mod->trk || mod->xxt[t] == NULL) { - goto err_load; - } - } - } - - libxmp_adjust_string(mod->name); - for (i = 0; i < mod->ins; i++) { - libxmp_adjust_string(mod->xxi[i].name); - } - for (i = 0; i < mod->smp; i++) { - libxmp_adjust_string(mod->xxs[i].name); - } - - libxmp_load_epilogue(ctx); - - ret = libxmp_prepare_scan(ctx); - if (ret < 0) { - xmp_release_module(opaque); - return ret; - } - - libxmp_scan_sequences(ctx); - - ctx->state = XMP_STATE_LOADED; - - return 0; - - err_load: - xmp_release_module(opaque); - return -XMP_ERROR_LOAD; -} - -#ifdef EDUKE32_DISABLED -int xmp_load_module(xmp_context opaque, char *path) -{ - struct context_data *ctx = (struct context_data *)opaque; -#ifndef LIBXMP_CORE_PLAYER - struct module_data *m = &ctx->m; - long size; - char *temp_name; -#endif - HIO_HANDLE *h; - struct stat st; - int ret; - - D_(D_WARN "path = %s", path); - - if (stat(path, &st) < 0) { - return -XMP_ERROR_SYSTEM; - } - -#ifndef _MSC_VER - if (S_ISDIR(st.st_mode)) { - errno = EISDIR; - return -XMP_ERROR_SYSTEM; - } -#endif - - if ((h = hio_open(path, "rb")) == NULL) { - return -XMP_ERROR_SYSTEM; - } - -#ifndef LIBXMP_CORE_PLAYER - D_(D_INFO "decrunch"); - if (decrunch(&h, path, &temp_name) < 0) { - ret = -XMP_ERROR_DEPACK; - goto err; - } - - size = hio_size(h); - if (size < 256) { /* get size after decrunch */ - ret = -XMP_ERROR_FORMAT; - goto err; - } -#endif - - if (ctx->state > XMP_STATE_UNLOADED) - xmp_release_module(opaque); - -#ifndef LIBXMP_CORE_PLAYER - m->dirname = get_dirname(path); - if (m->dirname == NULL) { - ret = -XMP_ERROR_SYSTEM; - goto err; - } - - m->basename = get_basename(path); - if (m->basename == NULL) { - ret = -XMP_ERROR_SYSTEM; - goto err; - } - - m->filename = path; /* For ALM, SSMT, etc */ - m->size = size; -#endif - - ret = load_module(opaque, h); - hio_close(h); - -#ifndef LIBXMP_CORE_PLAYER - unlink_temp_file(temp_name); -#endif - - return ret; - -#ifndef LIBXMP_CORE_PLAYER - err: - hio_close(h); - unlink_temp_file(temp_name); - return ret; -#endif -} -#endif - -int xmp_load_module_from_memory(xmp_context opaque, void *mem, long size) -{ - struct context_data *ctx = (struct context_data *)opaque; - struct module_data *m = &ctx->m; - HIO_HANDLE *h; - int ret; - - /* Use size < 0 for unknown/undetermined size */ - if (size == 0) - size--; - - if ((h = hio_open_mem(mem, size)) == NULL) - return -XMP_ERROR_SYSTEM; - - if (ctx->state > XMP_STATE_UNLOADED) - xmp_release_module(opaque); - - m->filename = NULL; - m->basename = NULL; - m->dirname = NULL; - m->size = size; - - ret = load_module(opaque, h); - - hio_close(h); - - return ret; -} - -#ifdef EDUKE32_DISABLED -int xmp_load_module_from_file(xmp_context opaque, void *file, long size) -{ - struct context_data *ctx = (struct context_data *)opaque; - struct module_data *m = &ctx->m; - HIO_HANDLE *h; - FILE *f = fdopen(fileno((FILE *)file), "rb"); - int ret; - - if ((h = hio_open_file(f)) == NULL) - return -XMP_ERROR_SYSTEM; - - if (ctx->state > XMP_STATE_UNLOADED) - xmp_release_module(opaque); - - m->filename = NULL; - m->basename = NULL; - m->dirname = NULL; - m->size = hio_size(h); - - ret = load_module(opaque, h); - - hio_close(h); - - return ret; -} -#endif - -void xmp_release_module(xmp_context opaque) -{ - struct context_data *ctx = (struct context_data *)opaque; - struct module_data *m = &ctx->m; - struct xmp_module *mod = &m->mod; - int i; - - /* can't test this here, we must call release_module to clean up - * load errors - if (ctx->state < XMP_STATE_LOADED) - return; - */ - - if (ctx->state > XMP_STATE_LOADED) - xmp_end_player(opaque); - - ctx->state = XMP_STATE_UNLOADED; - - D_(D_INFO "Freeing memory"); - -#ifndef LIBXMP_CORE_PLAYER - libxmp_release_module_extras(ctx); -#endif - - if (mod->xxt != NULL) { - for (i = 0; i < mod->trk; i++) { - free(mod->xxt[i]); - } - free(mod->xxt); - } - - if (mod->xxp != NULL) { - for (i = 0; i < mod->pat; i++) { - free(mod->xxp[i]); - } - free(mod->xxp); - } - - if (mod->xxi != NULL) { - for (i = 0; i < mod->ins; i++) { - free(mod->xxi[i].sub); - free(mod->xxi[i].extra); - } - free(mod->xxi); - } - - if (mod->xxs != NULL) { - for (i = 0; i < mod->smp; i++) { - if (mod->xxs[i].data != NULL) { - free(mod->xxs[i].data - 4); - } - } - free(mod->xxs); - free(m->xtra); - } - -#ifndef LIBXMP_CORE_DISABLE_IT - if (m->xsmp != NULL) { - for (i = 0; i < mod->smp; i++) { - if (m->xsmp[i].data != NULL) { - free(m->xsmp[i].data - 4); - } - } - free(m->xsmp); - } -#endif - - if (m->scan_cnt) { - for (i = 0; i < mod->len; i++) - free(m->scan_cnt[i]); - free(m->scan_cnt); - } - - free(m->comment); - - D_("free dirname/basename"); - free(m->dirname); - free(m->basename); -} - -void xmp_scan_module(xmp_context opaque) -{ - struct context_data *ctx = (struct context_data *)opaque; - - if (ctx->state < XMP_STATE_LOADED) - return; - - libxmp_scan_sequences(ctx); -} diff --git a/source/libxmp-lite/src/load_helpers.c b/source/libxmp-lite/src/load_helpers.c deleted file mode 100644 index 40cafe5db..000000000 --- a/source/libxmp-lite/src/load_helpers.c +++ /dev/null @@ -1,425 +0,0 @@ -/* Extended Module Player - * 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"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include -#include -#include -#include -#include "common.h" -#include "loader.h" - - -#ifndef LIBXMP_CORE_PLAYER - -#ifdef __ANDROID__ -#include -#include -#include -#endif - -#include - -/* - * Handle special "module quirks" that can't be detected automatically - * such as Protracker 2.x compatibility, vblank timing, etc. - */ - -struct module_quirk { - uint8 md5[16]; - int flags; - int mode; -}; - -const struct module_quirk mq[] = { - /* "No Mercy" by Alf/VTL (added by Martin Willers) */ - { - { 0x36, 0x6e, 0xc0, 0xfa, 0x96, 0x2a, 0xeb, 0xee, - 0x03, 0x4a, 0xa2, 0xdb, 0xaa, 0x49, 0xaa, 0xea }, - 0, XMP_MODE_PROTRACKER - }, - - /* mod.souvenir of china */ - { - { 0x93, 0xf1, 0x46, 0xae, 0xb7, 0x58, 0xc3, 0x9d, - 0x8b, 0x5f, 0xbc, 0x98, 0xbf, 0x23, 0x7a, 0x43 }, - XMP_FLAGS_FIXLOOP, XMP_MODE_AUTO - }, - - /* "siedler ii" (added by Daniel Åkerud) */ - { - { 0x70, 0xaa, 0x03, 0x4d, 0xfb, 0x2f, 0x1f, 0x73, - 0xd9, 0xfd, 0xba, 0xfe, 0x13, 0x1b, 0xb7, 0x01 }, - XMP_FLAGS_VBLANK, XMP_MODE_AUTO - }, - - /* "Klisje paa klisje" (added by Kjetil Torgrim Homme) */ - { - { 0xe9, 0x98, 0x01, 0x2c, 0x70, 0x0e, 0xb4, 0x3a, - 0xf0, 0x32, 0x17, 0x11, 0x30, 0x58, 0x29, 0xb2 }, - 0, XMP_MODE_NOISETRACKER - }, - -#if 0 - /* -- Already covered by Noisetracker fingerprinting -- */ - - /* Another version of Klisje paa klisje sent by Steve Fernandez */ - { - { 0x12, 0x19, 0x1c, 0x90, 0x41, 0xe3, 0xfd, 0x70, - 0xb7, 0xe6, 0xb3, 0x94, 0x8b, 0x21, 0x07, 0x63 }, - XMP_FLAGS_VBLANK - }, -#endif - - /* "((((( nebulos )))))" sent by Tero Auvinen (AMP version) */ - { - { 0x51, 0x6e, 0x8d, 0xcc, 0x35, 0x7d, 0x50, 0xde, - 0xa9, 0x85, 0xbe, 0xbf, 0x90, 0x2e, 0x42, 0xdc }, - 0, XMP_MODE_NOISETRACKER - }, - - /* Purple Motion's Sundance.mod, Music Channel BBS edit */ - { - { 0x5d, 0x3e, 0x1e, 0x08, 0x28, 0x52, 0x12, 0xc7, - 0x17, 0x64, 0x95, 0x75, 0x98, 0xe6, 0x95, 0xc1 }, - 0, XMP_MODE_ST3 - }, - - /* Asle's Ode to Protracker */ - { - { 0x97, 0xa3, 0x7d, 0x30, 0xd7, 0xae, 0x6d, 0x50, - 0xc9, 0x62, 0xe9, 0xd8, 0x87, 0x1b, 0x7e, 0x8a }, - 0, XMP_MODE_PROTRACKER - }, - - { - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - 0, 0 - } -}; - -static void module_quirks(struct context_data *ctx) -{ - struct player_data *p = &ctx->p; - struct module_data *m = &ctx->m; - int i; - - for (i = 0; mq[i].flags != 0 || mq[i].mode != 0; i++) { - if (!memcmp(m->md5, mq[i].md5, 16)) { - p->flags |= mq[i].flags; - p->mode = mq[i].mode; - } - } -} - -/* - * Check whether the given string matches one of the blacklisted glob - * patterns. Used to filter file names stored in archive files. - */ -int libxmp_exclude_match(const char *name) -{ - int i; - - static const char *const exclude[] = { - "README", "readme", - "*.DIZ", "*.diz", - "*.NFO", "*.nfo", - "*.DOC", "*.Doc", "*.doc", - "*.INFO", "*.info", "*.Info", - "*.TXT", "*.txt", - "*.EXE", "*.exe", - "*.COM", "*.com", - "*.README", "*.readme", "*.Readme", "*.ReadMe", - NULL - }; - - for (i = 0; exclude[i] != NULL; i++) { - if (fnmatch(exclude[i], name, 0) == 0) { - return 1; - } - } - - return 0; -} - -#endif /* LIBXMP_CORE_PLAYER */ - -char *libxmp_adjust_string(char *s) -{ - int i; - - for (i = 0; i < strlen(s); i++) { - if (!isprint((int)s[i]) || ((uint8) s[i] > 127)) - s[i] = ' '; - } - - while (*s && (s[strlen(s) - 1] == ' ')) { - s[strlen(s) - 1] = 0; - } - - return s; -} - -static void check_envelope(struct xmp_envelope *env) -{ - /* Disable envelope if invalid number of points */ - if (env->npt <= 0 || env->npt > XMP_MAX_ENV_POINTS) { - env->flg &= ~XMP_ENVELOPE_ON; - } - - /* Disable envelope loop if invalid loop parameters */ - if (env->lps >= env->npt || env->lpe >= env->npt) { - env->flg &= ~XMP_ENVELOPE_LOOP; - } - - /* Disable envelope loop if invalid sustain */ - if (env->sus >= env->npt) { - env->flg &= ~XMP_ENVELOPE_ON; - } -} - -void libxmp_load_prologue(struct context_data *ctx) -{ - struct module_data *m = &ctx->m; - int i; - - /* Reset variables */ - memset(&m->mod, 0, sizeof (struct xmp_module)); - m->rrate = PAL_RATE; - m->c4rate = C4_PAL_RATE; - m->volbase = 0x40; - m->gvol = m->gvolbase = 0x40; - m->vol_table = NULL; - m->quirk = 0; - m->read_event_type = READ_EVENT_MOD; - m->period_type = PERIOD_AMIGA; - m->comment = NULL; - m->scan_cnt = NULL; - - /* Set defaults */ - m->mod.pat = 0; - m->mod.trk = 0; - m->mod.chn = 4; - m->mod.ins = 0; - m->mod.smp = 0; - m->mod.spd = 6; - m->mod.bpm = 125; - m->mod.len = 0; - m->mod.rst = 0; - -#ifndef LIBXMP_CORE_PLAYER - m->extra = NULL; -#endif -#ifndef LIBXMP_CORE_DISABLE_IT - m->xsmp = NULL; -#endif - - m->time_factor = DEFAULT_TIME_FACTOR; - - for (i = 0; i < 64; i++) { - int pan = (((i + 1) / 2) % 2) * 0xff; - m->mod.xxc[i].pan = 0x80 + (pan - 0x80) * m->defpan / 100; - m->mod.xxc[i].vol = 0x40; - m->mod.xxc[i].flg = 0; - } -} - -void libxmp_load_epilogue(struct context_data *ctx) -{ - struct player_data *p = &ctx->p; - struct module_data *m = &ctx->m; - struct xmp_module *mod = &m->mod; - int i, j; - - mod->gvl = m->gvol; - - /* Sanity check for module parameters */ - CLAMP(mod->len, 0, XMP_MAX_MOD_LENGTH); - CLAMP(mod->pat, 0, 257); /* some formats have an extra pattern */ - CLAMP(mod->ins, 0, 255); - CLAMP(mod->smp, 0, MAX_SAMPLES); - CLAMP(mod->chn, 0, XMP_MAX_CHANNELS); - - /* Fix cases where the restart value is invalid e.g. kc_fall8.xm - * from http://aminet.net/mods/mvp/mvp_0002.lha (reported by - * Ralf Hoffmann ) - */ - if (mod->rst >= mod->len) { - mod->rst = 0; - } - - /* Sanity check for tempo and BPM */ - if (mod->spd <= 0 || mod->spd > 255) { - mod->spd = 6; - } - CLAMP(mod->bpm, XMP_MIN_BPM, 255); - - /* Set appropriate values for instrument volumes and subinstrument - * global volumes when QUIRK_INSVOL is not set, to keep volume values - * consistent if the user inspects struct xmp_module. We can later - * set volumes in the loaders and eliminate the quirk. - */ - for (i = 0; i < mod->ins; i++) { - if (~m->quirk & QUIRK_INSVOL) { - mod->xxi[i].vol = m->volbase; - } - for (j = 0; j < mod->xxi[i].nsm; j++) { - if (~m->quirk & QUIRK_INSVOL) { - mod->xxi[i].sub[j].gvl = m->volbase; - } - } - } - - /* Sanity check for envelopes - */ - for (i = 0; i < mod->ins; i++) { - check_envelope(&mod->xxi[i].aei); - check_envelope(&mod->xxi[i].fei); - check_envelope(&mod->xxi[i].pei); - } - - p->filter = 0; - p->mode = XMP_MODE_AUTO; - p->flags = p->player_flags; -#ifndef LIBXMP_CORE_PLAYER - module_quirks(ctx); -#endif - libxmp_set_player_mode(ctx); -} - -int libxmp_prepare_scan(struct context_data *ctx) -{ - struct module_data *m = &ctx->m; - struct xmp_module *mod = &m->mod; - int i, ord; - - if (mod->xxp == NULL || mod->xxt == NULL) - return -XMP_ERROR_LOAD; - ord = 0; - while (ord < mod->len && mod->xxo[ord] >= mod->pat) { - ord++; - } - - if (ord >= mod->len) { - mod->len = 0; - return 0; - } - - m->scan_cnt = (char **)calloc(sizeof (char *), mod->len); - if (m->scan_cnt == NULL) - return -XMP_ERROR_SYSTEM; - - for (i = 0; i < mod->len; i++) { - int pat_idx = mod->xxo[i]; - struct xmp_pattern *pat; - - /* Add pattern if referenced in orders */ - if (pat_idx < mod->pat && !mod->xxp[pat_idx]) { - if (libxmp_alloc_pattern(mod, pat_idx) < 0) { - return -XMP_ERROR_SYSTEM; - } - } - - pat = pat_idx >= mod->pat ? NULL : mod->xxp[pat_idx]; - m->scan_cnt[i] = (char *)calloc(1, pat && pat->rows ? pat->rows : 1); - if (m->scan_cnt[i] == NULL) - return -XMP_ERROR_SYSTEM; - } - - return 0; -} - -/* Process player personality flags */ -int libxmp_set_player_mode(struct context_data *ctx) -{ - struct player_data *p = &ctx->p; - struct module_data *m = &ctx->m; - int q; - - switch (p->mode) { - case XMP_MODE_AUTO: - break; - case XMP_MODE_MOD: - m->c4rate = C4_PAL_RATE; - m->quirk = 0; - m->read_event_type = READ_EVENT_MOD; - m->period_type = PERIOD_AMIGA; - break; - case XMP_MODE_NOISETRACKER: - m->c4rate = C4_PAL_RATE; - m->quirk = QUIRK_NOBPM; - m->read_event_type = READ_EVENT_MOD; - m->period_type = PERIOD_MODRNG; - break; - case XMP_MODE_PROTRACKER: - m->c4rate = C4_PAL_RATE; - m->quirk = QUIRK_PROTRACK; - m->read_event_type = READ_EVENT_MOD; - m->period_type = PERIOD_MODRNG; - break; - case XMP_MODE_S3M: - q = m->quirk & (QUIRK_VSALL | QUIRK_ARPMEM); - m->c4rate = C4_NTSC_RATE; - m->quirk = QUIRKS_ST3 | q; - m->read_event_type = READ_EVENT_ST3; - break; - case XMP_MODE_ST3: - q = m->quirk & (QUIRK_VSALL | QUIRK_ARPMEM); - m->c4rate = C4_NTSC_RATE; - m->quirk = QUIRKS_ST3 | QUIRK_ST3BUGS | q; - m->read_event_type = READ_EVENT_ST3; - break; - case XMP_MODE_ST3GUS: - q = m->quirk & (QUIRK_VSALL | QUIRK_ARPMEM); - m->c4rate = C4_NTSC_RATE; - m->quirk = QUIRKS_ST3 | QUIRK_ST3BUGS | q; - m->quirk &= ~QUIRK_RSTCHN; - m->read_event_type = READ_EVENT_ST3; - break; - case XMP_MODE_XM: - m->c4rate = C4_NTSC_RATE; - m->quirk = QUIRKS_FT2; - m->read_event_type = READ_EVENT_FT2; - break; - case XMP_MODE_FT2: - m->c4rate = C4_NTSC_RATE; - m->quirk = QUIRKS_FT2 | QUIRK_FT2BUGS; - m->read_event_type = READ_EVENT_FT2; - break; - case XMP_MODE_IT: - m->c4rate = C4_NTSC_RATE; - m->quirk = QUIRKS_IT | QUIRK_VIBHALF | QUIRK_VIBINV; - m->read_event_type = READ_EVENT_IT; - break; - case XMP_MODE_ITSMP: - m->c4rate = C4_NTSC_RATE; - m->quirk = QUIRKS_IT | QUIRK_VIBHALF | QUIRK_VIBINV; - m->quirk &= ~(QUIRK_VIRTUAL | QUIRK_RSTCHN); - m->read_event_type = READ_EVENT_IT; - break; - default: - return -1; - } - - return 0; -} - diff --git a/source/libxmp-lite/src/loader.h b/source/libxmp-lite/src/loader.h deleted file mode 100644 index 23acfd0ce..000000000 --- a/source/libxmp-lite/src/loader.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef XMP_LOADER_H -#define XMP_LOADER_H - -#include -#include -#include -#include "common.h" -#include "effects.h" -#include "format.h" -#include "hio.h" - -/* Sample flags */ -#define SAMPLE_FLAG_DIFF 0x0001 /* Differential */ -#define SAMPLE_FLAG_UNS 0x0002 /* Unsigned */ -#define SAMPLE_FLAG_8BDIFF 0x0004 -#define SAMPLE_FLAG_7BIT 0x0008 -#define SAMPLE_FLAG_NOLOAD 0x0010 /* Get from buffer, don't load */ -#define SAMPLE_FLAG_BIGEND 0x0040 /* Big-endian */ -#define SAMPLE_FLAG_VIDC 0x0080 /* Archimedes VIDC logarithmic */ -/*#define SAMPLE_FLAG_STEREO 0x0100 Interleaved stereo sample */ -#define SAMPLE_FLAG_FULLREP 0x0200 /* Play full sample before looping */ -#define SAMPLE_FLAG_ADLIB 0x1000 /* Adlib synth instrument */ -#define SAMPLE_FLAG_HSC 0x2000 /* HSC Adlib synth instrument */ -#define SAMPLE_FLAG_ADPCM 0x4000 /* ADPCM4 encoded samples */ - -#define DEFPAN(x) (0x80 + ((x) - 0x80) * m->defpan / 100) - -int libxmp_init_instrument (struct module_data *); -int libxmp_alloc_subinstrument (struct xmp_module *, int, int); -int libxmp_init_pattern (struct xmp_module *); -int libxmp_alloc_pattern (struct xmp_module *, int); -int libxmp_alloc_track (struct xmp_module *, int, int); -int libxmp_alloc_tracks_in_pattern (struct xmp_module *, int); -int libxmp_alloc_pattern_tracks (struct xmp_module *, int, int); -char *libxmp_instrument_name (struct xmp_module *, int, uint8 *, int); -struct xmp_sample* libxmp_realloc_samples(struct xmp_sample *, int *, int); - -char *libxmp_copy_adjust (char *, uint8 *, int); -int libxmp_test_name (uint8 *, int); -void libxmp_read_title (HIO_HANDLE *, char *, int); -void libxmp_set_xxh_defaults (struct xmp_module *); -void libxmp_decode_protracker_event (struct xmp_event *, uint8 *); -void libxmp_decode_noisetracker_event(struct xmp_event *, uint8 *); -void libxmp_disable_continue_fx (struct xmp_event *); -int libxmp_check_filename_case (char *, char *, char *, int); -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 *); - -extern uint8 libxmp_ord_xlat[]; -extern const int libxmp_arch_vol_table[]; - -#define MAGIC4(a,b,c,d) \ - (((uint32)(a)<<24)|((uint32)(b)<<16)|((uint32)(c)<<8)|(d)) - -#define LOAD_INIT() - -#define MODULE_INFO() do { \ - D_(D_WARN "Module title: \"%s\"", m->mod.name); \ - D_(D_WARN "Module type: %s", m->mod.type); \ -} while (0) - -#endif diff --git a/source/libxmp-lite/src/mdataio.h b/source/libxmp-lite/src/mdataio.h deleted file mode 100644 index 4fa8dc8e5..000000000 --- a/source/libxmp-lite/src/mdataio.h +++ /dev/null @@ -1,105 +0,0 @@ -#ifndef LIBXMP_MDATAIO_H -#define LIBXMP_MDATAIO_H - -#include -#include "common.h" - -static inline ptrdiff_t CAN_READ(MFILE *m) -{ - if (m->size >= 0) - return m->pos >= 0 ? m->size - m->pos : 0; - - return INT_MAX; -} - -static inline uint8 mread8(MFILE *m) -{ - uint8 x = 0xff; - mread(&x, 1, 1, m); - return x; -} - -static inline int8 mread8s(MFILE *m) -{ - return (int8)mgetc(m); -} - -static inline uint16 mread16l(MFILE *m) -{ - ptrdiff_t can_read = CAN_READ(m); - if (can_read >= 2) { - uint16 n = readmem16l(m->start + m->pos); - m->pos += 2; - return n; - } else { - m->pos += can_read; - return EOF; - } -} - -static inline uint16 mread16b(MFILE *m) -{ - ptrdiff_t can_read = CAN_READ(m); - if (can_read >= 2) { - uint16 n = readmem16b(m->start + m->pos); - m->pos += 2; - return n; - } else { - m->pos += can_read; - return EOF; - } -} - -static inline uint32 mread24l(MFILE *m) -{ - ptrdiff_t can_read = CAN_READ(m); - if (can_read >= 3) { - uint32 n = readmem24l(m->start + m->pos); - m->pos += 3; - return n; - } else { - m->pos += can_read; - return EOF; - } -} - -static inline uint32 mread24b(MFILE *m) -{ - ptrdiff_t can_read = CAN_READ(m); - if (can_read >= 3) { - uint32 n = readmem24b(m->start + m->pos); - m->pos += 3; - return n; - } else { - m->pos += can_read; - return EOF; - } -} - -static inline uint32 mread32l(MFILE *m) -{ - ptrdiff_t can_read = CAN_READ(m); - if (can_read >= 4) { - uint32 n = readmem32l(m->start + m->pos); - m->pos += 4; - return n; - } else { - m->pos += can_read; - return EOF; - } -} - -static inline uint32 mread32b(MFILE *m) -{ - ptrdiff_t can_read = CAN_READ(m); - if (can_read >= 4) { - uint32 n = readmem32b(m->start + m->pos); - m->pos += 4; - return n; - } else { - m->pos += can_read; - return EOF; - } -} - -#endif diff --git a/source/libxmp-lite/src/memio.c b/source/libxmp-lite/src/memio.c deleted file mode 100644 index 5112d12c8..000000000 --- a/source/libxmp-lite/src/memio.c +++ /dev/null @@ -1,136 +0,0 @@ -/* Extended Module Player - * 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"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include -#include -#include -#ifndef LIBXMP_CORE_PLAYER -#include -#include -#endif -#include "common.h" -#include "memio.h" - -static inline ptrdiff_t CAN_READ(MFILE *m) -{ - if (m->size >= 0) - return m->pos >= 0 ? m->size - m->pos : 0; - - return INT_MAX; -} - - -int mgetc(MFILE *m) -{ - if (CAN_READ(m) >= 1) - return *(const uint8 *)(m->start + m->pos++); - else - return EOF; -} - -size_t mread(void *buf, size_t size, size_t num, MFILE *m) -{ - size_t should_read = size * num; - ptrdiff_t can_read = CAN_READ(m); - - if (!size || !num || can_read <= 0) { - return 0; - } - - if (should_read > can_read) { - should_read = can_read; - } - - memcpy(buf, m->start + m->pos, should_read); - m->pos += should_read; - - return should_read / size; -} - - -int mseek(MFILE *m, long offset, int whence) -{ - switch (whence) { - default: - case SEEK_SET: - if (m->size >= 0 && (offset > m->size || offset < 0)) - return -1; - m->pos = offset; - return 0; - case SEEK_CUR: - if (m->size >= 0 && (offset > CAN_READ(m) || offset < -m->pos)) - return -1; - m->pos += offset; - return 0; - case SEEK_END: - if (m->size < 0) - return -1; - m->pos = m->size + offset; - return 0; - } -} - -long mtell(MFILE *m) -{ - return (long)m->pos; -} - -int meof(MFILE *m) -{ - if (m->size <= 0) - return 0; - else - return CAN_READ(m) <= 0; -} - -MFILE *mopen(const void *ptr, long size) -{ - MFILE *m; - - m = (MFILE *)malloc(sizeof (MFILE)); - if (m == NULL) - return NULL; - - m->start = (const unsigned char *)ptr; - m->pos = 0; - m->size = size; - - return m; -} - -int mclose(MFILE *m) -{ - free(m); - return 0; -} - -#ifndef LIBXMP_CORE_PLAYER - -int mstat(MFILE *m, struct stat *st) -{ - memset(st, 0, sizeof (struct stat)); - st->st_size = m->size; - return 0; -} - -#endif - diff --git a/source/libxmp-lite/src/memio.h b/source/libxmp-lite/src/memio.h deleted file mode 100644 index 8e8c04fa3..000000000 --- a/source/libxmp-lite/src/memio.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef LIBXMP_MEMIO_H -#define LIBXMP_MEMIO_H - -#include - -typedef struct { - const unsigned char *start; - ptrdiff_t pos; - ptrdiff_t size; -} MFILE; - -#ifdef __cplusplus -extern "C" { -#endif - -MFILE *mopen(const void *, long); -int mgetc(MFILE *stream); -size_t mread(void *, size_t, size_t, MFILE *); -int mseek(MFILE *, long, int); -long mtell(MFILE *); -int mclose(MFILE *); -int meof(MFILE *); -#ifndef LIBXMP_CORE_PLAYER -int mstat(MFILE *, struct stat *); -#endif - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/source/libxmp-lite/src/mix_all.c b/source/libxmp-lite/src/mix_all.c deleted file mode 100644 index 11ae8f691..000000000 --- a/source/libxmp-lite/src/mix_all.c +++ /dev/null @@ -1,439 +0,0 @@ -/* Extended Module Player - * 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"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include "common.h" -#include "virtual.h" -#include "mixer.h" -#include "precomp_lut.h" - -/* Mixers - * - * To increase performance eight mixers are defined, one for each - * combination of the following parameters: interpolation, resolution - * and number of channels. - */ -#define NEAREST_NEIGHBOR() do { \ - smp_in = ((int16)sptr[pos] << 8); \ -} while (0) - -#define NEAREST_NEIGHBOR_16BIT() do { \ - smp_in = sptr[pos]; \ -} while (0) - -#define LINEAR_INTERP() do { \ - smp_l1 = ((int16)sptr[pos] << 8); \ - smp_dt = ((int16)sptr[pos + 1] << 8) - smp_l1; \ - smp_in = smp_l1 + (((frac >> 1) * smp_dt) >> (SMIX_SHIFT - 1)); \ -} while (0) - -#define LINEAR_INTERP_16BIT() do { \ - smp_l1 = sptr[pos]; \ - smp_dt = sptr[pos + 1] - smp_l1; \ - smp_in = smp_l1 + (((frac >> 1) * smp_dt) >> (SMIX_SHIFT - 1)); \ -} while (0) - -/* The following lut settings are PRECOMPUTED. If you plan on changing these - * settings, you MUST also regenerate the arrays. - */ -/* number of bits used to scale spline coefs */ -#define SPLINE_QUANTBITS 14 -#define SPLINE_SHIFT (SPLINE_QUANTBITS) - -/* log2(number) of precalculated splines (range is [4..14]) */ -#define SPLINE_FRACBITS 10 -#define SPLINE_LUTLEN (1L<> 6; \ - smp_in = (cubic_spline_lut0[f] * sptr[(int)pos - 1] + \ - cubic_spline_lut1[f] * sptr[pos ] + \ - cubic_spline_lut3[f] * sptr[pos + 2] + \ - cubic_spline_lut2[f] * sptr[pos + 1]) >> (SPLINE_SHIFT - 8); \ -} while (0) - -#define SPLINE_INTERP_16BIT() do { \ - int f = frac >> 6; \ - smp_in = (cubic_spline_lut0[f] * sptr[(int)pos - 1] + \ - cubic_spline_lut1[f] * sptr[pos ] + \ - cubic_spline_lut3[f] * sptr[pos + 2] + \ - cubic_spline_lut2[f] * sptr[pos + 1]) >> SPLINE_SHIFT; \ -} while (0) - -#define LOOP_AC for (; count > ramp; count--) - -#define LOOP for (; count; count--) - -#define UPDATE_POS() do { \ - frac += step; \ - pos += frac >> SMIX_SHIFT; \ - frac &= SMIX_MASK; \ -} while (0) - -#define MIX_MONO() do { \ - *(buffer++) += smp_in * vl; \ -} while (0) - -#define MIX_MONO_AC() do { \ - *(buffer++) += smp_in * (old_vl >> 8); old_vl += delta_l; \ -} while (0) - -#define MIX_MONO_FILTER() do { \ - sl = (a0 * smp_in * vl + b0 * fl1 + b1 * fl2) >> FILTER_SHIFT; \ - fl2 = fl1; fl1 = sl; \ - *(buffer++) += sl; \ -} while (0) - -#define MIX_MONO_FILTER_AC() do { \ - int vl = old_vl >> 8; \ - MIX_MONO_FILTER(); \ - old_vl += delta_l; \ -} while (0) - -#define MIX_STEREO() do { \ - *(buffer++) += smp_in * vr; \ - *(buffer++) += smp_in * vl; \ -} while (0) - -#define MIX_STEREO_AC() do { \ - *(buffer++) += smp_in * (old_vr >> 8); old_vr += delta_r; \ - *(buffer++) += smp_in * (old_vl >> 8); old_vl += delta_l; \ -} while (0) - -#define MIX_STEREO_FILTER() do { \ - sr = (a0 * smp_in * vr + b0 * fr1 + b1 * fr2) >> FILTER_SHIFT; \ - fr2 = fr1; fr1 = sr; \ - sl = (a0 * smp_in * vl + b0 * fl1 + b1 * fl2) >> FILTER_SHIFT; \ - fl2 = fl1; fl1 = sl; \ - *(buffer++) += sr; \ - *(buffer++) += sl; \ -} while (0) - -#define MIX_STEREO_FILTER_AC() do { \ - int vr = old_vr >> 8; \ - int vl = old_vl >> 8; \ - MIX_STEREO_FILTER(); \ - old_vr += delta_r; \ - old_vl += delta_l; \ -} while (0) - -#define MIX_STEREO_FILTER_AC() do { \ - int vr = old_vr >> 8; \ - int vl = old_vl >> 8; \ - MIX_STEREO_FILTER(); \ - old_vr += delta_r; \ - old_vl += delta_l; \ -} while (0) - -#define VAR_NORM(x) \ - int smp_in; \ - x *sptr = (x *)vi->sptr; \ - unsigned int pos = (unsigned int)vi->pos; \ - int frac = (int)((1 << SMIX_SHIFT) * (vi->pos - (int)vi->pos)) - -#define VAR_LINEAR_MONO(x) \ - VAR_NORM(x); \ - int old_vl = vi->old_vl; \ - int smp_l1, smp_dt - -#define VAR_LINEAR_STEREO(x) \ - VAR_LINEAR_MONO(x); \ - int old_vr = vi->old_vr - -#define VAR_SPLINE_MONO(x) \ - int old_vl = vi->old_vl; \ - VAR_NORM(x) - -#define VAR_SPLINE_STEREO(x) \ - VAR_SPLINE_MONO(x); \ - int old_vr = vi->old_vr - -#ifndef LIBXMP_CORE_DISABLE_IT - -#define VAR_FILTER_MONO \ - int fl1 = vi->filter.l1, fl2 = vi->filter.l2; \ - int64 a0 = vi->filter.a0, b0 = vi->filter.b0, b1 = vi->filter.b1; \ - int sl - -#define VAR_FILTER_STEREO \ - VAR_FILTER_MONO; \ - int fr1 = vi->filter.r1, fr2 = vi->filter.r2; \ - int sr - -#define SAVE_FILTER_MONO() do { \ - vi->filter.l1 = fl1; \ - vi->filter.l2 = fl2; \ -} while (0) - -#define SAVE_FILTER_STEREO() do { \ - SAVE_FILTER_MONO(); \ - vi->filter.r1 = fr1; \ - vi->filter.r2 = fr2; \ -} while (0) - -#endif - - -/* - * Nearest neighbor mixers - */ - -/* Handler for 8 bit samples, nearest neighbor mono output - */ -MIXER(mono_8bit_nearest) -{ - VAR_NORM(int8); - - LOOP { NEAREST_NEIGHBOR(); MIX_MONO(); UPDATE_POS(); } -} - - -/* Handler for 16 bit samples, nearest neighbor mono output - */ -MIXER(mono_16bit_nearest) -{ - VAR_NORM(int16); - - LOOP { NEAREST_NEIGHBOR_16BIT(); MIX_MONO(); UPDATE_POS(); } -} - -/* Handler for 8 bit samples, nearest neighbor stereo output - */ -MIXER(stereo_8bit_nearest) -{ - VAR_NORM(int8); - - LOOP { NEAREST_NEIGHBOR(); MIX_STEREO(); UPDATE_POS(); } -} - -/* Handler for 16 bit samples, nearest neighbor stereo output - */ -MIXER(stereo_16bit_nearest) -{ - VAR_NORM(int16); - - LOOP { NEAREST_NEIGHBOR_16BIT(); MIX_STEREO(); UPDATE_POS(); } -} - - -/* - * Linear mixers - */ - -/* Handler for 8 bit samples, linear interpolated mono output - */ -MIXER(mono_8bit_linear) -{ - VAR_LINEAR_MONO(int8); - - LOOP_AC { LINEAR_INTERP(); MIX_MONO_AC(); UPDATE_POS(); } - LOOP { LINEAR_INTERP(); MIX_MONO(); UPDATE_POS(); } -} - -/* Handler for 16 bit samples, linear interpolated mono output - */ -MIXER(mono_16bit_linear) -{ - VAR_LINEAR_MONO(int16); - - LOOP_AC { LINEAR_INTERP_16BIT(); MIX_MONO_AC(); UPDATE_POS(); } - LOOP { LINEAR_INTERP_16BIT(); MIX_MONO(); UPDATE_POS(); } -} - -/* Handler for 8 bit samples, linear interpolated stereo output - */ -MIXER(stereo_8bit_linear) -{ - VAR_LINEAR_STEREO(int8); - - LOOP_AC { LINEAR_INTERP(); MIX_STEREO_AC(); UPDATE_POS(); } - LOOP { LINEAR_INTERP(); MIX_STEREO(); UPDATE_POS(); } -} - -/* Handler for 16 bit samples, linear interpolated stereo output - */ -MIXER(stereo_16bit_linear) -{ - VAR_LINEAR_STEREO(int16); - - LOOP_AC { LINEAR_INTERP_16BIT(); MIX_STEREO_AC(); UPDATE_POS(); } - LOOP { LINEAR_INTERP_16BIT(); MIX_STEREO(); UPDATE_POS(); } -} - - -#ifndef LIBXMP_CORE_DISABLE_IT - -/* Handler for 8 bit samples, filtered linear interpolated mono output - */ -MIXER(mono_8bit_linear_filter) -{ - VAR_LINEAR_MONO(int8); - VAR_FILTER_MONO; - - LOOP_AC { LINEAR_INTERP(); MIX_MONO_FILTER_AC(); UPDATE_POS(); } - LOOP { LINEAR_INTERP(); MIX_MONO_FILTER(); UPDATE_POS(); } - - SAVE_FILTER_MONO(); -} - -/* Handler for 16 bit samples, filtered linear interpolated mono output - */ -MIXER(mono_16bit_linear_filter) -{ - VAR_LINEAR_MONO(int16); - VAR_FILTER_MONO; - - LOOP_AC { LINEAR_INTERP_16BIT(); MIX_MONO_FILTER_AC(); UPDATE_POS(); } - LOOP { LINEAR_INTERP_16BIT(); MIX_MONO_FILTER(); UPDATE_POS(); } - - SAVE_FILTER_MONO(); -} - -/* Handler for 8 bit samples, filtered linear interpolated stereo output - */ -MIXER(stereo_8bit_linear_filter) -{ - VAR_LINEAR_STEREO(int8); - VAR_FILTER_STEREO; - - LOOP_AC { LINEAR_INTERP(); MIX_STEREO_FILTER_AC(); UPDATE_POS(); } - LOOP { LINEAR_INTERP(); MIX_STEREO_FILTER(); UPDATE_POS(); } - - SAVE_FILTER_STEREO(); -} - -/* Handler for 16 bit samples, filtered linear interpolated stereo output - */ -MIXER(stereo_16bit_linear_filter) -{ - VAR_LINEAR_STEREO(int16); - VAR_FILTER_STEREO; - - LOOP_AC { LINEAR_INTERP_16BIT(); MIX_STEREO_FILTER_AC(); UPDATE_POS(); } - LOOP { LINEAR_INTERP_16BIT(); MIX_STEREO_FILTER(); UPDATE_POS(); } - - SAVE_FILTER_STEREO(); -} - -#endif - -/* - * Spline mixers - */ - -/* Handler for 8 bit samples, spline interpolated mono output - */ -MIXER(mono_8bit_spline) -{ - VAR_SPLINE_MONO(int8); - - LOOP_AC { SPLINE_INTERP(); MIX_MONO_AC(); UPDATE_POS(); } - LOOP { SPLINE_INTERP(); MIX_MONO(); UPDATE_POS(); } -} - -/* Handler for 16 bit samples, spline interpolated mono output - */ -MIXER(mono_16bit_spline) -{ - VAR_SPLINE_MONO(int16); - - LOOP_AC { SPLINE_INTERP_16BIT(); MIX_MONO_AC(); UPDATE_POS(); } - LOOP { SPLINE_INTERP_16BIT(); MIX_MONO(); UPDATE_POS(); } -} - -/* Handler for 8 bit samples, spline interpolated stereo output - */ -MIXER(stereo_8bit_spline) -{ - VAR_SPLINE_STEREO(int8); - - LOOP_AC { SPLINE_INTERP(); MIX_STEREO_AC(); UPDATE_POS(); } - LOOP { SPLINE_INTERP(); MIX_STEREO(); UPDATE_POS(); } -} - -/* Handler for 16 bit samples, spline interpolated stereo output - */ -MIXER(stereo_16bit_spline) -{ - VAR_SPLINE_STEREO(int16); - - LOOP_AC { SPLINE_INTERP_16BIT(); MIX_STEREO_AC(); UPDATE_POS(); } - LOOP { SPLINE_INTERP_16BIT(); MIX_STEREO(); UPDATE_POS(); } -} - -#ifndef LIBXMP_CORE_DISABLE_IT - -/* Handler for 8 bit samples, filtered spline interpolated mono output - */ -MIXER(mono_8bit_spline_filter) -{ - VAR_SPLINE_MONO(int8); - VAR_FILTER_MONO; - - LOOP_AC { SPLINE_INTERP(); MIX_MONO_FILTER_AC(); UPDATE_POS(); } - LOOP { SPLINE_INTERP(); MIX_MONO_FILTER(); UPDATE_POS(); } - - SAVE_FILTER_MONO(); -} - -/* Handler for 16 bit samples, filtered spline interpolated mono output - */ -MIXER(mono_16bit_spline_filter) -{ - VAR_SPLINE_MONO(int16); - VAR_FILTER_MONO; - - LOOP_AC { SPLINE_INTERP_16BIT(); MIX_MONO_FILTER_AC(); UPDATE_POS(); } - LOOP { SPLINE_INTERP_16BIT(); MIX_MONO_FILTER(); UPDATE_POS(); } - - SAVE_FILTER_MONO(); -} - -/* Handler for 8 bit samples, filtered spline interpolated stereo output - */ -MIXER(stereo_8bit_spline_filter) -{ - VAR_SPLINE_STEREO(int8); - VAR_FILTER_STEREO; - - LOOP_AC { SPLINE_INTERP(); MIX_STEREO_FILTER_AC(); UPDATE_POS(); } - LOOP { SPLINE_INTERP(); MIX_STEREO_FILTER(); UPDATE_POS(); } - - SAVE_FILTER_STEREO(); -} - -/* Handler for 16 bit samples, filtered spline interpolated stereo output - */ -MIXER(stereo_16bit_spline_filter) -{ - VAR_SPLINE_STEREO(int16); - VAR_FILTER_STEREO; - - LOOP_AC { SPLINE_INTERP_16BIT(); MIX_STEREO_FILTER_AC(); UPDATE_POS(); } - LOOP { SPLINE_INTERP_16BIT(); MIX_STEREO_FILTER(); UPDATE_POS(); } - - SAVE_FILTER_STEREO(); -} - -#endif diff --git a/source/libxmp-lite/src/mixer.c b/source/libxmp-lite/src/mixer.c deleted file mode 100644 index 22020f47b..000000000 --- a/source/libxmp-lite/src/mixer.c +++ /dev/null @@ -1,840 +0,0 @@ -/* Extended Module Player - * 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"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include -#include -#include -#include "common.h" -#include "virtual.h" -#include "mixer.h" -#include "period.h" -#include "player.h" /* for set_sample_end() */ - -#ifdef LIBXMP_PAULA_SIMULATOR -#include "paula.h" -#endif - - -#define FLAG_16_BITS 0x01 -#define FLAG_STEREO 0x02 -#define FLAG_FILTER 0x04 -#define FLAG_ACTIVE 0x10 -/* #define FLAG_SYNTH 0x20 */ -#define FIDX_FLAGMASK (FLAG_16_BITS | FLAG_STEREO | FLAG_FILTER) - -#define DOWNMIX_SHIFT 12 -#define LIM8_HI 127 -#define LIM8_LO -128 -#define LIM16_HI 32767 -#define LIM16_LO -32768 - -#define MIX_FN(x) void libxmp_mix_##x(struct mixer_voice *, int32 *, int, int, int, int, int, int, int) - -MIX_FN(mono_8bit_nearest); -MIX_FN(mono_8bit_linear); -MIX_FN(mono_16bit_nearest); -MIX_FN(mono_16bit_linear); -MIX_FN(stereo_8bit_nearest); -MIX_FN(stereo_8bit_linear); -MIX_FN(stereo_16bit_nearest); -MIX_FN(stereo_16bit_linear); -MIX_FN(mono_8bit_spline); -MIX_FN(mono_16bit_spline); -MIX_FN(stereo_8bit_spline); -MIX_FN(stereo_16bit_spline); - -#ifndef LIBXMP_CORE_DISABLE_IT -MIX_FN(mono_8bit_linear_filter); -MIX_FN(mono_16bit_linear_filter); -MIX_FN(stereo_8bit_linear_filter); -MIX_FN(stereo_16bit_linear_filter); -MIX_FN(mono_8bit_spline_filter); -MIX_FN(mono_16bit_spline_filter); -MIX_FN(stereo_8bit_spline_filter); -MIX_FN(stereo_16bit_spline_filter); -#endif - -#ifdef LIBXMP_PAULA_SIMULATOR -MIX_FN(mono_a500); -MIX_FN(mono_a500_filter); -MIX_FN(stereo_a500); -MIX_FN(stereo_a500_filter); -#endif - -/* Mixers array index: - * - * bit 0: 0=8 bit sample, 1=16 bit sample - * bit 1: 0=mono output, 1=stereo output - * bit 2: 0=unfiltered, 1=filtered - */ - -typedef void (*mixer_set[])(struct mixer_voice *, int32 *, int, int, int, int, int, int, int); - -static mixer_set nearest_mixers = { - libxmp_mix_mono_8bit_nearest, - libxmp_mix_mono_16bit_nearest, - libxmp_mix_stereo_8bit_nearest, - libxmp_mix_stereo_16bit_nearest, - -#ifndef LIBXMP_CORE_DISABLE_IT - libxmp_mix_mono_8bit_nearest, - libxmp_mix_mono_16bit_nearest, - libxmp_mix_stereo_8bit_nearest, - libxmp_mix_stereo_16bit_nearest, -#endif -}; - -static mixer_set linear_mixers = { - libxmp_mix_mono_8bit_linear, - libxmp_mix_mono_16bit_linear, - libxmp_mix_stereo_8bit_linear, - libxmp_mix_stereo_16bit_linear, - -#ifndef LIBXMP_CORE_DISABLE_IT - libxmp_mix_mono_8bit_linear_filter, - libxmp_mix_mono_16bit_linear_filter, - libxmp_mix_stereo_8bit_linear_filter, - libxmp_mix_stereo_16bit_linear_filter -#endif -}; - -static mixer_set spline_mixers = { - libxmp_mix_mono_8bit_spline, - libxmp_mix_mono_16bit_spline, - libxmp_mix_stereo_8bit_spline, - libxmp_mix_stereo_16bit_spline, - -#ifndef LIBXMP_CORE_DISABLE_IT - libxmp_mix_mono_8bit_spline_filter, - libxmp_mix_mono_16bit_spline_filter, - libxmp_mix_stereo_8bit_spline_filter, - libxmp_mix_stereo_16bit_spline_filter -#endif -}; - -#ifdef LIBXMP_PAULA_SIMULATOR -static mixer_set a500_mixers = { - libxmp_mix_mono_a500, - NULL, - libxmp_mix_stereo_a500, - NULL, - NULL, - NULL, - NULL, - NULL -}; - - -static mixer_set a500led_mixers = { - libxmp_mix_mono_a500_filter, - NULL, - libxmp_mix_stereo_a500_filter, - NULL, - NULL, - NULL, - NULL, - NULL -}; -#endif - - -/* Downmix 32bit samples to 8bit, signed or unsigned, mono or stereo output */ -static void downmix_int_8bit(int8 *dest, int32 *src, int num, int amp, int offs) -{ - int smp; - int shift = DOWNMIX_SHIFT + 8 - amp; - - for (; num--; src++, dest++) { - smp = *src >> shift; - if (smp > LIM8_HI) { - *dest = LIM8_HI; - } else if (smp < LIM8_LO) { - *dest = LIM8_LO; - } else { - *dest = smp; - } - - if (offs) *dest += offs; - } -} - - -/* Downmix 32bit samples to 16bit, signed or unsigned, mono or stereo output */ -static void downmix_int_16bit(int16 *dest, int32 *src, int num, int amp, int offs) -{ - int smp; - int shift = DOWNMIX_SHIFT - amp; - - for (; num--; src++, dest++) { - smp = *src >> shift; - if (smp > LIM16_HI) { - *dest = LIM16_HI; - } else if (smp < LIM16_LO) { - *dest = LIM16_LO; - } else { - *dest = smp; - } - - if (offs) *dest += offs; - } -} - -static void anticlick(struct mixer_voice *vi) -{ - vi->flags |= ANTICLICK; - vi->old_vl = 0; - vi->old_vr = 0; -} - -/* Ok, it's messy, but it works :-) Hipolito */ -static void do_anticlick(struct context_data *ctx, int voc, int32 *buf, int count) -{ - struct player_data *p = &ctx->p; - struct mixer_data *s = &ctx->s; - struct mixer_voice *vi = &p->virt.voice_array[voc]; - int smp_l, smp_r, max_x2; - int discharge = s->ticksize >> ANTICLICK_SHIFT; - - smp_r = vi->sright; - smp_l = vi->sleft; - vi->sright = vi->sleft = 0; - - if (smp_l == 0 && smp_r == 0) { - return; - } - - if (buf == NULL) { - buf = s->buf32; - count = discharge; - } else if (count > discharge) { - count = discharge; - } - - if (count <= 0) { - return; - } - - max_x2 = count * count; - - while (count--) { - if (~s->format & XMP_FORMAT_MONO) { - *buf++ += (count * (smp_r >> 10) / max_x2 * count) << 10; - } - - *buf++ += (count * (smp_l >> 10) / max_x2 * count) << 10; - } -} - -static void set_sample_end(struct context_data *ctx, int voc, int end) -{ - struct player_data *p = &ctx->p; - struct module_data *m = &ctx->m; - struct mixer_voice *vi = &p->virt.voice_array[voc]; - struct channel_data *xc; - - if ((uint32)voc >= p->virt.maxvoc) - return; - - xc = &p->xc_data[vi->chn]; - - if (end) { - SET_NOTE(NOTE_SAMPLE_END); - if (HAS_QUIRK(QUIRK_RSTCHN)) { - libxmp_virt_resetvoice(ctx, voc, 0); - } - } else { - RESET_NOTE(NOTE_SAMPLE_END); - } -} - -static void adjust_voice_end(struct mixer_voice *vi, struct xmp_sample *xxs) -{ - if (xxs->flg & XMP_SAMPLE_LOOP) { - if ((xxs->flg & XMP_SAMPLE_LOOP_FULL) && (~vi->flags & SAMPLE_LOOP)) { - vi->end = xxs->len; - } else { - vi->end = xxs->lpe; - } - } else { - vi->end = xxs->len; - } -} - -static void loop_reposition(struct context_data *ctx, struct mixer_voice *vi, struct xmp_sample *xxs) -{ -#ifndef LIBXMP_CORE_DISABLE_IT - struct module_data *m = &ctx->m; -#endif - int loop_size = xxs->lpe - xxs->lps; - - /* Reposition for next loop */ - vi->pos -= loop_size; /* forward loop */ - vi->end = xxs->lpe; - vi->flags |= SAMPLE_LOOP; - - if (xxs->flg & XMP_SAMPLE_LOOP_BIDIR) { - vi->end += loop_size; /* unrolled loop */ - vi->pos -= loop_size; /* forward loop */ - -#ifndef LIBXMP_CORE_DISABLE_IT - /* OpenMPT Bidi-Loops.it: "In Impulse Tracker’s software mixer, - * ping-pong loops are shortened by one sample. - */ - if (IS_PLAYER_MODE_IT()) { - vi->end--; - vi->pos++; - } -#endif - } -} - - -/* Prepare the mixer for the next tick */ -void libxmp_mixer_prepare(struct context_data *ctx) -{ - struct player_data *p = &ctx->p; - struct module_data *m = &ctx->m; - struct mixer_data *s = &ctx->s; - int bytelen; - - s->ticksize = (int)(s->freq * m->time_factor * m->rrate / p->bpm / 1000); - - bytelen = s->ticksize * sizeof(int); - if (~s->format & XMP_FORMAT_MONO) { - bytelen *= 2; - } - memset(s->buf32, 0, bytelen); -} -/* Fill the output buffer calling one of the handlers. The buffer contains - * sound for one tick (a PAL frame or 1/50s for standard vblank-timed mods) - */ -void libxmp_mixer_softmixer(struct context_data *ctx) -{ - struct player_data *p = &ctx->p; - struct mixer_data *s = &ctx->s; - struct module_data *m = &ctx->m; - struct xmp_module *mod = &m->mod; - struct xmp_sample *xxs; - struct mixer_voice *vi; - double step; - int samples, size; - int vol_l, vol_r, voc, usmp; - int prev_l, prev_r = 0; - int lps, lpe; - int32 *buf_pos; - void (*mix_fn)(struct mixer_voice *, int32 *, int, int, int, int, int, int, int); - mixer_set *mixers; - - switch (s->interp) { - case XMP_INTERP_NEAREST: - mixers = (mixer_set *)&nearest_mixers; - break; - case XMP_INTERP_LINEAR: - mixers = (mixer_set *)&linear_mixers; - break; - case XMP_INTERP_SPLINE: - mixers = (mixer_set *)&spline_mixers; - break; - default: - mixers = (mixer_set *)&linear_mixers; - } - -#ifdef LIBXMP_PAULA_SIMULATOR - if (p->flags & XMP_FLAGS_A500) { - if (IS_AMIGA_MOD()) { - if (p->filter) { - mixers = (mixer_set *)&a500led_mixers; - } else { - mixers = (mixer_set *)&a500_mixers; - } - } - } -#endif - - libxmp_mixer_prepare(ctx); - - for (voc = 0; voc < p->virt.maxvoc; voc++) { - int c5spd, rampsize, delta_l, delta_r; - - vi = &p->virt.voice_array[voc]; - - if (vi->flags & ANTICLICK) { - if (s->interp > XMP_INTERP_NEAREST) { - do_anticlick(ctx, voc, NULL, 0); - } - vi->flags &= ~ANTICLICK; - } - - if (vi->chn < 0) { - continue; - } - - if (vi->period < 1) { - libxmp_virt_resetvoice(ctx, voc, 1); - continue; - } - - vi->pos0 = (int)vi->pos; - - buf_pos = s->buf32; - if (vi->pan == PAN_SURROUND) { - vol_r = vi->vol * 0x80; - vol_l = -vi->vol * 0x80; - } else { - vol_r = vi->vol * (0x80 - vi->pan); - vol_l = vi->vol * (0x80 + vi->pan); - } - - if (vi->smp < mod->smp) { - xxs = &mod->xxs[vi->smp]; - c5spd = (int) m->xtra[vi->smp].c5spd; - } else { - xxs = &ctx->smix.xxs[vi->smp - mod->smp]; - c5spd = m->c4rate; - } - - step = C4_PERIOD * c5spd / s->freq / vi->period; - - if (step < 0.001) { /* otherwise m5v-nwlf.it crashes */ - continue; - } - -#ifndef LIBXMP_CORE_DISABLE_IT - if (xxs->flg & XMP_SAMPLE_SLOOP && vi->smp < mod->smp) { - if (~vi->flags & VOICE_RELEASE) { - if (vi->pos < m->xsmp[vi->smp].lpe) { - xxs = &m->xsmp[vi->smp]; - } - } - } - - adjust_voice_end(vi, xxs); -#endif - - lps = xxs->lps; - lpe = xxs->lpe; - - if (p->flags & XMP_FLAGS_FIXLOOP) { - lps >>= 1; - } - - if (xxs->flg & XMP_SAMPLE_LOOP_BIDIR) { - vi->end += lpe - lps; - -#ifndef LIBXMP_CORE_DISABLE_IT - if (IS_PLAYER_MODE_IT()) { - vi->end--; - } -#endif - } - - rampsize = s->ticksize >> ANTICLICK_SHIFT; - delta_l = (vol_l - vi->old_vl) / rampsize; - delta_r = (vol_r - vi->old_vr) / rampsize; - - usmp = 0; - for (size = s->ticksize; size > 0; ) { - int split_noloop = 0; - - if (p->xc_data[vi->chn].split) { - split_noloop = 1; - } - - /* How many samples we can write before the loop break - * or sample end... */ - if (vi->pos >= vi->end) { - samples = 0; - usmp = 1; - } else { - int s = (int) ceil(((double)vi->end - vi->pos) / step); - /* ...inside the tick boundaries */ - if (s > size) { - s = size; - } - - samples = s; - if (samples > 0) { - usmp = 0; - } - } - - if (vi->vol) { - int mix_size = samples; - int mixer = vi->fidx & FIDX_FLAGMASK; - - if (~s->format & XMP_FORMAT_MONO) { - mix_size *= 2; - } - - /* For Hipolito's anticlick routine */ - if (samples > 0) { - if (~s->format & XMP_FORMAT_MONO) { - prev_r = buf_pos[mix_size - 2]; - } - prev_l = buf_pos[mix_size - 1]; - } else { - prev_r = prev_l = 0; - } - -#ifndef LIBXMP_CORE_DISABLE_IT - /* See OpenMPT env-flt-max.it */ - if (vi->filter.cutoff >= 0xfe && - vi->filter.resonance == 0) { - mixer &= ~FLAG_FILTER; - } -#endif - - mix_fn = (*mixers)[mixer]; - - /* Call the output handler */ - if (samples > 0 && vi->sptr != NULL) { - int rsize = 0; - - if (rampsize > samples) { - rampsize -= samples; - } else { - rsize = samples - rampsize; - rampsize = 0; - } - - if (delta_l == 0 && delta_r == 0) { - /* no need to ramp */ - rsize = samples; - } - - if (mix_fn != NULL) { - mix_fn(vi, buf_pos, samples, - vol_l >> 8, vol_r >> 8, (int) (step * (1 << SMIX_SHIFT)), rsize, delta_l, delta_r); - } - - buf_pos += mix_size; - vi->old_vl += samples * delta_l; - vi->old_vr += samples * delta_r; - - - /* For Hipolito's anticlick routine */ - if (~s->format & XMP_FORMAT_MONO) { - vi->sright = buf_pos[-2] - prev_r; - } - vi->sleft = buf_pos[-1] - prev_l; - } - } - - vi->pos += step * samples; - - /* No more samples in this tick */ - size -= samples + usmp; - if (size <= 0) { - if (xxs->flg & XMP_SAMPLE_LOOP) { - if (vi->pos + step > vi->end) { - vi->pos += step; - loop_reposition(ctx, vi, xxs); - } - } - continue; - } - - /* First sample loop run */ - if ((~xxs->flg & XMP_SAMPLE_LOOP) || split_noloop) { - do_anticlick(ctx, voc, buf_pos, size); - set_sample_end(ctx, voc, 1); - size = 0; - continue; - } - - loop_reposition(ctx, vi, xxs); - } - - vi->old_vl = vol_l; - vi->old_vr = vol_r; - } - - /* Render final frame */ - - size = s->ticksize; - if (~s->format & XMP_FORMAT_MONO) { - size *= 2; - } - - if (size > XMP_MAX_FRAMESIZE) { - size = XMP_MAX_FRAMESIZE; - } - - if (s->format & XMP_FORMAT_8BIT) { - downmix_int_8bit((int8 *)s->buffer, s->buf32, size, s->amplify, - s->format & XMP_FORMAT_UNSIGNED ? 0x80 : 0); - } else { - downmix_int_16bit((int16 *)s->buffer, s->buf32, size,s->amplify, - s->format & XMP_FORMAT_UNSIGNED ? 0x8000 : 0); - } - - s->dtright = s->dtleft = 0; -} - -void libxmp_mixer_voicepos(struct context_data *ctx, int voc, double pos, int ac) -{ - struct player_data *p = &ctx->p; - struct module_data *m = &ctx->m; - struct mixer_voice *vi = &p->virt.voice_array[voc]; - struct xmp_sample *xxs; - int lps; - - if (vi->smp < m->mod.smp) { - xxs = &m->mod.xxs[vi->smp]; - } else { - xxs = &ctx->smix.xxs[vi->smp - m->mod.smp]; - } - - if (xxs->flg & XMP_SAMPLE_SYNTH) { - return; - } - - vi->pos = pos; - - adjust_voice_end(vi, xxs); - - if (vi->pos >= vi->end) { - if (xxs->flg & XMP_SAMPLE_LOOP) { - vi->pos = xxs->lps; - } else { - vi->pos = xxs->len; - } - } - - lps = xxs->lps; - if (p->flags & XMP_FLAGS_FIXLOOP) { - lps >>= 1; - } - - if (xxs->flg & XMP_SAMPLE_LOOP_BIDIR) { - vi->end += (xxs->lpe - lps); - -#ifndef LIBXMP_CORE_DISABLE_IT - if (IS_PLAYER_MODE_IT()) { - vi->end--; - } -#endif - } - - if (ac) { - anticlick(vi); - } -} - -double libxmp_mixer_getvoicepos(struct context_data *ctx, int voc) -{ - struct player_data *p = &ctx->p; - struct mixer_voice *vi = &p->virt.voice_array[voc]; - struct xmp_sample *xxs; - - xxs = libxmp_get_sample(ctx, vi->smp); - - if (xxs->flg & XMP_SAMPLE_SYNTH) { - return 0; - } - - if (xxs->flg & XMP_SAMPLE_LOOP_BIDIR) { - if (vi->pos >= xxs->lpe) { - return xxs->lpe - (vi->pos - xxs->lpe) - 1; - } - } - - return vi->pos; -} - -void libxmp_mixer_setpatch(struct context_data *ctx, int voc, int smp, int ac) -{ - struct player_data *p = &ctx->p; -#ifndef LIBXMP_CORE_DISABLE_IT - struct module_data *m = &ctx->m; -#endif - struct mixer_data *s = &ctx->s; - struct mixer_voice *vi = &p->virt.voice_array[voc]; - struct xmp_sample *xxs; - - xxs = libxmp_get_sample(ctx, smp); - - vi->smp = smp; - vi->vol = 0; - vi->pan = 0; - vi->flags &= ~SAMPLE_LOOP; - - vi->fidx = 0; - - if (~s->format & XMP_FORMAT_MONO) { - vi->fidx |= FLAG_STEREO; - } - - set_sample_end(ctx, voc, 0); - - /*mixer_setvol(ctx, voc, 0);*/ - - vi->sptr = xxs->data; - vi->fidx |= FLAG_ACTIVE; - -#ifndef LIBXMP_CORE_DISABLE_IT - if (HAS_QUIRK(QUIRK_FILTER) && s->dsp & XMP_DSP_LOWPASS) { - vi->fidx |= FLAG_FILTER; - } -#endif - - if (xxs->flg & XMP_SAMPLE_16BIT) { - vi->fidx |= FLAG_16_BITS; - } - - libxmp_mixer_voicepos(ctx, voc, 0, ac); -} - -void libxmp_mixer_setnote(struct context_data *ctx, int voc, int note) -{ - struct player_data *p = &ctx->p; - struct mixer_voice *vi = &p->virt.voice_array[voc]; - - /* FIXME: Workaround for crash on notes that are too high - * see 6nations.it (+114 transposition on instrument 16) - */ - if (note > 149) { - note = 149; - } - - vi->note = note; - vi->period = libxmp_note_to_period_mix(note, 0); - - anticlick(vi); -} - -void libxmp_mixer_setperiod(struct context_data *ctx, int voc, double period) -{ - struct player_data *p = &ctx->p; - struct mixer_voice *vi = &p->virt.voice_array[voc]; - - vi->period = period; -} - -void libxmp_mixer_setvol(struct context_data *ctx, int voc, int vol) -{ - struct player_data *p = &ctx->p; - struct mixer_voice *vi = &p->virt.voice_array[voc]; - - if (vol == 0) { - anticlick(vi); - } - - vi->vol = vol; -} - -void libxmp_mixer_release(struct context_data *ctx, int voc, int rel) -{ - struct player_data *p = &ctx->p; - struct mixer_voice *vi = &p->virt.voice_array[voc]; - - if (rel) { - vi->flags |= VOICE_RELEASE; - } else { - vi->flags &= ~VOICE_RELEASE; - } -} - -void libxmp_mixer_seteffect(struct context_data *ctx, int voc, int type, int val) -{ -#ifndef LIBXMP_CORE_DISABLE_IT - struct player_data *p = &ctx->p; - struct mixer_voice *vi = &p->virt.voice_array[voc]; - - switch (type) { - case DSP_EFFECT_CUTOFF: - vi->filter.cutoff = val; - break; - case DSP_EFFECT_RESONANCE: - vi->filter.resonance = val; - break; - case DSP_EFFECT_FILTER_A0: - vi->filter.a0 = val; - break; - case DSP_EFFECT_FILTER_B0: - vi->filter.b0 = val; - break; - case DSP_EFFECT_FILTER_B1: - vi->filter.b1 = val; - break; - } -#endif -} - -void libxmp_mixer_setpan(struct context_data *ctx, int voc, int pan) -{ - struct player_data *p = &ctx->p; - struct mixer_voice *vi = &p->virt.voice_array[voc]; - - vi->pan = pan; -} - -int libxmp_mixer_numvoices(struct context_data *ctx, int num) -{ - struct mixer_data *s = &ctx->s; - - if (num > s->numvoc || num < 0) { - return s->numvoc; - } else { - return num; - } -} - -int libxmp_mixer_on(struct context_data *ctx, int rate, int format, int c4rate) -{ - struct mixer_data *s = &ctx->s; - - s->buffer = (char *)calloc(2, XMP_MAX_FRAMESIZE); - if (s->buffer == NULL) - goto err; - - s->buf32 = (int32 *)calloc(sizeof(int32), XMP_MAX_FRAMESIZE); - if (s->buf32 == NULL) - goto err1; - - s->freq = rate; - s->format = format; - s->amplify = DEFAULT_AMPLIFY; - s->mix = DEFAULT_MIX; - /* s->pbase = C4_PERIOD * c4rate / s->freq; */ - s->interp = XMP_INTERP_LINEAR; /* default interpolation type */ - s->dsp = XMP_DSP_LOWPASS; /* enable filters by default */ - /* s->numvoc = SMIX_NUMVOC; */ - s->dtright = s->dtleft = 0; - - return 0; - - err1: - free(s->buffer); - err: - return -1; -} - -void libxmp_mixer_off(struct context_data *ctx) -{ - struct mixer_data *s = &ctx->s; - - free(s->buffer); - free(s->buf32); - s->buf32 = NULL; - s->buffer = NULL; -} diff --git a/source/libxmp-lite/src/mixer.h b/source/libxmp-lite/src/mixer.h deleted file mode 100644 index 5ed3b9763..000000000 --- a/source/libxmp-lite/src/mixer.h +++ /dev/null @@ -1,78 +0,0 @@ -#ifndef LIBXMP_MIXER_H -#define LIBXMP_MIXER_H - -#define C4_PERIOD 428.0 - -#define SMIX_NUMVOC 128 /* default number of softmixer voices */ -#define SMIX_SHIFT 16 -#define SMIX_MASK 0xffff - -#define FILTER_SHIFT 16 -#define ANTICLICK_SHIFT 3 - -#ifdef LIBXMP_PAULA_SIMULATOR -#include "paula.h" -#endif - -#define MIXER(f) void libxmp_mix_##f(struct mixer_voice *vi, int *buffer, \ - int count, int vl, int vr, int step, int ramp, int delta_l, int delta_r) - -struct mixer_voice { - int chn; /* channel number */ - int root; /* */ - int note; /* */ -#define PAN_SURROUND 0x8000 - int pan; /* */ - int vol; /* */ - double period; /* current period */ - double pos; /* position in sample */ - int pos0; /* position in sample before mixing */ - int fidx; /* mixer function index */ - int ins; /* instrument number */ - int smp; /* sample number */ - int end; /* loop end */ - int act; /* nna info & status of voice */ - int old_vl; /* previous volume, left channel */ - int old_vr; /* previous volume, right channel */ - int sleft; /* last left sample output, in 32bit */ - int sright; /* last right sample output, in 32bit */ -#define VOICE_RELEASE (1 << 0) -#define ANTICLICK (1 << 1) -#define SAMPLE_LOOP (1 << 2) - int flags; /* flags */ - void *sptr; /* sample pointer */ -#ifdef LIBXMP_PAULA_SIMULATOR - struct paula_state *paula; /* paula simulation state */ -#endif - -#ifndef LIBXMP_CORE_DISABLE_IT - struct { - int r1; /* filter variables */ - int r2; - int l1; - int l2; - int a0; - int b0; - int b1; - int cutoff; - int resonance; - } filter; -#endif -}; - -int libxmp_mixer_on (struct context_data *, int, int, int); -void libxmp_mixer_off (struct context_data *); -void libxmp_mixer_setvol (struct context_data *, int, int); -void libxmp_mixer_seteffect (struct context_data *, int, int, int); -void libxmp_mixer_setpan (struct context_data *, int, int); -int libxmp_mixer_numvoices (struct context_data *, int); -void libxmp_mixer_softmixer (struct context_data *); -void libxmp_mixer_reset (struct context_data *); -void libxmp_mixer_setpatch (struct context_data *, int, int, int); -void libxmp_mixer_voicepos (struct context_data *, int, double, int); -double libxmp_mixer_getvoicepos(struct context_data *, int); -void libxmp_mixer_setnote (struct context_data *, int, int); -void libxmp_mixer_setperiod (struct context_data *, int, double); -void libxmp_mixer_release (struct context_data *, int, int); - -#endif /* LIBXMP_MIXER_H */ diff --git a/source/libxmp-lite/src/mod.h b/source/libxmp-lite/src/mod.h deleted file mode 100644 index 8208c58e2..000000000 --- a/source/libxmp-lite/src/mod.h +++ /dev/null @@ -1,55 +0,0 @@ -/* Extended Module Player - * 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"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -struct mod_instrument { - uint8 name[22]; /* Instrument name */ - uint16 size; /* Sample length in 16-bit words */ - int8 finetune; /* Finetune (signed nibble) */ - int8 volume; /* Linear playback volume */ - uint16 loop_start; /* Loop start in 16-bit words */ - uint16 loop_size; /* Loop length in 16-bit words */ -}; - -struct mod_header { - uint8 name[20]; - struct mod_instrument ins[31]; - uint8 len; - uint8 restart; /* Number of patterns in Soundtracker, - * Restart in Noisetracker/Startrekker, - * 0x7F in Protracker - */ - uint8 order[128]; - uint8 magic[4]; -}; - - -#ifndef LIBXMP_CORE_PLAYER -/* Soundtracker 15-instrument module header */ - -struct st_header { - uint8 name[20]; - struct mod_instrument ins[15]; - uint8 len; - uint8 restart; - uint8 order[128]; -}; -#endif diff --git a/source/libxmp-lite/src/mod_load.c b/source/libxmp-lite/src/mod_load.c deleted file mode 100644 index c9fcf9a5b..000000000 --- a/source/libxmp-lite/src/mod_load.c +++ /dev/null @@ -1,233 +0,0 @@ -/* Extended Module Player - * Copyright (C) 1996-2016 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"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -/* This loader recognizes the following variants of the Protracker - * module format: - * - * - Protracker M.K. - * - Fasttracker ?CHN and ??CH - */ - -#include -#include -#include "loader.h" -#include "mod.h" - -static int mod_test(HIO_HANDLE *, char *, const int); -static int mod_load(struct module_data *, HIO_HANDLE *, const int); - -extern const struct format_loader libxmp_loader_mod; -const struct format_loader libxmp_loader_mod = { - "Protracker", - mod_test, - mod_load -}; - -static int mod_test(HIO_HANDLE *f, char *t, const int start) -{ - int i; - char buf[4]; - - hio_seek(f, start + 1080, SEEK_SET); - if (hio_read(buf, 1, 4, f) < 4) - return -1; - - if (!strncmp(buf + 2, "CH", 2) && isdigit((int)buf[0]) - && isdigit((int)buf[1])) { - i = (buf[0] - '0') * 10 + buf[1] - '0'; - if (i > 0 && i <= 32) { - goto found; - } - } - - if (!strncmp(buf + 1, "CHN", 3) && isdigit((int)*buf)) { - if (*buf >= '0' && *buf <= '9') { - goto found; - } - } - - if (memcmp(buf, "M.K.", 4)) - return -1; - -found: - hio_seek(f, start + 0, SEEK_SET); - libxmp_read_title(f, t, 20); - - return 0; -} - -static int mod_load(struct module_data *m, HIO_HANDLE *f, const int start) -{ - struct xmp_module *mod = &m->mod; - int i, j; - struct xmp_event *event; - struct mod_header mh; - uint8 mod_event[4]; - char magic[8]; - int ptkloop = 0; /* Protracker loop */ - - LOAD_INIT(); - - mod->ins = 31; - mod->smp = mod->ins; - mod->chn = 0; - - m->quirk |= QUIRK_PROTRACK; - m->period_type = PERIOD_MODRNG; - - hio_read(&mh.name, 20, 1, f); - for (i = 0; i < 31; i++) { - hio_read(&mh.ins[i].name, 22, 1, f); /* Instrument name */ - mh.ins[i].size = hio_read16b(f); /* Length in 16-bit words */ - mh.ins[i].finetune = hio_read8(f); /* Finetune (signed nibble) */ - mh.ins[i].volume = hio_read8(f); /* Linear playback volume */ - mh.ins[i].loop_start = hio_read16b(f); /* Loop start in 16-bit words */ - mh.ins[i].loop_size = hio_read16b(f); /* Loop size in 16-bit words */ - } - mh.len = hio_read8(f); - mh.restart = hio_read8(f); - hio_read(&mh.order, 128, 1, f); - memset(magic, 0, 8); - hio_read(magic, 4, 1, f); - - if (!memcmp(magic, "M.K.", 4)) { - mod->chn = 4; - } else if (!strncmp(magic + 2, "CH", 2) && - isdigit((int)magic[0]) && isdigit((int)magic[1])) { - mod->chn = (*magic - '0') * 10 + magic[1] - '0'; - } else if (!strncmp(magic + 1, "CHN", 3) && isdigit((int)*magic)) { - mod->chn = *magic - '0'; - } else { - return -1; - } - - strncpy(mod->name, (char *)mh.name, 20); - - mod->len = mh.len; - /* mod->rst = mh.restart; */ - - if (mod->rst >= mod->len) - mod->rst = 0; - memcpy(mod->xxo, mh.order, 128); - - for (i = 0; i < 128; i++) { - /* This fixes dragnet.mod (garbage in the order list) */ - if (mod->xxo[i] > 0x7f) - break; - if (mod->xxo[i] > mod->pat) - mod->pat = mod->xxo[i]; - } - mod->pat++; - - if (libxmp_init_instrument(m) < 0) - return -1; - - for (i = 0; i < mod->ins; i++) { - struct xmp_instrument *xxi; - struct xmp_subinstrument *sub; - struct xmp_sample *xxs; - - if (libxmp_alloc_subinstrument(mod, i, 1) < 0) - return -1; - - xxi = &mod->xxi[i]; - sub = &xxi->sub[0]; - xxs = &mod->xxs[i]; - - xxs->len = 2 * mh.ins[i].size; - xxs->lps = 2 * mh.ins[i].loop_start; - xxs->lpe = xxs->lps + 2 * mh.ins[i].loop_size; - if (xxs->lpe > xxs->len) { - xxs->lpe = xxs->len; - } - xxs->flg = (mh.ins[i].loop_size > 1 && xxs->lpe >= 4) ? - XMP_SAMPLE_LOOP : 0; - sub->fin = (int8) (mh.ins[i].finetune << 4); - sub->vol = mh.ins[i].volume; - sub->pan = 0x80; - sub->sid = i; - libxmp_instrument_name(mod, i, mh.ins[i].name, 22); - - if (xxs->len > 0) { - xxi->nsm = 1; - } - } - - mod->trk = mod->chn * mod->pat; - - libxmp_set_type(m, mod->chn == 4 ? "Protracker" : "Fasttracker"); - - MODULE_INFO(); - - for (i = 0; i < mod->ins; i++) { - D_(D_INFO "[%2X] %-22.22s %04x %04x %04x %c V%02x %+d %c\n", - i, mod->xxi[i].name, - mod->xxs[i].len, mod->xxs[i].lps, mod->xxs[i].lpe, - (mh.ins[i].loop_size > 1 && mod->xxs[i].lpe > 8) ? - 'L' : ' ', mod->xxi[i].sub[0].vol, - mod->xxi[i].sub[0].fin >> 4, - ptkloop && mod->xxs[i].lps == 0 && mh.ins[i].loop_size > 1 && - mod->xxs[i].len > mod->xxs[i].lpe ? '!' : ' '); - } - - if (libxmp_init_pattern(mod) < 0) - return -1; - - /* Load and convert patterns */ - D_(D_INFO "Stored patterns: %d", mod->pat); - - for (i = 0; i < mod->pat; i++) { - if (libxmp_alloc_pattern_tracks(mod, i, 64) < 0) - return -1; - - for (j = 0; j < (64 * mod->chn); j++) { - event = &EVENT(i, j % mod->chn, j / mod->chn); - hio_read(mod_event, 1, 4, f); - libxmp_decode_protracker_event(event, mod_event); - } - } - - /* Load samples */ - - D_(D_INFO "Stored samples: %d", mod->smp); - - for (i = 0; i < mod->smp; i++) { - int flags; - - if (!mod->xxs[i].len) - continue; - - flags = ptkloop ? SAMPLE_FLAG_FULLREP : 0; - - if (libxmp_load_sample(m, f, flags, &mod->xxs[i], NULL) < 0) - return -1; - } - - if (mod->chn > 4) { - m->quirk &= ~QUIRK_PROTRACK; - m->quirk |= QUIRKS_FT2 | QUIRK_FTMOD; - m->read_event_type = READ_EVENT_FT2; - m->period_type = PERIOD_AMIGA; - } - - return 0; -} diff --git a/source/libxmp-lite/src/mtm_load.c b/source/libxmp-lite/src/mtm_load.c deleted file mode 100644 index d4bc76068..000000000 --- a/source/libxmp-lite/src/mtm_load.c +++ /dev/null @@ -1,265 +0,0 @@ -/* Extended Module Player - * 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"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include "loader.h" - -struct mtm_file_header { - uint8 magic[3]; /* "MTM" */ - uint8 version; /* MSN=major, LSN=minor */ - uint8 name[20]; /* ASCIIZ Module name */ - uint16 tracks; /* Number of tracks saved */ - uint8 patterns; /* Number of patterns saved */ - uint8 modlen; /* Module length */ - uint16 extralen; /* Length of the comment field */ - uint8 samples; /* Number of samples */ - uint8 attr; /* Always zero */ - uint8 rows; /* Number rows per track */ - uint8 channels; /* Number of tracks per pattern */ - uint8 pan[32]; /* Pan positions for each channel */ -}; - -struct mtm_instrument_header { - uint8 name[22]; /* Instrument name */ - uint32 length; /* Instrument length in bytes */ - uint32 loop_start; /* Sample loop start */ - uint32 loopend; /* Sample loop end */ - uint8 finetune; /* Finetune */ - uint8 volume; /* Playback volume */ - uint8 attr; /* &0x01: 16bit sample */ -}; - -static int mtm_test(HIO_HANDLE *, char *, const int); -static int mtm_load(struct module_data *, HIO_HANDLE *, const int); - -extern const struct format_loader libxmp_loader_mtm; -const struct format_loader libxmp_loader_mtm = { - "Multitracker", - mtm_test, - mtm_load -}; - -static int mtm_test(HIO_HANDLE *f, char *t, const int start) -{ - uint8 buf[4]; - - if (hio_read(buf, 1, 4, f) < 4) - return -1; - if (memcmp(buf, "MTM", 3)) - return -1; - if (buf[3] != 0x10) - return -1; - - libxmp_read_title(f, t, 20); - - return 0; -} - -static int mtm_load(struct module_data *m, HIO_HANDLE *f, const int start) -{ - struct xmp_module *mod = &m->mod; - int i, j; - struct mtm_file_header mfh; - struct mtm_instrument_header mih; - uint8 mt[192]; - - LOAD_INIT(); - - hio_read(&mfh.magic, 3, 1, f); /* "MTM" */ - mfh.version = hio_read8(f); /* MSN=major, LSN=minor */ - hio_read(&mfh.name, 20, 1, f); /* ASCIIZ Module name */ - mfh.tracks = hio_read16l(f); /* Number of tracks saved */ - mfh.patterns = hio_read8(f); /* Number of patterns saved */ - mfh.modlen = hio_read8(f); /* Module length */ - mfh.extralen = hio_read16l(f); /* Length of the comment field */ - - mfh.samples = hio_read8(f); /* Number of samples */ - if (mfh.samples > 63) { - return -1; - } - - mfh.attr = hio_read8(f); /* Always zero */ - - mfh.rows = hio_read8(f); /* Number rows per track */ - if (mfh.rows != 64) - return -1; - - mfh.channels = hio_read8(f); /* Number of tracks per pattern */ - if (mfh.channels > XMP_MAX_CHANNELS) { - return -1; - } - - hio_read(&mfh.pan, 32, 1, f); /* Pan positions for each channel */ - - if (hio_error(f)) { - return -1; - } - -#if 0 - if (strncmp((char *)mfh.magic, "MTM", 3)) - return -1; -#endif - - mod->trk = mfh.tracks + 1; - mod->pat = mfh.patterns + 1; - mod->len = mfh.modlen + 1; - mod->ins = mfh.samples; - mod->smp = mod->ins; - mod->chn = mfh.channels; - mod->spd = 6; - mod->bpm = 125; - - strncpy(mod->name, (char *)mfh.name, 20); - libxmp_set_type(m, "MultiTracker %d.%02d MTM", MSN(mfh.version), - LSN(mfh.version)); - - MODULE_INFO(); - - if (libxmp_init_instrument(m) < 0) - return -1; - - /* Read and convert instruments */ - for (i = 0; i < mod->ins; i++) { - struct xmp_instrument *xxi = &mod->xxi[i]; - struct xmp_sample *xxs = &mod->xxs[i]; - struct xmp_subinstrument *sub; - - if (libxmp_alloc_subinstrument(mod, i, 1) < 0) - return -1; - - sub = &xxi->sub[0]; - - hio_read(&mih.name, 22, 1, f); /* Instrument name */ - mih.length = hio_read32l(f); /* Instrument length in bytes */ - - if (mih.length > MAX_SAMPLE_SIZE) - return -1; - - mih.loop_start = hio_read32l(f); /* Sample loop start */ - mih.loopend = hio_read32l(f); /* Sample loop end */ - mih.finetune = hio_read8(f); /* Finetune */ - mih.volume = hio_read8(f); /* Playback volume */ - mih.attr = hio_read8(f); /* &0x01: 16bit sample */ - - xxs->len = mih.length; - xxs->lps = mih.loop_start; - xxs->lpe = mih.loopend; - xxs->flg = xxs->lpe ? XMP_SAMPLE_LOOP : 0; /* 1 == Forward loop */ - if (mfh.attr & 1) { - xxs->flg |= XMP_SAMPLE_16BIT; - xxs->len >>= 1; - xxs->lps >>= 1; - xxs->lpe >>= 1; - } - - sub->vol = mih.volume; - sub->fin = mih.finetune; - sub->pan = 0x80; - sub->sid = i; - - libxmp_instrument_name(mod, i, mih.name, 22); - - if (xxs->len > 0) - mod->xxi[i].nsm = 1; - - D_(D_INFO "[%2X] %-22.22s %04x%c%04x %04x %c V%02x F%+03d\n", i, - xxi->name, xxs->len, xxs->flg & XMP_SAMPLE_16BIT ? '+' : ' ', - xxs->lps, xxs->lpe, xxs->flg & XMP_SAMPLE_LOOP ? 'L' : ' ', - sub->vol, sub->fin - 0x80); - } - - hio_read(mod->xxo, 1, 128, f); - - if (libxmp_init_pattern(mod) < 0) - return -1; - - D_(D_INFO "Stored tracks: %d", mod->trk - 1); - - for (i = 0; i < mod->trk; i++) { - - if (libxmp_alloc_track(mod, i, mfh.rows) < 0) - return -1; - - if (i == 0) - continue; - - if (hio_read(&mt, 3, 64, f) != 64) - return -1; - - for (j = 0; j < 64; j++) { - struct xmp_event *e = &mod->xxt[i]->event[j]; - uint8 *d = mt + j * 3; - - if ((e->note = d[0] >> 2)) { - e->note += 37; - } - e->ins = ((d[0] & 0x3) << 4) + MSN(d[1]); - e->fxt = LSN(d[1]); - e->fxp = d[2]; - if (e->fxt > FX_SPEED) { - e->fxt = e->fxp = 0; - } - - /* Set pan effect translation */ - if (e->fxt == FX_EXTENDED && MSN(e->fxp) == 0x8) { - e->fxt = FX_SETPAN; - e->fxp <<= 4; - } - } - } - - /* Read patterns */ - D_(D_INFO "Stored patterns: %d", mod->pat - 1); - - for (i = 0; i < mod->pat; i++) { - if (libxmp_alloc_pattern(mod, i) < 0) - return -1; - - mod->xxp[i]->rows = 64; - for (j = 0; j < 32; j++) { - int track = hio_read16l(f); - - if (track >= mod->trk) { - track = 0; - } - - if (j < mod->chn) { - mod->xxp[i]->index[j] = track; - } - } - } - - /* Comments */ - hio_seek(f, mfh.extralen, SEEK_CUR); - - /* Read samples */ - D_(D_INFO "Stored samples: %d", mod->smp); - - for (i = 0; i < mod->ins; i++) { - if (libxmp_load_sample(m, f, SAMPLE_FLAG_UNS, &mod->xxs[i], NULL) < 0) - return -1; - } - - for (i = 0; i < mod->chn; i++) - mod->xxc[i].pan = mfh.pan[i] << 4; - - return 0; -} diff --git a/source/libxmp-lite/src/period.c b/source/libxmp-lite/src/period.c deleted file mode 100644 index 582eba0df..000000000 --- a/source/libxmp-lite/src/period.c +++ /dev/null @@ -1,268 +0,0 @@ -/* Extended Module Player - * 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"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#ifndef _GNU_SOURCE -#define _GNU_SOURCE -#endif - -#include -#include -#include "common.h" -#include "period.h" - -#include - -#ifdef LIBXMP_PAULA_SIMULATOR -/* - * Period table from the Protracker V2.1A play routine - */ -static uint16 pt_period_table[16][36] = { - /* Tuning 0, Normal */ - { - 856,808,762,720,678,640,604,570,538,508,480,453, - 428,404,381,360,339,320,302,285,269,254,240,226, - 214,202,190,180,170,160,151,143,135,127,120,113 - }, - /* Tuning 1 */ - { - 850,802,757,715,674,637,601,567,535,505,477,450, - 425,401,379,357,337,318,300,284,268,253,239,225, - 213,201,189,179,169,159,150,142,134,126,119,113 - }, - /* Tuning 2 */ - { - 844,796,752,709,670,632,597,563,532,502,474,447, - 422,398,376,355,335,316,298,282,266,251,237,224, - 211,199,188,177,167,158,149,141,133,125,118,112 - }, - /* Tuning 3 */ - { - 838,791,746,704,665,628,592,559,528,498,470,444, - 419,395,373,352,332,314,296,280,264,249,235,222, - 209,198,187,176,166,157,148,140,132,125,118,111 - }, - /* Tuning 4 */ - { - 832,785,741,699,660,623,588,555,524,495,467,441, - 416,392,370,350,330,312,294,278,262,247,233,220, - 208,196,185,175,165,156,147,139,131,124,117,110 - }, - /* Tuning 5 */ - { - 826,779,736,694,655,619,584,551,520,491,463,437, - 413,390,368,347,328,309,292,276,260,245,232,219, - 206,195,184,174,164,155,146,138,130,123,116,109 - }, - /* Tuning 6 */ - { - 820,774,730,689,651,614,580,547,516,487,460,434, - 410,387,365,345,325,307,290,274,258,244,230,217, - 205,193,183,172,163,154,145,137,129,122,115,109 - }, - /* Tuning 7 */ - { - 814,768,725,684,646,610,575,543,513,484,457,431, - 407,384,363,342,323,305,288,272,256,242,228,216, - 204,192,181,171,161,152,144,136,128,121,114,108 - }, - /* Tuning -8 */ - { - 907,856,808,762,720,678,640,604,570,538,508,480, - 453,428,404,381,360,339,320,302,285,269,254,240, - 226,214,202,190,180,170,160,151,143,135,127,120 - }, - /* Tuning -7 */ - { - 900,850,802,757,715,675,636,601,567,535,505,477, - 450,425,401,379,357,337,318,300,284,268,253,238, - 225,212,200,189,179,169,159,150,142,134,126,119 - }, - /* Tuning -6 */ - { - 894,844,796,752,709,670,632,597,563,532,502,474, - 447,422,398,376,355,335,316,298,282,266,251,237, - 223,211,199,188,177,167,158,149,141,133,125,118 - }, - /* Tuning -5 */ - { - 887,838,791,746,704,665,628,592,559,528,498,470, - 444,419,395,373,352,332,314,296,280,264,249,235, - 222,209,198,187,176,166,157,148,140,132,125,118 - }, - /* Tuning -4 */ - { - 881,832,785,741,699,660,623,588,555,524,494,467, - 441,416,392,370,350,330,312,294,278,262,247,233, - 220,208,196,185,175,165,156,147,139,131,123,117 - }, - /* Tuning -3 */ - { - 875,826,779,736,694,655,619,584,551,520,491,463, - 437,413,390,368,347,328,309,292,276,260,245,232, - 219,206,195,184,174,164,155,146,138,130,123,116 - }, - /* Tuning -2 */ - { - 868,820,774,730,689,651,614,580,547,516,487,460, - 434,410,387,365,345,325,307,290,274,258,244,230, - 217,205,193,183,172,163,154,145,137,129,122,115 - }, - /* Tuning -1 */ - { - 862,814,768,725,684,646,610,575,543,513,484,457, - 431,407,384,363,342,323,305,288,272,256,242,228, - 216,203,192,181,171,161,152,144,136,128,121,114 - } -}; -#endif - -#ifndef M_LN2 -#define M_LN2 0.69314718055994530942 -#endif -#if !defined(HAVE_ROUND) || defined(_MSC_VER) || defined(__WATCOMC__) -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 -/* Get period from note using Protracker tuning */ -static inline int libxmp_note_to_period_pt(int n, int f) -{ - if (n < MIN_NOTE_MOD || n > MAX_NOTE_MOD) { - return -1; - } - - n -= 48; - f >>= 4; - if (f < -8 || f > 7) { - return 0; - } - - if (f < 0) { - f += 16; - } - - return (int)pt_period_table[f][n]; -} -#endif - -/* Get period from note */ -double libxmp_note_to_period(struct context_data *ctx, int n, int f, double adj) -{ - double d, per; - struct module_data *m = &ctx->m; -#ifdef LIBXMP_PAULA_SIMULATOR - struct player_data *p = &ctx->p; - - /* If mod replayer, modrng and Amiga mixing are active */ - if (p->flags & XMP_FLAGS_A500) { - if (IS_AMIGA_MOD()) { - return libxmp_note_to_period_pt(n, f); - } - } -#endif - - d = (double)n + (double)f / 128; - - switch (m->period_type) { - case PERIOD_LINEAR: - per = (240.0 - d) * 16; /* Linear */ - break; - case PERIOD_CSPD: - per = 8363.0 * pow(2, n / 12) / 32 + f; /* Hz */ - break; - default: - per = PERIOD_BASE / pow(2, d / 12); /* Amiga */ - } - -#ifndef LIBXMP_CORE_PLAYER - if (adj > 0.1) { - per *= adj; - } -#endif - - return per; -} - -/* For the software mixer */ -double libxmp_note_to_period_mix(int n, int b) -{ - double d = (double)n + (double)b / 12800; - return PERIOD_BASE / pow(2, d / 12); -} - -/* Get note from period */ -/* This function is used only by the MOD loader */ -int libxmp_period_to_note(int p) -{ - if (p <= 0) { - return 0; - } - - return libxmp_round(12.0 * log(PERIOD_BASE / p) / M_LN2) + 1; -} - -/* Get pitchbend from base note and amiga period */ -int libxmp_period_to_bend(struct context_data *ctx, double p, int n, double adj) -{ - struct module_data *m = &ctx->m; - double d; - - if (n == 0) { - return 0; - } - - switch (m->period_type) { - case PERIOD_LINEAR: - return (int) (100 * (8 * (((240 - n) << 4) - p))); - case PERIOD_CSPD: - d = libxmp_note_to_period(ctx, n, 0, adj); - return libxmp_round(100.0 * (1536.0 / M_LN2) * log(p / d)); - default: - /* Amiga */ - d = libxmp_note_to_period(ctx, n, 0, adj); - return libxmp_round(100.0 * (1536.0 / M_LN2) * log(d / p)); - } -} - -/* Convert finetune = 1200 * log2(C2SPD/8363)) - * - * c = (1200.0 * log(c2spd) - 1200.0 * log(c4_rate)) / M_LN2; - * xpo = c/100; - * fin = 128 * (c%100) / 100; - */ -void libxmp_c2spd_to_note(int c2spd, int *n, int *f) -{ - int c; - - if (c2spd == 0) { - *n = *f = 0; - return; - } - - c = (int)(1536.0 * log((double)c2spd / 8363) / M_LN2); - *n = c / 128; - *f = c % 128; -} diff --git a/source/libxmp-lite/src/period.h b/source/libxmp-lite/src/period.h deleted file mode 100644 index 10a8c67dc..000000000 --- a/source/libxmp-lite/src/period.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef LIBXMP_PERIOD_H -#define LIBXMP_PERIOD_H - -#define PERIOD_BASE 13696.0 /* C0 period */ - -/* Macros for period conversion */ -#define NOTE_B0 11 -#define NOTE_Bb0 (NOTE_B0 + 1) -#define MAX_NOTE (NOTE_B0 * 8) -#define MAX_PERIOD 0x1c56 -#define MIN_PERIOD_A 0x0071 -#define MAX_PERIOD_A 0x0358 -#define MIN_PERIOD_L 0x0000 -#define MAX_PERIOD_L 0x1e00 -#define MIN_NOTE_MOD 48 -#define MAX_NOTE_MOD 83 - -double libxmp_note_to_period (struct context_data *, int, int, double); -double libxmp_note_to_period_mix (int, int); -int libxmp_period_to_note (int); -int libxmp_period_to_bend (struct context_data *, double, int, double); -void libxmp_c2spd_to_note (int, int *, int *); - -#endif /* LIBXMP_PERIOD_H */ diff --git a/source/libxmp-lite/src/player.c b/source/libxmp-lite/src/player.c deleted file mode 100644 index 834c03095..000000000 --- a/source/libxmp-lite/src/player.c +++ /dev/null @@ -1,1907 +0,0 @@ -/* Extended Module Player - * 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"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -/* - * Sat, 18 Apr 1998 20:23:07 +0200 Frederic Bujon - * Pan effect bug fixed: In Fastracker II the track panning effect erases - * the instrument panning effect, and the same should happen in xmp. - */ - -/* - * Fri, 26 Jun 1998 13:29:25 -0400 (EDT) - * Reported by Jared Spiegel - * when the volume envelope is not enabled (disabled) on a sample, and a - * notoff is delivered to ft2 (via either a noteoff in the note column or - * command Kxx [where xx is # of ticks into row to give a noteoff to the - * sample]), ft2 will set the volume of playback of the sample to 00h. - * - * Claudio's fix: implementing effect K - */ - -#include -#include -#include "virtual.h" -#include "period.h" -#include "effects.h" -#include "player.h" -#include "mixer.h" -#ifndef LIBXMP_CORE_PLAYER -#include "extras.h" -#endif - -/* Values for multi-retrig */ -static const struct retrig_control rval[] = { - { 0, 1, 1 }, { -1, 1, 1 }, { -2, 1, 1 }, { -4, 1, 1 }, - { -8, 1, 1 }, { -16, 1, 1 }, { 0, 2, 3 }, { 0, 1, 2 }, - { 0, 1, 1 }, { 1, 1, 1 }, { 2, 1, 1 }, { 4, 1, 1 }, - { 8, 1, 1 }, { 16, 1, 1 }, { 0, 3, 2 }, { 0, 2, 1 }, - { 0, 0, 1 } /* Note cut */ - -}; - - -/* - * "Anyway I think this is the most brilliant piece of crap we - * have managed to put up!" - * -- Ice of FC about "Mental Surgery" - */ - - -/* Envelope */ - -static int check_envelope_end(struct xmp_envelope *env, int x) -{ - int16 *data = env->data; - int index; - - if (~env->flg & XMP_ENVELOPE_ON || env->npt <= 0) - return 0; - - index = (env->npt - 1) * 2; - - /* last node */ - if (x >= data[index] || index == 0) { - if (~env->flg & XMP_ENVELOPE_LOOP) { - return 1; - } - } - - return 0; -} - -static int get_envelope(struct xmp_envelope *env, int x, int def) -{ - int x1, x2, y1, y2; - int16 *data = env->data; - int index; - - if (x < 0 || ~env->flg & XMP_ENVELOPE_ON || env->npt <= 0) - return def; - - index = (env->npt - 1) * 2; - - x1 = data[index]; /* last node */ - if (x >= x1 || index == 0) { - return data[index + 1]; - } - - do { - index -= 2; - x1 = data[index]; - } while (index > 0 && x1 > x); - - /* interpolate */ - y1 = data[index + 1]; - x2 = data[index + 2]; - y2 = data[index + 3]; - - return x2 == x1 ? y2 : ((y2 - y1) * (x - x1) / (x2 - x1)) + y1; -} - -static int update_envelope_xm(struct xmp_envelope *env, int x, int release) -{ - int16 *data = env->data; - int has_loop, has_sus; - int lpe, lps, sus; - - has_loop = env->flg & XMP_ENVELOPE_LOOP; - has_sus = env->flg & XMP_ENVELOPE_SUS; - - lps = env->lps << 1; - lpe = env->lpe << 1; - sus = env->sus << 1; - - /* FT2 and IT envelopes behave in a different way regarding loops, - * sustain and release. When the sustain point is at the end of the - * envelope loop end and the key is released, FT2 escapes the loop - * while IT runs another iteration. (See EnvLoops.xm in the OpenMPT - * test cases.) - */ - if (has_loop && has_sus && sus == lpe) { - if (!release) - has_sus = 0; - } - - /* If the envelope point is set to somewhere after the sustain point - * or sustain loop, enable release to prevent the envelope point to - * return to the sustain point or loop start. (See Filip Skutela's - * farewell_tear.xm.) - */ - if (has_loop && x > data[lpe] + 1) { - release = 1; - } else if (has_sus && x > data[sus] + 1) { - release = 1; - } - - /* If enabled, stay at the sustain point */ - if (has_sus && !release) { - if (x >= data[sus]) { - x = data[sus]; - } - } - - /* Envelope loops */ - if (has_loop && x >= data[lpe]) { - if (!(release && has_sus && sus == lpe)) - x = data[lps]; - } - - return x; -} - -#ifndef LIBXMP_CORE_DISABLE_IT - -static int update_envelope_it(struct xmp_envelope *env, int x, int release, int key_off) -{ - int16 *data = env->data; - int has_loop, has_sus; - int lpe, lps, sus, sue; - - has_loop = env->flg & XMP_ENVELOPE_LOOP; - has_sus = env->flg & XMP_ENVELOPE_SUS; - - lps = env->lps << 1; - lpe = env->lpe << 1; - sus = env->sus << 1; - sue = env->sue << 1; - - /* Release at the end of a sustain loop, run another loop */ - if (has_sus && key_off && x == data[sue] + 1) { - x = data[sus]; - } else - /* If enabled, stay in the sustain loop */ - if (has_sus && !release) { - if (x == data[sue] + 1) { - x = data[sus]; - } - } else - /* Finally, execute the envelope loop */ - if (has_loop) { - if (x > data[lpe]) { - x = data[lps]; - } - } - - return x; -} - -#endif - -static int update_envelope(struct xmp_envelope *env, int x, int release, int key_off, int it_env) -{ - if (x < 0xffff) { /* increment tick */ - x++; - } - - if (x < 0) { - return -1; - } - - if (~env->flg & XMP_ENVELOPE_ON || env->npt <= 0) { - return x; - } - -#ifndef LIBXMP_CORE_DISABLE_IT - return it_env ? - update_envelope_it(env, x, release, key_off) : - update_envelope_xm(env, x, release); -#else - return update_envelope_xm(env, x, release); -#endif -} - - -/* Returns: 0 if do nothing, <0 to reset channel, >0 if has fade */ -static int check_envelope_fade(struct xmp_envelope *env, int x) -{ - int16 *data = env->data; - int index; - - if (~env->flg & XMP_ENVELOPE_ON) - return 0; - - index = (env->npt - 1) * 2; /* last node */ - if (x > data[index]) { - if (data[index + 1] == 0) - return -1; - else - return 1; - } - - return 0; -} - - -#ifndef LIBXMP_CORE_PLAYER - -/* From http://www.un4seen.com/forum/?topic=7554.0 - * - * "Invert loop" effect replaces (!) sample data bytes within loop with their - * bitwise complement (NOT). The parameter sets speed of altering the samples. - * This effectively trashes the sample data. Because of that this effect was - * supposed to be removed in the very next ProTracker versions, but it was - * never removed. - * - * Prior to [Protracker 1.1A] this effect is called "Funk Repeat" and it moves - * loop of the instrument (just the loop information - sample data is not - * altered). The parameter is the speed of moving the loop. - */ - -static const int invloop_table[] = { - 0, 5, 6, 7, 8, 10, 11, 13, 16, 19, 22, 26, 32, 43, 64, 128 -}; - -static void update_invloop(struct module_data *m, struct channel_data *xc) -{ - struct xmp_sample *xxs = &m->mod.xxs[xc->smp]; - int len; - - xc->invloop.count += invloop_table[xc->invloop.speed]; - - if ((xxs->flg & XMP_SAMPLE_LOOP) && xc->invloop.count >= 128) { - xc->invloop.count = 0; - len = xxs->lpe - xxs->lps; - - if (++xc->invloop.pos > len) { - xc->invloop.pos = 0; - } - - if (~xxs->flg & XMP_SAMPLE_16BIT) { - xxs->data[xxs->lps + xc->invloop.pos] ^= 0xff; - } - } -} - -#endif - -/* - * From OpenMPT Arpeggio.xm test: - * - * "[FT2] Arpeggio behavior is very weird with more than 16 ticks per row. This - * comes from the fact that Fasttracker 2 uses a LUT for computing the arpeggio - * note (instead of doing something like tick%3 or similar). The LUT only has - * 16 entries, so when there are more than 16 ticks, it reads beyond array - * boundaries. The vibrato table happens to be stored right after arpeggio - * table. The tables look like this in memory: - * - * ArpTab: 0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0 - * VibTab: 0,24,49,74,97,120,141,161,180,197,... - * - * All values except for the first in the vibrato table are greater than 1, so - * they trigger the third arpeggio note. Keep in mind that Fasttracker 2 counts - * downwards, so the table has to be read from back to front, i.e. at 16 ticks - * per row, the 16th entry in the LUT is the first to be read. This is also the - * reason why Arpeggio is played 'backwards' in Fasttracker 2." - */ -static int ft2_arpeggio(struct context_data *ctx, struct channel_data *xc) -{ - struct player_data *p = &ctx->p; - int i; - - if (xc->arpeggio.val[1] == 0 && xc->arpeggio.val[2] == 0) { - return 0; - } - - if (p->frame == 0) { - return 0; - } - - i = p->speed - (p->frame % p->speed); - - if (i == 16) { - return 0; - } else if (i > 16) { - return xc->arpeggio.val[2]; - } - - return xc->arpeggio.val[i % 3]; -} - -static int is_first_frame(struct context_data *ctx) -{ - struct player_data *p = &ctx->p; - struct module_data *m = &ctx->m; - - switch (m->read_event_type) { -#ifndef LIBXMP_CORE_DISABLE_IT - case READ_EVENT_IT: - /* fall through */ -#endif - case READ_EVENT_ST3: - return p->frame % p->speed == 0; - default: - return p->frame == 0; - } -} - -static void reset_channels(struct context_data *ctx) -{ - struct player_data *p = &ctx->p; - struct module_data *m = &ctx->m; - struct xmp_module *mod = &m->mod; - struct smix_data *smix = &ctx->smix; - struct channel_data *xc; - int i; - -#ifndef LIBXMP_CORE_PLAYER - for (i = 0; i < p->virt.virt_channels; i++) { - void *extra; - - xc = &p->xc_data[i]; - extra = xc->extra; - memset(xc, 0, sizeof (struct channel_data)); - xc->extra = extra; - libxmp_reset_channel_extras(ctx, xc); - xc->ins = -1; - xc->old_ins = 1; /* raw value */ - xc->key = -1; - xc->volume = m->volbase; - } -#else - for (i = 0; i < p->virt.virt_channels; i++) { - xc = &p->xc_data[i]; - memset(xc, 0, sizeof (struct channel_data)); - xc->ins = -1; - xc->old_ins = 1; /* raw value */ - xc->key = -1; - xc->volume = m->volbase; - } -#endif - - for (i = 0; i < p->virt.num_tracks; i++) { - xc = &p->xc_data[i]; - - if (i >= mod->chn && i < mod->chn + smix->chn) { - xc->mastervol = 0x40; - xc->pan.val = 0x80; - } else { - xc->mastervol = mod->xxc[i].vol; - xc->pan.val = mod->xxc[i].pan; - } - -#ifndef LIBXMP_CORE_DISABLE_IT - xc->filter.cutoff = 0xff; - - /* Amiga split channel */ - if (mod->xxc[i].flg & XMP_CHANNEL_SPLIT) { - int j; - - xc->split = ((mod->xxc[i].flg & 0x30) >> 4) + 1; - /* Connect split channel pairs */ - for (j = 0; j < i; j++) { - if (mod->xxc[j].flg & XMP_CHANNEL_SPLIT) { - if (p->xc_data[j].split == xc->split) { - p->xc_data[j].pair = i; - xc->pair = j; - } - } - } - } else { - xc->split = 0; - } -#endif - - /* Surround channel */ - if (mod->xxc[i].flg & XMP_CHANNEL_SURROUND) { - xc->pan.surround = 1; - } - } -} - -static int check_delay(struct context_data *ctx, struct xmp_event *e, int chn) -{ - struct player_data *p = &ctx->p; - struct channel_data *xc = &p->xc_data[chn]; - struct module_data *m = &ctx->m; - - /* Tempo affects delay and must be computed first */ - if ((e->fxt == FX_SPEED && e->fxp < 0x20) || e->fxt == FX_S3M_SPEED) { - if (e->fxp) { - p->speed = e->fxp; - } - } - if ((e->f2t == FX_SPEED && e->f2p < 0x20) || e->f2t == FX_S3M_SPEED) { - if (e->f2p) { - p->speed = e->f2p; - } - } - - /* Delay event read */ - if (e->fxt == FX_EXTENDED && MSN(e->fxp) == EX_DELAY && LSN(e->fxp)) { - xc->delay = LSN(e->fxp) + 1; - goto do_delay; - } - if (e->f2t == FX_EXTENDED && MSN(e->f2p) == EX_DELAY && LSN(e->f2p)) { - xc->delay = LSN(e->f2p) + 1; - goto do_delay; - } - - return 0; - - do_delay: - memcpy(&xc->delayed_event, e, sizeof (struct xmp_event)); - - if (e->ins) { - xc->delayed_ins = e->ins; - } - - if (HAS_QUIRK(QUIRK_RTDELAY)) { - if (e->vol == 0 && e->f2t == 0 && e->ins == 0 && e->note != XMP_KEY_OFF) - xc->delayed_event.vol = xc->volume + 1; - if (e->note == 0) - xc->delayed_event.note = xc->key + 1; - if (e->ins == 0) - xc->delayed_event.ins = xc->old_ins; - } - - return 1; -} - -static inline void read_row(struct context_data *ctx, int pat, int row) -{ - int chn; - struct module_data *m = &ctx->m; - struct xmp_module *mod = &m->mod; - struct player_data *p = &ctx->p; - struct flow_control *f = &p->flow; - struct xmp_event ev; - - for (chn = 0; chn < mod->chn; chn++) { - const int num_rows = mod->xxt[TRACK_NUM(pat, chn)]->rows; - if (row < num_rows) { - memcpy(&ev, &EVENT(pat, chn, row), sizeof(ev)); - } else { - memset(&ev, 0, sizeof(ev)); - } - - if (ev.note == XMP_KEY_OFF) { - int env_on = 0; - int ins = ev.ins - 1; - - if (IS_VALID_INSTRUMENT(ins) && - (mod->xxi[ins].aei.flg & XMP_ENVELOPE_ON)) { - env_on = 1; - } - - if (ev.fxt == FX_EXTENDED && MSN(ev.fxp) == EX_DELAY) { - if (ev.ins && (LSN(ev.fxp) || env_on)) { - if (LSN(ev.fxp)) { - ev.note = 0; - } - ev.fxp = ev.fxt = 0; - } - } - } - - if (check_delay(ctx, &ev, chn) == 0) { - if (!f->rowdelay_set || f->rowdelay > 0) { - libxmp_read_event(ctx, &ev, chn); -#ifndef LIBXMP_CORE_PLAYER - libxmp_med_hold_hack(ctx, pat, chn, row); -#endif - } - } else { - if (IS_PLAYER_MODE_IT()) { - /* Reset flags. See SlideDelay.it */ - p->xc_data[chn].flags = 0; - } - } - } -} - -static inline int get_channel_vol(struct context_data *ctx, int chn) -{ - struct player_data *p = &ctx->p; - int root; - - /* channel is a root channel */ - if (chn < p->virt.num_tracks) - return p->channel_vol[chn]; - - /* channel is invalid */ - if (chn >= p->virt.virt_channels) - return 0; - - /* root is invalid */ - root = libxmp_virt_getroot(ctx, chn); - if (root < 0) - return 0; - - return p->channel_vol[root]; -} - -static int tremor_ft2(struct context_data *ctx, int chn, int finalvol) -{ - struct player_data *p = &ctx->p; - struct channel_data *xc = &p->xc_data[chn]; - - if (xc->tremor.count & 0x80) { - if (TEST(TREMOR) && p->frame != 0) { - xc->tremor.count &= ~0x20; - if (xc->tremor.count == 0x80) { - /* end of down cycle, set up counter for up */ - xc->tremor.count = xc->tremor.up | 0xc0; - } else if (xc->tremor.count == 0xc0) { - /* end of up cycle, set up counter for down */ - xc->tremor.count = xc->tremor.down | 0x80; - } else { - xc->tremor.count--; - } - } - - if ((xc->tremor.count & 0xe0) == 0x80) { - finalvol = 0; - } - } - - return finalvol; -} - -static int tremor_s3m(struct context_data *ctx, int chn, int finalvol) -{ - struct player_data *p = &ctx->p; - struct channel_data *xc = &p->xc_data[chn]; - - if (TEST(TREMOR)) { - if (xc->tremor.count == 0) { - /* end of down cycle, set up counter for up */ - xc->tremor.count = xc->tremor.up | 0x80; - } else if (xc->tremor.count == 0x80) { - /* end of up cycle, set up counter for down */ - xc->tremor.count = xc->tremor.down; - } - - xc->tremor.count--; - - if (~xc->tremor.count & 0x80) { - finalvol = 0; - } - } - - return finalvol; -} - -/* - * Update channel data - */ - -#define DOENV_RELEASE ((TEST_NOTE(NOTE_RELEASE) || act == VIRT_ACTION_OFF)) - -static void process_volume(struct context_data *ctx, int chn, int act) -{ - struct player_data *p = &ctx->p; - struct module_data *m = &ctx->m; - struct channel_data *xc = &p->xc_data[chn]; - struct xmp_instrument *instrument; - int finalvol; - uint16 vol_envelope; - int fade = 0; - - instrument = libxmp_get_instrument(ctx, xc->ins); - - /* Keyoff and fadeout */ - - /* Keyoff event in IT doesn't reset fadeout (see jeff93.it) - * In XM it depends on envelope (see graff-strange_land.xm vs - * Decibelter - Cosmic 'Wegian Mamas.xm) - */ - if (HAS_QUIRK(QUIRK_KEYOFF)) { - /* If IT, only apply fadeout on note release if we don't - * have envelope, or if we have envelope loop - */ - if (TEST_NOTE(NOTE_RELEASE) || act == VIRT_ACTION_OFF) { - if ((~instrument->aei.flg & XMP_ENVELOPE_ON) || - (instrument->aei.flg & XMP_ENVELOPE_LOOP)) { - fade = 1; - } - } - } else { - if (~instrument->aei.flg & XMP_ENVELOPE_ON) { - if (TEST_NOTE(NOTE_RELEASE)) { - xc->fadeout = 0; - } - } - - if (TEST_NOTE(NOTE_RELEASE) || act == VIRT_ACTION_OFF) { - fade = 1; - } - } - - if (TEST_NOTE(NOTE_FADEOUT) || act == VIRT_ACTION_FADE) { - fade = 1; - } - - if (fade) { - if (xc->fadeout > xc->ins_fade) { - xc->fadeout -= xc->ins_fade; - } else { - xc->fadeout = 0; - SET_NOTE(NOTE_END); - } - } - - switch (check_envelope_fade(&instrument->aei, xc->v_idx)) { - case -1: - SET_NOTE(NOTE_END); - /* Don't reset channel, we may have a tone portamento later - * virt_resetchannel(ctx, chn); - */ - break; - case 0: - break; - default: - if (HAS_QUIRK(QUIRK_ENVFADE)) { - SET_NOTE(NOTE_FADEOUT); - } - } - - if (!TEST_PER(VENV_PAUSE)) { - xc->v_idx = update_envelope(&instrument->aei, xc->v_idx, - DOENV_RELEASE, TEST(KEY_OFF), IS_PLAYER_MODE_IT()); - } - - vol_envelope = get_envelope(&instrument->aei, xc->v_idx, 64); - if (check_envelope_end(&instrument->aei, xc->v_idx)) { - if (vol_envelope == 0) { - SET_NOTE(NOTE_END); - } - SET_NOTE(NOTE_ENV_END); - } - - /* If note ended in background channel, we can safely reset it */ - if (TEST_NOTE(NOTE_END) && chn >= p->virt.num_tracks) { - libxmp_virt_resetchannel(ctx, chn); - return; - } - -#ifndef LIBXMP_CORE_PLAYER - finalvol = libxmp_extras_get_volume(ctx, xc); -#else - finalvol = xc->volume; -#endif - - if (IS_PLAYER_MODE_IT()) { - finalvol = xc->volume * (100 - xc->rvv) / 100; - } - - if (TEST(TREMOLO)) { - /* OpenMPT VibratoReset.mod */ - if (!is_first_frame(ctx) || !HAS_QUIRK(QUIRK_PROTRACK)) { - finalvol += libxmp_lfo_get(ctx, &xc->tremolo.lfo, 0) / (1 << 6); - } - - if (!is_first_frame(ctx) || HAS_QUIRK(QUIRK_VIBALL)) { - libxmp_lfo_update(&xc->tremolo.lfo); - } - } - - CLAMP(finalvol, 0, m->volbase); - - finalvol = (finalvol * xc->fadeout) >> 6; /* 16 bit output */ - - finalvol = (uint32)(vol_envelope * p->gvol * xc->mastervol / - m->gvolbase * ((int)finalvol * 0x40 / m->volbase)) >> 18; - - /* Apply channel volume */ - finalvol = finalvol * get_channel_vol(ctx, chn) / 100; - -#ifndef LIBXMP_CORE_PLAYER - /* Volume translation table (for PTM, ARCH, COCO) */ - if (m->vol_table) { - finalvol = m->volbase == 0xff ? - m->vol_table[finalvol >> 2] << 2 : - m->vol_table[finalvol >> 4] << 4; - } -#endif - - if (HAS_QUIRK(QUIRK_INSVOL)) { - finalvol = (finalvol * instrument->vol * xc->gvl) >> 12; - } - - if (IS_PLAYER_MODE_FT2()) { - finalvol = tremor_ft2(ctx, chn, finalvol); - } else { - finalvol = tremor_s3m(ctx, chn, finalvol); - } - - if (chn < m->mod.chn) { - finalvol = finalvol * p->master_vol / 100; - } else { - finalvol = finalvol * p->smix_vol / 100; - } - - xc->info_finalvol = TEST_NOTE(NOTE_SAMPLE_END) ? 0 : finalvol; - - libxmp_virt_setvol(ctx, chn, finalvol); - - /* Check Amiga split channel */ - if (xc->split) { - libxmp_virt_setvol(ctx, xc->pair, finalvol); - } -} - -static void process_frequency(struct context_data *ctx, int chn, int act) -{ -#ifndef LIBXMP_CORE_DISABLE_IT - struct mixer_data *s = &ctx->s; -#endif - struct player_data *p = &ctx->p; - struct module_data *m = &ctx->m; - struct channel_data *xc = &p->xc_data[chn]; - struct xmp_instrument *instrument; - double period, vibrato; - int linear_bend; - int frq_envelope; - int arp; -#ifndef LIBXMP_CORE_DISABLE_IT - int cutoff, resonance; -#endif - - instrument = libxmp_get_instrument(ctx, xc->ins); - - if (!TEST_PER(FENV_PAUSE)) { - xc->f_idx = update_envelope(&instrument->fei, xc->f_idx, - DOENV_RELEASE, TEST(KEY_OFF), IS_PLAYER_MODE_IT()); - } - frq_envelope = get_envelope(&instrument->fei, xc->f_idx, 0); - -#ifndef LIBXMP_CORE_PLAYER - /* Do note slide */ - - if (TEST(NOTE_SLIDE)) { - if (xc->noteslide.count == 0) { - xc->note += xc->noteslide.slide; - xc->period = libxmp_note_to_period(ctx, xc->note, - xc->finetune, xc->per_adj); - xc->noteslide.count = xc->noteslide.speed; - } - xc->noteslide.count--; - - libxmp_virt_setnote(ctx, chn, xc->note); - } -#endif - - /* Instrument vibrato */ - vibrato = 1.0 * libxmp_lfo_get(ctx, &xc->insvib.lfo, 1) / - (4096 * (1 + xc->insvib.sweep)); - libxmp_lfo_update(&xc->insvib.lfo); - if (xc->insvib.sweep > 1) { - xc->insvib.sweep -= 2; - } else { - xc->insvib.sweep = 0; - } - - /* Vibrato */ - if (TEST(VIBRATO) || TEST_PER(VIBRATO)) { - /* OpenMPT VibratoReset.mod */ - if (!is_first_frame(ctx) || !HAS_QUIRK(QUIRK_PROTRACK)) { - int shift = HAS_QUIRK(QUIRK_VIBHALF) ? 10 : 9; - int vib = libxmp_lfo_get(ctx, &xc->vibrato.lfo, 1) / (1 << shift); - - if (HAS_QUIRK(QUIRK_VIBINV)) { - vibrato -= vib; - } else { - vibrato += vib; - } - } - - if (!is_first_frame(ctx) || HAS_QUIRK(QUIRK_VIBALL)) { - libxmp_lfo_update(&xc->vibrato.lfo); - } - } - - period = xc->period; -#ifndef LIBXMP_CORE_PLAYER - period += libxmp_extras_get_period(ctx, xc); -#endif - - /* Sanity check */ - if (period < 0.1) { - period = 0.1; - } - - /* Arpeggio */ - - if (HAS_QUIRK(QUIRK_FT2BUGS)) { - arp = ft2_arpeggio(ctx, xc); - } else { - arp = xc->arpeggio.val[xc->arpeggio.count]; - } - - /* Pitch bend */ - - /* From OpenMPT PeriodLimit.s3m: - * "ScreamTracker 3 limits the final output period to be at least 64, - * i.e. when playing a note that is too high or when sliding the - * period lower than 64, the output period will simply be clamped to - * 64. However, when reaching a period of 0 through slides, the - * output on the channel should be stopped." - */ - /* ST3 uses periods*4, so the limit is 16. Adjusted to the exact - * A6 value because we compute periods in floating point. - */ - if (HAS_QUIRK(QUIRK_ST3BUGS)) { - if (period < 16.239270) { /* A6 */ - period = 16.239270; - } - } - - linear_bend = libxmp_period_to_bend(ctx, period + vibrato, xc->note, - xc->per_adj); - - if (TEST_NOTE(NOTE_GLISSANDO) && TEST(TONEPORTA)) { - if (linear_bend > 0) { - linear_bend = (linear_bend + 6400) / 12800 * 12800; - } else if (linear_bend < 0) { - linear_bend = (linear_bend - 6400) / 12800 * 12800; - } - } - - if (HAS_QUIRK(QUIRK_FT2BUGS)) { - if (arp) { - /* OpenMPT ArpSlide.xm */ - linear_bend = linear_bend / 12800 * 12800 + - xc->finetune * 100; - - /* OpenMPT ArpeggioClamp.xm */ - if (xc->note + arp > 107) { - if (p->speed - (p->frame % p->speed) > 0) { - arp = 108 - xc->note; - } - } - } - } - - /* Envelope */ - - if (xc->f_idx >= 0 && (~instrument->fei.flg & XMP_ENVELOPE_FLT)) { - /* IT pitch envelopes are always linear, even in Amiga period - * mode. Each unit in the envelope scale is 1/25 semitone. - */ - linear_bend += frq_envelope << 7; - } - - /* Arpeggio */ - - if (arp != 0) { - linear_bend += (100 << 7) * arp; - - /* OpenMPT ArpWrapAround.mod */ - if (HAS_QUIRK(QUIRK_PROTRACK)) { - if (xc->note + arp > MAX_NOTE_MOD + 1) { - linear_bend -= 12800 * (3 * 12); - } else if (xc->note + arp > MAX_NOTE_MOD) { - libxmp_virt_setvol(ctx, chn, 0); - } - } - } - - -#ifndef LIBXMP_CORE_PLAYER - linear_bend += libxmp_extras_get_linear_bend(ctx, xc); -#endif - - period = libxmp_note_to_period_mix(xc->note, linear_bend); - libxmp_virt_setperiod(ctx, chn, period); - - /* For xmp_get_frame_info() */ - xc->info_pitchbend = linear_bend >> 7; - xc->info_period = (int) (period * 4096); - - if (IS_PERIOD_MODRNG()) { - CLAMP(xc->info_period, - (int) (libxmp_note_to_period(ctx, MAX_NOTE_MOD, xc->finetune, 0) * 4096), - (int) (libxmp_note_to_period(ctx, MIN_NOTE_MOD, xc->finetune, 0) * 4096)); - } else if (xc->info_period < (1 << 12)) { - xc->info_period = (1 << 12); - } - - -#ifndef LIBXMP_CORE_DISABLE_IT - - /* Process filter */ - - if (!HAS_QUIRK(QUIRK_FILTER)) { - return; - } - - if (xc->f_idx >= 0 && (instrument->fei.flg & XMP_ENVELOPE_FLT)) { - if (frq_envelope < 0xfe) { - xc->filter.envelope = frq_envelope; - } - cutoff = xc->filter.cutoff * xc->filter.envelope >> 8; - } else { - cutoff = xc->filter.cutoff; - } - resonance = xc->filter.resonance; - - if (cutoff > 0xff) { - cutoff = 0xff; - } else if (cutoff < 0xff) { - int a0, b0, b1; - libxmp_filter_setup(s->freq, cutoff, resonance, &a0, &b0, &b1); - libxmp_virt_seteffect(ctx, chn, DSP_EFFECT_FILTER_A0, a0); - libxmp_virt_seteffect(ctx, chn, DSP_EFFECT_FILTER_B0, b0); - libxmp_virt_seteffect(ctx, chn, DSP_EFFECT_FILTER_B1, b1); - libxmp_virt_seteffect(ctx, chn, DSP_EFFECT_RESONANCE, resonance); - } - - /* Always set cutoff */ - libxmp_virt_seteffect(ctx, chn, DSP_EFFECT_CUTOFF, cutoff); - -#endif -} - -static void process_pan(struct context_data *ctx, int chn, int act) -{ - struct player_data *p = &ctx->p; - struct module_data *m = &ctx->m; - struct mixer_data *s = &ctx->s; - struct channel_data *xc = &p->xc_data[chn]; - struct xmp_instrument *instrument; - int finalpan, panbrello = 0; - int pan_envelope; - int channel_pan; - - instrument = libxmp_get_instrument(ctx, xc->ins); - - if (!TEST_PER(PENV_PAUSE)) { - xc->p_idx = update_envelope(&instrument->pei, xc->p_idx, - DOENV_RELEASE, TEST(KEY_OFF), IS_PLAYER_MODE_IT()); - } - pan_envelope = get_envelope(&instrument->pei, xc->p_idx, 32); - -#ifndef LIBXMP_CORE_DISABLE_IT - if (TEST(PANBRELLO)) { - panbrello = libxmp_lfo_get(ctx, &xc->panbrello.lfo, 0) / 512; - if (is_first_frame(ctx)) { - libxmp_lfo_update(&xc->panbrello.lfo); - } - } -#endif - - channel_pan = xc->pan.val; - -#if 0 -#ifdef LIBXMP_PAULA_SIMULATOR - /* Always use 100% pan separation in Amiga mode */ - if (p->flags & XMP_FLAGS_A500) { - if (IS_AMIGA_MOD()) { - channel_pan = channel_pan < 0x80 ? 0 : 0xff; - } - } -#endif -#endif - - finalpan = channel_pan + panbrello + (pan_envelope - 32) * - (128 - abs(xc->pan.val - 128)) / 32; - - if (IS_PLAYER_MODE_IT()) { - finalpan = finalpan + xc->rpv * 4; - } - - CLAMP(finalpan, 0, 255); - - if (s->format & XMP_FORMAT_MONO || xc->pan.surround) { - finalpan = 0; - } else { - finalpan = (finalpan - 0x80) * s->mix / 100; - } - - xc->info_finalpan = finalpan + 0x80; - - if (xc->pan.surround) { - libxmp_virt_setpan(ctx, chn, PAN_SURROUND); - } else { - libxmp_virt_setpan(ctx, chn, finalpan); - } -} - -static void update_volume(struct context_data *ctx, int chn) -{ - struct player_data *p = &ctx->p; - struct module_data *m = &ctx->m; -#ifndef LIBXMP_CORE_DISABLE_IT - struct flow_control *f = &p->flow; -#endif - struct channel_data *xc = &p->xc_data[chn]; - - /* Volume slides happen in all frames but the first, except when the - * "volume slide on all frames" flag is set. - */ - if (p->frame % p->speed != 0 || HAS_QUIRK(QUIRK_VSALL)) { - if (TEST(GVOL_SLIDE)) { - p->gvol += xc->gvol.slide; - } - - if (TEST(VOL_SLIDE) || TEST_PER(VOL_SLIDE)) { - xc->volume += xc->vol.slide; - } - -#ifndef LIBXMP_CORE_PLAYER - if (TEST_PER(VOL_SLIDE)) { - if (xc->vol.slide > 0 && xc->volume > m->volbase) { - xc->volume = m->volbase; - RESET_PER(VOL_SLIDE); - } - if (xc->vol.slide < 0 && xc->volume < 0) { - xc->volume = 0; - RESET_PER(VOL_SLIDE); - } - } -#endif - - if (TEST(VOL_SLIDE_2)) { - xc->volume += xc->vol.slide2; - } - if (TEST(TRK_VSLIDE)) { - xc->mastervol += xc->trackvol.slide; - } - } - - if (p->frame % p->speed == 0) { - /* Process "fine" effects */ - if (TEST(FINE_VOLS)) { - xc->volume += xc->vol.fslide; - } - -#ifndef LIBXMP_CORE_DISABLE_IT - if (TEST(FINE_VOLS_2)) { - /* OpenMPT FineVolColSlide.it: - * Unlike fine volume slides in the effect column, - * fine volume slides in the volume column are only - * ever executed on the first tick -- not on multiples - * of the first tick if there is a pattern delay. - */ - if (!f->rowdelay_set || f->rowdelay_set & 2) { - xc->volume += xc->vol.fslide2; - } - } - f->rowdelay_set &= ~2; -#endif - - if (TEST(TRK_FVSLIDE)) { - xc->mastervol += xc->trackvol.fslide; - } - - if (TEST(GVOL_SLIDE)) { - p->gvol += xc->gvol.fslide; - } - } - - /* Clamp volumes */ - CLAMP(xc->volume, 0, m->volbase); - CLAMP(p->gvol, 0, m->gvolbase); - CLAMP(xc->mastervol, 0, m->volbase); - - if (xc->split) { - p->xc_data[xc->pair].volume = xc->volume; - } -} - -static void update_frequency(struct context_data *ctx, int chn) -{ - struct player_data *p = &ctx->p; - struct module_data *m = &ctx->m; - struct channel_data *xc = &p->xc_data[chn]; - - if (!is_first_frame(ctx) || HAS_QUIRK(QUIRK_PBALL)) { - if (TEST(PITCHBEND) || TEST_PER(PITCHBEND)) { - xc->period += xc->freq.slide; - if (HAS_QUIRK(QUIRK_PROTRACK)) { - xc->porta.target = xc->period; - } - } - - /* Do tone portamento */ - if (TEST(TONEPORTA) || TEST_PER(TONEPORTA)) { - if (xc->porta.target > 0) { - int end = 0; - if (xc->porta.dir > 0) { - xc->period += xc->porta.slide; - if (xc->period >= xc->porta.target) - end = 1; - } else { - xc->period -= xc->porta.slide; - if (xc->period <= xc->porta.target) - end = 1; - } - - if (end) { - /* reached end */ - xc->period = xc->porta.target; - xc->porta.dir = 0; - RESET(TONEPORTA); - RESET_PER(TONEPORTA); - - if (HAS_QUIRK(QUIRK_PROTRACK)) { - xc->porta.target = -1; - } - } - } - } - } - - if (is_first_frame(ctx)) { - if (TEST(FINE_BEND)) { - xc->period += xc->freq.fslide; - } - -#ifndef LIBXMP_CORE_PLAYER - if (TEST(FINE_NSLIDE)) { - xc->note += xc->noteslide.fslide; - xc->period = libxmp_note_to_period(ctx, xc->note, - xc->finetune, xc->per_adj); - } -#endif - } - - switch (m->period_type) { - case PERIOD_LINEAR: - CLAMP(xc->period, MIN_PERIOD_L, MAX_PERIOD_L); - break; - case PERIOD_MODRNG: - CLAMP(xc->period, - libxmp_note_to_period(ctx, MAX_NOTE_MOD, xc->finetune, 0), - libxmp_note_to_period(ctx, MIN_NOTE_MOD, xc->finetune, 0)); - break; - } - - xc->arpeggio.count++; - xc->arpeggio.count %= xc->arpeggio.size; - - /* Check for invalid periods (from Toru Egashira's NSPmod) - * panic.s3m has negative periods - * ambio.it uses low (~8) period values - */ - if (xc->period < 0.25) { - libxmp_virt_setvol(ctx, chn, 0); - } -} - -static void update_pan(struct context_data *ctx, int chn) -{ - struct player_data *p = &ctx->p; - struct channel_data *xc = &p->xc_data[chn]; - - if (TEST(PAN_SLIDE)) { - if (is_first_frame(ctx)) { - xc->pan.val += xc->pan.fslide; - } else { - xc->pan.val += xc->pan.slide; - } - - if (xc->pan.val < 0) { - xc->pan.val = 0; - } else if (xc->pan.val > 0xff) { - xc->pan.val = 0xff; - } - } -} - -static void play_channel(struct context_data *ctx, int chn) -{ - struct player_data *p = &ctx->p; - struct smix_data *smix = &ctx->smix; - struct module_data *m = &ctx->m; - struct xmp_module *mod = &m->mod; - struct channel_data *xc = &p->xc_data[chn]; - int act; - - xc->info_finalvol = 0; - -#ifndef LIBXMP_CORE_DISABLE_IT - /* IT tempo slide */ - if (!is_first_frame(ctx) && TEST(TEMPO_SLIDE)) { - p->bpm += xc->tempo.slide; - CLAMP(p->bpm, 0x20, 0xff); - } -#endif - - /* Do delay */ - if (xc->delay > 0) { - if (--xc->delay == 0) { - libxmp_read_event(ctx, &xc->delayed_event, chn); - } - } - - act = libxmp_virt_cstat(ctx, chn); - if (act == VIRT_INVALID) { - /* We need this to keep processing global volume slides */ - update_volume(ctx, chn); - return; - } - - if (p->frame == 0 && act != VIRT_ACTIVE) { - if (!IS_VALID_INSTRUMENT_OR_SFX(xc->ins) || act == VIRT_ACTION_CUT) { - libxmp_virt_resetchannel(ctx, chn); - return; - } - } - - if (!IS_VALID_INSTRUMENT_OR_SFX(xc->ins)) - return; - -#ifndef LIBXMP_CORE_PLAYER - libxmp_play_extras(ctx, xc, chn); -#endif - - /* Do cut/retrig */ - if (TEST(RETRIG)) { - int cond = HAS_QUIRK(QUIRK_S3MRTG) ? - --xc->retrig.count <= 0 : - --xc->retrig.count == 0; - - if (cond) { - if (xc->retrig.type < 0x10) { - /* don't retrig on cut */ - libxmp_virt_voicepos(ctx, chn, 0); - } else { - SET_NOTE(NOTE_END); - } - xc->volume += rval[xc->retrig.type].s; - xc->volume *= rval[xc->retrig.type].m; - xc->volume /= rval[xc->retrig.type].d; - xc->retrig.count = LSN(xc->retrig.val); - } - } - - /* Do keyoff */ - if (xc->keyoff) { - if (--xc->keyoff == 0) - SET_NOTE(NOTE_RELEASE); - } - - libxmp_virt_release(ctx, chn, TEST_NOTE(NOTE_RELEASE)); - - process_volume(ctx, chn, act); - process_frequency(ctx, chn, act); - process_pan(ctx, chn, act); - - update_volume(ctx, chn); - update_frequency(ctx, chn); - update_pan(ctx, chn); - -#ifndef LIBXMP_CORE_PLAYER - if (HAS_QUIRK(QUIRK_PROTRACK) && xc->ins < mod->ins) { - update_invloop(m, xc); - } -#endif - - if (TEST_NOTE(NOTE_SUSEXIT)) { - SET_NOTE(NOTE_RELEASE); - } - - xc->info_position = (int) libxmp_virt_getvoicepos(ctx, chn); -} - -/* - * Event injection - */ - -static void inject_event(struct context_data *ctx) -{ - struct player_data *p = &ctx->p; - struct module_data *m = &ctx->m; - struct xmp_module *mod = &m->mod; - struct smix_data *smix = &ctx->smix; - int chn; - - for (chn = 0; chn < mod->chn + smix->chn; chn++) { - struct xmp_event *e = &p->inject_event[chn]; - if (e->_flag > 0) { - libxmp_read_event(ctx, e, chn); - e->_flag = 0; - } - } -} - -/* - * Sequencing - */ - -static void next_order(struct context_data *ctx) -{ - struct player_data *p = &ctx->p; - struct flow_control *f = &p->flow; - struct module_data *m = &ctx->m; - struct xmp_module *mod = &m->mod; - int mark; - - do { - p->ord++; - - /* Restart module */ - mark = HAS_QUIRK(QUIRK_MARKER) && mod->xxo[p->ord] == 0xff; - if (p->ord >= mod->len || mark) { - if (mod->rst > mod->len || - mod->xxo[mod->rst] >= mod->pat || - p->ord < m->seq_data[p->sequence].entry_point) { - p->ord = m->seq_data[p->sequence].entry_point; - } else { - if (libxmp_get_sequence(ctx, mod->rst) == p->sequence) { - p->ord = mod->rst; - } else { - p->ord = m->seq_data[p->sequence].entry_point; - } - } - - p->gvol = m->xxo_info[p->ord].gvl; - } - } while (mod->xxo[p->ord] >= mod->pat); - - p->current_time = m->xxo_info[p->ord].time; - - f->num_rows = mod->xxp[mod->xxo[p->ord]]->rows; - if (f->jumpline >= f->num_rows) - f->jumpline = 0; - p->row = f->jumpline; - f->jumpline = 0; - - p->pos = p->ord; - p->frame = 0; - -#ifndef LIBXMP_CORE_PLAYER - /* Reset persistent effects at new pattern */ - if (HAS_QUIRK(QUIRK_PERPAT)) { - int chn; - for (chn = 0; chn < mod->chn; chn++) { - p->xc_data[chn].per_flags = 0; - } - } -#endif -} - -static void next_row(struct context_data *ctx) -{ - struct player_data *p = &ctx->p; - struct flow_control *f = &p->flow; - - p->frame = 0; - f->delay = 0; - - if (f->pbreak) { - f->pbreak = 0; - - if (f->jump != -1) { - p->ord = f->jump - 1; - f->jump = -1; - } - - next_order(ctx); - } else { - if (f->loop_chn) { - p->row = f->loop[f->loop_chn - 1].start - 1; - f->loop_chn = 0; - } - - if (f->rowdelay == 0) { - p->row++; - f->rowdelay_set = 0; - } else { - f->rowdelay--; - } - - /* check end of pattern */ - if (p->row >= f->num_rows) { - next_order(ctx); - } - } -} - -#ifndef LIBXMP_CORE_DISABLE_IT - -/* - * Set note action for libxmp_virt_pastnote - */ -void libxmp_player_set_release(struct context_data *ctx, int chn) -{ - struct player_data *p = &ctx->p; - struct channel_data *xc = &p->xc_data[chn]; - - SET_NOTE(NOTE_RELEASE); -} - -void libxmp_player_set_fadeout(struct context_data *ctx, int chn) -{ - struct player_data *p = &ctx->p; - struct channel_data *xc = &p->xc_data[chn]; - - SET_NOTE(NOTE_FADEOUT); -} - -#endif - -static void update_from_ord_info(struct context_data *ctx) -{ - struct player_data *p = &ctx->p; - struct module_data *m = &ctx->m; - struct ord_data *oinfo = &m->xxo_info[p->ord]; - - if (oinfo->speed) - p->speed = oinfo->speed; - p->bpm = oinfo->bpm; - p->gvol = oinfo->gvl; - p->current_time = oinfo->time; - p->frame_time = m->time_factor * m->rrate / p->bpm; - -#ifndef LIBXMP_CORE_PLAYER - p->st26_speed = oinfo->st26_speed; -#endif -} - -int xmp_start_player(xmp_context opaque, int rate, int format) -{ - struct context_data *ctx = (struct context_data *)opaque; - struct player_data *p = &ctx->p; - struct smix_data *smix = &ctx->smix; - struct module_data *m = &ctx->m; - struct xmp_module *mod = &m->mod; - struct flow_control *f = &p->flow; - int i; - int ret = 0; - - if (rate < XMP_MIN_SRATE || rate > XMP_MAX_SRATE) - return -XMP_ERROR_INVALID; - - if (ctx->state < XMP_STATE_LOADED) - return -XMP_ERROR_STATE; - - if (ctx->state > XMP_STATE_LOADED) - xmp_end_player(opaque); - - if (libxmp_mixer_on(ctx, rate, format, m->c4rate) < 0) - return -XMP_ERROR_INTERNAL; - - p->master_vol = 100; - p->smix_vol = 100; - p->gvol = m->volbase; - p->pos = p->ord = 0; - p->frame = -1; - p->row = 0; - p->current_time = 0; - p->loop_count = 0; - p->sequence = 0; - - /* 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; - } - - /* Skip invalid patterns at start (the seventh laboratory.it) */ - while (p->ord < mod->len && mod->xxo[p->ord] >= mod->pat) { - p->ord++; - } - /* Check if all positions skipped */ - if (p->ord >= mod->len) { - mod->len = 0; - } - - if (mod->len == 0 || mod->chn == 0) { - /* set variables to sane state */ - p->ord = p->scan[0].ord = 0; - p->row = p->scan[0].row = 0; - f->end_point = 0; - f->num_rows = 0; - } else { - f->num_rows = mod->xxp[mod->xxo[p->ord]]->rows; - f->end_point = p->scan[0].num; - } - - update_from_ord_info(ctx); - - if (libxmp_virt_on(ctx, mod->chn + smix->chn) != 0) { - ret = -XMP_ERROR_INTERNAL; - goto err; - } - - f->delay = 0; - f->jumpline = 0; - f->jump = -1; - f->pbreak = 0; - f->rowdelay_set = 0; - - f->loop = (struct pattern_loop *)calloc(p->virt.virt_channels, sizeof(struct pattern_loop)); - if (f->loop == NULL) { - ret = -XMP_ERROR_SYSTEM; - goto err; - } - - p->xc_data = (struct channel_data *)calloc(p->virt.virt_channels, sizeof(struct channel_data)); - if (p->xc_data == NULL) { - ret = -XMP_ERROR_SYSTEM; - 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]; - if (libxmp_new_channel_extras(ctx, xc) < 0) - goto err2; - } -#endif - reset_channels(ctx); - - ctx->state = XMP_STATE_PLAYING; - - return 0; - -#ifndef LIBXMP_CORE_PLAYER - err2: - free(p->xc_data); -#endif - err1: - free(f->loop); - err: - return ret; -} - -static void check_end_of_module(struct context_data *ctx) -{ - struct player_data *p = &ctx->p; - struct flow_control *f = &p->flow; - - /* check end of module */ - if (p->ord == p->scan[p->sequence].ord && - p->row == p->scan[p->sequence].row) { - if (f->end_point == 0) { - p->loop_count++; - f->end_point = p->scan[p->sequence].num; - /* return -1; */ - } - f->end_point--; - } -} - -int xmp_play_frame(xmp_context opaque) -{ - 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 i; - - if (ctx->state < XMP_STATE_PLAYING) - return -XMP_ERROR_STATE; - - if (mod->len <= 0) { - return -XMP_END; - } - - if (HAS_QUIRK(QUIRK_MARKER) && mod->xxo[p->ord] == 0xff) { - return -XMP_END; - } - - /* check reposition */ - if (p->ord != p->pos) { - int start = m->seq_data[p->sequence].entry_point; - - if (p->pos == -2) { /* set by xmp_module_stop */ - return -XMP_END; /* that's all folks */ - } - - if (p->pos == -1) { - /* restart sequence */ - p->pos = start; - } - - if (p->pos == start) { - f->end_point = p->scan[p->sequence].num; - } - - /* Check if lands after a loop point */ - if (p->pos > p->scan[p->sequence].ord) { - f->end_point = 0; - } - - f->jumpline = 0; - f->jump = -1; - - p->ord = p->pos - 1; - - /* Stay inside our subsong */ - if (p->ord < start) { - p->ord = start - 1; - } - - next_order(ctx); - - update_from_ord_info(ctx); - - libxmp_virt_reset(ctx); - reset_channels(ctx); - } else { - p->frame++; - if (p->frame >= (p->speed * (1 + f->delay))) { - /* If break during pattern delay, next row is skipped. - * See corruption.mod order 1D (pattern 0D) last line: - * EE2 + D31 ignores D00 in order 1C line 31. Reported - * by The Welder , Jan 14 2012 - */ - if (HAS_QUIRK(QUIRK_PROTRACK) && f->delay && f->pbreak) - { - next_row(ctx); - check_end_of_module(ctx); - } - next_row(ctx); - } - } - - for (i = 0; i < mod->chn; i++) { - struct channel_data *xc = &p->xc_data[i]; - RESET(KEY_OFF); - } - - /* check new row */ - - if (p->frame == 0) { /* first frame in row */ - check_end_of_module(ctx); - read_row(ctx, mod->xxo[p->ord], p->row); - -#ifndef LIBXMP_CORE_PLAYER - if (p->st26_speed) { - if (p->st26_speed & 0x10000) { - p->speed = (p->st26_speed & 0xff00) >> 8; - } else { - p->speed = p->st26_speed & 0xff; - } - p->st26_speed ^= 0x10000; - } -#endif - } - - inject_event(ctx); - - /* play_frame */ - for (i = 0; i < p->virt.virt_channels; i++) { - play_channel(ctx, i); - } - - p->frame_time = m->time_factor * m->rrate / p->bpm; - p->current_time += p->frame_time; - - libxmp_mixer_softmixer(ctx); - - return 0; -} - -int xmp_play_buffer(xmp_context opaque, void *out_buffer, int size, int loop) -{ - struct context_data *ctx = (struct context_data *)opaque; - struct player_data *p = &ctx->p; - int ret = 0, filled = 0, copy_size; - struct xmp_frame_info fi; - - /* Reset internal state - * Syncs buffer start with frame start */ - if (out_buffer == NULL) { - p->loop_count = 0; - p->buffer_data.consumed = 0; - p->buffer_data.in_size = 0; - return 0; - } - - if (ctx->state < XMP_STATE_PLAYING) - return -XMP_ERROR_STATE; - - /* Fill buffer */ - while (filled < size) { - /* Check if buffer full */ - if (p->buffer_data.consumed == p->buffer_data.in_size) { - ret = xmp_play_frame(opaque); - xmp_get_frame_info(opaque, &fi); - - /* Check end of module */ - if (ret < 0 || (loop > 0 && fi.loop_count >= loop)) { - /* Start of frame, return end of replay */ - if (filled == 0) { - p->buffer_data.consumed = 0; - p->buffer_data.in_size = 0; - return -1; - } - - /* Fill remaining of this buffer */ - memset((char *)out_buffer + filled, 0, size - filled); - return 0; - } - - p->buffer_data.consumed = 0; - p->buffer_data.in_buffer = (char *)fi.buffer; - p->buffer_data.in_size = fi.buffer_size; - } - - /* Copy frame data to user buffer */ - copy_size = MIN(size - filled, p->buffer_data.in_size - - p->buffer_data.consumed); - memcpy((char *)out_buffer + filled, p->buffer_data.in_buffer + - p->buffer_data.consumed, copy_size); - p->buffer_data.consumed += copy_size; - filled += copy_size; - } - - return ret; -} - -void xmp_end_player(xmp_context opaque) -{ - struct context_data *ctx = (struct context_data *)opaque; - struct player_data *p = &ctx->p; - struct flow_control *f = &p->flow; -#ifndef LIBXMP_CORE_PLAYER - struct channel_data *xc; - int i; -#endif - - if (ctx->state < XMP_STATE_PLAYING) - return; - - ctx->state = XMP_STATE_LOADED; - -#ifndef LIBXMP_CORE_PLAYER - /* Free channel extras */ - for (i = 0; i < p->virt.virt_channels; i++) { - xc = &p->xc_data[i]; - libxmp_release_channel_extras(ctx, xc); - } -#endif - - libxmp_virt_off(ctx); - - free(p->xc_data); - free(f->loop); - - p->xc_data = NULL; - f->loop = NULL; - - libxmp_mixer_off(ctx); -} - -void xmp_get_module_info(xmp_context opaque, struct xmp_module_info *info) -{ - struct context_data *ctx = (struct context_data *)opaque; - struct module_data *m = &ctx->m; - struct xmp_module *mod = &m->mod; - - if (ctx->state < XMP_STATE_LOADED) - return; - - memcpy(info->md5, m->md5, 16); - info->mod = mod; - info->comment = m->comment; - info->num_sequences = m->num_sequences; - info->seq_data = m->seq_data; - info->vol_base = m->volbase; -} - -void xmp_get_frame_info(xmp_context opaque, struct xmp_frame_info *info) -{ - struct context_data *ctx = (struct context_data *)opaque; - struct player_data *p = &ctx->p; - struct mixer_data *s = &ctx->s; - struct module_data *m = &ctx->m; - struct xmp_module *mod = &m->mod; - int chn, i; - - if (ctx->state < XMP_STATE_LOADED) - return; - - chn = mod->chn; - - if (p->pos >= 0 && p->pos < mod->len) { - info->pos = p->pos; - } else { - info->pos = 0; - } - - info->pattern = mod->xxo[info->pos]; - - if (info->pattern < mod->pat) { - info->num_rows = mod->xxp[info->pattern]->rows; - } else { - info->num_rows = 0; - } - - info->row = p->row; - info->frame = p->frame; - info->speed = p->speed; - info->bpm = p->bpm; - info->total_time = p->scan[p->sequence].time; - info->frame_time = (int) (p->frame_time * 1000); - info->time = (int) p->current_time; - info->buffer = s->buffer; - - info->total_size = XMP_MAX_FRAMESIZE; - info->buffer_size = s->ticksize; - if (~s->format & XMP_FORMAT_MONO) { - info->buffer_size *= 2; - } - if (~s->format & XMP_FORMAT_8BIT) { - info->buffer_size *= 2; - } - - info->volume = p->gvol; - info->loop_count = p->loop_count; - info->virt_channels = p->virt.virt_channels; - info->virt_used = p->virt.virt_used; - - info->sequence = p->sequence; - - if (p->xc_data != NULL) { - for (i = 0; i < chn; i++) { - struct channel_data *c = &p->xc_data[i]; - struct xmp_channel_info *ci = &info->channel_info[i]; - struct xmp_track *track; - struct xmp_event *event; - int trk; - - ci->note = c->key; - ci->pitchbend = c->info_pitchbend; - ci->period = c->info_period; - ci->position = c->info_position; - ci->instrument = c->ins; - ci->sample = c->smp; - ci->volume = c->info_finalvol >> 4; - ci->pan = c->info_finalpan; - ci->reserved = 0; - memset(&ci->event, 0, sizeof(*event)); - - if (info->pattern < mod->pat && info->row < info->num_rows) { - trk = mod->xxp[info->pattern]->index[i]; - track = mod->xxt[trk]; - if (info->row < track->rows) { - event = &track->event[info->row]; - memcpy(&ci->event, event, sizeof(*event)); - } - } - } - } -} diff --git a/source/libxmp-lite/src/player.h b/source/libxmp-lite/src/player.h deleted file mode 100644 index 4b46e608e..000000000 --- a/source/libxmp-lite/src/player.h +++ /dev/null @@ -1,258 +0,0 @@ -#ifndef LIBXMP_PLAYER_H -#define LIBXMP_PLAYER_H - -#include "lfo.h" - -/* Quirk control */ -#define HAS_QUIRK(x) (m->quirk & (x)) - -/* Channel flag control */ -#define SET(f) SET_FLAG(xc->flags,(f)) -#define RESET(f) RESET_FLAG(xc->flags,(f)) -#define TEST(f) TEST_FLAG(xc->flags,(f)) - -/* Persistent effect flag control */ -#define SET_PER(f) SET_FLAG(xc->per_flags,(f)) -#define RESET_PER(f) RESET_FLAG(xc->per_flags,(f)) -#define TEST_PER(f) TEST_FLAG(xc->per_flags,(f)) - -/* Note flag control */ -#define SET_NOTE(f) SET_FLAG(xc->note_flags,(f)) -#define RESET_NOTE(f) RESET_FLAG(xc->note_flags,(f)) -#define TEST_NOTE(f) TEST_FLAG(xc->note_flags,(f)) - -struct retrig_control { - int s; - int m; - int d; -}; - -/* The following macros are used to set the flags for each channel */ -#define VOL_SLIDE (1 << 0) -#define PAN_SLIDE (1 << 1) -#define TONEPORTA (1 << 2) -#define PITCHBEND (1 << 3) -#define VIBRATO (1 << 4) -#define TREMOLO (1 << 5) -#define FINE_VOLS (1 << 6) -#define FINE_BEND (1 << 7) -#define OFFSET (1 << 8) -#define TRK_VSLIDE (1 << 9) -#define TRK_FVSLIDE (1 << 10) -#define NEW_INS (1 << 11) -#define NEW_VOL (1 << 12) -#define VOL_SLIDE_2 (1 << 13) -#define NOTE_SLIDE (1 << 14) -#define FINE_NSLIDE (1 << 15) -#define NEW_NOTE (1 << 16) -#define FINE_TPORTA (1 << 17) -#define RETRIG (1 << 18) -#define PANBRELLO (1 << 19) -#define GVOL_SLIDE (1 << 20) -#define TEMPO_SLIDE (1 << 21) -#define VENV_PAUSE (1 << 22) -#define PENV_PAUSE (1 << 23) -#define FENV_PAUSE (1 << 24) -#define FINE_VOLS_2 (1 << 25) -#define KEY_OFF (1 << 26) /* for IT release on envloop end */ -#define TREMOR (1 << 27) /* for XM tremor */ - -#define NOTE_FADEOUT (1 << 0) -#define NOTE_RELEASE (1 << 1) -#define NOTE_END (1 << 2) -#define NOTE_CUT (1 << 3) -#define NOTE_ENV_END (1 << 4) -#define NOTE_SAMPLE_END (1 << 5) -#define NOTE_SET (1 << 6) /* for IT portamento after keyoff */ -#define NOTE_SUSEXIT (1 << 7) /* for delayed note release */ -#define NOTE_KEY_CUT (1 << 8) /* note cut with XMP_KEY_CUT event */ -#define NOTE_GLISSANDO (1 << 9) - -#define IS_VALID_INSTRUMENT(x) ((uint32)(x) < mod->ins && mod->xxi[(x)].nsm > 0) -#define IS_VALID_INSTRUMENT_OR_SFX(x) (((uint32)(x) < mod->ins && mod->xxi[(x)].nsm > 0) || (smix->ins > 0 && (uint32)(x) < mod->ins + smix->ins)) - -struct instrument_vibrato { - int phase; - int sweep; -}; - -struct channel_data { - int flags; /* Channel flags */ - int per_flags; /* Persistent effect channel flags */ - int note_flags; /* Note release, fadeout or end */ - int note; /* Note number */ - int key; /* Key number */ - double period; /* Amiga or linear period */ - double per_adj; /* MED period/pitch adjustment factor hack */ - int finetune; /* Guess what */ - int ins; /* Instrument number */ - int old_ins; /* Last instruemnt */ - int smp; /* Sample number */ - int mastervol; /* Master vol -- for IT track vol effect */ - int delay; /* Note delay in frames */ - int keyoff; /* Key off counter */ - int fadeout; /* Current fadeout (release) value */ - int ins_fade; /* Instrument fadeout value */ - int volume; /* Current volume */ - int gvl; /* Global volume for instrument for IT */ - - int rvv; /* Random volume variation */ - int rpv; /* Random pan variation */ - - uint8 split; /* Split channel */ - uint8 pair; /* Split channel pair */ - - int v_idx; /* Volume envelope index */ - int p_idx; /* Pan envelope index */ - int f_idx; /* Freq envelope index */ - - int key_porta; /* Key number for portamento target - * -- needed to handle IT portamento xpo */ - struct { - struct lfo lfo; - int memory; - } vibrato; - - struct { - struct lfo lfo; - int memory; - } tremolo; - -#ifndef LIBXMP_CORE_DISABLE_IT - struct { - struct lfo lfo; - int memory; - } panbrello; -#endif - - struct { - int8 val[16]; /* 16 for Smaksak MegaArps */ - int size; - int count; - int memory; - } arpeggio; - - struct { - struct lfo lfo; - int sweep; - } insvib; - - struct { - int val; - int val2; /* For fx9 bug emulation */ - int memory; - } offset; - - struct { - int val; /* Retrig value */ - int count; /* Retrig counter */ - int type; /* Retrig type */ - } retrig; - - struct { - uint8 up,down; /* Tremor value */ - uint8 count; /* Tremor counter */ - uint8 memory; /* Tremor memory */ - } tremor; - - struct { - int slide; /* Volume slide value */ - int fslide; /* Fine volume slide value */ - int slide2; /* Volume slide value */ - int memory; /* Volume slide effect memory */ -#ifndef LIBXMP_CORE_DISABLE_IT - int fslide2; - int memory2; /* Volume slide effect memory */ -#endif - } vol; - - struct { - int up_memory; /* Fine volume slide up memory (XM) */ - int down_memory;/* Fine volume slide up memory (XM) */ - } fine_vol; - - struct { - int slide; /* Global volume slide value */ - int fslide; /* Fine global volume slide value */ - int memory; /* Global volume memory is saved per channel */ - } gvol; - - struct { - int slide; /* Track volume slide value */ - int fslide; /* Track fine volume slide value */ - int memory; /* Track volume slide effect memory */ - } trackvol; - - struct { - int slide; /* Frequency slide value */ - double fslide; /* Fine frequency slide value */ - int memory; /* Portamento effect memory */ - } freq; - - struct { - double target; /* Target period for tone portamento */ - int dir; /* Tone portamento up/down directionh */ - int slide; /* Delta for tone portamento */ - int memory; /* Tone portamento effect memory */ - } porta; - - struct { - int up_memory; /* FT2 has separate memories for these */ - int down_memory;/* cases (see Porta-LinkMem.xm) */ - } fine_porta; - - struct { - int val; /* Current pan value */ - int slide; /* Pan slide value */ - int fslide; /* Pan fine slide value */ - int memory; /* Pan slide effect memory */ - int surround; /* Surround channel flag */ - } pan; - - struct { - int speed; - int count; - int pos; - } invloop; - -#ifndef LIBXMP_CORE_DISABLE_IT - struct { - int slide; /* IT tempo slide */ - } tempo; - - struct { - int cutoff; /* IT filter cutoff frequency */ - int resonance; /* IT filter resonance */ - int envelope; /* IT filter envelope */ - } filter; - -#endif - -#ifndef LIBXMP_CORE_PLAYER - struct { - int slide; /* PTM note slide amount */ - int fslide; /* OKT fine note slide amount */ - int speed; /* PTM note slide speed */ - int count; /* PTM note slide counter */ - } noteslide; - - void *extra; -#endif - - struct xmp_event delayed_event; - int delayed_ins; /* IT save instrument emulation */ - - int info_period; /* Period */ - int info_pitchbend; /* Linear pitchbend */ - int info_position; /* Position before mixing */ - int info_finalvol; /* Final volume including envelopes */ - int info_finalpan; /* Final pan including envelopes */ -}; - - -void libxmp_process_fx (struct context_data *, struct channel_data *, - int, struct xmp_event *, int); -void libxmp_filter_setup (int, int, int, int*, int*, int *); -int libxmp_read_event (struct context_data *, struct xmp_event *, int); - -#endif /* LIBXMP_PLAYER_H */ diff --git a/source/libxmp-lite/src/precomp_lut.h b/source/libxmp-lite/src/precomp_lut.h deleted file mode 100644 index 67146725d..000000000 --- a/source/libxmp-lite/src/precomp_lut.h +++ /dev/null @@ -1,524 +0,0 @@ -static int16 cubic_spline_lut0[1024] = { - 0, -8, -16, -24, -32, -40, -47, -55, - -63, -71, -78, -86, -94, -101, -109, -117, - -124, -132, -139, -146, -154, -161, -169, -176, - -183, -190, -198, -205, -212, -219, -226, -233, - -240, -247, -254, -261, -268, -275, -282, -289, - -295, -302, -309, -316, -322, -329, -336, -342, - -349, -355, -362, -368, -375, -381, -388, -394, - -400, -407, -413, -419, -425, -432, -438, -444, - -450, -456, -462, -468, -474, -480, -486, -492, - -498, -504, -510, -515, -521, -527, -533, -538, - -544, -550, -555, -561, -566, -572, -577, -583, - -588, -594, -599, -604, -610, -615, -620, -626, - -631, -636, -641, -646, -651, -656, -662, -667, - -672, -677, -682, -686, -691, -696, -701, -706, - -711, -715, -720, -725, -730, -734, -739, -744, - -748, -753, -757, -762, -766, -771, -775, -780, - -784, -788, -793, -797, -801, -806, -810, -814, - -818, -822, -826, -831, -835, -839, -843, -847, - -851, -855, -859, -863, -866, -870, -874, -878, - -882, -886, -889, -893, -897, -900, -904, -908, - -911, -915, -918, -922, -925, -929, -932, -936, - -939, -943, -946, -949, -953, -956, -959, -962, - -966, -969, -972, -975, -978, -981, -984, -987, - -991, -994, -997, -999, -1002, -1005, -1008, -1011, - -1014, -1017, -1020, -1022, -1025, -1028, -1031, -1033, - -1036, -1039, -1041, -1044, -1047, -1049, -1052, -1054, - -1057, -1059, -1062, -1064, -1066, -1069, -1071, -1074, - -1076, -1078, -1080, -1083, -1085, -1087, -1089, -1092, - -1094, -1096, -1098, -1100, -1102, -1104, -1106, -1108, - -1110, -1112, -1114, -1116, -1118, -1120, -1122, -1124, - -1125, -1127, -1129, -1131, -1133, -1134, -1136, -1138, - -1139, -1141, -1143, -1144, -1146, -1147, -1149, -1150, - -1152, -1153, -1155, -1156, -1158, -1159, -1161, -1162, - -1163, -1165, -1166, -1167, -1169, -1170, -1171, -1172, - -1174, -1175, -1176, -1177, -1178, -1179, -1180, -1181, - -1182, -1184, -1185, -1186, -1187, -1187, -1188, -1189, - -1190, -1191, -1192, -1193, -1194, -1195, -1195, -1196, - -1197, -1198, -1198, -1199, -1200, -1200, -1201, -1202, - -1202, -1203, -1204, -1204, -1205, -1205, -1206, -1206, - -1207, -1207, -1208, -1208, -1208, -1209, -1209, -1210, - -1210, -1210, -1211, -1211, -1211, -1212, -1212, -1212, - -1212, -1212, -1213, -1213, -1213, -1213, -1213, -1213, - -1213, -1213, -1214, -1214, -1214, -1214, -1214, -1214, - -1214, -1214, -1213, -1213, -1213, -1213, -1213, -1213, - -1213, -1213, -1212, -1212, -1212, -1212, -1211, -1211, - -1211, -1211, -1210, -1210, -1210, -1209, -1209, -1209, - -1208, -1208, -1207, -1207, -1207, -1206, -1206, -1205, - -1205, -1204, -1204, -1203, -1202, -1202, -1201, -1201, - -1200, -1199, -1199, -1198, -1197, -1197, -1196, -1195, - -1195, -1194, -1193, -1192, -1192, -1191, -1190, -1189, - -1188, -1187, -1187, -1186, -1185, -1184, -1183, -1182, - -1181, -1180, -1179, -1178, -1177, -1176, -1175, -1174, - -1173, -1172, -1171, -1170, -1169, -1168, -1167, -1166, - -1165, -1163, -1162, -1161, -1160, -1159, -1158, -1156, - -1155, -1154, -1153, -1151, -1150, -1149, -1148, -1146, - -1145, -1144, -1142, -1141, -1140, -1138, -1137, -1135, - -1134, -1133, -1131, -1130, -1128, -1127, -1125, -1124, - -1122, -1121, -1119, -1118, -1116, -1115, -1113, -1112, - -1110, -1109, -1107, -1105, -1104, -1102, -1101, -1099, - -1097, -1096, -1094, -1092, -1091, -1089, -1087, -1085, - -1084, -1082, -1080, -1079, -1077, -1075, -1073, -1071, - -1070, -1068, -1066, -1064, -1062, -1061, -1059, -1057, - -1055, -1053, -1051, -1049, -1047, -1046, -1044, -1042, - -1040, -1038, -1036, -1034, -1032, -1030, -1028, -1026, - -1024, -1022, -1020, -1018, -1016, -1014, -1012, -1010, - -1008, -1006, -1004, -1002, -999, -997, -995, -993, - -991, -989, -987, -985, -982, -980, -978, -976, - -974, -972, -969, -967, -965, -963, -961, -958, - -956, -954, -952, -950, -947, -945, -943, -941, - -938, -936, -934, -931, -929, -927, -924, -922, - -920, -918, -915, -913, -911, -908, -906, -903, - -901, -899, -896, -894, -892, -889, -887, -884, - -882, -880, -877, -875, -872, -870, -867, -865, - -863, -860, -858, -855, -853, -850, -848, -845, - -843, -840, -838, -835, -833, -830, -828, -825, - -823, -820, -818, -815, -813, -810, -808, -805, - -803, -800, -798, -795, -793, -790, -787, -785, - -782, -780, -777, -775, -772, -769, -767, -764, - -762, -759, -757, -754, -751, -749, -746, -744, - -741, -738, -736, -733, -730, -728, -725, -723, - -720, -717, -715, -712, -709, -707, -704, -702, - -699, -696, -694, -691, -688, -686, -683, -680, - -678, -675, -672, -670, -667, -665, -662, -659, - -657, -654, -651, -649, -646, -643, -641, -638, - -635, -633, -630, -627, -625, -622, -619, -617, - -614, -611, -609, -606, -603, -601, -598, -595, - -593, -590, -587, -585, -582, -579, -577, -574, - -571, -569, -566, -563, -561, -558, -555, -553, - -550, -547, -545, -542, -539, -537, -534, -531, - -529, -526, -523, -521, -518, -516, -513, -510, - -508, -505, -502, -500, -497, -495, -492, -489, - -487, -484, -481, -479, -476, -474, -471, -468, - -466, -463, -461, -458, -455, -453, -450, -448, - -445, -442, -440, -437, -435, -432, -430, -427, - -424, -422, -419, -417, -414, -412, -409, -407, - -404, -402, -399, -397, -394, -392, -389, -387, - -384, -382, -379, -377, -374, -372, -369, -367, - -364, -362, -359, -357, -354, -352, -349, -347, - -345, -342, -340, -337, -335, -332, -330, -328, - -325, -323, -320, -318, -316, -313, -311, -309, - -306, -304, -302, -299, -297, -295, -292, -290, - -288, -285, -283, -281, -278, -276, -274, -272, - -269, -267, -265, -263, -260, -258, -256, -254, - -251, -249, -247, -245, -243, -240, -238, -236, - -234, -232, -230, -228, -225, -223, -221, -219, - -217, -215, -213, -211, -209, -207, -205, -202, - -200, -198, -196, -194, -192, -190, -188, -186, - -184, -182, -180, -178, -176, -175, -173, -171, - -169, -167, -165, -163, -161, -159, -157, -156, - -154, -152, -150, -148, -146, -145, -143, -141, - -139, -137, -136, -134, -132, -130, -129, -127, - -125, -124, -122, -120, -119, -117, -115, -114, - -112, -110, -109, -107, -106, -104, -102, -101, - -99, -98, -96, -95, -93, -92, -90, -89, - -87, -86, -84, -83, -82, -80, -79, -77, - -76, -75, -73, -72, -70, -69, -68, -67, - -65, -64, -63, -61, -60, -59, -58, -57, - -55, -54, -53, -52, -51, -49, -48, -47, - -46, -45, -44, -43, -42, -41, -40, -39, - -38, -37, -36, -35, -34, -33, -32, -31, - -30, -29, -28, -27, -26, -26, -25, -24, - -23, -22, -22, -21, -20, -19, -19, -18, - -17, -16, -16, -15, -14, -14, -13, -13, - -12, -11, -11, -10, -10, -9, -9, -8, - -8, -7, -7, -6, -6, -6, -5, -5, - -4, -4, -4, -3, -3, -3, -2, -2, - -2, -2, -2, -1, -1, -1, -1, -1, - 0, 0, 0, 0, 0, 0, 0, 0, -}; - -static int16 cubic_spline_lut1[1024] = { - 16384, 16384, 16384, 16384, 16384, 16383, 16382, 16381, - 16381, 16381, 16380, 16379, 16379, 16377, 16377, 16376, - 16374, 16373, 16371, 16370, 16369, 16366, 16366, 16364, - 16361, 16360, 16358, 16357, 16354, 16351, 16349, 16347, - 16345, 16342, 16340, 16337, 16335, 16331, 16329, 16326, - 16322, 16320, 16317, 16314, 16309, 16307, 16304, 16299, - 16297, 16293, 16290, 16285, 16282, 16278, 16274, 16269, - 16265, 16262, 16257, 16253, 16247, 16244, 16239, 16235, - 16230, 16225, 16220, 16216, 16211, 16206, 16201, 16196, - 16191, 16185, 16180, 16174, 16169, 16163, 16158, 16151, - 16146, 16140, 16133, 16128, 16122, 16116, 16109, 16104, - 16097, 16092, 16085, 16077, 16071, 16064, 16058, 16052, - 16044, 16038, 16030, 16023, 16015, 16009, 16002, 15995, - 15988, 15980, 15973, 15964, 15957, 15949, 15941, 15934, - 15926, 15918, 15910, 15903, 15894, 15886, 15877, 15870, - 15861, 15853, 15843, 15836, 15827, 15818, 15810, 15801, - 15792, 15783, 15774, 15765, 15756, 15747, 15738, 15729, - 15719, 15709, 15700, 15691, 15681, 15672, 15662, 15652, - 15642, 15633, 15623, 15613, 15602, 15592, 15582, 15572, - 15562, 15552, 15540, 15530, 15520, 15509, 15499, 15489, - 15478, 15467, 15456, 15446, 15433, 15423, 15412, 15401, - 15390, 15379, 15367, 15356, 15345, 15333, 15321, 15310, - 15299, 15287, 15276, 15264, 15252, 15240, 15228, 15216, - 15205, 15192, 15180, 15167, 15155, 15143, 15131, 15118, - 15106, 15094, 15081, 15067, 15056, 15043, 15031, 15017, - 15004, 14992, 14979, 14966, 14953, 14940, 14927, 14913, - 14900, 14887, 14874, 14860, 14846, 14833, 14819, 14806, - 14793, 14778, 14764, 14752, 14737, 14723, 14709, 14696, - 14681, 14668, 14653, 14638, 14625, 14610, 14595, 14582, - 14567, 14553, 14538, 14523, 14509, 14494, 14480, 14465, - 14450, 14435, 14420, 14406, 14391, 14376, 14361, 14346, - 14330, 14316, 14301, 14285, 14270, 14254, 14239, 14223, - 14208, 14192, 14177, 14161, 14146, 14130, 14115, 14099, - 14082, 14067, 14051, 14035, 14019, 14003, 13986, 13971, - 13955, 13939, 13923, 13906, 13890, 13873, 13857, 13840, - 13823, 13808, 13791, 13775, 13758, 13741, 13724, 13707, - 13691, 13673, 13657, 13641, 13623, 13607, 13589, 13572, - 13556, 13538, 13521, 13504, 13486, 13469, 13451, 13435, - 13417, 13399, 13383, 13365, 13347, 13330, 13312, 13294, - 13277, 13258, 13241, 13224, 13205, 13188, 13170, 13152, - 13134, 13116, 13098, 13080, 13062, 13044, 13026, 13008, - 12989, 12971, 12953, 12934, 12916, 12898, 12879, 12860, - 12842, 12823, 12806, 12787, 12768, 12750, 12731, 12712, - 12694, 12675, 12655, 12637, 12618, 12599, 12580, 12562, - 12542, 12524, 12504, 12485, 12466, 12448, 12427, 12408, - 12390, 12370, 12351, 12332, 12312, 12293, 12273, 12254, - 12235, 12215, 12195, 12176, 12157, 12137, 12118, 12097, - 12079, 12059, 12039, 12019, 11998, 11980, 11960, 11940, - 11920, 11900, 11880, 11860, 11839, 11821, 11801, 11780, - 11761, 11741, 11720, 11700, 11680, 11660, 11640, 11619, - 11599, 11578, 11559, 11538, 11518, 11498, 11477, 11457, - 11436, 11415, 11394, 11374, 11354, 11333, 11313, 11292, - 11272, 11251, 11231, 11209, 11189, 11168, 11148, 11127, - 11107, 11084, 11064, 11043, 11023, 11002, 10982, 10959, - 10939, 10918, 10898, 10876, 10856, 10834, 10814, 10792, - 10772, 10750, 10728, 10708, 10687, 10666, 10644, 10623, - 10602, 10581, 10560, 10538, 10517, 10496, 10474, 10453, - 10431, 10410, 10389, 10368, 10346, 10325, 10303, 10283, - 10260, 10239, 10217, 10196, 10175, 10152, 10132, 10110, - 10088, 10068, 10045, 10023, 10002, 9981, 9959, 9936, - 9915, 9893, 9872, 9851, 9829, 9806, 9784, 9763, - 9742, 9720, 9698, 9676, 9653, 9633, 9611, 9589, - 9567, 9545, 9523, 9501, 9479, 9458, 9436, 9414, - 9392, 9370, 9348, 9326, 9304, 9282, 9260, 9238, - 9216, 9194, 9172, 9150, 9128, 9106, 9084, 9062, - 9040, 9018, 8996, 8974, 8951, 8929, 8907, 8885, - 8863, 8841, 8819, 8797, 8775, 8752, 8730, 8708, - 8686, 8664, 8642, 8620, 8597, 8575, 8553, 8531, - 8509, 8487, 8464, 8442, 8420, 8398, 8376, 8353, - 8331, 8309, 8287, 8265, 8242, 8220, 8198, 8176, - 8154, 8131, 8109, 8087, 8065, 8042, 8020, 7998, - 7976, 7954, 7931, 7909, 7887, 7865, 7842, 7820, - 7798, 7776, 7754, 7731, 7709, 7687, 7665, 7643, - 7620, 7598, 7576, 7554, 7531, 7509, 7487, 7465, - 7443, 7421, 7398, 7376, 7354, 7332, 7310, 7288, - 7265, 7243, 7221, 7199, 7177, 7155, 7132, 7110, - 7088, 7066, 7044, 7022, 7000, 6978, 6956, 6934, - 6911, 6889, 6867, 6845, 6823, 6801, 6779, 6757, - 6735, 6713, 6691, 6669, 6647, 6625, 6603, 6581, - 6559, 6537, 6515, 6493, 6472, 6450, 6428, 6406, - 6384, 6362, 6340, 6318, 6297, 6275, 6253, 6231, - 6209, 6188, 6166, 6144, 6122, 6101, 6079, 6057, - 6035, 6014, 5992, 5970, 5949, 5927, 5905, 5884, - 5862, 5841, 5819, 5797, 5776, 5754, 5733, 5711, - 5690, 5668, 5647, 5625, 5604, 5582, 5561, 5540, - 5518, 5497, 5476, 5454, 5433, 5412, 5390, 5369, - 5348, 5327, 5305, 5284, 5263, 5242, 5221, 5199, - 5178, 5157, 5136, 5115, 5094, 5073, 5052, 5031, - 5010, 4989, 4968, 4947, 4926, 4905, 4885, 4864, - 4843, 4822, 4801, 4780, 4760, 4739, 4718, 4698, - 4677, 4656, 4636, 4615, 4595, 4574, 4553, 4533, - 4512, 4492, 4471, 4451, 4431, 4410, 4390, 4370, - 4349, 4329, 4309, 4288, 4268, 4248, 4228, 4208, - 4188, 4167, 4147, 4127, 4107, 4087, 4067, 4047, - 4027, 4007, 3988, 3968, 3948, 3928, 3908, 3889, - 3869, 3849, 3829, 3810, 3790, 3771, 3751, 3732, - 3712, 3693, 3673, 3654, 3634, 3615, 3595, 3576, - 3557, 3538, 3518, 3499, 3480, 3461, 3442, 3423, - 3404, 3385, 3366, 3347, 3328, 3309, 3290, 3271, - 3252, 3233, 3215, 3196, 3177, 3159, 3140, 3121, - 3103, 3084, 3066, 3047, 3029, 3010, 2992, 2974, - 2955, 2937, 2919, 2901, 2882, 2864, 2846, 2828, - 2810, 2792, 2774, 2756, 2738, 2720, 2702, 2685, - 2667, 2649, 2631, 2614, 2596, 2579, 2561, 2543, - 2526, 2509, 2491, 2474, 2456, 2439, 2422, 2405, - 2387, 2370, 2353, 2336, 2319, 2302, 2285, 2268, - 2251, 2234, 2218, 2201, 2184, 2167, 2151, 2134, - 2117, 2101, 2084, 2068, 2052, 2035, 2019, 2003, - 1986, 1970, 1954, 1938, 1922, 1906, 1890, 1874, - 1858, 1842, 1826, 1810, 1794, 1779, 1763, 1747, - 1732, 1716, 1701, 1685, 1670, 1654, 1639, 1624, - 1608, 1593, 1578, 1563, 1548, 1533, 1518, 1503, - 1488, 1473, 1458, 1444, 1429, 1414, 1400, 1385, - 1370, 1356, 1342, 1327, 1313, 1298, 1284, 1270, - 1256, 1242, 1228, 1214, 1200, 1186, 1172, 1158, - 1144, 1131, 1117, 1103, 1090, 1076, 1063, 1049, - 1036, 1022, 1009, 996, 983, 970, 956, 943, - 930, 917, 905, 892, 879, 866, 854, 841, - 828, 816, 803, 791, 778, 766, 754, 742, - 729, 717, 705, 693, 681, 669, 658, 646, - 634, 622, 611, 599, 588, 576, 565, 553, - 542, 531, 520, 508, 497, 486, 475, 464, - 453, 443, 432, 421, 411, 400, 389, 379, - 369, 358, 348, 338, 327, 317, 307, 297, - 287, 277, 268, 258, 248, 238, 229, 219, - 210, 200, 191, 182, 172, 163, 154, 145, - 136, 127, 118, 109, 100, 92, 83, 75, - 66, 58, 49, 41, 32, 24, 16, 8, -}; - -static int16 cubic_spline_lut2[1024] = { - 0, 8, 16, 24, 32, 41, 49, 58, - 66, 75, 83, 92, 100, 109, 118, 127, - 136, 145, 154, 163, 172, 182, 191, 200, - 210, 219, 229, 238, 248, 258, 268, 277, - 287, 297, 307, 317, 327, 338, 348, 358, - 369, 379, 389, 400, 411, 421, 432, 443, - 453, 464, 475, 486, 497, 508, 520, 531, - 542, 553, 565, 576, 588, 599, 611, 622, - 634, 646, 658, 669, 681, 693, 705, 717, - 729, 742, 754, 766, 778, 791, 803, 816, - 828, 841, 854, 866, 879, 892, 905, 917, - 930, 943, 956, 970, 983, 996, 1009, 1022, - 1036, 1049, 1063, 1076, 1090, 1103, 1117, 1131, - 1144, 1158, 1172, 1186, 1200, 1214, 1228, 1242, - 1256, 1270, 1284, 1298, 1313, 1327, 1342, 1356, - 1370, 1385, 1400, 1414, 1429, 1444, 1458, 1473, - 1488, 1503, 1518, 1533, 1548, 1563, 1578, 1593, - 1608, 1624, 1639, 1654, 1670, 1685, 1701, 1716, - 1732, 1747, 1763, 1779, 1794, 1810, 1826, 1842, - 1858, 1874, 1890, 1906, 1922, 1938, 1954, 1970, - 1986, 2003, 2019, 2035, 2052, 2068, 2084, 2101, - 2117, 2134, 2151, 2167, 2184, 2201, 2218, 2234, - 2251, 2268, 2285, 2302, 2319, 2336, 2353, 2370, - 2387, 2405, 2422, 2439, 2456, 2474, 2491, 2509, - 2526, 2543, 2561, 2579, 2596, 2614, 2631, 2649, - 2667, 2685, 2702, 2720, 2738, 2756, 2774, 2792, - 2810, 2828, 2846, 2864, 2882, 2901, 2919, 2937, - 2955, 2974, 2992, 3010, 3029, 3047, 3066, 3084, - 3103, 3121, 3140, 3159, 3177, 3196, 3215, 3233, - 3252, 3271, 3290, 3309, 3328, 3347, 3366, 3385, - 3404, 3423, 3442, 3461, 3480, 3499, 3518, 3538, - 3557, 3576, 3595, 3615, 3634, 3654, 3673, 3693, - 3712, 3732, 3751, 3771, 3790, 3810, 3829, 3849, - 3869, 3889, 3908, 3928, 3948, 3968, 3988, 4007, - 4027, 4047, 4067, 4087, 4107, 4127, 4147, 4167, - 4188, 4208, 4228, 4248, 4268, 4288, 4309, 4329, - 4349, 4370, 4390, 4410, 4431, 4451, 4471, 4492, - 4512, 4533, 4553, 4574, 4595, 4615, 4636, 4656, - 4677, 4698, 4718, 4739, 4760, 4780, 4801, 4822, - 4843, 4864, 4885, 4905, 4926, 4947, 4968, 4989, - 5010, 5031, 5052, 5073, 5094, 5115, 5136, 5157, - 5178, 5199, 5221, 5242, 5263, 5284, 5305, 5327, - 5348, 5369, 5390, 5412, 5433, 5454, 5476, 5497, - 5518, 5540, 5561, 5582, 5604, 5625, 5647, 5668, - 5690, 5711, 5733, 5754, 5776, 5797, 5819, 5841, - 5862, 5884, 5905, 5927, 5949, 5970, 5992, 6014, - 6035, 6057, 6079, 6101, 6122, 6144, 6166, 6188, - 6209, 6231, 6253, 6275, 6297, 6318, 6340, 6362, - 6384, 6406, 6428, 6450, 6472, 6493, 6515, 6537, - 6559, 6581, 6603, 6625, 6647, 6669, 6691, 6713, - 6735, 6757, 6779, 6801, 6823, 6845, 6867, 6889, - 6911, 6934, 6956, 6978, 7000, 7022, 7044, 7066, - 7088, 7110, 7132, 7155, 7177, 7199, 7221, 7243, - 7265, 7288, 7310, 7332, 7354, 7376, 7398, 7421, - 7443, 7465, 7487, 7509, 7531, 7554, 7576, 7598, - 7620, 7643, 7665, 7687, 7709, 7731, 7754, 7776, - 7798, 7820, 7842, 7865, 7887, 7909, 7931, 7954, - 7976, 7998, 8020, 8042, 8065, 8087, 8109, 8131, - 8154, 8176, 8198, 8220, 8242, 8265, 8287, 8309, - 8331, 8353, 8376, 8398, 8420, 8442, 8464, 8487, - 8509, 8531, 8553, 8575, 8597, 8620, 8642, 8664, - 8686, 8708, 8730, 8752, 8775, 8797, 8819, 8841, - 8863, 8885, 8907, 8929, 8951, 8974, 8996, 9018, - 9040, 9062, 9084, 9106, 9128, 9150, 9172, 9194, - 9216, 9238, 9260, 9282, 9304, 9326, 9348, 9370, - 9392, 9414, 9436, 9458, 9479, 9501, 9523, 9545, - 9567, 9589, 9611, 9633, 9653, 9676, 9698, 9720, - 9742, 9763, 9784, 9806, 9829, 9851, 9872, 9893, - 9915, 9936, 9959, 9981, 10002, 10023, 10045, 10068, - 10088, 10110, 10132, 10152, 10175, 10196, 10217, 10239, - 10260, 10283, 10303, 10325, 10346, 10368, 10389, 10410, - 10431, 10453, 10474, 10496, 10517, 10538, 10560, 10581, - 10602, 10623, 10644, 10666, 10687, 10708, 10728, 10750, - 10772, 10792, 10814, 10834, 10856, 10876, 10898, 10918, - 10939, 10959, 10982, 11002, 11023, 11043, 11064, 11084, - 11107, 11127, 11148, 11168, 11189, 11209, 11231, 11251, - 11272, 11292, 11313, 11333, 11354, 11374, 11394, 11415, - 11436, 11457, 11477, 11498, 11518, 11538, 11559, 11578, - 11599, 11619, 11640, 11660, 11680, 11700, 11720, 11741, - 11761, 11780, 11801, 11821, 11839, 11860, 11880, 11900, - 11920, 11940, 11960, 11980, 11998, 12019, 12039, 12059, - 12079, 12097, 12118, 12137, 12157, 12176, 12195, 12215, - 12235, 12254, 12273, 12293, 12312, 12332, 12351, 12370, - 12390, 12408, 12427, 12448, 12466, 12485, 12504, 12524, - 12542, 12562, 12580, 12599, 12618, 12637, 12655, 12675, - 12694, 12712, 12731, 12750, 12768, 12787, 12806, 12823, - 12842, 12860, 12879, 12898, 12916, 12934, 12953, 12971, - 12989, 13008, 13026, 13044, 13062, 13080, 13098, 13116, - 13134, 13152, 13170, 13188, 13205, 13224, 13241, 13258, - 13277, 13294, 13312, 13330, 13347, 13365, 13383, 13399, - 13417, 13435, 13451, 13469, 13486, 13504, 13521, 13538, - 13556, 13572, 13589, 13607, 13623, 13641, 13657, 13673, - 13691, 13707, 13724, 13741, 13758, 13775, 13791, 13808, - 13823, 13840, 13857, 13873, 13890, 13906, 13923, 13939, - 13955, 13971, 13986, 14003, 14019, 14035, 14051, 14067, - 14082, 14099, 14115, 14130, 14146, 14161, 14177, 14192, - 14208, 14223, 14239, 14254, 14270, 14285, 14301, 14316, - 14330, 14346, 14361, 14376, 14391, 14406, 14420, 14435, - 14450, 14465, 14480, 14494, 14509, 14523, 14538, 14553, - 14567, 14582, 14595, 14610, 14625, 14638, 14653, 14668, - 14681, 14696, 14709, 14723, 14737, 14752, 14764, 14778, - 14793, 14806, 14819, 14833, 14846, 14860, 14874, 14887, - 14900, 14913, 14927, 14940, 14953, 14966, 14979, 14992, - 15004, 15017, 15031, 15043, 15056, 15067, 15081, 15094, - 15106, 15118, 15131, 15143, 15155, 15167, 15180, 15192, - 15205, 15216, 15228, 15240, 15252, 15264, 15276, 15287, - 15299, 15310, 15321, 15333, 15345, 15356, 15367, 15379, - 15390, 15401, 15412, 15423, 15433, 15446, 15456, 15467, - 15478, 15489, 15499, 15509, 15520, 15530, 15540, 15552, - 15562, 15572, 15582, 15592, 15602, 15613, 15623, 15633, - 15642, 15652, 15662, 15672, 15681, 15691, 15700, 15709, - 15719, 15729, 15738, 15747, 15756, 15765, 15774, 15783, - 15792, 15801, 15810, 15818, 15827, 15836, 15843, 15853, - 15861, 15870, 15877, 15886, 15894, 15903, 15910, 15918, - 15926, 15934, 15941, 15949, 15957, 15964, 15973, 15980, - 15988, 15995, 16002, 16009, 16015, 16023, 16030, 16038, - 16044, 16052, 16058, 16064, 16071, 16077, 16085, 16092, - 16097, 16104, 16109, 16116, 16122, 16128, 16133, 16140, - 16146, 16151, 16158, 16163, 16169, 16174, 16180, 16185, - 16191, 16196, 16201, 16206, 16211, 16216, 16220, 16225, - 16230, 16235, 16239, 16244, 16247, 16253, 16257, 16262, - 16265, 16269, 16274, 16278, 16282, 16285, 16290, 16293, - 16297, 16299, 16304, 16307, 16309, 16314, 16317, 16320, - 16322, 16326, 16329, 16331, 16335, 16337, 16340, 16342, - 16345, 16347, 16349, 16351, 16354, 16357, 16358, 16360, - 16361, 16364, 16366, 16366, 16369, 16370, 16371, 16373, - 16374, 16376, 16377, 16377, 16379, 16379, 16380, 16381, - 16381, 16381, 16382, 16383, 16384, 16384, 16384, 16384, -}; - -static int16 cubic_spline_lut3[1024] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, -1, -1, -1, -1, -1, -2, -2, - -2, -2, -2, -3, -3, -3, -4, -4, - -4, -5, -5, -6, -6, -6, -7, -7, - -8, -8, -9, -9, -10, -10, -11, -11, - -12, -13, -13, -14, -14, -15, -16, -16, - -17, -18, -19, -19, -20, -21, -22, -22, - -23, -24, -25, -26, -26, -27, -28, -29, - -30, -31, -32, -33, -34, -35, -36, -37, - -38, -39, -40, -41, -42, -43, -44, -45, - -46, -47, -48, -49, -51, -52, -53, -54, - -55, -57, -58, -59, -60, -61, -63, -64, - -65, -67, -68, -69, -70, -72, -73, -75, - -76, -77, -79, -80, -82, -83, -84, -86, - -87, -89, -90, -92, -93, -95, -96, -98, - -99, -101, -102, -104, -106, -107, -109, -110, - -112, -114, -115, -117, -119, -120, -122, -124, - -125, -127, -129, -130, -132, -134, -136, -137, - -139, -141, -143, -145, -146, -148, -150, -152, - -154, -156, -157, -159, -161, -163, -165, -167, - -169, -171, -173, -175, -176, -178, -180, -182, - -184, -186, -188, -190, -192, -194, -196, -198, - -200, -202, -205, -207, -209, -211, -213, -215, - -217, -219, -221, -223, -225, -228, -230, -232, - -234, -236, -238, -240, -243, -245, -247, -249, - -251, -254, -256, -258, -260, -263, -265, -267, - -269, -272, -274, -276, -278, -281, -283, -285, - -288, -290, -292, -295, -297, -299, -302, -304, - -306, -309, -311, -313, -316, -318, -320, -323, - -325, -328, -330, -332, -335, -337, -340, -342, - -345, -347, -349, -352, -354, -357, -359, -362, - -364, -367, -369, -372, -374, -377, -379, -382, - -384, -387, -389, -392, -394, -397, -399, -402, - -404, -407, -409, -412, -414, -417, -419, -422, - -424, -427, -430, -432, -435, -437, -440, -442, - -445, -448, -450, -453, -455, -458, -461, -463, - -466, -468, -471, -474, -476, -479, -481, -484, - -487, -489, -492, -495, -497, -500, -502, -505, - -508, -510, -513, -516, -518, -521, -523, -526, - -529, -531, -534, -537, -539, -542, -545, -547, - -550, -553, -555, -558, -561, -563, -566, -569, - -571, -574, -577, -579, -582, -585, -587, -590, - -593, -595, -598, -601, -603, -606, -609, -611, - -614, -617, -619, -622, -625, -627, -630, -633, - -635, -638, -641, -643, -646, -649, -651, -654, - -657, -659, -662, -665, -667, -670, -672, -675, - -678, -680, -683, -686, -688, -691, -694, -696, - -699, -702, -704, -707, -709, -712, -715, -717, - -720, -723, -725, -728, -730, -733, -736, -738, - -741, -744, -746, -749, -751, -754, -757, -759, - -762, -764, -767, -769, -772, -775, -777, -780, - -782, -785, -787, -790, -793, -795, -798, -800, - -803, -805, -808, -810, -813, -815, -818, -820, - -823, -825, -828, -830, -833, -835, -838, -840, - -843, -845, -848, -850, -853, -855, -858, -860, - -863, -865, -867, -870, -872, -875, -877, -880, - -882, -884, -887, -889, -892, -894, -896, -899, - -901, -903, -906, -908, -911, -913, -915, -918, - -920, -922, -924, -927, -929, -931, -934, -936, - -938, -941, -943, -945, -947, -950, -952, -954, - -956, -958, -961, -963, -965, -967, -969, -972, - -974, -976, -978, -980, -982, -985, -987, -989, - -991, -993, -995, -997, -999, -1002, -1004, -1006, - -1008, -1010, -1012, -1014, -1016, -1018, -1020, -1022, - -1024, -1026, -1028, -1030, -1032, -1034, -1036, -1038, - -1040, -1042, -1044, -1046, -1047, -1049, -1051, -1053, - -1055, -1057, -1059, -1061, -1062, -1064, -1066, -1068, - -1070, -1071, -1073, -1075, -1077, -1079, -1080, -1082, - -1084, -1085, -1087, -1089, -1091, -1092, -1094, -1096, - -1097, -1099, -1101, -1102, -1104, -1105, -1107, -1109, - -1110, -1112, -1113, -1115, -1116, -1118, -1119, -1121, - -1122, -1124, -1125, -1127, -1128, -1130, -1131, -1133, - -1134, -1135, -1137, -1138, -1140, -1141, -1142, -1144, - -1145, -1146, -1148, -1149, -1150, -1151, -1153, -1154, - -1155, -1156, -1158, -1159, -1160, -1161, -1162, -1163, - -1165, -1166, -1167, -1168, -1169, -1170, -1171, -1172, - -1173, -1174, -1175, -1176, -1177, -1178, -1179, -1180, - -1181, -1182, -1183, -1184, -1185, -1186, -1187, -1187, - -1188, -1189, -1190, -1191, -1192, -1192, -1193, -1194, - -1195, -1195, -1196, -1197, -1197, -1198, -1199, -1199, - -1200, -1201, -1201, -1202, -1202, -1203, -1204, -1204, - -1205, -1205, -1206, -1206, -1207, -1207, -1207, -1208, - -1208, -1209, -1209, -1209, -1210, -1210, -1210, -1211, - -1211, -1211, -1211, -1212, -1212, -1212, -1212, -1213, - -1213, -1213, -1213, -1213, -1213, -1213, -1213, -1214, - -1214, -1214, -1214, -1214, -1214, -1214, -1214, -1213, - -1213, -1213, -1213, -1213, -1213, -1213, -1213, -1212, - -1212, -1212, -1212, -1212, -1211, -1211, -1211, -1210, - -1210, -1210, -1209, -1209, -1208, -1208, -1208, -1207, - -1207, -1206, -1206, -1205, -1205, -1204, -1204, -1203, - -1202, -1202, -1201, -1200, -1200, -1199, -1198, -1198, - -1197, -1196, -1195, -1195, -1194, -1193, -1192, -1191, - -1190, -1189, -1188, -1187, -1187, -1186, -1185, -1184, - -1182, -1181, -1180, -1179, -1178, -1177, -1176, -1175, - -1174, -1172, -1171, -1170, -1169, -1167, -1166, -1165, - -1163, -1162, -1161, -1159, -1158, -1156, -1155, -1153, - -1152, -1150, -1149, -1147, -1146, -1144, -1143, -1141, - -1139, -1138, -1136, -1134, -1133, -1131, -1129, -1127, - -1125, -1124, -1122, -1120, -1118, -1116, -1114, -1112, - -1110, -1108, -1106, -1104, -1102, -1100, -1098, -1096, - -1094, -1092, -1089, -1087, -1085, -1083, -1080, -1078, - -1076, -1074, -1071, -1069, -1066, -1064, -1062, -1059, - -1057, -1054, -1052, -1049, -1047, -1044, -1041, -1039, - -1036, -1033, -1031, -1028, -1025, -1022, -1020, -1017, - -1014, -1011, -1008, -1005, -1002, -999, -997, -994, - -991, -987, -984, -981, -978, -975, -972, -969, - -966, -962, -959, -956, -953, -949, -946, -943, - -939, -936, -932, -929, -925, -922, -918, -915, - -911, -908, -904, -900, -897, -893, -889, -886, - -882, -878, -874, -870, -866, -863, -859, -855, - -851, -847, -843, -839, -835, -831, -826, -822, - -818, -814, -810, -806, -801, -797, -793, -788, - -784, -780, -775, -771, -766, -762, -757, -753, - -748, -744, -739, -734, -730, -725, -720, -715, - -711, -706, -701, -696, -691, -686, -682, -677, - -672, -667, -662, -656, -651, -646, -641, -636, - -631, -626, -620, -615, -610, -604, -599, -594, - -588, -583, -577, -572, -566, -561, -555, -550, - -544, -538, -533, -527, -521, -515, -510, -504, - -498, -492, -486, -480, -474, -468, -462, -456, - -450, -444, -438, -432, -425, -419, -413, -407, - -400, -394, -388, -381, -375, -368, -362, -355, - -349, -342, -336, -329, -322, -316, -309, -302, - -295, -289, -282, -275, -268, -261, -254, -247, - -240, -233, -226, -219, -212, -205, -198, -190, - -183, -176, -169, -161, -154, -146, -139, -132, - -124, -117, -109, -101, -94, -86, -78, -71, - -63, -55, -47, -40, -32, -24, -16, -8, -}; - diff --git a/source/libxmp-lite/src/read_event.c b/source/libxmp-lite/src/read_event.c deleted file mode 100644 index 55a7f9bf3..000000000 --- a/source/libxmp-lite/src/read_event.c +++ /dev/null @@ -1,1613 +0,0 @@ -/* Extended Module Player - * 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"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include -#include -#include "common.h" -#include "player.h" -#include "effects.h" -#include "virtual.h" -#include "period.h" - -#ifndef LIBXMP_CORE_PLAYER -#include "med_extras.h" -#endif - - -static inline int is_valid_note(int note) -{ - return (note >= 0 && note < XMP_MAX_KEYS); -} - -static struct xmp_subinstrument *get_subinstrument(struct context_data *ctx, - int ins, int key) -{ - struct module_data *m = &ctx->m; - struct xmp_module *mod = &m->mod; - struct xmp_instrument *instrument; - - if (IS_VALID_INSTRUMENT(ins)) { - instrument = &mod->xxi[ins]; - if (is_valid_note(key)) { - int mapped = instrument->map[key].ins; - if (mapped != 0xff && mapped >= 0 && mapped < instrument->nsm) - return &instrument->sub[mapped]; - } else { - if (mod->xxi[ins].nsm > 0) { - return &instrument->sub[0]; - } - } - } - - return NULL; -} - -static void reset_envelopes(struct context_data *ctx, struct channel_data *xc) -{ - struct module_data *m = &ctx->m; - struct xmp_module *mod = &m->mod; - - if (!IS_VALID_INSTRUMENT(xc->ins)) - return; - - RESET_NOTE(NOTE_ENV_END); - - xc->v_idx = -1; - xc->p_idx = -1; - xc->f_idx = -1; -} - -#ifndef LIBXMP_CORE_DISABLE_IT - -static void reset_envelopes_carry(struct context_data *ctx, - struct channel_data *xc) -{ - struct module_data *m = &ctx->m; - struct xmp_module *mod = &m->mod; - struct xmp_instrument *xxi; - - if (!IS_VALID_INSTRUMENT(xc->ins)) - return; - - RESET_NOTE(NOTE_ENV_END); - - xxi = libxmp_get_instrument(ctx, xc->ins); - - /* Reset envelope positions */ - if (~xxi->aei.flg & XMP_ENVELOPE_CARRY) { - xc->v_idx = -1; - } - if (~xxi->pei.flg & XMP_ENVELOPE_CARRY) { - xc->p_idx = -1; - } - if (~xxi->fei.flg & XMP_ENVELOPE_CARRY) { - xc->f_idx = -1; - } -} - -#endif - -static void set_effect_defaults(struct context_data *ctx, int note, - struct xmp_subinstrument *sub, - struct channel_data *xc, int is_toneporta) -{ - struct module_data *m = &ctx->m; - struct xmp_module *mod = &m->mod; - struct smix_data *smix = &ctx->smix; - - if (sub != NULL && note >= 0) { - struct xmp_instrument *xxi; - - if (xc->ins >= mod->ins) { - xxi = &smix->xxi[xc->ins - mod->ins]; - } else { - xxi = &mod->xxi[xc->ins]; - } - - if (!HAS_QUIRK(QUIRK_PROTRACK)) { - xc->finetune = sub->fin; - } - xc->gvl = sub->gvl; - -#ifndef LIBXMP_CORE_DISABLE_IT - if (sub->ifc & 0x80) { - xc->filter.cutoff = (sub->ifc - 0x80) * 2; - } else if (~xxi->fei.flg & XMP_ENVELOPE_FLT) { - xc->filter.cutoff = 0xff; - } - xc->filter.envelope = 0x100; - - if (sub->ifr & 0x80) { - xc->filter.resonance = (sub->ifr - 0x80) * 2; - } /* else { - xc->filter.resonance = 0; - } */ -#endif - - libxmp_lfo_set_depth(&xc->insvib.lfo, sub->vde); - libxmp_lfo_set_rate(&xc->insvib.lfo, sub->vra >> 2); - libxmp_lfo_set_waveform(&xc->insvib.lfo, sub->vwf); - xc->insvib.sweep = sub->vsw; - - libxmp_lfo_set_phase(&xc->vibrato.lfo, 0); - libxmp_lfo_set_phase(&xc->tremolo.lfo, 0); - } - - xc->delay = 0; - xc->tremor.up = xc->tremor.down = 0; - - /* Reset arpeggio */ - xc->arpeggio.val[0] = 0; - xc->arpeggio.count = 0; - xc->arpeggio.size = 1; -} - -/* From OpenMPT PortaTarget.mod: - * "A new note (with no portamento command next to it) does not reset the - * portamento target. That is, if a previous portamento has not finished yet, - * calling 3xx or 5xx after the new note will slide it towards the old target. - * Once the portamento target period is reached, the target is reset. This - * means that if the period is modified by another slide (e.g. 1xx or 2xx), - * a following 3xx will not slide back to the original target." - */ -static void set_period(struct context_data *ctx, int note, - struct xmp_subinstrument *sub, - struct channel_data *xc, int is_toneporta) -{ - struct module_data *m = &ctx->m; - - if (sub != NULL && note >= 0) { - double per = libxmp_note_to_period(ctx, note, xc->finetune, - xc->per_adj); - - if (!HAS_QUIRK(QUIRK_PROTRACK) || (note > 0 && is_toneporta)) { - xc->porta.target = per; - } - - if (xc->period < 1 || !is_toneporta) { - xc->period = per; - } - } -} - -/* From OpenMPT Porta-Pickup.xm: - * "An instrument number should not reset the current portamento target. The - * portamento target is valid until a new target is specified by combining a - * note and a portamento effect." - */ -static void set_period_ft2(struct context_data *ctx, int note, - struct xmp_subinstrument *sub, - struct channel_data *xc, int is_toneporta) -{ - if (note > 0 && is_toneporta) { - xc->porta.target = libxmp_note_to_period(ctx, note, xc->finetune, - xc->per_adj); - } - if (sub != NULL && note >= 0) { - if (xc->period < 1 || !is_toneporta) { - xc->period = libxmp_note_to_period(ctx, note, xc->finetune, - xc->per_adj); - } - } -} - - -#ifndef LIBXMP_CORE_PLAYER -#define IS_SFX_PITCH(x) ((x) == FX_PITCH_ADD || (x) == FX_PITCH_SUB) -#define IS_TONEPORTA(x) ((x) == FX_TONEPORTA || (x) == FX_TONE_VSLIDE \ - || (x) == FX_PER_TPORTA) -#else -#define IS_TONEPORTA(x) ((x) == FX_TONEPORTA || (x) == FX_TONE_VSLIDE) -#endif - -#define set_patch(ctx,chn,ins,smp,note) \ - libxmp_virt_setpatch(ctx, chn, ins, smp, note, 0, 0, 0) - -static int read_event_mod(struct context_data *ctx, struct xmp_event *e, int chn) -{ - struct player_data *p = &ctx->p; - struct module_data *m = &ctx->m; - struct xmp_module *mod = &m->mod; - struct channel_data *xc = &p->xc_data[chn]; - int note; - struct xmp_subinstrument *sub; - int new_invalid_ins = 0; - int is_toneporta; - int use_ins_vol; - - xc->flags = 0; - note = -1; - is_toneporta = 0; - use_ins_vol = 0; - - if (IS_TONEPORTA(e->fxt) || IS_TONEPORTA(e->f2t)) { - is_toneporta = 1; - } - - /* Check instrument */ - - if (e->ins) { - int ins = e->ins - 1; - use_ins_vol = 1; - SET(NEW_INS); - xc->fadeout = 0x10000; /* for painlace.mod pat 0 ch 3 echo */ - xc->per_flags = 0; - xc->offset.val = 0; - RESET_NOTE(NOTE_RELEASE|NOTE_FADEOUT); - - if (IS_VALID_INSTRUMENT(ins)) { - sub = get_subinstrument(ctx, ins, e->note - 1); - - if (is_toneporta) { - /* Get new instrument volume */ - if (sub != NULL) { - /* Dennis Lindroos: instrument volume - * is not used on split channels - */ - if (!xc->split) { - xc->volume = sub->vol; - } - use_ins_vol = 0; - } - } else { - xc->ins = ins; - xc->ins_fade = mod->xxi[ins].rls; - - if (sub != NULL) { - if (HAS_QUIRK(QUIRK_PROTRACK)) { - xc->finetune = sub->fin; - } - } - } - } else { - new_invalid_ins = 1; - libxmp_virt_resetchannel(ctx, chn); - } - } - - /* Check note */ - - if (e->note) { - SET(NEW_NOTE); - - if (e->note == XMP_KEY_OFF) { - SET_NOTE(NOTE_RELEASE); - use_ins_vol = 0; - } else if (!is_toneporta) { - xc->key = e->note - 1; - RESET_NOTE(NOTE_END); - - sub = get_subinstrument(ctx, xc->ins, xc->key); - - if (!new_invalid_ins && sub != NULL) { - int transp = mod->xxi[xc->ins].map[xc->key].xpo; - int smp; - - note = xc->key + sub->xpo + transp; - smp = sub->sid; - - if (mod->xxs[smp].len == 0) { - smp = -1; - } - - if (smp >= 0 && smp < mod->smp) { - set_patch(ctx, chn, xc->ins, smp, note); - xc->smp = smp; - } - } else { - xc->flags = 0; - use_ins_vol = 0; - } - } - } - - sub = get_subinstrument(ctx, xc->ins, xc->key); - - set_effect_defaults(ctx, note, sub, xc, is_toneporta); - if (e->ins && sub != NULL) { - reset_envelopes(ctx, xc); - } - - /* Process new volume */ - if (e->vol) { - xc->volume = e->vol - 1; - SET(NEW_VOL); - } - - /* Secondary effect handled first */ - libxmp_process_fx(ctx, xc, chn, e, 1); - libxmp_process_fx(ctx, xc, chn, e, 0); - -#ifndef LIBXMP_CORE_PLAYER - if (IS_SFX_PITCH(e->fxt)) { - xc->period = libxmp_note_to_period(ctx, note, xc->finetune, - xc->per_adj); - } else -#endif - { - set_period(ctx, note, sub, xc, is_toneporta); - } - - if (sub == NULL) { - return 0; - } - - if (note >= 0) { - xc->note = note; - libxmp_virt_voicepos(ctx, chn, xc->offset.val); - } - - if (TEST(OFFSET)) { - if (HAS_QUIRK(QUIRK_PROTRACK) || p->flags & XMP_FLAGS_FX9BUG) { - xc->offset.val += xc->offset.val2; - } - RESET(OFFSET); - } - - if (use_ins_vol && !TEST(NEW_VOL) && !xc->split) { - xc->volume = sub->vol; - } - - return 0; -} - -static int sustain_check(struct xmp_envelope *env, int idx) -{ - return (env && - (env->flg & XMP_ENVELOPE_ON) && - (~env->flg & XMP_ENVELOPE_LOOP) && - idx == env->data[env->sus << 1]); -} - -static int read_event_ft2(struct context_data *ctx, struct xmp_event *e, int chn) -{ - struct player_data *p = &ctx->p; - struct module_data *m = &ctx->m; - struct xmp_module *mod = &m->mod; - struct channel_data *xc = &p->xc_data[chn]; - int note, key, ins; - struct xmp_subinstrument *sub; - int new_invalid_ins; - int is_toneporta; - int use_ins_vol; - int k00 = 0; - struct xmp_event ev; - - /* From the OpenMPT DelayCombination.xm test case: - * "Naturally, Fasttracker 2 ignores notes next to an out-of-range - * note delay. However, to check whether the delay is out of range, - * it is simply compared against the current song speed, not taking - * any pattern delays into account." - */ - if (p->frame >= p->speed) { - return 0; - } - - memcpy(&ev, e, sizeof (struct xmp_event)); - - /* From OpenMPT TremorReset.xm test case: - * "Even if a tremor effect muted the sample on a previous row, volume - * commands should be able to override this effect." - */ - if (ev.vol) { - xc->tremor.count &= ~0x80; - } - - xc->flags = 0; - note = -1; - key = ev.note; - ins = ev.ins; - new_invalid_ins = 0; - is_toneporta = 0; - use_ins_vol = 0; - - /* From the OpenMPT key_off.xm test case: - * "Key off at tick 0 (K00) is very dodgy command. If there is a note - * next to it, the note is ignored. If there is a volume column - * command or instrument next to it and the current instrument has - * no volume envelope, the note is faded out instead of being cut." - */ - if (ev.fxt == FX_KEYOFF && ev.fxp == 0) { - k00 = 1; - key = 0; - - if (ins || ev.vol || ev.f2t) { - if (IS_VALID_INSTRUMENT(xc->ins) && - ~mod->xxi[xc->ins].aei.flg & XMP_ENVELOPE_ON) { - SET_NOTE(NOTE_FADEOUT); - ev.fxt = 0; - } - } - } - - if (IS_TONEPORTA(ev.fxt) || IS_TONEPORTA(ev.f2t)) { - is_toneporta = 1; - } - - /* Check instrument */ - - /* Ignore invalid instruments. The last instrument, invalid or - * not, is preserved in channel data (see read_event() below). - * Fixes stray delayed notes in forgotten_city.xm. - */ - if (ins > 0 && !IS_VALID_INSTRUMENT(ins - 1)) { - ins = 0; - } - - /* FT2: Retrieve old instrument volume */ - if (ins) { - if (key == 0 || key >= XMP_KEY_OFF) { - struct xmp_subinstrument *sub; - - /* Previous instrument */ - sub = get_subinstrument(ctx, xc->ins, xc->key); - - /* No note */ - if (sub != NULL) { - int p = mod->xxc[chn].pan - 128; - xc->volume = sub->vol; - - if (!HAS_QUIRK(QUIRK_FTMOD)) { - xc->pan.val = p + ((sub->pan - 128) * - (128 - abs(p))) / 128 + 128; - } - - xc->ins_fade = mod->xxi[xc->ins].rls; - SET(NEW_VOL); - } - } - } - - /* Do this regardless if the instrument is invalid or not */ - if (ev.ins) { - SET(NEW_INS); - use_ins_vol = 1; - xc->fadeout = 0x10000; - xc->per_flags = 0; - RESET_NOTE(NOTE_RELEASE|NOTE_SUSEXIT); - if (!k00) { - RESET_NOTE(NOTE_FADEOUT); - } - - if (IS_VALID_INSTRUMENT(ins - 1)) { - if (!is_toneporta) - xc->ins = ins - 1; - } else { - new_invalid_ins = 1; - - /* If no note is set FT2 doesn't cut on invalid - * instruments (it keeps playing the previous one). - * If a note is set it cuts the current sample. - */ - xc->flags = 0; - - if (is_toneporta) { - key = 0; - } - } - - xc->tremor.count = 0x20; - } - - /* Check note */ - - if (ins) { - if (key > 0 && key < XMP_KEY_OFF) { - struct xmp_subinstrument *sub; - - /* Retrieve volume when we have note */ - - /* and only if we have instrument, otherwise we're in - * case 1: new note and no instrument - */ - - /* Current instrument */ - sub = get_subinstrument(ctx, xc->ins, key - 1); - if (sub != NULL) { - int p = mod->xxc[chn].pan - 128; - xc->volume = sub->vol; - - if (!HAS_QUIRK(QUIRK_FTMOD)) { - xc->pan.val = p + ((sub->pan - 128) * - (128 - abs(p))) / 128 + 128; - } - - xc->ins_fade = mod->xxi[xc->ins].rls; - } else { - xc->volume = 0; - } - SET(NEW_VOL); - } - } - - if (key) { - SET(NEW_NOTE); - - if (key == XMP_KEY_OFF) { - int env_on = 0; - int vol_set = ev.vol != 0 || ev.fxt == FX_VOLSET; - int delay_fx = ev.fxt == FX_EXTENDED && ev.fxp == 0xd0; - struct xmp_envelope *env = NULL; - - /* OpenMPT NoteOffVolume.xm: - * "If an instrument has no volume envelope, a note-off - * command should cut the sample completely - unless - * there is a volume command next it. This applies to - * both volume commands (volume and effect column)." - * - * ...and unless we have a keyoff+delay without setting - * an instrument. See OffDelay.xm. - */ - if (IS_VALID_INSTRUMENT(xc->ins)) { - env = &mod->xxi[xc->ins].aei; - if (env->flg & XMP_ENVELOPE_ON) { - env_on = 1; - } - } - - if (env_on || (!vol_set && (!ev.ins || !delay_fx))) { - if (sustain_check(env, xc->v_idx)) { - /* See OpenMPT EnvOff.xm. In certain - * cases a release event is effective - * only in the next frame - */ - SET_NOTE(NOTE_SUSEXIT); - } else { - SET_NOTE(NOTE_RELEASE); - } - use_ins_vol = 0; - } else { - SET_NOTE(NOTE_FADEOUT); - } - - /* See OpenMPT keyoff+instr.xm, pattern 2 row 0x40 */ - if (env_on && ev.fxt == FX_EXTENDED && - (ev.fxp >> 4) == EX_DELAY) { - /* See OpenMPT OffDelay.xm test case */ - if ((ev.fxp & 0xf) != 0) { - RESET_NOTE(NOTE_RELEASE|NOTE_SUSEXIT); - } - } - } else if (key == XMP_KEY_FADE) { - /* Handle keyoff + instrument case (NoteOff2.xm) */ - SET_NOTE(NOTE_FADEOUT); - } else if (is_toneporta) { - /* set key to 0 so we can have the tone portamento from - * the original note (see funky_stars.xm pos 5 ch 9) - */ - key = 0; - - /* And do the same if there's no keyoff (see comic - * bakery remix.xm pos 1 ch 3) - */ - } - - if (ev.ins == 0 && !IS_VALID_INSTRUMENT(xc->old_ins - 1)) { - new_invalid_ins = 1; - } - - if (new_invalid_ins) { - libxmp_virt_resetchannel(ctx, chn); - } - } - - - /* Check note range -- from the OpenMPT test NoteLimit.xm: - * "I think one of the first things Fasttracker 2 does when parsing a - * pattern cell is calculating the “real” note (i.e. pattern note + - * sample transpose), and if this “real” note falls out of its note - * range, it is ignored completely (wiped from its internal channel - * memory). The instrument number next it, however, is not affected - * and remains in the memory." - */ - sub = NULL; - if (is_valid_note(key - 1)) { - int k = key - 1; - sub = get_subinstrument(ctx, xc->ins, k); - if (!new_invalid_ins && sub != NULL) { - int transp = mod->xxi[xc->ins].map[k].xpo; - int k2 = k + sub->xpo + transp; - if (k2 < 12 || k2 > 130) { - key = 0; - RESET(NEW_NOTE); - } - } - } - - if (is_valid_note(key - 1)) { - xc->key = --key; - xc->fadeout = 0x10000; - RESET_NOTE(NOTE_END); - - if (sub != NULL) { - if (~mod->xxi[xc->ins].aei.flg & XMP_ENVELOPE_ON) { - RESET_NOTE(NOTE_RELEASE|NOTE_FADEOUT); - } - } - - if (!new_invalid_ins && sub != NULL) { - int transp = mod->xxi[xc->ins].map[key].xpo; - int smp; - - note = key + sub->xpo + transp; - smp = sub->sid; - - if (mod->xxs[smp].len == 0) { - smp = -1; - } - - if (smp >= 0 && smp < mod->smp) { - set_patch(ctx, chn, xc->ins, smp, note); - xc->smp = smp; - } - } else { - xc->flags = 0; - use_ins_vol = 0; - } - } - - sub = get_subinstrument(ctx, xc->ins, xc->key); - - set_effect_defaults(ctx, note, sub, xc, is_toneporta); - - if (ins && sub != NULL && !k00) { - /* Reset envelopes on new instrument, see olympic.xm pos 10 - * But make sure we have an instrument set, see Letting go - * pos 4 chn 20 - */ - reset_envelopes(ctx, xc); - } - - /* Process new volume */ - if (ev.vol) { - xc->volume = ev.vol - 1; - SET(NEW_VOL); - if (TEST_NOTE(NOTE_END)) { /* m5v-nine.xm */ - xc->fadeout = 0x10000; /* OpenMPT NoteOff.xm */ - RESET_NOTE(NOTE_RELEASE|NOTE_FADEOUT); - } - } - - /* FT2: always reset sample offset */ - xc->offset.val = 0; - - /* Secondary effect handled first */ - libxmp_process_fx(ctx, xc, chn, &ev, 1); - libxmp_process_fx(ctx, xc, chn, &ev, 0); - set_period_ft2(ctx, note, sub, xc, is_toneporta); - - if (sub == NULL) { - return 0; - } - - if (note >= 0) { - xc->note = note; - - /* From the OpenMPT test cases (3xx-no-old-samp.xm): - * "An offset effect that points beyond the sample end should - * stop playback on this channel." - * - * ... except in Skale Tracker (and possibly others), so make this a - * FastTracker2 quirk. See Armada Tanks game.it (actually an XM). - * Reported by Vladislav Suschikh. - */ - if (HAS_QUIRK(QUIRK_FT2BUGS) && xc->offset.val >= mod->xxs[sub->sid].len) { - libxmp_virt_resetchannel(ctx, chn); - } else { - - /* (From Decibelter - Cosmic 'Wegian Mamas.xm p04 ch7) - * We retrigger the sample only if we have a new note - * without tone portamento, otherwise we won't play - * sweeps and loops correctly. - */ - libxmp_virt_voicepos(ctx, chn, xc->offset.val); - } - } - - if (use_ins_vol && !TEST(NEW_VOL)) { - xc->volume = sub->vol; - } - - return 0; -} - -static int read_event_st3(struct context_data *ctx, struct xmp_event *e, int chn) -{ - struct player_data *p = &ctx->p; - struct module_data *m = &ctx->m; - struct xmp_module *mod = &m->mod; - struct channel_data *xc = &p->xc_data[chn]; - int note; - struct xmp_subinstrument *sub; - int not_same_ins; - int is_toneporta; - int use_ins_vol; - - xc->flags = 0; - note = -1; - not_same_ins = 0; - is_toneporta = 0; - use_ins_vol = 0; - - if (IS_TONEPORTA(e->fxt) || IS_TONEPORTA(e->f2t)) { - is_toneporta = 1; - } - - if (libxmp_virt_mapchannel(ctx, chn) < 0 && xc->ins != e->ins - 1) { - is_toneporta = 0; - } - - /* Check instrument */ - - if (e->ins) { - int ins = e->ins - 1; - SET(NEW_INS); - use_ins_vol = 1; - xc->fadeout = 0x10000; - xc->per_flags = 0; - xc->offset.val = 0; - RESET_NOTE(NOTE_RELEASE|NOTE_FADEOUT); - - if (IS_VALID_INSTRUMENT(ins)) { - /* valid ins */ - if (xc->ins != ins) { - not_same_ins = 1; - if (!is_toneporta) { - xc->ins = ins; - xc->ins_fade = mod->xxi[ins].rls; - } else { - /* Get new instrument volume */ - sub = get_subinstrument(ctx, ins, e->note - 1); - if (sub != NULL) { - xc->volume = sub->vol; - use_ins_vol = 0; - } - } - } - } else { - /* invalid ins */ - - /* Ignore invalid instruments */ - xc->flags = 0; - use_ins_vol = 0; - } - } - - /* Check note */ - - if (e->note) { - SET(NEW_NOTE); - - if (e->note == XMP_KEY_OFF) { - SET_NOTE(NOTE_RELEASE); - use_ins_vol = 0; - } else if (is_toneporta) { - /* Always retrig in tone portamento: Fix portamento in - * 7spirits.s3m, mod.Biomechanoid - */ - if (not_same_ins) { - xc->offset.val = 0; - } - } else { - xc->key = e->note - 1; - RESET_NOTE(NOTE_END); - - sub = get_subinstrument(ctx, xc->ins, xc->key); - - if (sub != NULL) { - int transp = mod->xxi[xc->ins].map[xc->key].xpo; - int smp; - - note = xc->key + sub->xpo + transp; - smp = sub->sid; - - if (mod->xxs[smp].len == 0) { - smp = -1; - } - - if (smp >= 0 && smp < mod->smp) { - set_patch(ctx, chn, xc->ins, smp, note); - xc->smp = smp; - } - } else { - xc->flags = 0; - use_ins_vol = 0; - } - } - } - - sub = get_subinstrument(ctx, xc->ins, xc->key); - - set_effect_defaults(ctx, note, sub, xc, is_toneporta); - if (e->ins && sub != NULL) { - reset_envelopes(ctx, xc); - } - - /* Process new volume */ - if (e->vol) { - xc->volume = e->vol - 1; - SET(NEW_VOL); - } - - /* Secondary effect handled first */ - libxmp_process_fx(ctx, xc, chn, e, 1); - libxmp_process_fx(ctx, xc, chn, e, 0); - set_period(ctx, note, sub, xc, is_toneporta); - - if (sub == NULL) { - return 0; - } - - if (note >= 0) { - xc->note = note; - libxmp_virt_voicepos(ctx, chn, xc->offset.val); - } - - if (use_ins_vol && !TEST(NEW_VOL)) { - xc->volume = sub->vol; - } - - if (HAS_QUIRK(QUIRK_ST3BUGS) && TEST(NEW_VOL)) { - xc->volume = xc->volume * p->gvol / m->volbase; - } - - return 0; -} - -#ifndef LIBXMP_CORE_DISABLE_IT - -static inline void copy_channel(struct player_data *p, int to, int from) -{ - if (to > 0 && to != from) { - memcpy(&p->xc_data[to], &p->xc_data[from], - sizeof (struct channel_data)); - } -} - -static inline int has_note_event(struct xmp_event *e) -{ - return (e->note && e->note <= XMP_MAX_KEYS); -} - -static int check_fadeout(struct context_data *ctx, struct channel_data *xc, int ins) -{ - struct xmp_instrument *xxi = libxmp_get_instrument(ctx, ins); - - if (xxi == NULL) { - return 1; - } - - return (~xxi->aei.flg & XMP_ENVELOPE_ON || - ~xxi->aei.flg & XMP_ENVELOPE_CARRY || - xc->ins_fade == 0 || - xc->fadeout <= xc->ins_fade); -} - -static int check_invalid_sample(struct context_data *ctx, int ins, int key) -{ - struct module_data *m = &ctx->m; - struct xmp_module *mod = &m->mod; - - if (ins < mod->ins) { - int smp = mod->xxi[ins].map[key].ins; - if (smp == 0xff || smp >= mod->smp) { - return 1; - }; - } - - return 0; -} - -static void fix_period(struct context_data *ctx, int chn, struct xmp_subinstrument *sub) -{ - if (sub->nna == XMP_INST_NNA_CONT) { - struct player_data *p = &ctx->p; - struct channel_data *xc = &p->xc_data[chn]; - struct xmp_instrument *xxi = libxmp_get_instrument(ctx, xc->ins); - - xc->period = libxmp_note_to_period(ctx, xc->key + sub->xpo + - xxi->map[xc->key_porta].xpo, xc->finetune, xc->per_adj); - } -} - -static int is_same_sid(struct context_data *ctx, int chn, int ins, int key) -{ - struct player_data *p = &ctx->p; - struct channel_data *xc = &p->xc_data[chn]; - struct xmp_subinstrument *s1, *s2; - - s1 = get_subinstrument(ctx, ins, key); - s2 = get_subinstrument(ctx, xc->ins, xc->key); - - return (s1 && s2 && s1->sid == s2->sid); -} - -static int read_event_it(struct context_data *ctx, struct xmp_event *e, int chn) -{ - struct player_data *p = &ctx->p; - struct module_data *m = &ctx->m; - struct xmp_module *mod = &m->mod; - struct channel_data *xc = &p->xc_data[chn]; - int note, key; - struct xmp_subinstrument *sub; - int not_same_ins, not_same_smp; - int new_invalid_ins; - int is_toneporta, is_release; - int candidate_ins; - int reset_env; - int use_ins_vol; - int sample_mode; - int toneporta_offset; - int disabled_toneporta; - int retrig_ins; - struct xmp_event ev; - - memcpy(&ev, e, sizeof (struct xmp_event)); - - /* Emulate Impulse Tracker "always read instrument" bug */ - if (ev.ins) { - xc->delayed_ins = 0; - } else if (ev.note && xc->delayed_ins) { - ev.ins = xc->delayed_ins; - xc->delayed_ins = 0; - } - - xc->flags = 0; - note = -1; - key = ev.note; - not_same_ins = 0; - not_same_smp = 0; - new_invalid_ins = 0; - is_toneporta = 0; - is_release = 0; - reset_env = 0; - use_ins_vol = 0; - candidate_ins = xc->ins; - sample_mode = !HAS_QUIRK(QUIRK_VIRTUAL); - toneporta_offset = 0; - disabled_toneporta = 0; - retrig_ins = 0; - - /* Keyoff + instrument retrigs current instrument in old fx mode */ - if (HAS_QUIRK(QUIRK_ITOLDFX)) { - if (ev.note == XMP_KEY_OFF && IS_VALID_INSTRUMENT(ev.ins -1)) { - retrig_ins = 1; - } - } - - /* Notes with unmapped instruments are ignored */ - if (ev.ins) { - if (ev.ins <= mod->ins && has_note_event(&ev)) { - int ins = ev.ins - 1; - if (check_invalid_sample(ctx, ins, ev.note - 1)) { - candidate_ins = ins; - memset(&ev, 0, sizeof (ev)); - } - } - } else { - if (has_note_event(&ev)) { - int ins = xc->old_ins - 1; - if (!IS_VALID_INSTRUMENT(ins)) { - new_invalid_ins = 1; - } else if (check_invalid_sample(ctx, ins, ev.note - 1)) { - memset(&ev, 0, sizeof (ev)); - } - } - } - - if (IS_TONEPORTA(ev.fxt) || IS_TONEPORTA(ev.f2t)) { - is_toneporta = 1; - } - - if (TEST_NOTE(NOTE_RELEASE | NOTE_FADEOUT)) { - is_release = 1; - } - - if (xc->period <= 0 || TEST_NOTE(NOTE_END)) { - is_toneporta = 0; - } - - /* Off-Porta.it */ - if (is_toneporta && ev.fxt == FX_OFFSET) { - disabled_toneporta = 1; - is_toneporta = 0; - if (!HAS_QUIRK(QUIRK_PRENV)) { - toneporta_offset = 1; - RESET_NOTE(NOTE_ENV_END); - } - } - - /* Check instrument */ - - if (ev.ins) { - int ins = ev.ins - 1; - int set_new_ins = 1; - - /* portamento_after_keyoff.it test case */ - if (is_release && !key) { - if (is_toneporta) { - if (HAS_QUIRK(QUIRK_PRENV) || TEST_NOTE(NOTE_SET)) { - is_toneporta = 0; - reset_envelopes_carry(ctx, xc); - } - } else { - /* fixes OpenMPT wnoteoff.it */ - reset_envelopes_carry(ctx, xc); - } - } - - if (is_toneporta && xc->ins == ins) { - if (!HAS_QUIRK(QUIRK_PRENV)) { - if (is_same_sid(ctx, chn, ins, key - 1)) { - /* same instrument and same sample */ - set_new_ins = !is_release; - } else { - /* same instrument, different sample */ - not_same_ins = 1; /* need this too */ - not_same_smp = 1; - } - } - } - - if (set_new_ins) { - SET(NEW_INS); - use_ins_vol = 1; - reset_env = 1; - } - xc->per_flags = 0; - - if (IS_VALID_INSTRUMENT(ins)) { - /* valid ins */ - - /* See OpenMPT StoppedInstrSwap.it for cut case */ - if (!key && !TEST_NOTE(NOTE_KEY_CUT)) { - /* Retrig in new ins in sample mode */ - if (sample_mode && TEST_NOTE(NOTE_END)) { - libxmp_virt_voicepos(ctx, chn, 0); - } - - /* IT: Reset note for every new != ins */ - if (xc->ins == ins) { - SET(NEW_INS); - use_ins_vol = 1; - } else { - key = xc->key + 1; - } - - RESET_NOTE(NOTE_SET); - } - - if (xc->ins != ins && (!is_toneporta || !HAS_QUIRK(QUIRK_PRENV))) { - candidate_ins = ins; - - if (!is_same_sid(ctx, chn, ins, key - 1)) { - not_same_ins = 1; - if (is_toneporta) { - /* Get new instrument volume */ - sub = get_subinstrument(ctx, ins, key); - if (sub != NULL) { - xc->volume = sub->vol; - use_ins_vol = 0; - } - } - } - } - } else { - /* In sample mode invalid ins cut previous ins */ - if (sample_mode) { - xc->volume = 0; - } - - /* Ignore invalid instruments */ - new_invalid_ins = 1; - xc->flags = 0; - use_ins_vol = 0; - } - } - - /* Check note */ - - if (key && !new_invalid_ins) { - SET(NEW_NOTE); - SET_NOTE(NOTE_SET); - - if (key == XMP_KEY_FADE) { - SET_NOTE(NOTE_FADEOUT); - reset_env = 0; - use_ins_vol = 0; - } else if (key == XMP_KEY_CUT) { - SET_NOTE(NOTE_END | NOTE_CUT | NOTE_KEY_CUT); - xc->period = 0; - libxmp_virt_resetchannel(ctx, chn); - } else if (key == XMP_KEY_OFF) { - struct xmp_envelope *env = NULL; - if (IS_VALID_INSTRUMENT(xc->ins)) { - env = &mod->xxi[xc->ins].aei; - } - if (sustain_check(env, xc->v_idx)) { - SET_NOTE(NOTE_SUSEXIT); - } else { - SET_NOTE(NOTE_RELEASE); - } - SET(KEY_OFF); - reset_env = 0; - use_ins_vol = 0; - } else { - /* portamento_after_keyoff.it test case */ - /* also see suburban_streets o13 c45 */ - if (ev.ins || !is_toneporta) { - if (!disabled_toneporta) { - reset_env = 1; - } - } - - if (is_toneporta) { - if (not_same_ins || TEST_NOTE(NOTE_END)) { - SET(NEW_INS); - RESET_NOTE(NOTE_RELEASE|NOTE_SUSEXIT|NOTE_FADEOUT); - } else { - if (is_valid_note(key - 1)) { - xc->key_porta = key - 1; - } - key = 0; - } - } - } - } - - if (is_valid_note(key - 1) && !new_invalid_ins) { - if (TEST_NOTE(NOTE_CUT)) { - use_ins_vol = 1; /* See OpenMPT NoteOffInstr.it */ - } - xc->key = --key; - RESET_NOTE(NOTE_END); - - sub = get_subinstrument(ctx, candidate_ins, key); - - if (sub != NULL) { - int transp = mod->xxi[candidate_ins].map[key].xpo; - int smp, to; - int rvv; - - note = key + sub->xpo + transp; - smp = sub->sid; - if (smp >= mod->smp || mod->xxs[smp].len == 0) { - smp = -1; - } - - if (not_same_smp) { - fix_period(ctx, chn, sub); - libxmp_virt_resetchannel(ctx, chn); - } - to = libxmp_virt_setpatch(ctx, chn, candidate_ins, smp, - note, sub->nna, sub->dct, sub->dca); - - /* Random value for volume swing */ - rvv = sub->rvv & 0xff; - if (rvv) { - CLAMP(rvv, 0, 100); - xc->rvv = rand() % (rvv + 1); - } else { - xc->rvv = 0; - } - - /* Random value for pan swing */ - rvv = (sub->rvv & 0xff00) >> 8; - if (rvv) { - CLAMP(rvv, 0, 64); - xc->rpv = rand() % (rvv + 1) - (rvv / 2); - } else { - xc->rpv = 0; - } - - if (to < 0) - return -1; - if (to != chn) { - copy_channel(p, to, chn); - p->xc_data[to].flags = 0; - } - - if (smp >= 0) { /* Not sure if needed */ - xc->smp = smp; - } - } else { - xc->flags = 0; - use_ins_vol = 0; - } - } - - /* Do after virtual channel copy */ - if (is_toneporta || retrig_ins) { - if (HAS_QUIRK(QUIRK_PRENV) && ev.ins) { - reset_envelopes_carry(ctx, xc); - } - } - - if (IS_VALID_INSTRUMENT(candidate_ins)) { - if (xc->ins != candidate_ins) { - /* Reset envelopes if instrument changes */ - reset_envelopes(ctx, xc); - } - xc->ins = candidate_ins; - xc->ins_fade = mod->xxi[candidate_ins].rls; - } - - /* Reset in case of new instrument and the previous envelope has - * finished (OpenMPT test EnvReset.it). This must take place after - * channel copies in case of NNA (see test/test.it) - * Also if we have envelope in carry mode, check fadeout - */ - if (ev.ins && TEST_NOTE(NOTE_ENV_END)) { - if (check_fadeout(ctx, xc, candidate_ins)) { - reset_envelopes(ctx, xc); - } else { - reset_env = 0; - } - } - - if (reset_env) { - if (ev.note) { - RESET_NOTE(NOTE_RELEASE|NOTE_SUSEXIT|NOTE_FADEOUT); - } - /* Set after copying to new virtual channel (see ambio.it) */ - xc->fadeout = 0x10000; - } - - /* See OpenMPT wnoteoff.it vs noteoff3.it */ - if (retrig_ins && not_same_ins) { - SET(NEW_INS); - libxmp_virt_voicepos(ctx, chn, 0); - xc->fadeout = 0x10000; - RESET_NOTE(NOTE_RELEASE|NOTE_SUSEXIT|NOTE_FADEOUT); - } - - sub = get_subinstrument(ctx, xc->ins, xc->key); - - set_effect_defaults(ctx, note, sub, xc, is_toneporta); - if (sub != NULL) { - if (note >= 0) { - /* Reset pan, see OpenMPT PanReset.it */ - if (sub->pan >= 0) { - xc->pan.val = sub->pan; - xc->pan.surround = 0; - } - - if (TEST_NOTE(NOTE_CUT)) { - reset_envelopes(ctx, xc); - } else if (!toneporta_offset) { - reset_envelopes_carry(ctx, xc); - } - RESET_NOTE(NOTE_CUT); - } - } - - /* Process new volume */ - if (ev.vol && (!TEST_NOTE(NOTE_CUT) || ev.ins != 0)) { - if (key != XMP_KEY_OFF) { /* See OpenMPT NoteOffInstr.it */ - xc->volume = ev.vol - 1; - SET(NEW_VOL); - } - } - - /* IT: always reset sample offset */ - xc->offset.val &= ~0xffff; - - /* According to Storlek test 25, Impulse Tracker handles the volume - * column effects after the standard effects. - */ - libxmp_process_fx(ctx, xc, chn, &ev, 0); - libxmp_process_fx(ctx, xc, chn, &ev, 1); - set_period(ctx, note, sub, xc, is_toneporta); - - if (sub == NULL) { - return 0; - } - - if (note >= 0) { - xc->note = note; - libxmp_virt_voicepos(ctx, chn, xc->offset.val); - } - - if (use_ins_vol && !TEST(NEW_VOL)) { - xc->volume = sub->vol; - } - - return 0; -} - -#endif - -#ifndef LIBXMP_CORE_PLAYER - -static int read_event_med(struct context_data *ctx, struct xmp_event *e, int chn) -{ - struct player_data *p = &ctx->p; - struct module_data *m = &ctx->m; - struct xmp_module *mod = &m->mod; - struct channel_data *xc = &p->xc_data[chn]; - int note; - struct xmp_subinstrument *sub; - int new_invalid_ins = 0; - int is_toneporta; - int use_ins_vol; - int finetune; - - xc->flags = 0; - note = -1; - is_toneporta = 0; - use_ins_vol = 0; - - if (e->fxt == FX_TONEPORTA || e->fxt == FX_TONE_VSLIDE) { - is_toneporta = 1; - } - - /* Check instrument */ - - if (e->ins && e->note) { - int ins = e->ins - 1; - use_ins_vol = 1; - SET(NEW_INS); - xc->fadeout = 0x10000; - xc->offset.val = 0; - RESET_NOTE(NOTE_RELEASE|NOTE_FADEOUT); - - if (IS_VALID_INSTRUMENT(ins)) { - if (is_toneporta) { - /* Get new instrument volume */ - sub = get_subinstrument(ctx, ins, e->note - 1); - if (sub != NULL) { - xc->volume = sub->vol; - use_ins_vol = 0; - } - } else { - xc->ins = ins; - xc->ins_fade = mod->xxi[ins].rls; - } - } else { - new_invalid_ins = 1; - libxmp_virt_resetchannel(ctx, chn); - } - - MED_CHANNEL_EXTRAS(*xc)->arp = 0; - MED_CHANNEL_EXTRAS(*xc)->aidx = 0; - } else { - /* Hold */ - if (e->ins && !e->note) { - use_ins_vol = 1; - } - } - - /* Check note */ - - if (e->note) { - SET(NEW_NOTE); - - if (e->note == XMP_KEY_OFF) { - SET_NOTE(NOTE_RELEASE); - use_ins_vol = 0; - } else if (e->note == XMP_KEY_CUT) { - SET_NOTE(NOTE_END); - xc->period = 0; - libxmp_virt_resetchannel(ctx, chn); - } else if (!is_toneporta && IS_VALID_INSTRUMENT(xc->ins)) { - struct xmp_instrument *xxi = &mod->xxi[xc->ins]; - - xc->key = e->note - 1; - RESET_NOTE(NOTE_END); - - xc->per_adj = 0.0; - if (xxi->nsm > 1 && HAS_MED_INSTRUMENT_EXTRAS(*xxi)) { - /* synth or iffoct */ - if (MED_INSTRUMENT_EXTRAS(*xxi)->vts == 0 && - MED_INSTRUMENT_EXTRAS(*xxi)->wts == 0) { - /* iffoct */ - xc->per_adj = 2.0; - } - } - - sub = get_subinstrument(ctx, xc->ins, xc->key); - - if (!new_invalid_ins && sub != NULL) { - int transp = xxi->map[xc->key].xpo; - int smp; - - note = xc->key + sub->xpo + transp; - smp = sub->sid; - - if (mod->xxs[smp].len == 0) { - smp = -1; - } - - if (smp >= 0 && smp < mod->smp) { - set_patch(ctx, chn, xc->ins, smp, note); - xc->smp = smp; - } - } else { - xc->flags = 0; - use_ins_vol = 0; - } - } - } - - sub = get_subinstrument(ctx, xc->ins, xc->key); - - /* Keep effect-set finetune if no instrument set */ - finetune = xc->finetune; - set_effect_defaults(ctx, note, sub, xc, is_toneporta); - if (!e->ins) { - xc->finetune = finetune; - } - - if (e->ins && sub != NULL) { - reset_envelopes(ctx, xc); - } - - /* Process new volume */ - if (e->vol) { - xc->volume = e->vol - 1; - SET(NEW_VOL); - } - - /* Secondary effect handled first */ - libxmp_process_fx(ctx, xc, chn, e, 1); - libxmp_process_fx(ctx, xc, chn, e, 0); - set_period(ctx, note, sub, xc, is_toneporta); - - if (sub == NULL) { - return 0; - } - - if (note >= 0) { - xc->note = note; - libxmp_virt_voicepos(ctx, chn, xc->offset.val); - } - - if (use_ins_vol && !TEST(NEW_VOL)) { - xc->volume = sub->vol; - } - - return 0; -} - -#endif - -static int read_event_smix(struct context_data *ctx, struct xmp_event *e, int chn) -{ - struct player_data *p = &ctx->p; - struct smix_data *smix = &ctx->smix; - struct module_data *m = &ctx->m; - struct xmp_module *mod = &m->mod; - struct channel_data *xc = &p->xc_data[chn]; - struct xmp_subinstrument *sub; - int is_smix_ins; - int ins, note, transp, smp; - - xc->flags = 0; - - if (!e->ins) - return 0; - - is_smix_ins = 0; - ins = e->ins - 1; - SET(NEW_INS); - xc->fadeout = 0x10000; - xc->per_flags = 0; - xc->offset.val = 0; - RESET_NOTE(NOTE_RELEASE); - - xc->ins = ins; - - if (ins >= mod->ins && ins < mod->ins + smix->ins) { - is_smix_ins = 1; - xc->ins_fade = smix->xxi[xc->ins - mod->ins].rls; - } - - SET(NEW_NOTE); - - if (e->note == XMP_KEY_OFF) { - SET_NOTE(NOTE_RELEASE); - return 0; - } - - xc->key = e->note - 1; - RESET_NOTE(NOTE_END); - - if (is_smix_ins) { - sub = &smix->xxi[xc->ins - mod->ins].sub[0]; - if (sub == NULL) { - return 0; - } - - note = xc->key + sub->xpo; - smp = sub->sid; - if (smix->xxs[smp].len == 0) - smp = -1; - if (smp >= 0 && smp < smix->smp) { - smp += mod->smp; - set_patch(ctx, chn, xc->ins, smp, note); - xc->smp = smp; - } - } else { - transp = mod->xxi[xc->ins].map[xc->key].xpo; - sub = get_subinstrument(ctx, xc->ins, xc->key); - if (sub == NULL) { - return 0; - } - note = xc->key + sub->xpo + transp; - smp = sub->sid; - if (mod->xxs[smp].len == 0) - smp = -1; - if (smp >= 0 && smp < mod->smp) { - set_patch(ctx, chn, xc->ins, smp, note); - xc->smp = smp; - } - } - - set_effect_defaults(ctx, note, sub, xc, 0); - set_period(ctx, note, sub, xc, 0); - - if (e->ins) { - reset_envelopes(ctx, xc); - } - - xc->volume = e->vol - 1; - - xc->note = note; - libxmp_virt_voicepos(ctx, chn, xc->offset.val); - - return 0; -} - -int libxmp_read_event(struct context_data *ctx, struct xmp_event *e, int chn) -{ - struct player_data *p = &ctx->p; - struct module_data *m = &ctx->m; - struct channel_data *xc = &p->xc_data[chn]; - - if (e->ins != 0) - xc->old_ins = e->ins; - - if (TEST_NOTE(NOTE_SAMPLE_END)) { - SET_NOTE(NOTE_END); - } - - if (chn >= m->mod.chn) { - return read_event_smix(ctx, e, chn); - } else switch (m->read_event_type) { - case READ_EVENT_MOD: - return read_event_mod(ctx, e, chn); - case READ_EVENT_FT2: - return read_event_ft2(ctx, e, chn); - case READ_EVENT_ST3: - return read_event_st3(ctx, e, chn); -#ifndef LIBXMP_CORE_DISABLE_IT - case READ_EVENT_IT: - return read_event_it(ctx, e, chn); -#endif -#ifndef LIBXMP_CORE_PLAYER - case READ_EVENT_MED: - return read_event_med(ctx, e, chn); -#endif - default: - return read_event_mod(ctx, e, chn); - } -} diff --git a/source/libxmp-lite/src/s3m.h b/source/libxmp-lite/src/s3m.h deleted file mode 100644 index 56717c57a..000000000 --- a/source/libxmp-lite/src/s3m.h +++ /dev/null @@ -1,116 +0,0 @@ -/* Extended Module Player - * 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"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -/* S3M packed pattern macros */ -#define S3M_EOR 0 /* End of row */ -#define S3M_CH_MASK 0x1f /* Channel */ -#define S3M_NI_FOLLOW 0x20 /* Note and instrument follow */ -#define S3M_VOL_FOLLOWS 0x40 /* Volume follows */ -#define S3M_FX_FOLLOWS 0x80 /* Effect and parameter follow */ - -/* S3M channel info macros */ -#define S3M_CH_ON 0x80 /* Psi says it's bit 8, I'll assume bit 7 */ -#define S3M_CH_OFF 0xff -#define S3M_CH_PAN 0x7f /* Left/Right */ - -/* S3M channel pan macros */ -#define S3M_PAN_SET 0x20 -#define S3M_PAN_MASK 0x0f - -/* S3M flags */ -#define S3M_ST2_VIB 0x01 /* Not recognized */ -#define S3M_ST2_TEMPO 0x02 /* Not recognized */ -#define S3M_AMIGA_SLIDE 0x04 /* Not recognized */ -#define S3M_VOL_OPT 0x08 /* Not recognized */ -#define S3M_AMIGA_RANGE 0x10 -#define S3M_SB_FILTER 0x20 /* Not recognized */ -#define S3M_ST300_VOLS 0x40 -#define S3M_CUSTOM_DATA 0x80 /* Not recognized */ - -/* S3M Adlib instrument types */ -#define S3M_INST_SAMPLE 0x01 -#define S3M_INST_AMEL 0x02 -#define S3M_INST_ABD 0x03 -#define S3M_INST_ASNARE 0x04 -#define S3M_INST_ATOM 0x05 -#define S3M_INST_ACYM 0x06 -#define S3M_INST_AHIHAT 0x07 - -struct s3m_file_header { - uint8 name[28]; /* Song name */ - uint8 doseof; /* 0x1a */ - uint8 type; /* File type */ - uint8 rsvd1[2]; /* Reserved */ - uint16 ordnum; /* Number of orders (must be even) */ - uint16 insnum; /* Number of instruments */ - uint16 patnum; /* Number of patterns */ - uint16 flags; /* Flags */ - uint16 version; /* Tracker ID and version */ - uint16 ffi; /* File format information */ - uint32 magic; /* 'SCRM' */ - uint8 gv; /* Global volume */ - uint8 is; /* Initial speed */ - uint8 it; /* Initial tempo */ - uint8 mv; /* Master volume */ - uint8 uc; /* Ultra click removal */ - uint8 dp; /* Default pan positions if 0xfc */ - uint8 rsvd2[8]; /* Reserved */ - uint16 special; /* Ptr to special custom data */ - uint8 chset[32]; /* Channel settings */ -}; - -struct s3m_instrument_header { - uint8 dosname[13]; /* DOS file name */ - uint16 memseg; /* Pointer to sample data */ - uint32 length; /* Length */ - uint32 loopbeg; /* Loop begin */ - uint32 loopend; /* Loop end */ - uint8 vol; /* Volume */ - uint8 rsvd1; /* Reserved */ - uint8 pack; /* Packing type (not used) */ - uint8 flags; /* Loop/stereo/16bit samples flags */ - uint16 c2spd; /* C 4 speed */ - uint16 rsvd2; /* Reserved */ - uint8 rsvd3[4]; /* Reserved */ - uint16 int_gp; /* Internal - GUS pointer */ - uint16 int_512; /* Internal - SB pointer */ - uint32 int_last; /* Internal - SB index */ - uint8 name[28]; /* Instrument name */ - uint32 magic; /* 'SCRS' */ -}; - -#ifndef LIBXMP_CORE_PLAYER -struct s3m_adlib_header { - uint8 dosname[12]; /* DOS file name */ - uint8 rsvd1[3]; /* 0x00 0x00 0x00 */ - uint8 reg[12]; /* Adlib registers */ - uint8 vol; - uint8 dsk; - uint8 rsvd2[2]; - uint16 c2spd; /* C 4 speed */ - uint16 rsvd3; /* Reserved */ - uint8 rsvd4[12]; /* Reserved */ - uint8 name[28]; /* Instrument name */ - uint32 magic; /* 'SCRI' */ -}; -#endif - diff --git a/source/libxmp-lite/src/s3m_load.c b/source/libxmp-lite/src/s3m_load.c deleted file mode 100644 index 611fb0bd6..000000000 --- a/source/libxmp-lite/src/s3m_load.c +++ /dev/null @@ -1,661 +0,0 @@ -/* Extended Module Player - * 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"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -/* - * Tue, 30 Jun 1998 20:23:11 +0200 - * Reported by John v/d Kamp : - * I have this song from Purple Motion called wcharts.s3m, the global - * volume was set to 0, creating a devide by 0 error in xmp. There should - * be an extra test if it's 0 or not. - * - * Claudio's fix: global volume ignored - */ - -/* - * Sat, 29 Aug 1998 18:50:43 -0500 (CDT) - * Reported by Joel Jordan : - * S3M files support tempos outside the ranges defined by xmp (that is, - * the MOD/XM tempo ranges). S3M's can have tempos from 0 to 255 and speeds - * from 0 to 255 as well, since these are handled with separate effects - * unlike the MOD format. This becomes an issue in such songs as Skaven's - * "Catch that Goblin", which uses speeds above 0x1f. - * - * Claudio's fix: FX_S3M_SPEED added. S3M supports speeds from 0 to 255 and - * tempos from 32 to 255 (S3M speed == xmp tempo, S3M tempo == xmp BPM). - */ - -/* Wed, 21 Oct 1998 15:03:44 -0500 Geoff Reedy - * It appears that xmp has issues loading/playing a specific instrument - * used in LUCCA.S3M. - * (Fixed by Hipolito in xmp-2.0.0dev34) - */ - -/* - * From http://code.pui.ch/2007/02/18/turn-demoscene-modules-into-mp3s/ - * The only flaw I noticed [in xmp] is a problem with portamento in Purple - * Motion's second reality soundtrack (1:06-1:17) - * - * Claudio's note: that's a dissonant beating between channels 6 and 7 - * starting at pos12, caused by pitchbending effect F25. - */ - -/* - * From: Ralf Hoffmann - * Date: Wed, 26 Sep 2007 17:12:41 +0200 - * ftp://ftp.scenesp.org/pub/compilations/modplanet/normal/bonuscd/artists/ - * Iq/return%20of%20litmus.s3m doesn't start playing, just uses 100% cpu, - * the number of patterns is unusually high - * - * Claudio's fix: this module seems to be a bad conversion, bad rip or - * simply corrupted since it has many instances of 0x87 instead of 0x00 - * in the module and instrument headers. I'm adding a simple workaround - * to be able to load/play the module as is, see the fix87() macro below. - */ - -#include "loader.h" -#include "s3m.h" -#include "period.h" - -#define MAGIC_SCRM MAGIC4('S','C','R','M') -#define MAGIC_SCRI MAGIC4('S','C','R','I') -#define MAGIC_SCRS MAGIC4('S','C','R','S') - -static int s3m_test(HIO_HANDLE *, char *, const int); -static int s3m_load(struct module_data *, HIO_HANDLE *, const int); - -extern const struct format_loader libxmp_loader_s3m; -const struct format_loader libxmp_loader_s3m = { - "Scream Tracker 3", - s3m_test, - s3m_load -}; - -static int s3m_test(HIO_HANDLE *f, char *t, const int start) -{ - hio_seek(f, start + 44, SEEK_SET); - if (hio_read32b(f) != MAGIC_SCRM) - return -1; - - hio_seek(f, start + 29, SEEK_SET); - if (hio_read8(f) != 0x10) - return -1; - - hio_seek(f, start + 0, SEEK_SET); - libxmp_read_title(f, t, 28); - - return 0; -} - -#define NONE 0xff -#define FX_S3M_EXTENDED 0xfe - -#define fix87(x) do { \ - int i; for (i = 0; i < sizeof(x); i++) { \ - if (*((uint8 *)&x + i) == 0x87) *((uint8 *)&x + i) = 0; } \ - } while (0) - -/* Effect conversion table */ -static const uint8 fx[] = { - NONE, - FX_S3M_SPEED, /* Axx Set speed to xx (the default is 06) */ - FX_JUMP, /* Bxx Jump to order xx (hexadecimal) */ - FX_BREAK, /* Cxx Break pattern to row xx (decimal) */ - FX_VOLSLIDE, /* Dxy Volume slide down by y/up by x */ - FX_PORTA_DN, /* Exx Slide down by xx */ - FX_PORTA_UP, /* Fxx Slide up by xx */ - FX_TONEPORTA, /* Gxx Tone portamento with speed xx */ - FX_VIBRATO, /* Hxy Vibrato with speed x and depth y */ - FX_TREMOR, /* Ixy Tremor with ontime x and offtime y */ - FX_S3M_ARPEGGIO, /* Jxy Arpeggio with halfnote additions */ - FX_VIBRA_VSLIDE, /* Kxy Dual command: H00 and Dxy */ - FX_TONE_VSLIDE, /* Lxy Dual command: G00 and Dxy */ - NONE, - NONE, - FX_OFFSET, /* Oxy Set sample offset */ - NONE, - FX_MULTI_RETRIG, /* Qxy Retrig (+volumeslide) note */ - FX_TREMOLO, /* Rxy Tremolo with speed x and depth y */ - FX_S3M_EXTENDED, /* Sxx (misc effects) */ - FX_S3M_BPM, /* Txx Tempo = xx (hex) */ - FX_FINE_VIBRATO, /* Uxx Fine vibrato */ - FX_GLOBALVOL, /* Vxx Set global volume */ - NONE, - FX_SETPAN, /* Xxx Set pan */ - NONE, - NONE -}; - -/* Effect translation */ -static void xlat_fx(int c, struct xmp_event *e) -{ - uint8 h = MSN(e->fxp), l = LSN(e->fxp); - - if (e->fxt > 26) { - D_(D_WARN "invalid effect %02x", e->fxt); - e->fxt = e->fxp = 0; - return; - } - - switch (e->fxt = fx[e->fxt]) { - case FX_S3M_BPM: - if (e->fxp < 0x20) { - e->fxp = e->fxt = 0; - } - break; - case FX_S3M_EXTENDED: /* Extended effects */ - e->fxt = FX_EXTENDED; - switch (h) { - case 0x1: /* Glissando */ - e->fxp = LSN(e->fxp) | (EX_GLISS << 4); - break; - case 0x2: /* Finetune */ - e->fxp = - ((LSN(e->fxp) - 8) & 0x0f) | (EX_FINETUNE << 4); - break; - case 0x3: /* Vibrato wave */ - e->fxp = LSN(e->fxp) | (EX_VIBRATO_WF << 4); - break; - case 0x4: /* Tremolo wave */ - e->fxp = LSN(e->fxp) | (EX_TREMOLO_WF << 4); - break; - case 0x5: - case 0x6: - case 0x7: - case 0x9: - case 0xa: /* Ignore */ - e->fxt = e->fxp = 0; - break; - case 0x8: /* Set pan */ - e->fxt = FX_SETPAN; - e->fxp = l << 4; - break; - case 0xb: /* Pattern loop */ - e->fxp = LSN(e->fxp) | (EX_PATTERN_LOOP << 4); - break; - case 0xc: - if (!l) - e->fxt = e->fxp = 0; - } - break; - case FX_SETPAN: - /* Saga Musix says: "The X effect in S3M files is not - * exclusive to IT and clones. You will find tons of S3Ms made - * with ST3 itself using this effect (and relying on an - * external player being used). X in S3M also behaves - * differently than in IT, which your code does not seem to - * handle: X00 - X80 is left... right, XA4 is surround (like - * S91 in IT), other values are not supposed to do anything. - */ - if (e->fxp == 0xa4) { - // surround - e->fxt = FX_SURROUND; - e->fxp = 1; - } else { - int pan = ((int)e->fxp) << 1; - if (pan > 0xff) { - pan = 0xff; - } - e->fxp = pan; - } - break; - case NONE: /* No effect */ - e->fxt = e->fxp = 0; - break; - } -} - -static int s3m_load(struct module_data *m, HIO_HANDLE * f, const int start) -{ - struct xmp_module *mod = &m->mod; - int c, r, i; - struct xmp_event *event = 0, dummy; - struct s3m_file_header sfh; - struct s3m_instrument_header sih; -#ifndef LIBXMP_CORE_PLAYER - struct s3m_adlib_header sah; - char tracker_name[40]; - int quirk87 = 0; -#endif - int pat_len; - uint8 n, b; - uint16 *pp_ins; /* Parapointers to instruments */ - uint16 *pp_pat; /* Parapointers to patterns */ - int ret; - uint8 buf[96] - - LOAD_INIT(); - - if (hio_read(buf, 1, 96, f) != 96) { - goto err; - } - - memcpy(&sfh.name, buf, 28); /* Song name */ - sfh.type = buf[30]; /* File type */ - sfh.ordnum = readmem16l(buf + 32); /* Number of orders (must be even) */ - sfh.insnum = readmem16l(buf + 34); /* Number of instruments */ - sfh.patnum = readmem16l(buf + 36); /* Number of patterns */ - sfh.flags = readmem16l(buf + 38); /* Flags */ - sfh.version = readmem16l(buf + 40); /* Tracker ID and version */ - sfh.ffi = readmem16l(buf + 42); /* File format information */ - - /* Sanity check */ - if (sfh.ffi != 1 && sfh.ffi != 2) { - goto err; - } - if (sfh.ordnum > 255 || sfh.insnum > 255 || sfh.patnum > 255) { - goto err; - } - - sfh.magic = readmem32b(buf + 44); /* 'SCRM' */ - sfh.gv = buf[48]; /* Global volume */ - sfh.is = buf[49]; /* Initial speed */ - sfh.it = buf[50]; /* Initial tempo */ - 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 */ - sfh.special = readmem16l(buf + 62); /* Ptr to special custom data */ - memcpy(sfh.chset, buf + 64, 32); /* Channel settings */ - - if (sfh.magic != MAGIC_SCRM) { - goto err; - } - -#ifndef LIBXMP_CORE_PLAYER - /* S3M anomaly in return_of_litmus.s3m */ - if (sfh.version == 0x1301 && sfh.name[27] == 0x87) - quirk87 = 1; - - if (quirk87) { - fix87(sfh.name); - fix87(sfh.patnum); - fix87(sfh.flags); - } -#endif - - libxmp_copy_adjust(mod->name, sfh.name, 28); - - pp_ins = (uint16 *)calloc(2, sfh.insnum); - if (pp_ins == NULL) { - goto err; - } - - pp_pat = (uint16 *)calloc(2, sfh.patnum); - if (pp_pat == NULL) { - goto err2; - } - - if (sfh.flags & S3M_AMIGA_RANGE) { - m->period_type = PERIOD_MODRNG; - } - if (sfh.flags & S3M_ST300_VOLS) { - m->quirk |= QUIRK_VSALL; - } - /* m->volbase = 4096 / sfh.gv; */ - mod->spd = sfh.is; - mod->bpm = sfh.it; - mod->chn = 0; - - for (i = 0; i < 32; i++) { - if (sfh.chset[i] == S3M_CH_OFF) - continue; - - mod->chn = i + 1; - - if (sfh.mv & 0x80) { /* stereo */ - int x = sfh.chset[i] & S3M_CH_PAN; - mod->xxc[i].pan = (x & 0x0f) < 8 ? 0x30 : 0xc0; - } else { - mod->xxc[i].pan = 0x80; - } - } - - if (sfh.ordnum <= XMP_MAX_MOD_LENGTH) { - mod->len = sfh.ordnum; - if (hio_read(mod->xxo, 1, mod->len, f) != mod->len) { - goto err3; - } - } else { - mod->len = XMP_MAX_MOD_LENGTH; - if (hio_read(mod->xxo, 1, mod->len, f) != mod->len) { - goto err3; - } - if (hio_seek(f, sfh.ordnum - XMP_MAX_MOD_LENGTH, SEEK_CUR) < 0) { - goto err3; - } - } - - /* Don't trust sfh.patnum */ - mod->pat = -1; - for (i = 0; i < mod->len; ++i) { - if (mod->xxo[i] < 0xfe && mod->xxo[i] > mod->pat) { - mod->pat = mod->xxo[i]; - } - } - mod->pat++; - if (mod->pat > sfh.patnum) { - mod->pat = sfh.patnum; - } - if (mod->pat == 0) { - goto err3; - } - - mod->trk = mod->pat * mod->chn; - /* Load and convert header */ - mod->ins = sfh.insnum; - mod->smp = mod->ins; - - for (i = 0; i < sfh.insnum; i++) { - pp_ins[i] = hio_read16l(f); - } - - for (i = 0; i < sfh.patnum; i++) { - pp_pat[i] = hio_read16l(f); - } - - /* Default pan positions */ - - for (i = 0, sfh.dp -= 0xfc; !sfh.dp /* && n */ && (i < 32); i++) { - uint8 x = hio_read8(f); - if (x & S3M_PAN_SET) { - mod->xxc[i].pan = (x << 4) & 0xff; - } else { - mod->xxc[i].pan = - sfh.mv % 0x80 ? 0x30 + 0xa0 * (i & 1) : 0x80; - } - } - - m->c4rate = C4_NTSC_RATE; - - if (sfh.version == 0x1300) { - m->quirk |= QUIRK_VSALL; - } - -#ifndef LIBXMP_CORE_PLAYER - switch (sfh.version >> 12) { - case 1: - snprintf(tracker_name, 40, "Scream Tracker %d.%02x", - (sfh.version & 0x0f00) >> 8, sfh.version & 0xff); - m->quirk |= QUIRK_ST3BUGS; - break; - case 2: - snprintf(tracker_name, 40, "Imago Orpheus %d.%02x", - (sfh.version & 0x0f00) >> 8, sfh.version & 0xff); - break; - case 3: - if (sfh.version == 0x3216) { - strcpy(tracker_name, "Impulse Tracker 2.14v3"); - } else if (sfh.version == 0x3217) { - strcpy(tracker_name, "Impulse Tracker 2.14v5"); - } else { - snprintf(tracker_name, 40, "Impulse Tracker %d.%02x", - (sfh.version & 0x0f00) >> 8, - sfh.version & 0xff); - } - break; - case 5: - snprintf(tracker_name, 40, "OpenMPT %d.%02x", - (sfh.version & 0x0f00) >> 8, sfh.version & 0xff); - m->quirk |= QUIRK_ST3BUGS; - break; - case 4: - if (sfh.version != 0x4100) { - snprintf(tracker_name, 40, "Schism Tracker %d.%02x", - (sfh.version & 0x0f00) >> 8, - sfh.version & 0xff); - break; - } - /* fall through */ - case 6: - snprintf(tracker_name, 40, "BeRoTracker %d.%02x", - (sfh.version & 0x0f00) >> 8, sfh.version & 0xff); - break; - default: - snprintf(tracker_name, 40, "unknown (%04x)", sfh.version); - } - - libxmp_set_type(m, "%s S3M", tracker_name); -#else - libxmp_set_type(m, "Scream Tracker 3"); - m->quirk |= QUIRK_ST3BUGS; -#endif - - MODULE_INFO(); - - if (libxmp_init_pattern(mod) < 0) - goto err3; - - /* Read patterns */ - - D_(D_INFO "Stored patterns: %d", mod->pat); - - for (i = 0; i < mod->pat; i++) { - if (libxmp_alloc_pattern_tracks(mod, i, 64) < 0) - goto err3; - - if (pp_pat[i] == 0) - continue; - - hio_seek(f, start + pp_pat[i] * 16, SEEK_SET); - r = 0; - pat_len = hio_read16l(f) - 2; - - while (pat_len >= 0 && r < mod->xxp[i]->rows) { - b = hio_read8(f); - - if (hio_error(f)) { - goto err3; - } - - if (b == S3M_EOR) { - r++; - continue; - } - - c = b & S3M_CH_MASK; - event = c >= mod->chn ? &dummy : &EVENT(i, c, r); - - if (b & S3M_NI_FOLLOW) { - switch (n = hio_read8(f)) { - case 255: - n = 0; - break; /* Empty note */ - case 254: - n = XMP_KEY_OFF; - break; /* Key off */ - default: - n = 13 + 12 * MSN(n) + LSN(n); - } - event->note = n; - event->ins = hio_read8(f); - pat_len -= 2; - } - - if (b & S3M_VOL_FOLLOWS) { - event->vol = hio_read8(f) + 1; - pat_len--; - } - - if (b & S3M_FX_FOLLOWS) { - event->fxt = hio_read8(f); - event->fxp = hio_read8(f); - xlat_fx(c, event); - - pat_len -= 2; - } - } - } - - D_(D_INFO "Stereo enabled: %s", sfh.mv & 0x80 ? "yes" : "no"); - D_(D_INFO "Pan settings: %s", sfh.dp ? "no" : "yes"); - - if (libxmp_init_instrument(m) < 0) - goto err3; - - /* Read and convert instruments and samples */ - - D_(D_INFO "Instruments: %d", mod->ins); - - for (i = 0; i < mod->ins; i++) { - struct xmp_instrument *xxi = &mod->xxi[i]; - struct xmp_sample *xxs = &mod->xxs[i]; - struct xmp_subinstrument *sub; - - xxi->sub = (struct xmp_subinstrument *)calloc(sizeof(struct xmp_subinstrument), 1); - if (xxi->sub == NULL) { - goto err3; - } - - sub = &xxi->sub[0]; - - hio_seek(f, start + pp_ins[i] * 16, SEEK_SET); - sub->pan = 0x80; - sub->sid = i; - - if (hio_read(buf, 1, 80, f) != 80) { - goto err3; - } - - if (buf[0] >= 2) { -#ifndef LIBXMP_CORE_PLAYER - /* OPL2 FM instrument */ - - memcpy(sah.dosname, buf + 1, 12); /* DOS file name */ - memcpy(sah.reg, buf + 16, 12); /* Adlib registers */ - sah.vol = buf[28]; - sah.dsk = buf[29]; - sah.c2spd = readmem16l(buf + 32); /* C4 speed */ - memcpy(sah.name, buf + 48, 28); /* Instrument name */ - sah.magic = readmem32b(buf + 76); /* 'SCRI' */ - - if (sah.magic != MAGIC_SCRI) { - D_(D_CRIT "error: FM instrument magic"); - goto err3; - } - sah.magic = 0; - - libxmp_instrument_name(mod, i, sah.name, 28); - - xxi->nsm = 1; - sub->vol = sah.vol; - libxmp_c2spd_to_note(sah.c2spd, &sub->xpo, &sub->fin); - sub->xpo += 12; - ret = - libxmp_load_sample(m, f, SAMPLE_FLAG_ADLIB, xxs, - (char *)&sah.reg); - if (ret < 0) - goto err3; - - D_(D_INFO "[%2X] %-28.28s", i, xxi->name); - - continue; -#else - goto err3; -#endif - } - - memcpy(sih.dosname, buf + 1, 13); /* DOS file name */ - sih.memseg = readmem16l(buf + 14); /* Pointer to sample data */ - sih.length = readmem32l(buf + 16); /* Length */ - -#if 0 - /* ST3 limit */ - if ((sfh.version >> 12) == 1 && sih.length > 64000) - sih.length = 64000; -#endif - - if (sih.length > MAX_SAMPLE_SIZE) { - goto err3; - } - - sih.loopbeg = readmem32l(buf + 20); /* Loop begin */ - sih.loopend = readmem32l(buf + 24); /* Loop end */ - sih.vol = buf[28]; /* Volume */ - sih.pack = buf[30]; /* Packing type (not used) */ - sih.flags = buf[31]; /* Loop/stereo/16bit flags */ - sih.c2spd = readmem16l(buf + 32); /* C4 speed */ - memcpy(sih.name, buf + 48, 28); /* Instrument name */ - sih.magic = readmem32b(buf + 76); /* 'SCRS' */ - - if (buf[0] == 1 && sih.magic != MAGIC_SCRS) { - D_(D_CRIT "error: instrument magic"); - goto err3; - } -#ifndef LIBXMP_CORE_PLAYER - if (quirk87) { - fix87(sih.length); - fix87(sih.loopbeg); - fix87(sih.loopend); - fix87(sih.flags); - } -#endif - - xxs->len = sih.length; - xxi->nsm = sih.length > 0 ? 1 : 0; - xxs->lps = sih.loopbeg; - xxs->lpe = sih.loopend; - - xxs->flg = sih.flags & 1 ? XMP_SAMPLE_LOOP : 0; - - if (sih.flags & 4) { - xxs->flg |= XMP_SAMPLE_16BIT; - } - - sub->vol = sih.vol; - sih.magic = 0; - - libxmp_instrument_name(mod, i, sih.name, 28); - - D_(D_INFO "[%2X] %-28.28s %04x%c%04x %04x %c V%02x %5d", - i, mod->xxi[i].name, mod->xxs[i].len, - xxs->flg & XMP_SAMPLE_16BIT ? '+' : ' ', - xxs->lps, mod->xxs[i].lpe, - xxs->flg & XMP_SAMPLE_LOOP ? 'L' : ' ', sub->vol, sih.c2spd); - - libxmp_c2spd_to_note(sih.c2spd, &sub->xpo, &sub->fin); - - if (hio_seek(f, start + 16L * sih.memseg, SEEK_SET) < 0) { - goto err3; - } - - ret = libxmp_load_sample(m, f, sfh.ffi == 1 ? 0 : SAMPLE_FLAG_UNS, - xxs, NULL); - if (ret < 0) { - goto err3; - } - } - - free(pp_pat); - free(pp_ins); - - m->quirk |= QUIRKS_ST3 | QUIRK_ARPMEM; - m->read_event_type = READ_EVENT_ST3; - - return 0; - -err3: - free(pp_pat); -err2: - free(pp_ins); -err: - return -1; -} diff --git a/source/libxmp-lite/src/sample.c b/source/libxmp-lite/src/sample.c deleted file mode 100644 index a81939e57..000000000 --- a/source/libxmp-lite/src/sample.c +++ /dev/null @@ -1,417 +0,0 @@ -/* Extended Module Player - * 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"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include "common.h" -#include "loader.h" - -#ifndef LIBXMP_CORE_PLAYER - -/* - * From the Audio File Formats (version 2.5) - * Submitted-by: Guido van Rossum - * Last-modified: 27-Aug-1992 - * - * The Acorn Archimedes uses a variation on U-LAW with the bit order - * reversed and the sign bit in bit 0. Being a 'minority' architecture, - * Arc owners are quite adept at converting sound/image formats from - * other machines, and it is unlikely that you'll ever encounter sound in - * one of the Arc's own formats (there are several). - */ -static const int8 vdic_table[128] = { - /* 0 */ 0, 0, 0, 0, 0, 0, 0, 0, - /* 8 */ 0, 0, 0, 0, 0, 0, 0, 0, - /* 16 */ 0, 0, 0, 0, 0, 0, 0, 0, - /* 24 */ 1, 1, 1, 1, 1, 1, 1, 1, - /* 32 */ 1, 1, 1, 1, 2, 2, 2, 2, - /* 40 */ 2, 2, 2, 2, 3, 3, 3, 3, - /* 48 */ 3, 3, 4, 4, 4, 4, 5, 5, - /* 56 */ 5, 5, 6, 6, 6, 6, 7, 7, - /* 64 */ 7, 8, 8, 9, 9, 10, 10, 11, - /* 72 */ 11, 12, 12, 13, 13, 14, 14, 15, - /* 80 */ 15, 16, 17, 18, 19, 20, 21, 22, - /* 88 */ 23, 24, 25, 26, 27, 28, 29, 30, - /* 96 */ 31, 33, 34, 36, 38, 40, 42, 44, - /* 104 */ 46, 48, 50, 52, 54, 56, 58, 60, - /* 112 */ 62, 65, 68, 72, 77, 80, 84, 91, - /* 120 */ 95, 98, 103, 109, 114, 120, 126, 127 -}; - - -/* Convert 7 bit samples to 8 bit */ -static void convert_7bit_to_8bit(uint8 *p, int l) -{ - for (; l--; p++) { - *p <<= 1; - } -} - -/* Convert Archimedes VIDC samples to linear */ -static void convert_vidc_to_linear(uint8 *p, int l) -{ - int i; - uint8 x; - - for (i = 0; i < l; i++) { - x = p[i]; - p[i] = vdic_table[x >> 1]; - if (x & 0x01) - p[i] *= -1; - } -} - -static void adpcm4_decoder(uint8 *inp, uint8 *outp, char *tab, int len) -{ - char delta = 0; - uint8 b0, b1; - int i; - - len = (len + 1) / 2; - - for (i = 0; i < len; i++) { - b0 = *inp; - b1 = *inp++ >> 4; - delta += tab[b0 & 0x0f]; - *outp++ = delta; - delta += tab[b1 & 0x0f]; - *outp++ = delta; - } -} - -#endif - -/* Convert differential to absolute sample data */ -static void convert_delta(uint8 *p, int l, int r) -{ - uint16 *w = (uint16 *)p; - uint16 abs = 0; - - if (r) { - for (; l--;) { - abs = *w + abs; - *w++ = abs; - } - } else { - for (; l--;) { - abs = *p + abs; - *p++ = (uint8) abs; - } - } -} - -/* Convert signed to unsigned sample data */ -static void convert_signal(uint8 *p, int l, int r) -{ - uint16 *w = (uint16 *)p; - - if (r) { - for (; l--; w++) - *w += 0x8000; - } else { - for (; l--; p++) - *p += (char)0x80; /* cast needed by MSVC++ */ - } -} - -/* Convert little-endian 16 bit samples to big-endian */ -static void convert_endian(uint8 *p, int l) -{ - uint8 b; - int i; - - for (i = 0; i < l; i++) { - b = p[0]; - p[0] = p[1]; - p[1] = b; - p += 2; - } -} - -#if 0 -/* Downmix stereo samples to mono */ -static void convert_stereo_to_mono(uint8 *p, int l, int r) -{ - int16 *b = (int16 *)p; - int i; - - if (r) { - l /= 2; - for (i = 0; i < l; i++) - b[i] = (b[i * 2] + b[i * 2 + 1]) / 2; - } else { - for (i = 0; i < l; i++) - p[i] = (p[i * 2] + p[i * 2 + 1]) / 2; - } -} -#endif - -static void unroll_loop(struct xmp_sample *xxs) -{ - int8 *s8; - int16 *s16; - int start, loop_size; - int i; - - s16 = (int16 *)xxs->data; - s8 = (int8 *)xxs->data; - - if (xxs->len > xxs->lpe) { - start = xxs->lpe; - } else { - start = xxs->len; - } - - loop_size = xxs->lpe - xxs->lps; - - if (xxs->flg & XMP_SAMPLE_16BIT) { - s16 += start; - for (i = 0; i < loop_size; i++) { - *(s16 + i) = *(s16 - i - 1); - } - } else { - s8 += start; - for (i = 0; i < loop_size; i++) { - *(s8 + i) = *(s8 - i - 1); - } - } -} - - -int libxmp_load_sample(struct module_data *m, HIO_HANDLE *f, int flags, struct xmp_sample *xxs, const void *buffer) -{ - int bytelen, extralen, unroll_extralen, i; - -#ifndef LIBXMP_CORE_PLAYER - /* Adlib FM patches */ - if (flags & SAMPLE_FLAG_ADLIB) { - return 0; - } -#endif - - /* Empty or invalid samples - */ - if (xxs->len <= 0) { - return 0; - } - - /* Skip sample loading - * FIXME: fails for ADPCM samples - * - * + Sanity check: skip huge samples (likely corrupt module) - */ - if (xxs->len > MAX_SAMPLE_SIZE || (m && m->smpctl & XMP_SMPCTL_SKIP)) { - if (~flags & SAMPLE_FLAG_NOLOAD) { - /* coverity[check_return] */ - hio_seek(f, xxs->len, SEEK_CUR); - } - return 0; - } - - /* Loop parameters sanity check - */ - if (xxs->lps < 0) { - xxs->lps = 0; - } - if (xxs->lpe > xxs->len) { - xxs->lpe = xxs->len; - } - if (xxs->lps >= xxs->len || xxs->lps >= xxs->lpe) { - xxs->lps = xxs->lpe = 0; - xxs->flg &= ~(XMP_SAMPLE_LOOP | XMP_SAMPLE_LOOP_BIDIR); - } - - /* Patches with samples - * Allocate extra sample for interpolation. - */ - bytelen = xxs->len; - extralen = 4; - unroll_extralen = 0; - - /* Disable birectional loop flag if sample is not looped - */ - if (xxs->flg & XMP_SAMPLE_LOOP_BIDIR) { - if (~xxs->flg & XMP_SAMPLE_LOOP) - xxs->flg &= ~XMP_SAMPLE_LOOP_BIDIR; - } - /* Unroll bidirectional loops - */ - if (xxs->flg & XMP_SAMPLE_LOOP_BIDIR) { - unroll_extralen = (xxs->lpe - xxs->lps) - - (xxs->len - xxs->lpe); - - if (unroll_extralen < 0) { - unroll_extralen = 0; - } - } - - if (xxs->flg & XMP_SAMPLE_16BIT) { - bytelen *= 2; - extralen *= 2; - unroll_extralen *= 2; - } - - /* add guard bytes before the buffer for higher order interpolation */ - xxs->data = (unsigned char *)malloc(bytelen + extralen + unroll_extralen + 4); - if (xxs->data == NULL) { - goto err; - } - - *(uint32 *)xxs->data = 0; - xxs->data += 4; - - if (flags & SAMPLE_FLAG_NOLOAD) { - memcpy(xxs->data, buffer, bytelen); - } else -#ifndef LIBXMP_CORE_PLAYER - if (flags & SAMPLE_FLAG_ADPCM) { - int x2 = (bytelen + 1) >> 1; - char table[16]; - - if (hio_read(table, 1, 16, f) != 16) { - goto err2; - } - if (hio_read(xxs->data + x2, 1, x2, f) != x2) { - goto err2; - } - adpcm4_decoder((uint8 *)xxs->data + x2, - (uint8 *)xxs->data, table, bytelen); - } else -#endif - { - int x = hio_read(xxs->data, 1, bytelen, f); - if (x != bytelen) { - D_(D_WARN "short read (%d) in sample load", x - bytelen); - memset(xxs->data + x, 0, bytelen - x); - } - } - -#ifndef LIBXMP_CORE_PLAYER - if (flags & SAMPLE_FLAG_7BIT) { - convert_7bit_to_8bit(xxs->data, xxs->len); - } -#endif - - /* Fix endianism if needed */ - if (xxs->flg & XMP_SAMPLE_16BIT) { -#ifdef WORDS_BIGENDIAN - if (~flags & SAMPLE_FLAG_BIGEND) - convert_endian(xxs->data, xxs->len); -#else - if (flags & SAMPLE_FLAG_BIGEND) - convert_endian(xxs->data, xxs->len); -#endif - } - - /* Convert delta samples */ - if (flags & SAMPLE_FLAG_DIFF) { - convert_delta(xxs->data, xxs->len, xxs->flg & XMP_SAMPLE_16BIT); - } else if (flags & SAMPLE_FLAG_8BDIFF) { - int len = xxs->len; - if (xxs->flg & XMP_SAMPLE_16BIT) { - len *= 2; - } - convert_delta(xxs->data, len, 0); - } - - /* Convert samples to signed */ - if (flags & SAMPLE_FLAG_UNS) { - convert_signal(xxs->data, xxs->len, - xxs->flg & XMP_SAMPLE_16BIT); - } - -#if 0 - /* Downmix stereo samples */ - if (flags & SAMPLE_FLAG_STEREO) { - convert_stereo_to_mono(xxs->data, xxs->len, - xxs->flg & XMP_SAMPLE_16BIT); - xxs->len /= 2; - } -#endif - -#ifndef LIBXMP_CORE_PLAYER - if (flags & SAMPLE_FLAG_VIDC) { - convert_vidc_to_linear(xxs->data, xxs->len); - } -#endif - - /* Check for full loop samples */ - if (flags & SAMPLE_FLAG_FULLREP) { - if (xxs->lps == 0 && xxs->len > xxs->lpe) - xxs->flg |= XMP_SAMPLE_LOOP_FULL; - } - - /* Unroll bidirectional loops */ - if (xxs->flg & XMP_SAMPLE_LOOP_BIDIR) { - unroll_loop(xxs); - bytelen += unroll_extralen; - } - - /* Add extra samples at end */ - if (xxs->flg & XMP_SAMPLE_16BIT) { - for (i = 0; i < 8; i++) { - xxs->data[bytelen + i] = xxs->data[bytelen - 2 + i]; - } - } else { - for (i = 0; i < 4; i++) { - xxs->data[bytelen + i] = xxs->data[bytelen - 1 + i]; - } - } - - /* Add extra samples at start */ - if (xxs->flg & XMP_SAMPLE_16BIT) { - xxs->data[-2] = xxs->data[0]; - xxs->data[-1] = xxs->data[1]; - } else { - xxs->data[-1] = xxs->data[0]; - } - - /* Fix sample at loop */ - if (xxs->flg & XMP_SAMPLE_LOOP) { - int lpe = xxs->lpe; - int lps = xxs->lps; - - if (xxs->flg & XMP_SAMPLE_LOOP_BIDIR) { - lpe += lpe - lps; - } - - if (xxs->flg & XMP_SAMPLE_16BIT) { - lpe <<= 1; - lps <<= 1; - for (i = 0; i < 8; i++) { - xxs->data[lpe + i] = xxs->data[lps + i]; - } - } else { - for (i = 0; i < 4; i++) { - xxs->data[lpe + i] = xxs->data[lps + i]; - } - } - } - - return 0; - -#ifndef LIBXMP_CORE_PLAYER - err2: - free(xxs->data - 4); - xxs->data = NULL; /* prevent double free in PCM load error */ -#endif - err: - return -1; -} diff --git a/source/libxmp-lite/src/scan.c b/source/libxmp-lite/src/scan.c deleted file mode 100644 index f3358c3fc..000000000 --- a/source/libxmp-lite/src/scan.c +++ /dev/null @@ -1,549 +0,0 @@ -/* Extended Module Player - * 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"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -/* - * Sun, 31 May 1998 17:50:02 -0600 - * Reported by ToyKeeper : - * For loop-prevention, I know a way to do it which lets most songs play - * fine once through even if they have backward-jumps. Just keep a small - * array (256 bytes, or even bits) of flags, each entry determining if a - * pattern in the song order has been played. If you get to an entry which - * is already non-zero, skip to the next song (assuming looping is off). - */ - -/* - * Tue, 6 Oct 1998 21:23:17 +0200 (CEST) - * Reported by John v/d Kamp : - * scan.c was hanging when it jumps to an invalid restart value. - * (Fixed by hipolito) - */ - - -#include -#include -#include "common.h" -#include "effects.h" -#include "mixer.h" - -#define S3M_END 0xff -#define S3M_SKIP 0xfe - - -static int scan_module(struct context_data *ctx, int ep, int chain) -{ - struct player_data *p = &ctx->p; - struct module_data *m = &ctx->m; - struct xmp_module *mod = &m->mod; - int parm, gvol_memory, f1, f2, p1, p2, ord, ord2; - int row, last_row, break_row, row_count; - int gvl, bpm, speed, base_time, chn; - int frame_count; - double time, start_time; - int loop_chn, loop_num, inside_loop; - int pdelay = 0; - int loop_count[XMP_MAX_CHANNELS]; - int loop_row[XMP_MAX_CHANNELS]; - struct xmp_event* event; - int i, pat; - int has_marker; - struct ord_data *info; -#ifndef LIBXMP_CORE_PLAYER - int st26_speed; -#endif - - if (mod->len == 0) - return 0; - - for (i = 0; i < mod->len; i++) { - int pat = mod->xxo[i]; - memset(m->scan_cnt[i], 0, pat >= mod->pat ? 1 : - mod->xxp[pat]->rows ? mod->xxp[pat]->rows : 1); - } - - for (i = 0; i < mod->chn; i++) { - loop_count[i] = 0; - loop_row[i] = -1; - } - loop_num = 0; - loop_chn = -1; - - gvl = mod->gvl; - bpm = mod->bpm; - - speed = mod->spd; - base_time = (int) m->rrate; -#ifndef LIBXMP_CORE_PLAYER - st26_speed = 0; -#endif - - has_marker = HAS_QUIRK(QUIRK_MARKER); - - /* By erlk ozlr - * - * xmp doesn't handle really properly the "start" option (-s for the - * command-line) for DeusEx's .umx files. These .umx files contain - * several loop "tracks" that never join together. That's how they put - * multiple musics on each level with a file per level. Each "track" - * starts at the same order in all files. The problem is that xmp starts - * decoding the module at order 0 and not at the order specified with - * the start option. If we have a module that does "0 -> 2 -> 0 -> ...", - * we cannot play order 1, even with the supposed right option. - * - * was: ord2 = ord = -1; - * - * CM: Fixed by using different "sequences" for each loop or subsong. - * Each sequence has its entry point. Sequences don't overlap. - */ - ord2 = -1; - ord = ep - 1; - - gvol_memory = break_row = row_count = frame_count = 0; - start_time = time = 0.0; - inside_loop = 0; - - while (42) { - if ((uint32)++ord >= mod->len) { - if (mod->rst > mod->len || mod->xxo[mod->rst] >= mod->pat) { - ord = ep; - } else { - if (libxmp_get_sequence(ctx, mod->rst) == chain) { - ord = mod->rst; - } else { - ord = ep; - } - } - - pat = mod->xxo[ord]; - if (has_marker && pat == S3M_END) { - break; - } - } - - pat = mod->xxo[ord]; - info = &m->xxo_info[ord]; - - /* Allow more complex order reuse only in main sequence */ - if (ep != 0 && p->sequence_control[ord] != 0xff) { - break; - } - p->sequence_control[ord] = chain; - - /* All invalid patterns skipped, only S3M_END aborts replay */ - if (pat >= mod->pat) { - if (has_marker && pat == S3M_END) { - ord = mod->len; - continue; - } - continue; - } - - if (break_row >= mod->xxp[pat]->rows) { - break_row = 0; - } - - /* Loops can cross pattern boundaries, so check if we're not looping */ - if (m->scan_cnt[ord][break_row] && !inside_loop) { - break; - } - - /* Don't update pattern information if we're inside a loop, otherwise - * a loop containing e.g. a global volume fade can make the pattern - * start with the wrong volume. - */ - if (!inside_loop && info->gvl < 0) { - info->gvl = gvl; - info->bpm = bpm; - info->speed = speed; - info->time = (int) (time + m->time_factor * frame_count * base_time / bpm); -#ifndef LIBXMP_CORE_PLAYER - info->st26_speed = st26_speed; -#endif - } - - if (info->start_row == 0 && ord != 0) { - if (ord == ep) { - start_time = time + m->time_factor * frame_count * base_time / bpm; - } - - info->start_row = break_row; - } - - last_row = mod->xxp[pat]->rows; - for (row = break_row, break_row = 0; row < last_row; row++, row_count++) { - /* Prevent crashes caused by large softmixer frames */ - if (bpm < XMP_MIN_BPM) { - bpm = XMP_MIN_BPM; - } - - /* Date: Sat, 8 Sep 2007 04:01:06 +0200 - * Reported by Zbigniew Luszpinski - * The scan routine falls into infinite looping and doesn't let - * xmp play jos-dr4k.xm. - * Claudio's workaround: we'll break infinite loops here. - * - * Date: Oct 27, 2007 8:05 PM - * From: Adric Riedel - * Jesper Kyd: Global Trash 3.mod (the 'Hardwired' theme) only - * plays the first 4:41 of what should be a 10 minute piece. - * (...) it dies at the end of position 2F - */ - - if (row_count > 512) /* was 255, but Global trash goes to 318 */ - goto end_module; - - if (!loop_num && m->scan_cnt[ord][row]) { - row_count--; - goto end_module; - } - m->scan_cnt[ord][row]++; - - pdelay = 0; - - for (chn = 0; chn < mod->chn; chn++) { - if (row >= mod->xxt[mod->xxp[pat]->index[chn]]->rows) - continue; - - event = &EVENT(mod->xxo[ord], chn, row); - - f1 = event->fxt; - p1 = event->fxp; - f2 = event->f2t; - p2 = event->f2p; - - if (f1 == FX_GLOBALVOL || f2 == FX_GLOBALVOL) { - gvl = (f1 == FX_GLOBALVOL) ? p1 : p2; - gvl = gvl > m->gvolbase ? m->gvolbase : gvl < 0 ? 0 : gvl; - } - - /* Process fine global volume slide */ - if (f1 == FX_GVOL_SLIDE || f2 == FX_GVOL_SLIDE) { - int h, l; - parm = (f1 == FX_GVOL_SLIDE) ? p1 : p2; - - process_gvol: - if (parm) { - gvol_memory = parm; - h = MSN(parm); - l = LSN(parm); - - if (HAS_QUIRK(QUIRK_FINEFX)) { - if (l == 0xf && h != 0) { - gvl += h; - } else if (h == 0xf && l != 0) { - gvl -= l; - } else { - if (m->quirk & QUIRK_VSALL) { - gvl += (h - l) * speed; - } else { - gvl += (h - l) * (speed - 1); - } - } - } else { - if (m->quirk & QUIRK_VSALL) { - gvl += (h - l) * speed; - } else { - gvl += (h - l) * (speed - 1); - } - } - } else { - if ((parm = gvol_memory) != 0) - goto process_gvol; - } - } - - if ((f1 == FX_SPEED && p1) || (f2 == FX_SPEED && p2)) { - parm = (f1 == FX_SPEED) ? p1 : p2; - frame_count += row_count * speed; - row_count = 0; - if (parm) { - if (HAS_QUIRK(QUIRK_NOBPM) || p->flags & XMP_FLAGS_VBLANK || parm < 0x20) { - if (parm > 0) { - speed = parm; -#ifndef LIBXMP_CORE_PLAYER - st26_speed = 0; -#endif - } - } else { - time += m->time_factor * frame_count * base_time / bpm; - frame_count = 0; - bpm = parm; - } - } - } - -#ifndef LIBXMP_CORE_PLAYER - if (f1 == FX_SPEED_CP) { - f1 = FX_S3M_SPEED; - } - if (f2 == FX_SPEED_CP) { - f2 = FX_S3M_SPEED; - } - - /* ST2.6 speed processing */ - - if (f1 == FX_ICE_SPEED && p1) { - if (LSN(p1)) { - st26_speed = (MSN(p1) << 8) | LSN(p1); - } else { - st26_speed = MSN(p1); - } - } -#endif - - if ((f1 == FX_S3M_SPEED && p1) || (f2 == FX_S3M_SPEED && p2)) { - parm = (f1 == FX_S3M_SPEED) ? p1 : p2; - if (parm > 0) { - frame_count += row_count * speed; - row_count = 0; - speed = parm; -#ifndef LIBXMP_CORE_PLAYER - st26_speed = 0; -#endif - } - } - - if ((f1 == FX_S3M_BPM && p1) || (f2 == FX_S3M_BPM && p2)) { - parm = (f1 == FX_S3M_BPM) ? p1 : p2; - if (parm >= 0x20) { - frame_count += row_count * speed; - row_count = 0; - time += m->time_factor * frame_count * base_time / bpm; - frame_count = 0; - bpm = parm; - } - } - -#ifndef LIBXMP_CORE_DISABLE_IT - if ((f1 == FX_IT_BPM && p1) || (f2 == FX_IT_BPM && p2)) { - parm = (f1 == FX_IT_BPM) ? p1 : p2; - frame_count += row_count * speed; - row_count = 0; - time += m->time_factor * frame_count * base_time / bpm; - frame_count = 0; - - if (MSN(parm) == 0) { - time += m->time_factor * base_time / bpm; - for (i = 1; i < speed; i++) { - bpm -= LSN(parm); - if (bpm < 0x20) - bpm = 0x20; - time += m->time_factor * base_time / bpm; - } - - /* remove one row at final bpm */ - time -= m->time_factor * speed * base_time / bpm; - - } else if (MSN(parm) == 1) { - time += m->time_factor * base_time / bpm; - for (i = 1; i < speed; i++) { - bpm += LSN(parm); - if (bpm > 0xff) - bpm = 0xff; - time += m->time_factor * base_time / bpm; - } - - /* remove one row at final bpm */ - time -= m->time_factor * speed * base_time / bpm; - - } else { - bpm = parm; - } - } - - if (f1 == FX_IT_ROWDELAY) { - m->scan_cnt[ord][row] += p1 & 0x0f; - frame_count += (p1 & 0x0f) * speed; - } - - if (f1 == FX_IT_BREAK) { - break_row = p1; - last_row = 0; - } -#endif - - if (f1 == FX_JUMP || f2 == FX_JUMP) { - ord2 = (f1 == FX_JUMP) ? p1 : p2; - break_row = 0; - last_row = 0; - - /* prevent infinite loop, see OpenMPT PatLoop-Various.xm */ - inside_loop = 0; - } - - if (f1 == FX_BREAK || f2 == FX_BREAK) { - parm = (f1 == FX_BREAK) ? p1 : p2; - break_row = 10 * MSN(parm) + LSN(parm); - last_row = 0; - } - - if (f1 == FX_EXTENDED || f2 == FX_EXTENDED) { - parm = (f1 == FX_EXTENDED) ? p1 : p2; - - if ((parm >> 4) == EX_PATT_DELAY) { - if (m->read_event_type != READ_EVENT_ST3 || !pdelay) { - pdelay = parm & 0x0f; - frame_count += pdelay * speed; - } - } - - if ((parm >> 4) == EX_PATTERN_LOOP) { - if (parm &= 0x0f) { - /* Loop end */ - if (loop_count[chn]) { - if (--loop_count[chn]) { - /* next iteraction */ - loop_chn = chn; - } else { - /* finish looping */ - loop_num--; - inside_loop = 0; - if (m->quirk & QUIRK_S3MLOOP) - loop_row[chn] = row; - } - } else { - loop_count[chn] = parm; - loop_chn = chn; - loop_num++; - } - } else { - /* Loop start */ - loop_row[chn] = row - 1; - inside_loop = 1; - if (HAS_QUIRK(QUIRK_FT2BUGS)) - break_row = row; - } - } - } - } - - if (loop_chn >= 0) { - row = loop_row[loop_chn]; - loop_chn = -1; - } - -#ifndef LIBXMP_CORE_PLAYER - if (st26_speed) { - frame_count += row_count * speed; - row_count = 0; - if (st26_speed & 0x10000) { - speed = (st26_speed & 0xff00) >> 8; - } else { - speed = st26_speed & 0xff; - } - st26_speed ^= 0x10000; - } -#endif - } - - if (break_row && pdelay) { - break_row++; - } - - if (ord2 >= 0) { - ord = ord2 - 1; - ord2 = -1; - } - - frame_count += row_count * speed; - row_count = 0; - } - row = break_row; - -end_module: - - /* Sanity check */ - { - pat = mod->xxo[ord]; - if (pat >= mod->pat || row >= mod->xxp[pat]->rows) { - row = 0; - } - } - - p->scan[chain].num = m->scan_cnt[ord][row]; - p->scan[chain].row = row; - p->scan[chain].ord = ord; - - time -= start_time; - frame_count += row_count * speed; - - return (int) (time + m->time_factor * frame_count * base_time / bpm); -} - -int libxmp_get_sequence(struct context_data *ctx, int ord) -{ - struct player_data *p = &ctx->p; - return p->sequence_control[ord]; -} - -int libxmp_scan_sequences(struct context_data *ctx) -{ - struct player_data *p = &ctx->p; - struct module_data *m = &ctx->m; - struct xmp_module *mod = &m->mod; - int i, ep; - int seq; - unsigned char temp_ep[XMP_MAX_MOD_LENGTH]; - - /* Initialize order data to prevent overwrite when a position is used - * multiple times at different starting points (see janosik.xm). - */ - for (i = 0; i < XMP_MAX_MOD_LENGTH; i++) { - m->xxo_info[i].gvl = -1; - } - - ep = 0; - memset(p->sequence_control, 0xff, XMP_MAX_MOD_LENGTH); - temp_ep[0] = 0; - p->scan[0].time = scan_module(ctx, ep, 0); - seq = 1; - - while (1) { - /* Scan song starting at given entry point */ - /* Check if any patterns left */ - for (i = 0; i < mod->len; i++) { - if (p->sequence_control[i] == 0xff) { - break; - } - } - if (i != mod->len && seq < MAX_SEQUENCES) { - /* New entry point */ - ep = i; - temp_ep[seq] = ep; - p->scan[seq].time = scan_module(ctx, ep, seq); - if (p->scan[seq].time > 0) - seq++; - } else { - break; - } - } - - m->num_sequences = seq; - - /* Now place entry points in the public accessible array */ - for (i = 0; i < m->num_sequences; i++) { - m->seq_data[i].entry_point = temp_ep[i]; - m->seq_data[i].duration = p->scan[i].time; - } - - - return 0; -} diff --git a/source/libxmp-lite/src/smix.c b/source/libxmp-lite/src/smix.c deleted file mode 100644 index 878d35970..000000000 --- a/source/libxmp-lite/src/smix.c +++ /dev/null @@ -1,333 +0,0 @@ -/* Extended Module Player - * 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"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include -#include "common.h" -#include "period.h" -#include "player.h" -#include "hio.h" - - -struct xmp_instrument *libxmp_get_instrument(struct context_data *ctx, int ins) -{ - struct smix_data *smix = &ctx->smix; - struct module_data *m = &ctx->m; - struct xmp_module *mod = &m->mod; - struct xmp_instrument *xxi; - - if (ins < mod->ins) { - xxi = &mod->xxi[ins]; - } else if (ins < mod->ins + smix->ins) { - xxi = &smix->xxi[ins - mod->ins]; - } else { - xxi = NULL; - } - - return xxi; -} - -struct xmp_sample *libxmp_get_sample(struct context_data *ctx, int smp) -{ - struct smix_data *smix = &ctx->smix; - struct module_data *m = &ctx->m; - struct xmp_module *mod = &m->mod; - struct xmp_sample *xxs; - - if (smp < mod->smp) { - xxs = &mod->xxs[smp]; - } else if (smp < mod->smp + smix->smp) { - xxs = &smix->xxs[smp - mod->smp]; - } else { - xxs = NULL; - } - - return xxs; -} - -int xmp_start_smix(xmp_context opaque, int chn, int smp) -{ - struct context_data *ctx = (struct context_data *)opaque; - struct smix_data *smix = &ctx->smix; - - if (ctx->state > XMP_STATE_LOADED) { - return -XMP_ERROR_STATE; - } - - smix->xxi = (struct xmp_instrument *)calloc(sizeof (struct xmp_instrument), smp); - if (smix->xxi == NULL) { - goto err; - } - smix->xxs = (struct xmp_sample *)calloc(sizeof (struct xmp_sample), smp); - if (smix->xxs == NULL) { - goto err1; - } - - smix->chn = chn; - smix->ins = smix->smp = smp; - - return 0; - - err1: - free(smix->xxi); - err: - return -XMP_ERROR_INTERNAL; -} - -int xmp_smix_play_instrument(xmp_context opaque, int ins, int note, int vol, int chn) -{ - struct context_data *ctx = (struct context_data *)opaque; - struct player_data *p = &ctx->p; - struct smix_data *smix = &ctx->smix; - struct module_data *m = &ctx->m; - struct xmp_module *mod = &m->mod; - struct xmp_event *event; - - if (ctx->state < XMP_STATE_PLAYING) { - return -XMP_ERROR_STATE; - } - - if (chn >= smix->chn || ins >= mod->ins) { - return -XMP_ERROR_INVALID; - } - - if (note == 0) { - note = 60; /* middle C note number */ - } - - event = &p->inject_event[mod->chn + chn]; - memset(event, 0, sizeof (struct xmp_event)); - event->note = note + 1; - event->ins = ins + 1; - event->vol = vol + 1; - event->_flag = 1; - - return 0; -} - -int xmp_smix_play_sample(xmp_context opaque, int ins, int note, int vol, int chn) -{ - struct context_data *ctx = (struct context_data *)opaque; - struct player_data *p = &ctx->p; - struct smix_data *smix = &ctx->smix; - struct module_data *m = &ctx->m; - struct xmp_module *mod = &m->mod; - struct xmp_event *event; - - if (ctx->state < XMP_STATE_PLAYING) { - return -XMP_ERROR_STATE; - } - - if (chn >= smix->chn || ins >= smix->ins) { - return -XMP_ERROR_INVALID; - } - - if (note == 0) { - note = 60; /* middle C note number */ - } - - event = &p->inject_event[mod->chn + chn]; - memset(event, 0, sizeof (struct xmp_event)); - event->note = note + 1; - event->ins = mod->ins + ins + 1; - event->vol = vol + 1; - event->_flag = 1; - - return 0; -} - -int xmp_smix_channel_pan(xmp_context opaque, int chn, int pan) -{ - struct context_data *ctx = (struct context_data *)opaque; - struct player_data *p = &ctx->p; - struct smix_data *smix = &ctx->smix; - struct module_data *m = &ctx->m; - struct channel_data *xc; - - if (chn >= smix->chn || pan < 0 || pan > 255) { - return -XMP_ERROR_INVALID; - } - - xc = &p->xc_data[m->mod.chn + chn]; - xc->pan.val = pan; - - return 0; -} - -#ifdef EDUKE32_DISABLED -int xmp_smix_load_sample(xmp_context opaque, int num, char *path) -{ - struct context_data *ctx = (struct context_data *)opaque; - struct smix_data *smix = &ctx->smix; - struct module_data *m = &ctx->m; - struct xmp_instrument *xxi; - struct xmp_sample *xxs; - HIO_HANDLE *h; - uint32 magic; - int chn, rate, bits, size; - int retval = -XMP_ERROR_INTERNAL; - - if (num >= smix->ins) { - retval = -XMP_ERROR_INVALID; - goto err; - } - - xxi = &smix->xxi[num]; - xxs = &smix->xxs[num]; - - h = hio_open(path, "rb"); - if (h == NULL) { - retval = -XMP_ERROR_SYSTEM; - goto err; - } - - /* Init instrument */ - - xxi->sub = (struct xmp_subinstrument *)calloc(sizeof(struct xmp_subinstrument), 1); - if (xxi->sub == NULL) { - retval = -XMP_ERROR_SYSTEM; - goto err1; - } - - xxi->vol = m->volbase; - xxi->nsm = 1; - xxi->sub[0].sid = num; - xxi->sub[0].vol = xxi->vol; - xxi->sub[0].pan = 0x80; - - /* Load sample */ - - magic = hio_read32b(h); - if (magic != 0x52494646) { /* RIFF */ - retval = -XMP_ERROR_FORMAT; - goto err2; - } - - if (hio_seek(h, 22, SEEK_SET) < 0) { - retval = -XMP_ERROR_SYSTEM; - goto err2; - } - chn = hio_read16l(h); - if (chn != 1) { - retval = -XMP_ERROR_FORMAT; - goto err2; - } - - rate = hio_read32l(h); - if (rate == 0) { - retval = -XMP_ERROR_FORMAT; - goto err2; - } - - if (hio_seek(h, 34, SEEK_SET) < 0) { - retval = -XMP_ERROR_SYSTEM; - goto err2; - } - bits = hio_read16l(h); - if (bits == 0) { - retval = -XMP_ERROR_FORMAT; - goto err2; - } - - if (hio_seek(h, 40, SEEK_SET) < 0) { - retval = -XMP_ERROR_SYSTEM; - goto err2; - } - size = hio_read32l(h); - if (size == 0) { - retval = -XMP_ERROR_FORMAT; - goto err2; - } - - libxmp_c2spd_to_note(rate, &xxi->sub[0].xpo, &xxi->sub[0].fin); - - xxs->len = 8 * size / bits; - xxs->lps = 0; - xxs->lpe = 0; - xxs->flg = bits == 16 ? XMP_SAMPLE_16BIT : 0; - - 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; - } - if (hio_read(xxs->data, 1, size, h) != size) { - retval = -XMP_ERROR_SYSTEM; - goto err2; - } - hio_close(h); - - return 0; - - err2: - free(xxi->sub); - xxi->sub = NULL; - err1: - hio_close(h); - err: - return retval; -} -#endif - -int xmp_smix_release_sample(xmp_context opaque, int num) -{ - struct context_data *ctx = (struct context_data *)opaque; - struct smix_data *smix = &ctx->smix; - - if (num >= smix->ins) { - return -XMP_ERROR_INVALID; - } - - if (smix->xxs[num].data != NULL) { - free(smix->xxs[num].data - 4); - } - free(smix->xxi[num].sub); - - smix->xxs[num].data = NULL; - smix->xxi[num].sub = NULL; - - return 0; -} - -void xmp_end_smix(xmp_context opaque) -{ - struct context_data *ctx = (struct context_data *)opaque; - struct smix_data *smix = &ctx->smix; - int i; - - for (i = 0; i < smix->smp; i++) { - xmp_smix_release_sample(opaque, i); - } - - free(smix->xxs); - free(smix->xxi); -} - diff --git a/source/libxmp-lite/src/virtual.c b/source/libxmp-lite/src/virtual.c deleted file mode 100644 index 77bcb6014..000000000 --- a/source/libxmp-lite/src/virtual.c +++ /dev/null @@ -1,608 +0,0 @@ -/* Extended Module Player - * 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"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include -#include -#include -#include "common.h" -#include "virtual.h" -#include "mixer.h" - -#ifdef LIBXMP_PAULA_SIMULATOR -#include "paula.h" -#endif - -#define FREE -1 - -/* For virt_pastnote() */ -void libxmp_player_set_release(struct context_data *, int); -void libxmp_player_set_fadeout(struct context_data *, int); - - -/* Get parent channel */ -int libxmp_virt_getroot(struct context_data *ctx, int chn) -{ - struct player_data *p = &ctx->p; - struct mixer_voice *vi; - int voc; - - voc = p->virt.virt_channel[chn].map; - if (voc < 0) { - return -1; - } - - vi = &p->virt.voice_array[voc]; - - return vi->root; -} - -void libxmp_virt_resetvoice(struct context_data *ctx, int voc, int mute) -{ - struct player_data *p = &ctx->p; - struct mixer_voice *vi = &p->virt.voice_array[voc]; -#ifdef LIBXMP_PAULA_SIMULATOR - struct paula_state *paula; -#endif - - if ((uint32)voc >= p->virt.maxvoc) { - return; - } - - if (mute) { - libxmp_mixer_setvol(ctx, voc, 0); - } - - p->virt.virt_used--; - p->virt.virt_channel[vi->root].count--; - p->virt.virt_channel[vi->chn].map = FREE; -#ifdef LIBXMP_PAULA_SIMULATOR - paula = vi->paula; -#endif - memset(vi, 0, sizeof(struct mixer_voice)); -#ifdef LIBXMP_PAULA_SIMULATOR - vi->paula = paula; -#endif - vi->chn = vi->root = FREE; -} - -/* virt_on (number of tracks) */ -int libxmp_virt_on(struct context_data *ctx, int num) -{ - struct player_data *p = &ctx->p; - struct module_data *m = &ctx->m; - int i; - - p->virt.num_tracks = num; - num = libxmp_mixer_numvoices(ctx, -1); - - p->virt.virt_channels = p->virt.num_tracks; - - if (HAS_QUIRK(QUIRK_VIRTUAL)) { - p->virt.virt_channels += num; - } else if (num > p->virt.virt_channels) { - num = p->virt.virt_channels; - } - - p->virt.maxvoc = libxmp_mixer_numvoices(ctx, num); - - p->virt.voice_array = (struct mixer_voice *)calloc(p->virt.maxvoc, - sizeof(struct mixer_voice)); - if (p->virt.voice_array == NULL) - goto err; - - for (i = 0; i < p->virt.maxvoc; i++) { - p->virt.voice_array[i].chn = FREE; - p->virt.voice_array[i].root = FREE; - } - -#ifdef LIBXMP_PAULA_SIMULATOR - /* Initialize Paula simulator */ - if (IS_AMIGA_MOD()) { - for (i = 0; i < p->virt.maxvoc; i++) { - p->virt.voice_array[i].paula = calloc(1, sizeof (struct paula_state)); - if (p->virt.voice_array[i].paula == NULL) { - goto err2; - } - libxmp_paula_init(ctx, p->virt.voice_array[i].paula); - } - } -#endif - - p->virt.virt_channel = (struct virt_channel *)malloc(p->virt.virt_channels * - sizeof(struct virt_channel)); - if (p->virt.virt_channel == NULL) - goto err2; - - for (i = 0; i < p->virt.virt_channels; i++) { - p->virt.virt_channel[i].map = FREE; - p->virt.virt_channel[i].count = 0; - } - - p->virt.virt_used = 0; - - return 0; - - err2: -#ifdef LIBXMP_PAULA_SIMULATOR - if (IS_AMIGA_MOD()) { - for (i = 0; i < p->virt.maxvoc; i++) { - free(p->virt.voice_array[i].paula); - } - } -#endif - free(p->virt.voice_array); - err: - return -1; -} - -void libxmp_virt_off(struct context_data *ctx) -{ - struct player_data *p = &ctx->p; -#ifdef LIBXMP_PAULA_SIMULATOR - struct module_data *m = &ctx->m; - int i; -#endif - -#ifdef LIBXMP_PAULA_SIMULATOR - /* Free Paula simulator state */ - if (IS_AMIGA_MOD()) { - for (i = 0; i < p->virt.maxvoc; i++) { - free(p->virt.voice_array[i].paula); - } - } -#endif - - p->virt.virt_used = p->virt.maxvoc = 0; - p->virt.virt_channels = 0; - p->virt.num_tracks = 0; - - free(p->virt.voice_array); - free(p->virt.virt_channel); -} - -void libxmp_virt_reset(struct context_data *ctx) -{ - struct player_data *p = &ctx->p; - int i; - - if (p->virt.virt_channels < 1) { - return; - } - - /* CID 129203 (#1 of 1): Useless call (USELESS_CALL) - * Call is only useful for its return value, which is ignored. - * - * libxmp_mixer_numvoices(ctx, p->virt.maxvoc); - */ - - for (i = 0; i < p->virt.maxvoc; i++) { - struct mixer_voice *vi = &p->virt.voice_array[i]; -#ifdef LIBXMP_PAULA_SIMULATOR - struct paula_state *paula = vi->paula; -#endif - memset(vi, 0, sizeof(struct mixer_voice)); -#ifdef LIBXMP_PAULA_SIMULATOR - vi->paula = paula; -#endif - vi->chn = FREE; - vi->root = FREE; - } - - for (i = 0; i < p->virt.virt_channels; i++) { - p->virt.virt_channel[i].map = FREE; - p->virt.virt_channel[i].count = 0; - } - - p->virt.virt_used = 0; -} - -static int free_voice(struct context_data *ctx) -{ - struct player_data *p = &ctx->p; - int i, num, vol; - - /* Find background voice with lowest volume*/ - num = FREE; - vol = INT_MAX; - for (i = 0; i < p->virt.maxvoc; i++) { - struct mixer_voice *vi = &p->virt.voice_array[i]; - - if (vi->chn >= p->virt.num_tracks && vi->vol < vol) { - num = i; - vol = vi->vol; - } - } - - /* Free voice */ - if (num >= 0) { - p->virt.virt_channel[p->virt.voice_array[num].chn].map = FREE; - p->virt.virt_channel[p->virt.voice_array[num].root].count--; - p->virt.virt_used--; - } - - return num; -} - -static int alloc_voice(struct context_data *ctx, int chn) -{ - struct player_data *p = &ctx->p; - int i; - - /* Find free voice */ - for (i = 0; i < p->virt.maxvoc; i++) { - if (p->virt.voice_array[i].chn == FREE) - break; - } - - /* not found */ - if (i == p->virt.maxvoc) { - i = free_voice(ctx); - } - - if (i >= 0) { - p->virt.virt_channel[chn].count++; - p->virt.virt_used++; - - p->virt.voice_array[i].chn = chn; - p->virt.voice_array[i].root = chn; - p->virt.virt_channel[chn].map = i; - } - - return i; -} - -static int map_virt_channel(struct player_data *p, int chn) -{ - int voc; - - if ((uint32)chn >= p->virt.virt_channels) - return -1; - - voc = p->virt.virt_channel[chn].map; - - if ((uint32)voc >= p->virt.maxvoc) - return -1; - - return voc; -} - -int libxmp_virt_mapchannel(struct context_data *ctx, int chn) -{ - return map_virt_channel(&ctx->p, chn); -} - -void libxmp_virt_resetchannel(struct context_data *ctx, int chn) -{ - struct player_data *p = &ctx->p; - struct mixer_voice *vi; -#ifdef LIBXMP_PAULA_SIMULATOR - struct paula_state *paula; -#endif - int voc; - - if ((voc = map_virt_channel(p, chn)) < 0) - return; - - libxmp_mixer_setvol(ctx, voc, 0); - - p->virt.virt_used--; - p->virt.virt_channel[p->virt.voice_array[voc].root].count--; - p->virt.virt_channel[chn].map = FREE; - - vi = &p->virt.voice_array[voc]; -#ifdef LIBXMP_PAULA_SIMULATOR - paula = vi->paula; -#endif - memset(vi, 0, sizeof(struct mixer_voice)); -#ifdef LIBXMP_PAULA_SIMULATOR - vi->paula = paula; -#endif - vi->chn = vi->root = FREE; -} - -void libxmp_virt_setvol(struct context_data *ctx, int chn, int vol) -{ - struct player_data *p = &ctx->p; - int voc, root; - - if ((voc = map_virt_channel(p, chn)) < 0) { - return; - } - - root = p->virt.voice_array[voc].root; - if (root < XMP_MAX_CHANNELS && p->channel_mute[root]) { - vol = 0; - } - - libxmp_mixer_setvol(ctx, voc, vol); - - if (vol == 0 && chn >= p->virt.num_tracks) { - libxmp_virt_resetvoice(ctx, voc, 1); - } -} - -void libxmp_virt_release(struct context_data *ctx, int chn, int rel) -{ - struct player_data *p = &ctx->p; - int voc; - - if ((voc = map_virt_channel(p, chn)) < 0) { - return; - } - - libxmp_mixer_release(ctx, voc, rel); -} - -void libxmp_virt_setpan(struct context_data *ctx, int chn, int pan) -{ - struct player_data *p = &ctx->p; - int voc; - - if ((voc = map_virt_channel(p, chn)) < 0) { - return; - } - - libxmp_mixer_setpan(ctx, voc, pan); -} - -void libxmp_virt_seteffect(struct context_data *ctx, int chn, int type, int val) -{ - struct player_data *p = &ctx->p; - int voc; - - if ((voc = map_virt_channel(p, chn)) < 0) { - return; - } - - libxmp_mixer_seteffect(ctx, voc, type, val); -} - -double libxmp_virt_getvoicepos(struct context_data *ctx, int chn) -{ - struct player_data *p = &ctx->p; - int voc; - - if ((voc = map_virt_channel(p, chn)) < 0) { - return -1; - } - - return libxmp_mixer_getvoicepos(ctx, voc); -} - -#ifndef LIBXMP_CORE_PLAYER - -void libxmp_virt_setsmp(struct context_data *ctx, int chn, int smp) -{ - struct player_data *p = &ctx->p; - struct mixer_voice *vi; - double pos; - int voc; - - if ((voc = map_virt_channel(p, chn)) < 0) { - return; - } - - vi = &p->virt.voice_array[voc]; - if (vi->smp == smp) { - return; - } - - pos = libxmp_mixer_getvoicepos(ctx, voc); - libxmp_mixer_setpatch(ctx, voc, smp, 0); - libxmp_mixer_voicepos(ctx, voc, pos, 0); /* Restore old position */ -} - -#endif - -#ifndef LIBXMP_CORE_DISABLE_IT - -void libxmp_virt_setnna(struct context_data *ctx, int chn, int nna) -{ - struct player_data *p = &ctx->p; - int voc; - - if ((voc = map_virt_channel(p, chn)) < 0) { - return; - } - - p->virt.voice_array[voc].act = nna; -} - -static void check_dct(struct context_data *ctx, int i, int chn, int ins, - int smp, int note, int nna, int dct, int dca) -{ - struct player_data *p = &ctx->p; - struct mixer_voice *vi = &p->virt.voice_array[i]; - int voc; - - voc = p->virt.virt_channel[chn].map; - - if (vi->root == chn && vi->ins == ins) { - - if (nna == XMP_INST_NNA_CUT) { - libxmp_virt_resetvoice(ctx, i, 1); - return; - } - - vi->act = nna; - - if ((dct == XMP_INST_DCT_INST) || - (dct == XMP_INST_DCT_SMP && vi->smp == smp) || - (dct == XMP_INST_DCT_NOTE && vi->note == note)) { - - if (nna == XMP_INST_NNA_OFF && dca == XMP_INST_DCA_FADE) { - vi->act = VIRT_ACTION_OFF; - } else if (dca) { - if (i != voc || vi->act) { - vi->act = dca; - } - } else { - libxmp_virt_resetvoice(ctx, i, 1); - } - } - } -} - -#endif - -/* For note slides */ -void libxmp_virt_setnote(struct context_data *ctx, int chn, int note) -{ - struct player_data *p = &ctx->p; - int voc; - - if ((voc = map_virt_channel(p, chn)) < 0) { - return; - } - - libxmp_mixer_setnote(ctx, voc, note); -} - -int libxmp_virt_setpatch(struct context_data *ctx, int chn, int ins, int smp, - int note, int nna, int dct, int dca) -{ - struct player_data *p = &ctx->p; - int voc, vfree; - - if ((uint32)chn >= p->virt.virt_channels) { - return -1; - } - - if (ins < 0) { - smp = -1; - } - -#ifndef LIBXMP_CORE_DISABLE_IT - if (dct) { - int i; - - for (i = 0; i < p->virt.maxvoc; i++) { - check_dct(ctx, i, chn, ins, smp, note, nna, dct, dca); - } - } -#endif - - voc = p->virt.virt_channel[chn].map; - - if (voc > FREE) { - if (p->virt.voice_array[voc].act) { - vfree = alloc_voice(ctx, chn); - - if (vfree < 0) { - return -1; - } - - for (chn = p->virt.num_tracks; - p->virt.virt_channel[chn++].map > FREE;) ; - - p->virt.voice_array[voc].chn = --chn; - p->virt.virt_channel[chn].map = voc; - voc = vfree; - } - } else { - voc = alloc_voice(ctx, chn); - if (voc < 0) { - return -1; - } - } - - if (smp < 0) { - libxmp_virt_resetvoice(ctx, voc, 1); - return chn; /* was -1 */ - } - - libxmp_mixer_setpatch(ctx, voc, smp, 1); - libxmp_mixer_setnote(ctx, voc, note); - p->virt.voice_array[voc].ins = ins; - p->virt.voice_array[voc].act = nna; - - return chn; -} - -void libxmp_virt_setperiod(struct context_data *ctx, int chn, double period) -{ - struct player_data *p = &ctx->p; - int voc; - - if ((voc = map_virt_channel(p, chn)) < 0) { - return; - } - - libxmp_mixer_setperiod(ctx, voc, period); -} - -void libxmp_virt_voicepos(struct context_data *ctx, int chn, double pos) -{ - struct player_data *p = &ctx->p; - int voc; - - if ((voc = map_virt_channel(p, chn)) < 0) { - return; - } - - libxmp_mixer_voicepos(ctx, voc, pos, 1); -} - -#ifndef LIBXMP_CORE_DISABLE_IT - -void libxmp_virt_pastnote(struct context_data *ctx, int chn, int act) -{ - struct player_data *p = &ctx->p; - int c, voc; - - for (c = p->virt.num_tracks; c < p->virt.virt_channels; c++) { - if ((voc = map_virt_channel(p, c)) < 0) - continue; - - if (p->virt.voice_array[voc].root == chn) { - switch (act) { - case VIRT_ACTION_CUT: - libxmp_virt_resetvoice(ctx, voc, 1); - break; - case VIRT_ACTION_OFF: - libxmp_player_set_release(ctx, c); - break; - case VIRT_ACTION_FADE: - libxmp_player_set_fadeout(ctx, c); - break; - } - } - } -} - -#endif - -int libxmp_virt_cstat(struct context_data *ctx, int chn) -{ - struct player_data *p = &ctx->p; - int voc; - - if ((voc = map_virt_channel(p, chn)) < 0) { - return VIRT_INVALID; - } - - if (chn < p->virt.num_tracks) { - return VIRT_ACTIVE; - } - - return p->virt.voice_array[voc].act; -} diff --git a/source/libxmp-lite/src/virtual.h b/source/libxmp-lite/src/virtual.h deleted file mode 100644 index a7668c562..000000000 --- a/source/libxmp-lite/src/virtual.h +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef LIBXMP_VIRTUAL_H -#define LIBXMP_VIRTUAL_H - -#include "common.h" - -#define VIRT_ACTION_CUT XMP_INST_NNA_CUT -#define VIRT_ACTION_CONT XMP_INST_NNA_CONT -#define VIRT_ACTION_OFF XMP_INST_NNA_OFF -#define VIRT_ACTION_FADE XMP_INST_NNA_FADE - -#define VIRT_ACTIVE 0x100 -#define VIRT_INVALID -1 - -int libxmp_virt_on (struct context_data *, int); -void libxmp_virt_off (struct context_data *); -int libxmp_virt_mute (struct context_data *, int, int); -int libxmp_virt_setpatch (struct context_data *, int, int, int, int, - int, int, int); -int libxmp_virt_cvt8bit (void); -void libxmp_virt_setnote (struct context_data *, int, int); -void libxmp_virt_setsmp (struct context_data *, int, int); -void libxmp_virt_setnna (struct context_data *, int, int); -void libxmp_virt_pastnote (struct context_data *, int, int); -void libxmp_virt_setvol (struct context_data *, int, int); -void libxmp_virt_voicepos (struct context_data *, int, double); -double libxmp_virt_getvoicepos (struct context_data *, int); -void libxmp_virt_setperiod (struct context_data *, int, double); -void libxmp_virt_setpan (struct context_data *, int, int); -void libxmp_virt_seteffect (struct context_data *, int, int, int); -int libxmp_virt_cstat (struct context_data *, int); -int libxmp_virt_mapchannel (struct context_data *, int); -void libxmp_virt_resetchannel(struct context_data *, int); -void libxmp_virt_resetvoice (struct context_data *, int, int); -void libxmp_virt_reset (struct context_data *); -void libxmp_virt_release (struct context_data *, int, int); -int libxmp_virt_getroot (struct context_data *, int); - -#endif /* LIBXMP_VIRTUAL_H */ diff --git a/source/libxmp-lite/src/win32.c b/source/libxmp-lite/src/win32.c deleted file mode 100644 index 3844565ac..000000000 --- a/source/libxmp-lite/src/win32.c +++ /dev/null @@ -1,34 +0,0 @@ -/* _[v]snprintf() from msvcrt.dll might not nul terminate */ -/* OpenWatcom-provided versions seem to behave the same... */ - -#if defined(_WIN32) || defined(__WATCOMC__) - -#include -#include - -#undef snprintf -#undef vsnprintf - -int libxmp_vsnprintf(char *str, size_t sz, const char *fmt, va_list ap) -{ - int rc = _vsnprintf(str, sz, fmt, ap); - if (sz != 0) { - if (rc < 0) rc = (int)sz; - if ((size_t)rc >= sz) str[sz - 1] = '\0'; - } - return rc; -} - -int libxmp_snprintf (char *str, size_t sz, const char *fmt, ...) -{ - va_list ap; - int rc; - - va_start (ap, fmt); - rc = _vsnprintf(str, sz, fmt, ap); - va_end (ap); - - return rc; -} - -#endif diff --git a/source/libxmp-lite/src/xm.h b/source/libxmp-lite/src/xm.h deleted file mode 100644 index 443a369ce..000000000 --- a/source/libxmp-lite/src/xm.h +++ /dev/null @@ -1,101 +0,0 @@ -#ifndef LIBXMP_LOADERS_XM_H -#define LIBXMP_LOADERS_XM_H - -#define XM_EVENT_PACKING 0x80 -#define XM_EVENT_PACK_MASK 0x7f -#define XM_EVENT_NOTE_FOLLOWS 0x01 -#define XM_EVENT_INSTRUMENT_FOLLOWS 0x02 -#define XM_EVENT_VOLUME_FOLLOWS 0x04 -#define XM_EVENT_FXTYPE_FOLLOWS 0x08 -#define XM_EVENT_FXPARM_FOLLOWS 0x10 -#define XM_LINEAR_FREQ 0x01 -#define XM_LOOP_MASK 0x03 -#define XM_LOOP_NONE 0 -#define XM_LOOP_FORWARD 1 -#define XM_LOOP_PINGPONG 2 -#define XM_SAMPLE_16BIT 0x10 -#define XM_ENVELOPE_ON 0x01 -#define XM_ENVELOPE_SUSTAIN 0x02 -#define XM_ENVELOPE_LOOP 0x04 -#define XM_LINEAR_PERIOD_MODE 0x01 - - -struct xm_file_header { - uint8 id[17]; /* ID text: "Extended module: " */ - uint8 name[20]; /* Module name, padded with zeroes */ - uint8 doseof; /* 0x1a */ - uint8 tracker[20]; /* Tracker name */ - uint16 version; /* Version number, minor-major */ - uint32 headersz; /* Header size */ - uint16 songlen; /* Song length (in patten order table) */ - uint16 restart; /* Restart position */ - uint16 channels; /* Number of channels (2,4,6,8,10,...,32) */ - uint16 patterns; /* Number of patterns (max 256) */ - uint16 instruments; /* Number of instruments (max 128) */ - uint16 flags; /* bit 0: 0=Amiga freq table, 1=Linear */ - uint16 tempo; /* Default tempo */ - uint16 bpm; /* Default BPM */ - uint8 order[256]; /* Pattern order table */ -}; - -struct xm_pattern_header { - uint32 length; /* Pattern header length */ - uint8 packing; /* Packing type (always 0) */ - uint16 rows; /* Number of rows in pattern (1..256) */ - uint16 datasize; /* Packed patterndata size */ -}; - -struct xm_instrument_header { - uint32 size; /* Instrument size */ - uint8 name[22]; /* Instrument name */ - uint8 type; /* Instrument type (always 0) */ - uint16 samples; /* Number of samples in instrument */ - uint32 sh_size; /* Sample header size */ -}; - -struct xm_instrument { - uint8 sample[96]; /* Sample number for all notes */ - uint16 v_env[24]; /* Points for volume envelope */ - uint16 p_env[24]; /* Points for panning envelope */ - uint8 v_pts; /* Number of volume points */ - uint8 p_pts; /* Number of panning points */ - uint8 v_sus; /* Volume sustain point */ - uint8 v_start; /* Volume loop start point */ - uint8 v_end; /* Volume loop end point */ - uint8 p_sus; /* Panning sustain point */ - uint8 p_start; /* Panning loop start point */ - uint8 p_end; /* Panning loop end point */ - uint8 v_type; /* Bit 0: On; 1: Sustain; 2: Loop */ - uint8 p_type; /* Bit 0: On; 1: Sustain; 2: Loop */ - uint8 y_wave; /* Vibrato waveform */ - uint8 y_sweep; /* Vibrato sweep */ - uint8 y_depth; /* Vibrato depth */ - uint8 y_rate; /* Vibrato rate */ - uint16 v_fade; /* Volume fadeout */ -#if 0 - uint8 reserved[22]; /* Reserved; 2 bytes in specs, 22 in 1.04 */ -#endif -}; - -struct xm_sample_header { - uint32 length; /* Sample length */ - uint32 loop_start; /* Sample loop start */ - uint32 loop_length; /* Sample loop length */ - uint8 volume; /* Volume */ - int8 finetune; /* Finetune (signed byte -128..+127) */ - uint8 type; /* 0=No loop,1=Fwd loop,2=Ping-pong,16-bit */ - uint8 pan; /* Panning (0-255) */ - int8 relnote; /* Relative note number (signed byte) */ - uint8 reserved; /* Reserved */ - uint8 name[22]; /* Sample_name */ -}; - -struct xm_event { - uint8 note; /* Note (0-71, 0 = C-0) */ - uint8 instrument; /* Instrument (0-128) */ - uint8 volume; /* Volume column byte */ - uint8 fx_type; /* Effect type */ - uint8 fx_parm; /* Effect parameter */ -}; - -#endif diff --git a/source/libxmp-lite/src/xm_load.c b/source/libxmp-lite/src/xm_load.c deleted file mode 100644 index e310f5d17..000000000 --- a/source/libxmp-lite/src/xm_load.c +++ /dev/null @@ -1,789 +0,0 @@ -/* Extended Module Player - * 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"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -/* - * Fri, 26 Jun 1998 17:45:59 +1000 Andrew Leahy - * Finally got it working on the DEC Alpha running DEC UNIX! In the pattern - * reading loop I found I was getting "0" for (p-patbuf) and "0" for - * xph.datasize, the next if statement (where it tries to read the patbuf) - * would then cause a seg_fault. - * - * Sun Sep 27 12:07:12 EST 1998 Claudio Matsuoka - * Extended Module 1.02 stores data in a different order, we must handle - * this accordingly. MAX_SAMP used as a workaround to check the number of - * samples recognized by the player. - */ - -#include "loader.h" -#include "xm.h" - -static int xm_test(HIO_HANDLE *, char *, const int); -static int xm_load(struct module_data *, HIO_HANDLE *, const int); - -extern const struct format_loader libxmp_loader_xm; -const struct format_loader libxmp_loader_xm = { - "Fast Tracker II", - xm_test, - xm_load -}; - -static int xm_test(HIO_HANDLE *f, char *t, const int start) -{ - char buf[20]; - - if (hio_read(buf, 1, 17, f) < 17) /* ID text */ - return -1; - - if (memcmp(buf, "Extended Module: ", 17)) - return -1; - - libxmp_read_title(f, t, 20); - - return 0; -} - -static int load_xm_pattern(struct module_data *m, int num, int version, HIO_HANDLE *f) -{ - const int headsize = version > 0x0102 ? 9 : 8; - struct xmp_module *mod = &m->mod; - struct xm_pattern_header xph; - struct xmp_event *event; - uint8 *patbuf, *pat, b; - int j, r; - int size; - - xph.length = hio_read32l(f); - xph.packing = hio_read8(f); - xph.rows = version > 0x0102 ? hio_read16l(f) : hio_read8(f) + 1; - - /* Sanity check */ - if (xph.rows > 256) { - goto err; - } - - xph.datasize = hio_read16l(f); - hio_seek(f, xph.length - headsize, SEEK_CUR); - if (hio_error(f)) { - goto err; - } - - r = xph.rows; - if (r == 0) { - r = 0x100; - } - - if (libxmp_alloc_pattern_tracks(mod, num, r) < 0) { - goto err; - } - - if (xph.datasize == 0) { - return 0; - } - - size = xph.datasize; - - pat = patbuf = (uint8 *)calloc(1, size); - if (patbuf == NULL) { - goto err; - } - - hio_read(patbuf, 1, size, f); - for (j = 0; j < (mod->chn * r); j++) { - - /*if ((pat - patbuf) >= xph.datasize) - break; */ - - event = &EVENT(num, j % mod->chn, j / mod->chn); - - if (--size < 0) { - goto err2; - } - - if ((b = *pat++) & XM_EVENT_PACKING) { - if (b & XM_EVENT_NOTE_FOLLOWS) { - if (--size < 0) - goto err2; - event->note = *pat++; - } - if (b & XM_EVENT_INSTRUMENT_FOLLOWS) { - if (--size < 0) - goto err2; - event->ins = *pat++; - } - if (b & XM_EVENT_VOLUME_FOLLOWS) { - if (--size < 0) - goto err2; - event->vol = *pat++; - } - if (b & XM_EVENT_FXTYPE_FOLLOWS) { - if (--size < 0) - goto err2; - event->fxt = *pat++; - } - if (b & XM_EVENT_FXPARM_FOLLOWS) { - if (--size < 0) - goto err2; - event->fxp = *pat++; - } - } else { - size -= 4; - if (size < 0) - goto err2; - event->note = b; - event->ins = *pat++; - event->vol = *pat++; - event->fxt = *pat++; - event->fxp = *pat++; - } - - /* Sanity check */ - switch (event->fxt) { - case 18: - case 19: - case 22: - case 23: - case 24: - case 26: - case 28: - case 30: - case 31: - case 32: - event->fxt = 0; - } - if (event->fxt > 34) { - event->fxt = 0; - } - - if (event->note == 0x61) { - /* See OpenMPT keyoff+instr.xm test case */ - if (event->fxt == 0x0e && MSN(event->fxp) == 0x0d) { - event->note = XMP_KEY_OFF; - } else { - event->note = - event->ins ? XMP_KEY_FADE : XMP_KEY_OFF; - } - } else if (event->note > 0) { - event->note += 12; - } - - if (event->fxt == 0x0e) { - if (MSN(event->fxp) == EX_FINETUNE) { - unsigned char val = (LSN(event->fxp) - 8) & 0xf; - event->fxp = (EX_FINETUNE << 4) | val; - } - switch (event->fxp) { - case 0x43: - case 0x73: - event->fxp--; - break; - } - } - - if (!event->vol) { - continue; - } - - /* Volume set */ - if ((event->vol >= 0x10) && (event->vol <= 0x50)) { - event->vol -= 0x0f; - continue; - } - - /* Volume column effects */ - switch (event->vol >> 4) { - case 0x06: /* Volume slide down */ - event->f2t = FX_VOLSLIDE_2; - event->f2p = event->vol - 0x60; - break; - case 0x07: /* Volume slide up */ - event->f2t = FX_VOLSLIDE_2; - event->f2p = (event->vol - 0x70) << 4; - break; - case 0x08: /* Fine volume slide down */ - event->f2t = FX_EXTENDED; - event->f2p = - (EX_F_VSLIDE_DN << 4) | (event->vol - 0x80); - break; - case 0x09: /* Fine volume slide up */ - event->f2t = FX_EXTENDED; - event->f2p = - (EX_F_VSLIDE_UP << 4) | (event->vol - 0x90); - break; - case 0x0a: /* Set vibrato speed */ - event->f2t = FX_VIBRATO; - event->f2p = (event->vol - 0xa0) << 4; - break; - case 0x0b: /* Vibrato */ - event->f2t = FX_VIBRATO; - event->f2p = event->vol - 0xb0; - break; - case 0x0c: /* Set panning */ - event->f2t = FX_SETPAN; - event->f2p = (event->vol - 0xc0) << 4; - break; - case 0x0d: /* Pan slide left */ - event->f2t = FX_PANSL_NOMEM; - event->f2p = (event->vol - 0xd0) << 4; - break; - case 0x0e: /* Pan slide right */ - event->f2t = FX_PANSL_NOMEM; - event->f2p = event->vol - 0xe0; - break; - case 0x0f: /* Tone portamento */ - event->f2t = FX_TONEPORTA; - event->f2p = (event->vol - 0xf0) << 4; - - /* From OpenMPT TonePortamentoMemory.xm: - * "Another nice bug (...) is the combination of both - * portamento commands (Mx and 3xx) in the same cell: - * The 3xx parameter is ignored completely, and the Mx - * parameter is doubled. (M2 3FF is the same as M4 000) - */ - if (event->fxt == FX_TONEPORTA - || event->fxt == FX_TONE_VSLIDE) { - if (event->fxt == FX_TONEPORTA) { - event->fxt = 0; - } else { - event->fxt = FX_VOLSLIDE; - } - event->fxp = 0; - - if (event->f2p < 0x80) { - event->f2p <<= 1; - } else { - event->f2p = 0xff; - } - } - - /* From OpenMPT porta-offset.xm: - * "If there is a portamento command next to an offset - * command, the offset command is ignored completely. In - * particular, the offset parameter is not memorized." - */ - if (event->fxt == FX_OFFSET - && event->f2t == FX_TONEPORTA) { - event->fxt = event->fxp = 0; - } - break; - } - event->vol = 0; - } - free(patbuf); - - return 0; - -err2: - free(patbuf); -err: - return -1; -} - -static int load_patterns(struct module_data *m, int version, HIO_HANDLE *f) -{ - struct xmp_module *mod = &m->mod; - int i, j; - - mod->pat++; - if (libxmp_init_pattern(mod) < 0) { - return -1; - } - - D_(D_INFO "Stored patterns: %d", mod->pat - 1); - - for (i = 0; i < mod->pat - 1; i++) { - if (load_xm_pattern(m, i, version, f) < 0) { - goto err; - } - } - - /* Alloc one extra pattern */ - { - int t = i * mod->chn; - - if (libxmp_alloc_pattern(mod, i) < 0) { - goto err; - } - - mod->xxp[i]->rows = 64; - - if (libxmp_alloc_track(mod, t, 64) < 0) { - goto err; - } - - for (j = 0; j < mod->chn; j++) { - mod->xxp[i]->index[j] = t; - } - } - - return 0; - -err: - return -1; -} - -/* Packed structures size */ -#define XM_INST_HEADER_SIZE 33 -#define XM_INST_SIZE 208 - -static int load_instruments(struct module_data *m, int version, HIO_HANDLE * f) -{ - struct xmp_module *mod = &m->mod; - struct xm_instrument_header xih; - struct xm_instrument xi; - struct xm_sample_header xsh[16]; - int sample_num = 0; - long total_sample_size; - int i, j; - uint8 buf[208]; - - D_(D_INFO "Instruments: %d", mod->ins); - - /* ESTIMATED value! We don't know the actual value at this point */ - mod->smp = MAX_SAMPLES; - - if (libxmp_init_instrument(m) < 0) - 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 - * instruments, but file may end abruptly before that. Also covers - * XMLiTE stripped modules and truncated files. This test will not - * work if file has trailing garbage. - */ - if (hio_read(buf, 33, 1, f) != 1) { - D_(D_WARN "short read in instrument header data"); - break; - } - - xih.size = readmem32l(buf); /* Instrument size */ - memcpy(xih.name, buf + 4, 22); /* Instrument name */ - xih.type = buf[26]; /* Instrument type (always 0) */ - xih.samples = readmem16l(buf + 27); /* Number of samples */ - xih.sh_size = readmem32l(buf + 29); /* Sample header size */ - - /* Sanity check */ - if (xih.samples > 0x10 || (xih.samples > 0 && xih.sh_size > 0x100)) { - D_(D_CRIT "Sanity check: %d %d", xih.samples, xih.sh_size); - return -1; - } - - libxmp_instrument_name(mod, i, xih.name, 22); - - xxi->nsm = xih.samples; - - D_(D_INFO "[%2X] %-22.22s %2d", i, xxi->name, xxi->nsm); - - if (xxi->nsm == 0) { - /* Sample size should be in struct xm_instrument according to - * the official format description, but FT2 actually puts it in - * struct xm_instrument header. There's a tracker or converter - * that follow the specs, so we must handle both cases (see - * "Braintomb" by Jazztiz/ART). - */ - - /* Umm, Cyke O'Path sent me a couple of - * mods ("Breath of the Wind" and "Broken Dimension") that - * reserve the instrument data space after the instrument header - * even if the number of instruments is set to 0. In these modules - * the instrument header size is marked as 263. The following - * generalization should take care of both cases. - */ - - if (hio_seek(f, (int)xih.size - XM_INST_HEADER_SIZE, SEEK_CUR) < 0) { - return -1; - } - - continue; - } - - if (libxmp_alloc_subinstrument(mod, i, xxi->nsm) < 0) { - return -1; - } - - if (xih.size < XM_INST_HEADER_SIZE) { - return -1; - } - - /* for BoobieSqueezer (see http://boobie.rotfl.at/) - * It works pretty much the same way as Impulse Tracker's sample - * only mode, where it will strip off the instrument data. - */ - if (xih.size < XM_INST_HEADER_SIZE + XM_INST_SIZE) { - memset(&xi, 0, sizeof(struct xm_instrument)); - hio_seek(f, xih.size - XM_INST_HEADER_SIZE, SEEK_CUR); - } else { - uint8 *b = buf; - - if (hio_read(buf, 208, 1, f) != 1) { - D_(D_CRIT "short read in instrument data"); - return -1; - } - - memcpy(xi.sample, b, 96); /* Sample map */ - b += 96; - - for (j = 0; j < 24; j++) { - xi.v_env[j] = readmem16l(b); /* Points for volume envelope */ - b += 2; - } - - for (j = 0; j < 24; j++) { - xi.p_env[j] = readmem16l(b); /* Points for pan envelope */ - b += 2; - } - - xi.v_pts = *b++; /* Number of volume points */ - xi.p_pts = *b++; /* Number of pan points */ - xi.v_sus = *b++; /* Volume sustain point */ - xi.v_start = *b++; /* Volume loop start point */ - xi.v_end = *b++; /* Volume loop end point */ - xi.p_sus = *b++; /* Pan sustain point */ - xi.p_start = *b++; /* Pan loop start point */ - xi.p_end = *b++; /* Pan loop end point */ - xi.v_type = *b++; /* Bit 0:On 1:Sustain 2:Loop */ - xi.p_type = *b++; /* Bit 0:On 1:Sustain 2:Loop */ - xi.y_wave = *b++; /* Vibrato waveform */ - xi.y_sweep = *b++; /* Vibrato sweep */ - xi.y_depth = *b++; /* Vibrato depth */ - xi.y_rate = *b++; /* Vibrato rate */ - xi.v_fade = readmem16l(b); /* Volume fadeout */ - - /* Skip reserved space */ - if (hio_seek(f, (int)xih.size - (XM_INST_HEADER_SIZE + XM_INST_SIZE), SEEK_CUR) < 0) { - return -1; - } - - /* Envelope */ - xxi->rls = xi.v_fade << 1; - xxi->aei.npt = xi.v_pts; - xxi->aei.sus = xi.v_sus; - xxi->aei.lps = xi.v_start; - xxi->aei.lpe = xi.v_end; - xxi->aei.flg = xi.v_type; - xxi->pei.npt = xi.p_pts; - xxi->pei.sus = xi.p_sus; - xxi->pei.lps = xi.p_start; - xxi->pei.lpe = xi.p_end; - xxi->pei.flg = xi.p_type; - - if (xxi->aei.npt <= 0 || xxi->aei.npt > 12 /*XMP_MAX_ENV_POINTS */ ) { - xxi->aei.flg &= ~XMP_ENVELOPE_ON; - } else { - memcpy(xxi->aei.data, xi.v_env, xxi->aei.npt * 4); - } - - if (xxi->pei.npt <= 0 || xxi->pei.npt > 12 /*XMP_MAX_ENV_POINTS */ ) { - xxi->pei.flg &= ~XMP_ENVELOPE_ON; - } else { - memcpy(xxi->pei.data, xi.p_env, xxi->pei.npt * 4); - } - - for (j = 12; j < 108; j++) { - xxi->map[j].ins = xi.sample[j - 12]; - if (xxi->map[j].ins >= xxi->nsm) - xxi->map[j].ins = -1; - } - } - - for (j = 0; j < xxi->nsm; j++, sample_num++) { - struct xmp_subinstrument *sub = &xxi->sub[j]; - struct xmp_sample *xxs; - uint8 *b = buf; - - if (sample_num >= mod->smp) { - mod->xxs = libxmp_realloc_samples(mod->xxs, &mod->smp, mod->smp * 3 / 2); - if (mod->xxs == NULL) - return -1; - } - xxs = &mod->xxs[sample_num]; - - if (hio_read(buf, 40, 1, f) != 1) { - D_(D_CRIT "short read in sample data"); - return -1; - } - - xsh[j].length = readmem32l(b); /* Sample length */ - b += 4; - - /* Sanity check */ - if (xsh[j].length > MAX_SAMPLE_SIZE) { - D_(D_CRIT "sanity check: %d: bad sample size", j); - return -1; - } - - xsh[j].loop_start = readmem32l(b); /* Sample loop start */ - b += 4; - xsh[j].loop_length = readmem32l(b); /* Sample loop length */ - b += 4; - xsh[j].volume = *b++; /* Volume */ - xsh[j].finetune = *b++; /* Finetune (-128..+127) */ - xsh[j].type = *b++; /* Flags */ - xsh[j].pan = *b++; /* Panning (0-255) */ - xsh[j].relnote = *(int8 *) b++; /* Relative note number */ - xsh[j].reserved = *b++; - memcpy(xsh[j].name, b, 22); - - sub->vol = xsh[j].volume; - sub->pan = xsh[j].pan; - sub->xpo = xsh[j].relnote; - sub->fin = xsh[j].finetune; - sub->vwf = xi.y_wave; - sub->vde = xi.y_depth << 2; - sub->vra = xi.y_rate; - sub->vsw = xi.y_sweep; - sub->sid = sample_num; - - libxmp_copy_adjust(xxs->name, xsh[j].name, 22); - - xxs->len = xsh[j].length; - xxs->lps = xsh[j].loop_start; - xxs->lpe = xsh[j].loop_start + xsh[j].loop_length; - - xxs->flg = 0; - if (xsh[j].type & XM_SAMPLE_16BIT) { - xxs->flg |= XMP_SAMPLE_16BIT; - xxs->len >>= 1; - xxs->lps >>= 1; - xxs->lpe >>= 1; - } - - xxs->flg |= xsh[j].type & XM_LOOP_FORWARD ? XMP_SAMPLE_LOOP : 0; - 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; - - D_(D_INFO " %1x: %06x%c%06x %06x %c V%02x F%+04d P%02x R%+03d", - j, mod->xxs[sub->sid].len, - mod->xxs[sub->sid].flg & XMP_SAMPLE_16BIT ? '+' : ' ', - mod->xxs[sub->sid].lps, - mod->xxs[sub->sid].lpe, - mod->xxs[sub->sid].flg & XMP_SAMPLE_LOOP_BIDIR ? 'B' : - mod->xxs[sub->sid].flg & XMP_SAMPLE_LOOP ? 'L' : ' ', - sub->vol, sub->fin, sub->pan, sub->xpo); - - flags = SAMPLE_FLAG_DIFF; -#ifndef LIBXMP_CORE_PLAYER - if (xsh[j].reserved == 0xad) { - flags = SAMPLE_FLAG_ADPCM; - } -#endif - - if (version > 0x0103) { - 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; - } - } - - /* Final sample number adjustment */ - mod->xxs = libxmp_realloc_samples(mod->xxs, &mod->smp, sample_num); - if (mod->xxs == NULL) { - return -1; - } - - return 0; -} - -static int xm_load(struct module_data *m, HIO_HANDLE * f, const int start) -{ - struct xmp_module *mod = &m->mod; - int i, j; - struct xm_file_header xfh; - char tracker_name[21]; - int len; - uint8 buf[80]; - - LOAD_INIT(); - - if (hio_read(buf, 80, 1, f) != 1) { - D_(D_CRIT "error reading header"); - return -1; - } - - memcpy(xfh.id, buf, 17); /* ID text */ - memcpy(xfh.name, buf + 17, 20); /* Module name */ - /* */ /* skip 0x1a */ - memcpy(xfh.tracker, buf + 38, 20); /* Tracker name */ - xfh.version = readmem16l(buf + 58); /* Version number, minor-major */ - xfh.headersz = readmem32l(buf + 60); /* Header size */ - xfh.songlen = readmem16l(buf + 64); /* Song length */ - xfh.restart = readmem16l(buf + 66); /* Restart position */ - xfh.channels = readmem16l(buf + 68); /* Number of channels */ - xfh.patterns = readmem16l(buf + 70); /* Number of patterns */ - xfh.instruments = readmem16l(buf + 72); /* Number of instruments */ - xfh.flags = readmem16l(buf + 74); /* 0=Amiga freq table, 1=Linear */ - xfh.tempo = readmem16l(buf + 76); /* Default tempo */ - xfh.bpm = readmem16l(buf + 78); /* Default BPM */ - - /* Sanity checks */ - if (xfh.songlen > 256 || xfh.patterns > 256 || xfh.instruments > 255) { - D_(D_CRIT "Sanity check: %d %d %d", xfh.songlen, xfh.patterns, xfh.instruments); - return -1; - } - - if (xfh.restart > 255 || xfh.channels > XMP_MAX_CHANNELS) { - D_(D_CRIT "Sanity check: %d %d", xfh.restart, xfh.channels); - return -1; - } - - if (xfh.tempo >= 32 || xfh.bpm < 32 || xfh.bpm > 255) { - if (memcmp("MED2XM", xfh.tracker, 6)) { - D_(D_CRIT "Sanity check: %d %d", xfh.tempo, xfh.bpm); - return -1; - } - } - - /* Honor header size -- needed by BoobieSqueezer XMs */ - len = xfh.headersz - 0x14; - if (len < 0 || len > 256) { - D_(D_CRIT "Sanity check: %d", len); - return -1; - } - - if (hio_read(&xfh.order, len, 1, f) != 1) { /* Pattern order table */ - D_(D_CRIT "error reading orders"); - return -1; - } - - strncpy(mod->name, (char *)xfh.name, 20); - - mod->len = xfh.songlen; - mod->chn = xfh.channels; - mod->pat = xfh.patterns; - mod->ins = xfh.instruments; - mod->rst = xfh.restart; - mod->spd = xfh.tempo; - mod->bpm = xfh.bpm; - mod->trk = mod->chn * mod->pat + 1; - - m->c4rate = C4_NTSC_RATE; - m->period_type = xfh.flags & XM_LINEAR_PERIOD_MODE ? PERIOD_LINEAR : PERIOD_AMIGA; - - memcpy(mod->xxo, xfh.order, mod->len); - /*tracker_name[20] = 0;*/ - snprintf(tracker_name, 21, "%-20.20s", xfh.tracker); - for (i = 20; i >= 0; i--) { - if (tracker_name[i] == 0x20) - tracker_name[i] = 0; - if (tracker_name[i]) - break; - } - - /* OpenMPT accurately emulates weird FT2 bugs */ - if (!strncmp(tracker_name, "FastTracker v2.00", 17) || - !strncmp(tracker_name, "OpenMPT ", 8)) { - m->quirk |= QUIRK_FT2BUGS; - } -#ifndef LIBXMP_CORE_PLAYER - if (xfh.headersz == 0x0113) { - strcpy(tracker_name, "unknown tracker"); - m->quirk &= ~QUIRK_FT2BUGS; - } else if (*tracker_name == 0) { - strcpy(tracker_name, "Digitrakker"); /* best guess */ - m->quirk &= ~QUIRK_FT2BUGS; - } - - /* See MMD1 loader for explanation */ - if (!strncmp(tracker_name, "MED2XM by J.Pynnone", 19)) { - if (mod->bpm <= 10) { - mod->bpm = 125 * (0x35 - mod->bpm * 2) / 33; - } - m->quirk &= ~QUIRK_FT2BUGS; - } - - if (!strncmp(tracker_name, "FastTracker v 2.00", 18)) { - strcpy(tracker_name, "old ModPlug Tracker"); - m->quirk &= ~QUIRK_FT2BUGS; - } - - libxmp_set_type(m, "%s XM %d.%02d", tracker_name, xfh.version >> 8, xfh.version & 0xff); -#else - libxmp_set_type(m, tracker_name); -#endif - - MODULE_INFO(); - - /* Honor header size */ - if (hio_seek(f, start + xfh.headersz + 60, SEEK_SET) < 0) { - return -1; - } - - /* XM 1.02/1.03 has a different patterns and instruments order */ - if (xfh.version <= 0x0103) { - if (load_instruments(m, xfh.version, f) < 0) { - return -1; - } - if (load_patterns(m, xfh.version, f) < 0) { - return -1; - } - } else { - if (load_patterns(m, xfh.version, f) < 0) { - return -1; - } - if (load_instruments(m, xfh.version, f) < 0) { - return -1; - } - } - - D_(D_INFO "Stored samples: %d", mod->smp); - - /* XM 1.02 stores all samples after the patterns */ - if (xfh.version <= 0x0103) { - for (i = 0; i < mod->ins; i++) { - for (j = 0; j < mod->xxi[i].nsm; j++) { - int sid = mod->xxi[i].sub[j].sid; - if (libxmp_load_sample(m, f, SAMPLE_FLAG_DIFF, &mod->xxs[sid], NULL) < 0) { - return -1; - } - } - } - } - - for (i = 0; i < mod->chn; i++) { - mod->xxc[i].pan = 0x80; - } - - m->quirk |= QUIRKS_FT2; - m->read_event_type = READ_EVENT_FT2; - - return 0; -}