cp_loader_xm.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726
  1. /*************************************************************************/
  2. /* cp_loader_xm.cpp */
  3. /*************************************************************************/
  4. /* This file is part of: */
  5. /* GODOT ENGINE */
  6. /* https://godotengine.org */
  7. /*************************************************************************/
  8. /* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
  9. /* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
  10. /* */
  11. /* Permission is hereby granted, free of charge, to any person obtaining */
  12. /* a copy of this software and associated documentation files (the */
  13. /* "Software"), to deal in the Software without restriction, including */
  14. /* without limitation the rights to use, copy, modify, merge, publish, */
  15. /* distribute, sublicense, and/or sell copies of the Software, and to */
  16. /* permit persons to whom the Software is furnished to do so, subject to */
  17. /* the following conditions: */
  18. /* */
  19. /* The above copyright notice and this permission notice shall be */
  20. /* included in all copies or substantial portions of the Software. */
  21. /* */
  22. /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
  23. /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
  24. /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
  25. /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
  26. /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
  27. /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
  28. /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
  29. /*************************************************************************/
  30. #include "cp_loader_xm.h"
  31. #include "cp_tables.h"
  32. #define ABORT_LOAD \
  33. { \
  34. file->close(); \
  35. return FILE_CORRUPTED; \
  36. }
  37. CPLoader::Error CPLoader_XM::load_song(const char *p_file, CPSong *p_song, bool p_sampleset) {
  38. song = p_song;
  39. if (file->open(p_file, CPFileAccessWrapper::READ)) {
  40. return FILE_CANNOT_OPEN;
  41. };
  42. /**************************************
  43. LOAD HEADER
  44. ***************************************/
  45. file->get_byte_array(header.idtext, 17);
  46. header.idtext[17] = 0;
  47. file->get_byte_array(header.songname, 20);
  48. header.songname[20] = 0;
  49. header.hex1a = file->get_byte();
  50. if (header.hex1a != 0x1A) { //XM "magic" byte.. this sucks :)
  51. file->close();
  52. return FILE_UNRECOGNIZED;
  53. }
  54. //magic byte sucks, but can't do much about it..
  55. song->reset(); //must reset the song
  56. song->set_name((const char *)header.songname);
  57. file->get_byte_array(header.trackername, 20);
  58. header.trackername[20] = 0;
  59. header.version = file->get_word();
  60. header.headersize = file->get_dword();
  61. header.songlength = file->get_word();
  62. header.restart_pos = file->get_word();
  63. header.channels_used = file->get_word();
  64. header.patterns_used = file->get_word();
  65. header.instruments_used = file->get_word();
  66. song->set_linear_slides(file->get_word());
  67. song->set_speed(file->get_word());
  68. song->set_tempo(file->get_word());
  69. song->set_instruments(true);
  70. file->get_byte_array(header.orderlist, 256);
  71. for (int i = 0; i < header.songlength; i++) {
  72. if (i > 199)
  73. break;
  74. song->set_order(i, header.orderlist[i]);
  75. }
  76. /**************************************
  77. LOAD PATTERNS
  78. ***************************************/
  79. for (int i = 0; i < header.patterns_used; i++) {
  80. uint32_t aux, rows;
  81. aux = file->get_dword(); //length
  82. aux = file->get_byte(); //packing type
  83. rows = aux = file->get_word(); //rows!
  84. song->get_pattern(i)->set_length(aux);
  85. aux = file->get_word(); //packed size
  86. if (aux == 0)
  87. continue;
  88. //unpaaack!
  89. for (int j = 0; j < (int)rows; j++)
  90. for (int k = 0; k < header.channels_used; k++) {
  91. CPNote aux_note;
  92. uint8_t aux_byte;
  93. //uint8_t field;
  94. aux_byte = file->get_byte(); //packing type
  95. if (!(aux_byte & 0x80)) {
  96. aux_note.note = aux_byte;
  97. aux_byte = 0xFE; //if bit 7 not set, read all of them except the note
  98. }
  99. if (aux_byte & 1) aux_note.note = file->get_byte();
  100. if (aux_byte & 2) aux_note.instrument = file->get_byte();
  101. if (aux_byte & 4) aux_note.volume = file->get_byte();
  102. if (aux_byte & 8) aux_note.command = file->get_byte();
  103. if (aux_byte & 16) aux_note.parameter = file->get_byte();
  104. if (aux_note.note != CPNote::EMPTY) {
  105. if (aux_note.note == 97)
  106. aux_note.note = CPNote::OFF;
  107. else {
  108. aux_note.note += 11; //octave minus one (XM C-0 is 1, not zero )
  109. }
  110. }
  111. if (aux_note.instrument != CPNote::EMPTY) {
  112. if ((aux_note.instrument > 0) && (aux_note.instrument < 100))
  113. aux_note.instrument--;
  114. else
  115. aux_note.instrument = CPNote::EMPTY;
  116. }
  117. if (aux_note.volume != CPNote::EMPTY) {
  118. if (aux_note.volume < 0x10) {
  119. } else if (aux_note.volume < 0x50) {
  120. aux_note.volume -= 0x10;
  121. } else if (aux_note.volume < 0x60) {
  122. //
  123. aux_note.volume = CPNote::EMPTY;
  124. } else if (aux_note.volume < 0x70) {
  125. //60 -- volume slide down
  126. aux_note.volume -= 0x60;
  127. if (aux_note.volume > 9) aux_note.volume = 9;
  128. aux_note.volume += 95;
  129. } else if (aux_note.volume < 0x80) {
  130. //70 -- volume slide up
  131. aux_note.volume -= 0x70;
  132. if (aux_note.volume > 9) aux_note.volume = 9;
  133. aux_note.volume += 85;
  134. } else if (aux_note.volume < 0x90) {
  135. //80 -- fine volume slide down
  136. aux_note.volume -= 0x80;
  137. if (aux_note.volume > 9) aux_note.volume = 9;
  138. aux_note.volume += 75;
  139. } else if (aux_note.volume < 0xA0) {
  140. //9 -- fine volume slide up
  141. aux_note.volume -= 0x90;
  142. if (aux_note.volume > 9) aux_note.volume = 9;
  143. aux_note.volume += 65;
  144. } else if (aux_note.volume < 0xB0) {
  145. //A -- set vibrato speed
  146. aux_note.volume = CPNote::EMPTY;
  147. } else if (aux_note.volume < 0xC0) {
  148. //B -- vibrato
  149. aux_note.volume -= 0xB0;
  150. if (aux_note.volume > 9) aux_note.volume = 9;
  151. aux_note.volume += 203;
  152. } else if (aux_note.volume < 0xD0) {
  153. //C -- set panning
  154. int aux = aux_note.volume -= 0xC0;
  155. aux = aux * 65 / 0xF;
  156. aux_note.volume = 128 + aux;
  157. } else if (aux_note.volume < 0xE0) {
  158. aux_note.volume = CPNote::EMPTY;
  159. } else if (aux_note.volume < 0xF0) {
  160. aux_note.volume = CPNote::EMPTY;
  161. } else {
  162. //F -- tone porta
  163. aux_note.volume -= 0xF0;
  164. aux_note.volume *= 9;
  165. aux_note.volume /= 0xF;
  166. aux_note.volume += 193;
  167. }
  168. }
  169. if (aux_note.command != CPNote::EMPTY) {
  170. switch (aux_note.command) {
  171. case 0x0:
  172. aux_note.command = 'J' - 'A';
  173. break;
  174. case 0x1:
  175. aux_note.command = 'F' - 'A';
  176. break;
  177. case 0x2:
  178. aux_note.command = 'E' - 'A';
  179. break;
  180. case 0x3:
  181. aux_note.command = 'G' - 'A';
  182. break;
  183. case 0x4:
  184. aux_note.command = 'H' - 'A';
  185. break;
  186. case 0x5:
  187. aux_note.command = 'L' - 'A';
  188. break;
  189. case 0x6:
  190. aux_note.command = 'K' - 'A';
  191. break;
  192. case 0x7:
  193. aux_note.command = 'R' - 'A';
  194. break;
  195. case 0x8:
  196. aux_note.command = 'X' - 'A';
  197. break;
  198. case 0x9:
  199. aux_note.command = 'O' - 'A';
  200. break;
  201. case 0xa:
  202. aux_note.command = 'D' - 'A';
  203. break;
  204. case 0xb:
  205. aux_note.command = 'B' - 'A';
  206. break;
  207. case 0xc:
  208. //printf("XM Import: Warning! effect C (set volume) not implemented!\n");
  209. break;
  210. case 0xd:
  211. aux_note.command = 'C' - 'A';
  212. break;
  213. case 0xe: /* Extended effects */
  214. aux_note.command = 'S' - 'A';
  215. switch (aux_note.parameter >> 4) {
  216. case 0x1: /* XM fine porta up */
  217. if (!(aux_note.parameter & 0xF)) {
  218. aux_note.command = CPNote::EMPTY;
  219. aux_note.parameter = 0;
  220. break;
  221. }
  222. aux_note.command = 'F' - 'A';
  223. aux_note.parameter = 0xF0 | (aux_note.parameter & 0xF);
  224. break;
  225. case 0x2: /* XM fine porta down */
  226. if (!(aux_note.parameter & 0xF)) {
  227. aux_note.command = CPNote::EMPTY;
  228. aux_note.parameter = 0;
  229. break;
  230. }
  231. aux_note.command = 'E' - 'A';
  232. aux_note.parameter = 0xF0 | (aux_note.parameter & 0xF);
  233. break;
  234. case 0xa: /* XM fine volume up */
  235. if (!(aux_note.parameter & 0xF)) {
  236. aux_note.command = CPNote::EMPTY;
  237. aux_note.parameter = 0;
  238. break;
  239. }
  240. aux_note.command = 'D' - 'A';
  241. aux_note.parameter = 0x0F | ((aux_note.parameter & 0xF) << 4);
  242. break;
  243. case 0xb: /* XM fine volume down */
  244. if (!(aux_note.parameter & 0xF)) {
  245. aux_note.command = CPNote::EMPTY;
  246. aux_note.parameter = 0;
  247. break;
  248. }
  249. aux_note.command = 'D' - 'A';
  250. aux_note.parameter = 0xF0 | (aux_note.parameter & 0xF);
  251. break;
  252. case 0x9: /* XM fine volume down */
  253. if (!(aux_note.parameter & 0xF)) {
  254. aux_note.command = CPNote::EMPTY;
  255. aux_note.parameter = 0;
  256. break;
  257. }
  258. aux_note.command = 'Q' - 'A';
  259. aux_note.parameter = 0x00 | (aux_note.parameter & 0xF);
  260. break;
  261. case 0xc: //notecut
  262. aux_note.parameter = 0xC0 | (aux_note.parameter & 0xF);
  263. break;
  264. case 0xd: //notedelay
  265. aux_note.parameter = 0xD0 | (aux_note.parameter & 0xF);
  266. break;
  267. case 0xe: //patterndelay
  268. aux_note.parameter = 0xE0 | (aux_note.parameter & 0xF);
  269. break;
  270. }
  271. break;
  272. case 0xf:
  273. if (aux_note.parameter < 32) {
  274. aux_note.command = 'A' - 'A';
  275. } else {
  276. aux_note.command = 'T' - 'A';
  277. }
  278. break;
  279. case 'G' - 55:
  280. aux_note.command = 'V' - 'A';
  281. break;
  282. case 'H' - 55:
  283. aux_note.command = 'W' - 'A';
  284. break;
  285. case 'K' - 55:
  286. if (aux_note.note != CPNote::EMPTY) break;
  287. aux_note.note = CPNote::OFF;
  288. break;
  289. case 'P' - 55:
  290. aux_note.command = 'P' - 'A';
  291. break;
  292. case 'R' - 55:
  293. aux_note.command = 'Q' - 'A';
  294. break;
  295. case 'T' - 55:
  296. aux_note.command = 'I' - 'A';
  297. break;
  298. default: {
  299. aux_note.command = CPNote::EMPTY;
  300. }
  301. }
  302. }
  303. song->get_pattern(i)->set_note(k, j, aux_note);
  304. }
  305. }
  306. /**************************************
  307. LOAD INSTRUMENTS!
  308. ***************************************/
  309. for (int i = 0; i < header.instruments_used; i++) {
  310. uint32_t aux;
  311. int sampnum;
  312. CPInstrument &instrument = *song->get_instrument(i);
  313. uint32_t cpos = file->get_pos();
  314. //printf("pos is %i\n",cpos);
  315. /* +4 */ uint32_t hsize = file->get_dword(); //header length
  316. char instrname[23];
  317. instrname[22] = 0;
  318. file->get_byte_array((uint8_t *)instrname, 22);
  319. //XM_LOAD_DEBUG printf("name is %s\n",instrname);
  320. /* +27 */ aux = file->get_byte(); //byte that must be ignored
  321. //XM_LOAD_DEBUG printf("header size is %i\n",hsize);
  322. /* +29 */ sampnum = file->get_word();
  323. //XM_LOAD_DEBUG printf("samples %i\n",sampnum);
  324. instrument.set_name(instrname);
  325. // printf("Header Len: %i, CPInstrument %i, %i samples , name: s,\n",hsize,i,sampnum,instrname);
  326. if (sampnum == 0) {
  327. //aux=file->get_dword(); //Why is this for? -- for nothing, skipped
  328. if (hsize) {
  329. file->seek(cpos + hsize); //skip header if size has been specified
  330. }
  331. continue;
  332. }
  333. /* +33 */ file->get_dword();
  334. if (Error result = load_instrument_internal(&instrument, false, cpos, hsize, sampnum)) {
  335. CP_PRINTERR("Error loading instrument");
  336. file->close();
  337. return result;
  338. }
  339. }
  340. //
  341. file->close();
  342. return FILE_OK;
  343. }
  344. CPLoader::Error CPLoader_XM::load_instrument_internal(CPInstrument *p_instr, bool p_xi, int p_cpos, int p_hsize, int p_sampnum) {
  345. int sampnum;
  346. uint32_t aux;
  347. uint8_t notenumb[96];
  348. uint16_t panenv[24], volenv[24];
  349. int volpoints, panpoints;
  350. int vol_loop_begin, vol_loop_end, vol_sustain_loop;
  351. int pan_loop_begin, pan_loop_end, pan_sustain_loop;
  352. char instrname[23];
  353. int sample_index[16] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }; //-1 means no index!
  354. instrname[22] = 0;
  355. /* +129 */ file->get_byte_array((uint8_t *)notenumb, 96);
  356. for (int j = 0; j < 24; j++) {
  357. volenv[j] = file->get_word();
  358. }
  359. for (int j = 0; j < 24; j++) {
  360. panenv[j] = file->get_word();
  361. }
  362. /* +177 */
  363. /* +225 */
  364. /* +226 */ volpoints = file->get_byte();
  365. /* +227 */ panpoints = file->get_byte();
  366. /* +230 */ vol_sustain_loop = file->get_byte();
  367. /* +228 */ vol_loop_begin = file->get_byte();
  368. /* +229 */ vol_loop_end = file->get_byte();
  369. //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);
  370. pan_sustain_loop = file->get_byte();
  371. /* +231 */ pan_loop_begin = file->get_byte();
  372. /* +232 */ pan_loop_end = file->get_byte();
  373. /* +234 */ aux = file->get_byte();
  374. p_instr->get_volume_envelope()->reset();
  375. p_instr->get_volume_envelope()->set_enabled(aux & 1);
  376. p_instr->get_volume_envelope()->set_sustain_loop_enabled((aux & 2) ? true : false);
  377. p_instr->get_volume_envelope()->set_loop_enabled((aux & 4) ? true : false);
  378. /* +235 */ aux = file->get_byte();
  379. p_instr->get_pan_envelope()->reset();
  380. p_instr->get_pan_envelope()->set_enabled(aux & 1);
  381. p_instr->get_pan_envelope()->set_sustain_loop_enabled((aux & 2) ? true : false);
  382. p_instr->get_pan_envelope()->set_loop_enabled((aux & 4) ? true : false);
  383. /* +239 */ aux = file->get_dword(); // sadly, cant use those
  384. /* +241 */ p_instr->set_volume_fadeout(file->get_word() >> 4);
  385. /* +243 */ aux = file->get_word(); // reserved!
  386. for (int j = 0; j < volpoints; j++) {
  387. int ofs = volenv[j * 2];
  388. int val = volenv[j * 2 + 1];
  389. p_instr->get_volume_envelope()->add_position(ofs, val);
  390. }
  391. //make sure minimum is 2
  392. while (p_instr->get_volume_envelope()->get_node_count() < 2) {
  393. p_instr->get_volume_envelope()->add_position(p_instr->get_volume_envelope()->get_node_count() * 20, 64);
  394. }
  395. for (int j = 0; j < panpoints; j++) {
  396. int ofs = panenv[j * 2];
  397. int val = panenv[j * 2 + 1];
  398. p_instr->get_pan_envelope()->add_position(ofs, val - 32);
  399. }
  400. //make sure minimum is 2
  401. while (p_instr->get_pan_envelope()->get_node_count() < 2) {
  402. p_instr->get_pan_envelope()->add_position(p_instr->get_pan_envelope()->get_node_count() * 20, 0);
  403. }
  404. p_instr->get_volume_envelope()->set_loop_begin(vol_loop_begin);
  405. p_instr->get_volume_envelope()->set_loop_end(vol_loop_end);
  406. p_instr->get_volume_envelope()->set_sustain_loop_end(vol_sustain_loop);
  407. p_instr->get_volume_envelope()->set_sustain_loop_begin(vol_sustain_loop);
  408. p_instr->get_pan_envelope()->set_loop_begin(pan_loop_begin);
  409. p_instr->get_pan_envelope()->set_loop_end(pan_loop_end);
  410. p_instr->get_pan_envelope()->set_sustain_loop_end(pan_sustain_loop);
  411. p_instr->get_pan_envelope()->set_sustain_loop_begin(pan_sustain_loop);
  412. if (!p_xi) {
  413. if ((file->get_pos() - p_cpos) < p_hsize) {
  414. uint8_t junkbuster[500];
  415. //printf("extra junk XM instrument in header! hsize is %i, extra junk: %i\n",p_hsize,(file->get_pos()-p_cpos));
  416. //printf("extra: %i\n",p_hsize-(file->get_pos()-p_cpos));
  417. file->get_byte_array((uint8_t *)junkbuster, p_hsize - (file->get_pos() - p_cpos));
  418. }
  419. sampnum = p_sampnum;
  420. } else {
  421. uint8_t junkbuster[500];
  422. file->get_byte_array((uint8_t *)junkbuster, 20); //14 bytes?
  423. sampnum = file->get_word();
  424. }
  425. CPSampleManager *sm = CPSampleManager::get_singleton();
  426. /*SAMPLE!!*/
  427. for (int j = 0; j < sampnum; j++) {
  428. if (j > 16) ABORT_LOAD;
  429. int s_idx = -1;
  430. for (int s = 0; s < CPSong::MAX_SAMPLES; s++) {
  431. if (song->get_sample(s)->get_sample_data().is_null()) {
  432. //empty sample!
  433. s_idx = s;
  434. break;
  435. }
  436. }
  437. if (s_idx == -1) ABORT_LOAD;
  438. //printf("free sample: %i\n",s_idx);
  439. CPSample &sample = *song->get_sample(s_idx);
  440. int sample_size = file->get_dword();
  441. int tmp_loop_begin = file->get_dword();
  442. int tmp_loop_end = file->get_dword();
  443. sample.set_default_volume(file->get_byte());
  444. uint8_t ftb = file->get_byte();
  445. int8_t *fts = (int8_t *)&ftb;
  446. int finetune = *fts;
  447. uint32_t flags = file->get_byte();
  448. if (flags & 16) { // is 16 bits.. at flag 16.. fun :)
  449. tmp_loop_end /= 2;
  450. tmp_loop_begin /= 2;
  451. sample_size /= 2;
  452. }
  453. CPSample_ID sample_data = sm->create(flags & 16, false, sample_size);
  454. sample.set_sample_data(sample_data);
  455. sm->set_loop_begin(sample_data, tmp_loop_begin);
  456. sm->set_loop_end(sample_data, tmp_loop_end + tmp_loop_begin);
  457. sm->set_loop_type(sample_data, (flags & 3) ? ((flags & 2) ? CP_LOOP_BIDI : CP_LOOP_FORWARD) : CP_LOOP_NONE);
  458. sample.set_pan_enabled(true);
  459. sample.set_pan(file->get_byte() * 64 / 255);
  460. uint8_t noteb = file->get_byte();
  461. int8_t *notes = (int8_t *)&noteb;
  462. int note_offset = *notes;
  463. note_offset += 48;
  464. //note_offset+=60;
  465. //int linear_period=10*12*16*4 - (note_offset)*16*4 - finetune/2;
  466. //int freq=(int)(8363*pow(2.0,(double)(6*12*16*4 - linear_period) / (double)(12*16*4)));
  467. //sm->set_c5_freq( sample_data, freq);
  468. sm->set_c5_freq(sample_data, CPTables::get_linear_frequency(CPTables::get_linear_period(note_offset << 1, finetune)));
  469. //printf("NOTE %i,fine %i\n",note_offset,finetune);
  470. char auxb;
  471. auxb = file->get_byte(); //reserved?
  472. file->get_byte_array((uint8_t *)instrname, 22);
  473. sample.set_name(instrname);
  474. sample_index[j] = s_idx;
  475. }
  476. /*SAMPLE __DATA__!!*/
  477. for (int j = 0; j < sampnum; j++) {
  478. if (sample_index[j] == -1) continue;
  479. CPSample *sample = song->get_sample(sample_index[j]);
  480. CPSample_ID sid = sample->get_sample_data();
  481. sm->lock_data(sid);
  482. void *dataptr = sm->get_data(sid);
  483. if (sm->is_16bits(sid)) {
  484. int16_t old = 0;
  485. for (int k = 0; k < sm->get_size(sid); k++) {
  486. int16_t newsample;
  487. int16_t sampleval = file->get_word();
  488. newsample = sampleval + old;
  489. old = newsample;
  490. ((int16_t *)dataptr)[k] = newsample;
  491. //sm->set_data( sid, k, newsample );
  492. }
  493. } else {
  494. int8_t old = 0;
  495. for (int k = 0; k < sm->get_size(sid); k++) {
  496. int8_t newsample;
  497. int8_t sampleval = file->get_byte();
  498. newsample = sampleval + old;
  499. old = newsample;
  500. ((int8_t *)dataptr)[k] = newsample;
  501. //sm->set_data( sid, k, (int16_t)newsample << 8 );
  502. }
  503. }
  504. sm->unlock_data(sid);
  505. }
  506. for (int j = 0; j < 96; j++) {
  507. int val = notenumb[j];
  508. if ((val < 0) || (val > 15))
  509. continue;
  510. else
  511. val = sample_index[val];
  512. if (val == -1) continue;
  513. p_instr->set_sample_number(12 + j, val);
  514. }
  515. return FILE_OK;
  516. }
  517. CPLoader::Error CPLoader_XM::load_sample(const char *p_file, CPSample *p_sample) {
  518. return FILE_UNRECOGNIZED;
  519. }
  520. /* Compute CPInstrument Info */
  521. CPLoader::Error CPLoader_XM::load_instrument(const char *p_file, CPSong *p_song, int p_instr_idx) {
  522. if (file->open(p_file, CPFileAccessWrapper::READ)) return FILE_CANNOT_OPEN;
  523. //int i;
  524. song = p_song;
  525. CPInstrument &instr = *p_song->get_instrument(p_instr_idx);
  526. int aux;
  527. char buffer[500];
  528. file->get_byte_array((uint8_t *)buffer, 0x15);
  529. buffer[8] = 0;
  530. if (buffer[0] != 'E' ||
  531. buffer[1] != 'x' ||
  532. buffer[2] != 't' ||
  533. buffer[3] != 'e' ||
  534. buffer[4] != 'n' ||
  535. buffer[5] != 'd' ||
  536. buffer[6] != 'e' ||
  537. buffer[7] != 'd') {
  538. file->close();
  539. return FILE_UNRECOGNIZED;
  540. }
  541. file->get_byte_array((uint8_t *)buffer, 0x16);
  542. buffer[0x16] = 0;
  543. instr.set_name(buffer);
  544. aux = file->get_byte(); //says ignore ti
  545. /*if(aux!=0x1a) { I'm not sure. this is supposed to be ignored...
  546. file->close();
  547. return FILE_UNRECOGNIZED;
  548. } */
  549. file->get_byte_array((uint8_t *)buffer, 0x14); //somethingaboutthename
  550. aux = file->get_word(); //version or blahblah
  551. if (load_instrument_internal(&instr, true, 0, 0)) {
  552. file->close();
  553. return FILE_CORRUPTED;
  554. }
  555. file->close(); //ook, we got it..
  556. return FILE_OK;
  557. }
  558. CPLoader_XM::CPLoader_XM(CPFileAccessWrapper *p_file) {
  559. file = p_file;
  560. }
  561. CPLoader_XM::~CPLoader_XM() {
  562. }