]> 4ch.mooo.com Git - 16.git/blob - 16/adplug/adplug-2.2.1/src/bmf.cpp
Please enter the commit message for your changes. Lines starting
[16.git] / 16 / adplug / adplug-2.2.1 / src / bmf.cpp
1 /*
2  * Adplug - Replayer for many OPL2/OPL3 audio file formats.
3  * Copyright (C) 1999 - 2003, 2006 Simon Peter, <dn.tlp@gmx.net>, et al.
4  * 
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  * 
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  * 
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  *
19  * [xad] BMF player, by Riven the Mage <riven@ok.ru>
20  */
21
22 /*
23     - discovery -
24
25   file(s) : GAMESNET.COM
26      type : GamesNet advertising intro
27      tune : by (?)The Brain [Razor 1911]
28    player : ver.0.9b by Hammer
29
30   file(s) : 2FAST4U.COM
31      type : Ford Knox BBStro
32      tune : by The Brain [Razor 1911]
33    player : ver.1.1 by ?
34   comment : in original player at 9th channel the feedback adlib register is not C8 but C6.
35
36   file(s) : DATURA.COM
37      type : Datura BBStro
38      tune : by The Brain [Razor 1911]
39    player : ver.1.2 by ?
40   comment : inaccurate replaying, because constant outport; in original player it can be 380 or 382.
41 */
42
43 #include <cstring>
44 #include "bmf.h"
45 #include "debug.h"
46
47 const unsigned char CxadbmfPlayer::bmf_adlib_registers[117] =
48 {
49   0x20, 0x23, 0x40, 0x43, 0x60, 0x63, 0x80, 0x83, 0xA0, 0xB0, 0xC0, 0xE0, 0xE3,
50   0x21, 0x24, 0x41, 0x44, 0x61, 0x64, 0x81, 0x84, 0xA1, 0xB1, 0xC1, 0xE1, 0xE4,
51   0x22, 0x25, 0x42, 0x45, 0x62, 0x65, 0x82, 0x85, 0xA2, 0xB2, 0xC2, 0xE2, 0xE5,
52   0x28, 0x2B, 0x48, 0x4B, 0x68, 0x6B, 0x88, 0x8B, 0xA3, 0xB3, 0xC3, 0xE8, 0xEB,
53   0x29, 0x2C, 0x49, 0x4C, 0x69, 0x6C, 0x89, 0x8C, 0xA4, 0xB4, 0xC4, 0xE9, 0xEC,
54   0x2A, 0x2D, 0x4A, 0x4D, 0x6A, 0x6D, 0x8A, 0x8D, 0xA5, 0xB5, 0xC5, 0xEA, 0xED,
55   0x30, 0x33, 0x50, 0x53, 0x70, 0x73, 0x90, 0x93, 0xA6, 0xB6, 0xC6, 0xF0, 0xF3,
56   0x31, 0x34, 0x51, 0x54, 0x71, 0x74, 0x91, 0x94, 0xA7, 0xB7, 0xC7, 0xF1, 0xF4,
57   0x32, 0x35, 0x52, 0x55, 0x72, 0x75, 0x92, 0x95, 0xA8, 0xB8, 0xC8, 0xF2, 0xF5
58 };
59
60 const unsigned short CxadbmfPlayer::bmf_notes[12] =
61 {
62   0x157, 0x16B, 0x181, 0x198, 0x1B0, 0x1CA, 0x1E5, 0x202, 0x220, 0x241, 0x263, 0x287
63 };
64
65 /* for 1.1 */
66 const unsigned short CxadbmfPlayer::bmf_notes_2[12] =
67 {
68   0x159, 0x16D, 0x183, 0x19A, 0x1B2, 0x1CC, 0x1E8, 0x205, 0x223, 0x244, 0x267, 0x28B
69 };
70
71 const unsigned char CxadbmfPlayer::bmf_default_instrument[13] =
72 {
73   0x01, 0x01, 0x3F, 0x3F, 0x00, 0x00, 0xF0, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00
74 };
75
76 CPlayer *CxadbmfPlayer::factory(Copl *newopl)
77 {
78   return new CxadbmfPlayer(newopl);
79 }
80
81 bool CxadbmfPlayer::xadplayer_load()
82 {
83   unsigned short ptr = 0;
84   int i;
85
86   if(xad.fmt != BMF)
87     return false;
88
89 #ifdef DEBUG
90   AdPlug_LogWrite("\nbmf_load():\n\n");
91 #endif
92   if (!strncmp((char *)&tune[0],"BMF1.2",6))
93   {
94     bmf.version = BMF1_2;
95     bmf.timer = 70.0f;
96   }
97   else if (!strncmp((char *)&tune[0],"BMF1.1",6))
98   {
99     bmf.version = BMF1_1;
100     bmf.timer = 60.0f;
101   }
102   else
103   {
104     bmf.version = BMF0_9B;
105     bmf.timer = 18.2f;
106   }
107
108   // copy title & author
109   if (bmf.version > BMF0_9B)
110   {
111     ptr = 6;
112
113     strncpy(bmf.title,(char *)&tune[ptr],36);
114
115     while (tune[ptr]) { ptr++; }
116         ptr++;
117
118     strncpy(bmf.author,(char *)&tune[ptr],36);
119
120     while (tune[ptr]) { ptr++; }
121         ptr++;
122   }
123   else
124   {
125     strncpy(bmf.title,xad.title,36);
126     strncpy(bmf.author,xad.author,36);
127   }
128
129   // speed
130   if (bmf.version > BMF0_9B)
131     bmf.speed = tune[ptr++];
132   else
133     bmf.speed = ((tune[ptr++] << 8) / 3) >> 8; // strange, yeh ?
134
135   // load instruments
136   if (bmf.version > BMF0_9B)
137   {
138     unsigned long iflags = (tune[ptr] << 24) | (tune[ptr+1] << 16) | (tune[ptr+2] << 8) | tune[ptr+3];
139     ptr+=4;
140
141     for(i=0;i<32;i++)
142       if (iflags & (1 << (31-i)))
143           {
144         strcpy(bmf.instruments[i].name, (char *)&tune[ptr]);
145         memcpy(bmf.instruments[i].data, &tune[ptr+11], 13);
146         ptr += 24;
147           }
148       else
149           {
150         bmf.instruments[i].name[0] = 0;
151                 
152         if (bmf.version == BMF1_1)
153                   for(int j=0;j<13;j++)
154                         bmf.instruments[i].data[j] = bmf_default_instrument[j];
155         else
156                   for(int j=0;j<13;j++)
157                         bmf.instruments[i].data[j] = 0;
158           }
159   }
160   else
161   {
162     ptr = 6;
163
164     for(i=0;i<32;i++)
165     {
166       bmf.instruments[i].name[0] = 0;
167       memcpy(bmf.instruments[tune[ptr]].data, &tune[ptr+2],13); // bug no.1 (no instrument-table-end detection)
168       ptr+=15;
169     }
170   }
171   
172   // load streams
173   if (bmf.version > BMF0_9B)
174   {
175     unsigned long sflags = (tune[ptr] << 24) | (tune[ptr+1] << 16) | (tune[ptr+2] << 8) | tune[ptr+3];
176     ptr+=4;
177
178     for(i=0;i<9;i++)
179       if (sflags & (1 << (31-i)))
180         ptr+=__bmf_convert_stream(&tune[ptr],i);
181       else
182         bmf.streams[i][0].cmd = 0xFF;
183   }
184   else
185   {
186     for(i=0;i<tune[5];i++)
187       ptr+=__bmf_convert_stream(&tune[ptr],i);
188
189         for(i=tune[5];i<9;i++)
190       bmf.streams[i][0].cmd = 0xFF;
191   }
192
193   return true;
194 }
195
196 void CxadbmfPlayer::xadplayer_rewind(int subsong)
197 {
198   int i,j;
199
200   for(i=0; i<9; i++)
201   {
202     bmf.channel[i].stream_position = 0;
203     bmf.channel[i].delay = 0;
204     bmf.channel[i].loop_position = 0;
205     bmf.channel[i].loop_counter = 0;
206   }
207
208   plr.speed = bmf.speed;
209 #ifdef DEBUG
210   AdPlug_LogWrite("speed: %x\n",plr.speed);
211 #endif
212
213   bmf.active_streams = 9;
214
215   // OPL initialization
216   if (bmf.version > BMF0_9B)
217   {
218     opl_write(0x01, 0x20);
219     
220     /* 1.1 */
221     if (bmf.version == BMF1_1)
222       for(i=0;i<9;i++)
223         for(j=0;j<13;j++)
224           opl_write(bmf_adlib_registers[13*i+j], bmf_default_instrument[j]);
225     /* 1.2 */
226     else if (bmf.version == BMF1_2)
227       for(i=0x20; i<0x100; i++)
228         opl_write(i,0xFF); // very interesting, really!
229   }
230
231   /* ALL */
232
233   opl_write(0x08, 0x00);
234   opl_write(0xBD, 0xC0);
235 }
236
237 void CxadbmfPlayer::xadplayer_update()
238 {
239   for(int i=0;i<9;i++)
240     if (bmf.channel[i].stream_position != 0xFFFF)
241     if (bmf.channel[i].delay)
242       bmf.channel[i].delay--;
243         else
244         {
245 #ifdef DEBUG
246    AdPlug_LogWrite("channel %02X:\n", i);
247 #endif
248       bmf_event event;
249
250       // process so-called cross-events
251           while (true)
252           {
253         memcpy(&event, &bmf.streams[i][bmf.channel[i].stream_position], sizeof(bmf_event));
254 #ifdef DEBUG
255    AdPlug_LogWrite("%02X %02X %02X %02X %02X %02X\n",
256                    event.note,event.delay,event.volume,event.instrument,
257                    event.cmd,event.cmd_data);
258 #endif
259
260         if (event.cmd == 0xFF)
261                 {
262           bmf.channel[i].stream_position = 0xFFFF;
263           bmf.active_streams--;
264           break;
265                 }
266         else if (event.cmd == 0xFE)
267                 {
268           bmf.channel[i].loop_position = bmf.channel[i].stream_position+1;
269           bmf.channel[i].loop_counter = event.cmd_data;
270                 }
271         else if (event.cmd == 0xFD)
272                 {
273           if (bmf.channel[i].loop_counter)
274           {
275             bmf.channel[i].stream_position = bmf.channel[i].loop_position-1;
276             bmf.channel[i].loop_counter--;
277           }
278                 }
279         else
280           break;
281
282         bmf.channel[i].stream_position++;
283           } // while (true)
284
285       // process normal event
286       unsigned short pos = bmf.channel[i].stream_position;
287
288       if (pos != 0xFFFF)
289       {
290         bmf.channel[i].delay = bmf.streams[i][pos].delay;
291
292         // command ?
293         if (bmf.streams[i][pos].cmd)
294                 {
295           unsigned char cmd = bmf.streams[i][pos].cmd;
296
297           // 0x01: Set Modulator Volume
298           if (cmd == 0x01)
299                   {
300             unsigned char reg = bmf_adlib_registers[13*i+2];
301
302             opl_write(reg, (adlib[reg] | 0x3F) - bmf.streams[i][pos].cmd_data);
303                   }
304           // 0x10: Set Speed
305                   else if (cmd == 0x10)
306                   {
307             plr.speed = bmf.streams[i][pos].cmd_data;
308                     plr.speed_counter = plr.speed;
309                   }
310                 } // if (bmf.streams[i][pos].cmd)
311
312         // instrument ?
313         if (bmf.streams[i][pos].instrument)
314                 {
315           unsigned char ins = bmf.streams[i][pos].instrument-1;
316
317           if (bmf.version != BMF1_1)
318             opl_write(0xB0+i, adlib[0xB0+i] & 0xDF);
319
320           for(int j=0;j<13;j++)
321             opl_write(bmf_adlib_registers[i*13+j], bmf.instruments[ins].data[j]);
322                 } // if (bmf.streams[i][pos].instrument)
323
324         // volume ?
325         if (bmf.streams[i][pos].volume)
326                 {
327           unsigned char vol = bmf.streams[i][pos].volume-1;
328           unsigned char reg = bmf_adlib_registers[13*i+3];
329
330           opl_write(reg, (adlib[reg] | 0x3F) - vol);
331                 } // if (bmf.streams[i][pos].volume)
332
333             // note ?
334         if (bmf.streams[i][pos].note)
335                 {
336           unsigned short note = bmf.streams[i][pos].note;
337           unsigned short freq = 0;
338
339           // mute channel
340           opl_write(0xB0+i, adlib[0xB0+i] & 0xDF);
341
342           // get frequency
343           if (bmf.version == BMF1_1)
344           {
345             if (note <= 0x60)
346               freq = bmf_notes_2[--note % 12];
347           }
348           else
349                   {
350             if (note != 0x7F)
351               freq = bmf_notes[--note % 12];
352                   }
353
354           // play note
355                   if (freq)
356           {
357             opl_write(0xB0+i, (freq >> 8) | ((note / 12) << 2) | 0x20);
358             opl_write(0xA0+i, freq & 0xFF);
359           }
360                 } // if (bmf.streams[i][pos].note)
361
362         bmf.channel[i].stream_position++;
363       } // if (pos != 0xFFFF)
364
365         } // if (!bmf.channel[i].delay)
366
367   // is module loop ?
368   if (!bmf.active_streams)
369   {
370     for(int j=0;j<9;j++)
371       bmf.channel[j].stream_position = 0;
372
373         bmf.active_streams = 9;
374
375     plr.looping = 1;
376   }
377 }
378
379 float CxadbmfPlayer::xadplayer_getrefresh()
380 {
381   return bmf.timer;
382 }
383
384 std::string CxadbmfPlayer::xadplayer_gettype()
385 {
386   return std::string("xad: BMF Adlib Tracker");
387 }
388
389 std::string CxadbmfPlayer::xadplayer_gettitle()
390 {
391   return std::string(bmf.title);
392 }
393
394 std::string CxadbmfPlayer::xadplayer_getauthor()
395 {
396   return std::string(bmf.author);
397 }
398
399 unsigned int CxadbmfPlayer::xadplayer_getinstruments()
400 {
401   return 32;
402 }
403
404 std::string CxadbmfPlayer::xadplayer_getinstrument(unsigned int i)
405 {
406   return std::string(bmf.instruments[i].name);
407 }
408
409 /* -------- Internal Functions ---------------------------- */
410
411 int CxadbmfPlayer::__bmf_convert_stream(unsigned char *stream, int channel)
412 {
413 #ifdef DEBUG
414   AdPlug_LogWrite("channel %02X (note,delay,volume,instrument,command,command_data):\n",channel);
415   unsigned char *last = stream;
416 #endif
417   unsigned char *stream_start = stream;
418
419   int pos = 0;
420
421   while (true)
422   {
423     memset(&bmf.streams[channel][pos], 0, sizeof(bmf_event));
424
425     bool is_cmd = false;
426
427     if (*stream == 0xFE)
428         {
429       // 0xFE -> 0xFF: End of Stream
430       bmf.streams[channel][pos].cmd = 0xFF;
431
432           stream++;
433
434       break;
435         }
436     else if (*stream == 0xFC)
437         {
438       // 0xFC -> 0xFE xx: Save Loop Position
439       bmf.streams[channel][pos].cmd = 0xFE;
440       bmf.streams[channel][pos].cmd_data = (*(stream+1) & ((bmf.version == BMF0_9B) ? 0x7F : 0x3F)) - 1;
441
442           stream+=2;
443     }
444     else if (*stream == 0x7D)
445         {
446       // 0x7D -> 0xFD: Loop Saved Position
447       bmf.streams[channel][pos].cmd = 0xFD;
448
449           stream++;
450         }
451         else
452     {
453       if (*stream & 0x80)                           
454       {
455                 if (*(stream+1) & 0x80)
456         {
457                   if (*(stream+1) & 0x40)
458           {
459             // byte0: 1aaaaaaa = NOTE
460             bmf.streams[channel][pos].note = *stream & 0x7F;
461             // byte1: 11bbbbbb = DELAY
462             bmf.streams[channel][pos].delay = *(stream+1) & 0x3F;
463             // byte2: cccccccc = COMMAND
464
465             stream+=2;
466
467             is_cmd = true;
468           }
469                   else
470           {
471             // byte0: 1aaaaaaa = NOTE
472             bmf.streams[channel][pos].note = *stream & 0x7F;
473             // byte1: 11bbbbbb = DELAY
474             bmf.streams[channel][pos].delay = *(stream+1) & 0x3F;
475
476                         stream+=2;
477           } // if (*(stream+1) & 0x40)
478                 }
479         else
480         {
481           // byte0: 1aaaaaaa = NOTE
482           bmf.streams[channel][pos].note = *stream & 0x7F;
483           // byte1: 0bbbbbbb = COMMAND
484
485           stream++;
486
487           is_cmd = true;
488         } // if (*(stream+1) & 0x80)
489           }
490           else
491       {
492         // byte0: 0aaaaaaa = NOTE
493         bmf.streams[channel][pos].note = *stream & 0x7F;
494
495                 stream++;
496       } // if (*stream & 0x80)
497     } // if (*stream == 0xFE)
498
499         // is command ?
500     if (is_cmd)
501     {
502
503       /* ALL */
504
505       if ((0x20 <= *stream) && (*stream <= 0x3F))
506       {
507         // 0x20 or higher; 0x3F or lower: Set Instrument 
508         bmf.streams[channel][pos].instrument = *stream - 0x20 + 1;
509
510                 stream++;
511       }
512       else if (0x40 <= *stream)
513       {
514         // 0x40 or higher: Set Volume
515         bmf.streams[channel][pos].volume = *stream - 0x40 + 1;
516
517                 stream++;
518       }
519       else
520       {
521
522         /* 0.9b */
523
524         if (bmf.version == BMF0_9B)
525         if (*stream < 0x20)
526                 {
527           // 0x1F or lower: ?
528                   stream++;
529                 }
530
531         /* 1.2 */
532
533         if (bmf.version == BMF1_2)
534         if (*stream == 0x01)
535                 {
536           // 0x01: Set Modulator Volume -> 0x01
537           bmf.streams[channel][pos].cmd = 0x01;
538           bmf.streams[channel][pos].cmd_data = *(stream+1);
539
540                   stream+=2;
541                 }
542         else if (*stream == 0x02)
543                 {
544           // 0x02: ?
545                   stream+=2;
546                 }
547         else if (*stream == 0x03)
548                 {
549           // 0x03: ?
550                   stream+=2;
551                 }
552         else if (*stream == 0x04)
553                 {
554           // 0x04: Set Speed -> 0x10
555           bmf.streams[channel][pos].cmd = 0x10;
556           bmf.streams[channel][pos].cmd_data = *(stream+1);
557
558           stream+=2;
559                 }
560         else if (*stream == 0x05)
561                 {
562           // 0x05: Set Carrier Volume (port 380)
563           bmf.streams[channel][pos].volume = *(stream+1) + 1;
564
565                   stream+=2;
566                 }
567         else if (*stream == 0x06)
568                 {
569           // 0x06: Set Carrier Volume (port 382)
570           bmf.streams[channel][pos].volume = *(stream+1) + 1;
571
572                   stream+=2;
573                 } // if (bmf.version == BMF1_2)
574
575       } // if ((0x20 <= *stream) && (*stream <= 0x3F))
576
577     } // if (is_cmd)
578
579 #ifdef DEBUG
580    AdPlug_LogWrite("%02X %02X %02X %02X %02X %02X  <----  ", 
581                         bmf.streams[channel][pos].note, 
582                         bmf.streams[channel][pos].delay,
583                         bmf.streams[channel][pos].volume, 
584                         bmf.streams[channel][pos].instrument,
585                         bmf.streams[channel][pos].cmd, 
586                         bmf.streams[channel][pos].cmd_data
587                    );
588    for(int zz=0;zz<(stream-last);zz++)
589      AdPlug_LogWrite("%02X ",last[zz]);
590    AdPlug_LogWrite("\n");
591    last=stream;
592 #endif
593     pos++;
594   } // while (true)
595
596   return (stream - stream_start);
597 }