Mercurial > audlegacy
annotate Plugins/Input/adplug/core/ksm.cpp @ 713:cf7b5a288564 trunk
[svn] rule for installing data
| author | nenolod |
|---|---|
| date | Sun, 26 Feb 2006 20:14:08 -0800 |
| parents | 2b06eb5e472d |
| children | ddb6e5dac908 |
| rev | line source |
|---|---|
| 359 | 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 * ksm.cpp - KSM Player for AdPlug by Simon Peter <dn.tlp@gmx.net> | |
| 20 */ | |
| 21 | |
| 22 #include <string.h> | |
| 23 | |
| 24 #include "ksm.h" | |
| 25 #include "debug.h" | |
| 26 | |
| 27 const unsigned int CksmPlayer::adlibfreq[63] = { | |
| 28 0, | |
| 29 2390,2411,2434,2456,2480,2506,2533,2562,2592,2625,2659,2695, | |
| 30 3414,3435,3458,3480,3504,3530,3557,3586,3616,3649,3683,3719, | |
| 31 4438,4459,4482,4504,4528,4554,4581,4610,4640,4673,4707,4743, | |
| 32 5462,5483,5506,5528,5552,5578,5605,5634,5664,5697,5731,5767, | |
| 33 6486,6507,6530,6552,6576,6602,6629,6658,6688,6721,6755,6791, | |
| 34 7510}; | |
| 35 | |
| 36 /*** public methods **************************************/ | |
| 37 | |
| 38 CPlayer *CksmPlayer::factory(Copl *newopl) | |
| 39 { | |
| 40 return new CksmPlayer(newopl); | |
| 41 } | |
| 42 | |
| 43 bool CksmPlayer::load(const std::string &filename, const CFileProvider &fp) | |
| 44 { | |
| 45 binistream *f; | |
| 46 int i; | |
| 47 char *fn = new char[filename.length() + 9]; | |
| 48 | |
| 49 // file validation section | |
| 50 if(!fp.extension(filename, ".ksm")) { | |
| 51 AdPlug_LogWrite("CksmPlayer::load(,\"%s\"): File doesn't have '.ksm' " | |
| 52 "extension! Rejected!\n", filename.c_str()); | |
| 53 return false; | |
| 54 } | |
| 55 AdPlug_LogWrite("*** CksmPlayer::load(,\"%s\") ***\n", filename.c_str()); | |
| 56 | |
| 57 // Load instruments from 'insts.dat' | |
| 58 strcpy(fn, filename.c_str()); | |
| 59 for(i = strlen(fn) - 1; i >= 0; i--) | |
| 60 if(fn[i] == '/' || fn[i] == '\\') | |
| 61 break; | |
| 62 strcpy(fn + i + 1, "insts.dat"); | |
| 63 AdPlug_LogWrite("Instruments file: \"%s\"\n", fn); | |
| 64 f = fp.open(fn); | |
| 65 delete [] fn; | |
| 66 if(!f) { | |
| 67 AdPlug_LogWrite("Couldn't open instruments file! Aborting!\n"); | |
| 68 AdPlug_LogWrite("--- CksmPlayer::load ---\n"); | |
| 69 return false; | |
| 70 } | |
| 71 loadinsts(f); | |
| 72 fp.close(f); | |
| 73 | |
| 74 f = fp.open(filename); if(!f) return false; | |
| 75 for(i = 0; i < 16; i++) trinst[i] = f->readInt(1); | |
| 76 for(i = 0; i < 16; i++) trquant[i] = f->readInt(1); | |
| 77 for(i = 0; i < 16; i++) trchan[i] = f->readInt(1); | |
| 78 f->ignore(16); | |
| 79 for(i = 0; i < 16; i++) trvol[i] = f->readInt(1); | |
| 80 numnotes = f->readInt(2); | |
| 81 note = new unsigned long [numnotes]; | |
| 82 for(i = 0; i < numnotes; i++) note[i] = f->readInt(4); | |
| 83 fp.close(f); | |
| 84 | |
| 85 if(!trchan[11]) { | |
| 86 drumstat = 0; | |
| 87 numchans = 9; | |
| 88 } else { | |
| 89 drumstat = 32; | |
| 90 numchans = 6; | |
| 91 } | |
| 92 | |
| 93 rewind(0); | |
| 94 AdPlug_LogWrite("--- CksmPlayer::load ---\n"); | |
| 95 return true; | |
| 96 } | |
| 97 | |
| 98 bool CksmPlayer::update() | |
| 99 { | |
|
637
2b06eb5e472d
[svn] Sync with upstream. Drop hardware OPL2/3 support, it throws warnings and is not used on most modern machines. Added var inits where GCC 4.0 thought it was a good idea.
chainsaw
parents:
359
diff
changeset
|
100 int quanter,chan=0,drumnum=0,freq,track,volevel,volval; |
| 359 | 101 unsigned int i,j,bufnum; |
| 102 unsigned long temp,templong; | |
| 103 | |
| 104 count++; | |
| 105 if (count >= countstop) | |
| 106 { | |
| 107 bufnum = 0; | |
| 108 while (count >= countstop) | |
| 109 { | |
| 110 templong = note[nownote]; | |
| 111 track = (int)((templong>>8)&15); | |
| 112 if ((templong&192) == 0) | |
| 113 { | |
| 114 i = 0; | |
| 115 while (((chanfreq[i] != (templong&63)) || (chantrack[i] != ((templong>>8)&15))) && (i < numchans)) | |
| 116 i++; | |
| 117 if (i < numchans) | |
| 118 { | |
| 119 databuf[bufnum] = (char)0; bufnum++; | |
| 120 databuf[bufnum] = (unsigned char)(0xb0+i); bufnum++; | |
| 121 databuf[bufnum] = (unsigned char)((adlibfreq[templong&63]>>8)&223); bufnum++; | |
| 122 chanfreq[i] = 0; | |
| 123 chanage[i] = 0; | |
| 124 } | |
| 125 } | |
| 126 else | |
| 127 { | |
| 128 volevel = trvol[track]; | |
| 129 if ((templong&192) == 128) | |
| 130 { | |
| 131 volevel -= 4; | |
| 132 if (volevel < 0) | |
| 133 volevel = 0; | |
| 134 } | |
| 135 if ((templong&192) == 192) | |
| 136 { | |
| 137 volevel += 4; | |
| 138 if (volevel > 63) | |
| 139 volevel = 63; | |
| 140 } | |
| 141 if (track < 11) | |
| 142 { | |
| 143 temp = 0; | |
| 144 i = numchans; | |
| 145 for(j=0;j<numchans;j++) | |
| 146 if ((countstop - chanage[j] >= temp) && (chantrack[j] == track)) | |
| 147 { | |
| 148 temp = countstop - chanage[j]; | |
| 149 i = j; | |
| 150 } | |
| 151 if (i < numchans) | |
| 152 { | |
| 153 databuf[bufnum] = (char)0, bufnum++; | |
| 154 databuf[bufnum] = (unsigned char)(0xb0+i); bufnum++; | |
| 155 databuf[bufnum] = (unsigned char)0; bufnum++; | |
| 156 volval = (inst[trinst[track]][1]&192)+(volevel^63); | |
| 157 databuf[bufnum] = (char)0, bufnum++; | |
| 158 databuf[bufnum] = (unsigned char)(0x40+op_table[i]+3); bufnum++; | |
| 159 databuf[bufnum] = (unsigned char)volval; bufnum++; | |
| 160 databuf[bufnum] = (char)0, bufnum++; | |
| 161 databuf[bufnum] = (unsigned char)(0xa0+i); bufnum++; | |
| 162 databuf[bufnum] = (unsigned char)(adlibfreq[templong&63]&255); bufnum++; | |
| 163 databuf[bufnum] = (char)0, bufnum++; | |
| 164 databuf[bufnum] = (unsigned char)(0xb0+i); bufnum++; | |
| 165 databuf[bufnum] = (unsigned char)((adlibfreq[templong&63]>>8)|32); bufnum++; | |
| 166 chanfreq[i] = templong&63; | |
| 167 chanage[i] = countstop; | |
| 168 } | |
| 169 } | |
| 170 else if ((drumstat&32) > 0) | |
| 171 { | |
| 172 freq = adlibfreq[templong&63]; | |
| 173 switch(track) | |
| 174 { | |
| 175 case 11: drumnum = 16; chan = 6; freq -= 2048; break; | |
| 176 case 12: drumnum = 8; chan = 7; freq -= 2048; break; | |
| 177 case 13: drumnum = 4; chan = 8; break; | |
| 178 case 14: drumnum = 2; chan = 8; break; | |
| 179 case 15: drumnum = 1; chan = 7; freq -= 2048; break; | |
| 180 } | |
| 181 databuf[bufnum] = (char)0, bufnum++; | |
| 182 databuf[bufnum] = (unsigned char)(0xa0+chan); bufnum++; | |
| 183 databuf[bufnum] = (unsigned char)(freq&255); bufnum++; | |
| 184 databuf[bufnum] = (char)0, bufnum++; | |
| 185 databuf[bufnum] = (unsigned char)(0xb0+chan); bufnum++; | |
| 186 databuf[bufnum] = (unsigned char)((freq>>8)&223); bufnum++; | |
| 187 databuf[bufnum] = (char)0, bufnum++; | |
| 188 databuf[bufnum] = (unsigned char)(0xbd); bufnum++; | |
| 189 databuf[bufnum] = (unsigned char)(drumstat&(255-drumnum)); bufnum++; | |
| 190 drumstat |= drumnum; | |
| 191 if ((track == 11) || (track == 12) || (track == 14)) | |
| 192 { | |
| 193 volval = (inst[trinst[track]][1]&192)+(volevel^63); | |
| 194 databuf[bufnum] = (char)0, bufnum++; | |
| 195 databuf[bufnum] = (unsigned char)(0x40+op_table[chan]+3); bufnum++; | |
| 196 databuf[bufnum] = (unsigned char)(volval); bufnum++; | |
| 197 } | |
| 198 else | |
| 199 { | |
| 200 volval = (inst[trinst[track]][6]&192)+(volevel^63); | |
| 201 databuf[bufnum] = (char)0, bufnum++; | |
| 202 databuf[bufnum] = (unsigned char)(0x40+op_table[chan]); bufnum++; | |
| 203 databuf[bufnum] = (unsigned char)(volval); bufnum++; | |
| 204 } | |
| 205 databuf[bufnum] = (char)0, bufnum++; | |
| 206 databuf[bufnum] = (unsigned char)(0xbd); bufnum++; | |
| 207 databuf[bufnum] = (unsigned char)(drumstat); bufnum++; | |
| 208 } | |
| 209 } | |
| 210 nownote++; | |
| 211 if (nownote >= numnotes) { | |
| 212 nownote = 0; | |
| 213 songend = true; | |
| 214 } | |
| 215 templong = note[nownote]; | |
| 216 if (nownote == 0) | |
| 217 count = (templong>>12)-1; | |
| 218 quanter = (240/trquant[(templong>>8)&15]); | |
| 219 countstop = (((templong>>12)+(quanter>>1)) / quanter) * quanter; | |
| 220 } | |
| 221 for(i=0;i<bufnum;i+=3) | |
| 222 opl->write(databuf[i+1],databuf[i+2]); | |
| 223 } | |
| 224 return !songend; | |
| 225 } | |
| 226 | |
| 227 void CksmPlayer::rewind(int subsong) | |
| 228 { | |
| 229 unsigned int i,j,k; | |
| 230 unsigned char instbuf[11]; | |
| 231 unsigned long templong; | |
| 232 | |
| 233 songend = false; | |
| 234 opl->init(); opl->write(1,32); opl->write(4,0); opl->write(8,0); opl->write(0xbd,drumstat); | |
| 235 | |
| 236 if (trchan[11] == 1) { | |
| 237 for(i=0;i<11;i++) | |
| 238 instbuf[i] = inst[trinst[11]][i]; | |
| 239 instbuf[1] = ((instbuf[1]&192)|(trvol[11])^63); | |
| 240 setinst(6,instbuf[0],instbuf[1],instbuf[2],instbuf[3],instbuf[4],instbuf[5],instbuf[6],instbuf[7],instbuf[8],instbuf[9],instbuf[10]); | |
| 241 for(i=0;i<5;i++) | |
| 242 instbuf[i] = inst[trinst[12]][i]; | |
| 243 for(i=5;i<11;i++) | |
| 244 instbuf[i] = inst[trinst[15]][i]; | |
| 245 instbuf[1] = ((instbuf[1]&192)|(trvol[12])^63); | |
| 246 instbuf[6] = ((instbuf[6]&192)|(trvol[15])^63); | |
| 247 setinst(7,instbuf[0],instbuf[1],instbuf[2],instbuf[3],instbuf[4],instbuf[5],instbuf[6],instbuf[7],instbuf[8],instbuf[9],instbuf[10]); | |
| 248 for(i=0;i<5;i++) | |
| 249 instbuf[i] = inst[trinst[14]][i]; | |
| 250 for(i=5;i<11;i++) | |
| 251 instbuf[i] = inst[trinst[13]][i]; | |
| 252 instbuf[1] = ((instbuf[1]&192)|(trvol[14])^63); | |
| 253 instbuf[6] = ((instbuf[6]&192)|(trvol[13])^63); | |
| 254 setinst(8,instbuf[0],instbuf[1],instbuf[2],instbuf[3],instbuf[4],instbuf[5],instbuf[6],instbuf[7],instbuf[8],instbuf[9],instbuf[10]); | |
| 255 } | |
| 256 | |
| 257 for(i=0;i<numchans;i++) | |
| 258 { | |
| 259 chantrack[i] = 0; | |
| 260 chanage[i] = 0; | |
| 261 } | |
| 262 j = 0; | |
| 263 for(i=0;i<16;i++) | |
| 264 if ((trchan[i] > 0) && (j < numchans)) | |
| 265 { | |
| 266 k = trchan[i]; | |
| 267 while ((j < numchans) && (k > 0)) | |
| 268 { | |
| 269 chantrack[j] = i; | |
| 270 k--; | |
| 271 j++; | |
| 272 } | |
| 273 } | |
| 274 for(i=0;i<numchans;i++) | |
| 275 { | |
| 276 for(j=0;j<11;j++) | |
| 277 instbuf[j] = inst[trinst[chantrack[i]]][j]; | |
| 278 instbuf[1] = ((instbuf[1]&192)|(63-trvol[chantrack[i]])); | |
| 279 setinst(i,instbuf[0],instbuf[1],instbuf[2],instbuf[3],instbuf[4],instbuf[5],instbuf[6],instbuf[7],instbuf[8],instbuf[9],instbuf[10]); | |
| 280 chanfreq[i] = 0; | |
| 281 } | |
| 282 k = 0; | |
| 283 templong = *note; | |
| 284 count = (templong>>12)-1; | |
| 285 countstop = (templong>>12)-1; | |
| 286 nownote = 0; | |
| 287 } | |
| 288 | |
| 289 std::string CksmPlayer::getinstrument(unsigned int n) | |
| 290 { | |
| 291 if(trchan[n]) | |
| 292 return std::string(instname[trinst[n]]); | |
| 293 else | |
| 294 return std::string(); | |
| 295 } | |
| 296 | |
| 297 /*** private methods *************************************/ | |
| 298 | |
| 299 void CksmPlayer::loadinsts(binistream *f) | |
| 300 { | |
| 301 int i, j; | |
| 302 | |
| 303 for(i = 0; i < 256; i++) { | |
| 304 f->readString(instname[i], 20); | |
| 305 for(j = 0; j < 11; j++) inst[i][j] = f->readInt(1); | |
| 306 f->ignore(2); | |
| 307 } | |
| 308 } | |
| 309 | |
| 310 void CksmPlayer::setinst(int chan, | |
| 311 unsigned char v0,unsigned char v1,unsigned char v2, | |
| 312 unsigned char v3,unsigned char v4,unsigned char v5, | |
| 313 unsigned char v6,unsigned char v7,unsigned char v8, | |
| 314 unsigned char v9,unsigned char v10) | |
| 315 { | |
| 316 int offs; | |
| 317 | |
| 318 opl->write(0xa0+chan,0); | |
| 319 opl->write(0xb0+chan,0); | |
| 320 opl->write(0xc0+chan,v10); | |
| 321 offs = op_table[chan]; | |
| 322 opl->write(0x20+offs,v5); | |
| 323 opl->write(0x40+offs,v6); | |
| 324 opl->write(0x60+offs,v7); | |
| 325 opl->write(0x80+offs,v8); | |
| 326 opl->write(0xe0+offs,v9); | |
| 327 offs+=3; | |
| 328 opl->write(0x20+offs,v0); | |
| 329 opl->write(0x40+offs,v1); | |
| 330 opl->write(0x60+offs,v2); | |
| 331 opl->write(0x80+offs,v3); | |
| 332 opl->write(0xe0+offs,v4); | |
| 333 } |
