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); }
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); }
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; }