Перейти к содержимому


Фотография
- - - - -

IMG архив


  • Авторизуйтесь для ответа в теме
Сообщений в теме: 65

#41 OLEGator2

OLEGator2

    Участник

  • Пользователи
  • PipPip
  • 13 сообщений

Отправлено 24 May 2010 - 12:41

Приветствую всех!
Уважаемые подскажите с одним вопросом:
Пишу редактор для первой версии архива (Vice City) на скриптовом языке AutoIt
Возникла проблема в формировании имён файлов из 24 байт
Некоторые имена выглядят как положено типа: 0x726164617230302E74786400000000000000000000000000 (radar00.txd)
Где нули это оставшееся место и его спокойно можно выявить и отрезать от самого имени.

$filename = BinaryMid ($b_gta3_dir, 9 , 24); читаем 24 байта (имя файла в архиве)
$filename1 = BinaryToString ($filename); имя в виде текста
$filename2 = StringReplace ($filename1, BinaryToString ("0x00"), ""); удаляем все пустые байты

А встречаются и такие фрагменты: 0x6469617A2E646666006666000001130043003A005C005700 (diaz.dffffCW)
И формируется кривое имя как на скриншоте:
Изображение
Посоветуйте как быть? Пытался отфильтровать по кодам ASCII, но в мусорных байтах они тоже встречаются.

Сообщение отредактировал OLEGator2: 24 May 2010 - 12:46


#42 Chipsman

Chipsman

    Активный участник

  • Главные администраторы
  • PipPipPip
  • 786 сообщений
  • Пол:Не определился


Отправлено 24 May 2010 - 13:08

там идет Нуль-терминированная строка.
то есть тебе нужно читать до первого 0x00, все остальное - мусор (diaz.dff = 0x6469617A2E646666)

#43 OLEGator2

OLEGator2

    Участник

  • Пользователи
  • PipPip
  • 13 сообщений

Отправлено 24 May 2010 - 15:07

Эхх... Точно как я не заметил, что у всех присутствует хоть 1 фрагмент 0x00
Большое спасибо, продолжу работу. Думаю вопросы ещё возникнут...

--------- updated -----------
Реализовал вот так:

;~~~~~~~~~ функция Получения имени файла ~~~~~~~~
Func _GetName($b_bytes)
If $b_bytes = "" Then Return "" ; если ничего не передано, возвращаем пустоту
$sFileName = "0x" ; объявляем переменную для будующей строки
For $i = 1 To 24 ; крутим цикл 24 раза (так как 24 байта)
$b = BinaryMid ($b_bytes, $i, 1) ; каждый круг читаем по одному байту сначала
If $b <> "0x00" Then ; Если прочитанный байт не является 0x00
$sXX = Hex ($b, 2); то преобразуем в HEX (отрезается 0x)
$sFileName &= $sXX ; и объединяем его с переменной
Else ; иначе (тоесть уже строка сформирована и это был конец)
$sFileName = BinaryToString ($sFileName) ; преобразуем данные в строку
Return $sFileName ;и возвращаем из функции
EndIf
Next

$sFileName = BinaryToString ($sFileName) ; если вдруг не попалось 0x00, всёравно преобразуем данные в строку
Return $sFileName ; возвращаем всю целиком
EndFunc


Сообщение отредактировал OLEGator2: 24 May 2010 - 16:49


#44 Chipsman

Chipsman

    Активный участник

  • Главные администраторы
  • PipPipPip
  • 786 сообщений
  • Пол:Не определился


Отправлено 24 May 2010 - 15:42

чем сможем тем поможем:)

#45 OLEGator2

OLEGator2

    Участник

  • Пользователи
  • PipPip
  • 13 сообщений

Отправлено 25 May 2010 - 10:27

Реализовал извлечение файлов

Func _ExtractFile()
$index = _GUICtrlListView_GetSelectedIndices($ListView1, False); получаем индекс выбранного элемента
If $index = "" Then Return ; если вернулась пустота, значит ничего не выбрано
$index = Number ($index) ; преобразуем строку в число
$string = _GUICtrlListView_GetItemTextString($ListView1, $index); читаем текст элемента
$string = StringSplit ($string, "|"); разбиваем строку на 3 элемента имя|размер|оффсет (результат в виде массива)
$o_gta3_img = FileOpen ($gta3_img, 16) ; открываем файл gta3.img для чтения в бинарном режиме
$offset_dec = Dec ($string[3]) ; преобразуем офсет в десятичное значение (так как FileSetPos работает с ним)
FileSetPos ($o_gta3_img, $offset_dec, 0) ; встаём на офсет нужного нам файла (отсчёт с начала архива)
$bindata = FileRead ($o_gta3_img, $string[2]) ; читаем из архива нужное нам количество байт
FileClose ($o_gta3_img); закрываем gta3.img
$Foldertosave = FileSelectFolder ( "Укажите каталог извлечения", @ScriptDir, 1)
$Filetosave = $Foldertosave &"\"&$string[1]
$extractedFile = FileOpen ($Filetosave, 17)
FileWrite ($extractedFile, $bindata)
FileClose ($extractedFile); закрываем
MsgBox (0, "", "Имя: "&$string[1])
EndFunc

1. Возник вопрос: Что делать с пустым местом в конце последнего блока? Оставить его как есть или отрезать? Если отрезать, то как его вычислить?

2. В статье нет примера кода как удалять, заменять, добавлять новые файлы. Можно хотябы на словах принцип?
Я представляю так:
Удаление - из IMG архива вырезается фрагмент файла, из-за чего все смещения идущие после сдвигаются и необходимо их все пересчитать и записать в DIR файл и естественно ещё вырезать фрагмент информации о удалённом файле из DIR файла.
Добавление - Тупо в конец IMG файла дописываем фрагмент нового файла и также в конец DIR файла пишем 30 байт информации о нём.
Замена - запускам функцию удаления и потом функцию добавления в конец.
Но думается мне, что всё не так просто иначе зачем в программах есть функция Rebuild, как собственно она перестраивает архив?
Заранее спасибо за ответы.
з.ы.
Нет ли у кого желания написать библиотеку (DLL) для работы с основными форматами файлов? Было бы неплохо.

Сообщение отредактировал OLEGator2: 25 May 2010 - 10:31


#46 Chipsman

Chipsman

    Активный участник

  • Главные администраторы
  • PipPipPip
  • 786 сообщений
  • Пол:Не определился


Отправлено 25 May 2010 - 12:00

1. Ну настолько можно судить из IMGTool`а с пустыми байтами в конце последнего блока можно ничего не делать (так как он извлекает файлы с нулями в конце). На счет удаления этих пустых байтов в конце файлов, вероятно нужно знать формат этих самих файлов, так как если просто удалить все пустые байты то можно удалить чего нибудь нужное. 2. Вообще твоя логика нормальная А вот тот же IMGTool, судя по всему, работает иначе (но я точно утверждать не могу): Удаление: он просто удаляет элемент с .dir файла, сам имг судя по всему не трогает Добавление: добавляет новый элемент в конец .dir файла и сам файл в конец имг Замена: если файл, которым заменяют, <= по размеру чем файл, который заменяют, то тупо идет замена соответствующих байт в имг-архиве (насколько я помню если файл > по размеру, то прога говорила что замена не возможна) как видно с этого всего с одной стороны это работает быстро, с другой - весь мусор остается в имг (удаленные файлы на самом деле не удаляются и т.п.), поэтому даже если удалить половину файлов в архиве, то меньше он весить от этого не станет. Вот и поэтому и присутствует такая функция как Rebuild, которая делает новый архив и ссылаясь на .dir файл последовательно копирует(добавляет) все файлы из старого имг попутно меняя инфу о смещениях в самом .dir файле. Если реализовывать по твоей логике то сами операции будут выполнятся за большее время но зато не нужно будет никакого ребилдинга

#47 OLEGator2

OLEGator2

    Участник

  • Пользователи
  • PipPip
  • 13 сообщений

Отправлено 25 May 2010 - 12:11

Вобщем хочется сделать качественно, попробую реализовать удаление как я изложил выше. А с заменой спасибо за подсказку, если новый файл меньше или равен старому, буду писать его в тоже место.

#48 XEPOMAHT007

XEPOMAHT007

    Активный участник

  • LCSTeam
  • PipPipPip
  • 472 сообщений
  • Пол:Мужчина


Отправлено 27 May 2010 - 21:56

Что то про img-архивы сториесов написано совсем скудно, решил дописать то, что там не хватает:

===Версия 2А - GTA:LCS и GTA:VCS===
(описание сформировано по данным LCS TEAM)
Архивы портативных GTA делятся на два типа - сжатые и несжатые.

Сжатые архивы подразделяются на [[GAME.DTZ]] (DTZ можно расшифровать как DaTa Zlib) и на архивы с расширением LVZ, расположенные рядом с одноимёнными IMG-архивами (например около INDUST.IMG будет располагаться INDUST.LVZ, поэтому раньше считалось, что LVZ - это новый формат dir, на самом деле это не так). Сами архивы запакованы с помощью алгоритма Zlib, для их распаковки рекомендуется использовать утилиту DTZ Editor by Dageron. Для просмотра и извлечения содержимого подходит любой HEX-редактор.

Структура несжатого архива почти не отличается от структуры версии 1. Так же как и в GTA SA, в GTA LCS и GTA VCS отсутствуют <code>.dir</code> файлы, исключение - архив CUTS.IMG в LCS и MOCAPPS2.IMG в VCS. Для GTA3PS2.IMG существуют несколько директорий. Одна из них - стандартный dir-файл, содержащий имена и пути к моделям, участвующим в cut-сценах. Этот dir легко находится в [[GAME.DTZ]] (вполне достаточно ввести в окошке поисковика TextString слово LDM (это формат моделей в сториесах)), извлечь от туда, переименовать в GTA3PS2.DIR и открыть с помощью IMGtool. Полная директория к GTA3PS2.IMG имеет другую структуру, нежели в обычном dir.

Длинна строки директории = 14 байт
Первые 2 байта = номерочек файла (директорию, которую выложил я, нумерация начинается с 94). Если номер файла = -1, значит в этой строке ничего нету, её при чтении пропускаем.
Следующие 4 байта = смещение файла в блоках (аналогично стандартному dir)
Следующие 4 байта = размер файла в блоках (аналогично стандартному dir)
Далее идут нули, заканчивающиеся неизвестным параметром, варьирующим от 0 до 4х.

Для работы с данным форматом директорий программ не существует, поэтому приходится вручную переписывать смещение и размер в "чистый" обычный dir и после этого архив можно открывать с помощью IMGtool.

Для более удобного просмотра и извлечения содержимого GTA3PS2.IMG применяется утилита [[YAIE]], которая на основе идентификаторов LDM, XET, MINA и 2LOC создаёт dir-файл без надобности извлечения каких-то данных из [[GAME.DTZ]].

Извлечение оставшихся архивов так же делается в ручную, с помощью HEX-редактора в силу того, что директории к ним до сих пор не найдены.

Сообщение отредактировал XEPOMAHT007: 27 May 2010 - 21:57

a4ea86ab343c.gif
BETA 4.0 COMING SOON


#49 TEDERI

TEDERI

    Новичок

  • Пользователи
  • Pip
  • 2 сообщений

Отправлено 29 June 2010 - 10:46

Вопрос к знатокам. Уже достаточно давно бьюсь над казалось бы простой задачей - добавить в архив 2-й версии новый файл. Посмотрел в исходники и увидел, что после записи файла в архив нужно прописать в конце ноли, количество которых равняется размеру добавленного файла. Вопрос такой: нужно ли их действительно прописывать и зачем?

#50 Chipsman

Chipsman

    Активный участник

  • Главные администраторы
  • PipPipPip
  • 786 сообщений
  • Пол:Не определился


Отправлено 29 June 2010 - 11:19

после записи файла в архив нужно прописать в конце ноли, количество которых равняется размеру добавленного файла.


кто тебе такое сказал, где такое увидел?

нулей нужно дописывать ровно столько, чтобы размер файла в архиве стал кратным двум КБ (например, есть у тебя файл 2000 байт, при добавлении его в архив тебе нужно дописать вконец 24 байта нулей, если, например, у тебя файл размером 6144 байт = 6 КБ, то дописывать ничего не нужно )

#51 TEDERI

TEDERI

    Новичок

  • Пользователи
  • Pip
  • 2 сообщений

Отправлено 29 June 2010 - 11:43

кто тебе такое сказал, где такое увидел?

В исходниках доп. функция, в ней описана эта процедура.
В остальном - спасибо за оперативную помощь...

#52 Sweet

Sweet

    Активный участник

  • Пользователи
  • PipPipPip
  • 418 сообщений
  • Пол:Мужчина
  • Город:Нижний Новгород


Отправлено 03 June 2011 - 13:32

Может кто-нибудь выложить исходники редактора IMG (или хотя бы ридера) для San Andreas (версии 2)? Интересно посмотреть.

#53 Chipsman

Chipsman

    Активный участник

  • Главные администраторы
  • PipPipPip
  • 786 сообщений
  • Пол:Не определился


Отправлено 03 June 2011 - 18:34

ну если бы у меня были то выложил бы, посмотрим может еще у кого есть :) а в чем проблема свои написать? формат на вики вроде расписан подробно, если есть в чем-то конкретно загвоздка/вопросы то спрашивай, разберемся вместе)

#54 XEPOMAHT007

XEPOMAHT007

    Активный участник

  • LCSTeam
  • PipPipPip
  • 472 сообщений
  • Пол:Мужчина


Отправлено 03 June 2011 - 22:20

На мапсе лежит темка про читальник IMG на дельфе + там есть исходник в аттаче: http://gtamaps.net/f...showtopic=10641

Например никто почему-то не написал распаковщик для BEACH.IMG, MAINLA.IMG и MALL.IMG в ВСС, формат архивов, как и в случае ЛСС, давно расковырян, но всё дело упирается в незнание того, как заставить дельфу понимать оффсеты и находить по ним начало файла и его размер.

Сообщение отредактировал XEPOMAHT007: 03 June 2011 - 22:27

a4ea86ab343c.gif
BETA 4.0 COMING SOON


#55 VcSaJen

VcSaJen

    Активный участник

  • Пользователи
  • PipPipPip
  • 270 сообщений
  • Пол:Мужчина
  • Интересы:GTA, скриптинг в GTA.


Отправлено 04 June 2011 - 04:23

TFileStream тебе в помощь. (.Seek, .Read, .Write) Хотя может быть может я неправильно понял вопрос (В VCS не моддил).

Сообщение отредактировал VcSaJen: 04 June 2011 - 04:24


#56 Sweet

Sweet

    Активный участник

  • Пользователи
  • PipPipPip
  • 418 сообщений
  • Пол:Мужчина
  • Город:Нижний Новгород


Отправлено 04 June 2011 - 06:08

Прочитал тему на мапсе (просветился работой со стримами), при открытии IMG архива в ListView: во-первых - нет колонок, во-вторых - китайские символы за место имён.

#57 Chipsman

Chipsman

    Активный участник

  • Главные администраторы
  • PipPipPip
  • 786 сообщений
  • Пол:Не определился


Отправлено 04 June 2011 - 08:33

колонки нужно создать либо в в свойстве Columns (или пкм на ListView и выбрать Columns editor), либо создавfть в рантайме при создании формы наверняка проблема с "иероглифами" в том, что исходники написаны под Delphi 7 (я не смотрел), а ты компилишь в делфи 2009+, где по умолчанию для строк используется юникод, в таком случае тебе надо заменить все вхождения string на AnsiString и все вхождения Char на AnsiChar (аналогично если есть PChar на PAnsiChar и т.п.)

#58 Sweet

Sweet

    Активный участник

  • Пользователи
  • PipPipPip
  • 418 сообщений
  • Пол:Мужчина
  • Город:Нижний Новгород


Отправлено 04 June 2011 - 15:14

Chipsman, спасибо, разобрался.

#59 Chipsman

Chipsman

    Активный участник

  • Главные администраторы
  • PipPipPip
  • 786 сообщений
  • Пол:Не определился


Отправлено 04 June 2011 - 15:24

не за что

#60 djsystem

djsystem

    Новичок

  • Пользователи
  • Pip
  • 2 сообщений

Отправлено 07 April 2012 - 10:59

Привет )) Вот посмотрел Структуру Img2 и нухрена не смог написать по этим данным программу ZZZZ PS: Криворукий Автор ;) Без обид; Однако Смог Найти Структуру :

char {4} - Заголовок (VER2)
uint32 {4} - Количество файлов

// цикл получения имён
uint32 {4} - Начало блока файла *2048 От начала файла а не от текущей позиции
uint32 {4} - Размер файла *2048
char {X} - Имя файла
byte {1} - Нулевой байт Для определения конца имени
byte {0-3} - Небольшой шифр Длинна имени +1 и по такому алгоритму т.е a[i]=b[i]
a(4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24);
b(20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0);

// конец цикла
// ну а тут уже файлы пошли
byte {X} - файл дата
Ну а Кому нужен исходник Распаковки (delphi cmd) сюда 569006813 или если чё сюда выкину




Количество пользователей, читающих эту тему: 1

0 пользователей, 1 гостей, 0 анонимных