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