bool _prepare_DirectSound(byte[] instrument_code, string key, bool is_deps) { Debug.Assert(SongInstrumentForm.IsDirectSound(instrument_code[0])); uint sample_location = U.p32(instrument_code, 4); if (sample_location > this.Data.Length) { this.ErrorMessage += "\r\n" + R.Error("DirectSoundの中に、おかしなデータがありました。無視します。 sample_location:{0} > {1} ROM Size" , U.To0xHexString(sample_location), U.To0xHexString(this.Data.Length)); //ダメな楽器として認識する. return(false); } uint sample_hz1024 = U.u32(this.Data, sample_location + 4) / 1024; uint sample_length = SongUtil.GetDirectSoundWaveDataLength(this.Data, sample_location); Log.Debug(R._("DirectSound Sample:{0} bytes ({1} *1024 hz)", sample_length, sample_hz1024)); if (is_deps) { if (sample_length > 1024 * 1024 * 1 || //1MB sample_hz1024 > 48 * 1024 //48khz Over ) { this.ErrorMessage += "\r\n" + R.Error("Multi または Drumの中に、おかしなデータがありました。無視します。 OverHZ Sample:{0} bytes ({1} *1024 hz)", sample_length, sample_hz1024); //ダメな楽器として認識する. return(false); } } List <byte> current_sample = U.subrangeToList(this.Data, sample_location, sample_location + 16 + sample_length); //4バイトアライメント while ((current_sample.Count % 4) != 0) { current_sample.Add(0); } Log.Debug(Instrument_mapping.Count.ToString(), sample_length.ToString("X"), this.Sample_data.Count.ToString("X")); U.write_u32(instrument_code, 4, (uint)this.Sample_data.Count); this.Sample_data.AddRange(current_sample); Log.Debug(R._("SampleData:{0} bytes (append({1}bytes))", this.Sample_data.Count, current_sample.Count)); return(true); }
uint _prepare(byte[] instrument_code, string key, bool is_deps) { // Fix instrument pointer to be an offset relative to start of sample data. // The pointer for the first instrument - which is the percussion map - is // of course relative to the start of instrument data, being zero. The // burn procedure is aware of this. if (is_deps && (instrument_code[0] == 0x80 || instrument_code[0] == 0x40)) { //print "song in song error!" //print hexdump(instrument_code) Log.Error(U.HexDump(instrument_code)); this.ErrorMessage += "\r\n" + R.Error("Multi または Drumの中に、さらにMulti または Drumがありました。\r\nこういう複雑なものは対応できないので無視します。\r\n"); instrument_code = bad_inst(); Debug.Assert(false); } else if (SongInstrumentForm.IsDirectSound(instrument_code[0])) { bool success = _prepare_DirectSound(instrument_code, key, is_deps); if (success == false) { instrument_code = bad_inst(); } } else if (SongInstrumentForm.IsWaveMemory(instrument_code[0])) { bool success = _prepare_WaveMemory(instrument_code, key, is_deps); if (success == false) { instrument_code = bad_inst(); } } else if (instrument_code[0] == 0x80) { Log.Debug("Drum"); Log.Debug(U.HexDump(instrument_code)); //drum instrument is always id:0 this.Instrument_mapping[key] = 0; return(0); } else if (instrument_code[0] == 0x40) { bool success = _prepare_MultiSample(instrument_code, key, is_deps); if (success == false) { instrument_code = bad_inst(); } } else { Log.Debug("???"); Log.Debug(U.HexDump(instrument_code)); } Debug.Assert(instrument_code.Length >= 0xC); uint result = this.Count(); this.Instrument_mapping[key] = result; this.Instrument_codes.AddRange(instrument_code); return(result); }
void Burn(SongSt song, InstrumentMap instrument_map, List <List <byte> > trackdata) { //必要なサイズを計算する. uint use_size = 8 + (4 * (uint)trackdata.Count); //ヘッダー for (int track = 0; track < trackdata.Count; track++) { use_size += (uint)trackdata[track].Count; //楽譜 } use_size = U.Padding4(use_size); //楽譜と楽器の間は 4バイトアライメントが必要. use_size += (uint)(instrument_map.Instrument_mapping.Count * 12); //楽器 use_size += (uint)instrument_map.Sample_data.Count; //楽器データ uint write_pointer = InputFormRef.AllocBinaryData(use_size); if (write_pointer == U.NOT_FOUND) { R.ShowStopError("データサイズを({0})確保できません。\r\nROM容量がもうないか、音楽のパースに失敗しています。", use_size); return; } U.toPointer(write_pointer); byte[] data = new byte[use_size]; U.write_u8(data, 0, (uint)trackdata.Count); //トラック数 U.write_u8(data, 1, 0x0); //常にゼロ. U.write_u8(data, 2, 0x0A); //Do these values matter? U.write_u8(data, 3, 0x80); //This is just copying what the stock ROM does... uint offset = 8 + (4 * (uint)trackdata.Count); //データ構造 //ヘッダー //[track数] [0] [0x0A] [0x80] [楽器ポンタ] [楽譜1ポインタ] [楽譜2ポインタ].... [楽譜Nポインタ] // //実データ //[楽譜1データ]....... //[楽譜2データ]....... // //[楽器データ] //[楽器サンプルデータ] //楽譜 for (int track = 0; track < trackdata.Count; track++) { //楽譜ポインタの書き込み U.write_u32(data, 8 + (4 * (uint)track), U.toPointer(write_pointer + offset)); //楽譜データを書き込む. burn_track(data, offset, write_pointer, trackdata[track].ToArray()); offset += (uint)trackdata[track].Count; } offset = U.Padding4(offset); //楽譜と楽器の間は 4バイトアライメントが必要. //楽器ポインタ U.write_u32(data, 4, U.toPointer(write_pointer + offset)); uint instrument_start = offset; //楽器開始 uint instrumentdata_start = instrument_start + (12 * (uint)instrument_map.Instrument_mapping.Count); //楽器データ開始 Log.Debug("instrumentdata_start(", instrumentdata_start.ToString(), ") = instrument_start(", instrument_start.ToString(), ") + 12 * instrument_count(", instrument_map.Instrument_mapping.Count.ToString(), ")"); U.write_range(data, instrument_start, instrument_map.Instrument_codes.ToArray()); U.write_range(data, instrumentdata_start, instrument_map.Sample_data.ToArray()); //楽器 uint resyclesize = 0; for (int i = 0; i < instrument_map.Instrument_mapping.Count; i++) { uint this_instrument = instrument_start + (12 * (uint)i); Log.Debug("track:", i.ToString(), " ", data[this_instrument + 0].ToString()); uint instrumentCode = U.u8(data, this_instrument + 0); if (SongInstrumentForm.IsDirectSound(instrumentCode) || SongInstrumentForm.IsWaveMemory(instrumentCode)) { uint sample_data_start = U.u32(data, this_instrument + 4); sample_data_start += instrumentdata_start; if (sample_data_start < resyclesize) { Log.Error("BAD INSTRUMENT:", i.ToString(), (sample_data_start - instrumentdata_start).ToString(), sample_data_start.ToString(), resyclesize.ToString()); continue; } sample_data_start -= resyclesize; uint sample_data_len; if (SongInstrumentForm.IsWaveMemory(instrumentCode)) { sample_data_len = 16; } else { sample_data_len = U.u32(data, sample_data_start + 12); sample_data_len = U.Padding4(sample_data_len); } Log.Debug("d ", sample_data_start.ToString("X"), " ", sample_data_len.ToString()); uint found_address = U.Grep(Program.ROM.Data, U.subrange(data, sample_data_start, sample_data_start + sample_data_len), 100, 0, 4); if (found_address != U.NOT_FOUND) { Log.Debug("recycle ", sample_data_start.ToString("X"), " len ", sample_data_len.ToString(), " -> ", found_address.ToString("X")); //existing address in ROM. //recycle data = U.del(data, sample_data_start, sample_data_start + sample_data_len); U.write_u32(data, this_instrument + 4, U.toPointer(found_address)); resyclesize += sample_data_len; } else { //nothing to recycle, write the data. uint baseoffset = U.u32(data, this_instrument + 4); //相対アドレスが書いてあるので、それを求めに絶対値に変換する U.write_u32(data, this_instrument + 4 , U.toPointer((instrumentdata_start + write_pointer + baseoffset) - resyclesize)); } } else if (instrumentCode == 0x80) { //ドラム uint baseoffset = U.u32(data, this_instrument + 4); //相対アドレスが書いてあるので、それを求めに絶対値に変換する U.write_u32(data, this_instrument + 4 , U.toPointer(instrument_start + write_pointer + baseoffset)); } else if (instrumentCode == 0x40) { Log.Debug("MULTI TRACK!"); uint baseoffset = U.u32(data, this_instrument + 4); //相対アドレスが書いてあるので、それを求めに絶対値に変換する U.write_u32(data, this_instrument + 4 , U.toPointer(instrument_start + write_pointer + baseoffset)); baseoffset = U.u32(data, this_instrument + 8); //相対アドレスが書いてあるので、それを求めに絶対値に変換する U.write_u32(data, this_instrument + 8 , U.toPointer((instrumentdata_start + write_pointer + baseoffset) - resyclesize)); } } Log.Notify("resyclesize:", resyclesize.ToString(), U.To0xHexString(resyclesize)); string undo_name = ""; Undo.UndoData undodata = Program.Undo.NewUndoData(undo_name); undodata.list.Add(new Undo.UndoPostion(song.table, 8)); Program.ROM.write_u32(song.table, U.toPointer(write_pointer)); InputFormRef.WriteBinaryDataDirect(write_pointer, data, undodata); uint priority = GetSongPriority(trackdata.Count); Program.ROM.write_u32(song.table + 4, priority, undodata); Program.Undo.Push(undodata); }