Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Dekodowanie plików .mgx
Forum PHP.pl > Forum > PHP
sanneo
Witam serdecznie wszystkich.

Jako, że jestem tutaj nowy, to się przy tej okazji przedstawię.

Nazywam się Mariusz, pochodzę z Łomży, ale od 4 lat mieszkam w Warszawie pracuję i studiuję Informatykę w zarządzaniu (7 semestr aktualnie)

Od 2002 roku programuje w PHP.

Moja stronka domowa to http://www.sanneo.net (nieaktualizowana od lat, kiedyś do niej wrócę)

Moja druga stronka, to stronka o mojej ulubionej grze Age of Empires 2 the Conquerors Expansion - http://www.empires2.net

I w związku z tą właśnie drugą stronką potrzebuję dekodować pliki .mgx za pomocą PHP.

Chciałbym utworzyć nasz własny wewnętrzny system ratingu, zasada byłaby taka.

Użytkownik postuje plik .mgx, PHP go przetwarza i zapisuje dane do bazy danych w tym wyniki rozgrywki.

Długo szukam rozwiązania mojego problemu, ale niestety nie wiele jest o tym typie pliku napisane.

Znalazłem bardzo ważne źródła informacji:
http://aocai.at.infoseek.co.jp/mgx_format.html

Jest tu opisana dokładna budowa pliku .mgx, dla mnie do póki co czarna magia, bo aż tak się w stukturę plików nie zagłębiałem, nawet nie potrafię tego oczytać.

Przykładowy plik .mgx, gdyby ktoś zechciał testować:
http://www.sanneo.net/tmp/FC1_Tournament_G...auT__Game_5.mgx

A także przykład, gdzie jest pokazane, że da się tak zrobić w PHP:


Prosiłbym o namiary na jakieś ciekawe strony gdzie dekodowanie plików będzie opisane jeżeli tutaj nie znajdę odpowiedzi.

Na stronie http://www.empires2.net jestem jako PL_King

Pozdrawiam serdecznie
Mariusz (sanneo)
kicaj
Musisz sam poznac strukture tego pliku, a my pomozemy Ci wyciagnac dane za pomoca php - jesli oczywiscie bedziesz mial problemy
sanneo
Witam.

Struktura pliku jest podana pod tym linkiem:
http://aocai.at.infoseek.co.jp/mgx_format.html

Ale zupełnie nie wiem jak takie coś odczytać, any hints, any resources?

Pozdrawiam
Kicok
Poczytaj sobie o funkcji unpack" title="Zobacz w manualu PHP" target="_manual. W manualu niewiele pisze więc przeglądnij sobie jeszcze pack" title="Zobacz w manualu PHP" target="_manual i google. Przyda się też substr" title="Zobacz w manualu PHP" target="_manual.

W pliku tym liczby całkowite zapisywane są tak, że najmniej znaczący bajt jest na początku. Dlatego do odczytywania danych typu int używaj: V ( Manual: unsigned long (always 32 bit, little endian byte order) )

Główna część pliku, w której są zapisane interesujące cię informacje, jest skompresowana, więc musisz użyć funkcji gzinflate" title="Zobacz w manualu PHP" target="_manual z biblioteki zlib" title="Zobacz w manualu PHP" target="_manual aby odzyskać oryginalne dane.
Kod, który odczyta i zdekompresuje "compressed_data" z pliku:

  1. <?php
  2.  
  3.  
  4.  
  5. // Ścieżka do pliku .mgx
  6. $filename = 'FC1_Tournament_Grand_Finals_L_Clan_Chris_vs__DauT__Game_5.mgx';
  7.  
  8.  
  9. // Sprawdzamy czy plik istniejne
  10. if( !file_exists( $filename ) )
  11. {
  12. die( 'Nie odnaleziono pliku .mgx' );
  13. }
  14.  
  15.  
  16. // Otwieramy plik w trybie "do odczytu"
  17. $fp = fopen( $filename, 'rb' );
  18.  
  19. // Odczytujemy długość naglówka pliku i odejmujemy 8
  20. $array = unpack( 'Vlen', fread( $fp, 4 ) );
  21. $length = $array['len'] - 8;
  22.  
  23. //Odczytujemy 4 zbędne bajty
  24. fread( $fp, 4 );
  25.  
  26.  
  27. // Odczytujemy interesującą nas część pliku
  28. $content = fread( $fp, $length );
  29.  
  30.  
  31. // Kończymy pracę z plikiem
  32. fclose( $fp );
  33.  
  34.  
  35.  
  36. //
  37. // ...
  38. //
  39.  
  40.  
  41.  
  42. ?>
sanneo
Wielkie dzięki Kicok.

Teraz przynajmniej wiem jak się dobrać do pliku.

No i dobrałem się, dodatkowo odkompresowałem dane ze zmiennej $content.

Dodałem fragment kodu:

  1. <?php
  2. $uncompressed = gzinflate($content);
  3. echo print_r("<pre>".$uncompressed."</pre>");
  4. ?>


Efekt jest taki, że część danych jest dla mnie czytelna, ale cała reszta nadal wygląda praktycznie jak przed odkompresowaniem.

Coś jeszcze powinienem o tym wiedzieć?

http://sanneo.nazwa.pl/skrypty_pomocnicze/plik.php

Przejżałem też Google i znalazłem tyle co w manualu PHP, tylko, że w różnych językach smile.gif

Czy te dane z pliku muszę pobierać za pomocą wyrażeń regularnych?

Czym sa te widoczne "krzaczki", jak je zrozumieć?

Pozdrawiam serdecznie
Mariusz (sanneo)
Kicok
Po pierwsze nie patrz się na te dane jak na tekst, bo do niczego nie dojdziesz. Najlepiej zapomnij o wyrażeniach regularnych.

Na stronie masz opisaną strukturę pliku. Idąc od lewej masz kolumnę z typami danych, nazwami, wielkościami i kolumnę z opisem. Musisz teraz odczytywać odpowiednią ilość bajtów. Jeśli na przykład interesuje cię wersja tego pliku oraz "include_ai", to:
- Sprawdzasz ile miejsca zajmuje wersja. W kolumnie z nazwami danych masz "version[8]". Wielkość w nawiasach kwadratowych to ilość danych, natomiast po lewej masz typ danych char. Wynika z tego, że wersja będzie występowała w tym pliku jako napis o 8 znakach długości.
- Z tabelki u góry odczytujesz ile bajtów zajmuje typ char (1 bajt)
- 1 bajt razy 8 wychodzi 8 bajtów

- Zaraz za tym napisem znajdują się 4 bajty: "F6 28 3C 41", które cię nie i interesują.

- Następnie masz "include_ai" o typie BOOL, który zajmuje 4 bajty (czyli może być traktowany jako typ long integer)


Do odczytania tych danych używamy więc funkcji:

  1. <?php
  2.  
  3. // (...)
  4.  
  5. // Odczytujemy interesującą nas część pliku
  6. $content = fread( $fp, $length );
  7. $content = gzinflate( $content );
  8.  
  9. // Kończymy pracę z plikiem
  10. fclose( $fp );
  11.  
  12.  
  13.  
  14. // Odczytujemy teraz wersję pliku oraz include_ai
  15. $dane = unpack( 'a8wersja/x4/Vinclude_ai', $content );
  16. echo '<pre>' . print_r( $dane, true ) . '</pre>';
  17.  
  18.  
  19. // (...)
  20.  
  21. ?>



Wzorzec podany jako argument funkcji unpack" title="Zobacz w manualu PHP" target="_manual wygląda tak:
a8wersja/x4/Vinclude_ai


a - typ danych: string zakończony znakiem NULL
8 - ilość danych: 8 bajtów
wersja - nazwa dla odczytanych danych: "wersja"
/
x - typ danych: bajt NULL (w unpack używa się tego typu do pominięcia określonej ilości bajtów)
4 - ilość danych: 4 bajty
/
V - typ danych: long integer (little-endian) (długość bajtów standardowa dla tego typu: 4 bajty)
include_ai - nazwa dla odczytanych danych: "include_ai"
sanneo
Dziękuje Kicok.

Teraz już mam bardzo dobrą wizję jak to zrobić smile.gif

Spróbowałem sobie pobrać wartość pola:

rec_player_ref

Mój wzorzec wygląda tak, wraz z obsługą danych pliku:

  1. <?php
  2. // Odczytujemy teraz wersję pliku oraz include_ai
  3. $dane = unpack( 'x4290/vrec_player_ref', $content );
  4. echo '<pre>' . print_r( $dane, true ) . '</pre>';
  5. ?>


Efekt jest widoczny tutaj, pobrała mi się wartość 61412, oczywiście jest to zła wartość, no i tu jest pytanie, czy to jest problem tylko złej liczby bajtów pominiętych, czy może zły typ wartości wybrałem?

A jak radzić sobie z polami typu var, które są zaraz po include_ai

W ogóle mam nadzieję, że mogę z Tobą na ten temat dużo korespondować?

Spodziewam sie, że w dalszej mojej pracy także będą problemy, a widać, że masz doświadczenie w czytaniu tego typu plików smile.gif

Pozdrawiam serdecznie
Mariusz (sanneo)
Kicok
Nie ma tak łatwo. Gdzieniegdzie w nazwach danych masz coś w rodzaju: "ai_info[include_ai]" albo "resource_string[num_string]", a to znaczy, że musisz najpierw odczytać "include_ai" i "num_string" żeby wiedzieć ile bajtów będą zajmowały te dane.

Np. jeśli "include_ai" będzie równe 0 a "num_string" 3, to "ai_info[include_ai]" nie będzie występowało w ogóle w tym pliku, a "resource_string[num_string]" wystąpi 3 razy.
sanneo
Heh, wygląda to strasznie smile.gif

Ale jest ciekawe i interesujące.

Dodałem dodatkową funkcjonalność tutaj

A także odkodowałem troszkę więcej danych, wcześniej był problem, bo danych nie odkompresowałem.

Niestety mam kilka pytań dotyczących liczenia bajtów, Ty napisałeś takie coś

Cytat(Kicok)
- 1 bajt razy 8 wychodzi 8 bajtów


Dotyczące pola version[8], według tabeli u góry char ma 1 bajt, natomiast obok tej wartości było 4 byte

W tamtym zestawieniu mamy dwa pola "byte", jedno w tabelce u góry, opisujące jaki typ danych zajmuje ile bajtów i także w tej głównej długiej tabelce mamy pole byte.

Dla przykładu, bo tu utknąłem:

Jest pole: unknown4[17], obok którego jest napisane 17, to jest typ char, który zajmuje 1 byte, to wielkość tego pola jaka jest?

Jak rozumieć te 17 w nawiasach kwadratowych?

Propos poprzedniego mojego posta jeszcze ai_info[include_ai] na szczęście w tej nagranej grze jest puste, więc łatwo to mogłem przeskoczyć smile.gif

Rozumiem, że gdyby nie było puste, to musiałbym wszytkie bajty stamtąd zsumować, aby to przeskoczyć.

Jak obliczać liczbę bajtów, które muszę przeskoczyć, aby dojść do danego pola, chciałbym pobrać wartość pola rec_player_ref i num_player.

Czy ai_info[include_ai] oznacza: powtórz blok ai_info razy include_ai?

Pozdrawiam
Kicok
Cytat(sanneo @ 17.01.2008, 21:50:03 ) *
Niestety mam kilka pytań dotyczących liczenia bajtów, Ty napisałeś takie coś
Cytat("Kicok")
- 1 bajt razy 8 wychodzi 8 bajtów

Dotyczące pola version[8], według tabeli u góry char ma 1 bajt, natomiast obok tej wartości było 4 byte

Nie wiem właśnie dlaczego tam pisze 4 bytes. Według mnie jest to błąd, bo w kolumnie z opisem są podane wszystkie możliwości: "VER 9.4", "VER 9.3" i "TRL 9.3". Każde z nich ma 7 znaków długości ( + ósmy znak: NULL ). Można to sprawdzić zapisując odkompresowane dane w pliku, a następnie otwierając ten plik jakimś HEXedytorem.


Cytat(sanneo @ 17.01.2008, 21:50:03 ) *
Dla przykładu, bo tu utknąłem:

Jest pole: unknown4[17], obok którego jest napisane 17, to jest typ char, który zajmuje 1 byte, to wielkość tego pola jaka jest?

Jak rozumieć te 17 w nawiasach kwadratowych?

17 * ilość_bajtów_jaką_zajmuje_typ_char
Czyli: 17 * 1


Cytat(sanneo @ 17.01.2008, 21:50:03 ) *
Propos poprzedniego mojego posta jeszcze ai_info[include_ai] na szczęście w tej nagranej grze jest puste, więc łatwo to mogłem przeskoczyć smile.gif

Rozumiem, że gdyby nie było puste, to musiałbym wszytkie bajty stamtąd zsumować, aby to przeskoczyć.

Tak


Cytat(sanneo @ 17.01.2008, 21:50:03 ) *
Jak obliczać liczbę bajtów, które muszę przeskoczyć, aby dojść do danego pola, chciałbym pobrać wartość pola rec_player_ref i num_player.

Czy ai_info[include_ai] oznacza: powtórz blok ai_info razy include_ai?

Tak


Jako że include_ai jest w tym pliku równe 0, to możesz pominąć cały duży blok AI_info. W takim wypadku odczytanie rec_player_ref i num_player jest proste. Jednak jeśli w którymś pliku include_ai będzie równe 1, to będziesz musiał obliczyć ile bajtów trzeba pominąć. Czyli będziesz musiał odczytać jeszcze "num_string", żeby wiedzieć ile razy wystąpi blok "resource_string[num_string]", oraz "string_length", żeby znać długość każdego "str[string_length]" ;]
sanneo
Cytat(Kicok)
W takim wypadku odczytanie rec_player_ref i num_player jest proste.


Hmm, próbuję na różne sposoby, różnymi wzorcami, ale nie mogę wyciągnąć poprawnej wartości.

Próbuję z wzorcami:

a8version/x4/Vinclude_ai/x4/Vgame_speed1/x4/Vgame_speed2/x25/a2rec_player_ref

a8version/x4/Vinclude_ai/x4/Vgame_speed1/x4/Vgame_speed2/x25/a2rec_player_ref

I kilkoma innymi, ale ciągle mam "dziwne" wyniki.

Jak mam zatem traktować typ wartości short?

Według górnej tabelki w opisie budowy pliku short ma zawsze 2 Bajty

Pozdrawiam
Mariusz (sanneo)
Kicok
OK, no to otwórzmy odkompresowane dane w HEXedytorze i popatrzmy na tą część tabelki:
Kod
int    game_speed1    4
int    zero    4     
int    game_speed2    4     
float     unknown2    4     
int     unknown3     4     
char     unknown4[17]     17     
short     rec_player_ref     2     
char     num_player     1     
int     zero2     4     
char     negative[12]     12


Co wiemy o tych danych:
-# (int)game_speed1 i (int)game_speed2 mogą przyjmować wartości: 100, 150 lub 200 ( czyli: 64000000, 96000000 lub C8000000 )
-# między (int)game_speed1 a (int)game_speed2 jest jeszcze (int)zero ( czyli najprawdopodobniej: 00000000 )
- nastepnie powinno być 25 bajtów, które nas nie interesują
-# później mamy: (short)rec_player_ref
-# zaraz za nim: (char)num_player (obie wartoścvi powinny być stosunkowo niewielkie )
-# następnie (int)zero2 ( czyli najprawdopodobniej: 00000000 )
-# i (char)negative[12] ( które z kolei wygląda na: FFFFFFFFFFFFFFFFFFFFFFFF )

Odnajdujemy charakterystyczne miejsca w HEXedytorze i sprawdzamy, czy rzeczywiście jest tam "25 bajtów, które nas nie interesują":


Ja ich naliczyłem 29. Wygląda więc na to, że nie powinieneś zbytnio wierzyć tej stronce: http://aocai.at.infoseek.co.jp/mgx_format.html
sanneo
Witam.

Co krok to coraz dalej smile.gif

Przygotowałem sobie taki wzorzec

a8version/x4/Vinclude_ai/x4/Vgame_speed1/x4/Vgame_speed2/x29/vrec_player_ref/vnum_player/x61/imap_size_x/imap_size_y/inum_unknown_data/x2/

Efekt jego działania widoczny jest tutaj

Natrafiłem na kolejną ciekawostkę, fragment tej długiej tabelki:

Map | map[map_size_x][map_size_y] | var | Map data

Czy mam to map[map_size_x][map_size_y] traktować jako: "powtórz map data razy map_size_x*map_size_y"?

Wewnątrz tego jest bloczek:

char | terrain_id | 1
char | elevation | 1

Czy aby pominąć taki blok, to mam użyć x28800 Bajtów (map_size_x*1+map_size_x*1+map_size_y*1+max_size_y*1) dla przykładu pod linkiem, gdzie map_size_x = 120 i map_size_y = 120?

Czy taki zapis powinienem rozumieć inaczej?

A druga sprawa, pobrałem sobie taki HexEdytor jak Twój i z lewej strony w wąskiej kolumnie (1 od lewej) wyświetlane są chyba adresy bajtów, aczkolwiek nie widzę w tamtej kolumnie logiki, zatem o co w niej chodzi?

No i jeszcze jedna ważna sprawa, a raczej poytanie.

Czytam sobie manual PHP i funkcję pack()

Jest tam:
Tabela 148. pack() format characters
i są tam typy danych mające przedrostek signed i unsigned, co to oznacza?

Oczywiście tłumaczenie znam, ale co to znaczy w PHP? smile.gif

W oczekiwaniu na Twoja odpowiedź idę jeszcze trochę pokombinuję smile.gif

Może wciągnę jakieś dane gracza z bloku:
Player_info | player_info[num_player] | var | index 0 is GAIA data smile.gif

Pozdrawiam
Mariusz (sanneo)
Kicok
Cytat
Natrafiłem na kolejną ciekawostkę, fragment tej długiej tabelki:

Map | map[map_size_x][map_size_y] | var | Map data

Czy mam to map[map_size_x][map_size_y] traktować jako: "powtórz map data razy map_size_x*map_size_y"?

Wewnątrz tego jest bloczek:

char | terrain_id | 1
char | elevation | 1

Czy aby pominąć taki blok, to mam użyć x28800 Bajtów (map_size_x*1+map_size_x*1+map_size_y*1+max_size_y*1) dla przykładu pod linkiem, gdzie map_size_x = 120 i map_size_y = 120?

Tak. Mapa o wymiarach 120x120 ma 14400 pól, a każde pole opisane jest dwoma bajtami ( typ terenu i wysokość ), czyli razem 28800 bajtów.


Cytat
A druga sprawa, pobrałem sobie taki HexEdytor jak Twój i z lewej strony w wąskiej kolumnie (1 od lewej) wyświetlane są chyba adresy bajtów, aczkolwiek nie widzę w tamtej kolumnie logiki, zatem o co w niej chodzi?

Tak, to jest adres pierwszego w danym rzędzie bajtu. Czyli ilość bajtów która jest przed nim zapisana w systemie szesnastkowym.
Na screenie który zamieściłem w poście powyżej w jednym rzędzie znajdują się 23 bajty. Jeśli zmienisz sobie rozmiar okna tak, że będzie ich w jednym rzędzie 16, to zauważysz logikę ;]


Cytat
No i jeszcze jedna ważna sprawa, a raczej poytanie.

Czytam sobie manual PHP i funkcję pack()

Jest tam:
Tabela 148. pack() format characters
i są tam typy danych mające przedrostek signed i unsigned, co to oznacza?

Oczywiście tłumaczenie znam, ale co to znaczy w PHP?

Informuje to funkcję unpack" title="Zobacz w manualu PHP" target="_manual jak ma traktować pobrany ciąg bitów. Poczytaj na googlach o binarnym kodowaniu liczb ujemnych
sanneo
Witam smile.gif

Cytat(Kicok)
Tak, to jest adres pierwszego w danym rzędzie bajtu. Czyli ilość bajtów która jest przed nim zapisana w systemie szesnastkowym.


Już widzę. Traktowałem wartości, 0, 17, 45, 73 itd. z pierwszej kolumny jako wartości decymalne, a okazuje się, że to jest zapis szesnastkowy, także już wszystko się zgadza tongue.gif

Cytat(Kicok)
Na screenie który zamieściłem w poście powyżej w jednym rzędzie znajdują się 23 bajty. Jeśli zmienisz sobie rozmiar okna tak, że będzie ich w jednym rzędzie 16, to zauważysz logikę ;]


Tak, to zauważyłem już wczoraj smile.gif

Ustawiłem sobie szerokość tyle bajtów co u Ciebie tongue.gif

Tym razem przychodzę z praktycznym problemem do Ciebie jak można.

Niebardzo wiem jak praktycznie wykorzystać te dane w programie PHP.

unpack() tworzy tablicę danych, a jak chciałbym przejść po całym pliku, to albo wzorzec byłby mega długi i nie do końca poprawny, bo niektóre bloki trzeba powtarzać, albo musiałbym skakać co każde wywołanie unpack() pomijając zsumowaną liczbę bajtów. Raczej skłaniam się ku drugiej opcji.

Jak to praktycznie się rozwiązuje?

Propos binarnego kodowania liczb ujemnych, to już się boję... winksmiley.jpg

PS: Mam pewien sukces, udało mi się pobrać dane o początkowej wartości jednostek jedzenia playera smile.gif

Pozdrawiam serdecznie
Mariusz (sanneo)

Edit: 20-01-2008 10:22
No prosze, poszedłem dalej i udało mi się to praktycznie wykorzystać w PHP tongue.gif

Poszedłem za moją metodą numer 2, okazuje się, że jest całkiem funkcjonalna, nawet udało się zautomatyzować proces odkodowywania danych smile.gif

-> tutaj


Jednak trafiłem na coś z czym sobie chyba nie poradzę sad.gif

Ten fragment mnie blokuje:

char | long_unknown_data[?] | ?

Nie wiem ile tam bajtów jest, próbowałem znaleźć jakieś punkty zaczepienia, tak jak zrobiłem z bajtami 98 9E 00 00 02 0B.

Zatem może ktoś jeszcze zechce się wypowiedzieć w temacie i "pomóc"?

Pozdrawiam
Kicok
W takim razie albo szukasz na necie dokładniejszego opisu struktury tego pliku, albo jednak używasz wyrażenia regularnego, które usunie ze zmiennej $content wszystkie dane aż do obj_exist_flg[num_object]:
  1. <?php
  2.  
  3.  
  4. // Odczytujemy interesującą nas część pliku
  5. $content = fread( $fp, $length );
  6. $content = gzinflate( $content );
  7.  
  8.  
  9. // (...)
  10.  
  11.  
  12. // Usuwamy nieznaną ilość bajtów ze zmiennej $content
  13. preg_match( '/x62x03x00x00((?:(?:x00|x01)x00x00x00){866})(.*)$/s', $content, $matches );
  14. $content = $matches[1].$matches[2];
  15. unset( $matches );
  16.  
  17. echo $content;
  18.  
  19.  
  20. ?>



Mam nadzieję, że między long_unknown_data[?] a unknown14[?] nie było żadnych danych, które chciałbyś wyciągnąć ;]

Teraz na początku zmiennej $content będziesz miał 866 * (0x00000001 lub 0x00000000). Musisz zliczyć ile razy w tym ciągu wystąpi 0x00000001, żeby wiedzieć ile razy powtórzy się blok: Master_Object[var]
sanneo
Witam.

Chyba ten wzorzec wyrażenia regularnego u mnie nie zadziałał w sensie, że echo $content (w moim wypadku $uncompressed_data) był pusty.

Ale w związku z tym, czy nie lepiej wykorzystać strpos()?

Oczywiście i tego próbowałem, ale żaden z poniższych zapisów nie działał (wyszukiwałem za pomocą strpos() ciąg bajtów "98 9E 00 00 02 0B", to jeszcze było wczoraj).

strpos($uncompressed_data,0x98 0x9E 0x00 0x00 0x02 0x0B)
strpos($uncompressed_data,0x989E0000020B)
strpos($uncompressed_data,\\x98\\x9E\\x00\\x00\\x02\\x0B)

za to zadziałało takie coś:

strpos($uncompressed_data,0x98);

Tylko, aby to było pewne, musiałem dodać liczbę bajtów do pominięcia, w moim wypadku $byte_jump

I wszystko odnoście tego ciągu bajtów "98 9E 00 00 02 0B" działało OK.

Podsumowując, w jaki sposób wyszukać ciąg kolejnych bajtów za pomocą strpos()?

A inna sprawa, w tym pliku (1v1.mgx) znajdują się między innymi wartości:

1026 - punkty zbrojeniowe military points (war_point) int
4437 - łączna liczba punktów (total_point) int
2655 - suma liczba jednostek złota (total_gold) float
9083 - suma liczba jednostek drewna (total_gold) float

Jak te wartości odszukać za pomocą Twojego hex Edytora?

To by dało jakiś punkt zaczepienia w razie dalszych problemów smile.gif

Najważniejsze, to chyba określanie strpos() ciągu bajtów lub Twoje wyrażenie regularne, ale w wyrażeniach regularnych czuję się średnio, jeszcze gdyby to był tekst to Ok, ale nie dość, że to są bajty, to jeszcze wydaje mi się zapis niezrozumiały, zatem wolałbym nauczyć się szukać ciągu bajtów za pomoca strpos().

Cytat(Kicok @ 20.01.2008, 12:34:58 ) *
Mam nadzieję, że między long_unknown_data[?] a unknown14[?] nie było żadnych danych, które chciałbyś wyciągnąć ;]

Na razie są niepotrzebne, może kiedyś w bardziej zaawansowanym etapie potrzebowałbym odczytywać nazwy plików tam zawartych, ale to mało ważne, więc można pominąć smile.gif

Cytat(Kicok @ 20.01.2008, 12:34:58 ) *
Teraz na początku zmiennej $content będziesz miał 866 * (0x00000001 lub 0x00000000). Musisz zliczyć ile razy w tym ciągu wystąpi 0x00000001, żeby wiedzieć ile razy powtórzy się blok: Master_Object[var]

Dobrze wiedzieć, że w tym wypadku mam brać pod uwagę ciąg 0x00000001, a nie oba smile.gif

Domyślam się, że to będzie oznaczało rozłożenie elementów po mapie należących do danego gracza.

Tak na prawdę po etapie player_name, player_color, player_civ potrzebne mi są tylko dane z sekcji Achievement.

Ale żeby pobrać dane z tej sekcji, to muszę najpierw pozbyć się wszystkich bajtów opisującycy ustawienia gracza*liczba graczy, w takim wypadku, także strpos dałoby mi pewnego rodzaju pomoc, tak mi się zdaje smile.gif

Pozdrawiam smile.gif
Mariusz (sanneo)
Kicok
Cytat
Chyba ten wzorzec wyrażenia regularnego u mnie nie zadziałał w sensie, że echo $content (w moim wypadku $uncompressed_data) był pusty.

Dziwne, bo u mnie działa. W specyfikacji pliku pisało, że zawsze będzie w nim występowała liczba 866 (0x00000362). W pliku który zamieściłeś w pierwszym poście występuje i u mnie to wyrażenie działa prawidłowo.


Cytat
Oczywiście i tego próbowałem, ale żaden z poniższych zapisów nie działał (wyszukiwałem za pomocą strpos() ciąg bajtów "98 9E 00 00 02 0B", to jeszcze było wczoraj).

strpos($uncompressed_data,0x98 0x9E 0x00 0x00 0x02 0x0B)
strpos($uncompressed_data,0x989E0000020B)
strpos($uncompressed_data,\\x98\\x9E\\x00\\x00\\x02\\x0B)

za to zadziałało takie coś:

strpos($uncompressed_data,0x98);

  1. <?php
  2.  
  3. strpos( $uncompressed_data, "x98x9Ex00x00x02x0B" );
  4.  
  5. ?>

Tutaj musi być cudzysłów, oraz pojedyncze slashe. Zamiast \xNN będzie do stringu wstawiony znak o kodzie ASCII 0xNN


Cytat
A inna sprawa, w tym pliku (1v1.mgx) znajdują się między innymi wartości:

1026 - punkty zbrojeniowe military points (war_point) int
4437 - łączna liczba punktów (total_point) int
2655 - suma liczba jednostek złota (total_gold) float
9083 - suma liczba jednostek drewna (total_gold) float

Jak te wartości odszukać za pomocą Twojego hex Edytora?

int:
Odpalasz windowsowski kalkulator, zamieniasz te liczby na HEX (Upewnij się, że zaznaczone masz Dword - przyda się jak będziesz chciał znaleźć liczbę ujemną) zapisujesz sobie gdzieś na kartce uzupełniając liczby zerami do 8 cyfr, odpalasz HEXedytora, Ctrl + F i wpisujesz zapisaną liczbę "parami od tyłu", np.:
1026 = 402h = 00000402h ===> 02 04 00 00
4437 = 1155h = 00001155h ===> 55 11 00 00

float:
Liczby zmiennoprzecinkowe mają o wiele bardziej skomplikowany zapis, więc najprawdopodobniej ciężko będzie cokolwiek znaleźć.
sanneo
Witam.

Dzięki Kicok za poświęcony mi czas i za wszystkie informacje, które mi przekazałeś, były dla mnie bardzo, bardzo pomocne, dowiedziałem się mnóstwo ciekawych rzeczy o budowie plików.

Niestety potem są jeszcze większe schodki, które dziś próbowałem przejść i niestety.

Jeszcze skupię się na wyciągnięciu tylko potrzebnych danych, typu nazwy graczy ich osiągnięcia itp, czyli głównie część Achievement, może się uda - kombinując i wyszukując specyficznych wartości.

Ps: Twoje wyrażenie regularne zadziałało, coś miałem skopane jak tamto poprzednim razem sprawdzałem.

Ps2: Domyślam się, że tamta tabelka nie była wygenerowana ręcznie, czy znasz jakieś programy do analizy plików i generowania tego typu zestawień? smile.gif Intryguje mnie, skoro ktos miał pola Unknown z nieznaną liczbą bajtów, to jak mu się udało odkodować pozostałe dane?

Raz jeszcze dzięki za poświęcony czas.

Pozdrowienia!

Mariusz (sanneo)
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.