// TIATracker music player // Copyright 2016 Andre "Kylearan" Wichmann // Website: https://bitbucket.org/kylearan/tiatracker // Email: andre.wichmann@gmx.de // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Song author: Bomb the bass / covered by Glafouk // Song name: Miniblast // @com.wudsn.ide.asm.hardware=ATARI2600 // ===================================================================== // TIATracker melodic and percussion instruments, patterns and sequencer // data. // ===================================================================== // ===================================================================== // Melodic instrument definitions (up to 7). tt_envelope_index_c0/1 hold // the index values into these tables for the current instruments played // in channel 0 and 1. // // Each instrument is defined by: // - tt_InsCtrlTable: the AUDC value // - tt_InsADIndexes: the index of the start of the ADSR envelope as // defined in tt_InsFreqVolTable // - tt_InsSustainIndexes: the index of the start of the Sustain phase // of the envelope // - tt_InsReleaseIndexes: the index of the start of the Release phase // - tt_InsFreqVolTable: The AUDF frequency and AUDV volume values of // the envelope // ===================================================================== // Instrument master CTRL values const char tt_InsCtrlTable[] = { 0x0f, 0x0c, 0x04, 0x0c, 0x06 }; // Instrument Attack/Decay start indexes into ADSR tables. const char tt_InsADIndexes[] = { 0x00, 0x0c, 0x14, 0x14, 0x1c }; // Instrument Sustain start indexes into ADSR tables const char tt_InsSustainIndexes[] = { 0x08, 0x10, 0x18, 0x18, 0x24 }; // Instrument Release start indexes into ADSR tables // Caution: Values are stored with an implicit -1 modifier! To get the // real index, add 1. const char tt_InsReleaseIndexes[] = { 0x09, 0x11, 0x19, 0x19, 0x25 }; // AUDVx and AUDFx ADSR envelope values. // Each byte encodes the frequency and volume: // - Bits 7..4: Freqency modifier for the current note ([-8..7]), // 8 means no change. Bit 7 is the sign bit. // - Bits 3..0: Volume // Between sustain and release is one byte that is not used and // can be any value. // The end of the release phase is encoded by a 0. const char tt_InsFreqVolTable[] = { // 0: Guitoune 0xf0, 0x25, 0x28, 0x2a, 0x3c, 0x2a, 0x28, 0x25, 0xf0, 0x00, 0xf0, 0x00, // 1: Chords 0x27, 0x6c, 0x8e, 0x8e, 0x82, 0x00, 0x80, 0x00, // 2+3: Chords2 0x70, 0x88, 0x7c, 0x7c, 0x70, 0x00, 0x70, 0x00, // 4: bassline 0x80, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x80, 0x00, 0x80, 0x00 }; // ===================================================================== // Percussion instrument definitions (up to 15) ; // Each percussion instrument is defined by: // - tt_PercIndexes: The index of the first percussion frame as defined // in tt_PercFreqTable and tt_PercCtrlVolTable // - tt_PercFreqTable: The AUDF frequency value // - tt_PercCtrlVolTable: The AUDV volume and AUDC values // ===================================================================== // Indexes into percussion definitions signifying the first frame for // each percussion in tt_PercFreqTable. // Caution: Values are stored with an implicit +1 modifier! To get the // real index, subtract 1. const char tt_PercIndexes[] = { 0x01, 0x05, 0x16 }; // The AUDF frequency values for the percussion instruments. // If the second to last value is negative (>=128), it means it's an // "overlay" percussion, i.e. the player fetches the next instrument note // immediately and starts it in the sustain phase next frame. (Needs // TT_USE_OVERLAY) const char tt_PercFreqTable[] = { // 0: hi 0x00, 0x04, 0x04, 0x00, // 1: Break SD 0x0a, 0x0a, 0x0b, 0x0b, 0x0c, 0x0c, 0x0d, 0x0d, 0x0e, 0x0e, 0x0f, 0x0f, 0x10, 0x10, 0x11, 0x11, 0x00, // 2: Snare 0x07, 0x0d, 0x0e, 0x10, 0x14, 0x14, 0x15, 0x18, 0x18, 0x19, 0x1a, 0x1b, 0x1e, 0x1f, 0x00 }; // The AUDCx and AUDVx volume values for the percussion instruments. // - Bits 7..4: AUDC value // - Bits 3..0: AUDV value // 0 means end of percussion data. const char tt_PercCtrlVolTable[] = { // 0: hi 0x8f, 0x8a, 0x84, 0x00, // 1: Break SD 0x8a, 0x8a, 0x89, 0x89, 0x88, 0x88, 0x88, 0x87, 0x87, 0x87, 0x86, 0x84, 0x83, 0x83, 0x81, 0x80, 0x00, // 2: Snare 0x8e, 0x8d, 0x8d, 0x8c, 0x8b, 0x8a, 0x88, 0x88, 0x87, 0x86, 0x84, 0x82, 0x81, 0x80, 0x00 }; // ===================================================================== // Track definition // The track is defined by: // - tt_PatternX (X=0, 1, ...): Pattern definitions // - tt_PatternPtrLo/Hi: Pointers to the tt_PatternX tables, serving // as index values // - tt_SequenceTable: The order in which the patterns should be played, // i.e. indexes into tt_PatternPtrLo/Hi. Contains the sequences // for all channels and sub-tracks. The variables // tt_cur_pat_index_c0/1 hold an index into tt_SequenceTable for // each channel. // // So tt_SequenceTable holds indexes into tt_PatternPtrLo/Hi, which // in turn point to pattern definitions (tt_PatternX) in which the notes // to play are specified. // ===================================================================== // --------------------------------------------------------------------- // Pattern definitions, one table per pattern. tt_cur_note_index_c0/1 // hold the index values into these tables for the current pattern // played in channel 0 and 1. // // A pattern is a sequence of notes (one byte per note) ending with a 0. // A note can be either: // - Pause: Put melodic instrument into release. Must only follow a // melodic instrument. // - Hold: Continue to play last note (or silence). Default "empty" note. // - Slide (needs TT_USE_SLIDE): Adjust frequency of last melodic note // by -7..+7 and keep playing it // - Play new note with melodic instrument // - Play new note with percussion instrument // - End of pattern // // A note is defined by: // - Bits 7..5: 1-7 means play melodic instrument 1-7 with a new note // and frequency in bits 4..0. If bits 7..5 are 0, bits 4..0 are // defined as: // - 0: End of pattern // - [1..15]: Slide -7..+7 (needs TT_USE_SLIDE) // - 8: Hold // - 16: Pause // - [17..31]: Play percussion instrument 1..15 // // The tracker must ensure that a pause only follows a melodic // instrument or a hold/slide. // --------------------------------------------------------------------- const char TT_FREQ_MASK = 0x1f; const char TT_INS_HOLD = 8; const char TT_INS_PAUSE = 16; const char TT_FIRST_PERC = 17; // mel2 const char tt_pattern0[] = { 0x27, 0x08, 0x08, 0x08, 0x08, 0x08, 0x28, 0x08, 0x27, 0x08, 0x27, 0x08, 0x08, 0x08, 0x27, 0x08, 0x08, 0x08, 0x28, 0x08, 0x27, 0x08, 0x28, 0x08, 0x27, 0x08, 0x28, 0x08, 0x27, 0x08, 0x28, 0x08, 0x27, 0x08, 0x08, 0x08, 0x08, 0x08, 0x28, 0x08, 0x27, 0x08, 0x27, 0x08, 0x08, 0x08, 0x27, 0x08, 0x08, 0x08, 0x28, 0x08, 0x27, 0x08, 0x28, 0x08, 0x27, 0x08, 0x28, 0x08, 0x27, 0x08, 0x28, 0x08, 0x00 }; // mel0 const char tt_pattern1[] = { 0x56, 0x08, 0x08, 0x08, 0x56, 0x08, 0x56, 0x08, 0x52, 0x08, 0x56, 0x08, 0x56, 0x08, 0x56, 0x08, 0x52, 0x08, 0x56, 0x08, 0x11, 0x08, 0x08, 0x08, 0x56, 0x08, 0x12, 0x08, 0x12, 0x08, 0x08, 0x08, 0x52, 0x08, 0x08, 0x08, 0x52, 0x08, 0x52, 0x08, 0x4e, 0x08, 0x52, 0x08, 0x52, 0x08, 0x52, 0x08, 0x4e, 0x08, 0x52, 0x08, 0x11, 0x08, 0x08, 0x08, 0x52, 0x08, 0x12, 0x08, 0x12, 0x08, 0x08, 0x08, 0x00 }; // mel1 const char tt_pattern2[] = { 0x58, 0x08, 0x08, 0x08, 0x58, 0x08, 0x58, 0x08, 0x53, 0x08, 0x58, 0x08, 0x58, 0x08, 0x58, 0x08, 0x53, 0x08, 0x58, 0x08, 0x11, 0x08, 0x08, 0x08, 0x58, 0x08, 0x12, 0x08, 0x12, 0x08, 0x08, 0x08, 0x56, 0x08, 0x08, 0x08, 0x56, 0x08, 0x56, 0x08, 0x52, 0x08, 0x56, 0x08, 0x56, 0x08, 0x56, 0x08, 0x52, 0x08, 0x56, 0x08, 0x11, 0x08, 0x08, 0x08, 0x56, 0x08, 0x12, 0x08, 0x12, 0x08, 0x08, 0x08, 0x00 }; // mel3 const char tt_pattern3[] = { 0x56, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x56, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x56, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x56, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x56, 0x08, 0x08, 0x08, 0x56, 0x08, 0x08, 0x08, 0x56, 0x08, 0x08, 0x08, 0x56, 0x08, 0x08, 0x08, 0x56, 0x08, 0x08, 0x08, 0x56, 0x08, 0x08, 0x08, 0x56, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00 }; // mel4 const char tt_pattern4[] = { 0x97, 0x08, 0x08, 0x08, 0x08, 0x08, 0x8f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x8b, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x11, 0x08, 0x08, 0x08, 0x08, 0x08, 0x12, 0x08, 0x12, 0x08, 0x97, 0x08, 0x97, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x8f, 0x08, 0x08, 0x08, 0x08, 0x8b, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x11, 0x08, 0x97, 0x08, 0x97, 0x08, 0x12, 0x08, 0x12, 0x08, 0x97, 0x08, 0x00 }; // mel5 const char tt_pattern5[] = { 0x27, 0x97, 0x08, 0x08, 0x08, 0x08, 0x28, 0x8f, 0x27, 0x08, 0x27, 0x08, 0x8b, 0x08, 0x27, 0x08, 0x08, 0x08, 0x28, 0x08, 0x11, 0x08, 0x28, 0x08, 0x27, 0x08, 0x28, 0x08, 0x12, 0x08, 0x28, 0x97, 0x27, 0x97, 0x08, 0x08, 0x08, 0x08, 0x28, 0x8f, 0x27, 0x08, 0x27, 0x08, 0x8b, 0x08, 0x27, 0x08, 0x08, 0x08, 0x28, 0x08, 0x27, 0x08, 0x28, 0x97, 0x12, 0x97, 0x12, 0x97, 0x27, 0x97, 0x28, 0x97, 0x00 }; // bass+drum0 const char tt_pattern6[] = { 0xb1, 0x08, 0x08, 0x08, 0x11, 0x08, 0xb1, 0x08, 0x13, 0x08, 0x08, 0x08, 0xb1, 0x08, 0x08, 0x08, 0xb1, 0x08, 0x08, 0x08, 0xb1, 0x08, 0x08, 0x08, 0x13, 0x08, 0xb1, 0x08, 0xb1, 0x08, 0x08, 0x08, 0xae, 0x08, 0x08, 0x08, 0x11, 0x08, 0xae, 0x08, 0x13, 0x08, 0x08, 0x08, 0xae, 0x08, 0x08, 0x08, 0xae, 0x08, 0x08, 0x08, 0xae, 0x08, 0x08, 0x08, 0x13, 0x08, 0xae, 0x08, 0xae, 0x08, 0x08, 0x08, 0x00 }; // bass+drum1 const char tt_pattern7[] = { 0xb3, 0x08, 0x08, 0x08, 0x11, 0x08, 0xb3, 0x08, 0x13, 0x08, 0x08, 0x08, 0xb3, 0x08, 0x08, 0x08, 0xb3, 0x08, 0x08, 0x08, 0xb3, 0x08, 0x08, 0x08, 0x13, 0x08, 0xb3, 0x08, 0xb3, 0x08, 0x08, 0x08, 0xb1, 0x08, 0x08, 0x08, 0x11, 0x08, 0xb1, 0x08, 0x13, 0x08, 0x08, 0x08, 0xb1, 0x08, 0x08, 0x08, 0xb1, 0x08, 0x08, 0x08, 0xb1, 0x08, 0x08, 0x08, 0x13, 0x08, 0xb1, 0x08, 0xb1, 0x08, 0x08, 0x08, 0x00 }; // drum0 const char tt_pattern8[] = { 0x08, 0x08, 0x08, 0x08, 0x11, 0x08, 0x08, 0x08, 0x13, 0x08, 0x08, 0x08, 0x11, 0x08, 0x08, 0x08, 0x11, 0x08, 0x11, 0x08, 0x11, 0x08, 0x08, 0x08, 0x13, 0x08, 0x12, 0x08, 0x12, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x11, 0x08, 0x08, 0x08, 0x13, 0x08, 0x08, 0x08, 0x11, 0x08, 0x08, 0x08, 0x11, 0x08, 0x11, 0x08, 0x11, 0x08, 0x11, 0x08, 0x13, 0x08, 0x12, 0x08, 0x12, 0x08, 0x11, 0x08, 0x00 }; // Individual pattern speeds (needs TT_GLOBAL_SPEED = 0). // Each byte encodes the speed of one pattern in the order // of the tt_PatternPtr tables below. // If TT_USE_FUNKTEMPO is 1, then the low nibble encodes // the even speed and the high nibble the odd speed. #if _TT_GLOBAL_SPEED == 0 const char tt_PatternSpeeds[] = { %%PATTERNSPEEDS%% }; #endif // --------------------------------------------------------------------- // Pattern pointers look-up table. // --------------------------------------------------------------------- const char tt_PatternPtrLo[] = { tt_pattern0 & 0xff, tt_pattern1 & 0xff, tt_pattern2 & 0xff, tt_pattern3 & 0xff, tt_pattern4 & 0xff, tt_pattern5 & 0xff, tt_pattern6 & 0xff, tt_pattern7 & 0xff, tt_pattern8 & 0xff }; const char tt_PatternPtrHi[] = { tt_pattern0 >> 8, tt_pattern1 >> 8, tt_pattern2 >> 8, tt_pattern3 >> 8, tt_pattern4 >> 8, tt_pattern5 >> 8, tt_pattern6 >> 8, tt_pattern7 >> 8, tt_pattern8 >> 8 }; // --------------------------------------------------------------------- // Pattern sequence table. Each byte is an index into the // tt_PatternPtrLo/Hi tables where the pointers to the pattern // definitions can be found. When a pattern has been played completely, // the next byte from this table is used to get the address of the next // pattern to play. tt_cur_pat_index_c0/1 hold the current index values // into this table for channels 0 and 1. // If TT_USE_GOTO is used, a value >=128 denotes a goto to the pattern // number encoded in bits 6..0 (i.e. value AND %01111111). // --------------------------------------------------------------------- const char tt_SequenceTable[] = { // ---------- Channel 0 ---------- 0x00, 0x00, 0x01, 0x02, 0x01, 0x02, 0x03, 0x04, 0x04, 0x05, 0x05, 0x82 , // ---------- Channel 1 ---------- 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x08, 0x06, 0x07, 0x06, 0x07, 0x8e }; char tia_tracker_init() { tt_timer = 0; tt_cur_note_index_c0 = 0; tt_cur_note_index_c1 = 0; tt_cur_pat_index_c0 = 0; tt_cur_pat_index_c1 = 12; }