Beispiel #1
0
bool CadtrackLoader::load(const std::string &filename, const CFileProvider &fp)
{
  binistream *f = fp.open(filename); if(!f) return false;
  binistream *instf;
  char note[2];
  unsigned short rwp;
  unsigned char chp, octave, pnote = 0;
  int i,j;
  AdTrackInst myinst;

  // file validation
  if(!fp.extension(filename, ".sng") || fp.filesize(f) != 36000)
    { fp.close(f); return false; }

  // check for instruments file
  std::string instfilename(filename, 0, filename.find_last_of('.'));
  instfilename += ".ins";
  AdPlug_LogWrite("CadtrackLoader::load(,\"%s\"): Checking for \"%s\"...\n",
		  filename.c_str(), instfilename.c_str());
  instf = fp.open(instfilename);
  if(!instf || fp.filesize(instf) != 468) { fp.close(f); return false; }

  // give CmodPlayer a hint on what we're up to
  realloc_patterns(1,1000,9); realloc_instruments(9); realloc_order(1);
  init_trackord(); flags = NoKeyOn;
  (*order) = 0; length = 1; restartpos = 0; bpm = 120; initspeed = 3;

  // load instruments from instruments file
  for(i=0;i<9;i++) {
    for(j=0;j<2;j++) {
      myinst.op[j].appampmod = instf->readInt(2);
      myinst.op[j].appvib = instf->readInt(2);
      myinst.op[j].maintsuslvl = instf->readInt(2);
      myinst.op[j].keybscale = instf->readInt(2);
      myinst.op[j].octave = instf->readInt(2);
      myinst.op[j].freqrisevollvldn = instf->readInt(2);
      myinst.op[j].softness = instf->readInt(2);
      myinst.op[j].attack = instf->readInt(2);
      myinst.op[j].decay = instf->readInt(2);
      myinst.op[j].release = instf->readInt(2);
      myinst.op[j].sustain = instf->readInt(2);
      myinst.op[j].feedback = instf->readInt(2);
      myinst.op[j].waveform = instf->readInt(2);
    }
    convert_instrument(i, &myinst);
  }
  fp.close(instf);

  // load file
  for(rwp=0;rwp<1000;rwp++)
    for(chp=0;chp<9;chp++) {
      // read next record
      f->readString(note, 2); octave = f->readInt(1); f->ignore();
      switch(*note) {
      case 'C': if(note[1] == '#') pnote = 2; else pnote = 1; break;
      case 'D': if(note[1] == '#') pnote = 4; else pnote = 3; break;
      case 'E': pnote = 5; break;
      case 'F': if(note[1] == '#') pnote = 7; else pnote = 6; break;
      case 'G': if(note[1] == '#') pnote = 9; else pnote = 8; break;
      case 'A': if(note[1] == '#') pnote = 11; else pnote = 10; break;
      case 'B': pnote = 12; break;
      case '\0':
	if(note[1] == '\0')
	  tracks[chp][rwp].note = 127;
	else {
	  fp.close(f);
	  return false;
	}
	break;
      default: fp.close(f); return false;
      }
      if((*note) != '\0') {
	tracks[chp][rwp].note = pnote + (octave * 12);
	tracks[chp][rwp].inst = chp + 1;
      }
    }

  fp.close(f);
  rewind(0);
  return true;
}
Beispiel #2
0
bool CmadLoader::load(const std::string &filename, const CFileProvider &fp)
{
  binistream *f = fp.open(filename); if(!f) return false;
  const unsigned char conv_inst[10] = { 2,1,10,9,4,3,6,5,8,7 };
  unsigned int i, j, k, t = 0;

  // 'MAD+' - signed ?
  char id[4]; f->readString(id, 4);
  if (strncmp(id,"MAD+",4)) { fp.close(f); return false; }

  // load instruments
  for(i = 0; i < 9; i++) {
    f->readString(instruments[i].name, 8);
    for(j = 0; j < 12; j++) instruments[i].data[j] = f->readInt(1);
  }

  f->ignore(1);

  // data for Protracker
  length = f->readInt(1); nop = f->readInt(1); timer = f->readInt(1);

  // init CmodPlayer
  realloc_instruments(9);
  realloc_order(length);
  realloc_patterns(nop,32,9);
  init_trackord();

  // load tracks
  for(i = 0; i < nop; i++)
    for(k = 0; k < 32; k++)
      for(j = 0; j < 9; j++) {
	t = i * 9 + j;

	// read event
	unsigned char event = f->readInt(1);

	// convert event
	if (event < 0x61)
	  tracks[t][k].note = event;
	if (event == 0xFF) // 0xFF: Release note
	  tracks[t][k].command = 8;
	if (event == 0xFE) // 0xFE: Pattern Break
	  tracks[t][k].command = 13;
      }

  // load order
  for(i = 0; i < length; i++) order[i] = f->readInt(1) - 1;

  fp.close(f);

  // convert instruments
  for(i = 0; i < 9; i++)
    for(j = 0; j < 10; j++)
      inst[i].data[conv_inst[j]] = instruments[i].data[j];

  // data for Protracker
  restartpos = 0;
  initspeed = 1;

  rewind(0);
  return true;
}
Beispiel #3
0
bool CcffLoader::load(const std::string &filename, const CFileProvider &fp)
{
  binistream *f = fp.open(filename); if(!f) return false;
  const unsigned char conv_inst[11] = { 2,1,10,9,4,3,6,5,0,8,7 };
  const unsigned short conv_note[12] = { 0x16B, 0x181, 0x198, 0x1B0, 0x1CA, 0x1E5, 0x202, 0x220, 0x241, 0x263, 0x287, 0x2AE };

  int i,j,k,t=0;

  // '<CUD-FM-File>' - signed ?
  f->readString(header.id, 16);
  header.version = f->readInt(1); header.size = f->readInt(2);
  header.packed = f->readInt(1); f->readString((char *)header.reserved, 12);
  if (memcmp(header.id,"<CUD-FM-File>""\x1A\xDE\xE0",16))
    { fp.close(f); return false; }

  unsigned char *module = new unsigned char [0x10000];

  // packed ?
  if (header.packed)
    {
      cff_unpacker *unpacker = new cff_unpacker;

      unsigned char *packed_module = new unsigned char [header.size + 4];

      memset(packed_module,0,header.size + 4);

      f->readString((char *)packed_module, header.size);
      fp.close(f);

      if (!unpacker->unpack(packed_module,module))
	{
	  delete unpacker;
	  delete [] packed_module;
	  delete [] module;
	  return false;
	}

      delete unpacker;
      delete [] packed_module;

      if (memcmp(&module[0x5E1],"CUD-FM-File - SEND A POSTCARD -",31))
	{
	  delete [] module;
	  return false;
	}
    }
  else
    {
      f->readString((char *)module, header.size);
      fp.close(f);
    }

  // init CmodPlayer
  realloc_instruments(47);
  realloc_order(64);
  realloc_patterns(36,64,9);
  init_notetable(conv_note);
  init_trackord();

  // load instruments
  for (i=0;i<47;i++)
    {
      memcpy(&instruments[i],&module[i*32],sizeof(cff_instrument));

      for (j=0;j<11;j++)
	inst[i].data[conv_inst[j]] = instruments[i].data[j];

      instruments[i].name[20] = 0;
    }

  // number of patterns
  nop = module[0x5E0];

  // load title & author
  memcpy(song_title,&module[0x614],20);
  memcpy(song_author,&module[0x600],20);

  // load order
  memcpy(order,&module[0x628],64);

  // load tracks
  for (i=0;i<nop;i++)
    {
      unsigned char old_event_byte2[9];

      memset(old_event_byte2,0,9);

      for (j=0;j<9;j++)
	{
	  for (k=0;k<64;k++)
	    {
	      cff_event *event = (cff_event *)&module[0x669 + ((i*64+k)*9+j)*3];

	      // convert note
	      if (event->byte0 == 0x6D)
		tracks[t][k].note = 127;
	      else
		if (event->byte0)
		  tracks[t][k].note = event->byte0;

	      if (event->byte2)
		old_event_byte2[j] = event->byte2;

	      // convert effect
	      switch (event->byte1)
		{
		case 'I': // set instrument
		  tracks[t][k].inst = event->byte2 + 1;
		  tracks[t][k].param1 = tracks[t][k].param2 = 0;
		  break;

		case 'H': // set tempo
		  tracks[t][k].command = 7;
		  if (event->byte2 < 16)
		    {
		      tracks[t][k].param1 = 0x07;
		      tracks[t][k].param2 = 0x0D;
		    }
		  break;

		case 'A': // set speed
		  tracks[t][k].command = 19;
		  tracks[t][k].param1  = event->byte2 >> 4;
		  tracks[t][k].param2  = event->byte2 & 15;
		  break;

		case 'L': // pattern break
		  tracks[t][k].command = 13;
		  tracks[t][k].param1  = event->byte2 >> 4;
		  tracks[t][k].param2  = event->byte2 & 15;
		  break;

		case 'K': // order jump
		  tracks[t][k].command = 11;
		  tracks[t][k].param1  = event->byte2 >> 4;
		  tracks[t][k].param2  = event->byte2 & 15;
		  break;

		case 'M': // set vibrato/tremolo
		  tracks[t][k].command = 27;
		  tracks[t][k].param1  = event->byte2 >> 4;
		  tracks[t][k].param2  = event->byte2 & 15;
		  break;

		case 'C': // set modulator volume
		  tracks[t][k].command = 21;
		  tracks[t][k].param1 = (0x3F - event->byte2) >> 4;
		  tracks[t][k].param2 = (0x3F - event->byte2) & 15;
		  break;

		case 'G': // set carrier volume
		  tracks[t][k].command = 22;
		  tracks[t][k].param1 = (0x3F - event->byte2) >> 4;
		  tracks[t][k].param2 = (0x3F - event->byte2) & 15;
		  break;

		case 'B': // set carrier waveform
		  tracks[t][k].command = 25;
		  tracks[t][k].param1  = event->byte2;
		  tracks[t][k].param2  = 0x0F;
		  break;

		case 'E': // fine frequency slide down
		  tracks[t][k].command = 24;
		  tracks[t][k].param1  = old_event_byte2[j] >> 4;
		  tracks[t][k].param2  = old_event_byte2[j] & 15;
		  break;

		case 'F': // fine frequency slide up
		  tracks[t][k].command = 23;
		  tracks[t][k].param1  = old_event_byte2[j] >> 4;
		  tracks[t][k].param2  = old_event_byte2[j] & 15;
		  break;

		case 'D': // fine volume slide
		  tracks[t][k].command = 14;
		  if (old_event_byte2[j] & 15)
		    {
		      // slide down
		      tracks[t][k].param1 = 5;
		      tracks[t][k].param2 = old_event_byte2[j] & 15;
		    }
		  else
		    {
		      // slide up
		      tracks[t][k].param1 = 4;
		      tracks[t][k].param2 = old_event_byte2[j] >> 4;
		    }
		  break;

		case 'J': // arpeggio
		  tracks[t][k].param1  = old_event_byte2[j] >> 4;
		  tracks[t][k].param2  = old_event_byte2[j] & 15;
		  break;
		}
	    }

	  t++;
	}
    }

  delete [] module;

  // order loop
  restartpos = 0;

  // order length
  for (i=0;i<64;i++)
    {
      if (order[i] >= 0x80)
	{
	  length = i;
	  break;
	}
    }

  // default tempo
  bpm = 0x7D;

  rewind(0);

  return true;	
}
Beispiel #4
0
bool CffPlayer::load(const std::string& filename)
{
    FileStream f(filename);
    if(!f)
        return false;
    const uint8_t conv_inst[11] = { 2, 1, 10, 9, 4, 3, 6, 5, 0, 8, 7 };
    const std::array<uint16_t, 12> conv_note = { 0x16B, 0x181, 0x198, 0x1B0, 0x1CA,
        0x1E5, 0x202, 0x220, 0x241, 0x263,
        0x287, 0x2AE };

    // '<CUD-FM-File>' - signed ?
    f >> m_header;
    if(memcmp(m_header.id, "<CUD-FM-File>"
              "\x1A\xDE\xE0",
              16))
    {
        return false;
    }

    std::vector<uint8_t> module(0x10000);

    // packed ?
    if(m_header.packed)
    {
        std::unique_ptr<cff_unpacker> unpacker{ new cff_unpacker() };

        std::vector<uint8_t> packedModule;
        packedModule.resize(m_header.size + 4, 0);

        f.read(packedModule.data(), m_header.size);
        unpacker->unpack(packedModule, module);

        if(module.empty())
        {
            return false;
        }

        if(memcmp(&module[0x5E1], "CUD-FM-File - SEND A POSTCARD -", 31))
        {
            return false;
        }
    }
    else
    {
        f.read(module.data(), m_header.size);
    }

    // init CmodPlayer
    realloc_patterns(36, 64, 9);
    init_notetable(conv_note);
    init_trackord();

    // load instruments
    for(int i = 0; i < 47; i++)
    {
        memcpy(&m_instruments[i], &module[i * 32], sizeof(cff_instrument));

        for(int j = 0; j < 11; j++)
            addInstrument().data[conv_inst[j]] = m_instruments[i].data[j];

        m_instruments[i].name[20] = 0;
    }

    // number of patterns
    const auto patternCount = module[0x5E0];

    // load title & author
    m_title = stringncpy(reinterpret_cast<const char*>(&module[0x614]), 20);
    m_author = stringncpy(reinterpret_cast<const char*>(&module[0x600]), 20);

    // load orders
    {
        static constexpr auto OrderDataOffset = 0x628;
        for(int i = 0; i < 64; i++)
        {
            if(module[OrderDataOffset + i] & 0x80)
                break;

            addOrder(module[OrderDataOffset + i]);
        }
    }

    // load tracks
    int t = 0;
    for(int i = 0; i < patternCount; i++)
    {
        uint8_t old_event_byte2[9];

        memset(old_event_byte2, 0, 9);

        for(int channel = 0; channel < 9; channel++)
        {
            for(int row = 0; row < 64; row++)
            {
                const cff_event* event = reinterpret_cast<const cff_event *>(&module[0x669 + ((i * 64 + row) * 9 + channel) * 3]);
                PatternCell& cell = patternCell(t, row);

                // convert note
                if(event->byte0 == 0x6D)
                    cell.note = 127;
                else if(event->byte0)
                    cell.note = event->byte0;

                if(event->byte2)
                    old_event_byte2[channel] = event->byte2;

                // convert effect
                switch(event->byte1)
                {
                    case 'I': // set instrument
                        cell.instrument = event->byte2 + 1;
                        cell.hiNybble = cell.loNybble = 0;
                        break;

                    case 'H': // set tempo
                        cell.command = Command::SetTempo;
                        if(event->byte2 < 16)
                        {
                            cell.hiNybble = 0x07;
                            cell.loNybble = 0x0D;
                        }
                        break;

                    case 'A': // set speed
                        cell.command = Command::RADSpeed;
                        cell.hiNybble = event->byte2 >> 4;
                        cell.loNybble = event->byte2 & 15;
                        break;

                    case 'L': // pattern break
                        cell.command = Command::PatternBreak;
                        cell.hiNybble = event->byte2 >> 4;
                        cell.loNybble = event->byte2 & 15;
                        break;

                    case 'K': // order jump
                        cell.command = Command::OrderJump;
                        cell.hiNybble = event->byte2 >> 4;
                        cell.loNybble = event->byte2 & 15;
                        break;

                    case 'M': // set vibrato/tremolo
                        cell.command = Command::OplTremoloVibrato;
                        cell.hiNybble = event->byte2 >> 4;
                        cell.loNybble = event->byte2 & 15;
                        break;

                    case 'C': // set modulator volume
                        cell.command = Command::ModulatorVolume;
                        cell.hiNybble = (0x3F - event->byte2) >> 4;
                        cell.loNybble = (0x3F - event->byte2) & 15;
                        break;

                    case 'G': // set carrier volume
                        cell.command = Command::CarrierVolume;
                        cell.hiNybble = (0x3F - event->byte2) >> 4;
                        cell.loNybble = (0x3F - event->byte2) & 15;
                        break;

                    case 'B': // set carrier waveform
                        cell.command = Command::WaveForm;
                        cell.hiNybble = event->byte2;
                        cell.loNybble = 0x0F;
                        break;

                    case 'E': // fine frequency slide down
                        cell.command = Command::FineSlideDown;
                        cell.hiNybble = old_event_byte2[channel] >> 4;
                        cell.loNybble = old_event_byte2[channel] & 15;
                        break;

                    case 'F': // fine frequency slide up
                        cell.command = Command::FineSlideUp;
                        cell.hiNybble = old_event_byte2[channel] >> 4;
                        cell.loNybble = old_event_byte2[channel] & 15;
                        break;

                    case 'D': // fine volume slide
                        if(old_event_byte2[channel] & 15)
                        {
                            // slide down
                            cell.command = Command::SFXFineVolumeDown;
                            cell.loNybble = old_event_byte2[channel] & 15;
                        }
                        else
                        {
                            // slide up
                            cell.command = Command::SFXFineVolumeUp;
                            cell.loNybble = old_event_byte2[channel] >> 4;
                        }
                        break;

                    case 'J': // arpeggio
                        cell.hiNybble = old_event_byte2[channel] >> 4;
                        cell.loNybble = old_event_byte2[channel] & 15;
                        break;
                }
            }

            t++;
        }
    }

    // order loop
    setRestartOrder(0);

    // default tempo
    setInitialTempo(0x7D);

    rewind(0);

    return true;
}