diff --git a/dumb/include/internal/it.h b/dumb/include/internal/it.h index e248ade796..36b083e0c4 100644 --- a/dumb/include/internal/it.h +++ b/dumb/include/internal/it.h @@ -643,6 +643,10 @@ struct IT_CHANNEL unsigned char xm_lastX1; unsigned char xm_lastX2; + unsigned char inv_loop_delay; + unsigned char inv_loop_speed; + int inv_loop_offset; + IT_PLAYING *playing; #ifdef BIT_ARRAY_BULLSHIT @@ -802,6 +806,7 @@ extern DUH_SIGTYPE_DESC _dumb_sigtype_it; #define XM_E_NOTE_CUT 0xC #define XM_E_NOTE_DELAY 0xD #define XM_E_PATTERN_DELAY 0xE +#define XM_E_SET_MIDI_MACRO 0xF #define XM_X_EXTRAFINE_PORTA_UP 1 #define XM_X_EXTRAFINE_PORTA_DOWN 2 diff --git a/dumb/src/it/itrender.c b/dumb/src/it/itrender.c index b8d4b5e929..f1ff9721d5 100644 --- a/dumb/src/it/itrender.c +++ b/dumb/src/it/itrender.c @@ -274,6 +274,10 @@ static void dup_channel(IT_CHANNEL *dst, IT_CHANNEL *src) dst->xm_lastX1 = src->xm_lastX1; dst->xm_lastX2 = src->xm_lastX2; + dst->inv_loop_delay = src->inv_loop_delay; + dst->inv_loop_speed = src->inv_loop_speed; + dst->inv_loop_offset = src->inv_loop_offset; + dst->playing = dup_playing(src->playing, dst, src); @@ -1045,6 +1049,33 @@ static void update_smooth_effects(DUMB_IT_SIGRENDERER *sigrenderer) } +static const unsigned char pt_tab_invloop[16] = +{ + 0x00, 0x05, 0x06, 0x07, 0x08, 0x0A, 0x0B, 0x0D, + 0x0F, 0x13, 0x16, 0x1A, 0x20, 0x2B, 0x40, 0x80 +}; + +static void update_invert_loop(IT_CHANNEL *channel, IT_SAMPLE *sample) +{ + channel->inv_loop_delay += pt_tab_invloop[channel->inv_loop_speed]; + if (channel->inv_loop_delay >= 0x80) + { + channel->inv_loop_delay = 0; + + if (sample && ((sample->flags & (IT_SAMPLE_EXISTS | IT_SAMPLE_LOOP)) == (IT_SAMPLE_EXISTS | IT_SAMPLE_LOOP)) && !(sample->flags & (IT_SAMPLE_STEREO | IT_SAMPLE_16BIT))) + { + if (sample->loop_end - sample->loop_start >= 4) + { + channel->inv_loop_offset++; + if (channel->inv_loop_offset >= (sample->loop_end - sample->loop_start)) channel->inv_loop_offset = 0; + + ((char *)sample->data)[sample->loop_start + channel->inv_loop_offset] ^= 0xFF; + } + } + } +} + + static void update_effects(DUMB_IT_SIGRENDERER *sigrenderer) { @@ -1140,6 +1171,8 @@ static void update_effects(DUMB_IT_SIGRENDERER *sigrenderer) update_retrig(sigrenderer, channel); + if (channel->inv_loop_speed) update_invert_loop(channel, playing ? playing->sample : NULL); + if (playing) { playing->slide += channel->portamento; @@ -2538,7 +2571,10 @@ Yxy This uses a table 4 times larger (hence 4 times slower) than } break; case IT_S_SET_MIDI_MACRO: - channel->SFmacro = effectvalue & 15; + if ((sigdata->flags & (IT_WAS_AN_XM | IT_WAS_A_MOD)) == (IT_WAS_AN_XM | IT_WAS_A_MOD)) { + channel->inv_loop_speed = effectvalue & 15; + update_invert_loop(channel, channel->playing ? channel->playing->sample : NULL); + } else channel->SFmacro = effectvalue & 15; break; } } @@ -2937,6 +2973,7 @@ static void process_xm_note_data(DUMB_IT_SIGRENDERER *sigrenderer, IT_ENTRY *ent if (entry->mask & IT_ENTRY_INSTRUMENT) { int oldsample = channel->sample; int oldvolume = channel->volume; + channel->inv_loop_offset = 0; channel->instrument = entry->instrument; instrument_to_sample(sigdata, channel); if (channel->playing && @@ -4907,6 +4944,9 @@ static DUMB_IT_SIGRENDERER *init_sigrenderer(DUMB_IT_SIGDATA *sigdata, int n_cha channel->xm_lastEB = 0; channel->xm_lastX1 = 0; channel->xm_lastX2 = 0; + channel->inv_loop_delay = 0; + channel->inv_loop_speed = 0; + channel->inv_loop_offset = 0; channel->playing = NULL; #ifdef BIT_ARRAY_BULLSHIT channel->played_patjump = NULL; diff --git a/dumb/src/it/readasy.c b/dumb/src/it/readasy.c index 9ab5a1f32d..3cc89ab172 100644 --- a/dumb/src/it/readasy.c +++ b/dumb/src/it/readasy.c @@ -71,7 +71,7 @@ static int it_asy_read_pattern( IT_PATTERN *pattern, DUMBFILE *f, unsigned char entry->mask |= IT_ENTRY_INSTRUMENT; } - _dumb_it_xm_convert_effect( buffer[ pos + 2 ] & 0x0F, buffer[ pos + 3 ], entry, 1 ); + _dumb_it_xm_convert_effect( buffer[ pos + 2 ], buffer[ pos + 3 ], entry, 1 ); if ( entry->mask ) ++entry; } @@ -90,7 +90,7 @@ static int it_asy_read_pattern( IT_PATTERN *pattern, DUMBFILE *f, unsigned char static int it_asy_read_sample_header( IT_SAMPLE *sample, DUMBFILE *f ) { - int finetune; + int finetune, key_offset; /** 21 22 Chars Sample 1 name. If the name is not a full @@ -111,7 +111,7 @@ assumed not to be an instrument name, and is probably a message. sample->default_volume = dumbfile_getc( f ); // Should we be setting global_volume to this instead? sample->global_volume = 64; if ( sample->default_volume > 64 ) sample->default_volume = 64; - dumbfile_skip( f, 1 ); /* XXX unknown */ + key_offset = ( signed char ) dumbfile_getc( f ); /* base key offset */ sample->length = dumbfile_igetl( f ); sample->loop_start = dumbfile_igetl( f ); sample->loop_end = sample->loop_start + dumbfile_igetl( f ); @@ -124,7 +124,8 @@ assumed not to be an instrument name, and is probably a message. sample->flags = IT_SAMPLE_EXISTS; sample->default_pan = 0; - sample->C5_speed = (int)( AMIGA_CLOCK / 214.0 );//( int32 )( 16726.0 * pow( DUMB_PITCH_BASE, finetune * 32 ) ); + sample->C5_speed = (int)( AMIGA_CLOCK / 214.0 * pow( DUMB_SEMITONE_BASE, key_offset ) );//( long )( 16726.0 * pow( DUMB_PITCH_BASE, +finetune * 32 ) ); sample->finetune = finetune * 32; // the above line might be wrong diff --git a/dumb/src/it/xmeffect.c b/dumb/src/it/xmeffect.c index f0f8820ffa..1aa489222b 100644 --- a/dumb/src/it/xmeffect.c +++ b/dumb/src/it/xmeffect.c @@ -188,6 +188,7 @@ if (log) printf(" - %2d %02X", effect, value); case EBASE+XM_E_SET_PANNING: effect = SBASE+IT_S_SET_PAN; break; case EBASE+XM_E_FINE_VOLSLIDE_UP: effect = IT_XM_FINE_VOLSLIDE_UP; break; case EBASE+XM_E_FINE_VOLSLIDE_DOWN: effect = IT_XM_FINE_VOLSLIDE_DOWN; break; + case EBASE+XM_E_SET_MIDI_MACRO: effect = SBASE+IT_S_SET_MIDI_MACRO; break; case EBASE + XM_E_FINE_PORTA_UP: effect = IT_PORTAMENTO_UP;