cp_loader_mod.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482
  1. /*************************************************************************/
  2. /* cp_loader_mod.cpp */
  3. /*************************************************************************/
  4. /* This file is part of: */
  5. /* GODOT ENGINE */
  6. /* http://www.godotengine.org */
  7. /*************************************************************************/
  8. /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
  9. /* */
  10. /* Permission is hereby granted, free of charge, to any person obtaining */
  11. /* a copy of this software and associated documentation files (the */
  12. /* "Software"), to deal in the Software without restriction, including */
  13. /* without limitation the rights to use, copy, modify, merge, publish, */
  14. /* distribute, sublicense, and/or sell copies of the Software, and to */
  15. /* permit persons to whom the Software is furnished to do so, subject to */
  16. /* the following conditions: */
  17. /* */
  18. /* The above copyright notice and this permission notice shall be */
  19. /* included in all copies or substantial portions of the Software. */
  20. /* */
  21. /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
  22. /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
  23. /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
  24. /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
  25. /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
  26. /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
  27. /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
  28. /*************************************************************************/
  29. #include "cp_loader_mod.h"
  30. static bool tag_equal_to(const char *p_tag, const char *p_string) {
  31. return( p_tag[0]==p_string[0] &&
  32. p_tag[1]==p_string[1] &&
  33. p_tag[2]==p_string[2] &&
  34. p_tag[3]==p_string[3]);
  35. }
  36. /* ProTracker period table */
  37. uint16_t period_table[6*12] = {
  38. 1712,1616,1524,1440,1356,1280,1208,1140,1076,1016,960,907,
  39. 856,808,762,720,678,640,604,570,538,508,480,453,
  40. 428,404,381,360,339,320,302,285,269,254,240,226,
  41. 214,202,190,180,170,160,151,143,135,127,120,113,
  42. 107,101,95,90,85,80,75,71,67,63,60,56,
  43. 53,50,47,45,42,40,37,35,33,31,30,28
  44. };
  45. CPLoader::Error CPLoader_MOD::load_song(const char *p_file,CPSong *p_song,bool p_sampleset) {
  46. if (file->open(p_file,CPFileAccessWrapper::READ)) {
  47. //printf("Can't open file! %s\n",p_file);
  48. return FILE_CANNOT_OPEN;
  49. };
  50. /* FIRST OF ALL, one needs to read the .mod file format tag */
  51. file->seek( 1080 ); //located at 1080
  52. char format_tag[4];
  53. file->get_byte_array( (uint8_t*)format_tag, 4 );
  54. int channels=-1;
  55. /** THE PAIN!! - COMPARE TAGS */
  56. /* Classic 4-chan */
  57. if (tag_equal_to(format_tag,"M.K.") )
  58. channels=4;
  59. if (tag_equal_to(format_tag,"FLT4") )
  60. channels=4;
  61. if (tag_equal_to(format_tag,"M!K!") )
  62. channels=4;
  63. /* 8 Channel MODS */
  64. if (tag_equal_to(format_tag,"FLT8") )
  65. channels=2;
  66. if (tag_equal_to(format_tag,"CD81") )
  67. channels=2;
  68. /* Custom channel MODS */
  69. for (int i=1;i<=32;i++) {
  70. if (i<10) { // up to 9 channels mods
  71. /* Old Take Tracker */
  72. char old_take_tracker[4]={'T','D','Z',char('0'+i)};
  73. if (tag_equal_to(format_tag,old_take_tracker)) {
  74. channels=i;
  75. break;
  76. }
  77. /* Contemplates many XCHN Formats */
  78. char xchn[4]={char('0'+i),'C','H','N'};
  79. if (tag_equal_to(format_tag,xchn)) {
  80. channels=i;
  81. break;
  82. }
  83. }
  84. /* Fast Tracker */
  85. char fast_tracker[4]={char('0'+(i/10)),char('0'+(i%10)),'C','H'};
  86. if (tag_equal_to(format_tag,fast_tracker)) {
  87. channels=i;
  88. break;
  89. }
  90. }
  91. if (channels==-1) {
  92. file->close();
  93. return FILE_UNRECOGNIZED;
  94. }
  95. /** Load CPSong INFO */
  96. file->seek( 0 ); //go to begining of file
  97. file->set_endian_conversion( true );
  98. p_song->reset();
  99. p_song->set_instruments( false );
  100. char name[21];
  101. file->get_byte_array( (uint8_t*)name,20);
  102. name[20]=0;
  103. p_song->set_name(name);
  104. p_song->set_old_effects( true );
  105. p_song->set_linear_slides( false );
  106. p_song->set_compatible_gxx( true );
  107. CPSampleManager *sm=CPSampleManager::get_singleton();
  108. int instruments=31;
  109. for (int i=0;i<instruments;i++) {
  110. char sample_name[23];
  111. file->get_byte_array( (uint8_t*)sample_name,22);
  112. sample_name[22]=0;
  113. uint32_t sample_len=file->get_word();
  114. sample_len<<=1;
  115. uint8_t fine_nibble=file->get_byte()&0xF;
  116. //(int8_t)(fine_nibble & 7) - (int8_t)(fine_nibble & 8); //yesso's genius trick
  117. // boo, I can't use it :( but i leave it here because of how cool it is
  118. uint8_t linear_volume=file->get_byte(); //0 .. ?
  119. uint32_t loop_begin=file->get_word(); //0 .. ?
  120. loop_begin<<=1;
  121. uint32_t loop_end=file->get_word(); //0 .. ?
  122. loop_end<<=1;
  123. if (sample_len>0) {
  124. CPSample_ID sid=sm->create( false, false, sample_len );
  125. if (sid.is_null()) {
  126. file->close();
  127. return FILE_OUT_OF_MEMORY;
  128. }
  129. if (loop_end>2) {
  130. sm->set_loop_begin( sid, loop_begin );
  131. sm->set_loop_end( sid, loop_end+loop_begin );
  132. sm->set_loop_type( sid,CP_LOOP_FORWARD );
  133. }
  134. static const uint16_t fine_to_freq[16]={
  135. 8363,8413,8463,8529,8581,8651,8723,8757,
  136. 7895,7941,7985,8046,8107,8169,8232,8280
  137. };
  138. sm->set_c5_freq( sid, fine_to_freq[fine_nibble] );
  139. p_song->get_sample(i)->set_sample_data(sid);
  140. }
  141. p_song->get_sample(i)->set_name(sample_name);
  142. p_song->get_sample(i)->set_default_volume( linear_volume );
  143. }
  144. /* pan for MODs */
  145. for (int i=0;i<channels;i++)
  146. p_song->set_channel_pan( i, (((i&3)==1) || ((i&3)==2)) ? 0: 64);
  147. uint8_t order_count=file->get_byte();
  148. //uint8_t loop_to=file->get_byte();
  149. int pattern_count=0;
  150. for (int i=0;i<128;i++) {
  151. uint8_t order=file->get_byte();
  152. if (i<order_count) {
  153. p_song->set_order(i,order);
  154. /* Determine the amount of patterns */
  155. if ((order+1)>pattern_count)
  156. pattern_count=order+1;
  157. } else
  158. p_song->set_order( i, CP_ORDER_NONE );
  159. }
  160. if (instruments==31)
  161. file->get_dword(); // identiefier, now skip it
  162. for (int i=0;i<pattern_count;i++) {
  163. for(int line=0;line<64;line++) {
  164. for(int column=0;column<channels;column++) {
  165. uint32_t note_w=file->get_dword();
  166. CPNote note;
  167. note.instrument=(note_w>>12)&0xF;
  168. note.instrument|=(note_w>>24)&0xF0;
  169. if (note.instrument==0)
  170. note.instrument=CPNote::EMPTY;
  171. else
  172. note.instrument--;
  173. note.parameter=note_w&0xFF;
  174. int cmd=(note_w>>8)&0xF;
  175. uint32_t period=(note_w>>16)&0xFFF;
  176. if (period>0 && period<0xFFF) {
  177. //period>>=2;
  178. //period<<=1;
  179. for (int n=0; n<6*12; n++) {
  180. if (period >= period_table[n]) {
  181. if ((period!=period_table[n]) && (n))
  182. {
  183. uint32_t p1 = period_table[n-1];
  184. uint32_t p2 = period_table[n];
  185. if (p1 - period < (period - p2)) {
  186. note.note=n+36;
  187. break;
  188. }
  189. }
  190. note.note=n+1+36;
  191. break;
  192. }
  193. }
  194. if (note.note==CPNote::EMPTY)
  195. note.note=6*12+36;
  196. note.note--;
  197. }
  198. switch(cmd) {
  199. case 0x0: {
  200. if (note.parameter>0)
  201. note.command='J'-'A';
  202. } break;
  203. case 0x1: {
  204. note.command='F'-'A';
  205. } break;
  206. case 0x2: {
  207. note.command='E'-'A';
  208. } break;
  209. case 0x3: {
  210. note.command='G'-'A';
  211. } break;
  212. case 0x4: {
  213. note.command='H'-'A';
  214. } break;
  215. case 0x5: {
  216. note.command='L'-'A';
  217. } break;
  218. case 0x6: {
  219. note.command='K'-'A';
  220. } break;
  221. case 0x7: {
  222. note.command='R'-'A';
  223. } break;
  224. case 0x8: {
  225. note.command='X'-'A';
  226. } break;
  227. case 0x9: {
  228. note.command='O'-'A';
  229. } break;
  230. case 0xA: {
  231. note.command='D'-'A';
  232. } break;
  233. case 0xB: {
  234. note.command='B'-'A';
  235. } break;
  236. case 0xC: {
  237. note.volume=note.parameter;
  238. if (note.volume>64)
  239. note.volume=64;
  240. note.parameter=0;
  241. } break;
  242. case 0xD: {
  243. note.command='C'-'A';
  244. note.parameter=(note.parameter>>4)*10 + (note.parameter&0xF);
  245. } break;
  246. case 0xE: { //SPECIAL EFFECT!
  247. note.command='S'-'A';
  248. switch(note.parameter>>4) {
  249. case 0x1: {
  250. note.command='F'-'A';
  251. note.parameter=0xF0|(note.parameter&0xF);
  252. } break;
  253. case 0x2: {
  254. note.command='E'-'A';
  255. note.parameter=0xF0|(note.parameter&0xF);
  256. } break;
  257. case 0x4: {
  258. note.command='S'-'A';
  259. note.parameter=0x30|(note.parameter&0x3);
  260. } break;
  261. case 0x6: {
  262. note.command='S'-'A';
  263. note.parameter=0xB0|(note.parameter&0xF);
  264. } break;
  265. case 0x7: {
  266. note.command='S'-'A';
  267. note.parameter=0x40|(note.parameter&0x3);
  268. } break;
  269. case 0x8: {
  270. note.command='S'-'A'; // wow, it's the same!
  271. } break;
  272. case 0x9: {
  273. note.command='Q'-'A';
  274. note.parameter=(note.parameter&0xF);
  275. } break;
  276. case 0xA: {
  277. note.command='D'-'A';
  278. note.parameter=0xF|((note.parameter&0xF)<<4);
  279. } break;
  280. case 0xB: {
  281. note.command='D'-'A';
  282. note.parameter=0xF0|(note.parameter&0xF);
  283. } break;
  284. case 0xC:
  285. case 0xD: {
  286. note.command='S'-'A'; //wow, they are the same!
  287. } break;
  288. case 0xE: {
  289. note.command='S'-'A';
  290. note.parameter=0x60|(note.parameter&0xF);
  291. } break;
  292. default: {
  293. note.command=CPNote::EMPTY;
  294. note.parameter=0;
  295. } break;
  296. }
  297. } break;
  298. case 0xF: {
  299. if (note.parameter<32)
  300. note.command='A'-'A';
  301. else
  302. note.command='T'-'A';
  303. } break;
  304. }
  305. p_song->get_pattern(i)->set_note( column,line, note );
  306. }
  307. }
  308. }
  309. for (int i=0;i<instruments;i++) {
  310. CPSample_ID sid=p_song->get_sample(i)->get_sample_data();
  311. if (sid.is_null()) {
  312. continue; //empty sample, not stored?
  313. }
  314. sm->lock_data(sid);
  315. uint8_t *dataptr = (uint8_t*)sm->get_data(sid);
  316. int len=sm->get_size(sid);
  317. for (int s=0;s<len;s++) {
  318. uint8_t d=file->get_byte();
  319. //d-=128; //convert to signed
  320. int8_t*ds=(int8_t*)&d;
  321. dataptr[s]=*ds;
  322. }
  323. sm->unlock_data(sid);
  324. }
  325. file->close();
  326. return FILE_OK;
  327. }
  328. CPLoader_MOD::CPLoader_MOD(CPFileAccessWrapper *p_file) {
  329. file=p_file;
  330. }
  331. CPLoader_MOD::~CPLoader_MOD()
  332. {
  333. }