Пример #1
0
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")) return false;
  f = fp.open(filename); if(!f) 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]);
  }
Пример #2
0
bool DmoPlayer::load(const std::string& filename)
{
    FileStream f(filename);
    if(!f || f.extension() != ".dmo")
        return false;

    unsigned char chkhdr[16];
    f.read(chkhdr, 16);

    DMOUnpacker unpacker;
    if(!unpacker.decrypt(chkhdr, 16))
    {
        return false;
    }

    f.seek(0);

    std::vector<uint8_t> packed_module(f.size());

    // load file
    f.read(packed_module.data(), f.size());

    // decrypt
    unpacker.decrypt(packed_module.data(), packed_module.size());

    const auto unpacked_length = 0x2000 * ARRAY_AS_WORD(packed_module.data(), 12);
    std::vector<uint8_t> module(unpacked_length);

    // unpack
    if(!unpacker.unpack(packed_module.data() + 12, module.data(), unpacked_length))
    {
        return false;
    }

    // "TwinTeam" - signed ?
    if(memcmp(module.data(), "TwinTeam Module File"
              "\x0D\x0A",
              22))
    {
        return false;
    }

    // load header
    MemoryStream uf;
    uf.write(module.data(), module.size());
    uf.seek(0);

    S3mHeader header;

    uf.seekrel(22); // ignore DMO header ID string
    uf.read(header.name, 28);

    uf.seekrel(2); // _unk_1
    uf >> header.orderCount >> header.instrumentCount >> header.patternCount;
    uf.seekrel(2); // _unk_2
    uf >> header.initialSpeed >> header.initialTempo;

    header.chanset.fill(0xff);

    for(int i = 0; i < 9; i++)
        header.chanset[i] = 0x10 + i;

    uf.seekrel(32); // ignore panning settings for all 32 channels

    // load orders
    for(int i = 0; i < header.orderCount; ++i)
    {
        uint8_t tmp;
        uf >> tmp;
        addOrder(tmp);
        std::cerr << "ORD=" << int(tmp) << "\n";
    }
    addOrder(0xff);
    uf.seekrel(256 - header.orderCount);

    // load pattern lengths
    uint16_t my_patlen[100];
    uf.read(my_patlen, 100);

    // load instruments
    for(int i = 0; i < header.instrumentCount; i++)
    {
        S3mInstrument instrument;

        uf.read(instrument.name, 28);

        uf >> instrument.volume;
        uf >> instrument.dsk;
        uf >> instrument.c2spd;
        uf >> instrument.type;
        uf >> instrument.d00;
        uf >> instrument.d01;
        uf >> instrument.d02;
        uf >> instrument.d03;
        uf >> instrument.d04;
        uf >> instrument.d05;
        uf >> instrument.d06;
        uf >> instrument.d07;
        uf >> instrument.d08;
        uf >> instrument.d09;
        uf >> instrument.d0a;
        /*
         * Originally, riven sets d0b = d0a and ignores 1 byte in the
         * stream, but i guess this was a typo, so i read it here.
         */
        uf >> instrument.d0b;

        setInstrument(i, instrument);
    }

    // load patterns
    for(int pattern = 0; pattern < header.patternCount; pattern++)
    {
        const auto cur_pos = uf.pos();

        for(int row = 0; row < 64; row++)
        {
            S3mCell* currentChannel = patternChannel(pattern, row);

            while(true)
            {
                uint8_t token;
                uf >> token;

                if(!token)
                    break;

                const auto chan = token & 31;

                // note + instrument ?
                if(token & 32)
                {
                    uint8_t bufbyte;
                    uf >> bufbyte;

                    currentChannel[chan].note = bufbyte & 15;
                    currentChannel[chan].octave = bufbyte >> 4;
                    uf >> currentChannel[chan].instrument;
                }

                // volume ?
                if(token & 64)
                    uf >> currentChannel[chan].volume;

                // command ?
                if(token & 128)
                {
                    uf >> currentChannel[chan].effect;
                    uf >> currentChannel[chan].effectValue;
                }
            }
        }