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, 24 апр 2014, ответов - 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, 13 фев 2014, ответов - 10, в разделе: .NET
  4. Du10
  5. Du10
  6. Du10
  7. Du10
  8. Du10
  9. Du10
  10. Du10
  11. Du10
  12. Du10
  13. Du10
    Сообщение

    [WL] JoLan

    - Админ форума не может быть в WL.
    Сообщение от: Du10, 24 окт 2013 в разделе: Сообщество
  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, 7 авг 2011, ответов - 1, в разделе: Архив
  19. Du10
  20. Du10