1. 游客, мы просим Вас ознакомиться с Правилами Форума и Отказом от ответственности!

搜索结果

  1. Du10
    Эта тема уже освещена на жуке, но часть скринов там тупо потерялась, а так же есть не совсем понятные тонкости. Эта тема не претендует на отдельный гайд, она скорее всего дополняет топик на жуке. 1. Всяческими уловками ищем значение. 2. находится от 1 до 100 значений, которые меняются синхронно с значением в игре. 3. Добавляем все, и будем перебирать каждый. Авось, нужный да найдется. 4. Выбираем значение в нижнем списке (обращаем внимание на его адрес. У меня он такой: 0D07C510), щелк по нему Правой кнопкой мыши, и выбираем Find what writes to this adress (Найти что пишет на этот адрес). 5. Немного поизменяем значение в игре, дабы нашлось несколько значений. 6. В списке смотрим только на те, у которых в квадратных скобках есть что-то вроде следующего: 0099E1F2 - 89 87 80020000 - mov [edi+00000280],eax На месте edi может быть что-то другое, но обязательно должны быть квадратный скобки. 7. Выбираем это значение в списке, и тыкаем справа More information (больше информации). 8. Тут нас интерисует 2 цифры: - Это плюсуемое значение, подсвеченное красным. в моем случае это: 0099E1F2 - mov [edi+00000280],eax - И Оффсет. Оффсеты записанны в нижней части, и их там аж 9 штук. Какой же из них выбрать? А очень просто. Т.к. у нас в квадратных скобках именно EDI, то и оффсет смотрим от EDI. У меня это следующее: EDI=0D07C510 9. Закрываем окно с продробной информацией, останавливаем и закрываем поиск того, что ищет что пишет на адрес (Stop - Close). Тыкаем NewScan, указываем тип значение 4 Bytes, и отмечаем галочкой, что значение у нас в хексовом виде (Hex) Вставляем в строку поиска наш оффсет (у меня это 0D07C510) и ищем. 10. Если ничего не нашлось, то нам надо искать по другому игровому значению (мы же на 3 шаге добавили не одно, а несколько). Выбираем следующее значение, и идем начиная с шага 4. Если же нашлось что-то, то идем дальше. 11. В результатах поиска есть 3 колонки: - Adress (Адрес) - Value (значение) - Previous (предыдущее значение) Тыкаем Add Adress Manually (Добавить адрес вручную), отмечаем галочку Pointer (Указатель) и вбиваем туда следующие значения В поле Адрес вбиваем адрес первого найденного только-что значения (из колонки Adress), в поле Оффсет вбиваем первую цифру из 8 шага (у меня это 280). И смотрим на полученный результат сложения. Или у вас это может так-же называться The offset you choose brings it to: Он должен быть равен адресу значения из шага 4 (у меня это 0D07C510). Если он не равен - то вбиваем ручками следующий адрес из результатов поиска, и смотрим на результат сложения/ 12. Оффсеты совпали, и мы добавили указатель в наш список снизу. Далее тык по нему Правой кнопкой мыши и выбираем Find what acess this adress (Найти что получает доступ к этому адресу). Далее тык на первую кнопку Find what acess this pointer. Далее в игре поизменяем любым способом наше игровое значение. Найдется несколько значений. Нам нужно первое, у которого что-то плюсуется в квадратных скобках (как на шаге 6). Тыкаем More information (больше информации) и, как на 8 шаге, записываем или запоминаем те же 2 параметра (см. 8 шаг). У меня получились ESI значения, поэтому я смотрю оффсет ESI (02000368 ) и записываю плюсуемое значение (4). 13. Закрываем окна с подробной информацией и поиском, и начинаем новый поиск оффсета, как на шаге 9. Теперь ищем только-что найденный оффсет (у меня это 02000368 ). 14. В результате что-то находится. Подсвеченный зеленым адрес в первой кнолонке и есть наш базовый адрес. Если не находится, то идем на шаг 11, и добавляем указатель, используя следующий адрес из результатов поиска.
    作者: Du10, 2014-04-24, 2 个回复, 所属版块: Общее
  2. Du10
  3. Du10
    Всем здрасьте. Хочу обсудить кто как пишет чтение-сохранения файлов, дабы в процессе дискуссии выявить самые красивые и быстрые варианты. Начну с того, как пишу я. Для примера возмем файл Dynamicobjects.data (Чуть ли не самый простой файл). Структура Естественно-понятно, что прежде чем писать какой-то редактор или парсер файла - мы разбираем его структуру. У динамика структура (для 010) такова: struct object { int ID; int Length; char Path[Length]; }; int sign; int Count; object Object[Count]<optimize=false>; Код Далее я пишу класс, который будет содержать заголовочные переменные, и массивы каких-то блоков (их я объявляю структурой). А что бы код можно было легко и непринужденно переносить в другие проекты (и что бы в этом другом проекте не образовывалась свалка) - сразу переименовываю его в соответсвии с типом файла, с которым работаю Пример класса: using System; using System.Text; using System.IO; namespace DynObj { class DynObj { protected static int Sign = 1347242308; protected static DynObj_CS.Templates.Object[] Objects; } } Тут же в проекте создал папку (Folder), и обозвал её DynObj_CS. Тут будут располагаться все классы для работы с этим файлом. В ней создал папку Templates. Тут будут располагаться все структуры для этого файла. В папке Templates создал класс, и назвал его Object - в него я запишу под структуру Object. Содержимое этого класса: namespace DynObj.DynObj_CS.Templates { struct Object { public int ID; public string Path; } } Чтение в память Далее мы будем читать файл в память. Я делаю это так: В класс для чтения передаю массив байтов, которые закидываю в MemoryStream, к которому подключаю BinaryReader. Получается очень даже симпатичный код. using System; using System.Text; using System.IO; namespace DynObj.DynObj_CS { class Load : DynObj { public static void Start(byte[] fileArr) { MemStream = new MemoryStream(fileArr); file = new BinaryReader(MemStream); int inSign = file.ReadInt32(); if (inSign != Sign) throw new Exception("Неверный тип файла."); readObjects(); file.Close(); MemStream.Close(); } static void readObjects() { int count = file.ReadInt32(); Objects = new Templates.Object[count]; for (int i = 0; i < count; i++) { Objects[i].ID = file.ReadInt32(); Objects[i].Path = readString(); } } static string readString() { int Length = file.ReadInt32(); byte[] strArr = file.ReadBytes(Length); string result = Encoding.GetEncoding(936).GetString(strArr, 0, Length); //Кодировка (Encoding.GetEncoding(936)) захардкоженна а не передана в параметре, тк //в PW почти везде используется именно она //Но для гибкости можно передавать кодировку и в параметре return result; } static MemoryStream MemStream; static BinaryReader file; } } В основном классе подключаем чтение по имени файла и по массиву байт: using System; using System.Text; using System.IO; namespace DynObj { class DynObj { public static void Load(string fileName) { byte[] fileArr = File.ReadAllBytes(fileName); DynObj_CS.Load.Start(fileArr); } public static void Load(byte[] fileArr) { DynObj_CS.Load.Start(fileArr); } protected static int Sign = 1347242308; protected static DynObj_CS.Templates.Object[] Objects; } } Выгрузка из памяти Теперь напишем класс для сохранения всей той информации, что у нас есть. using System; using System.Text; using System.IO; namespace DynObj.DynObj_CS { class Save : DynObj { public static byte[] Start() { MemStream = new MemoryStream(GetFileSize()); file = new BinaryWriter(MemStream); file.Write(Sign); writeObjects(); byte[] result = MemStream.ToArray(); file.Close(); MemStream.Close(); return result; } static void writeObjects() { file.Write(Objects.Length); for (int i = 0; i < Objects.Length; i++) { file.Write(Objects[i].ID); writeString(Objects[i].Path); } } static int GetFileSize() { //Что бы у нас не было много циклов копирования памяти что бы //просто расширить её - мы сразу подсчитаем размер, который нам понадобится //Можно, конечно, задать какой-то фиксированный большой размер //НО для красивого и правильного примера мы так делать не будем int Size = 8;//Header for (int i = 0; i < Objects.Length; i++) { Size += 8;//ID и длинна строки byte[] tmpArr = Encoding.GetEncoding(936).GetBytes(Objects[i].Path); Size += tmpArr.Length; } return Size; } static void writeString(string Value) { byte[] strArr = Encoding.GetEncoding(936).GetBytes(Value); file.Write(strArr.Length); file.Write(strArr); } static MemoryStream MemStream; static BinaryWriter file; } } И подключим в основном классе сохранение: using System; using System.Text; using System.IO; namespace DynObj { class DynObj { public static void Load(string fileName) { byte[] fileArr = File.ReadAllBytes(fileName); DynObj_CS.Load.Start(fileArr); } public static void Load(byte[] fileArr) { DynObj_CS.Load.Start(fileArr); } public static void Save(string fileName) { byte[] fileArr = DynObj_CS.Save.Start(); //Создаем папку для файла - что бы при сохранении не ругался Directory.CreateDirectory(Path.GetDirectoryName(fileName)); File.WriteAllBytes(fileName, fileArr); } public static byte[] Save() { byte[] fileArr = DynObj_CS.Save.Start(); return fileArr; } protected static int Sign = 1347242308; protected static DynObj_CS.Templates.Object[] Objects; } } Итог Вот и всё :) Теперь мы можем загружать и сохранять этот файл. А в промежутке между этими действиями делать с ним всё что угодно :) P.S. Архив с этим проектом. http://files.mail.ru/E0C7DA0DA3AC4C689DB7025389CFB35E
    作者: Du10, 2014-02-13, 10 个回复, 所属版块: .NET
  4. Du10
  5. Du10
  6. Du10
  7. Du10
  8. Du10
  9. Du10
  10. Du10
  11. Du10
  12. Du10
  13. Du10
  14. Du10
  15. Du10
  16. Du10
  17. Du10
  18. Du10
    主题

    .ecm importer

    Простая программа для сбора всех нужных файлов для .ecm файла, или списка .ecm файлов. Resourses directory: каталог, который содежрит 4 под-каталога(gfx, models, sfx, grasses). Например: C:\PWRD\PW2\element. *.pck.files - Указывает на то, что, gfx, models, sfx, и grasses каталоги являются под каталогами папок (gfx.pck.files\gfx, models.pck.files\models, sfx.pck.files\sfx, grasses.pck.files\grasses). Output directory: Куда всё будет складываться. Например: C:\new\test. *.pck.files - указывает на то, что gfx, models, sfx, и grasses будут собранны в под-каталоги (gfx.pck.files\gfx, models.pck.files\models, sfx.pck.files\sfx, grasses.pck.files\grasses). Single .ecm file: указывает на то, что выбран один .ecm файл. List of .ecm files: указывает на то, что используется список .ecm файлов. From file: указывает на то, что список находится в файле. Примечание: список должен быть в Юникоде (UTF-16).From list: указывает на то, что список берется из программы. ECP: for Perfect World: указывает на то, что .ecp файлы (отвечающие за "каркас" (непроходимость) моделек), будут сложенны в grasses\ecmodelhull а не в models\ecmodelhull. Скачать: http://dump.ru/file/5339474 [img] Change log: v 1.1: - Исправленны мелкие баги; - Добавленн перенос .att файлов. v 1.2: - Исправленны мелкие баги; - Добавленна поддержка списка файлов в программе; - Добавленн перенос .ecp файлов.
    作者: Du10, 2011-08-07, 1 个回复, 所属版块: Архив
  19. Du10
  20. Du10