Пример #1
0
        public static RealTimeCore Run(RealTimeConfig config, string rootPath, ILocalizationProvider localizationProvider)
        {
            if (config == null)
            {
                throw new ArgumentNullException(nameof(config));
            }

            if (string.IsNullOrEmpty(rootPath))
            {
                throw new ArgumentException("The root path cannot be null or empty string", nameof(rootPath));
            }

            if (localizationProvider == null)
            {
                throw new ArgumentNullException(nameof(localizationProvider));
            }

            var patcher = new MethodPatcher(
                BuildingAIPatches.PrivateConstructionTime,
                BuildingAIPatches.PrivateHandleWorkers,
                BuildingAIPatches.CommercialSimulation,
                ResidentAIPatch.Location,
                ResidentAIPatch.ArriveAtDestination,
                TouristAIPatch.Location,
                UIGraphPatches.MinDataPoints,
                UIGraphPatches.VisibleEndTime,
                UIGraphPatches.BuildLabels);

            try
            {
                patcher.Apply();
                Log.Info("The 'Real Time' successfully performed the methods redirections");
            }
            catch (Exception ex)
            {
                Log.Error("The 'Real Time' mod failed to perform method redirections: " + ex);
                patcher.Revert();
                return(null);
            }

            var timeInfo        = new TimeInfo(config);
            var buildingManager = new BuildingManagerConnection();
            var randomizer      = new GameRandomizer();

            var weatherInfo = new WeatherInfo(new WeatherManagerConnection());

            var gameConnections = new GameConnections <Citizen>(
                timeInfo,
                new CitizenConnection(),
                new CitizenManagerConnection(),
                buildingManager,
                randomizer,
                new TransferManagerConnection(),
                weatherInfo);

            var eventManager = new RealTimeEventManager(
                config,
                CityEventsLoader.Instance,
                new EventManagerConnection(),
                buildingManager,
                randomizer,
                timeInfo);

            if (!SetupCustomAI(timeInfo, config, gameConnections, eventManager))
            {
                Log.Error("The 'Real Time' mod failed to setup the customized AI and will now be deactivated.");
                patcher.Revert();
                return(null);
            }

            var      timeAdjustment = new TimeAdjustment(config);
            DateTime gameDate       = timeAdjustment.Enable();

            SimulationHandler.CitizenProcessor.SetFrameDuration(timeAdjustment.HoursPerFrame);

            CityEventsLoader.Instance.ReloadEvents(rootPath);

            var customTimeBar = new CustomTimeBar();

            customTimeBar.Enable(gameDate);
            customTimeBar.CityEventClick += CustomTimeBarCityEventClick;

            var result = new RealTimeCore(timeAdjustment, customTimeBar, eventManager, patcher);

            eventManager.EventsChanged += result.CityEventsChanged;
            SimulationHandler.NewDay   += result.CityEventsChanged;

            SimulationHandler.TimeAdjustment    = timeAdjustment;
            SimulationHandler.DayTimeSimulation = new DayTimeSimulation(config);
            SimulationHandler.EventManager      = eventManager;
            SimulationHandler.WeatherInfo       = weatherInfo;
            SimulationHandler.Buildings         = BuildingAIPatches.RealTimeAI;

            AwakeSleepSimulation.Install(config);

            RealTimeStorage.CurrentLevelStorage.GameSaving += result.GameSaving;
            result.storageData.Add(eventManager);
            result.storageData.Add(ResidentAIPatch.RealTimeAI.GetStorageService());
            result.LoadStorageData();

            result.Translate(localizationProvider);

            return(result);
        }
Пример #2
0
        public static RealTimeCore Run(
            ConfigurationProvider <RealTimeConfig> configProvider,
            string rootPath,
            ILocalizationProvider localizationProvider,
            bool setDefaultTime,
            Compatibility compatibility)
        {
            if (configProvider == null)
            {
                throw new ArgumentNullException(nameof(configProvider));
            }

            if (string.IsNullOrEmpty(rootPath))
            {
                throw new ArgumentException("The root path cannot be null or empty string", nameof(rootPath));
            }

            if (localizationProvider == null)
            {
                throw new ArgumentNullException(nameof(localizationProvider));
            }

            if (compatibility == null)
            {
                throw new ArgumentNullException(nameof(compatibility));
            }

            var patches = GetMethodPatches(compatibility);
            var patcher = new MethodPatcher(HarmonyId, patches);

            var appliedPatches = patcher.Apply();

            if (!CheckRequiredMethodPatches(appliedPatches))
            {
                Log.Error("The 'Real Time' mod failed to perform method redirections for required methods");
                patcher.Revert();
                return(null);
            }

            if (StorageBase.CurrentLevelStorage != null)
            {
                LoadStorageData(new[] { configProvider }, StorageBase.CurrentLevelStorage);
            }

            localizationProvider.SetEnglishUSFormatsState(configProvider.Configuration.UseEnglishUSFormats);

            var timeInfo        = new TimeInfo(configProvider.Configuration);
            var buildingManager = new BuildingManagerConnection();
            var randomizer      = new GameRandomizer();

            var weatherInfo = new WeatherInfo(new WeatherManagerConnection(), randomizer);

            var gameConnections = new GameConnections <Citizen>(
                timeInfo,
                new CitizenConnection(),
                new CitizenManagerConnection(),
                buildingManager,
                randomizer,
                new TransferManagerConnection(),
                weatherInfo);

            var eventManager = new RealTimeEventManager(
                configProvider.Configuration,
                CityEventsLoader.Instance,
                new EventManagerConnection(),
                buildingManager,
                randomizer,
                timeInfo,
                Constants.MaxTravelTime);

            if (!SetupCustomAI(timeInfo, configProvider.Configuration, gameConnections, eventManager, compatibility))
            {
                Log.Error("The 'Real Time' mod failed to setup the customized AI and will now be deactivated.");
                patcher.Revert();
                return(null);
            }

            var timeAdjustment = new TimeAdjustment(configProvider.Configuration);
            var gameDate       = timeAdjustment.Enable(setDefaultTime);

            SimulationHandler.CitizenProcessor.UpdateFrameDuration();

            CityEventsLoader.Instance.ReloadEvents(rootPath);

            var customTimeBar = new CustomTimeBar();

            customTimeBar.Enable(gameDate);
            customTimeBar.CityEventClick += CustomTimeBarCityEventClick;

            var vanillaEvents = VanillaEvents.Customize();

            var result = new RealTimeCore(timeAdjustment, customTimeBar, eventManager, patcher, vanillaEvents);

            eventManager.EventsChanged += result.CityEventsChanged;

            var statistics = new Statistics(timeInfo, localizationProvider);

            if (statistics.Initialize())
            {
                statistics.RefreshUnits();
            }
            else
            {
                statistics = null;
            }

            SimulationHandler.NewDay += result.CityEventsChanged;

            SimulationHandler.TimeAdjustment    = timeAdjustment;
            SimulationHandler.DayTimeSimulation = new DayTimeSimulation(configProvider.Configuration);
            SimulationHandler.EventManager      = eventManager;
            SimulationHandler.WeatherInfo       = weatherInfo;
            SimulationHandler.Buildings         = BuildingAIPatch.RealTimeAI;
            SimulationHandler.Buildings.UpdateFrameDuration();

            if (appliedPatches.Contains(CitizenManagerPatch.CreateCitizenPatch1))
            {
                CitizenManagerPatch.NewCitizenBehavior = new NewCitizenBehavior(randomizer, configProvider.Configuration);
            }

            if (appliedPatches.Contains(BuildingAIPatch.GetColor))
            {
                SimulationHandler.Buildings.InitializeLightState();
            }

            SimulationHandler.Statistics = statistics;

            if (appliedPatches.Contains(WorldInfoPanelPatch.UpdateBindings))
            {
                WorldInfoPanelPatch.CitizenInfoPanel     = CustomCitizenInfoPanel.Enable(ResidentAIPatch.RealTimeAI, localizationProvider);
                WorldInfoPanelPatch.VehicleInfoPanel     = CustomVehicleInfoPanel.Enable(ResidentAIPatch.RealTimeAI, localizationProvider);
                WorldInfoPanelPatch.CampusWorldInfoPanel = CustomCampusWorldInfoPanel.Enable(localizationProvider);
            }

            AwakeSleepSimulation.Install(configProvider.Configuration);

            var schedulesStorage = ResidentAIPatch.RealTimeAI.GetStorageService(
                schedules => new CitizenScheduleStorage(schedules, gameConnections.CitizenManager.GetCitizensArray, timeInfo));

            result.storageData.Add(schedulesStorage);
            result.storageData.Add(eventManager);
            if (StorageBase.CurrentLevelStorage != null)
            {
                StorageBase.CurrentLevelStorage.GameSaving += result.GameSaving;
                LoadStorageData(result.storageData, StorageBase.CurrentLevelStorage);
            }

            result.storageData.Add(configProvider);
            result.Translate(localizationProvider);
            result.IsRestrictedMode = appliedPatches.Count != patches.Count;

            return(result);
        }
Пример #3
0
        private void btnSaveROM_Click(object sender, EventArgs e)
        {
            /* ROM sections:
             *
             * Header (0x0000-0x4000)
             * ARM9 Binary
             *   |_ARM9
             *   |_ARM9 Overlays Tables
             *   |_ARM9 Overlays
             * ARM7 Binary
             *   |_ARM7
             *   |_ARM7 Overlays Tables
             *   |_ARM7 Overlays
             * FNT (File Name Table)
             *   |_Main tables
             *   |_Subtables (names)
             * FAT (File Allocation Table)
             *   |_Files offset
             *     |_Start offset
             *     |_End offset
             * Banner
             *   |_Header 0x20
             *   |_Icon (Bitmap + palette) 0x200 + 0x20
             *   |_Game titles (Japanese, English, French, German, Italian, Spanish) 6 * 0x100
             * Files...
             */

            Thread espera = new Thread(ThreadEspera);

            if (!isMono)
            {
                espera.Start("S05");
            }

            // Get special files
            sFolder ftc = accion.Search_Folder("ftc");

            sFile fnt  = ftc.files.Find(sFile => sFile.name == "fnt.bin");
            sFile fat  = ftc.files.Find(sFile => sFile.name == "fat.bin");
            sFile arm9 = ftc.files.Find(sFile => sFile.name == "arm9.bin");
            sFile arm7 = ftc.files.Find(sFile => sFile.name == "arm7.bin");

            int          index = ftc.files.FindIndex(sFile => sFile.name == "y9.bin");
            sFile        y9    = new sFile();
            List <sFile> ov9   = new List <sFile>();

            if (index != -1)
            {
                y9  = ftc.files[index];
                ov9 = ftc.files.FindAll(sFile => sFile.name.StartsWith("overlay9_"));
            }

            index = ftc.files.FindIndex(sFile => sFile.name == "y7.bin");
            List <sFile> ov7 = new List <sFile>();
            sFile        y7  = new sFile();

            if (index != -1)
            {
                y7  = ftc.files[index];
                ov7 = ftc.files.FindAll(sFile => sFile.name.StartsWith("overlay7_"));
            }

            #region Get ROM sections
            BinaryReader br;
            Console.WriteLine(Tools.Helper.GetTranslation("Messages", "S08"));
            Nitro.Estructuras.ROMHeader header = romInfo.Cabecera;
            uint currPos = header.headerSize;


            // Write ARM9
            string arm9Binary = Path.GetTempFileName();
            string overlays9  = Path.GetTempFileName();
            Console.Write("\tARM9 Binary...");

            br = new BinaryReader(File.OpenRead(arm9.path));
            br.BaseStream.Position = arm9.offset;
            BinaryWriter bw = new BinaryWriter(File.OpenWrite(arm9Binary));
            bw.Write(br.ReadBytes((int)arm9.size));
            bw.Flush();
            br.Close();

            header.ARM9romOffset     = currPos;
            header.ARM9size          = arm9.size;
            header.ARM9overlayOffset = 0;
            uint arm9overlayOffset = 0;

            currPos += arm9.size;

            // Write the Nitrocode
            br = new BinaryReader(File.OpenRead(accion.ROMFile));
            br.BaseStream.Position = romInfo.Cabecera.ARM9romOffset + romInfo.Cabecera.ARM9size;
            if (br.ReadUInt32() == 0xDEC00621)
            {
                // Nitrocode found
                bw.Write(0xDEC00621);
                bw.Write(br.ReadUInt32());
                bw.Write(br.ReadUInt32());
                currPos += 0x0C;
                bw.Flush();
            }
            br.Close();

            uint rem = currPos % 0x200;
            if (rem != 0)
            {
                while (rem < 0x200)
                {
                    bw.Write((byte)0xFF);
                    rem++;
                    currPos++;
                }
            }

            if (header.ARM9overlaySize != 0)
            {
                // ARM9 Overlays Tables
                br = new BinaryReader(File.OpenRead(y9.path));
                br.BaseStream.Position = y9.offset;
                Nitro.Overlay.Write_Y9(bw, br, ov9.ToArray());
                bw.Flush();
                br.Close();
                header.ARM9overlayOffset = currPos;
                header.ARM9overlaySize   = y9.size;

                currPos += y9.size;
                rem      = currPos % 0x200;
                if (rem != 0)
                {
                    while (rem < 0x200)
                    {
                        bw.Write((byte)0xFF);
                        rem++;
                        currPos++;
                    }
                }

                Nitro.Overlay.EscribirOverlays(overlays9, ov9, accion.ROMFile);
                bw.Write(File.ReadAllBytes(overlays9)); // ARM9 Overlays
                arm9overlayOffset = currPos;
                currPos          += (uint)new FileInfo(overlays9).Length;
            }
            bw.Flush();
            bw.Close();

            Console.WriteLine(Tools.Helper.GetTranslation("Messages", "S09"), new FileInfo(arm9Binary).Length);

            string seedStr = seedTxt.Text;
            if (seedStr == "")
            {
                seedStr = DateTime.Now.ToString("s");
            }
            String         seed     = "MiUSlRDz" + seedStr;
            GameRandomizer rando    = null;
            string         gameCode = new string(romInfo.Cabecera.gameCode);
            if (gameCode == "A5FP")
            {
                rando = new CuriousVillagePALRandomizer(accion.Root, seed, accion);
            }

            if (rando != null)
            {
                rando.enforceMaxPuzzles         = this.enforceMaxPuzzlesBox.Checked;
                rando.removePuzzleCounterChecks = this.disablePuzzleCheckBox.Checked;
                rando.removeRiddleHutChecks     = this.disableRiddleHutBox.Checked;
                rando.seedPuzzles();
                rando.Write();
            }

            // Escribismo el ARM7 Binary
            string arm7Binary = Path.GetTempFileName();
            string overlays7  = Path.GetTempFileName();
            Console.Write("\tARM7 Binary...");

            br = new BinaryReader(File.OpenRead(arm7.path));
            br.BaseStream.Position = arm7.offset;
            bw = new BinaryWriter(File.OpenWrite(arm7Binary));
            bw.Write(br.ReadBytes((int)arm7.size));
            bw.Flush();
            br.Close();

            header.ARM7romOffset     = currPos;
            header.ARM7size          = arm7.size;
            header.ARM7overlayOffset = 0x00;
            uint arm7overlayOffset = 0x00;

            currPos += arm7.size;
            rem      = currPos % 0x200;
            if (rem != 0)
            {
                while (rem < 0x200)
                {
                    bw.Write((byte)0xFF);
                    rem++;
                    currPos++;
                }
            }

            if (romInfo.Cabecera.ARM7overlaySize != 0x00)
            {
                // ARM7 Overlays Tables
                br = new BinaryReader(File.OpenRead(y7.path));
                br.BaseStream.Position = y7.offset;
                bw.Write(br.ReadBytes((int)y7.size));
                bw.Flush();
                br.Close();
                header.ARM7overlayOffset = currPos;
                header.ARM7overlaySize   = y7.size;

                currPos += y7.size;
                rem      = currPos % 0x200;
                if (rem != 0)
                {
                    while (rem < 0x200)
                    {
                        bw.Write((byte)0xFF);
                        rem++;
                        currPos++;
                    }
                }

                Nitro.Overlay.EscribirOverlays(overlays7, ov7, accion.ROMFile);
                bw.Write(File.ReadAllBytes(overlays7)); // ARM7 Overlays

                arm7overlayOffset = currPos;
                currPos          += (uint)new FileInfo(overlays7).Length;
            }
            bw.Flush();
            bw.Close();
            Console.WriteLine(Tools.Helper.GetTranslation("Messages", "S09"), new FileInfo(arm7Binary).Length);


            // Escribimos el FNT (File Name Table)
            string fileFNT = Path.GetTempFileName();
            Console.Write("\tFile Name Table (FNT)...");

            bw = new BinaryWriter(File.OpenWrite(fileFNT));
            br = new BinaryReader(File.OpenRead(fnt.path));
            br.BaseStream.Position = fnt.offset;
            bw.Write(br.ReadBytes((int)fnt.size));
            bw.Flush();
            br.Close();
            header.fileNameTableSize   = fnt.size;
            header.fileNameTableOffset = currPos;

            currPos += fnt.size;
            rem      = currPos % 0x200;
            if (rem != 0)
            {
                while (rem < 0x200)
                {
                    bw.Write((byte)0xFF);
                    rem++;
                    currPos++;
                }
            }
            bw.Flush();
            bw.Close();

            Console.WriteLine(Tools.Helper.GetTranslation("Messages", "S09"), new FileInfo(fileFNT).Length);


            // Escribimos el FAT (File Allocation Table)
            string fileFAT = Path.GetTempFileName();
            header.FAToffset = currPos;
            Nitro.FAT.Write(fileFAT, accion.Root, header.FAToffset, accion.SortedIDs, arm9overlayOffset, arm7overlayOffset);
            currPos += (uint)new FileInfo(fileFAT).Length;

            // Escribimos el banner
            string banner = Path.GetTempFileName();
            Nitro.NDS.EscribirBanner(banner, romInfo.Banner);
            header.bannerOffset = currPos;
            currPos            += (uint)new FileInfo(banner).Length;

            // Escribimos los archivos
            string files = Path.GetTempFileName();
            Nitro.NDS.Write_Files(files, accion.ROMFile, accion.Root, accion.SortedIDs);
            currPos += (uint)new FileInfo(files).Length;

            // Update the ROM size values of the header
            header.ROMsize = currPos;
            header.tamaño  = (uint)Math.Ceiling(Math.Log(currPos, 2));
            header.tamaño  = (uint)Math.Pow(2, header.tamaño);

            // Get Header CRC
            string tempHeader = Path.GetTempFileName();
            Nitro.NDS.EscribirCabecera(tempHeader, header, accion.ROMFile);
            BinaryReader brHeader = new BinaryReader(File.OpenRead(tempHeader));
            header.headerCRC16 = (ushort)Ekona.Helper.CRC16.Calculate(brHeader.ReadBytes(0x15E));
            brHeader.Close();
            File.Delete(tempHeader);

            // Write header
            string header_file = Path.GetTempFileName();
            Nitro.NDS.EscribirCabecera(header_file, header, accion.ROMFile);


            Console.Write("<br>");
            #endregion

            if (!isMono)
            {
                espera.Abort();
            }


            // Obtenemos el nuevo archivo para guardar
            SaveFileDialog o = new SaveFileDialog();
            o.AddExtension    = true;
            o.DefaultExt      = ".nds";
            o.Filter          = "Nintendo DS ROM (*.nds)|*.nds";
            o.OverwritePrompt = true;
Open_Dialog:
            if (o.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                if (o.FileName == accion.ROMFile)
                {
                    MessageBox.Show(Tools.Helper.GetTranslation("Sistema", "S44"));
                    goto Open_Dialog;
                }

                espera = new Thread(ThreadEspera);
                if (!isMono)
                {
                    espera.Start("S06");
                }

                Console.WriteLine(Tools.Helper.GetTranslation("Messages", "S0D"), o.FileName);
                bw = new BinaryWriter(new FileStream(o.FileName, FileMode.Create));

                Ekona.Helper.IOutil.Append(ref bw, header_file);
                Ekona.Helper.IOutil.Append(ref bw, arm9Binary);
                Ekona.Helper.IOutil.Append(ref bw, arm7Binary);
                Ekona.Helper.IOutil.Append(ref bw, fileFNT);
                Ekona.Helper.IOutil.Append(ref bw, fileFAT);
                Ekona.Helper.IOutil.Append(ref bw, banner);
                Ekona.Helper.IOutil.Append(ref bw, files);

                rem = header.tamaño - (uint)bw.BaseStream.Position;
                while (rem > 0)
                {
                    bw.Write((byte)0xFF);
                    rem--;
                }
                bw.Flush();
                bw.Close();

                Console.WriteLine("<b>" + Tools.Helper.GetTranslation("Messages", "S09") + "</b>", new FileInfo(o.FileName).Length);
                accion.IsNewRom = false;
            }

            // Borramos archivos ya innecesarios
            File.Delete(header_file);
            File.Delete(arm9Binary);
            File.Delete(overlays9);
            File.Delete(arm7Binary);
            File.Delete(overlays7);
            File.Delete(fileFNT);
            File.Delete(fileFAT);
            File.Delete(banner);
            File.Delete(files);

            if (!isMono)
            {
                espera.Abort();
            }
            sb.Length = 0;
        }