1 /*
2  * Adplug - Replayer for many OPL2/OPL3 audio file formats.
3  * Copyright (C) 1999 - 2003 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  * adtrack.cpp - Adlib Tracker 1.0 Loader by Simon Peter <dn.tlp@gmx.net>
20  *
21  * NOTES:
22  * The original Adlib Tracker 1.0 is behaving a little different from the
23  * official spec: The 'octave' integer from the instrument file is stored
24  * "minus 1" from the actual value, underflowing from 0 to 0xffff.
25  *
26  * I also noticed that my player is playing everything transposed a few tones
27  * higher than the original tracker. As far as i can see, my player perfectly
28  * follows the official spec, so it "must" be the tracker that does something
29  * wrong here...
30  */
31 
32 #include <stdlib.h>
33 #include <string.h>
34 
35 #include "adtrack.h"
36 #include "debug.h"
37 
38 #include <limits.h>
39 #ifndef PATH_MAX
40 #define PATH_MAX    1024    /* max # of characters in a path name */
41 #endif
42 /*** Public methods ***/
43 
factory(Copl * newopl)44 CPlayer *CadtrackLoader::factory(Copl *newopl)
45 {
46   return new CadtrackLoader(newopl);
47 }
48 
load(const char * filename,const CFileProvider & fp)49 bool CadtrackLoader::load(const char * filename, const CFileProvider &fp)
50 {
51   binistream *f = fp.open(filename); if(!f) return false;
52   binistream *instf;
53   char note[2];
54   unsigned short rwp;
55   unsigned char chp, octave, pnote = 0;
56   int i,j;
57   AdTrackInst myinst;
58 
59   // file validation
60   if(!fp.extension(filename, ".sng") || fp.filesize(f) != 36000)
61     { fp.close(f); return false; }
62 
63   // check for instruments file
64   char instfilename[PATH_MAX];
65   strncpy (instfilename, filename, sizeof (instfilename)-5);
66   instfilename[PATH_MAX-5] = 0;
67   char *pext = strrchr (instfilename, '.');
68   if (pext) {
69       strcpy (pext, ".ins");
70   }
71   else {
72       strcat (instfilename, ".ins");
73   }
74   AdPlug_LogWrite("CadtrackLoader::load(,\"%s\"): Checking for \"%s\"...\n",
75 		  filename, instfilename);
76   instf = fp.open(instfilename);
77   if(!instf || fp.filesize(instf) != 468) { fp.close(f); return false; }
78 
79   // give CmodPlayer a hint on what we're up to
80   realloc_patterns(1,1000,9); realloc_instruments(9); realloc_order(1);
81   init_trackord(); flags = NoKeyOn;
82   (*order) = 0; length = 1; restartpos = 0; bpm = 120; initspeed = 3;
83 
84   // load instruments from instruments file
85   for(i=0;i<9;i++) {
86     for(j=0;j<2;j++) {
87       myinst.op[j].appampmod = instf->readInt(2);
88       myinst.op[j].appvib = instf->readInt(2);
89       myinst.op[j].maintsuslvl = instf->readInt(2);
90       myinst.op[j].keybscale = instf->readInt(2);
91       myinst.op[j].octave = instf->readInt(2);
92       myinst.op[j].freqrisevollvldn = instf->readInt(2);
93       myinst.op[j].softness = instf->readInt(2);
94       myinst.op[j].attack = instf->readInt(2);
95       myinst.op[j].decay = instf->readInt(2);
96       myinst.op[j].release = instf->readInt(2);
97       myinst.op[j].sustain = instf->readInt(2);
98       myinst.op[j].feedback = instf->readInt(2);
99       myinst.op[j].waveform = instf->readInt(2);
100     }
101     convert_instrument(i, &myinst);
102   }
103   fp.close(instf);
104 
105   // load file
106   for(rwp=0;rwp<1000;rwp++)
107     for(chp=0;chp<9;chp++) {
108       // read next record
109       f->readString(note, 2); octave = f->readInt(1); f->ignore();
110       switch(*note) {
111       case 'C': if(note[1] == '#') pnote = 2; else pnote = 1; break;
112       case 'D': if(note[1] == '#') pnote = 4; else pnote = 3; break;
113       case 'E': pnote = 5; break;
114       case 'F': if(note[1] == '#') pnote = 7; else pnote = 6; break;
115       case 'G': if(note[1] == '#') pnote = 9; else pnote = 8; break;
116       case 'A': if(note[1] == '#') pnote = 11; else pnote = 10; break;
117       case 'B': pnote = 12; break;
118       case '\0':
119 	if(note[1] == '\0')
120 	  tracks[chp][rwp].note = 127;
121 	else {
122 	  fp.close(f);
123 	  return false;
124 	}
125 	break;
126       default: fp.close(f); return false;
127       }
128       if((*note) != '\0') {
129 	tracks[chp][rwp].note = pnote + (octave * 12);
130 	tracks[chp][rwp].inst = chp + 1;
131       }
132     }
133 
134   fp.close(f);
135   rewind(0);
136   return true;
137 }
138 
getrefresh()139 float CadtrackLoader::getrefresh()
140 {
141   return 18.2f;
142 }
143 
144 /*** Private methods ***/
145 
convert_instrument(unsigned int n,AdTrackInst * i)146 void CadtrackLoader::convert_instrument(unsigned int n, AdTrackInst *i)
147 {
148   // Carrier "Amp Mod / Vib / Env Type / KSR / Multiple" register
149   inst[n].data[2] = i->op[Carrier].appampmod ? 1 << 7 : 0;
150   inst[n].data[2] += i->op[Carrier].appvib ? 1 << 6 : 0;
151   inst[n].data[2] += i->op[Carrier].maintsuslvl ? 1 << 5 : 0;
152   inst[n].data[2] += i->op[Carrier].keybscale ? 1 << 4 : 0;
153   inst[n].data[2] += (i->op[Carrier].octave + 1) & 0xffff; // Bug in original tracker
154   // Modulator...
155   inst[n].data[1] = i->op[Modulator].appampmod ? 1 << 7 : 0;
156   inst[n].data[1] += i->op[Modulator].appvib ? 1 << 6 : 0;
157   inst[n].data[1] += i->op[Modulator].maintsuslvl ? 1 << 5 : 0;
158   inst[n].data[1] += i->op[Modulator].keybscale ? 1 << 4 : 0;
159   inst[n].data[1] += (i->op[Modulator].octave + 1) & 0xffff; // Bug in original tracker
160 
161   // Carrier "Key Scaling / Level" register
162   inst[n].data[10] = (i->op[Carrier].freqrisevollvldn & 3) << 6;
163   inst[n].data[10] += i->op[Carrier].softness & 63;
164   // Modulator...
165   inst[n].data[9] = (i->op[Modulator].freqrisevollvldn & 3) << 6;
166   inst[n].data[9] += i->op[Modulator].softness & 63;
167 
168   // Carrier "Attack / Decay" register
169   inst[n].data[4] = (i->op[Carrier].attack & 0x0f) << 4;
170   inst[n].data[4] += i->op[Carrier].decay & 0x0f;
171   // Modulator...
172   inst[n].data[3] = (i->op[Modulator].attack & 0x0f) << 4;
173   inst[n].data[3] += i->op[Modulator].decay & 0x0f;
174 
175   // Carrier "Release / Sustain" register
176   inst[n].data[6] = (i->op[Carrier].release & 0x0f) << 4;
177   inst[n].data[6] += i->op[Carrier].sustain & 0x0f;
178   // Modulator...
179   inst[n].data[5] = (i->op[Modulator].release & 0x0f) << 4;
180   inst[n].data[5] += i->op[Modulator].sustain & 0x0f;
181 
182   // Channel "Feedback / Connection" register
183   inst[n].data[0] = (i->op[Carrier].feedback & 7) << 1;
184 
185   // Carrier/Modulator "Wave Select" registers
186   inst[n].data[8] = i->op[Carrier].waveform & 3;
187   inst[n].data[7] = i->op[Modulator].waveform & 3;
188 }
189