IPB

Добро пожаловать, гость ( Вход | Регистрация )

> Alien Trilogy (PC), разбор ресурсов
LexSafonov
Oct 29 2020, 17:48
Сообщение #1


Member
**

Группа: Authorized
Сообщений: 21
Регистрация: 29-October 20
Пользователь №: 18,034
Спасибо сказали: 1 раз(а)



Всем привет, решил создать тему про разбор форматов ресурсов игры Alien Trilogy, преимущественно её ПК варианта. Некоторые ресурсы лежат довольно открыто, но есть некоторые, весьма нестандартные.
Но обо всём по порядку.

Начну я вот с чего.
Из довольно открытых ресурсов - это звуки, это обычные raw-данные без заголовка. Спокойно съедается через Sound Forge или аналогичные программы, достаточно выставить нужный битрейт.
Так же из открытых ресурсов можно выделить текстуры, о них я напишу ниже, т.к. это напрямую связано с "секциями" BND(B16) файлов.
Кстати говоря о этих файлах. Игра использует BND "архивы", для хранения ресурсов - моделей, текстур, спрайтов, текстурных сеток для моделей. Ещё есть аналог BND - B16, в которых лежат данные от 16 битных вариаций текстур\спрайтов.
Вернёмся к так называемым "секциям". В файлах встречаются вот такие секции:

F000(#1,2,3....) - F? - Frame, кадр, используется такая секция у спрайтов. Может внутри себя содержать несколько изображений. Об этом я напишу далее и расскажу об одной особенности.
T000(#1,2,3....) - T? - Texture, текстура. Тут всё проще, у таких секций есть строгие параметры, как у обычных изображений, длина ширина, нет компресии(что самое главное), изображение содержит идексы цветов. Спокойно дёргается XWE редактором. Может быть несколько штук в одном месте. Вообще эта секция достаточно интересная, т.к. используется у моделей\карт, рядом с этой секцией обычно бывает лежит ещё секция с индексами полигонов.
M000(#1,2,3....) - M? - Model, модель. Тут всё просто, эта секция отвечает за модели. Имет список квадов(не полигонов!)\вершин. Прикол с квадами очевидно связан с тем, что изначально игру лепили для двух приставок - PS и Sega Saturn. Так вот, на сколько помню у сеги вроде бы аппаратная часть лучше работала именно с квадами. И вроде бы(поправьте, если не прав) - сначала игру делали именно для сеги. Но не суть, в файле именно описание квадов. В одном файле может быть несколько штук
таких секций.
BX00(#1,2,3....) - BX? - прямоугольники для текстурирования квадов(полигонов) в модели.Что то типа текстурной сетки.
CX00(#1,2,3....) - CX? - пока не разбирал и не смотрел реакцию игры на эту секцию.

Вот описание формата моделей текстом от моего товарища по думу ZZYZX:

Разбор формата PICKMOD.BND текстом

- сначала заголовок файла:
размер содержимое комментарий
-------------------------------------------------------------------------------------------------------------------------
0x04 46 4F 52 4D FORM
0x04 - размер данных файла в байтах, BIG-ENDIAN (перевёрнутый как на сраном арме)
0x04 - количество моделей в файле текстом. всегда 4 символа (формат %04d)

- дальше идут модели по очереди. у каждой модели есть:
размер содержимое комментарий
-------------------------------------------------------------------------------------------------------------------------
0x01 4D первая буква идентификатора M (M000, M001, ...)
0x03 - индекс модели текстом. всегда три символа (формат %03d)
0x04 - размер данных модели в байтах, BIG-ENDIAN
0x04 4F 42 4A 31 OBJ1
0x08 00 00 00 00 00 00 00 00 неизвестное значение
0x04 - количество прямоугольников в модели. LITTLE-ENDIAN
0x04 - неизвестное значение
0x14*N - прямоугольники по очереди (см. формат дальше)
0x08*N - вершины по очереди (см. формат дальше)

- формат прямоугольника:
размер содержимое комментарий
-------------------------------------------------------------------------------------------------------------------------
0x04 - индекс первой точки. LITTLE-ENDIAN
0x04 - вторая точка
0x04 - третья точка
0x04 - четвёртая точка. может быть -1 (0xFFFFFFFF), тогда это треугольник и надо продублировать третью точку.
0x04 - неизвестное значение

- формат вершины:
размер содержимое комментарий
-------------------------------------------------------------------------------------------------------------------------
0x02 - координата X (signed, LITTLE-ENDIAN, short)
0x02 - координата Y
0x02 - координата Z
0x02 - неизвестное значение, вроде бы всегда 0

А вот и текстурная сетка для моделек

Разбор формата PICKGFX.BND текстом

- сначала заголовок файла:
размер содержимое комментарий
-------------------------------------------------------------------------------------------------------------------------
0x04 46 4F 52 4D FORM
0x04 - размер данных файла в байтах, BIG-ENDIAN
0x04 50 53 58 54 PSXT (вероятно идентификатор формата)

- дальше идут (в произвольном порядке?) секции INFO, TP00, CL00, BX00. Возможно бывают *01, *02 и так далее, но мне не встречались.
- секция INFO
размер содержимое комментарий
-------------------------------------------------------------------------------------------------------------------------
0x04 49 4E 46 4F INFO
0x04 - размер данных секции в байтах, BIG-ENDIAN
0x02 - размер текстуры X
0x02 - размер текстуры Y
0x0C - неизвестная информация, 12 байт

- секция TP00
тут тупо лежат WxH пиксели. каждый пиксель = 1 байт. смещение в палитру текущую экрана. найти можно в PALS/WSELECT.PAL (768 байт, 3 байта на каждый цвет, умножить на 4 каждый компонент)

- секция CL00
тут лежит неизвестно что. не кантовать.

- секция BX00
тут лежат прямоугольники текстуры для текстурирования квадов.
размер содержимое комментарий
-------------------------------------------------------------------------------------------------------------------------
0x04 42 58 30 30 BX00
0x04 - размер данных секции в байтах, BIG-ENDIAN
0x04 - количество прямоугольников
- - прямоугольники по очереди (см. формат дальше)

- формат прямоугольника текстуры BX00
размер содержимое комментарий
-------------------------------------------------------------------------------------------------------------------------
0x01 - размер по X (-1 пиксель, т.е. 31 вместо 32 и так далее)
0x01 - размер по Y (-1 пиксель)
0x01 - неизвестное значение
0x01 - неизвестное значение
0x01 - смещение по X с конца (т.е. надо отнять ширину перед использованием)
0x01 - смещение по Y

C000(#1,2,3....) - C? - Color, цвет, секция, очевидно отвечающая за цвет. У файлов B16, такая секция идёт в самом конце. Формат этой секции такой:

0x04 - С000
0x04 - кол-во байт, отведённых под цвета\палитру.
0x02 - непосредственно цвета, по 2 байта на цвет(обычно)

У этой секции есть одна особенность - в некоторых файлах бывает так, что кол-во байт под палитру меньше 512, не понял с чем это связано. Если я правильно понимаю логику, то 512\2 = 256 ячеек(если отталкиваться от каких то простых форматов тип BMP). Вроде бы во многих мануалах пишут, что 16 бит именно так и работает, поправьте, если я не прав.


Теперь вернёмся с секциям F000, которые отвечают за спрайты. Собрал небольшое описание, в основном из экспериментов с пожатыми данными в Hex-редакторе.
Временное описание формата:


0x04 - Заголовок файла FORM
0x04 - размер данных файла в байтах, BIG-ENDIAN
0x04 - кол-во блоков, видимо текст

-------------------------------------------------------------------------------------------------------------------------
0x04 - индентификатор F000
0x04 - Длина до следующей секции, видимо в бинарном представлении.
0x01 - Непонятный байт, крошит изображение, есть подозрение, что это длина алфавита или какой то цепочки байт. Это не длина\ширина. Ниже объясню.
0x0? - Цвета и повторения.


Формат повторений
0x01 - Код цвета
0х01 - Флаг\префикс повторений(обычно символ P, т.е. в Hex коде 50)
0х01 - промежуток повторений(через какой промежуток надо повторить этот цвет)
0х01 - кол-во раз повторений(сколько пикселей рисовать в ряд
https://www.old-games.ru/forum/attachments/...mat-png.211586/
немного наглядности из примерного описания формата, файл MM9.B16

По поводу формата повторений. У него тоже есть определённые условия, а именно, описание верно только для одного условия - когда первое число после префикса равно 1. Видимо для игры это обозначает рисовать цвет сплошняком. Плюс изначально для сплошного цвета игра прибавляет в ряд толи 8, толи 10 неубираемых пикселей. Я насчитал 10.
В файле присутствуют варианты, когда первый байт после префикса больше единицы. Из своих экспериментов пока только сделал вывод, что что-то двигается(из пикселей), но не понял закономерности. Иногда бывает, что в повторениях походу висят какие-то ссылки на другие места. Кстати об этом тоже по подробнее.

В один момент я решил разбирать вообще сплошняком побайтово, но запутался ещё больше:
https://www.old-games.ru/forum/attachments/...ble-png.215950/
красный - видимо ссылки, при изменении ломают изображение
желтый - меняют цвет в нескольких местах, либо подставляют туда какой то кусок
синий - одиночный пиксель
голубой - нет эффекта, либо эффект незаметен
бардовый - нули, непонятно чё делают, если изменить на значение, отличное от нуля, то в изображении пропадают пиксели(местами).

Из переписки с -=CHE@TER=- я увидел, что стандартных данных, как у любой другой картинки, в файле нет, т.к. он нашёл указатель на этот самый пистолет в TRILOGY.EXE, где благополучно лежит длина и ширина кадра.

Теперь по поводу магического числа, ломающего изображение. В MM9.B16 это 92(Hex вариант).
Я пошёл ещё дальше и решил сделать "чистый" кадр. Забил всё одиночными пикселями, с цветом 01, а само число 92 поставил на нуль. Получил такую картину:
https://www.old-games.ru/forum/attachments/nulls-png.216418/
Откуда то взялась лесенка. Байт, где число 92, каким то образом на неё влияет, как будто сдвигает её. Закономерности сдвигов не понял, двигает всегда на разную длину(если менять значение).
Потом забил серый цвет. Лесенка уменьшилась, а само изображение увеличилось(по идее ничего не должно было подобного произойти):
https://www.old-games.ru/forum/attachments/probe-png.216419/

Вопрос к знатокам - может, кто то видел подобное? Похоже на LZX, но какое то своё, хитро-мудрое.
Я описывал B16 вариант, но на сайте old-games, чувак с ником ak48 видимо пробовал смотреть BND аналог и там какие то вывороты с палитрой жёсткие)
User is offlineProfile CardPM
Go to the top of the page
+Quote Post
 
Reply to this topicStart new topic
Ответов
LexSafonov
Nov 16 2020, 19:24
Сообщение #2


Member
**

Группа: Authorized
Сообщений: 21
Регистрация: 29-October 20
Пользователь №: 18,034
Спасибо сказали: 1 раз(а)



И так, после долгого мучения и раздумий, я наконец заставил мои 2 инструмента работать в полной мере, Пока что очень тестово(т.к. наверняка есть баги, которые я не успел отловить).

BNDEXTRACTOR - Это инструмент "декомпановщик" BND(B16) бинарных файлов.
Использование: Перетащите BND(B16) файл на exe файл программы. В корневой директории программы создадутся файлы с такими именами - F000/1/2/3 и C000.
Секции F000\1\2\3 - секции, содержащие в себе спрайты. В одной и той же секции могут быть по несколько штук спрайтов. Данные секции - это "сырые" сжатые спрайты, информация о которых
зашита в исполняемый файл игры.
Секция C000 - есть только у B16 вариантов файлов со спрайтами, это секция - 16 бит палитра. Содержит в себе по 2 байта на цвет.

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

После того, как вы "декомпануете" BND(B16) файл, используйте далее инструмент FDecompressor.

FDecompressor - это инструмент, который одновременно "декомпанует" секции F000\1\2\3 на отдельные одиночные спрайты и декомпрессует их.
Использование: Перетащите файл с названием F000\1\2\3 на исполняемый файл. На выходе получаются файлы D000\1\2\3...N, которые можно
спокойно просмотреть инструментами для "сырых" данных. Например TiledGGD. В TiledGGD в качестве палитры выбирайте файл с названием C000 и выставляйте режим 2 байта на цвет.

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

Ссылка на архив с инструментами:
http://www.filedropper.com/trilogydecompress

Ну и пару скриншотов на последок, для затравки))



Обе программы чисто исходными кодами(если вдруг файл снесут с хостинга, можно будет скомпилить в 2008 студии)

Декомпановщик
CODE
// BNDEXTRACTOR - программа "раскомпоновщик" структур BND-архивов. По сути это даже не архивы, а контейнеры со своими блоками(секциями).
//Сразу делаю оговорку на то, что у игры есть два варианта спрайтов - B16 и BND. Файлы B16 хранят в себе дополнительную секцию с цветами C000 и более насыщены.
//Bnd варианты имеют слишком "зернистую" графику из-за строгой привязанности к простой "общей" палитре(эдакий облегчённый вариант).
//На данный момент пишу по простому. Из-за недостатка знаний.

#include "stdafx.h"
#include <math.h>
#include <iostream>
#include <fstream>
#include <string>
#include <stdlib.h>
#include <stdint.h>
#include <cstdlib> // для system
using namespace std;
typedef unsigned __int32 uint32_t;



int main(int argc, char *argv[])
{
    char *FileName = argv[1]; //Текущее имя файла. Нюанс - в параметрах коммандной строки массив строк, строку надо перевести в массив символов.
    char ch;
    char FileExt[4];
    FileExt[3] = '\0';
    int ProgrammMode; //Чтобы "извлечь" секцию цветов, если таковая есть. А она есть в B16 файлах.
    int i = 0;
      while(true)
      {
         ch = FileName[i];
         if(ch != 0)
         {
             if(ch == '.')
             {
              i++;
              FileExt[0] = FileName[i];
              i++;
              FileExt[1] = FileName[i];
              i++;
              FileExt[2] = FileName[i];
                   if(FileExt[0] == 'B' && FileExt[1] == 'N' && FileExt[2] == 'D')
                           {
                           ProgrammMode = 0;
                           cout << "Set BND mode" << endl;
                           break;
                           }
                   else if(FileExt[0] == 'B' && FileExt[1] == '1' && FileExt[2] == '6')
                          {
                          ProgrammMode = 1;
                          cout << "Set B16 mode" << endl;
                          break;
                          }
             }
         }
        i++;
      }


    unsigned char ByteBuffer[4]; //Все смещения и длины в файле представлены в прямом порядке, а не в обратном, как читает сишный язык. Этот "буффер" решает проблему.
    int FileLenth; //Размер файла, 4 байта
    int SectionNumbers; //Это чтобы собрать текст в число в правильном порядке.
    char SectionName[5]; //Название секции, текст, 4 байта
    SectionName[4] = '\0'; //Это чтобы собиралось название, обрубает всё "нулём".
    int SectionLenth; //Длина секции, 4 байта
    int ColorNumbers; //Кол-во цветов в секции

    int CurrentPosition; //Указатель в файле
    

    FILE* BNDFileIn; //Входной файл
    FILE* BNDFileOut;//Выходной файл
    BNDFileIn = fopen(FileName, "rb");
    
    //-------Существуют ли наши файлы-----//
    if(BNDFileIn == NULL) // Существует ли такой файл в папке с программой.
    {
      cout << "Can't open input file" << endl;
      system("pause");
      return 0;

    }


    CurrentPosition=4;
    fseek(BNDFileIn, CurrentPosition, SEEK_SET);
    fread(&ByteBuffer, 1, 4, BNDFileIn);
    FileLenth = ByteBuffer[3] | (ByteBuffer[2] << 8) | (ByteBuffer[1] << 16) | (ByteBuffer[0] << 24); //Разворачиваем число и получаем корректную длину файла.
  
     CurrentPosition+=4; //Ещё на 4 байта вперёд, читаем кол-во секций.
     fseek(BNDFileIn, CurrentPosition, SEEK_SET);
    
     fread(&ByteBuffer, 1, 4, BNDFileIn);
     ByteBuffer[0] -= 0x30;//Делаем из текста число.
     ByteBuffer[1] -= 0x30;
     ByteBuffer[2] -= 0x30;
     ByteBuffer[3] -= 0x30;
     SectionNumbers = ByteBuffer[3] | (ByteBuffer[2] << 8) | (ByteBuffer[1] << 16) | (ByteBuffer[0] << 24); //Тоже самое, только с кол-вом секций.

     CurrentPosition+=4; //Ещё на 4 байта вперёд, читаем название секции, которое запишем в название выходного файла.
     fseek(BNDFileIn, CurrentPosition, SEEK_SET);
     fread(SectionName, 1, 4, BNDFileIn);
    
     CurrentPosition+=4; //Ещё на 4 байта вперёд, читаем длину секции.
     fseek(BNDFileIn, CurrentPosition, SEEK_SET);
     fread(&ByteBuffer, 1, 4, BNDFileIn);
     SectionLenth = ByteBuffer[3] | (ByteBuffer[2] << 8) | (ByteBuffer[1] << 16) | (ByteBuffer[0] << 24);
//Здесь начинается цикл, который разделит нам файл на отдельные секции.
//Файлы с названием F00x - это спрайты, пожатые, похожим на LZX, алгоритмом. Без дополнительной информации(длина\ширина),
//зашито в игровой движок в анимационных струкрурах
     CurrentPosition+=4; //Ещё на 4 байта вперёд, приступаем к циклу.
     fseek(BNDFileIn, CurrentPosition, SEEK_SET);

     SectionLenth=SectionLenth+CurrentPosition;
     int CurrentSection;
     int CurrentByte;

     CurrentSection = 1;

     while(true)
     {
        if(CurrentSection > SectionNumbers) { break; } //Если все секции раскомпанованы, то заканчиваем цикл.
        BNDFileOut = fopen(SectionName, "a+b"); //надо собирать название.
        if(BNDFileOut == NULL)
           {
            cout << "Out File is not enough!!" << endl;
            break;
            }
        while(true)
          {


             fread(&CurrentByte, 1, 1, BNDFileIn); //побайтово читаем
             fwrite(&CurrentByte, 1, 1, BNDFileOut); //Побайтово пишем
             CurrentPosition++;
             fseek(BNDFileIn, CurrentPosition, SEEK_SET);
             //Объяснение, чтобы не забыть. В файле прямой порядок чтения байтов(не обратный!)
             //С этим и связано побайтовое чтение. Очередное упрощения для себя


             if(CurrentPosition == SectionLenth) //Если достигнут конец секции
             {
               CurrentSection++;
               //CurrentPosition++;
               fseek(BNDFileIn, CurrentPosition, SEEK_SET);
               fread(&SectionName, 1, 4, BNDFileIn); //Читаем название новой секции

               CurrentPosition+=4; //Ещё на 4 байта вперёд, читаем длину секции.
               fseek(BNDFileIn, CurrentPosition, SEEK_SET);
               fread(&ByteBuffer, 1, 4, BNDFileIn);
               SectionLenth = ByteBuffer[3] | (ByteBuffer[2] << 8) | (ByteBuffer[1] << 16) | (ByteBuffer[0] << 24);
                    
               CurrentPosition+=4; //Ещё на 4 байта вперёд, новый заход
               fseek(BNDFileIn, CurrentPosition, SEEK_SET);
               SectionLenth=SectionLenth+CurrentPosition;
               break;
             }
           }

       }

     if(ProgrammMode == 1)//только для файлов B16,извлечение палитры 16 бит.
     {

        CurrentPosition-=8;
        fseek(BNDFileIn, CurrentPosition, SEEK_SET);
        fread(&SectionName, 1, 4, BNDFileIn); //Читаем название новой секции
        
        CurrentPosition+=4;
        fread(&ByteBuffer, 1, 4, BNDFileIn);
        ColorNumbers = ByteBuffer[3] | (ByteBuffer[2] << 8) | (ByteBuffer[1] << 16) | (ByteBuffer[0] << 24);
        CurrentPosition+=4;

        SectionLenth=ColorNumbers+CurrentPosition;
        BNDFileOut = fopen(SectionName, "a+b"); //Секция с цветами
        while(true)
          {
          if(CurrentPosition >= SectionLenth) { break; } //Если все секции раскомпанованы, то заканчиваем цикл.
          if(BNDFileOut == NULL)
           {
            cout << "Out File is not enough!!" << endl;
            break;
            }
             fread(&CurrentByte, 1, 1, BNDFileIn); //побайтово читаем
             fwrite(&CurrentByte, 1, 1, BNDFileOut); //Побайтово пишем
             CurrentPosition++;
             fseek(BNDFileIn, CurrentPosition, SEEK_SET);
           }

       }
      fcloseall(); //закрываем все файловые потоки.
      system("pause"); // Только для тех, у кого MS Visual Studio
      return 0;
}



Декомпрессор
CODE

/* FDecompressor - Декомпрессор спрайтов(секций F000\1\2). Очень похож на LXZ, только обратный. Оригинальный код взят у -=CHE@TER=-, он отловил процедуру.
Ниже после программы в комментариях будет функция PicDecoder, откуда собственно и взят сам алгоритм декомпресии.
Немного из истории - данные секции не имеют стандартных "длины" и "ширины" изображения, все параметры забиты в исполняемом файле игры. Все данные собираются
в единое в анимационных структурах.Одна секция может содержать в себе сразу несколько штук спрайтов. Если программа увидит, что длина позиции не в конце,
то механизм декомпресии запустится заного.Декомпрессованые изображения спокойно смотрятся через программу TiledGGD(вьювер сырых данных) - для корректного
отображения цвета в качестве палитры выбирайте секцию C000(Color), формула такой секции - 2 байта на цвет.
Декомпановщик BNDExtractor извлекает её, если встречает B16 файл. Для BND файлов применяется общая "зернистая" палитра видимо из GUNPALS.pal

[code]#include "stdafx.h"
#include <math.h>
#include <iostream>
#include <fstream>
#include <string>
#include <stdlib.h>
#include <pstdint.h>

#include <cstdlib> // для system
using namespace std;




int main(int argc, char *argv[])
{
    char *FileName = argv[1];
    char OutPutFileName[5]; //Нужно, чтобы собиралось название, если спрайтов больше одного
    OutPutFileName[0] = 'D';
    OutPutFileName[1] = '0';
    OutPutFileName[2] = '0';
    OutPutFileName[3] = '0';
    OutPutFileName[4] = '\0'; //Это чтобы собиралось название, обрубает всё "нулём".
    FILE* InputFile; //Входной файл
    FILE* OutputFile;//Выходной файл
    
    InputFile = fopen(FileName, "rb");
    int CurrentPosition = 0;
    int OutFilePosition = 0;
    unsigned char CurrentByte;
    unsigned char OutputByte;
    
    
    fseek(InputFile, 0, SEEK_END);
    int LengthOfFile = ftell(InputFile);

    int i, offs, size, CurrentNameNumber;
    int FileLenthResult = LengthOfFile-2;
//Главный цикл, проверяет конец файла и запускает механизм декомпресии
while(true)
{
if(CurrentPosition >= (LengthOfFile-2)) //Если указатель уехал в конец, то выходим из главного цикла и завершаем работу
           {
            cout << "End File" << endl;
            break;
            }


   OutputFile = fopen(OutPutFileName, "a+b"); //Создаём выходной файл
        if(OutputFile == NULL)
           {
            cout << "Error, can't create file" << endl;
            break;
            }
              i = 0;
              offs = 0;
              size = 0;
              fseek(InputFile, CurrentPosition, SEEK_SET);
              fread(&CurrentByte, 1, 1, InputFile);
  while (1)
  {
//-----------------------------------------//
      //
         while (1)
         {
            i >>= 1; // Сдвиг вправо
            if (!(i & 0xFF00))  // если старший байт ноль
               {
               i = 0xFF00 | CurrentByte; // то заменяем на 0xFF //конкатенация с текущим байтом
               CurrentPosition++;
               fseek(InputFile, CurrentPosition, SEEK_SET); // и переходим к следующему байту во входном файле
               fread(&CurrentByte, 1, 1, InputFile);
               }
            if (i & 1) // если младший бит зажжён - выходим из этого цикла
            {
               break;
            }  
            
            OutputByte = CurrentByte; // если нет, то копируем байт входного файла в выходной
            fwrite(&OutputByte, 1, 1, OutputFile);
            CurrentPosition++;
            fseek(InputFile, CurrentPosition, SEEK_SET); // и двигаем указатель во входном файле на следующую позицию
            fread(&CurrentByte, 1, 1, InputFile);
         }
//-----------------------------------------//
//В начале цикл вываливается с символа P(50), после третьего захода(?).

    if (CurrentByte >= 96)
    {
      offs = CurrentByte - 256;
      size = 3;
      CurrentPosition++;
      fseek(InputFile, CurrentPosition, SEEK_SET); // и переходим к следующему байту во входном потоке
      fread(&CurrentByte, 1, 1, InputFile);
    }
    else
    {            

//Это блок, отвечающий за повторы, сколько раз повторить и на какой дистанции взять пиксель. Словарём являются выходные данные(Выходной файл)
      size = (CurrentByte & 0xF0) >> 4;  
      offs = (CurrentByte & 0x0F) << 8;

      CurrentPosition++;
      fseek(InputFile, CurrentPosition, SEEK_SET);
      fread(&CurrentByte, 1, 1, InputFile);

      offs |= CurrentByte;

      CurrentPosition++;
      fseek(InputFile, CurrentPosition, SEEK_SET);
      fread(&CurrentByte, 1, 1, InputFile);

      if (!offs) //не нуль? Это условие срабатывает, если встретился конец спрайта.
      {

             if(CurrentPosition != (LengthOfFile-2)) //Если указатель не приехал в конец файла, то надо запустить процесс по новой, собираем новое название
             {
              CurrentNameNumber =(int)(OutPutFileName[1] -0x30) *100 +(int)(OutPutFileName[2] -0x30) *10 +(int)(OutPutFileName[3] -0x30) +1;// собираем число +1
              OutPutFileName[1] =(char)(CurrentNameNumber /100) +0x30;
              OutPutFileName[2] =(char)((CurrentNameNumber /10) %10) +0x30;
              OutPutFileName[3] =(char)(CurrentNameNumber %10) +0x30;
                while(CurrentByte == 0 && !feof(InputFile))//Если случайно не встретился конец файла и текущий байт нуль(разделительные нули между спрайтами)
                {
                  CurrentPosition++;
                  fseek(InputFile, CurrentPosition, SEEK_SET);
                  fread(&CurrentByte, 1, 1, InputFile);
                }
              }
          break;
      }
      offs = -offs; //-1?
      if (size == 5)
      {
        size = CurrentByte + 9; //48
      CurrentPosition++;
      fseek(InputFile, CurrentPosition, SEEK_SET);
      fread(&CurrentByte, 1, 1, InputFile);
      }
      else
      {
        size = size + 4;
      }
    }
    while (--size) //Скользящее окно, формула - повторять size-раз на offs расстояние предыдущих пикселей
    {
    
        OutFilePosition = ftell(OutputFile) + offs; //Вычисляем предыдущие пиксели относительно текущей позиции в выходном файле

        fseek(OutputFile,OutFilePosition, SEEK_SET);//Ставим туда указатель

        fread(&OutputByte, 1, 1, OutputFile);//Читаем от туда байт

        fseek(OutputFile, 0, SEEK_END);//Ставим указатель в конец

        fwrite(&OutputByte, 1, 1, OutputFile);//Пишем этот байт и запускаем цикл заного.
    }

  }
    
}
    fcloseall(); //Закрываем все потоки.
    system("pause");
    return 0;
}
User is offlineProfile CardPM
Go to the top of the page
+Quote Post
-=CHE@TER=-
Nov 17 2020, 11:15
Сообщение #3


Walter Sullivan
***

Группа: Root Admin
Сообщений: 1,355
Регистрация: 4-February 08
Пользователь №: 3
Спасибо сказали: 311 раз(а)



QUOTE(LexSafonov @ Nov 16 2020, 19:24) *
Недоработка: все файлы на выходе дозаписываются в конец, перед повторным использованием убирайте старые декомпанованые файлы.
Так ты "wb" (w = write, b = binary) делай, а не "a+b" (a = append to existing, + = modify, b = binary), когда выходной файл создаёшь при помощи fopen().
User is offlineProfile CardPM
Go to the top of the page
+Quote Post
LexSafonov
Nov 17 2020, 13:39
Сообщение #4


Member
**

Группа: Authorized
Сообщений: 21
Регистрация: 29-October 20
Пользователь №: 18,034
Спасибо сказали: 1 раз(а)



QUOTE(-=CHE@TER=- @ Nov 17 2020, 11:15) *

Так ты "wb" (w = write, b = binary) делай, а не "a+b" (a = append to existing, + = modify, b = binary), когда выходной файл создаёшь при помощи fopen().

А функция fwrite() жаловаться не будет? У меня же все данные в основном в конец дозаписываются
User is offlineProfile CardPM
Go to the top of the page
+Quote Post
-=CHE@TER=-
Nov 17 2020, 16:04
Сообщение #5


Walter Sullivan
***

Группа: Root Admin
Сообщений: 1,355
Регистрация: 4-February 08
Пользователь №: 3
Спасибо сказали: 311 раз(а)



QUOTE(LexSafonov @ Nov 17 2020, 13:39) *
А функция fwrite() жаловаться не будет? У меня же все данные в основном в конец дозаписываются
Какая разница куда у тебя данные записываются, если файл открыт для записи? Если ты помимо записи что-то читаешь или по файлу туда-сюда ходишь, то сделай "w+b".
И ещё ты делаешь главную ошибку: вместо того чтобы попробовать и посмотреть как будет работать, ты задаёшь вопрос. А так у тебя уйдёт 1 минута чтобы проверить или 5 чтобы спросить на форуме.
Если бы жёсткий диск форматировал или человека в космос запускал - переспрашивать и перепроверить было бы логично для надёжности, ибо последствия могут быть необратимыми. А смысл это здесь делать?
Добавлю: я твой код не смотрел, так что если ты несколько файлов в один зачем-то пишешь, тогда тебе нужно первый создавать с "w+b", а остальные уже с добавлением.
User is offlineProfile CardPM
Go to the top of the page
+Quote Post
LexSafonov
Nov 17 2020, 16:39
Сообщение #6


Member
**

Группа: Authorized
Сообщений: 21
Регистрация: 29-October 20
Пользователь №: 18,034
Спасибо сказали: 1 раз(а)



QUOTE(-=CHE@TER=- @ Nov 17 2020, 16:04) *

Какая разница куда у тебя данные записываются, если файл открыт для записи? Если ты помимо записи что-то читаешь или по файлу туда-сюда ходишь, то сделай "w+b".
И ещё ты делаешь главную ошибку: вместо того чтобы попробовать и посмотреть как будет работать, ты задаёшь вопрос. А так у тебя уйдёт 1 минута чтобы проверить или 5 чтобы спросить на форуме.
Если бы жёсткий диск форматировал или человека в космос запускал - переспрашивать и перепроверить было бы логично для надёжности, ибо последствия могут быть необратимыми. А смысл это здесь делать?
Добавлю: я твой код не смотрел, так что если ты несколько файлов в один зачем-то пишешь, тогда тебе нужно первый создавать с "w+b", а остальные уже с добавлением.


Ладно, исправлю, не ругайся только smile.gif
User is offlineProfile CardPM
Go to the top of the page
+Quote Post
-=CHE@TER=-
Nov 17 2020, 17:18
Сообщение #7


Walter Sullivan
***

Группа: Root Admin
Сообщений: 1,355
Регистрация: 4-February 08
Пользователь №: 3
Спасибо сказали: 311 раз(а)



QUOTE(LexSafonov @ Nov 17 2020, 16:39) *
Ладно, исправлю, не ругайся только smile.gif
Я не ругаюсь, у меня просто голос такой. Кстати, вспомнился, похожий случай 13 лет назад. Время летит - офигеть можно.
Смысл в том, что вопрос нужно задавать, когда ты уже сам всё перепробовал и упёрся в тупик и не понимаешь что делать дальше.
Или сделал так-то, но сомневаешься и хочешь узнать можно ли сделать лучше.
И тому подобные случаи.
Я ж говорю - я готов помочь, мне не жалко.
Просто человек когда сам до чего-то доходит, то лучше усваивает материал: лучше запоминает, плюс в схожей ситуации попробует так же сделать - решение уже будет само напрашиваться.
User is offlineProfile CardPM
Go to the top of the page
+Quote Post

Сообщения в этой теме
LexSafonov   Alien Trilogy (PC)   Oct 29 2020, 17:48
-=CHE@TER=-   Ну, я уже писал, что смотрел игру бегло, там реаль...   Oct 29 2020, 19:21
LexSafonov   Так, продолжаю работу по просмотру сырого дизассем...   Oct 30 2020, 19:34
-=CHE@TER=-   По началу при беглом просмотре этих строк я и не д...   Oct 30 2020, 20:24
LexSafonov   Так, сегодня сел со вежей головой и решил прикинут...   Oct 31 2020, 09:46
-=CHE@TER=-   Всё, я нашёл функцию декодирования. Ищешь в исполн...   Oct 31 2020, 17:22
LexSafonov   Блин, бро, да ты мозг! Прям интересно стало, ч...   Nov 1 2020, 08:11
-=CHE@TER=-   Проверка возможно связана с тем, что в BND вариант...   Nov 1 2020, 18:03
LexSafonov   Так, ещё порция глупых вопросов, по поводу того ал...   Nov 11 2020, 08:21
-=CHE@TER=-   В функцию надо передавать указатель на файл? Или ж...   Nov 11 2020, 12:59
LexSafonov   Ух ты. Даже как то не по себе, от того, что ты про...   Nov 11 2020, 14:09
-=CHE@TER=-   Там вроде есть секции, в которых содержится сразу ...   Nov 11 2020, 18:02
LexSafonov   Так, сделал простую прогу, линейную, для декомпрес...   Nov 13 2020, 16:01
-=CHE@TER=-   А блин, понял, я же неправильно скользящее окно сд...   Nov 13 2020, 17:21
LexSafonov   Получилось! Переделал немного, сделал выходной...   Nov 13 2020, 17:51
-=CHE@TER=-   Получилось!Во, молодец! Можно наверное эт...   Nov 13 2020, 20:54
LexSafonov   На счёт исходных кодов - и твои и мои. Если ты не ...   Nov 13 2020, 22:15
-=CHE@TER=-   На счёт исходных кодов - и твои и мои. Если ты не ...   Nov 14 2020, 12:05
LexSafonov   И так, после долгого мучения и раздумий, я наконец...   Nov 16 2020, 19:24
-=CHE@TER=-   Недоработка: все файлы на выходе дозаписываются в ...   Nov 17 2020, 11:15
LexSafonov   Так ты "wb" (w = write, b = binary) дел...   Nov 17 2020, 13:39
-=CHE@TER=-   А функция fwrite() жаловаться не будет? У меня же ...   Nov 17 2020, 16:04
LexSafonov   Какая разница куда у тебя данные записываются, ес...   Nov 17 2020, 16:39
-=CHE@TER=-   Ладно, исправлю, не ругайся только :)Я не ругаюсь,...   Nov 17 2020, 17:18
LexSafonov   Так, решил своим же инструментом попробовать извле...   Nov 19 2020, 09:33
-=CHE@TER=-   Пока извлекал ресурсы, нашёл неиспользуемые спрайт...   Nov 19 2020, 14:43
LexSafonov   Так, продолжаю свои разборы формата карты. Ещё раз...   Nov 19 2020, 20:10
LexSafonov   Обновляю данные по поводу формата карт. http://i....   Nov 20 2020, 15:08
LexSafonov   И так, сейчас будет хороший такой пост по разбору ...   Nov 22 2020, 12:45
-=CHE@TER=-   Нифига себе сколько. Кстати, на первом скриншоте о...   Nov 22 2020, 14:27
LexSafonov   По поводу опечатки, да.... Я заметил это в самый п...   Nov 22 2020, 15:52
-=CHE@TER=-   Ещё одна проблема в том, что я очень туго сообража...   Nov 22 2020, 16:51
LexSafonov   Так ребята, всем привет. Долго меня не было. Вообщ...   May 13 2021, 16:11
-=CHE@TER=-   - Так же я не совсем понял, что за последнее поле ...   May 14 2021, 18:11


Reply to this topicStart new topic
3 чел. читают эту тему (гостей: 3, скрытых пользователей: 0)
Пользователей: 0 -

 



Упрощённая версия Сейчас: 28th April 2024 - 23:38