1 /* 2 * ITTools.h 3 * --------- 4 * Purpose: Definition of IT file structures and helper functions 5 * Notes : (currently none) 6 * Authors: OpenMPT Devs 7 * The OpenMPT source code is released under the BSD license. Read LICENSE for more details. 8 */ 9 10 11 #pragma once 12 13 #include "openmpt/all/BuildSettings.hpp" 14 15 #include "../soundlib/ModInstrument.h" 16 #include "../soundlib/ModSample.h" 17 #include "../soundlib/SampleIO.h" 18 19 OPENMPT_NAMESPACE_BEGIN 20 21 struct ITFileHeader 22 { 23 // Header Flags 24 enum ITHeaderFlags 25 { 26 useStereoPlayback = 0x01, 27 vol0Optimisations = 0x02, 28 instrumentMode = 0x04, 29 linearSlides = 0x08, 30 itOldEffects = 0x10, 31 itCompatGxx = 0x20, 32 useMIDIPitchController = 0x40, 33 reqEmbeddedMIDIConfig = 0x80, 34 extendedFilterRange = 0x1000, 35 }; 36 37 // Special Flags 38 enum ITHeaderSpecialFlags 39 { 40 embedSongMessage = 0x01, 41 embedEditHistory = 0x02, 42 embedPatternHighlights = 0x04, 43 embedMIDIConfiguration = 0x08, 44 }; 45 46 char id[4]; // Magic Bytes (IMPM) 47 char songname[26]; // Song Name, null-terminated (but may also contain nulls) 48 uint8le highlight_minor; // Rows per Beat highlight 49 uint8le highlight_major; // Rows per Measure highlight 50 uint16le ordnum; // Number of Orders 51 uint16le insnum; // Number of Instruments 52 uint16le smpnum; // Number of Samples 53 uint16le patnum; // Number of Patterns 54 uint16le cwtv; // "Made With" Tracker 55 uint16le cmwt; // "Compatible With" Tracker 56 uint16le flags; // Header Flags 57 uint16le special; // Special Flags, for embedding extra information 58 uint8le globalvol; // Global Volume (0...128) 59 uint8le mv; // Master Volume (0...128), referred to as Sample Volume in OpenMPT 60 uint8le speed; // Initial Speed (1...255) 61 uint8le tempo; // Initial Tempo (31...255) 62 uint8le sep; // Pan Separation (0...128) 63 uint8le pwd; // Pitch Wheel Depth 64 uint16le msglength; // Length of Song Message 65 uint32le msgoffset; // Offset of Song Message in File (IT crops message after first null) 66 uint32le reserved; // Some IT versions save an edit timer here. ChibiTracker writes "CHBI" here. OpenMPT and Schism Tracker save extended version information here. 67 uint8le chnpan[64]; // Initial Channel Panning 68 uint8le chnvol[64]; // Initial Channel Volume 69 }; 70 71 MPT_BINARY_STRUCT(ITFileHeader, 192) 72 73 74 struct ITEnvelope 75 { 76 // Envelope Flags 77 enum ITEnvelopeFlags 78 { 79 envEnabled = 0x01, 80 envLoop = 0x02, 81 envSustain = 0x04, 82 envCarry = 0x08, 83 envFilter = 0x80, 84 }; 85 86 struct Node 87 { 88 int8le value; 89 uint16le tick; 90 }; 91 92 uint8 flags; // Envelope Flags 93 uint8 num; // Number of Envelope Nodes 94 uint8 lpb; // Loop Start 95 uint8 lpe; // Loop End 96 uint8 slb; // Sustain Start 97 uint8 sle; // Sustain End 98 Node data[25]; // Envelope Node Positions / Values 99 uint8 reserved; // Reserved 100 101 // Convert OpenMPT's internal envelope format to an IT/MPTM envelope. 102 void ConvertToIT(const InstrumentEnvelope &mptEnv, uint8 envOffset, uint8 envDefault); 103 // Convert IT/MPTM envelope data into OpenMPT's internal envelope format - To be used by ITInstrToMPT() 104 void ConvertToMPT(InstrumentEnvelope &mptEnv, uint8 envOffset, uint8 maxNodes) const; 105 }; 106 107 MPT_BINARY_STRUCT(ITEnvelope::Node, 3) 108 MPT_BINARY_STRUCT(ITEnvelope, 82) 109 110 111 // Old Impulse Instrument Format (cmwt < 0x200) 112 struct ITOldInstrument 113 { 114 enum ITOldInstrFlags 115 { 116 envEnabled = 0x01, 117 envLoop = 0x02, 118 envSustain = 0x04, 119 }; 120 121 char id[4]; // Magic Bytes (IMPI) 122 char filename[13]; // DOS Filename, null-terminated 123 uint8le flags; // Volume Envelope Flags 124 uint8le vls; // Envelope Loop Start 125 uint8le vle; // Envelope Loop End 126 uint8le sls; // Envelope Sustain Start 127 uint8le sle; // Envelope Sustain End 128 char reserved1[2]; // Reserved 129 uint16le fadeout; // Instrument Fadeout (0...128) 130 uint8le nna; // New Note Action 131 uint8le dnc; // Duplicate Note Check Type 132 uint16le trkvers; // Tracker ID 133 uint8le nos; // Number of embedded samples 134 char reserved2; // Reserved 135 char name[26]; // Instrument Name, null-terminated (but may also contain nulls) 136 char reserved3[6]; // Even more reserved bytes 137 uint8le keyboard[240]; // Sample / Transpose map 138 uint8le volenv[200]; // This appears to be a pre-computed (interpolated) version of the volume envelope data found below. 139 uint8le nodes[25 * 2]; // Volume Envelope Node Positions / Values 140 141 // Convert an ITOldInstrument to OpenMPT's internal instrument representation. 142 void ConvertToMPT(ModInstrument &mptIns) const; 143 }; 144 145 MPT_BINARY_STRUCT(ITOldInstrument, 554) 146 147 148 // Impulse Instrument Format 149 struct ITInstrument 150 { 151 enum ITInstrumentFlags 152 { 153 ignorePanning = 0x80, 154 enableCutoff = 0x80, 155 enableResonance = 0x80, 156 }; 157 158 char id[4]; // Magic Bytes (IMPI) 159 char filename[13]; // DOS Filename, null-terminated 160 uint8le nna; // New Note Action 161 uint8le dct; // Duplicate Note Check Type 162 uint8le dca; // Duplicate Note Check Action 163 uint16le fadeout; // Instrument Fadeout (0...256, although values up to 1024 would be sensible. Up to IT2.07, the limit was 0...128) 164 int8le pps; // Pitch/Pan Separatation 165 uint8le ppc; // Pitch/Pan Centre 166 uint8le gbv; // Global Volume 167 uint8le dfp; // Panning 168 uint8le rv; // Vol Swing 169 uint8le rp; // Pan Swing 170 uint16le trkvers; // Tracker ID 171 uint8le nos; // Number of embedded samples 172 char reserved1; // Reserved 173 char name[26]; // Instrument Name, null-terminated (but may also contain nulls) 174 uint8le ifc; // Filter Cutoff 175 uint8le ifr; // Filter Resonance 176 uint8le mch; // MIDI Channel 177 uint8le mpr; // MIDI Program 178 uint8le mbank[2]; // MIDI Bank 179 uint8le keyboard[240]; // Sample / Transpose map 180 ITEnvelope volenv; // Volume Envelope 181 ITEnvelope panenv; // Pan Envelope 182 ITEnvelope pitchenv; // Pitch / Filter Envelope 183 char dummy[4]; // IT saves some additional padding bytes to match the size of the old instrument format for simplified loading. We use them for some hacks. 184 185 // Convert OpenMPT's internal instrument representation to an ITInstrument. Returns amount of bytes that need to be written. 186 uint32 ConvertToIT(const ModInstrument &mptIns, bool compatExport, const CSoundFile &sndFile); 187 // Convert an ITInstrument to OpenMPT's internal instrument representation. Returns size of the instrument data that has been read. 188 uint32 ConvertToMPT(ModInstrument &mptIns, MODTYPE fromType) const; 189 }; 190 191 MPT_BINARY_STRUCT(ITInstrument, 554) 192 193 194 // MPT IT Instrument Extension 195 struct ITInstrumentEx 196 { 197 ITInstrument iti; // Normal IT Instrument 198 uint8 keyboardhi[120]; // High Byte of Sample map 199 200 // Convert OpenMPT's internal instrument representation to an ITInstrumentEx. Returns amount of bytes that need to be written. 201 uint32 ConvertToIT(const ModInstrument &mptIns, bool compatExport, const CSoundFile &sndFile); 202 // Convert an ITInstrumentEx to OpenMPT's internal instrument representation. Returns size of the instrument data that has been read. 203 uint32 ConvertToMPT(ModInstrument &mptIns, MODTYPE fromType) const; 204 }; 205 206 MPT_BINARY_STRUCT(ITInstrumentEx, sizeof(ITInstrument) + 120) 207 208 209 // IT Sample Format 210 struct ITSample 211 { 212 // Magic Bytes 213 enum Magic 214 { 215 magic = 0x53504D49, // "IMPS" IT Sample Header Magic Bytes 216 }; 217 218 enum ITSampleFlags 219 { 220 sampleDataPresent = 0x01, 221 sample16Bit = 0x02, 222 sampleStereo = 0x04, 223 sampleCompressed = 0x08, 224 sampleLoop = 0x10, 225 sampleSustain = 0x20, 226 sampleBidiLoop = 0x40, 227 sampleBidiSustain = 0x80, 228 229 enablePanning = 0x80, 230 231 cvtSignedSample = 0x01, 232 cvtOPLInstrument = 0x40, // FM instrument in MPTM 233 cvtExternalSample = 0x80, // Keep MPTM sample on disk 234 cvtADPCMSample = 0xFF, // MODPlugin :( 235 236 // ITTECH.TXT says these convert flags are "safe to ignore". IT doesn't ignore them, though, so why should we? :) 237 cvtBigEndian = 0x02, 238 cvtDelta = 0x04, 239 cvtPTM8to16 = 0x08, 240 }; 241 242 char id[4]; // Magic Bytes (IMPS) 243 char filename[13]; // DOS Filename, null-terminated 244 uint8le gvl; // Global Volume 245 uint8le flags; // Sample Flags 246 uint8le vol; // Default Volume 247 char name[26]; // Sample Name, null-terminated (but may also contain nulls) 248 uint8le cvt; // Sample Import Format 249 uint8le dfp; // Sample Panning 250 uint32le length; // Sample Length (in samples) 251 uint32le loopbegin; // Sample Loop Begin (in samples) 252 uint32le loopend; // Sample Loop End (in samples) 253 uint32le C5Speed; // C-5 frequency 254 uint32le susloopbegin; // Sample Sustain Begin (in samples) 255 uint32le susloopend; // Sample Sustain End (in samples) 256 uint32le samplepointer; // Pointer to sample data 257 uint8le vis; // Auto-Vibrato Rate (called Sweep in IT) 258 uint8le vid; // Auto-Vibrato Depth 259 uint8le vir; // Auto-Vibrato Sweep (called Rate in IT) 260 uint8le vit; // Auto-Vibrato Type 261 262 // Convert OpenMPT's internal sample representation to an ITSample. 263 void ConvertToIT(const ModSample &mptSmp, MODTYPE fromType, bool compress, bool compressIT215, bool allowExternal); 264 // Convert an ITSample to OpenMPT's internal sample representation. 265 uint32 ConvertToMPT(ModSample &mptSmp) const; 266 // Retrieve the internal sample format flags for this instrument. 267 SampleIO GetSampleFormat(uint16 cwtv = 0x214) const; 268 }; 269 270 MPT_BINARY_STRUCT(ITSample, 80) 271 272 273 struct FileHistory; 274 275 // IT Header extension: Save history 276 struct ITHistoryStruct 277 { 278 uint16le fatdate; // DOS / FAT date when the file was opened / created in the editor. For details, read https://docs.microsoft.com/de-de/windows/win32/api/winbase/nf-winbase-dosdatetimetofiletime 279 uint16le fattime; // DOS / FAT time when the file was opened / created in the editor. 280 uint32le runtime; // The time how long the file was open in the editor, in 1/18.2th seconds. (= ticks of the DOS timer) 281 282 // Convert an ITHistoryStruct to OpenMPT's internal edit history representation 283 void ConvertToMPT(FileHistory &mptHistory) const; 284 // Convert OpenMPT's internal edit history representation to an ITHistoryStruct 285 void ConvertToIT(const FileHistory &mptHistory); 286 287 }; 288 289 MPT_BINARY_STRUCT(ITHistoryStruct, 8) 290 291 292 enum IT_ReaderBitMasks 293 { 294 // pattern row parsing, the channel data is read to obtain 295 // number of channels active in the pattern. These bit masks are 296 // to blank out sections of the byte of data being read. 297 298 IT_bitmask_patternChanField_c = 0x7f, 299 IT_bitmask_patternChanMask_c = 0x3f, 300 IT_bitmask_patternChanEnabled_c = 0x80, 301 IT_bitmask_patternChanUsed_c = 0x0f 302 }; 303 304 305 // Calculate Schism Tracker version field for IT / S3M header based on specified release date 306 // Date calculation derived from https://alcor.concordia.ca/~gpkatch/gdate-algorithm.html 307 template<int32 y, int32 m, int32 d> 308 struct SchismVersionFromDate 309 { 310 private: 311 static constexpr int32 mm = (m + 9) % 12; 312 static constexpr int32 yy = y - mm / 10; 313 314 public: 315 static constexpr int32 date = yy * 365 + yy / 4 - yy / 100 + yy / 400 + (mm * 306 + 5) / 10 + (d - 1); 316 }; 317 318 inline constexpr int32 SchismTrackerEpoch = SchismVersionFromDate<2009, 10, 31>::date; 319 320 321 uint32 DecodeITEditTimer(uint16 cwtv, uint32 editTime); 322 323 OPENMPT_NAMESPACE_END 324