Ejemplo n.º 1
0
        public static byte[] GenerateSampleDirectory(Config config, List <BRRFile> samples)
        {
            var currentAramOffset = config.offsetForBRRdump;
            //Thanks to BlueStone for helping with the following!
            var samplesByFilename           = samples.ToDictionary(sample => sample.filename);
            var sampleDirectoriesByFilename = new Dictionary <string, SampleDirectory>();
            var resultSampleDirectory       = new List <SampleDirectory>();

            foreach (var patch in config.patches)
            {
                // If an entry with the same filename was already added, reuse the existing entry.
                if (sampleDirectoriesByFilename.TryGetValue(patch.Filename, out SampleDirectory entry))
                {
                    resultSampleDirectory.Add(entry);
                }
                else
                {
                    // We haven't added an entry with this file before, so find the sample and add the entry.
                    if (!samplesByFilename.TryGetValue(patch.Filename, out BRRFile currentSample))
                    {
                        if (!patch.Filename.Contains("0x")) //don't display this message for duplicates
                        {
                            Console.WriteLine("Sample file \"" + patch.Filename + "\" does not exist!");
                        }
                    }
                    else
                    {
                        ushort tempStartOffset = 0; //Duplicates need to use the explicitly-specified offsets
                        ushort tempLoopOffset  = 0; //instead of the running count that BRR files use
                        if (currentSample.filename.Contains("Duplicate"))
                        {
                            tempStartOffset = currentSample.dupeStartOffset;
                            tempLoopOffset  = currentSample.dupeLoopOffset;
                        }
                        else
                        {
                            tempStartOffset = currentAramOffset;
                            if (currentSample.loopPoint == 0)
                            {
                                tempLoopOffset = (ushort)(currentAramOffset + currentSample.data.Length); //loopPoint is 0, so unlooped samples would otherwise loop infinitely
                            }
                            else
                            {
                                tempLoopOffset = (ushort)(currentAramOffset + BRRFunctions.EncodeLoopPoint(currentSample.loopPoint));
                            }
                        }

                        var sampleDirEntry = new SampleDirectory
                        {
                            aramOffset = tempStartOffset,
                            loopOffset = tempLoopOffset,
                            Filename   = currentSample.filename,
                        };
                        sampleDirectoriesByFilename[patch.Filename] = sampleDirEntry;
                        resultSampleDirectory.Add(sampleDirEntry);

                        currentAramOffset += (ushort)currentSample.data.Length;
                    }
                }
            }

            //turn the entire thing into a byte array
            var result = new List <byte>();

            foreach (var entry in resultSampleDirectory)
            {
                result.AddRange(entry.MakeHex());
            }
            return(result.ToArray());
        }
Ejemplo n.º 2
0
        internal static List <BRRFile> LoadBRRs(string folderPath)
        {
            var allFiles    = Directory.GetFiles(GetFullPath(folderPath));
            var brrFileList = LoadFilenames(folderPath); //Get just the filenames from config.txt
            var dupeIndex   = 0;

            //Find matches based on the list, add them to the result
            var result = new List <BRRFile>();

            foreach (var nameToLookFor in brrFileList)
            {
                if (nameToLookFor.Contains("0x"))
                {
                    //this line is a duplicate, not a reference to a file - it contains manual ARAM offsets
                    var offsets = nameToLookFor.Split("0x");
                    result.Add(new BRRFile
                    {
                        dupeStartOffset = HexHelpers.HexStringToUInt16(offsets[1]),
                        dupeLoopOffset  = HexHelpers.HexStringToUInt16(offsets[2]),
                        data            = new byte[0],                               //empty so the running offset count doesn't get incremented
                        filename        = $"Duplicate #{dupeIndex} {nameToLookFor}", //it breaks if there's identical filenames here
                    });
                    dupeIndex++;
                }
                else
                {
                    foreach (string filename in allFiles)
                    {
                        bool alreadyInserted = false;

                        var info = new FileInfo(filename);
                        if (info.Extension != ".brr" || info.Name != nameToLookFor)
                        {
                            continue; //skip everything that isn't a BRR file, and files that aren't the next one in the list
                        }
                        foreach (var foo in result)
                        {
                            if (foo.filename.Contains(nameToLookFor))
                            {
                                alreadyInserted = true;
                            }
                        }

                        if (alreadyInserted)
                        {
                            continue;
                        }

                        var fileContents = File.ReadAllBytes(info.FullName);

                        if (BRRFunctions.FileHasNoLoopHeader(fileContents.Length))
                        {
                            result.Add(new BRRFile
                            {
                                data      = fileContents,
                                loopPoint = 0, //rudimentary support for raw, non-AMK BRRs
                                filename  = info.Name,
                            });
                        }
                        else
                        {
                            //separate the loop point header and the actual BRR data, and add them to the list
                            result.Add(new BRRFile
                            {
                                data      = BRRFunctions.IsolateBRRdata(fileContents),
                                loopPoint = BRRFunctions.DecodeLoopPoint(fileContents),
                                filename  = info.Name,
                            });
                        }
                    }
                }
            }
            return(result);
        }
        //TODO:
        //Edge-case bugs that people find
        //Comission an icon for the program
        //Make it so it puts the BRRs in the CCScript file seperately and puts a comment with the filename
        //Recreate vanilla packs in the Examples folder to make them easier for people to modify
        //Finish songs instead of messing with this!!!

        static void Main(string[] args)
        {
            const bool DEBUG = false;
            string     folderPath;

            Console.Title = "EarthBound Instrument Packer";

            //load the folder contents
            if (DEBUG)
            {
                folderPath = @"C:\Users\vince\Dropbox\Programming scratchpad\EarthBound-Instrument-Packer\EBInstPack\Examples\famicomDetectiveClub";
            }
            else
            {
                if (args.Length == 0) //If they just double-clicked the exe - no args present
                {
                    Console.WriteLine("Command-line usage:");
                    Console.WriteLine("   EBInstPack [folder path in quotes]");
                    Console.WriteLine("   Or just drag the folder onto the EXE!");
                    Console.WriteLine();
                    Console.WriteLine("Input the folder path where the samples & text file are:");
                    folderPath = Console.ReadLine();
                }
                else
                {
                    folderPath = args[0]; //Use the command-line argument if it's present
                }

                if (FileIO.FolderNonexistant(folderPath))
                {
                    return;
                }
            }

            //load the config.txt
            var config  = FileIO.LoadConfig(folderPath);
            var samples = FileIO.LoadBRRs(folderPath);

            //Generate all the hex
            var sampleDirectory = Config.GenerateSampleDirectory(config, samples);
            var brrDump         = BRRFunctions.Combine(samples);

            //Validation
            var tooManyBRRs = ARAM.CheckBRRLimit(brrDump, config.offsetForBRRdump);

            config.maxDelay = ARAM.GetMaxDelayPossible(brrDump, config.offsetForBRRdump);
            Console.WriteLine($"Highest possible delay value for this pack: {config.maxDelay:X2}");
            Console.WriteLine($"These BRRs will be loaded into ARAM from {config.offsetForBRRdump:X4} to {config.offsetForBRRdump + brrDump.Length:X4}.\n");

            var ccsFile = CCScriptOutput.Generate(config, sampleDirectory, brrDump);

            FileIO.SaveCCScriptFile(ccsFile, folderPath, config);

            //Check the folder for .EBM files
            var ebmFiles = FileIO.LoadEBMs(folderPath);

            foreach (var song in ebmFiles)
            {
                var spc = new PreviewSPC(config, sampleDirectory, brrDump, song);
                FileIO.SaveSPCfile(spc.filedata, folderPath, song.name);
            }

            Console.WriteLine("Press any key to continue...");
            Console.ReadKey();
        }