Пример #1
0
        void ConvertSong(byte[] srcdata, SongSt srcsong, byte[] destdata, SongSt destsong)
        {
            InstrumentMap       instrument_map = new InstrumentMap(srcdata, srcsong.voices);
            List <List <byte> > trackdata      = new List <List <byte> >();

            if (instrument_map.ErrorMessage != "")
            {
                DialogResult dr = R.ShowNoYes("この曲のデータ構造は壊れているようです。\r\nインポートを強行しますか?\r\n強行する場合は、正しく認識できたトラックのみをインポートします。" + "\r\n\r\n" + instrument_map.ErrorMessage);
                if (dr != System.Windows.Forms.DialogResult.Yes)
                {
                    return;
                }
            }

            //曲の取出し.
            this.ErrorMessage = "";
            bool success = Rip(srcdata, srcsong, instrument_map, trackdata);

            if (success == false)
            {
                R.ShowStopError("この曲のデータ構造は壊れているため、Rip出来ませんでした。" + "\r\n\r\n" + this.ErrorMessage);
                return;
            }

            //取り出した曲を書き込む.
            Burn(destsong, instrument_map, trackdata);
        }
Пример #2
0
        private static RootElement ConvertRootElement(KeySwitch source, ListElement listOfPSoundSlot, ListElement listOfUSlotVisuals)
        {
            // Construction of InstrumentMap element
            var slots       = InstrumentMap.Slots(listOfPSoundSlot);
            var slotVisuals = InstrumentMap.SlotVisuals(listOfUSlotVisuals);

            var instrumentName = $"{source.ProductName.Value} {source.InstrumentName.Value}";
            var rootElement    = InstrumentMap.New(instrumentName);

            rootElement.Member.Add(slotVisuals);
            rootElement.Member.Add(slots);
            rootElement.StringElement.Value = instrumentName;

            return(rootElement);
        }
Пример #3
0
        bool Rip(byte[] data, SongSt song, InstrumentMap instrument_map, List <List <byte> > trackdata)
        {
            //Rip
            for (uint track = 0; track < song.tracks; track++)
            {
                uint songtrack_pointer     = song.header + 8 + (4 * track);
                uint songtrackdata_pointer = U.u32(data, songtrack_pointer);
                if (!U.isPointer(songtrackdata_pointer))
                {
                    this.ErrorMessage += "\r\n" +
                                         R.Error("track:" + track.ToString() + " can not pointer! addr:" + songtrack_pointer.ToString("X08") + " data:" + songtrackdata_pointer.ToString("X08"));
                    return(false);
                }
                songtrackdata_pointer = U.toOffset(songtrackdata_pointer);

                List <byte> track_data = process_track(data, songtrackdata_pointer, instrument_map);

                trackdata.Add(track_data);
            }
            //ドラムがない曲の場合、それは困るので、ダミーのドラムを追加する.
            instrument_map.appendDrumIfNoDrum();
            return(true);
        }
Пример #4
0
        List <byte> process_track(byte[] data, uint songtrackdata_pointer, InstrumentMap instrument_map)
        {
            List <byte> ret = new List <byte>();

            //Transform the data.
            uint position   = songtrackdata_pointer;
            uint percussion = 0;

            while (true)
            {
                uint b = U.u8(data, position);
                position++;
                ret.Add((byte)b);

                if (b == 0xB1)
                {
                    break;
                }
                else if (b == 0xB2 || b == 0xB3)
                {
                    //repointer
                    U.append_u32(ret, U.p32(data, position) - songtrackdata_pointer);
                    position += 4;
                }
                else if (b == 0xBD)
                {
                    uint next_byte = U.u8(data, position);
                    position++;

                    uint translated = instrument_map.translate(next_byte);
                    if (translated == 0)
                    {
                        percussion = next_byte;
                    }
                    ret.Add((byte)translated);
                }
                else if (b == 0xBB || b == 0xBC || b == 0xBE || b == 0xBF || b == 0xC0 || b == 0xC1 || b == 0xC2 || b == 0xC3 || b == 0xC4 || b == 0xC5 || b == 0xC8)
                {
                    // These commands take a data byte that must not be processed.
                    ret.Add((byte)U.u8(data, position));
                    position++;
                }
                else if (b == 0xb9)
                {//MEMACC 4バイト命令
                    //最初の1バイトはコピー済みなので、残りの3バイトコピーする.
                    ret.Add((byte)U.u8(data, position));
                    position++;
                    ret.Add((byte)U.u8(data, position));
                    position++;
                    ret.Add((byte)U.u8(data, position));
                    position++;
                }
                else if (percussion != 0 && b < 0x80)
                {
                    uint inst = instrument_map.translate_percussion(percussion, b);
                    ret[ret.Count - 1] = ((byte)inst);
                    //There might be a volume marker, and then a 'gate' byte
                    //For now, assuming that any subsequent low-value bytes are extra data
                    //that should be passed as-is - even though previous experimentation suggested
                    //that these bytes could be used to specify a chord...
                    while (U.u8(data, position) < 0x80)
                    {// Volume marker
                        ret.Add((byte)U.u8(data, position));
                        position++;
                    }
                }
            }
            return(ret);
        }
Пример #5
0
        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);
        }