summaryrefslogtreecommitdiff
path: root/src/adplug/core/dmo.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/adplug/core/dmo.cc')
-rw-r--r--src/adplug/core/dmo.cc419
1 files changed, 0 insertions, 419 deletions
diff --git a/src/adplug/core/dmo.cc b/src/adplug/core/dmo.cc
deleted file mode 100644
index 72c0450..0000000
--- a/src/adplug/core/dmo.cc
+++ /dev/null
@@ -1,419 +0,0 @@
-/*
- Adplug - Replayer for many OPL2/OPL3 audio file formats.
- Copyright (C) 1999 - 2004, 2006 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
-
- dmo.cpp - TwinTeam loader by Riven the Mage <riven@ok.ru>
-*/
-/*
- NOTES:
- Panning is ignored.
-
- A WORD ist 16 bits, a DWORD is 32 bits and a BYTE is 8 bits in this context.
-*/
-
-#include <string.h>
-#include "binstr.h"
-
-#include "dmo.h"
-#include "debug.h"
-
-#define LOWORD(l) ((l) & 0xffff)
-#define HIWORD(l) ((l) >> 16)
-#define LOBYTE(w) ((w) & 0xff)
-#define HIBYTE(w) ((w) >> 8)
-
-#define ARRAY_AS_DWORD(a, i) \
-((a[i + 3] << 24) + (a[i + 2] << 16) + (a[i + 1] << 8) + a[i])
-#define ARRAY_AS_WORD(a, i) ((a[i + 1] << 8) + a[i])
-
-#define CHARP_AS_WORD(p) (((*(p + 1)) << 8) + (*p))
-
-/* -------- Public Methods -------------------------------- */
-
-CPlayer *CdmoLoader::factory(Copl *newopl)
-{
- return new CdmoLoader(newopl);
-}
-
-bool CdmoLoader::load(const std::string &filename, const CFileProvider &fp)
-{
- int i,j;
- binistream *f;
-
- // check header
- dmo_unpacker *unpacker = new dmo_unpacker;
- unsigned char chkhdr[16];
-
- if (!fp.extension(filename, ".dmo"))
- {
- delete unpacker;
- return false;
- }
-
- f = fp.open(filename);
- if (!f)
- {
- delete unpacker;
- return false;
- }
-
- f->readString((char *)chkhdr, 16);
-
- if (!unpacker->decrypt(chkhdr, 16))
- {
- delete unpacker;
- fp.close(f);
- return false;
- }
-
- // get file size
- long packed_length = fp.filesize(f);
- f->seek(0);
-
- unsigned char *packed_module = new unsigned char [packed_length];
-
- // load file
- f->readString((char *)packed_module, packed_length);
- fp.close(f);
-
- // decrypt
- unpacker->decrypt(packed_module,packed_length);
-
- long unpacked_length = 0x2000 * ARRAY_AS_WORD(packed_module, 12);
- unsigned char *module = new unsigned char [unpacked_length];
-
- // unpack
- if (!unpacker->unpack(packed_module+12,module,unpacked_length))
- {
- delete unpacker;
- delete [] packed_module;
- delete [] module;
- return false;
- }
-
- delete unpacker;
- delete [] packed_module;
-
- // "TwinTeam" - signed ?
- if (memcmp(module,"TwinTeam Module File""\x0D\x0A",22))
- {
- delete [] module;
- return false;
- }
-
- // load header
- binisstream uf(module, unpacked_length);
- uf.setFlag(binio::BigEndian, false); uf.setFlag(binio::FloatIEEE);
-
- memset(&header,0,sizeof(s3mheader));
-
- uf.ignore(22); // ignore DMO header ID string
- uf.readString(header.name, 28);
-
- uf.ignore(2); // _unk_1
- header.ordnum = uf.readInt(2);
- header.insnum = uf.readInt(2);
- header.patnum = uf.readInt(2);
- uf.ignore(2); // _unk_2
- header.is = uf.readInt(2);
- header.it = uf.readInt(2);
-
- memset(header.chanset,0xFF,32);
-
- for (i=0;i<9;i++)
- header.chanset[i] = 0x10 + i;
-
- uf.ignore(32); // ignore panning settings for all 32 channels
-
- // load orders
- for(i = 0; i < 256; i++) orders[i] = uf.readInt(1);
-
- orders[header.ordnum] = 0xFF;
-
- // load pattern lengths
- unsigned short my_patlen[100];
- for(i = 0; i < 100; i++) my_patlen[i] = uf.readInt(2);
-
- // load instruments
- for (i = 0; i < header.insnum; i++)
- {
- memset(&inst[i],0,sizeof(s3minst));
-
- uf.readString(inst[i].name, 28);
-
- inst[i].volume = uf.readInt(1);
- inst[i].dsk = uf.readInt(1);
- inst[i].c2spd = uf.readInt(4);
- inst[i].type = uf.readInt(1);
- inst[i].d00 = uf.readInt(1);
- inst[i].d01 = uf.readInt(1);
- inst[i].d02 = uf.readInt(1);
- inst[i].d03 = uf.readInt(1);
- inst[i].d04 = uf.readInt(1);
- inst[i].d05 = uf.readInt(1);
- inst[i].d06 = uf.readInt(1);
- inst[i].d07 = uf.readInt(1);
- inst[i].d08 = uf.readInt(1);
- inst[i].d09 = uf.readInt(1);
- inst[i].d0a = uf.readInt(1);
- /*
- * Originally, riven sets d0b = d0a and ignores 1 byte in the
- * stream, but i guess this was a typo, so i read it here.
- */
- inst[i].d0b = uf.readInt(1);
- }
-
- // load patterns
- for (i = 0; i < header.patnum; i++) {
- long cur_pos = uf.pos();
-
- for (j = 0; j < 64; j++) {
- while (1) {
- unsigned char token = uf.readInt(1);
-
- if (!token)
- break;
-
- unsigned char chan = token & 31;
-
- // note + instrument ?
- if (token & 32) {
- unsigned char bufbyte = uf.readInt(1);
-
- pattern[i][j][chan].note = bufbyte & 15;
- pattern[i][j][chan].oct = bufbyte >> 4;
- pattern[i][j][chan].instrument = uf.readInt(1);
- }
-
- // volume ?
- if (token & 64)
- pattern[i][j][chan].volume = uf.readInt(1);
-
- // command ?
- if (token & 128) {
- pattern[i][j][chan].command = uf.readInt(1);
- pattern[i][j][chan].info = uf.readInt(1);
- }
- }
- }
-
- uf.seek(cur_pos + my_patlen[i]);
- }
-
- delete [] module;
- rewind(0);
- return true;
-}
-
-std::string CdmoLoader::gettype()
-{
- return std::string("TwinTeam (packed S3M)");
-}
-
-std::string CdmoLoader::getauthor()
-{
- /*
- All available .DMO modules written by one composer. And because all .DMO
- stuff was lost due to hd crash (TwinTeam guys said this), there are
- never(?) be another.
- */
- return std::string("Benjamin GERARDIN");
-}
-
-/* -------- Private Methods ------------------------------- */
-
-unsigned short CdmoLoader::dmo_unpacker::brand(unsigned short range)
-{
- unsigned short ax,bx,cx,dx;
-
- ax = LOWORD(bseed);
- bx = HIWORD(bseed);
- cx = ax;
- ax = LOWORD(cx * 0x8405);
- dx = HIWORD(cx * 0x8405);
- cx <<= 3;
- cx = (((HIBYTE(cx) + LOBYTE(cx)) & 0xFF) << 8) + LOBYTE(cx);
- dx += cx;
- dx += bx;
- bx <<= 2;
- dx += bx;
- dx = (((HIBYTE(dx) + LOBYTE(bx)) & 0xFF) << 8) + LOBYTE(dx);
- bx <<= 5;
- dx = (((HIBYTE(dx) + LOBYTE(bx)) & 0xFF) << 8) + LOBYTE(dx);
- ax += 1;
- if (!ax) dx += 1;
-
- // leave it that way or amd64 might get it wrong
- bseed = dx;
- bseed <<= 16;
- bseed += ax;
-
- return HIWORD(HIWORD(LOWORD(bseed) * range) + HIWORD(bseed) * range);
-}
-
-bool CdmoLoader::dmo_unpacker::decrypt(unsigned char *buf, long len)
-{
- unsigned long seed = 0;
- int i;
-
- bseed = ARRAY_AS_DWORD(buf, 0);
-
- for (i=0; i < ARRAY_AS_WORD(buf, 4) + 1; i++)
- seed += brand(0xffff);
-
- bseed = seed ^ ARRAY_AS_DWORD(buf, 6);
-
- if (ARRAY_AS_WORD(buf, 10) != brand(0xffff))
- return false;
-
- for (i=0;i<(len-12);i++)
- buf[12+i] ^= brand(0x100);
-
- buf[len - 2] = buf[len - 1] = 0;
-
- return true;
-}
-
-short CdmoLoader::dmo_unpacker::unpack_block(unsigned char *ibuf, long ilen, unsigned char *obuf)
-{
- unsigned char code,par1,par2;
- unsigned short ax,bx,cx;
-
- unsigned char *ipos = ibuf;
- unsigned char *opos = obuf;
-
- // LZ77 child
- while (ipos - ibuf < ilen)
- {
- code = *ipos++;
-
- // 00xxxxxx: copy (xxxxxx + 1) bytes
- if ((code >> 6) == 0)
- {
- cx = (code & 0x3F) + 1;
-
- if(opos + cx >= oend)
- return -1;
-
- for (int i=0;i<cx;i++)
- *opos++ = *ipos++;
-
- continue;
- }
-
- // 01xxxxxx xxxyyyyy: copy (Y + 3) bytes from (X + 1)
- if ((code >> 6) == 1)
- {
- par1 = *ipos++;
-
- ax = ((code & 0x3F) << 3) + ((par1 & 0xE0) >> 5) + 1;
- cx = (par1 & 0x1F) + 3;
-
- if(opos + cx >= oend)
- return -1;
-
- for(int i=0;i<cx;i++) {
- *opos = *(opos - ax);
- opos++;
- }
-
- continue;
- }
-
- // 10xxxxxx xyyyzzzz: copy (Y + 3) bytes from (X + 1); copy Z bytes
- if ((code >> 6) == 2)
- {
- int i;
-
- par1 = *ipos++;
-
- ax = ((code & 0x3F) << 1) + (par1 >> 7) + 1;
- cx = ((par1 & 0x70) >> 4) + 3;
- bx = par1 & 0x0F;
-
- if(opos + bx + cx >= oend)
- return -1;
-
- for(i=0;i<cx;i++) {
- *opos = *(opos - ax);
- opos++;
- }
-
- for (i=0;i<bx;i++)
- *opos++ = *ipos++;
-
- continue;
- }
-
- // 11xxxxxx xxxxxxxy yyyyzzzz: copy (Y + 4) from X; copy Z bytes
- if ((code >> 6) == 3)
- {
- int i;
-
- par1 = *ipos++;
- par2 = *ipos++;
-
- bx = ((code & 0x3F) << 7) + (par1 >> 1);
- cx = ((par1 & 0x01) << 4) + (par2 >> 4) + 4;
- ax = par2 & 0x0F;
-
- if(opos + ax + cx >= oend)
- return -1;
-
- for(i=0;i<cx;i++) {
- *opos = *(opos - bx);
- opos++;
- }
-
- for (i=0;i<ax;i++)
- *opos++ = *ipos++;
-
- continue;
- }
- }
-
- return opos - obuf;
-}
-
-long CdmoLoader::dmo_unpacker::unpack(unsigned char *ibuf, unsigned char *obuf,
- unsigned long outputsize)
-{
- long olen = 0;
- unsigned short block_count = CHARP_AS_WORD(ibuf);
-
- ibuf += 2;
- unsigned char *block_length = ibuf;
- ibuf += 2 * block_count;
-
- oend = obuf + outputsize;
-
- for (int i=0;i<block_count;i++)
- {
- unsigned short bul = CHARP_AS_WORD(ibuf);
-
- if(unpack_block(ibuf + 2,CHARP_AS_WORD(block_length) - 2,obuf) != bul)
- return 0;
-
- obuf += bul;
- olen += bul;
-
- ibuf += CHARP_AS_WORD(block_length);
- block_length += 2;
- }
-
- return olen;
-}