Magic Team

Информация о пользователе

Привет, Гость! Войдите или зарегистрируйтесь.


Вы здесь » Magic Team » Программирование » Помогите молодому программисту


Помогите молодому программисту

Сообщений 1 страница 14 из 14

1

Здраствуйте всем кто слышит. Вот мне нужно написать распоковщек графики для игры на нес, но как подойти к ентай штуке незнаю. Так вот. Немогли вы бы мне мне рассказать принцапы по написанию распаковщека или дать исходник какого-нибудь распаковщика к уже переведенной игре, что бы разобраться(желательно Pascal).
P.S. Прошу мня простить что вообще обноглел(Не сильно обижусь если куда-нибудь пошлете).

0

2

Эээ... А что именно распаковывать надо? Могу привести VB код распаковщика LZ77 графики в Pac-Man 2 на Sega.

Код:
Private Sub Command1_Click()
If Dir(file1) = "" Then MsgBox "Указанный вами файл не существует!", vbCritical: Exit Sub
If Dir(file2) <> "" Then If MsgBox("Файл уже существует, перезаписать?", vbQuestion + vbYesNo) = vbNo Then Exit Sub Else Kill (file2)

Dim bte As Byte
Dim uprbyte As Integer
Open file1 For Binary As 1
Open file2 For Binary As 2
adr2 = 1
adr1 = Val("&H" + Adress) + 1


Get #1, adr1, bte
If bte > 16 Then MsgBox "Неверный адрес начала архива!": Close: Exit Sub
'MsgBox "Считан начальный байт " & Hex(bte) & " по адресу " & Hex$(adr1 - 1)
adr1 = adr1 + 1
num = 16 - bte
dic = 2 ^ bte - 1

getuprbyte:
Get #1, adr1, bte
'If bte > 16 Then MsgBox "ROM не правильного формата!": Close: Exit Sub
'MsgBox "Считан управляющий байт " & Hex(bte) & " по адресу " & Hex$(adr1 - 1)
cnt = 0
adr1 = adr1 + 1
uprbyte = bte
If uprbyte = 0 Then
    MsgBox "Управляющий байт по адресу " & Hex$(adr1 - 1) & " равен нулю - выход."
    GoTo ENDUNP
End If
    

count:
cnt = cnt + 1
If cnt = 8 Or uprbyte = 0 Then GoTo getuprbyte  '
If uprbyte / 2 = uprbyte \ 2 Then rbit = 0 Else rbit = 1
'MsgBox "Правый бит байта " & Hex(uprbyte) & " равен " & rbit
uprbyte = uprbyte \ 2
If rbit = 1 Then
    Get #1, adr1, bte: adr1 = adr1 + 1
    Put #2, adr2, bte: adr2 = adr2 + 1
    'MsgBox "Правый бит равен 1, просто считываем байт " & Hex(bte) & " по адресу " & Hex(adr1 - 2) & " и пишем байт " & Hex(bte) & " по адресу " & Hex(adr2 - 2)
    GoTo count
Else
    Get #1, adr1, bte: adr1 = adr1 + 1: pbyte1 = bte
    Get #1, adr1, bte: adr1 = adr1 + 1: pbyte2 = bte
    'MsgBox "Правый бит равен 0, читаем байты " & Hex(pbyte1) & " и " & Hex(pbyte2) & " по адресу " & Hex(adr1 - 3)
    'pbyte = Val("&h" + Right$("00" + Hex$(pbyte1), 2) + Right$("00" + Hex$(pbyte2), 2))
    'If pbyte < 0 Then
        pbyte = (pbyte1 * 256) + pbyte2
        'MsgBox pbyte
    'End If
    For koef = 1 To 16
    If pbyte / 2 = pbyte \ 2 Then bitst = "0" & bitst Else bitst = "1" & bitst
        pbyte = pbyte \ 2
    Next koef
  Right(Str$(bitsn1), Len(Str$(bitsn1)) - 1), 8)
    'MsgBox bitsn2 & bitsn1 & "|" & bitst & "|" & Hex(adr1 - 3) & "|" & pbyte1 & " " & pbyte2 & "|" & pbyte
    
    

    bits2 = Right(bitst, 16 - num)
    bits1 = Left(bitst, num)
    
    For r = 0 To Len(bits1) - 1
        byte1 = byte1 + Val(Mid(bits1, Len(bits1) - r, 1)) * (2 ^ r)
    Next r
    For r = 0 To Len(bits2) - 1
        byte2 = byte2 + Val(Mid(bits2, Len(bits2) - r, 1)) * (2 ^ r)
    Next r
    
 
    If byte2 = 0 Then byte2 = 2048
    adr2b = adr2 - byte2
  
   If adr2b < 1 Then MsgBox adr2b & "   " & adr2 & " - " & byte2 & "|||" & Hex(adr1 - 3) & "   " & bitst
 
    
    If byte1 = 0 Then byte1 = 32
    
    For cntr = 1 To byte1
    Get #2, adr2b, bte: adr2b = adr2b + 1
    Put #2, adr2, bte: adr2 = adr2 + 1
    If bte < 0 Then MsgBox adr1 & "   " & adr2 & "    " & adr2b
    Next cntr
    End If
    bitst = ""
    pbyte = 0
    bits = 0
    bitsn1 = 0
    bitsn2 = 0
    byte1 = 0
    byte2 = 0
    adr2b = 0
    GoTo count
    MsgBox "Почему выход?"
ENDUNP:
Close
MsgBox "Всё! Последний байт по адресу " & Hex$(adr1 - 1)
End Sub

З.Ы. ' - это комментарии, то есть не рабочий код.
З.З.Ы. Код ещё немного не доработан, так как я не знаю, что делать с размером словаря. Его небольшой глюк в том, что он выдаёт немного мусора после графики(видимо размер словаря ограничивает объём данных).
З.З.З.Ы. Да, скажите мне кто-нибудь пожалуйста, что же всё таки делает размер словаря.
З.З.З.З.Ы. Если надо - разъясню, как работает.

Отредактировано HoRRoR (2006-08-31 21:24:04)

0

3

Спасибо за код.

HoRRoR написал(а):

З.З.З.З.Ы. Если надо - разъясню, как работает

Но нечего не понял что делает так-что прошу разяснений(Непонял потому что vb незнаю).

Отредактировано D.s3mm (2006-09-01 02:55:52)

0

4

Думаю, объяснять тебе LZ77 бесполезно... Это все само придет с опытом и с годами. Кстати, что за игра? Ты уверен, что графика пожата?

Отредактировано Griever (2006-09-01 05:15:52)

0

5

Griever написал(а):

Кстати, что за игра?

Cabal(U).nes

Griever написал(а):

Ты уверен, что графика пожата?

Незнаю, но вот что видно в в тайлах.

Скрытый текст:

Для просмотра скрытого текста - войдите или зарегистрируйтесь.


(Несмею судить о том что это,  но выравневание не помогает).
З.Ы. Появился вопрос размеры вот я читал в что ромы Snes расширять можно, а остольных приставок это возможно? ЕСли да то посколько?

Отредактировано D.s3mm (2006-09-01 08:03:34)

0

6

Griever написал(а):

Думаю, объяснять тебе LZ77 бесполезно...

Почему? Там всё оооооочень просто.

D.s3mm написал(а):

З.Ы. Появился вопрос размеры вот я читал в что ромы Snes расширять можно, а остольных приставок это возможно? ЕСли да то посколько?

Можно всё, только надо либо знать асм, либо чтобы условия это позволяли(радиус действия указателей и т.п.

Тут, кстати, графика похоже не пожата.

Сейчас допишу пояснения к моему коду.

0

7

Разъясняю(давненько дело было, могу чё неправильно написать):

Код:
If Dir(file1) = "" Then MsgBox "Указанный вами файл не существует!", vbCritical: Exit Sub
If Dir(file2) <> "" Then If MsgBox("Файл уже существует, перезаписать?", vbQuestion + vbYesNo) = vbNo Then Exit Sub Else Kill (file2)

Dim bte As Byte
Dim uprbyte As Integer
Open file1 For Binary As 1
Open file2 For Binary As 2
adr2 = 1
adr1 = Val("&H" + Adress) + 1

Открытие файла, описание и присвоение переменным нужных значений. adr2=1, то есть адрес получаемого файла графики устанавливается как 1, т.к. в VB адрес начинается с 1. adr1=значению, полученному при обращении текста, введённого пользователем, то есть конвертируется из шестнадцатиричного формата, тебе это не обязательно. 1 прибавляетсяпо той же причине. То есть получется так: adr1=адрес в РОМе, adr2=адрес в получаемом файле.

Код:
Get #1, adr1, bte
If bte > 16 Then MsgBox "Неверный адрес начала архива!": Close: Exit Sub
'MsgBox "Считан начальный байт " & Hex(bte) & " по адресу " & Hex$(adr1 - 1)
adr1 = adr1 + 1
num = 16 - bte
dic = 2 ^ bte - 1

Считывается первый байт, определяющий, сколько бит будет отводиться в двух байтах под кол-во считываемых байт, а сколько под "указатель", который указывает на сколько байт назад вернуться. Адрес РОМа увеличивается на 1, т.е. переходим к следующему байту. num=16-bte -  определяется кол-во бит, отводящихся под кол-во повторений. Т.е., допустим, под указатель отводится 7 из 16 бит, => остаётся 9 бит под кол-во повторений.

Код:
getuprbyte:
Get #1, adr1, bte
'If bte > 16 Then MsgBox "ROM не правильного формата!": Close: Exit Sub
'MsgBox "Считан управляющий байт " & Hex(bte) & " по адресу " & Hex$(adr1 - 1)
cnt = 0
adr1 = adr1 + 1
uprbyte = bte
If uprbyte = 0 Then
    MsgBox "Управляющий байт по адресу " & Hex$(adr1 - 1) & " равен нулю - выход."
    GoTo ENDUNP
End If

Считывается "управляющий" байт, который будет говорить распаковщику, что делать.
Если он равен 0, то значит процедура распаковки закончена, если же нет, то идём дальше.

Код:
count:
cnt = cnt + 1
If cnt = 8 Or uprbyte = 0 Then GoTo getuprbyte  '
If uprbyte / 2 = uprbyte \ 2 Then rbit = 0 Else rbit = 1
'MsgBox "Правый бит байта " & Hex(uprbyte) & " равен " & rbit
uprbyte = uprbyte \ 2
If rbit = 1 Then
    Get #1, adr1, bte: adr1 = adr1 + 1
    Put #2, adr2, bte: adr2 = adr2 + 1
    'MsgBox "Правый бит равен 1, просто считываем байт " & Hex(bte) & " по адресу " & Hex(adr1 - 2) & " и пишем байт " & Hex(bte) & " по адресу " & Hex(adr2 - 2)
    GoTo count
Else
    Get #1, adr1, bte: adr1 = adr1 + 1: pbyte1 = bte
    Get #1, adr1, bte: adr1 = adr1 + 1: pbyte2 = bte
    'MsgBox "Правый бит равен 0, читаем байты " & Hex(pbyte1) & " и " & Hex(pbyte2) & " по адресу " & Hex(adr1 - 3)
    'pbyte = Val("&h" + Right$("00" + Hex$(pbyte1), 2) + Right$("00" + Hex$(pbyte2), 2))
    'If pbyte < 0 Then
        pbyte = (pbyte1 * 256) + pbyte2
        'MsgBox pbyte
    'End If
    For koef = 1 To 16
    If pbyte / 2 = pbyte \ 2 Then bitst = "0" & bitst Else bitst = "1" & bitst
        pbyte = pbyte \ 2
    Next koef
  Right(Str$(bitsn1), Len(Str$(bitsn1)) - 1), 8)
 

    bits2 = Right(bitst, 16 - num)
    bits1 = Left(bitst, num)
    
    For r = 0 To Len(bits1) - 1
        byte1 = byte1 + Val(Mid(bits1, Len(bits1) - r, 1)) * (2 ^ r)
    Next r
    For r = 0 To Len(bits2) - 1
        byte2 = byte2 + Val(Mid(bits2, Len(bits2) - r, 1)) * (2 ^ r)
    Next r

  If byte2 = 0 Then byte2 = 2048
    adr2b = adr2 - byte2
  
   If adr2b < 1 Then MsgBox adr2b & "   " & adr2 & " - " & byte2 & "|||" & Hex(adr1 - 3) & "   " & bitst
 
    
    If byte1 = 0 Then byte1 = 32
    
    For cntr = 1 To byte1
    Get #2, adr2b, bte: adr2b = adr2b + 1
    Put #2, adr2, bte: adr2 = adr2 + 1
    If bte < 0 Then MsgBox adr1 & "   " & adr2 & "    " & adr2b
    Next cntr
    End If
    bitst = ""
    pbyte = 0
    bits = 0
    bitsn1 = 0
    bitsn2 = 0
    byte1 = 0
    byte2 = 0
    adr2b = 0
    GoTo count
    MsgBox "Почему выход?"
ENDUNP:
Close
MsgBox "Всё! Последний байт по адресу " & Hex$(adr1 - 1)
End Sub

Тут байт разлаживается по битам, начиная с правого. Происходит это путём логического сдвига вправо, т.е. все биты сдвигаются вправо и самый правый читается программой. Если бит равен 1, то просто считываем байт в файл(приставка делает это в видеопамять). Если бит равен 0, то считывается два байта подряд, у которых потом берутся первые num бит(num - кол-во бит, отводящееся под кол-во повторений), хотя можно взять первые num-16 бит с другой стороны, то есть если на указатель отводится n бит, то на кол-во повторений остаётся 16-n бит, т.к. в двух байтах 16 бит. В данном случае справа берётся num-16 бит, это будет "указатель". Оставшейся биты определяют кол-во повторений. Ну так вот, программа возвращается назад в создаваемом файле графики на столько байт, какое значение имеет "указатель", считывает кол-во байт, которое определяется битами, отвечающими за кол-во повторений, а затем пишет их в этот же файл, только уже в конце.
Всё это будет повторятся, пока "управляющий" байт не станет равен нулю, затем программа переходит к считыванию следующего "управляющего" байта, пока она не встретин нулевой "управляющий" байт.
Дальше идёт присвоение переменным исходных значений.

Хочу ещё раз обратить внимание на знаки  ' , после них идёт не рабочая часть кода, это просто комментарии.

Если чего не понял - спрашивай, я иногда сам себя не понимаю :)

Отредактировано HoRRoR (2006-09-01 19:39:08)

0

8

Я написал(а):

Тут, кстати, графика похоже не пожата.

Хотя, может RLE...

0

9

D.s3mm написал(а):

З.Ы. Появился вопрос размеры вот я читал в что ромы Snes расширять можно, а остольных приставок это возможно? ЕСли да то посколько?

В конец рома можно что-нибудь запихнуть,изменив при этом пойнтер.На Genesis,по-моему, можно до 4 Mb.(Или до 8-не помню).

0

10

Чёрт... У тебя нюх что-ли на такие вещи? К счастью, мне опять было нечего делать весь день: да, графика пожата RLE.
Правда, такого RLE я ещё не встречал.
Поначалу я всё думал, что тут им и не пахнет, однако, разобравшись в коде понял, что принципиально
он напоминает именно RLE. Точнее, сам алгоритм не так сложен, но с точки зрения кода игры можно было
всё это cделать намного легче, как в большинстве других игр - эффективность сжатия от этого бы не
снизилась. Специально не говорю что за алгоритм - если захочешь - можешь попробовать сам всё распаковать -
не буду лишать удовольствия. Вот что у меня получилось:

http://griever.ucoz.ru/files/cabal2.png

Тайловая карта титульника(конечно не только титульника) пожата тем же муторным алгоритмом.
На рисунке - разжатая графика титульника, повешенная на разжатую тайловую карту титульника.

http://griever.ucoz.ru/files/cabal.png

Графика внутриигровая не пожата, зато повсюду спрайтовые надписи =).
Текст, вроде, нормальный,судя по заставке - дальше мне лень было лезть. А есть ли там вообще текст?
Не стоит забывать и о главной проблеме: написание упаковщика. Чем легче алгоритм(а RLE относится
к элементарным), тем хуже он жмёт данные. Т.е. поставил лишнюю чёрточку в одной букве(особенно это
касается Ж) - RLE пожмёт данные в бОльшую цепочку - ресурс не влезет в ром. Та же ситуация и с
тайловой картой, но она нагляднее, плюс - оригинальная тайловая карта тоже очень плохо пожалась.
И, наконец, очень трудно само написание упаковщика. Мало того, что нельзя воспользоваться подобием
из кода игры (как это бывает с распаком), так ещё возникают тысячи мелких проблем с особенностями
работы упаковщика. Помнится, я под самый общий RLE писал упаковщик - до сих пор как-то криво жмёт,
но, вроде, это не сказывается на качестве графики...

Отредактировано Griever (2006-09-02 19:24:34)

0

11

Огромное спасибо за сделаную за меня работу.
P.S. после прочтения темы форума про RLE в N-цатый раз у меня появился вопрос(кахись с него и нодо было начинать разговор) вот там написано:

HoRRoR написал(а):

...{Неизвестный байт}{00}{Описывающий байт}{Байты графики}...

В чем, где этот код виден и как его отличить от ненужного?

0

12

D.s3mm написал(а):

В чем, где этот код виден и как его отличить от ненужного?

Этот код ты можешь увидить в обычном hex-редакторе, а чтобы отличить его от ненужного, ты должен заранее найти место с пожатыми данными, например поганкой, т.е. поганить РОМ до тех пор, пока не изменятся искомые данные. Определив границы кода тебе легче будет разобраться с алгоритмом, ещё легче это будет при знании асма и имении дебагера.

0

13

:) Да, ещё есть житейский способ: особенность RLE в том что есть цепь с непожатыми данными(если байты идут все время разные). вот их и ищешь. смотришь где они обрываются на каком-нибудь необычном байте - он и будет управляющим.

0

14

В LZ77 первые байты, кстати, тоже идут не пожатыми.

0


Вы здесь » Magic Team » Программирование » Помогите молодому программисту