PDA

Просмотр полной версии : Помогите HRUST21.CPP превратить в DLL



newart
26.05.2009, 23:09
Для дальнейшего развития zxpress.ru (http://zxpress.ru) необходима DLL'ка до недавнего времени выручал Ander (одээлелев MSPACK, LZS, HRUST1, HRUM), но сейчас он похоже очень и на долго занят. :(

На форуме ведь есть С програмерры?
Переделки в общем то минимальные, тем более есть пример и полный пакет файлов из уже готовых распаковщиков (под Visual C++).

выглядет оно так (плагин к FAR'у)



#include <windows.h>
#include "..\\dtr.hpp"

BYTE *hr_d_output;
BYTE *hr_d_input;
BYTE hr_d_tagbyte;/*буфер для битов.*/
BYTE __index = 7;

BYTE hr_d_getbit(void)
{
BYTE bit[] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };

__index = (__index + 1) % 8;
if(__index == 0) hr_d_tagbyte = *hr_d_input++;

return (hr_d_tagbyte & bit[__index]) == 0 ? 0 : 1;
}

WORD hr_d_getlen(void)
{
WORD tmp, result = 1;
do
{
tmp = (hr_d_getbit() << 1) + hr_d_getbit();
result += tmp;
} while(tmp == 0x03 && result != 0x10);

return(result);
}

WORD hr_d_getdist(void)
{
WORD result;volatile WORD tmp;

if(hr_d_getbit())
{
result = 0xff00 + *hr_d_input++;
}
else
{
result = 0xffff;
tmp = (hr_d_getbit() << 1) + hr_d_getbit() + 0xffff-3;

for(; tmp; tmp++) result = (result << 1) + hr_d_getbit() - 1;
if(result == 0xffff - 30) result = *hr_d_input++;
result = (result << 8) + *hr_d_input++;
}
return (result);
}

void dehrust(BYTE* source, BYTE* destination)
{
__index = 7;
WORD len;
short offs;

hr_d_input = source + 6;
hr_d_output = destination;

*hr_d_output++ = *hr_d_input++;

while(true)
{
if(!hr_d_getbit())
{
len = hr_d_getlen();
offs = 0xffff;

if(len == 4)
{
if(hr_d_getbit())
{
len = *hr_d_input++;

if(len == 0)
break;
else
if(len < 16) len = (len << 8) + *hr_d_input++;

offs = hr_d_getdist();

for(; len; len--) *hr_d_output = *(hr_d_output++ + offs);
}
else
{
len = 0;
for(int i = 4; i; i--) len = (len << 1) + hr_d_getbit();
len += 6;
len <<= 1;
for(; len; len--) *hr_d_output++ = *hr_d_input++;
}
}
else
{
if(len > 4) len--;
if(len == 1)
{
for(int i = 3; i; i--) offs = (offs << 1) + hr_d_getbit();
}
else
{
if(len == 2)
offs = 0xff00 + *hr_d_input++;
else
offs = hr_d_getdist();
}
for(; len; len--) *hr_d_output = *(hr_d_output++ + offs);
}
}
else
{
*hr_d_output++ = *hr_d_input++;
}
}

for(int i = 0; i < 6; i++) *hr_d_output++ = source[i];
}

bool WINAPI extract(HoHdr *hdr, const BYTE *source, DWORD sourceSize, BYTE *unpackBuffer, DWORD *noUnpackedBytes, DWORD)
{
*noUnpackedBytes = *(WORD*)(source + 4);

if(source[3] & 0x80)
CopyMemory(unpackBuffer, source + 8, *noUnpackedBytes);
else
{
dehrust((BYTE*)source + 8, unpackBuffer);

#define ACE_notSUPPORT
#ifdef ACE_SUPPORT
// ACE detector
int i;
WORD len = hdr->length;
bool ace = true;
DWORD extraLen = sourceSize - len;
if(extraLen >= 14) extraLen = 14;
for(i = 0; i < extraLen; ++i)
if(source[i] != source[len+i])
{
ace = false;
break;
}

WORD maxLen = 128;
WORD lineLen = 0;
for(i = 0; i < *noUnpackedBytes && ace ; ++i)
{
if(unpackBuffer[i] == 0)
{
// sprites?
if((*noUnpackedBytes-i-1)%9*32 != 0)
{
ace = false;
break;
}
*noUnpackedBytes = i; // let's crop sprites
break;
}
else
{
if(lineLen > maxLen)
{
ace = false;
break;
}
++lineLen;
if(unpackBuffer[i] == 0x0d) lineLen = 0;
}
}
if(ace)
{
for(i = 0; i < *noUnpackedBytes; ++i)
if((unpackBuffer[i] > 0 && unpackBuffer[i] < 9) || (unpackBuffer[i] > 13 && unpackBuffer[i] < 21)) unpackBuffer[i] = ' ';
}
// END of ACE detector
#endif
}

return true;
}

bool WINAPI detect(DetectorResult &result, const char*, const HoHdr*, const BYTE *data, int file_size)
{
if(data[0] != 'h' || data[1] != 'r' || data[2] != '2') return false;

WORD size = *(WORD*)(data + 4);
WORD packed_size = *(WORD*)(data + 6);

if(packed_size > size || packed_size > file_size) return false;

result.action = do_extract;
lstrcpy(result.title, "[hrust 2.1]");

return true;
}




На самом деле есть еще PCD, TRUSH, CC, DSQ, ESV, но большинство интересных статей запаковано именно HRUST21.

rasmer
26.05.2009, 23:11
А на спеке распаковать никак? Или скомпилить плугин к фаре?

Vitamin
27.05.2009, 00:00
Почему dll? Как планируется использовать? Может лучше CLI-приложение?

newart
27.05.2009, 08:02
Почему dll? Как планируется использовать? Может лучше CLI-приложение?
Потому что так удобно. Что такое CLI не знаю.

Сейчас глянул, все 4 распаковщика уже обьеденены в одну DLL.

Либа используется для поиска и распаковки архивов.
Есть три функции: detect, depack и freemem

HRUST1 что было и что получилось:


было:






#include <windows.h>
#include "..\\dtr.hpp"

class BBStream
{
private:
BYTE* base;
BYTE* p;
int idx;
int len;
bool eof;
WORD bits;
public:
BBStream(BYTE* from, int blockSize)
{
base = p = from;

len = blockSize;
idx = 0;
eof = false;

bits = getByte();
bits += 256*getByte();
}

BYTE getByte(void)
{
if(p - base == len) { eof = true; return 0; }
return *p++;
}

BYTE getBit()
{
WORD mask[] = { 0x8000, 0x4000, 0x2000, 0x1000, 0x800, 0x400, 0x200, 0x100, 0x80, 0x40, 0x20, 0x10, 0x8, 0x4, 0x2, 0x1 };

BYTE bit = (bits & mask[idx]) ? 1 : 0;
if(idx == 15)
{
bits = getByte();
bits += 256*getByte();
}

idx = (idx + 1) % 16;
return bit;
}

BYTE getBits(int n)
{
BYTE r = 0;
do { r = 2*r + getBit(); } while(--n);
return r;
}

bool error(void) { return eof; }
};

bool WINAPI extract(HoHdr *hdr, const BYTE *source, DWORD, BYTE *unpackBuffer, DWORD *noUnpackedBytes, DWORD)
{
BYTE *from = (BYTE*)source;
BYTE *to = unpackBuffer;

if(source[0] != 'H' || source[1] != 'R')
from += 0x103;

BBStream s(from + 12, from[4] + 256*from[5]);

*to++ = s.getByte();

BYTE noBits = 2;
BYTE mask[] = { 0, 0, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0 };

while(!s.error())
{
while(s.getBit()) *to++ = s.getByte();

WORD len = 0;
BYTE bb = 0;
do
{
bb = s.getBits(2);
len += bb;
} while(bb == 0x03 && len != 0x0f);

short offset = 0;

if(len == 0)
{
offset = 0xfff8 + s.getBits(3);
*to++ = to[offset];
continue;
}

if(len == 1)
{
BYTE code = s.getBits(2);

if(code == 2)
{
BYTE b = s.getByte();
if(b >= 0xe0)
{
b <<= 1; ++b; // rlca
b ^= 2; // xor c

if(b == 0xff) { ++noBits; continue; }

offset = 0xff00 + b - 0x0f;

*to++ = to[offset];
*to++ = s.getByte();
*to++ = to[offset];
continue;
}
offset = 0xff00 + b;
}

if(code == 0 || code == 1)
{
offset = s.getByte();
offset += 256*(code ? 0xfe : 0xfd);
}
if(code == 3) offset = 0xffe0 + s.getBits(5);

for(BYTE i = 0; i < 2; ++i)
*to++ = to[offset];
continue;
}

if(len == 3)
{
if(s.getBit())
{
offset = 0xfff0 + s.getBits(4);
*to++ = to[offset];
*to++ = s.getByte();
*to++ = to[offset];
continue;
}

if(s.getBit())
{
BYTE noBytes = 6 + s.getBits(4);
for(BYTE i = 0; i < 2*noBytes; ++i)
*to++ = s.getByte();
continue;
}

len = s.getBits(7);
if(len == 0x0f) break; // EOF
if(len < 0x0f) len = 256*len + s.getByte();
}

if(len == 2) ++len;

BYTE code = s.getBits(2);

if(code == 1)
{
BYTE b = s.getByte();

if(b >= 0xe0)
{
if(len > 3) return false;

b <<= 1; ++b; // rlca
b ^= 3; // xor c

offset = 0xff00 + b - 0x0f;

*to++ = to[offset];
*to++ = s.getByte();
*to++ = to[offset];
continue;
}
offset = 0xff00 + b;
}

if(code == 0) offset = 0xfe00 + s.getByte();
if(code == 2) offset = 0xffe0 + s.getBits(5);
if(code == 3)
{
offset = 256*(mask[noBits] + s.getBits(noBits));
offset += s.getByte();
}

for(WORD i = 0; i < len; ++i)
*to++ = to[offset];
}

for(int i = 0; i < 6; ++i)
*to++ = from[6+i];

*noUnpackedBytes = to-unpackBuffer;

return true;
}

bool WINAPI detect(DetectorResult &result, const char*, const HoHdr*, const BYTE *data, int file_size)
{
WORD size;
WORD packed_size;

while(true)
{
if(data[0] == 'H' && data[1] == 'R')
{
size = *(WORD*)(data + 2);
packed_size = *(WORD*)(data + 4);

// check for HRiP
if(data[2] == 'i' && (data[2+5] == 0 || data[2+5] == 1))
return false;

break;
}

if(data[0x103] == 'H' && data[0x104] == 'R')
{
size = *(WORD*)(data + 0x105);
packed_size = *(WORD*)(data + 0x107);

break;
}

return false;
}

if(packed_size > size || packed_size > file_size)
return false;

result.action = do_extract;
lstrcpy(result.title, "[hrust 1.x]");

return true;
}


стало:



#include "stdafx.h"
#include "hrust1.h"
#include <vector>

class BBStream
{
private:
BYTE* base;
BYTE* p;
int idx;
int len;
bool eof;
WORD bits;
public:
BBStream(BYTE* from, int blockSize)
{
base = p = from;

len = blockSize;
idx = 0;
eof = false;

bits = getByte();
bits += 256*getByte();
}

BYTE getByte(void)
{
if(p - base == len) { eof = true; return 0; }
return *p++;
}

BYTE getBit()
{
WORD mask[] = { 0x8000, 0x4000, 0x2000, 0x1000, 0x800, 0x400, 0x200, 0x100, 0x80, 0x40, 0x20, 0x10, 0x8, 0x4, 0x2, 0x1 };

BYTE bit = (bits & mask[idx]) ? 1 : 0;
if(idx == 15)
{
bits = getByte();
bits += 256*getByte();
}

idx = (idx + 1) % 16;
return bit;
}

BYTE getBits(int n)
{
BYTE r = 0;
do { r = 2*r + getBit(); } while(--n);
return r;
}

bool error(void) { return eof; }
};

extern "C" HRUST1_API void *hrust1_extract(const BYTE *source, DWORD *noUnpackedBytes)
{
WORD packed_size;
BYTE *from = (BYTE*)source;
BYTE *unpackBuffer = 0;
*noUnpackedBytes = 0;
std::vector<BYTE> out;

try
{
if(source[0] != 'H' || source[1] != 'R')
from += 0x103;

BBStream s(from + 12, from[4] + 256*from[5]);

out.push_back(s.getByte());

BYTE noBits = 2;
BYTE mask[] = { 0, 0, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0 };

while(!s.error())
{
while(s.getBit())
{
out.push_back(s.getByte());
}

WORD len = 0;
BYTE bb = 0;
do
{
bb = s.getBits(2);
len += bb;
} while(bb == 0x03 && len != 0x0f);

short offset = 0;

if(len == 0)
{
offset = 0xfff8 + s.getBits(3);
out.push_back(out.at(out.size() + offset));
continue;
}

if(len == 1)
{
BYTE code = s.getBits(2);

if(code == 2)
{
BYTE b = s.getByte();
if(b >= 0xe0)
{
b <<= 1; ++b; // rlca
b ^= 2; // xor c

if(b == 0xff) { ++noBits; continue; }

offset = 0xff00 + b - 0x0f;

out.push_back(out.at(out.size() + offset));
out.push_back(s.getByte());
out.push_back(out.at(out.size() + offset));
continue;
}
offset = 0xff00 + b;
}

if(code == 0 || code == 1)
{
offset = s.getByte();
offset += 256*(code ? 0xfe : 0xfd);
}
if(code == 3) offset = 0xffe0 + s.getBits(5);

for(BYTE i = 0; i < 2; ++i)
out.push_back(out.at(out.size() + offset));
continue;
}

if(len == 3)
{
if(s.getBit())
{
offset = 0xfff0 + s.getBits(4);
out.push_back(out.at(out.size() + offset));
out.push_back(s.getByte());
out.push_back(out.at(out.size() + offset));
continue;
}

if(s.getBit())
{
BYTE noBytes = 6 + s.getBits(4);
for(BYTE i = 0; i < 2*noBytes; ++i)
out.push_back(s.getByte());
continue;
}

len = s.getBits(7);
if(len == 0x0f) break; // EOF
if(len < 0x0f) len = 256*len + s.getByte();
}

if(len == 2) ++len;

BYTE code = s.getBits(2);

if(code == 1)
{
BYTE b = s.getByte();

if(b >= 0xe0)
{
if(len > 3) return false;

b <<= 1; ++b; // rlca
b ^= 3; // xor c

offset = 0xff00 + b - 0x0f;

out.push_back(out.at(out.size() + offset));
out.push_back(s.getByte());
out.push_back(out.at(out.size() + offset));
continue;
}
offset = 0xff00 + b;
}

if(code == 0) offset = 0xfe00 + s.getByte();
if(code == 2) offset = 0xffe0 + s.getBits(5);
if(code == 3)
{
offset = 256*(mask[noBits] + s.getBits(noBits));
offset += s.getByte();
}

for(WORD i = 0; i < len; ++i)
out.push_back(out.at(out.size() + offset));
}

for(int i = 0; i < 6; ++i)
out.push_back(from[6+i]);
}
catch(...)
{
return 0;
}

*noUnpackedBytes = out.size();
unpackBuffer = (BYTE *)malloc(*noUnpackedBytes);
std::vector<BYTE>::pointer ptr = &out [0];
memcpy(unpackBuffer, ptr, *noUnpackedBytes);
return unpackBuffer;
}

extern "C" HRUST1_API int hrust1_detect(const BYTE *data)
{
WORD size;
WORD packed_size;

while(true)
{
if(data[0] == 'H' && data[1] == 'R')
{
size = *(WORD*)(data + 2);
packed_size = *(WORD*)(data + 4);

// check for HRiP
if(data[2] == 'i' && (data[2+5] == 0 || data[2+5] == 1))
return 0;

break;
}

return 0;
}

if(packed_size > size)
return 0;

return size;
}





Архив проекта (чуток старый, тут нет Hrum'а)

Vitamin
27.05.2009, 08:16
Потому что так удобно. Что такое CLI не знаю.
Command-Line interface.

Из какой программы используется либа? Где исходники оригинальной (с 4 депакерами) либы?

newart
27.05.2009, 08:25
Из какой программы используется либа?
Из рипалки , которую пишу на PureBasic.

Добавлено через 2 минуты
DLL в любом случае мне кажется более универсальным вариантом.
Написать обертку для комндной строки дело одной минуты (если кому надо будет).

Firestarter
27.05.2009, 15:07
http://wincmd.ru/plugring/inhrust.html

Плагин к TotalCommander, позволяющий распаковывать HRIP-архивы и файлы упакованные спектрумовскими компрессорами Hrust 1 и Hrust 2.

Щас полетят помидоры что он не для FAR

Shadow Maker
27.05.2009, 15:09
Ему ж не это надо, он предлагает на базе плагина от фара слепить ему длл-ку для его рипалки.

Firestarter
27.05.2009, 15:18
Ему ж не это надо, он предлагает на базе плагина от фара слепить ему длл-ку для его рипалки.

Началось...

newart
27.05.2009, 15:23
Ему ж не это надо, он предлагает на базе плагина от фара слепить ему длл-ку для его рипалки.
Ну и не только для нее.
Ничто не мешает далее использовать эту DLL в Тотале или любом другом софте.

Вот сорцы от XLOOK'а (не знаю можно ли их вот так публиковать? если нет, удалю)

Barmaley_m
05.06.2009, 14:43
Объясняю ряд основных принципов.

Компилированный c/cpp файл или их группа являются библиотекой функций.

Библиотека функций может быть скомпонована в исполняемый файл (EXE) или в DLL. Различия между ними следующие:

EXE-файл имеет одну стандартную точку запуска, с которой начинается исполнение после его загрузки в память. Как правило, это функция main() или WinMain().

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

На усмотрение программиста, при компоновке DLL-файла из библиотеки c/cpp, часть функций может быть экспортирована. Они будут доступны для программ, использующих данный DLL-файл. Все остальные функции будут внутренними для DLL и невидимыми для программ, использующих DLL.

Экспортировать функции можно двумя способами.
1. Указать это как атрибут при декларации функции, например:
void __declspec(dllexport) SomeFunction(int a);
2. Создать def-файл, в котором перечислить экспортируемые функции, например:
; some_library.def : Declares the module parameters for the DLL.

LIBRARY "SOME_LIBRARY"

EXPORTS
; Explicit exports can go here
SomeFunction
OtherFunction

-------------

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