diff options
Diffstat (limited to 'src/adplug/core/a2m.cc')
-rw-r--r-- | src/adplug/core/a2m.cc | 484 |
1 files changed, 0 insertions, 484 deletions
diff --git a/src/adplug/core/a2m.cc b/src/adplug/core/a2m.cc deleted file mode 100644 index dd59a58..0000000 --- a/src/adplug/core/a2m.cc +++ /dev/null @@ -1,484 +0,0 @@ -/* - * Adplug - Replayer for many OPL2/OPL3 audio file formats. - * Copyright (C) 1999 - 2007 Simon Peter, <dn.tlp@gmx.net>, et al. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * a2m.cpp - A2M Loader by Simon Peter <dn.tlp@gmx.net> - * - * NOTES: - * This loader detects and loads version 1, 4, 5 & 8 files. - * - * version 1-4 files: - * Following commands are ignored: FF1 - FF9, FAx - FEx - * - * version 5-8 files: - * Instrument panning is ignored. Flags byte is ignored. - * Following commands are ignored: Gxy, Hxy, Kxy - &xy - */ - -#include <cstring> -#include "a2m.h" - -const unsigned int Ca2mLoader::MAXFREQ = 2000, -Ca2mLoader::MINCOPY = ADPLUG_A2M_MINCOPY, -Ca2mLoader::MAXCOPY = ADPLUG_A2M_MAXCOPY, -Ca2mLoader::COPYRANGES = ADPLUG_A2M_COPYRANGES, -Ca2mLoader::CODESPERRANGE = ADPLUG_A2M_CODESPERRANGE, -Ca2mLoader::TERMINATE = 256, -Ca2mLoader::FIRSTCODE = ADPLUG_A2M_FIRSTCODE, -Ca2mLoader::MAXCHAR = FIRSTCODE + COPYRANGES * CODESPERRANGE - 1, -Ca2mLoader::SUCCMAX = MAXCHAR + 1, -Ca2mLoader::TWICEMAX = ADPLUG_A2M_TWICEMAX, -Ca2mLoader::ROOT = 1, Ca2mLoader::MAXBUF = 42 * 1024, -Ca2mLoader::MAXDISTANCE = 21389, Ca2mLoader::MAXSIZE = 21389 + MAXCOPY; - -const unsigned short Ca2mLoader::bitvalue[14] = - {1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192}; - -const signed short Ca2mLoader::copybits[COPYRANGES] = - {4, 6, 8, 10, 12, 14}; - -const signed short Ca2mLoader::copymin[COPYRANGES] = - {0, 16, 80, 336, 1360, 5456}; - -CPlayer *Ca2mLoader::factory(Copl *newopl) -{ - return new Ca2mLoader(newopl); -} - -bool Ca2mLoader::load(const std::string &filename, const CFileProvider &fp) -{ - binistream *f = fp.open(filename); if(!f) return false; - char id[10]; - int i,j,k,t; - unsigned int l; - unsigned char *org = nullptr, *orgptr, flags = 0, numpats, version; - unsigned long alength; - unsigned short len[9], *secdata, *secptr; - const unsigned char convfx[16] = {0,1,2,23,24,3,5,4,6,9,17,13,11,19,7,14}; - const unsigned char convinf1[16] = {0,1,2,6,7,8,9,4,5,3,10,11,12,13,14,15}; - const unsigned char newconvfx[] = {0,1,2,3,4,5,6,23,24,21,10,11,17,13,7,19, - 255,255,22,25,255,15,255,255,255,255,255, - 255,255,255,255,255,255,255,255,14,255}; - - // read header - f->readString(id, 10); (void)f->readInt(4); - version = f->readInt(1); numpats = f->readInt(1); - - // file validation section - if(strncmp(id,"_A2module_",10) || (version != 1 && version != 5 && - version != 4 && version != 8)) { - fp.close(f); - return false; - } - - // load, depack & convert section - nop = numpats; length = 128; restartpos = 0; - if(version < 5) { - for(i=0;i<5;i++) len[i] = f->readInt(2); - t = 9; - } else { // version >= 5 - for(i=0;i<9;i++) len[i] = f->readInt(2); - t = 18; - } - - // block 0 - secdata = new unsigned short [len[0] / 2]; - if(version == 1 || version == 5) { - for(i=0;i<len[0]/2;i++) secdata[i] = f->readInt(2); - org = new unsigned char [MAXBUF]; orgptr = org; - sixdepak(secdata,org,len[0]); - } else { - orgptr = (unsigned char *)secdata; - for(i=0;i<len[0];i++) orgptr[i] = f->readInt(1); - } - memcpy(songname,orgptr,43); orgptr += 43; - memcpy(author,orgptr,43); orgptr += 43; - memcpy(instname,orgptr,250*33); orgptr += 250*33; - - for(i=0;i<250;i++) { // instruments - inst[i].data[0] = *(orgptr+i*13+10); - inst[i].data[1] = *(orgptr+i*13); - inst[i].data[2] = *(orgptr+i*13+1); - inst[i].data[3] = *(orgptr+i*13+4); - inst[i].data[4] = *(orgptr+i*13+5); - inst[i].data[5] = *(orgptr+i*13+6); - inst[i].data[6] = *(orgptr+i*13+7); - inst[i].data[7] = *(orgptr+i*13+8); - inst[i].data[8] = *(orgptr+i*13+9); - inst[i].data[9] = *(orgptr+i*13+2); - inst[i].data[10] = *(orgptr+i*13+3); - - if(version < 5) - inst[i].misc = *(orgptr+i*13+11); - else { // version >= 5 -> OPL3 format - int pan = *(orgptr+i*13+11); - - if(pan) - inst[i].data[0] |= (pan & 3) << 4; // set pan - else - inst[i].data[0] |= 48; // enable both speakers - } - - inst[i].slide = *(orgptr+i*13+12); - } - - orgptr += 250*13; - memcpy(order,orgptr,128); orgptr += 128; - bpm = *orgptr; orgptr++; - initspeed = *orgptr; orgptr++; - if(version >= 5) flags = *orgptr; - if(version == 1 || version == 5) delete [] org; - delete [] secdata; - - // blocks 1-4 or 1-8 - alength = len[1]; - for(i = 0; i < (version < 5 ? numpats / 16 : numpats / 8); i++) - alength += len[i+2]; - - secdata = new unsigned short [alength / 2]; - if(version == 1 || version == 5) { - for(l=0;l<alength/2;l++) secdata[l] = f->readInt(2); - org = new unsigned char [MAXBUF * (numpats / (version == 1 ? 16 : 8) + 1)]; - orgptr = org; secptr = secdata; - orgptr += sixdepak(secptr,orgptr,len[1]); secptr += len[1] / 2; - if(version == 1) { - if(numpats > 16) - { orgptr += sixdepak(secptr,orgptr,len[2]); secptr += len[2] / 2; } - if(numpats > 32) - { orgptr += sixdepak(secptr,orgptr,len[3]); secptr += len[3] / 2; } - if(numpats > 48) - sixdepak(secptr,orgptr,len[4]); - } else { - if(numpats > 8) - { orgptr += sixdepak(secptr,orgptr,len[2]); secptr += len[2] / 2; } - if(numpats > 16) - { orgptr += sixdepak(secptr,orgptr,len[3]); secptr += len[3] / 2; } - if(numpats > 24) - { orgptr += sixdepak(secptr,orgptr,len[4]); secptr += len[4] / 2; } - if(numpats > 32) - { orgptr += sixdepak(secptr,orgptr,len[5]); secptr += len[5] / 2; } - if(numpats > 40) - { orgptr += sixdepak(secptr,orgptr,len[6]); secptr += len[6] / 2; } - if(numpats > 48) - { orgptr += sixdepak(secptr,orgptr,len[7]); secptr += len[7] / 2; } - if(numpats > 56) - sixdepak(secptr,orgptr,len[8]); - } - delete [] secdata; - } else { - org = (unsigned char *)secdata; - for(l=0;l<alength;l++) org[l] = f->readInt(1); - } - - if(version < 5) { - for(i=0;i<numpats;i++) - for(j=0;j<64;j++) - for(k=0;k<9;k++) { - struct Tracks *track = &tracks[i * 9 + k][j]; - unsigned char *o = &org[i*64*t*4+j*t*4+k*4]; - - track->note = o[0] == 255 ? 127 : o[0]; - track->inst = o[1]; - track->command = convfx[o[2]]; - track->param2 = o[3] & 0x0f; - if(track->command != 14) - track->param1 = o[3] >> 4; - else { - track->param1 = convinf1[o[3] >> 4]; - if(track->param1 == 15 && !track->param2) { // convert key-off - track->command = 8; - track->param1 = 0; - track->param2 = 0; - } - } - if(track->command == 14) { - switch(track->param1) { - case 2: // convert define waveform - track->command = 25; - track->param1 = track->param2; - track->param2 = 0xf; - break; - case 8: // convert volume slide up - track->command = 26; - track->param1 = track->param2; - track->param2 = 0; - break; - case 9: // convert volume slide down - track->command = 26; - track->param1 = 0; - break; - } - } - } - } else { // version >= 5 - realloc_patterns(64, 64, 18); - - for(i=0;i<numpats;i++) - for(j=0;j<18;j++) - for(k=0;k<64;k++) { - struct Tracks *track = &tracks[i * 18 + j][k]; - unsigned char *o = &org[i*64*t*4+j*64*4+k*4]; - - track->note = o[0] == 255 ? 127 : o[0]; - track->inst = o[1]; - track->command = newconvfx[o[2]]; - track->param1 = o[3] >> 4; - track->param2 = o[3] & 0x0f; - - // Convert '&' command - if(o[2] == 36) - switch(track->param1) { - case 0: // pattern delay (frames) - track->command = 29; - track->param1 = 0; - // param2 already set correctly - break; - - case 1: // pattern delay (rows) - track->command = 14; - track->param1 = 8; - // param2 already set correctly - break; - } - } - } - - init_trackord(); - - if(version == 1 || version == 5) - delete [] org; - else - delete [] secdata; - - // Process flags - if(version >= 5) { - CmodPlayer::flags |= Opl3; // All versions >= 5 are OPL3 - if(flags & 8) CmodPlayer::flags |= Tremolo; // Tremolo depth - if(flags & 16) CmodPlayer::flags |= Vibrato; // Vibrato depth - } - - fp.close(f); - rewind(0); - return true; -} - -float Ca2mLoader::getrefresh() -{ - if(tempo != 18) - return (float) (tempo); - else - return 18.2f; -} - -/*** private methods *************************************/ - -void Ca2mLoader::inittree() -{ - unsigned short i; - - for(i=2;i<=TWICEMAX;i++) { - dad[i] = i / 2; - freq[i] = 1; - } - - for(i=1;i<=MAXCHAR;i++) { - leftc[i] = 2 * i; - rghtc[i] = 2 * i + 1; - } -} - -void Ca2mLoader::updatefreq(unsigned short a,unsigned short b) -{ - do { - freq[dad[a]] = freq[a] + freq[b]; - a = dad[a]; - if(a != ROOT) { - if(leftc[dad[a]] == a) - b = rghtc[dad[a]]; - else - b = leftc[dad[a]]; - } - } while(a != ROOT); - - if(freq[ROOT] == MAXFREQ) - for(a=1;a<=TWICEMAX;a++) - freq[a] >>= 1; -} - -void Ca2mLoader::updatemodel(unsigned short code) -{ - unsigned short a=code+SUCCMAX,b,c,code1,code2; - - freq[a]++; - if(dad[a] != ROOT) { - code1 = dad[a]; - if(leftc[code1] == a) - updatefreq(a,rghtc[code1]); - else - updatefreq(a,leftc[code1]); - - do { - code2 = dad[code1]; - if(leftc[code2] == code1) - b = rghtc[code2]; - else - b = leftc[code2]; - - if(freq[a] > freq[b]) { - if(leftc[code2] == code1) - rghtc[code2] = a; - else - leftc[code2] = a; - - if(leftc[code1] == a) { - leftc[code1] = b; - c = rghtc[code1]; - } else { - rghtc[code1] = b; - c = leftc[code1]; - } - - dad[b] = code1; - dad[a] = code2; - updatefreq(b,c); - a = b; - } - - a = dad[a]; - code1 = dad[a]; - } while(code1 != ROOT); - } -} - -unsigned short Ca2mLoader::inputcode(unsigned short bits) -{ - unsigned short i,code=0; - - for(i=1;i<=bits;i++) { - if(!ibitcount) { - if(ibitcount == MAXBUF) - ibufcount = 0; - ibitbuffer = wdbuf[ibufcount]; - ibufcount++; - ibitcount = 15; - } else - ibitcount--; - - if(ibitbuffer > 0x7fff) - code |= bitvalue[i-1]; - ibitbuffer <<= 1; - } - - return code; -} - -unsigned short Ca2mLoader::uncompress() -{ - unsigned short a=1; - - do { - if(!ibitcount) { - if(ibufcount == MAXBUF) - ibufcount = 0; - ibitbuffer = wdbuf[ibufcount]; - ibufcount++; - ibitcount = 15; - } else - ibitcount--; - - if(ibitbuffer > 0x7fff) - a = rghtc[a]; - else - a = leftc[a]; - ibitbuffer <<= 1; - } while(a <= MAXCHAR); - - a -= SUCCMAX; - updatemodel(a); - return a; -} - -void Ca2mLoader::decode() -{ - unsigned short i,j,k,t,c,count=0,dist,len,index; - - inittree(); - c = uncompress(); - - while(c != TERMINATE) { - if(c < 256) { - obuf[obufcount] = (unsigned char)c; - obufcount++; - if(obufcount == MAXBUF) { - output_size = MAXBUF; - obufcount = 0; - } - - buf[count] = (unsigned char)c; - count++; - if(count == MAXSIZE) - count = 0; - } else { - t = c - FIRSTCODE; - index = t / CODESPERRANGE; - len = t + MINCOPY - index * CODESPERRANGE; - dist = inputcode(copybits[index]) + len + copymin[index]; - - j = count; - k = count - dist; - if(count < dist) - k += MAXSIZE; - - for(i=0;i<=len-1;i++) { - obuf[obufcount] = buf[k]; - obufcount++; - if(obufcount == MAXBUF) { - output_size = MAXBUF; - obufcount = 0; - } - - buf[j] = buf[k]; - j++; k++; - if(j == MAXSIZE) j = 0; - if(k == MAXSIZE) k = 0; - } - - count += len; - if(count >= MAXSIZE) - count -= MAXSIZE; - } - c = uncompress(); - } - output_size = obufcount; -} - -unsigned short Ca2mLoader::sixdepak(unsigned short *source, unsigned char *dest, - unsigned short size) -{ - if((unsigned int)size + 4096 > MAXBUF) - return 0; - - buf = new unsigned char [MAXSIZE]; - input_size = size; - ibitcount = 0; ibitbuffer = 0; - obufcount = 0; ibufcount = 0; - wdbuf = source; obuf = dest; - - decode(); - delete [] buf; - return output_size; -} |