summaryrefslogtreecommitdiff
path: root/modules/chibi/cp_loader_xm.cpp
diff options
context:
space:
mode:
authorRémi Verschelde <rverschelde@gmail.com>2016-10-14 19:14:40 +0200
committerRémi Verschelde <rverschelde@gmail.com>2016-10-15 12:20:53 +0200
commite6dc51a0f764dcd7cd07482c022c1e92e6a4da3d (patch)
tree4562ecd03b4d438cae0b179968f091130dadc14d /modules/chibi/cp_loader_xm.cpp
parentcbf52606f4928df46fc89d37d781bad782f0616e (diff)
chibi: Move to a module
Diffstat (limited to 'modules/chibi/cp_loader_xm.cpp')
-rw-r--r--modules/chibi/cp_loader_xm.cpp752
1 files changed, 752 insertions, 0 deletions
diff --git a/modules/chibi/cp_loader_xm.cpp b/modules/chibi/cp_loader_xm.cpp
new file mode 100644
index 0000000000..bff8615a32
--- /dev/null
+++ b/modules/chibi/cp_loader_xm.cpp
@@ -0,0 +1,752 @@
+/*************************************************************************/
+/* cp_loader_xm.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* */
+/* 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 "cp_loader_xm.h"
+#include "cp_tables.h"
+
+#define ABORT_LOAD { file->close(); return FILE_CORRUPTED; }
+
+
+
+
+CPLoader::Error CPLoader_XM::load_song(const char *p_file,CPSong *p_song,bool p_sampleset) {
+
+ song=p_song;
+
+ if (file->open(p_file,CPFileAccessWrapper::READ)) {
+
+ return FILE_CANNOT_OPEN;
+ };
+
+
+ /**************************************
+ LOAD HEADER
+ ***************************************/
+
+ file->get_byte_array(header.idtext,17);
+ header.idtext[17]=0;
+
+ file->get_byte_array(header.songname,20);
+
+
+
+ header.songname[20]=0;
+ header.hex1a=file->get_byte();
+ if (header.hex1a!=0x1A) { //XM "magic" byte.. this sucks :)
+
+ file->close();
+ return FILE_UNRECOGNIZED;
+
+ }
+
+
+ //magic byte sucks, but can't do much about it..
+
+ song->reset(); //must reset the song
+
+ song->set_name( (const char*)header.songname );
+
+ file->get_byte_array(header.trackername,20);
+ header.trackername[20]=0;
+
+
+ header.version=file->get_word();
+
+ header.headersize=file->get_dword();
+
+ header.songlength=file->get_word();
+
+ header.restart_pos=file->get_word();
+
+ header.channels_used=file->get_word();
+
+ header.patterns_used=file->get_word();
+
+ header.instruments_used=file->get_word();
+
+ song->set_linear_slides( file->get_word() );
+
+ song->set_speed( file->get_word() );
+
+ song->set_tempo( file->get_word() );
+ song->set_instruments( true );
+
+ file->get_byte_array(header.orderlist,256);
+
+ for (int i=0;i<header.songlength;i++) {
+
+ if (i>199)
+ break;
+ song->set_order(i,header.orderlist[i]);
+ }
+
+ /**************************************
+ LOAD PATTERNS
+ ***************************************/
+
+ for (int i=0;i<header.patterns_used;i++) {
+
+ uint32_t aux,rows;
+
+ aux=file->get_dword(); //length
+ aux=file->get_byte(); //packing type
+ rows=aux=file->get_word(); //rows!
+
+ song->get_pattern(i)->set_length( aux );
+
+ aux=file->get_word(); //packed size
+ if (aux==0)
+ continue;
+ //unpaaack!
+ for(int j=0;j<(int)rows;j++)
+ for(int k=0;k<header.channels_used;k++) {
+
+ CPNote aux_note;
+ uint8_t aux_byte;
+ //uint8_t field;
+ aux_byte=file->get_byte(); //packing type
+ if (!(aux_byte&0x80)) {
+
+ aux_note.note=aux_byte;
+ aux_byte=0xFE; //if bit 7 not set, read all of them except the note
+ }
+
+ if (aux_byte&1) aux_note.note=file->get_byte();
+ if (aux_byte&2) aux_note.instrument=file->get_byte();
+ if (aux_byte&4) aux_note.volume=file->get_byte();
+ if (aux_byte&8) aux_note.command=file->get_byte();
+ if (aux_byte&16) aux_note.parameter=file->get_byte();
+
+ if (aux_note.note!=CPNote::EMPTY) {
+
+ if (aux_note.note==97) aux_note.note=CPNote::OFF;
+ else {
+ aux_note.note+=11; //octave minus one (XM C-0 is 1, not zero )
+ }
+ }
+ if (aux_note.instrument!=CPNote::EMPTY) {
+
+ if ((aux_note.instrument>0) && (aux_note.instrument<100))
+ aux_note.instrument--;
+ else
+ aux_note.instrument=CPNote::EMPTY;
+ }
+ if (aux_note.volume!=CPNote::EMPTY) {
+
+ if (aux_note.volume<0x10) {}
+ else if (aux_note.volume<0x50) {
+
+ aux_note.volume-=0x10;
+
+ } else if (aux_note.volume<0x60) {
+ //
+ aux_note.volume=CPNote::EMPTY;
+
+ } else if (aux_note.volume<0x70) {
+ //60 -- volume slide down
+ aux_note.volume-=0x60;
+ if (aux_note.volume>9) aux_note.volume=9;
+ aux_note.volume+=95;
+
+ } else if (aux_note.volume<0x80) {
+ //70 -- volume slide up
+ aux_note.volume-=0x70;
+ if (aux_note.volume>9) aux_note.volume=9;
+ aux_note.volume+=85;
+
+
+ } else if (aux_note.volume<0x90) {
+ //80 -- fine volume slide down
+ aux_note.volume-=0x80;
+ if (aux_note.volume>9) aux_note.volume=9;
+ aux_note.volume+=75;
+
+
+ } else if (aux_note.volume<0xA0) {
+ //9 -- fine volume slide up
+
+ aux_note.volume-=0x90;
+ if (aux_note.volume>9) aux_note.volume=9;
+
+ aux_note.volume+=65;
+
+
+
+ } else if (aux_note.volume<0xB0) {
+ //A -- set vibrato speed
+ aux_note.volume=CPNote::EMPTY;
+
+ } else if (aux_note.volume<0xC0) {
+ //B -- vibrato
+ aux_note.volume-=0xB0;
+ if (aux_note.volume>9) aux_note.volume=9;
+ aux_note.volume+=203;
+
+
+ } else if (aux_note.volume<0xD0) {
+ //C -- set panning
+ int aux=aux_note.volume-=0xC0;
+ aux=aux*65/0xF;
+ aux_note.volume=128+aux;
+
+ } else if (aux_note.volume<0xE0) {
+ aux_note.volume=CPNote::EMPTY;
+
+
+ } else if (aux_note.volume<0xF0) {
+ aux_note.volume=CPNote::EMPTY;
+
+
+ } else {
+ //F -- tone porta
+ aux_note.volume-=0xF0;
+ aux_note.volume*=9;
+ aux_note.volume/=0xF;
+ aux_note.volume+=193;
+ }
+ }
+ if (aux_note.command!=CPNote::EMPTY) {
+
+ switch(aux_note.command) {
+
+ case 0x0:
+ aux_note.command='J'-'A';
+ break;
+ case 0x1:
+ aux_note.command='F'-'A';
+ break;
+ case 0x2:
+ aux_note.command='E'-'A';
+ break;
+ case 0x3:
+ aux_note.command='G'-'A';
+ break;
+ case 0x4:
+ aux_note.command='H'-'A';
+ break;
+ case 0x5:
+ aux_note.command='L'-'A';
+ break;
+ case 0x6:
+ aux_note.command='K'-'A';
+ break;
+ case 0x7:
+ aux_note.command='R'-'A';
+ break;
+ case 0x8:
+ aux_note.command='X'-'A';
+ break;
+ case 0x9:
+ aux_note.command='O'-'A';
+ break;
+ case 0xa:
+ aux_note.command='D'-'A';
+ break;
+ case 0xb:
+ aux_note.command='B'-'A';
+ break;
+ case 0xc:
+ //printf("XM Import: Warning! effect C (set volume) not implemented!\n");
+ break;
+ case 0xd:
+ aux_note.command='C'-'A';
+ break;
+
+ case 0xe: /* Extended effects */
+
+ aux_note.command='S'-'A';
+ switch(aux_note.parameter>>4) {
+ case 0x1: /* XM fine porta up */
+ if (!(aux_note.parameter&0xF)) { aux_note.command=CPNote::EMPTY; aux_note.parameter=0; break; }
+ aux_note.command='F'-'A';
+ aux_note.parameter=0xF0|(aux_note.parameter&0xF);
+ break;
+ case 0x2: /* XM fine porta down */
+ if (!(aux_note.parameter&0xF)) { aux_note.command=CPNote::EMPTY; aux_note.parameter=0; break; }
+ aux_note.command='E'-'A';
+ aux_note.parameter=0xF0|(aux_note.parameter&0xF);
+ break;
+ case 0xa: /* XM fine volume up */
+ if (!(aux_note.parameter&0xF)) { aux_note.command=CPNote::EMPTY; aux_note.parameter=0; break; }
+ aux_note.command='D'-'A';
+ aux_note.parameter=0x0F|((aux_note.parameter&0xF)<<4);
+
+ break;
+ case 0xb: /* XM fine volume down */
+ if (!(aux_note.parameter&0xF)) { aux_note.command=CPNote::EMPTY; aux_note.parameter=0; break; }
+ aux_note.command='D'-'A';
+ aux_note.parameter=0xF0|(aux_note.parameter&0xF);
+
+ break;
+ case 0x9: /* XM fine volume down */
+ if (!(aux_note.parameter&0xF)) { aux_note.command=CPNote::EMPTY; aux_note.parameter=0; break; }
+ aux_note.command='Q'-'A';
+ aux_note.parameter=0x00|(aux_note.parameter&0xF);
+ break;
+
+ case 0xc: //notecut
+
+ aux_note.parameter=0xC0|(aux_note.parameter&0xF);
+ break;
+
+ case 0xd: //notedelay
+
+ aux_note.parameter=0xD0|(aux_note.parameter&0xF);
+ break;
+
+ case 0xe: //patterndelay
+
+ aux_note.parameter=0xE0|(aux_note.parameter&0xF);
+ break;
+ }
+
+ break;
+ case 0xf:
+ if (aux_note.parameter<32) {
+ aux_note.command='A'-'A';
+ } else {
+ aux_note.command='T'-'A';
+ }
+ break;
+ case 'G'-55:
+ aux_note.command='V'-'A';
+ break;
+ case 'H'-55:
+ aux_note.command='W'-'A';
+ break;
+ case 'K'-55:
+ if (aux_note.note!=CPNote::EMPTY) break;
+ aux_note.note=CPNote::OFF;
+ break;
+ case 'P'-55:
+ aux_note.command='P'-'A';
+ break;
+ case 'R'-55:
+ aux_note.command='Q'-'A';
+ break;
+ case 'T'-55:
+ aux_note.command='I'-'A';
+ break;
+ default: {
+
+ aux_note.command=CPNote::EMPTY;
+ }
+ }
+
+
+ }
+
+ song->get_pattern( i)->set_note( k,j,aux_note );
+ }
+ }
+
+ /**************************************
+ LOAD INSTRUMENTS!
+ ***************************************/
+
+ for (int i=0;i<header.instruments_used;i++) {
+
+
+ uint32_t aux;
+ int sampnum;
+
+ CPInstrument &instrument=*song->get_instrument(i);
+ uint32_t cpos=file->get_pos();
+ //printf("pos is %i\n",cpos);
+
+
+
+/* +4 */ uint32_t hsize=file->get_dword(); //header length
+
+ char instrname[23];
+ instrname[22]=0;
+
+ file->get_byte_array((uint8_t*)instrname,22);
+//XM_LOAD_DEBUG printf("name is %s\n",instrname);
+
+/* +27 */ aux=file->get_byte(); //byte that must be ignored
+//XM_LOAD_DEBUG printf("header size is %i\n",hsize);
+
+/* +29 */ sampnum=file->get_word();
+
+//XM_LOAD_DEBUG printf("samples %i\n",sampnum);
+
+
+ instrument.set_name( instrname );
+// printf("Header Len: %i, CPInstrument %i, %i samples , name: s,\n",hsize,i,sampnum,instrname);
+
+ if (sampnum==0) {
+ //aux=file->get_dword(); //Why is this for? -- for nothing, skipped
+ if (hsize) {
+
+ file->seek( cpos+hsize ); //skip header if size has been specified
+ }
+ continue;
+ }
+
+/* +33 */ file->get_dword();
+
+ if (Error result=load_instrument_internal(&instrument,false,cpos,hsize,sampnum)) {
+
+ CP_PRINTERR("Error loading instrument");
+ file->close();
+ return result;
+ }
+
+ }
+//
+ file->close();
+ return FILE_OK;
+}
+
+CPLoader::Error CPLoader_XM::load_instrument_internal(CPInstrument *p_instr,bool p_xi,int p_cpos, int p_hsize, int p_sampnum) {
+
+ int sampnum;
+ uint32_t aux;
+ uint8_t notenumb[96];
+ uint16_t panenv[24],volenv[24];
+ int volpoints,panpoints;
+ int vol_loop_begin,vol_loop_end,vol_sustain_loop;
+ int pan_loop_begin,pan_loop_end,pan_sustain_loop;
+ char instrname[23];
+ int sample_index[16]={-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1}; //-1 means no index!
+
+ instrname[22]=0;
+
+
+/* +129 */ file->get_byte_array((uint8_t*)notenumb,96);
+ for (int j=0;j<24;j++) {
+ volenv[j]=file->get_word();
+ }
+ for (int j=0;j<24;j++) {
+ panenv[j]=file->get_word();
+ }
+
+/* +177 */
+/* +225 */
+/* +226 */ volpoints=file->get_byte();
+/* +227 */ panpoints=file->get_byte();
+/* +230 */ vol_sustain_loop=file->get_byte();
+/* +228 */ vol_loop_begin=file->get_byte();
+/* +229 */ vol_loop_end=file->get_byte();
+
+//XM_LOAD_DEBUG printf("1- volpoints: %i, panpoints: %i, susloop: %i, loop begin: %i, loop end %i\n",volpoints,panpoints,vol_sustain_loop,vol_loop_begin,vol_loop_end);
+ pan_sustain_loop=file->get_byte();
+/* +231 */ pan_loop_begin=file->get_byte();
+/* +232 */ pan_loop_end=file->get_byte();
+
+
+
+/* +234 */ aux=file->get_byte();
+ p_instr->get_volume_envelope()->reset();
+ p_instr->get_volume_envelope()->set_enabled(aux&1);
+ p_instr->get_volume_envelope()->set_sustain_loop_enabled((aux&2)?true:false);
+ p_instr->get_volume_envelope()->set_loop_enabled((aux&4)?true:false);
+/* +235 */ aux=file->get_byte();
+ p_instr->get_pan_envelope()->reset();
+ p_instr->get_pan_envelope()->set_enabled(aux&1);
+ p_instr->get_pan_envelope()->set_sustain_loop_enabled((aux&2)?true:false);
+ p_instr->get_pan_envelope()->set_loop_enabled((aux&4)?true:false);
+
+/* +239 */ aux=file->get_dword(); // sadly, cant use those
+/* +241 */ p_instr->set_volume_fadeout( file->get_word() >> 4 );
+/* +243 */ aux=file->get_word(); // reserved!
+
+
+
+ for (int j=0;j<volpoints;j++) {
+ int ofs=volenv[j*2];
+ int val=volenv[j*2+1];
+ p_instr->get_volume_envelope()->add_position(ofs,val);
+
+ }
+
+ //make sure minimum is 2
+ while (p_instr->get_volume_envelope()->get_node_count()<2) {
+
+ p_instr->get_volume_envelope()->add_position( p_instr->get_volume_envelope()->get_node_count()*20,64 );
+ }
+
+ for (int j=0;j<panpoints;j++) {
+ int ofs=panenv[j*2];
+ int val=panenv[j*2+1];
+ p_instr->get_pan_envelope()->add_position(ofs,val-32);
+ }
+
+ //make sure minimum is 2
+ while (p_instr->get_pan_envelope()->get_node_count()<2) {
+
+ p_instr->get_pan_envelope()->add_position( p_instr->get_pan_envelope()->get_node_count()*20,0 );
+ }
+
+
+ p_instr->get_volume_envelope()->set_loop_begin(vol_loop_begin);
+ p_instr->get_volume_envelope()->set_loop_end(vol_loop_end);
+ p_instr->get_volume_envelope()->set_sustain_loop_end(vol_sustain_loop);
+ p_instr->get_volume_envelope()->set_sustain_loop_begin(vol_sustain_loop);
+ p_instr->get_pan_envelope()->set_loop_begin(pan_loop_begin);
+ p_instr->get_pan_envelope()->set_loop_end(pan_loop_end);
+ p_instr->get_pan_envelope()->set_sustain_loop_end(pan_sustain_loop);
+ p_instr->get_pan_envelope()->set_sustain_loop_begin(pan_sustain_loop);
+
+
+ if (!p_xi) {
+
+ if ((file->get_pos()-p_cpos)<p_hsize) {
+
+ uint8_t junkbuster[500];
+
+ //printf("extra junk XM instrument in header! hsize is %i, extra junk: %i\n",p_hsize,(file->get_pos()-p_cpos));
+ //printf("extra: %i\n",p_hsize-(file->get_pos()-p_cpos));
+ file->get_byte_array((uint8_t*)junkbuster,p_hsize-(file->get_pos()-p_cpos));
+ }
+
+ sampnum=p_sampnum;
+ } else {
+
+ uint8_t junkbuster[500];
+ file->get_byte_array((uint8_t*)junkbuster,20); //14 bytes?
+
+ sampnum=file->get_word();
+
+ }
+
+
+ CPSampleManager *sm=CPSampleManager::get_singleton();
+
+ /*SAMPLE!!*/
+
+ for (int j=0;j<sampnum;j++) {
+
+ if (j>16) ABORT_LOAD;
+
+
+ int s_idx=-1;
+ for (int s=0;s<CPSong::MAX_SAMPLES;s++) {
+
+ if (song->get_sample(s)->get_sample_data().is_null()) {
+ //empty sample!
+ s_idx=s;
+ break;
+ }
+ }
+
+ if (s_idx==-1) ABORT_LOAD;
+ //printf("free sample: %i\n",s_idx);
+
+
+ CPSample& sample=*song->get_sample(s_idx);
+
+ int sample_size=file->get_dword();
+ int tmp_loop_begin=file->get_dword();
+
+ int tmp_loop_end=file->get_dword();
+
+ sample.set_default_volume(file->get_byte());
+
+ uint8_t ftb=file->get_byte();
+ int8_t *fts=(int8_t*)&ftb;
+ int finetune=*fts;
+ uint32_t flags=file->get_byte();
+
+ if (flags&16) { // is 16 bits.. at flag 16.. fun :)
+
+ tmp_loop_end/=2;
+ tmp_loop_begin/=2;
+ sample_size/=2;
+ }
+
+
+ CPSample_ID sample_data=sm->create( flags&16, false, sample_size );
+
+ sample.set_sample_data(sample_data);
+ sm->set_loop_begin(sample_data,tmp_loop_begin);
+ sm->set_loop_end(sample_data,tmp_loop_end+tmp_loop_begin);
+
+ sm->set_loop_type( sample_data, (flags&3)?( (flags&2) ? CP_LOOP_BIDI : CP_LOOP_FORWARD ):CP_LOOP_NONE );
+
+
+
+ sample.set_pan_enabled(true);
+ sample.set_pan(file->get_byte()*64/255);
+ uint8_t noteb=file->get_byte();
+ int8_t *notes=(int8_t*)&noteb;
+ int note_offset=*notes;
+ note_offset+=48;
+ //note_offset+=60;
+
+
+
+ //int linear_period=10*12*16*4 - (note_offset)*16*4 - finetune/2;
+ //int freq=(int)(8363*pow(2.0,(double)(6*12*16*4 - linear_period) / (double)(12*16*4)));
+
+ //sm->set_c5_freq( sample_data, freq);
+ sm->set_c5_freq( sample_data, CPTables::get_linear_frequency(CPTables::get_linear_period(note_offset<<1,finetune)) );
+ //printf("NOTE %i,fine %i\n",note_offset,finetune);
+
+ char auxb;
+ auxb=file->get_byte(); //reserved?
+ file->get_byte_array((uint8_t*)instrname,22);
+ sample.set_name(instrname);
+
+ sample_index[j]=s_idx;
+ }
+
+ /*SAMPLE __DATA__!!*/
+
+ for (int j=0;j<sampnum;j++) {
+
+ if (sample_index[j]==-1) continue;
+
+ CPSample *sample=song->get_sample(sample_index[j]);
+ CPSample_ID sid=sample->get_sample_data();
+
+ sm->lock_data(sid);
+
+ void*dataptr=sm->get_data(sid);
+
+ if (sm->is_16bits( sid)) {
+
+ int16_t old=0;
+
+
+ for (int k=0;k<sm->get_size(sid);k++) {
+
+ int16_t newsample;
+ int16_t sampleval=file->get_word();
+ newsample=sampleval+old;
+ old=newsample;
+
+ ((int16_t*)dataptr)[k]=newsample;
+ //sm->set_data( sid, k, newsample );
+ }
+ } else {
+
+ int8_t old=0;
+
+
+ for (int k=0;k<sm->get_size(sid);k++) {
+
+ int8_t newsample;
+ int8_t sampleval=file->get_byte();
+ newsample=sampleval+old;
+ old=newsample;
+
+ ((int8_t*)dataptr)[k]=newsample;
+
+ //sm->set_data( sid, k, (int16_t)newsample << 8 );
+
+ }
+ }
+
+ sm->unlock_data(sid);
+
+ }
+
+ for (int j=0;j<96;j++) {
+
+ int val=notenumb[j];
+ if ((val<0) || (val>15)) continue;
+ else val=sample_index[val];
+ if (val==-1) continue;
+ p_instr->set_sample_number( 12+j,val );
+ }
+
+
+ return FILE_OK;
+}
+
+
+
+CPLoader::Error CPLoader_XM::load_sample(const char *p_file,CPSample *p_sample) {
+
+ return FILE_UNRECOGNIZED;
+}
+
+
+/* Compute CPInstrument Info */
+CPLoader::Error CPLoader_XM::load_instrument(const char *p_file,CPSong *p_song,int p_instr_idx) {
+
+ if ( file->open(p_file,CPFileAccessWrapper::READ) ) return FILE_CANNOT_OPEN;
+ //int i;
+ song=p_song;
+ CPInstrument& instr=*p_song->get_instrument( p_instr_idx );
+ int aux;
+
+
+ char buffer[500];
+ file->get_byte_array((uint8_t*)buffer,0x15);
+ buffer[8]=0;
+ if ( buffer[0]!='E' ||
+ buffer[1]!='x' ||
+ buffer[2]!='t' ||
+ buffer[3]!='e' ||
+ buffer[4]!='n' ||
+ buffer[5]!='d' ||
+ buffer[6]!='e' ||
+ buffer[7]!='d') {
+ file->close();
+ return FILE_UNRECOGNIZED;
+ }
+
+ file->get_byte_array((uint8_t*)buffer,0x16);
+ buffer[0x16]=0;
+ instr.set_name(buffer);
+ aux=file->get_byte(); //says ignore ti
+ /*if(aux!=0x1a) { I'm not sure. this is supposed to be ignored...
+
+ file->close();
+ return FILE_UNRECOGNIZED;
+ } */
+
+ file->get_byte_array((uint8_t*)buffer,0x14); //somethingaboutthename
+ aux=file->get_word(); //version or blahblah
+
+ if (load_instrument_internal(&instr,true,0,0)) {
+
+ file->close();
+ return FILE_CORRUPTED;
+ }
+
+ file->close(); //ook, we got it..
+
+
+ return FILE_OK;
+
+}
+
+
+
+CPLoader_XM::CPLoader_XM(CPFileAccessWrapper *p_file){
+
+ file=p_file;
+}
+CPLoader_XM::~CPLoader_XM(){
+}
+