Blog. Just Blog

Распаковка данных в формате BitBuster на Ассемблере

Версия для печати Добавить в Избранное Отправить на E-Mail | Категория: Образ мышления: Assembler | Автор: ManHunter
Распаковка данных в формате BitBuster на Ассемблере
Распаковка данных в формате BitBuster на Ассемблере

BitBuster - высокоэффективный алгоритм сжатия данных от GameDev-команды Team Bomba. Исходный код упаковщика и распаковщика открыт, но готовых ассемблерных распаковщиков для BitBuster не было. Ну ничего, посидел вечерок в отладчике, портировал алгоритм распаковки с Си на Ассемблер, теперь есть.

Для упаковки данных надо использовать утилиту из прилагаемого архива. Формат сжатых данных затруднений не вызывает. Размер исходных данных хранится в первом DWORD'е упакованных данных. С 4-го байта идут сами упакованные данные. Несмотря на то, что на больших файлах упаковщик работает очень долго, результат получается впечатляющий. Для примера, BitBuster сжал тестовую иконку с 16958 байт до 192, тогда как упаковщик LZE эту же иконку сжал только до 378 байт. Скорость распаковки тоже очень высокая.
  1. ;------------------------------------------------------------
  2. ; Распаковка данных в формате BitBuster
  3. ; by ManHunter / PCL (www.manhunter.ru)
  4. ;------------------------------------------------------------
  5. ; На входе:
  6. ;   lpCompressed - указатель на упакованные данные
  7. ;   lpOut - указатель на буфер для распакованных данных
  8. ; На выходе:
  9. ;   EAX = размер распакованных данных
  10. ;------------------------------------------------------------
  11. proc bb_unpack lpCompressed:DWORD,lpOut:DWORD
  12.         pusha
  13.  
  14.         mov     esi,[lpCompressed]
  15.         mov     edi,[lpOut]
  16.         lodsd
  17.         mov     ebx,eax
  18.         add     ebx,edi
  19.  
  20.         mov     dh,8
  21. .loc_1:
  22.         cmp     edi,ebx
  23.         jnb     .done
  24.  
  25.         stdcall .read_bit
  26.         je      .loc_2
  27.         ; 1 = packed data
  28.         lodsb
  29.         or      al,al
  30.         jnz     .loc_3
  31.         ; rle
  32.         stdcall .read_gamma
  33.         mov     al,[edi-1]
  34.         rep     stosb
  35.         jmp     .loc_1
  36. .loc_3:
  37.         movzx   ecx,al
  38.         test    al,128
  39.         jz      @f
  40.  
  41.         and     al,127
  42.         movzx   ecx,al
  43.  
  44.         stdcall .read_bit
  45.         setnz   al
  46.         movzx   eax,al
  47.         shl     eax,10
  48.         add     ecx,eax
  49.         stdcall .read_bit
  50.         setnz   al
  51.         movzx   eax,al
  52.         shl     eax,9
  53.         add     ecx,eax
  54.         stdcall .read_bit
  55.         setnz   al
  56.         movzx   eax,al
  57.         shl     eax,8
  58.         add     ecx,eax
  59.         stdcall .read_bit
  60.         setnz   al
  61.         movzx   eax,al
  62.         shl     eax,7
  63.         add     ecx,eax
  64. @@:
  65.         push    ebx
  66.         mov     ebx,ecx
  67.  
  68.         stdcall .read_gamma
  69.  
  70.         push    esi
  71.         mov     esi,edi
  72.         sub     esi,ebx
  73.         dec     esi
  74.         rep     movsb
  75.         pop     esi
  76.         pop     ebx
  77.         jmp     .loc_1
  78. .loc_2:
  79.         ; 0 = literal byte
  80.         movsb
  81.         jmp     .loc_1
  82.  
  83. .read_gamma:
  84.         mov     ecx,1
  85.         push    ebx
  86.         mov     bh,0
  87. @@:
  88.         stdcall .read_bit
  89.         jz      @f
  90.         inc     bh
  91.         jmp     @b
  92. @@:
  93.         or      bh,bh
  94.         jz      @f
  95.         dec     bh
  96.         add     ecx,ecx
  97.         stdcall .read_bit
  98.         jz      @b
  99.         inc     ecx
  100.         jmp     @b
  101. @@:
  102.         inc     ecx
  103.         pop     ebx
  104.         retn
  105.  
  106. .read_bit:
  107.         cmp     dh,8
  108.         jne     @f
  109.         mov     dl,byte[esi]
  110.         inc     esi
  111.         mov     dh,0
  112. @@:
  113.         inc     dh
  114.         push    eax
  115.         mov     al,dl
  116.         add     dl,dl
  117.         test    al,80h
  118.         pop     eax
  119.         retn
  120.  
  121. .done:
  122.         sub     edi,[lpOut]
  123.         mov     [esp+28],edi
  124.         popa
  125.         ret
  126. endp
В качестве параметров передается указатель на упакованные данные и указатель на буфер-приемник. На выходе в регистре EAX возвращается количество байт, которое было извлечено из сжатых данных. Размер принимающего буфера в процессе распаковки никак не проверяется, об этом вы должны позаботиться самостоятельно.

В приложении пример программы с исходным текстом, которая извлекает из памяти иконку, упакованную по алгоритму BitBuster, и выводит ее на форму. Там же в архиве утилиты для упаковки и распаковки данных от Team Bomba вместе с исходниками.

Пример программы с исходным текстом (FASM)Пример программы с исходным текстом (FASM)

BitBuster.Unpack.Demo.zip (33,874 bytes)


Поделиться ссылкой ВКонтакте Поделиться ссылкой на Facebook Поделиться ссылкой на LiveJournal Поделиться ссылкой в Мой Круг Добавить в Мой мир Добавить на ЛиРу (Liveinternet) Добавить в закладки Memori Добавить в закладки Google
Просмотров: 424 | Комментариев: 0

Комментарии

Отзывы посетителей сайта о статье
Комментариeв нет

Добавить комментарий

Заполните форму для добавления комментария
Имя*:
Текст комментария (не более 2000 символов)*:

*Все поля обязательны для заполнения.
Комментарии, содержащие рекламу, ненормативную лексику, оскорбления и т.п., а также флуд и сообщения не по теме, будут удаляться. Нарушителям может быть заблокирован доступ к сайту.
Наверх
Powered by PCL's Speckled Band Engine 0.2 RC3
© ManHunter / PCL, 2008-2021
При использовании материалов ссылка на сайт обязательна
Время генерации: 0.07 сек. / MySQL: 2 (0.0033 сек.) / Память: 4.75 Mb
Наверх