├── .clang-format ├── .gitignore ├── CMakeBuildPackage.cmake ├── CMakeLists.txt ├── README.md ├── arcanum ├── art.bt └── dat.bt ├── beyond-good-and-evil ├── README.rst ├── bf.bt ├── bge.bti ├── bge.r2 ├── bin-riff.bt ├── bin-riff2.bt ├── bin-txg.bt ├── bin-wow.bt ├── bootstrap ├── decomp.cpp ├── extract-wow.1sc ├── extract.cpp ├── wip-gao.bt └── wip-wow.bt ├── commandos └── dir.bt ├── commandos2 └── pck.bt ├── common.bt ├── fallout └── dat.bt ├── fallout2 └── dat.bt ├── game-data-reverse-engineering-config-version.cmake ├── game-data-reverse-engineering-config.cmake ├── neverwinter-nights-2 ├── README ├── fxa.bt ├── gr2.bt ├── gr2raw.bt ├── granny-asm.cpp ├── granny-dis.cpp ├── granny.cpp ├── mdb.bt ├── nwn-gr2-raw.py └── nwn-gr2.py ├── neverwinter-nights └── gff.bt ├── primordia ├── adventure-game-studio-clib.bt └── primordia-decrypt.cpp ├── python ├── arcanum.py ├── fallout.py ├── fallout2.py ├── format │ ├── __init__.py │ ├── arcanum.py │ ├── fallout.py │ ├── fallout2.py │ └── neverwinter_nights.py ├── lzss │ ├── __init__.py │ ├── lzss.pyx │ └── setup.py └── neverwinter_nights.py ├── src ├── undertale-game2po.cpp └── undertale-po2game.cpp └── undertale ├── extract-strings-2.cpp ├── extract-strings.cpp ├── patch-strings.cpp ├── undertale.bt ├── undertale.cpp └── undertale.h /.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | AlignConsecutiveAssignments: true 3 | AlignConsecutiveDeclarations: true 4 | ColumnLimit: 80 5 | PointerAlignment: Left 6 | AlwaysBreakTemplateDeclarations: false 7 | AlignEscapedNewlinesLeft: true 8 | ... 9 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.4) 2 | list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}") 3 | include(CMakeBuildPackage) 4 | 5 | build_package() 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # game-data-reverse-engineering 2 | Reverse engineering resources for data files from various video games I like 3 | -------------------------------------------------------------------------------- /arcanum/art.bt: -------------------------------------------------------------------------------- 1 | // Arcanum art 2 | 3 | LittleEndian(); 4 | 5 | /* 6 | enum Flags : uint32 { 7 | Static = 0x01, 8 | Critter = 0x02, 9 | Font = 0x04, 10 | Facade = 0x08, 11 | Unknown = 0x10, 12 | }; 13 | */ 14 | 15 | struct Header { 16 | uint32 flags; 17 | uint32 frame_rate; 18 | uint32 rotation_count; 19 | uint32 palette_list[4]; 20 | uint32 action_frame; 21 | uint32 frame_count; 22 | uint32 info_list[8]; 23 | uint32 size_list[8]; 24 | uint32 data_list[8]; 25 | }; 26 | 27 | struct Frame { 28 | uint32 width; 29 | uint32 height; 30 | uint32 size; 31 | int32 off_x; 32 | int32 off_y; 33 | int32 hot_x; 34 | int32 hot_y; 35 | }; 36 | 37 | struct Palette { 38 | uint32 count; 39 | uint32 color[count]; 40 | }; 41 | 42 | Header header ; 43 | 44 | local uint32 i; 45 | for (i = 0; i < 4; ++i) { 46 | if (header.palette_list[i] == 0) 47 | continue; 48 | 49 | Palette palettes ; 50 | } 51 | 52 | local uint32 rotation_count = header.rotation_count; 53 | if (header.flags & 1) 54 | rotation_count = 1; 55 | 56 | Frame frames[rotation_count * header.frame_count] ; 57 | 58 | for (i = 0; i < rotation_count * header.frame_count; ++i) { 59 | struct { 60 | uchar pixel[frames[i].size]; 61 | } image ; 62 | } 63 | -------------------------------------------------------------------------------- /arcanum/dat.bt: -------------------------------------------------------------------------------- 1 | #include "../common.bt" 2 | 3 | LittleEndian(); 4 | 5 | struct Footer { 6 | byte uuid[16]; 7 | Magic magic(4, "1TAD"); 8 | uint32 names_size; 9 | uint32 index_size; 10 | }; 11 | 12 | enum FileFlags { FILE = 1, ZLIB = 2, DIR = 1024 }; 13 | 14 | struct File { 15 | SizedString name; 16 | uint32 name_offset; 17 | FileFlags flags; 18 | uint32 size_unpacked; 19 | uint32 size_packed; 20 | uint32 offset; 21 | 22 | local uint64 position = FTell(); 23 | if (flags == FILE) { 24 | FSeek(offset); 25 | byte contents[size_unpacked] ; 26 | FSeek(position); 27 | } else if (flags == ZLIB) { 28 | FSeek(offset); 29 | byte contents[size_packed] ; 30 | FSeek(position); 31 | } 32 | }; 33 | 34 | struct Index { 35 | uint32 file_count; 36 | File files[file_count] ; 37 | }; 38 | 39 | FSeek(FileSize() - 28); 40 | Footer footer; 41 | 42 | FSeek(FileSize() - footer.index_size); 43 | Index index; 44 | -------------------------------------------------------------------------------- /beyond-good-and-evil/README.rst: -------------------------------------------------------------------------------- 1 | Beyond Good and Evil 2 | -------------------------------------------------------------------------------- 3 | 4 | Quite obfuscated file format, with very few resources. 5 | 6 | Game engine 7 | ================================================================================ 8 | 9 | Game engine is JADE Engine, custom made for Beyond Good and Evil and re-used on 10 | the Prince of Persia trilogy, among other. Engine is not generic and is tailored 11 | for each game. The data file probably as well. 12 | 13 | Assets are stored in a single file named ``sally_clean.bf``. 14 | 15 | BF file format 16 | ================================================================================ 17 | 18 | BF stands for Big File. It consists of a header followed by an ``id and offset`` 19 | table, a ``file`` table, a ``folder`` table, then the resource data. 20 | 21 | Each resource has one entry in the ``id and offset`` table and one in the ``file`` 22 | table. The tables have a capacity and a size and may not be filled. 23 | 24 | Each file is linked to a ``folder``, which has one entry in the ``folder`` table. 25 | 26 | Each folder is linked to is siblings, its parent, and the first file in the 27 | folder. 28 | 29 | The resource data is sometimes compressed with LZO1X algorithm, usually the 30 | files located in the Bin folder, with ``.bin`` extension. 31 | -------------------------------------------------------------------------------- /beyond-good-and-evil/bf.bt: -------------------------------------------------------------------------------- 1 | // Beyond Good and Evil sally_clean.bf 2 | 3 | #include 4 | 5 | LittleEndian(); 6 | 7 | struct { 8 | Magic magic(4, "BIG"); 9 | uint32 unknown; // (0x00000022 == BGE, 0x00000025 == PoP SoT & WW, 0x00000026 == PoP TT) 10 | uint32 fcount ; 11 | uint32 dcount ; 12 | Fixed64 unknown(0x0000000000000000lu); 13 | Fixed64 unknown(0xfffffffffffffffflu); 14 | uint32 capacity; 15 | Fixed32 unknown(0x00000001); 16 | uint32 main_id ; 17 | uint32 fcount; 18 | uint32 dcount; 19 | uint32 offset ; 20 | Fixed32 unknown(0xffffffff); 21 | Fixed32 unknown(0x00000000); 22 | uint32 last; 23 | } header ; 24 | 25 | FSeek(header.offset); 26 | struct Entry { 27 | uint32 offset ; 28 | uint32 id ; 29 | } entries[header.capacity] ; 30 | string ReadEntryId(struct Entry& entry) { string out; SPrintf(out, "%08Xh", entry.id); return out; } 31 | 32 | struct FileEntry { 33 | uint32 size; 34 | uint32 next ; 35 | uint32 prev ; 36 | uint32 folder ; 37 | time_t timestamp; 38 | char name[64]; 39 | } files[header.capacity] ; 40 | string ReadFileName(struct FileEntry& entry) { return entry.name; } 41 | 42 | struct FolderEntry { 43 | uint32 file ; 44 | uint32 child ; 45 | uint32 next ; 46 | uint32 prev ; 47 | uint32 parent ; 48 | char name[64]; 49 | } folders[header.capacity] ; 50 | string ReadFolderName(struct FolderEntry& entry) { return entry.name; } 51 | 52 | local uint32 e; 53 | for (e = 0; e < header.fcount; ++e) { 54 | FSeek(entries[e].offset); 55 | struct { 56 | uint32 size ; 57 | uchar bytes[size]; 58 | } data ; 59 | } 60 | -------------------------------------------------------------------------------- /beyond-good-and-evil/bge.bti: -------------------------------------------------------------------------------- 1 | // Beyond Good and Evil 2 | 3 | typedef struct (uint32 count, string magic) { 4 | char data[count] ; 5 | Assert(data == magic); 6 | } Magic ; 7 | string ReadMagic(Magic& value) { return value.data; } 8 | 9 | typedef struct (uint32 value) { 10 | uint32 data ; 11 | Assert(data == value); 12 | } Fixed32 ; 13 | string ReadFixed32(Fixed32& value) { string out; SPrintf(out, "%08Xh", value.data); return out; } 14 | 15 | typedef struct (uint64 value) { 16 | uint64 data ; 17 | Assert(data == value); 18 | } Fixed64 ; 19 | string ReadFixed64(Fixed64& value) { string out; SPrintf(out, "%016LXh", value.data); return out; } 20 | 21 | typedef struct { string value; } String ; 22 | string ReadStr(String& data) { return data.value; } 23 | 24 | typedef struct (uint32 size) { char value[size]; } PaddedString ; 25 | string ReadPaddedString(PaddedString& data) { return data.value; } 26 | 27 | typedef struct { uint32 size; char value[size]; } SizedString ; 28 | string ReadSizedString(SizedString& data) { return data.value; } 29 | 30 | typedef struct { uint32 count; uint32 data[count]; } UInt32Array; 31 | 32 | typedef struct { 33 | uint32 data ; 34 | } ResId ; 35 | string ReadResId(ResId& value) { string out; SPrintf(out, "%08Xh", value.data); return out; } 36 | 37 | typedef struct (uint32 width, uint32 height) { 38 | local uint32 width = width; 39 | local uint32 height = height; 40 | float data[width * height] ; 41 | } Matrix ; 42 | string ReadMatrix(Matrix& value) { 43 | local string out = "{", buf; 44 | local uint32 x,y; 45 | for (y = 0; y < value.height; ++y) { 46 | if (y > 0) out += ",\n"; 47 | out += "{"; 48 | for (x = 0; x < value.width; ++x) { 49 | if (x > 0) out += ","; 50 | SPrintf(buf, "%f", value.data[x + y * value.width]); 51 | out += buf; 52 | } 53 | out += "}"; 54 | } 55 | out += "}"; 56 | return out; 57 | } 58 | 59 | struct Chunk { 60 | uint32 size ; 61 | byte data[size] ; 62 | }; 63 | -------------------------------------------------------------------------------- /beyond-good-and-evil/bge.r2: -------------------------------------------------------------------------------- 1 | # This requires a patched version of radare2 to remove the forced base address that is used: 2 | # diff --git a/libr/bin/format/pe/pe.c b/libr/bin/format/pe/pe.c 3 | # index 2f0f786eb..0c5343fd3 100644 4 | # --- a/libr/bin/format/pe/pe.c 5 | # +++ b/libr/bin/format/pe/pe.c 6 | # @@ -331,7 +331,4 @@ ut64 PE_(r_bin_pe_get_image_base)(struct PE_(r_bin_pe_obj_t)* bin) { 7 | # imageBase = 0x10000; 8 | # } 9 | # - if (imageBase < bin->size) { 10 | # - imageBase = 0x8000000; 11 | # - } 12 | # return imageBase; 13 | # } 14 | 15 | f sym.memcpy 829 0x00ae8090 16 | af+ 0x00ae8090 sym.memcpy f n 17 | afu 0x00ae83cd @ 0x00ae8090 18 | 19 | f sym.strcpy 248 0x00aeb8e0 20 | af+ 0x00aeb8e0 sym.strcpy f n 21 | afu 0x00aeb9d8 @ 0x00aeb8e0 22 | 23 | afr sym.jmp.KERNEL32.dll_RtlUnwind 0x00b318f2 24 | afr sym.jmp.DINPUT8.dll_DirectInput8Create 0x00af1200 25 | afr sym.jmp.d3d9.dll_Direct3DCreate9 0x00af12c0 26 | afr sym.jmp.DSOUND.dll_DirectSoundCreate8 0x00af12c6 27 | afr sym.jmp.KERNEL32.dll_GetCurrentProcessId 0x00b35800 28 | 29 | afr sym.__sbh_memcpy @ 0x00ae39e0 30 | afr sym.memset 0x00ae49e0 31 | 32 | afr sym.__sbh_free_block.00ae3ac0 0x00ae3ac0 33 | afr sym.__sbh_free_block.00ae3c78 0x00ae3c78 34 | 35 | afr sym.__sbh_alloc_block 0x00ae7869 36 | afr sym.__sbh_alloc_new_group 0x00ae7484 37 | afr sym.__sbh_alloc_new_region 0x00ae73cd 38 | afr sym.__sbh_find_block 0x00ae708a 39 | afr sym.__sbh_free_block 0x00ae70b5 40 | afr sym.__sbh_heap_init 0x00ae7042 41 | afr sym.__sbh_resize_block 0x00ae758a 42 | 43 | afr sym._SEH_prolog 0x00ae65bc 44 | afr sym._SEH_epilog 0x00ae65f7 45 | 46 | afr sym.strcmp 0x00aec9d0 47 | 48 | afr sym.strncmp 0x00ae3090 49 | afvb 0x08 str1 const char * @ 0x00ae3090 50 | afvb 0x0c str2 const char * @ 0x00ae3090 51 | afvb 0x10 num size_t @ 0x00ae3090 52 | 53 | afr sym.strlen 0x00ae5b10 54 | afr sym.strchr 0x00ae4c20 55 | afr sym.strrchr 0x00b36820 56 | afr sym.strspn 0x00b34bb0 57 | afr sym.strcspn 0x00b34190 58 | afr sym.strncpy 0x00aeb9e0 59 | afr sym.strncnt 0x00aeefb8 60 | 61 | afr sym._heap_alloc 0x00ae35c2 62 | afr sym._callnewh 0x00ae7b65 63 | afr sym._nh_malloc 0x00ae3608 64 | afr sym._alloca_probe 0x00ae6610 65 | afr sym.malloc 0x00ae3634 66 | afr sym.calloc 0x00aeccf1 67 | afr sym.free 0x00ae3646 68 | afr sym.realloc 0x00aec01c 69 | 70 | afr sym._NLG_Notify 0x00aee57e 71 | afr sym._global_unwind2 0x00aee4a8 72 | afr sym._local_unwind2 0x00aee4ea 73 | afr sym._unwind_handler 0x00aee4c8 74 | afr sym._except_handler3 0x00aebf44 75 | 76 | afr sym._exit 0x00ae34b8 77 | afr sym.doexit 0x00ae33e5 78 | afr sym.exit 0x00ae34a7 79 | afr sym._cexit 0x00ae34c9 80 | afr sym._c_exit 0x00ae34d8 81 | afr sym._amsg_exit 0x00ae3152 82 | afr sym._onexit 0x00ae664d 83 | afr sym.atexit 0x00ae66cf 84 | 85 | afr sym.__crtExitProcess 0x00ae3350 86 | afr sym.__crtMessageBoxA 0x00aeb7e4 87 | afr sym.__crtGetEnvironmentStringsA 0x00ae61fa 88 | afr sym.__crtGetLocaleInfoW 0x00b3684d 89 | afr sym.__crtGetLocaleInfoA 0x00b3697d 90 | 91 | afr sym.__security_check_cookie.00aeb76f 0x00aeb76f 92 | afr sym.__security_check_cookie.00aeb793 0x00aeb793 93 | afr sym.__security_check_cookie 0x00aeb7a0 94 | afr sym.__security_init_cookie 0x00aee307 95 | afr sym.report_failure 0x00aee35d 96 | 97 | afr sym.__crtGetStringTypeA 0x00ae9008 98 | afr sym.__crtGetStringTypeW 0x00b365f0 99 | afr sym.__crtLCMapStringA 0x00aeb15c 100 | afr sym.__crtsetenv 0x00aef40c 101 | 102 | afr sym.strtoxl 0x00ae4a40 103 | 104 | afr sym.inconsistency.00ae5b9b 0x00ae5b9b 105 | afr sym.inconsistency 0x00b354fc 106 | afr sym.raise 0x00b36af6 107 | 108 | afr sym.UnwindNestedFrames 0x00b32852 109 | afr sym.FrameUnwindFilter 0x00b34d10 110 | afr sym.__FrameUnwindToState 0x00b34d29 111 | afr sym.seh_longjmp_unwind 0x00aec001 112 | afr sym.__InternalCxxFrameHandler 0x00b3545a 113 | afr sym.__cxxframehandler 0x00b328a4 114 | afr sym.catchguardhandler 0x00b328da 115 | afr sym.translatorguardhandler 0x00b328fe 116 | 117 | afr sym.__FrameUnwindToState.00b34dd6 0x00b34dd6 118 | afr sym.__FrameUnwindToState.00b35529 0x0x00b35529 119 | afr sym.__InternalCxxFrameHandler.00b35283 0x00b35283 120 | afr sym.__InternalCxxFrameHandler.00b351c1 0x00b351c1 121 | afr sym.CatchIt.00b34e48 0x00b34e48 122 | afr sym.CatchIt.00b34f80 0x00b34f80 123 | 124 | afr sym.isdigit 0x00aeb584 125 | afr sym.isspace 0x00aeb5ad 126 | afr sym.nanf 0x00422a70 127 | 128 | afr sym.j__free 0x00b31b8c 129 | afr sym._flush.00ae83cd 0x00ae83cd 130 | 131 | f sym._vsnprintf.00ae68ad 1909 0x00ae68ad 132 | af+ 0x00ae68ad sym._vsnprintf.00ae68ad f n 133 | afu 0x00ae7022 @ 0x00ae68ad 134 | 135 | afr sym._vsnprintf 0x00ae34e7 136 | afr sym.sprintf 0x00ae353d 137 | afr sym.vsprintf 0x00ae3986 138 | afr sym.fprintf 0x00ae3d1d 139 | 140 | afr sym.sscanf 0x00ae311e 141 | afr sym.sscanf.00ae4f69 0x00ae4f69 142 | 143 | afr sym.fclose 0x00ae3740 144 | afr sym.fread 0x00ae3796 145 | afr sym.fwrite 0x00ae387f 146 | afr sym.fgetpos 0x00ae3d4f 147 | afr sym.fsetpos 0x00ae3d71 148 | afr sym.fseek 0x00ae3f69 149 | afr sym.ftell 0x00ae44b9 150 | afr sym.fflush 0x00ae7ef4 151 | afr sym.flsall 0x00ae7f2f 152 | afr sym._filbuf 0x00ae7fa5 153 | afr sym._flsbuf 0x00ae6709 154 | afr sym._flush 0x00ae7e97 155 | afr sym._flushall 0x00ae7f9c 156 | afr sym._fseeki64 0x00ae87cd 157 | afr sym._fsopen 0x00ae3703 158 | afr sym._ftbuf 0x00ae8609 159 | afr sym._ftelli64 0x00ae8645 160 | 161 | afr sym.__DestructExceptionObject 0x00b34de6 162 | afr sym._CallSettingFrame_12 0x00b35560 163 | afr sym._CIpow.00ae47ed 0x00ae47ed 164 | afr sym._CIpow.00ae9689 0x00ae9689 165 | afr sym._CIpow.00ae4865 0x00ae4865 166 | afr sym._CIpow.00ae48ca 0x00ae48ca 167 | afr sym._CIpow.00ae9572 0x00ae9572 168 | afr sym._CIpow.00ae9539 0x00ae9539 169 | afr sym._CIpow 0x00ae4790 170 | afr sym._CopyMan 0x00aee975 171 | afr sym._FF_MSGBANNER 0x00ae5d12 172 | afr sym._IncMan 0x00aee8b6 173 | afr sym._IsZeroMan 0x00aee990 174 | afr sym._RoundMan 0x00aee903 175 | afr sym._RTC_Initialize 0x00ae64c7 176 | afr sym._ShrMan 0x00aee9a9 177 | afr sym._XcptFilter 0x00ae5d4b 178 | afr sym._ZeroTail 0x00aee884 179 | 180 | afr sym.AdjustPointer 0x00b34e2b 181 | afr sym.BuildCatchObject 0x00b34fde 182 | afr sym.BuildCatchObject.00b3284b 0x00b3284b 183 | afr sym.CallCatchBlock2 0x00b32a56 184 | afr sym.CallSETranslator 0x00b32aa7 185 | afr sym.CatchIt 0x00b3515a 186 | afr sym.CPtoLCID 0x00aebb46 187 | afr sym.CreateFrameInfo 0x00b329e9 188 | afr sym.FindAndUnlinkFrame 0x00b32a1d 189 | afr sym.GetLcidFromCountry.00b3441f 0x00b3441f 190 | afr sym.GetLcidFromCountry 0x00b34821 191 | afr sym.GetLcidFromDefault 0x00b34236 192 | afr sym.GetLcidFromLangCountry.00b34530 0x00b34530 193 | afr sym.GetLcidFromLangCountry 0x00b34858 194 | afr sym.GetLcidFromLanguage.00b34750 0x00b34750 195 | afr sym.GetLcidFromLanguage 0x00b348de 196 | afr sym.GetPrimaryLen 0x00b34402 197 | afr sym.GetRangeOfTrysToCheck 0x00b3296f 198 | afr sym.IsExceptionObjectToBeDestroyed 0x00b32a02 199 | afr sym.JumpToContinuation 0x00b3281b 200 | afr sym.LcidFromHexString 0x00b343cd 201 | afr sym.TestDefaultCountry 0x00b342cc 202 | afr sym.TranslateName 0x00b341d6 203 | afr sym.TypeMatch 0x00b34cc1 204 | afr sym.ValidateExecute 0x00b365c0 205 | afr sym.ValidateRead 0x00b365a4 206 | 207 | af sym.WinMainCRTStartup 0x00ae3177 208 | 209 | afr sym.__add_12 0x00aef5e2 210 | afr sym.__addl 0x00aef5c1 211 | afr sym.__ascii_stricmp 0x00b35730 212 | afr sym.__dtold 0x00aeeca5 213 | afr sym.__free_lconv_mon 0x00b33d55 214 | afr sym.__free_lconv_num 0x00b33bcf 215 | afr sym.__get_qualified_locale.00ae30c9 0x00ae30c9 216 | afr sym.__get_qualified_locale.00b344b9 0x00b344b9 217 | afr sym.__get_qualified_locale.00b34250 0x00b34250 218 | afr sym.__get_qualified_locale 0x00b34933 219 | afr sym.__heap_select 0x00ae654f 220 | afr sym.__initmbctable 0x00aebf1c 221 | afr sym.__initmbctable.00aebd30 0x00aebd30 222 | afr sym.__initmbctable.00aebb9e 0x00aebb9e 223 | afr sym.__lc_lctostr 0x00b31fac 224 | afr sym.__set_app_type 0x00ae3595 225 | afr sym.__shl_12 0x00aef640 226 | afr sym.__shr_12 0x00aef66e 227 | afr sym.__tzset 0x00ae8e87 228 | afr sym.__wtomb_environ 0x00aee819 229 | afr sym._abstract_cw 0x00aeedd9 230 | afr sym._access 0x00ae367e 231 | afr sym._allmul 0x00aeb7b0 232 | afr sym._alloc_osfhnd 0x00aec6b5 233 | afr sym._aulldiv 0x00ae8fa0 234 | afr sym._aulldvrm 0x00aec350 235 | afr sym._aullshr 0x00b32730 236 | afr sym._cfltcvt_init 0x00ae939a 237 | afr sym._cfto.00aeed5f 0x00aeed5f 238 | afr sym._cfto.00aefc0c 0x00aefc0c 239 | afr sym._cfto.00af016a 0x00af016a 240 | afr sym._cfto.00aeff32 0x00aeff32 241 | afr sym._cftoe 0x00aece84 242 | afr sym._cftof 0x00aecf77 243 | afr sym._cftog 0x00aed054 244 | afr sym._chmod 0x00ae36c2 245 | afr sym._close 0x00ae7db9 246 | afr sym._clrfp 0x00aeb0d1 247 | afr sym._commit 0x00aec87f 248 | afr sym._control87 0x00aeeef9 249 | afr sym._controlfp 0x00aeef2b 250 | afr sym._copysign 0x00ae4cde 251 | afr sym._crt_debugger_hook 0x00ab33a0 252 | afr sym._ctrlfp 0x00aeb0df 253 | afr sym._d_inttype 0x00aea3c7 254 | afr sym._decomp 0x00aea813 255 | afr sym._dosmaperr 0x00ae7b80 256 | afr sym._errcode 0x00aeadba 257 | afr sym._finite 0x00ae4cff 258 | afr sym._fpclass 0x00ae4d42 259 | afr sym._fptostr 0x00aeec2e 260 | afr sym._free_lc_time 0x00b339b3 261 | afr sym._free_osfhnd 0x00aec7c9 262 | afr sym._freebuf 0x00ae7e6c 263 | afr sym._frnd 0x00aee2eb 264 | afr sym._ftol 0x00b31ba0 265 | afr sym._ftol2 0x00b36c20 266 | afr sym._get_exp 0x00aea7a3 267 | afr sym._get_lc_time 0x00b3364c 268 | afr sym._get_lc_time.00b363d0 0x00b363d0 269 | afr sym._get_osfhandle 0x00aec843 270 | afr sym._getbuf 0x00aec1b6 271 | afr sym._getstream 0x00ae7d47 272 | afr sym._handle_exc 0x00aeab72 273 | afr sym._handle_qnan1 0x00aeae87 274 | afr sym._handle_qnan2 0x00aeaed9 275 | afr sym._heap_init 0x00ae6569 276 | afr sym._hextodec 0x00ae4f21 277 | afr sym._hw_cw 0x00aeee6b 278 | afr sym._hypot.00ae9495 0x00ae9495 279 | afr sym._hypot.00ae947c 0x00ae947c 280 | afr sym._hypot.00ae9407 0x00ae9407 281 | afr sym._hypot.00ae9465 0x00ae9465 282 | afr sym._hypot.00aed1ca 0x00aed1ca 283 | afr sym._hypot.00ae46a4 0x00ae46a4 284 | afr sym._hypot 0x00b31b6f 285 | afr sym._hypothlp 0x00b318f8 286 | afr sym._inc 0x00ae4f53 287 | afr sym._ioinit 0x00ae631c 288 | afr sym._isatty 0x00aec1fa 289 | afr sym._isctype 0x00ae4612 290 | afr sym._ismbblead 0x00aebb35 291 | afr sym._ismbcspace 0x00aee74a 292 | afr sym._isnan 0x00ae4d14 293 | afr sym._itoa 0x00b357bc 294 | afr sym._ld12cvt 0x00aeea24 295 | afr sym._ld12tod 0x00aeeb92 296 | afr sym._lseek 0x00ae885f 297 | afr sym._lseeki64 0x00aec8d6 298 | afr sym._mbschr 0x00aefecb 299 | afr sym._mbsnbicoll 0x00aee7da 300 | afr sym._mbsnbicoll.00aecad9 0x00aecad9 301 | afr sym._mbsnbicoll.00aecb22 0x00aecb22 302 | afr sym._mbsnbicoll.00aeefd4 0x00aeefd4 303 | afr sym._mbsrchr 0x00b35806 304 | afr sym._ms_p5_mp_test_fdiv 0x00aed1a1 305 | afr sym._msize 0x00aec17e 306 | afr sym._nlg_notify1 0x00aee575 307 | afr sym._openfile 0x00ae7bdf 308 | afr sym._powhlp 0x00aea431 309 | afr sym._raise_exc 0x00aea8cd 310 | afr sym._read 0x00ae3d89 311 | afr sym._rtonenpop 0x00ae92dd 312 | afr sym._rttosnpopde 0x00ae9389 313 | afr sym._set_errno 0x00aead94 314 | afr sym._set_exp 0x00aea779 315 | afr sym._set_osfhnd 0x00aec752 316 | afr sym._set_statfp 0x00aeb103 317 | afr sym._setdefaultprecision 0x00aed14f 318 | afr sym._setenvp 0x00ae5f25 319 | afr sym._setjmp3 0x00b31e38 320 | afr sym._setlocale_get_all 0x00b31ffa 321 | afr sym._setmode 0x00aeef41 322 | afr sym._shift 0x00aece67 323 | afr sym._sopen.00aee5ee 0x00aee5ee 324 | afr sym._sopen 0x00aec3e5 325 | afr sym._sptype 0x00aea7b8 326 | afr sym._statfp 0x00aeb0c4 327 | afr sym._stbuf 0x00ae8581 328 | afr sym._strcats 0x00b31eb6 329 | afr sym._strdup 0x00aefea0 330 | afr sym._stricmp 0x00b32cf8 331 | afr sym._strtoui64 0x00ae4bed 332 | afr sym._trandisp1 0x00ae91d0 333 | af sym._trandisp2 0x00ae9237 334 | afr sym._tzset 0x00ae88eb 335 | afr sym._ultoa 0x00b357e6 336 | afr sym._umatherr.00b31eb3 0x00b31eb3 337 | afr sym._umatherr 0x00aeade7 338 | afr sym._wfopen 0x00ae372d 339 | afr sym.atam.00ae94fb 0x00ae94fb 340 | afr sym.atam.00aed2c8 0x00aed2c8 341 | afr sym.atan 0x00b331c0 342 | afr sym.atol 0x00aec975 343 | afr sym.bsearch 0x00b3347e 344 | afr sym.copy_environ 0x00aef3ab 345 | afr sym.cvtdate 0x00ae8b3e 346 | afr sym.fabs.00aeaf37 0x00aeaf37 347 | afr sym.fabs 0x00b33310 348 | afr sym.findenv 0x00aef35e 349 | afr sym.genfname 0x00b32d9c 350 | afr sym.getenv 0x00aeca58 351 | afr sym.gmtime 0x00ae8e9c 352 | afr sym.has_osfxsr_set 0x00ae95dc 353 | afr sym.init_namebuf 0x00b32d3b 354 | afr sym.iswalpha 0x00b32b73 355 | afr sym.iswctype 0x00b355ac 356 | afr sym.iswdigit 0x00b32b84 357 | afr sym.iswpunct 0x00b32ba0 358 | afr sym.iswspace 0x00b32b92 359 | afr sym.ldexp.00aeaff5 0x00aeaff5 360 | afr sym.ldexp 0x00aea593 361 | afr sym.localtime.00ae8cf6 0x00ae8cf6 362 | afr sym.localtime 0x00ae4300 363 | afr sym.longjmp.00b3360a 0x00b3360a 364 | afr sym.longjmp 0x00b31dbc 365 | afr sym.mbtowc 0x00aeb5d6 366 | afr sym.parse_cmdline 0x00ae5fec 367 | afr sym.pow.00ae93f0 0x00ae93f0 368 | afr sym.pow.00ae9450 0x00ae9450 369 | afr sym.pow 0x00ae4750 370 | af- fcn.00ae94ee;f- @ 0x00ae94ee;afr sym.pow.00ae94ee 0x00ae94ee 371 | afr sym.rand 0x00ae359f 372 | afr sym.setSBCS 0x00aebb75 373 | afr sym.shortsort 0x00ae4000 374 | afr sym.siglookup 0x00b36abd 375 | af sym.start 0x00b33258 376 | afr sym.test_whether_TOS_is_int 0x00ae49b2 377 | afr sym.time 0x00ae4480 378 | afr sym.tolower 0x00ae4ddc 379 | afr sym.ungetc 0x00aeb518 380 | afr sym.wctomb 0x00aec2db 381 | afr sym.write_char 0x00ae681f 382 | afr sym.write_multi_char 0x00ae6852 383 | afr sym.write_string 0x00ae6876 384 | afr sym.x_ismbbtype 0x00aebb04 385 | afr sym.xtoa 0x00b3577e 386 | 387 | af sym.strcat 0x00aeb8f0 388 | 389 | # af sym.j_allocmemory.00425d00 0x00425d00 390 | # af sym.j_allocmemory.00ab1fc0 0x00ab1fc0 391 | # af sym.j_allocmemory.00494240 0x00494240 392 | # 393 | # af sym._cisqrt.00ae46ad 0x00ae46ad 394 | # af sym.cintrinexit.00aed1ca 0x00aed1ca 395 | # af sym._fassign.00aeebeb 0x00aeebeb 396 | # af sym._fassign.00aeeba8 0x00aeeba8 397 | # af sym._fassign.00aeeb7c 0x00aeeb7c 398 | # af sym._fassign.00aef77f 0x00aef77f 399 | 400 | # af sym._cfltcvt_init 0x004340c0 401 | # af sym.j_allocmemory 0x0044dd60 402 | # af sym.dialogfunc 0x00ac6000 403 | # af sym._strnicmp 0x00ae30c9 404 | # af sym._cisqrt 0x00ae4690 405 | # af sym.sqrt 0x00ae46a4 406 | # af sym.__ascii_strnicmp 0x00ae4ec0 407 | # af sym._flush.00ae83cd 0x00ae83cd 408 | # af sym.localtime.00ae8cf6 0x00ae8cf6 409 | # af sym._rttosnpop 0x00ae92cc 410 | # af sym._starttwoargerrorhandling 0x00ae93f0 411 | # af sym._startoneargerrorhandling 0x00ae9407 412 | # af sym._twototos 0x00ae9450 413 | # af sym._load_cw 0x00ae9465 414 | # af sym._converttostoqnan 0x00ae947c 415 | # af sym._fload_withfb 0x00ae9495 416 | # af sym._checktos_withfb 0x00ae94d8 417 | # af sym._check_overflow_exit 0x00ae9525 418 | # af sym._check_range_exit 0x00ae9539 419 | # af sym._cipow_pentium4 0x00ae9670 420 | # af sym._pow_pentium4 0x00ae9689 421 | # af sym.zerotoxdone 0x00aea2a7 422 | # af sym.expbigret 0x00aea2f2 423 | # af sym._rtinfnpop 0x00aea301 424 | # af sym._ffexpm1 0x00aea31e 425 | # af sym.isinttos 0x00aea361 426 | # af sym.isinttosret 0x00aea386 427 | # af sym.noerror 0x00aea3c6 428 | # af sym._forcdecpt 0x00aecd6c 429 | # af sym._fassign 0x00aece29 430 | # af sym._cfltcvt 0x00aed0fe 431 | # af sym._ms_p5_test_fdiv 0x00aed161 432 | # af sym._fptrap 0x00aee2fe 433 | af sym._abnormal_termination 0x00aee552 434 | # af sym._fcloseall 0x00aee596 435 | # af sym.ceil 0x00b31bd0 436 | # af sym._ciacos 0x00b31cf0 437 | # af sym.acos 0x00b31d04 438 | # af sym.start_2 0x00b31d0d 439 | # af sym.floor 0x00b32600 440 | # af sym._ciasin 0x00b32750 441 | # af sym.asin 0x00b32764 442 | # af sym.start_3 0x00b3276d 443 | # af sym._eh_prolog 0x00b32b54 444 | # af sym.modf 0x00b32bb0 445 | # af sym.return 0x00b32c88 446 | # af sym.call_libm_error_0 0x00b32cc8 447 | # af sym.asin_0 0x00b32ed8 448 | # af sym.acos_0 0x00b32ee2 449 | # af sym.atan 0x00b32ee9 450 | # af sym.atan2 0x00b32ef0 451 | # af sym.exp 0x00b32f30 452 | # af sym._cicos 0x00b32fc0 453 | # af sym.cos 0x00b32fd4 454 | # af sym.start_4 0x00b32fdd 455 | # af sym.log 0x00b33070 456 | # af sym._cisin 0x00b333d0 457 | # af sym.sin 0x00b333e4 458 | # af sym.start_7 0x00b333ed 459 | # af sym.remove 0x00b3350a 460 | # af sym.j__remove 0x00b33534 461 | # af sym.rt_probe_read4 0x00b3360a 462 | # af sym.__init_time 0x00b33b43 463 | # af sym.__init_numeric 0x00b33c0f 464 | # af sym.__init_monetary 0x00b33dde 465 | # af sym.crtgetlocaleinfoa 0x00b342ea 466 | # af sym.localeenumproc 0x00b3441f 467 | # af sym._modf_default 0x00b35606 468 | # af sym._rmtmp 0x00b3585c 469 | # af sym._ffsinh 0x00b358a0 470 | # af sym.rtforcnhlarge 0x00b35935 471 | # af sym.ffexph 0x00b35948 472 | # af sym.exphypsum 0x00b35979 473 | # af sym.exphypsumreturn 0x00b3598a 474 | # af sym.exphypcopyinv 0x00b3598b 475 | # af sym._cintrindisp2 0x00b359a0 476 | # af sym._cintrindisp1 0x00b359de 477 | # af sym._ctrandisp2 0x00b35a14 478 | # af sym.ctranexit 0x00b35a4e 479 | # af sym.cintrinexit 0x00b35a55 480 | # af sym._ctrandisp1 0x00b35b9a 481 | # af sym._fload 0x00b35bc6 482 | # af sym._ciexp_pentium4 0x00b35c10 483 | # af sym.start_8 0x00b35c2e 484 | # af sym._cilog_pentium4 0x00b35ed0 485 | # af sym.start_9 0x00b35eee 486 | # af sym._cilog10_pentium4 0x00b36140 487 | # af sym.start_10 0x00b3615e 488 | # af sym._cxxunhandledexceptionfilter 0x00b36522 489 | af sym.validateread 0x00b36588 490 | # af sym.validatewrite 0x00b365a4 491 | # af sym.validateexecute 0x00b365c0 492 | # af sym._ctrandisp2.00ae9237 0x00ae9237 493 | # af sym.start_11 0x00aed2c8 494 | 495 | 496 | afr sym.jade_parse_int32 0x00427b50 497 | afvr edx input uint8_t ** @ 0x00427b50 498 | afvr esi output int32_t * @ 0x00427b50 499 | afvs 0x8 flags uint8_t @ 0x00427b50 500 | 501 | afr sym.jade_parse_int16 0x00427b90 502 | afvr edx input uint8_t ** @ 0x00427b90 503 | afvr esi output int16_t * @ 0x00427b90 504 | afvs 0x8 flags uint8_t @ 0x00427b90 505 | 506 | afr sym.jade_parse_float 0x00427bd0 507 | afvr ecx input uint8_t ** @ 0x00427bd0 508 | afvr edx output float * @ 0x00427bd0 509 | afvs 0x8 flags uint8_t @ 0x00427bd0 510 | 511 | afr sym.jade_parse_vec3f 0x00427cc0 512 | afvr ecx input uint8_t ** @ 0x00427cc0 513 | afvr esi output float * @ 0x00427cc0 514 | afvs 0x8 flags uint8_t @ 0x00427cc0 515 | 516 | afr sym.jade_parse_vec4f 0x00427df0 517 | afvr ecx input uint8_t ** @ 0x00427df0 518 | afvr esi output float * @ 0x00427df0 519 | afvs 0x8 flags uint8_t @ 0x00427df0 520 | 521 | afr sym.jade_parse_transform 0x00427d10 522 | afvr ecx input uint8_t ** @ 0x00427d10 523 | afvr edi output float * @ 0x00427d10 524 | afvs 0x8 flags uint8_t @ 0x00427d10 525 | 526 | afr sym.jade_parse_int8 0x00433da0 527 | afvr edx input uint8_t ** @ 0x00433da0 528 | afvr esi output int8_t * @ 0x00433da0 529 | afvs 0x8 flags uint8_t @ 0x00433da0 530 | 531 | afr sym.jade_malloc.00425d00 0x00425d00 532 | afr sym.jade_malloc.00494240 0x00494240 533 | afr sym.jade_malloc.00ab1fc0 0x00ab1fc0 534 | afr sym.jade_malloc 0x00425f30 535 | afvs 0x8 size size_t @ 0x00425f30 536 | 537 | afr sym.jade_malloc_tracked 0x00426320 538 | afvr eax size size_t @ 0x00426320 539 | 540 | afr sym.jade_wow_alloc 0x0045e3e0 541 | 542 | afr sym.jade_are_globals_not_0_and_2 0x00416ae0 543 | 544 | afr sym.jade_normalize_vec3f 0x00429550 545 | afr sym.jade_normalize_rotation 0x00429770 546 | afr sym.jade_make_identity_matrix 0x00409ab0 547 | afr sym.jade_validate_transform 0x00ac8ed0 548 | afr sym.jade_are_points_within_range 0x00425a00 549 | 550 | afr sym.jade_insert_in_global_double_linked_list 0x00ac8240 551 | afr sym.jade_create_wow_subnode 0x0047b1d0 552 | afr sym.jade_create_wow_node 0x0047b480 553 | afr sym.jade_push_parser 0x00421e00 554 | 555 | afr sym.jade_binary_search_from_global_list 0x004280e0 556 | afr sym.jade_binary_search_by_id 0x00427410 557 | 558 | afr sym.jade_read_at 0x004277a0 559 | afr sym.jade_read_at_expect 0x00427830 560 | afr sym.jade_read_at_chunk 0x004278d0 561 | 562 | afr sym.jade_read_at.00426060 0x00426060 563 | afr sym.jade_read_at.004263c0 0x004263c0 564 | afr sym.jade_read_at.00432ce0 0x00432ce0 565 | afr sym.jade_read_at.00432df0 0x00432df0 566 | 567 | afr sym.jade_read_at.00426d90 0x00426d90 568 | afr sym.jade_read_at.004265d0 0x004265d0 569 | afr sym.jade_read_at.00426690 0x00426690 570 | afr sym.jade_read_at.00429390 0x00429390 571 | afr sym.jade_read_at.00494200 0x00494200 572 | afr sym.jade_read_at.0042a540 0x0042a540 573 | 574 | afr sym.jade_read_at_chunk.00426570 0x00426570 575 | afr sym.jade_read_at_chunk.00426770 0x00426770 576 | afr sym.jade_read_at_chunk.00427a90 0x00427a90 577 | afr sym.jade_read_at_chunk.00426450 0x00426450 578 | 579 | afr sym.jade_report_error 0x00428100 580 | 581 | af sym.jade_report_error.00428440 0x00428440 582 | afr sym.jade_report_error.00422620 0x00422620 583 | afr sym.jade_report_error.00429dc0 0x00429dc0 584 | afr sym.jade_report_error.00495d40 0x00495d40 585 | afr sym.jade_report_error.00495490 0x00495490 586 | afr sym.jade_report_error.004288a0 0x004288a0 587 | afr sym.jade_report_error.00495b60 0x00495b60 588 | 589 | af sym.fsetpos 0x00ae3d71 590 | 591 | afr sym.jade_parse_wow 0x00466690 592 | 593 | afr sym.jade_parse_wow.0047d720 0x0047d720 594 | afr sym.jade_parse_wow.00422300 0x00422300 595 | afr sym.jade_parse_wow.0045e490 0x0045e490 596 | afr sym.jade_parse_wow.0045e280 0x0045e280 597 | afr sym.jade_parse_wow.00465580 0x00465580 598 | afr sym.jade_parse_wow.00427620 0x00427620 599 | 600 | afr sym.jade_parse_wow.0045e220 0x0045e220 601 | 602 | afr sym.jade_parse_wax_sxx 0x0041e190 603 | 604 | afr sym.jade_parse_wax_sxx.0041d900 0x0041d900 605 | afr sym.jade_parse_wax_sxx.0041d310 0x0041d310 606 | afr sym.jade_parse_wax_sxx.0041b090 0x0041b090 607 | afr sym.jade_parse_wax_sxx.00420270 0x00420270 608 | afr sym.jade_parse_wax_sxx.00419a20 0x00419a20 609 | afr sym.jade_parse_wax_sxx.00420730 0x00420730 610 | afr sym.jade_parse_wax_sxx.00420770 0x00420770 611 | afr sym.jade_parse_wax_sxx.00ae30c9 0x00ae30c9 612 | afr sym.jade_parse_wax_sxx.00414d90 0x00414d90 613 | afr sym.jade_parse_wax_sxx.00414d20 0x00414d20 614 | afr sym.jade_parse_wax_sxx.00416820 0x00416820 615 | afr sym.jade_parse_wax_sxx.0041af10 0x0041af10 616 | afr sym.jade_parse_wax_sxx.00427c20 0x00427c20 617 | afr sym.jade_parse_wax_sxx.00427830 0x00427830 618 | afr sym.jade_parse_wax_sxx.0041e8b0 0x0041e8b0 619 | afr sym.jade_parse_wax_sxx.0041d470 0x0041d470 620 | afr sym.jade_parse_wax_sxx.0041b040 0x0041b040 621 | afr sym.jade_parse_wax_sxx.0041b070 0x0041b070 622 | 623 | afr sym.jade_parse_wax_sxx.0041d730 0x0041d730 624 | afr sym.jade_parse_wax_sxx.0041afa0 0x0041afa0 625 | afr sym.jade_parse_wax_sxx.004166f0 0x004166f0 626 | afr sym.jade_parse_wax_sxx.004177b0 0x004177b0 627 | afr sym.jade_parse_wax_sxx.00417d60 0x00417d60 628 | afr sym.jade_parse_wax_sxx.00417c50 0x00417c50 629 | afr sym.jade_parse_wax_sxx.004275b0 0x004275b0 630 | 631 | afr sym.jade_parse_gao 0x0046ba50 632 | 633 | afr sym.jade_parse_gao.00469660 0x00469660 634 | afr sym.jade_parse_gao.00426540 0x00426540 635 | afr sym.jade_parse_gao.0047dac0 0x0047dac0 636 | afr sym.jade_parse_gao.00460b60 0x00460b60 637 | afr sym.jade_parse_gao.00475940 0x00475940 638 | afr sym.jade_parse_gao.00490660 0x00490660 639 | 640 | afr sym.jade_gao_create_object_0 0x00468730 641 | afr sym.jade_gao_create_object_1 0x00476900 642 | afr sym.jade_gao_create_translation 0x00490d00 643 | afr sym.jade_gao_fill_structure_0 0x0047db20 644 | 645 | afr sym.jade_parse_ova_ofc 0x004a61f0 646 | 647 | afr sym.jade_parse_snk 0x0041e570 648 | afr sym.jade_parse_snk.0041e610 0x0041e610 649 | 650 | afr sym.jade_open_data 0x00421cf0 651 | afr sym.jade_close_data 0x00421d90 652 | 653 | afr sym.jade_open_data.00428c50 0x00428c50 654 | afr sym.jade_open_data.00428f30 0x00428f30 655 | 656 | afr sym.jade_open_data.004276a0 0x004276a0 657 | afr sym.jade_open_data.00ae4070 0x00ae4070 658 | afr sym.jade_open_data.00428da0 0x00428da0 659 | afr sym.jade_open_data.004274b0 0x004274b0 660 | 661 | afr sym.jade_get_wow_element_id 0x00422420 662 | 663 | f var.__global_wait_handle 4 0xb7ad3c 664 | f var.__global_constant_128 1 0xb6453c 665 | f var.__global_allocated_size_2 4 0xb8a124 666 | f var.__global_allocated_size 4 0xb8a128 667 | f var.__global_double_linked_list.head 4 0xd4af80 668 | f var.__global_double_linked_list.tail 4 0xd4af84 669 | f var.__global_double_linked_list.size 4 0xd4af88 670 | f var.__global_double_linked_list 12 0xd4af80 671 | f var.__global_list 8 0xb8cdd4 672 | f var.__global_list_ptr 4 0xb89fc4 673 | f var.__invalid_rotation_1 12 0xb7ad40 674 | f var.__invalid_rotation_2 12 0xb7ad50 675 | f var.__invalid_rotation_3 12 0xb7ad60 676 | f var.__invalid_translate1_0 4 0xbab960 677 | f var.__invalid_translate1_1 4 0xbab964 678 | f var.__invalid_translate1_2 4 0xbab968 679 | f var.__invalid_translate1 12 0xbab960 680 | f var.__invalid_translate2 12 0xbb09a0 681 | f var.___should_not_be_0 4 0xb8a150 682 | f var.___should_be_2 4 0xb89fc8 683 | f var.__wow_list_last 4 0xb8a144 684 | f var.__global_wow001 4 0xb8a148 685 | f var.__wow_list_count 4 0xb8a14c 686 | f var.__wow_list 0x1388 0xb8de00 687 | f var.__global_wow020 4 0xb6454c 688 | f var.__global_wow030 4 0xd13274 689 | f var.__global_gao000 4 0xb8a0fc 690 | f var.__global_gao001 4 0xb8a118 691 | f var.__global_gao002 4 0xb8a118 692 | f var.__global_gao003 4 0xd14940 693 | f var.__global_wax000 4 0xb79e00 694 | f var.__global_wax001 4 0xb8c450 695 | f var.__global_ofc000 4 0xb8a120 696 | f var.__global_snk000 4 0xb8cdd0 697 | f var.__global_epsilon 4 0xb4ffc4 698 | f var.__global_one 4 0xb4ffd8 699 | 700 | af- 0x007ffe00;f- @ 0x007ffe00 701 | f~fcn 702 | -------------------------------------------------------------------------------- /beyond-good-and-evil/bin-riff.bt: -------------------------------------------------------------------------------- 1 | // Beyond Good and Evil 2 | 3 | #include 4 | 5 | LittleEndian(); 6 | 7 | typedef struct { 8 | uint32 id ; 9 | Magic type(4, "RIFF"); 10 | byte data[42]; 11 | uint32 id ; 12 | } RiffEntry ; 13 | string ReadRiffEntry(RiffEntry& entry) { string out; SPrintf(out, "%08Xh", entry.id); return out; } 14 | 15 | local uint32 i; 16 | 17 | uint32 size ; 18 | for (i = 0; i < size; i += 54) 19 | RiffEntry riff; 20 | -------------------------------------------------------------------------------- /beyond-good-and-evil/bin-riff2.bt: -------------------------------------------------------------------------------- 1 | // Beyond Good and Evil 2 | 3 | #include 4 | 5 | LittleEndian(); 6 | 7 | typedef struct { 8 | uint32 id ; 9 | uint32 unknown ; 10 | } Riff2Entry ; 11 | string ReadRiff2Entry(Riff2Entry& entry) { string out; SPrintf(out, "%08Xh", entry.id); return out; } 12 | 13 | typedef struct { 14 | Magic type(4, "RIFF"); 15 | uint32 tsize; 16 | Magic type(4, "WAVE"); 17 | Magic type(4, "fmt "); 18 | uint32 fsize; 19 | byte data[fsize]; 20 | Magic type(4, "data"); 21 | uint32 dsize; 22 | } RiffEntry ; 23 | 24 | local uint32 i; 25 | 26 | uint32 size ; 27 | for (i = 0; i < size; i += 1) 28 | Riff2Entry riff2; 29 | for (i = 0; i < size; i += 1) 30 | RiffEntry riff; 31 | for (i = 0; i < size; i += 1) 32 | struct { byte data[riff[i].dsize]; } data; -------------------------------------------------------------------------------- /beyond-good-and-evil/bin-txg.bt: -------------------------------------------------------------------------------- 1 | // Beyond Good and Evil 2 | 3 | #include 4 | 5 | LittleEndian(); 6 | 7 | typedef struct (string magic) { 8 | uint32 id; 9 | Magic type(4, magic); 10 | } TxXEntry ; 11 | string ReadTxXEntry(TxXEntry& entry) { string out; SPrintf(out, "%08Xh%s", entry.id, entry.type.data); return out; } 12 | 13 | struct TxgList { 14 | uint32 size ; 15 | 16 | local uint32 i; 17 | for (i = 0; i < size; i += 8) 18 | TxXEntry txg(".txg"); 19 | }; 20 | 21 | struct TxgHeader { 22 | uint32 size ; Assert(size == 160); 23 | 24 | local uint32 i; 25 | for (i = 0; i < size; i += 16) { 26 | TxXEntry txi(".txi"); 27 | TxXEntry txs(".txs"); 28 | } 29 | 30 | uint32 u000 ; 31 | }; 32 | 33 | struct TxgOffsetChunk { 34 | uint32 size ; 35 | 36 | local uint32 i; 37 | for (i = 0; i < size; i += 4) 38 | uint32 data ; 39 | }; 40 | 41 | struct TxgStringChunk(uint32 count) { 42 | uint32 size ; 43 | for (count; count > 0; --count) 44 | String data; 45 | }; 46 | 47 | struct TxgData { 48 | TxgOffsetChunk offsets; 49 | TxgStringChunk strings(offsets.size / 4); 50 | }; 51 | 52 | local uint32 j; 53 | while (!FEof()) { 54 | TxgList list; 55 | for (j = 0; j < list.size; j += 8) 56 | TxgHeader txg; 57 | for (j = 0; j < list.size; j += 8) 58 | TxgData data; 59 | } -------------------------------------------------------------------------------- /beyond-good-and-evil/bin-wow.bt: -------------------------------------------------------------------------------- 1 | // Beyond Good and Evil 2 | 3 | #include 4 | 5 | LittleEndian(); 6 | 7 | typedef struct (string magic) { 8 | ResId id; 9 | Magic type(4, magic); 10 | } WowEntry ; 11 | string ReadWowEntry(WowEntry& entry) { string out; SPrintf(out, "%08Xh%s", entry.id.data, entry.type.data); return out; } 12 | 13 | struct WowList { 14 | uint32 size ; 15 | 16 | local uint32 i; 17 | for (i = 0; i < size; i += 8) 18 | WowEntry wow(".wow"); 19 | }; 20 | 21 | struct GaoList { 22 | uint32 size ; 23 | 24 | local uint32 i; 25 | for (i = 0; i < size; i += 4) 26 | ResId id; 27 | }; 28 | 29 | typedef struct { 30 | uint32 count; 31 | uint32 u000[count]; 32 | float u001[count*3]; 33 | } GaoHeaderChunk ; 34 | 35 | struct GaoHeader { 36 | uint32 size ; 37 | Magic type(4, ".gao"); 38 | 39 | local uint64 begin = FTell(); 40 | 41 | uint16 unknown ; 42 | Assert(unknown == 0x00 || 43 | unknown == 0x08 || 44 | unknown == 0x09 || 45 | unknown == 0x00 || 46 | unknown == 0x40 || 47 | unknown == 0x48); 48 | uint16 unknown ; 49 | Assert(unknown == 0x00 || 50 | unknown == 0x00 || 51 | unknown == 0x00 || 52 | unknown == 0x00 || 53 | unknown == 0x01 || 54 | unknown == 0x01 || 55 | unknown == 0x10); 56 | 57 | uint32 unknown ; 58 | uint16 unknown ; 59 | uint16 unknown ; 60 | uint16 unknown ; 61 | uint16 unknown ; 62 | uint16 unknown ; 63 | Matrix unknown(4, 4); 64 | 65 | uint32 unknown ; 66 | Assert(unknown == 0x0 || 67 | unknown == 0x2 || 68 | unknown == 0x4 || 69 | unknown == 0x6 || 70 | unknown == 0xa || 71 | unknown == 0xe); 72 | 73 | struct { 74 | switch (unknown[2]) { 75 | default: byte unknown[size-90] ; 76 | case 0x2080: 77 | Matrix unknown(3, 2); 78 | ResId unknown; 79 | uint32 unknown; 80 | ResId unknown; 81 | uint32 unknown; 82 | uint16 unknown; 83 | uint32 unknown; 84 | break; 85 | case 0x20a0: 86 | Matrix unknown(3, 2); 87 | ResId unknown; 88 | Fixed32 unknown(0); 89 | ResId unknown; 90 | Fixed32 unknown(0); 91 | uint16 unknown; 92 | Fixed32 unknown(127); 93 | ResId unknown; 94 | break; 95 | case 0x5080: 96 | Matrix unknown(3, 2); 97 | ResId unknown; 98 | ResId unknown; 99 | uint32 unknown; 100 | uint32 unknown; 101 | UInt32Array unknown; 102 | break; 103 | case 0x70a0: 104 | Matrix unknown(3, 2); 105 | ResId unknown; 106 | ResId unknown; 107 | uint32 unknown; 108 | uint32 unknown; 109 | UInt32Array unknown; 110 | ResId unknown; 111 | uint16 unknown; 112 | uint32 unknown; 113 | uint32 unknown; 114 | uint32 unknown; 115 | uint32 unknown; 116 | float unknown; 117 | uint32 unknown; 118 | uint32 unknown; 119 | uint32 unknown; 120 | uint32 unknown; 121 | uint32 unknown; 122 | uint32 unknown; 123 | Matrix unknown(3, 2); 124 | uint32 unknown; 125 | uint32 unknown; 126 | uint32 unknown; 127 | uint32 unknown; 128 | uint32 unknown; 129 | uint32 unknown; 130 | uint32 unknown; 131 | 132 | Matrix unknown(3, 2); 133 | ResId unknown; 134 | Matrix unknown(3, 2); 135 | ResId unknown; 136 | uint32 unknown; 137 | uint32 unknown; 138 | ResId unknown; 139 | break; 140 | case 0x15000: 141 | Matrix unknown(3, 2); 142 | ResId unknown; 143 | ResId unknown; 144 | uint32 unknown; 145 | uint32 unknown; 146 | UInt32Array unknown; 147 | break; 148 | case 0x403010: 149 | Matrix unknown(3, 2); 150 | ResId unknown; 151 | Matrix unknown(4, 4); 152 | ResId unknown; 153 | ResId unknown; 154 | uint32 unknown; 155 | uint32 unknown; 156 | uint16 unknown; 157 | uint32 unknown; 158 | uint32 unknown; 159 | ResId unknown; 160 | break; 161 | case 0x405000: 162 | case 0x415000: 163 | Matrix unknown(3, 2); 164 | ResId unknown; 165 | ResId unknown; 166 | uint32 unknown; 167 | uint32 unknown; 168 | UInt32Array unknown; 169 | ResId unknown; 170 | Matrix unknown(4, 4); 171 | uint32 unknown; 172 | break; 173 | case 0x485000: 174 | Matrix unknown(3, 4); 175 | ResId unknown; 176 | ResId unknown; 177 | uint32 unknown; 178 | uint32 unknown; 179 | UInt32Array unknown; 180 | ResId unknown; 181 | Matrix unknown(4, 4); 182 | uint32 unknown; 183 | break; 184 | case 0x95000: 185 | Matrix unknown(3, 4); 186 | ResId unknown; 187 | ResId unknown; 188 | uint32 unknown; 189 | uint32 unknown; 190 | UInt32Array unknown; 191 | break; 192 | case 0x97000: 193 | case 0x97020: 194 | Matrix unknown(3, 4); 195 | ResId unknown; 196 | ResId unknown; 197 | uint32 unknown; 198 | uint32 unknown; 199 | UInt32Array unknown; 200 | ResId unknown; 201 | uint16 unknown; 202 | uint32 unknown; 203 | uint32 unknown; 204 | uint32 unknown; 205 | uint32 unknown; 206 | uint32 unknown; 207 | uint32 unknown; 208 | uint32 unknown; 209 | uint32 unknown; 210 | uint32 unknown; 211 | uint32 unknown; 212 | uint32 unknown; 213 | GaoHeaderChunk unknown[unknown[17]] ; 214 | uint32 u006; 215 | float u006; 216 | float u006; 217 | uint32 u006; 218 | uint32 u006; 219 | uint32 u006; 220 | uint32 u006; 221 | uint32 u006; 222 | uint32 u006; 223 | uint32 u006; 224 | float u006; 225 | float u006; 226 | uint32 u006; 227 | uint32 u006; 228 | float u006; 229 | float u006; 230 | uint32 u006; 231 | uint32 u006; 232 | float u006; 233 | float u006; 234 | uint32 u006; 235 | uint32 u006; 236 | float u006; 237 | float u006; 238 | uint32 u006; 239 | uint32 u006; 240 | float u006; 241 | float u006; 242 | uint32 u006; 243 | uint32 u006; 244 | float u006; 245 | float u006; 246 | uint32 u006; 247 | uint32 u006; 248 | float u006; 249 | float u006; 250 | uint32 u006; 251 | uint32 u006; 252 | float u006; 253 | float u006; 254 | uint32 u006; 255 | uint32 u006; 256 | float u006; 257 | float u006; 258 | uint32 u006; 259 | uint32 u006; 260 | float u006; 261 | float u006; 262 | uint32 u006; 263 | uint32 u006; 264 | float u006; 265 | float u006; 266 | uint32 u006; 267 | uint32 u006; 268 | uint32 u006; 269 | uint32 u006; 270 | float u006; 271 | float u006; 272 | uint32 u006; 273 | uint32 u006; 274 | float u006; 275 | float u006; 276 | uint32 u006; 277 | uint32 u006; 278 | float u006; 279 | float u006; 280 | uint32 u006; 281 | ResId u007; 282 | break; 283 | } 284 | } custom; 285 | 286 | // SizedString name; 287 | 288 | FSeek(begin + size - 4); 289 | }; 290 | 291 | struct WowHeader { 292 | uint32 size ; Assert(size == 180); 293 | Magic type(4, ".wow"); 294 | 295 | Fixed32 unknown(3); 296 | uint32 unknown; 297 | Assert(unknown == 0 || 298 | unknown == 1); 299 | uint32 unknown; 300 | 301 | PaddedString name(60); 302 | 303 | Matrix unknown(4, 4); 304 | Fixed32 unknown(6); 305 | float unknown ; 306 | uint32 unknown ; 307 | uint32 unknown ; 308 | uint32 unknown ; 309 | 310 | ResId unknown; 311 | ResId unknown; 312 | ResId unknown; 313 | 314 | ResId unknown; 315 | ResId unknown; 316 | if (unknown[12].data != 0) 317 | GaoList list0; 318 | GaoList list; 319 | if (unknown[12].data != 0) 320 | GaoHeader gao0[list0.size / 4] ; 321 | GaoHeader gao[list.size / 4] ; 322 | }; 323 | 324 | struct SizesChunk { 325 | uint32 size; 326 | uint32 sizes[size / 4]; 327 | }; 328 | 329 | local uint32 j; 330 | while (!FEof()) { 331 | WowList list; 332 | for (j = 0; j < list.size; j += 8) { 333 | WowHeader wow; 334 | SizesChunk unknown; 335 | SizesChunk unknown[4] ; 336 | } 337 | } -------------------------------------------------------------------------------- /beyond-good-and-evil/bootstrap: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ./extract ~/Games/GoG/Beyond\ Good\ and\ Evil/sally_clean.bf 4 | find ROOT/Bin -iname *.bin -print0|xargs -0 -t -I{} ./decomp {} {}.dec 5 | 6 | find ROOT/Bin/ -iname *.bin | xargs -I{} bash -c '(tail -c+9 {}|head -c4|grep RIFF)' 7 | find ROOT/Bin/ -iname *.bin | xargs -I{} bash -c '(tail -c+9 {}|head -c4|grep txg) && mv {} TXG/{}' 8 | find ROOT/Bin/ -iname *.bin | xargs -I{} bash -c '(tail -c+9 {}|head -c4|grep wow) && mv {} WOW/{}' 9 | 10 | find ROOT/Bin/ -iname *.bin | xargs -I{} bash -c '(tail -c+13 {}|head -c4|grep txg) && mv {} TXG2/{}' 11 | find ROOT/Bin/ -iname *.bin | xargs -I{} bash -c '(tail -c+13 {}|head -c4|grep RIFF) && mv {} RIFF2/{}' 12 | 13 | find ROOT/Bin/ -iname *.bin | xargs -I{} bash -c '(head -c4 {}|hd|grep "2c 00") && mv {} 2C00/{}' 14 | find ROOT/Bin/ -iname *.bin | xargs -I{} bash -c '(head -c4 {}|hd|grep "58 00") && mv {} 5800/{}' 15 | -------------------------------------------------------------------------------- /beyond-good-and-evil/decomp.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | struct decompress_args { 10 | uint8_t* cbuffer; 11 | uint8_t* dbuffer; 12 | size_t dsize; 13 | }; 14 | 15 | bool is_compressed = true; 16 | size_t dblock_size = 0x7d000; 17 | 18 | int decompress_block(size_t csize, 19 | uint8_t* cbuffer, 20 | uint8_t* dbuffer, 21 | size_t* bsize); 22 | 23 | uint8_t* decompress(decompress_args& args, size_t bcount) { 24 | std::printf("decompress: bcount: %d\n", bcount); 25 | 26 | if (is_compressed) { 27 | args.dsize = 0; 28 | uint8_t* dbuf = args.dbuffer; 29 | uint8_t* cbuf = args.cbuffer; 30 | size_t block = 0; 31 | 32 | while (block < bcount) { 33 | size_t dsize 34 | = (cbuf[3] << 24) | (cbuf[2] << 16) | (cbuf[1] << 8) | (cbuf[0] << 0); 35 | cbuf += 4; 36 | if (dsize == 0) break; 37 | 38 | size_t csize 39 | = (cbuf[3] << 24) | (cbuf[2] << 16) | (cbuf[1] << 8) | (cbuf[0] << 0); 40 | cbuf += 4; 41 | 42 | if (csize < dsize) { 43 | std::printf("decompress: csize: %x, dsize: %x\n", csize, dsize); 44 | size_t bsize = dsize; 45 | lzo1x_decompress_safe(cbuf, csize, dbuf, &dsize, NULL); 46 | // decompress_block(csize, cbuf, dbuf, &bsize); 47 | std::printf("decompress: bsize: %x\n", bsize); 48 | // assert(bsize == dsize); 49 | } else { 50 | std::memcpy(dbuf, cbuf, csize); 51 | } 52 | 53 | cbuf += csize; 54 | dbuf += dsize; 55 | args.dsize += dsize; 56 | block++; 57 | } 58 | 59 | return cbuf; 60 | } else { 61 | std::memcpy(args.dbuffer, args.cbuffer, dblock_size * bcount); 62 | args.dsize = dblock_size * bcount; 63 | return args.cbuffer + args.dsize; 64 | } 65 | } 66 | #define log(message) \ 67 | std::printf(message \ 68 | ", count: %x, dbuf: %x, cbuf: %x, cend: %x, sref: %x, lref: " \ 69 | "%x, %s:%d\n", \ 70 | count, \ 71 | dbuf - dbuffer, \ 72 | cbuf - cbuffer, \ 73 | cend - cbuffer, \ 74 | sref - dbuffer, \ 75 | lref - dbuffer, \ 76 | __FILE__, \ 77 | __LINE__) 78 | int decompress_block(size_t csize, 79 | uint8_t* cbuffer, 80 | uint8_t* dbuffer, 81 | size_t* bsize) { 82 | #define copy(dst, src, count) \ 83 | do { \ 84 | assert(count > 0); \ 85 | std::memcpy(dst, src, count); \ 86 | dst += count; \ 87 | src += count; \ 88 | count = 0; \ 89 | } while (0) 90 | 91 | #define copy4(dst, src, count) \ 92 | do { \ 93 | assert((count & ~3) > 0); \ 94 | std::memcpy(dst, src, count & ~3); \ 95 | dst += count & ~3; \ 96 | src += count & ~3; \ 97 | count &= 3; \ 98 | } while (0) 99 | 100 | #define copyn(dst, src, count, n, m) \ 101 | do { \ 102 | assert(count > 0); \ 103 | std::memcpy(dst, src, n); \ 104 | dst += n; \ 105 | src += n; \ 106 | count -= m; \ 107 | } while (0) 108 | 109 | #define countz(cbuf, count, value) \ 110 | do { \ 111 | count &= value; \ 112 | if (count == 0) { \ 113 | while (cbuf[0] == 0) { \ 114 | count += 0xff; \ 115 | cbuf++; \ 116 | } \ 117 | count += cbuf[0] + value; \ 118 | cbuf++; \ 119 | } \ 120 | } while (0) 121 | 122 | uint8_t* cbuf = cbuffer; 123 | uint8_t* cend = cbuf + csize; 124 | uint8_t* dbuf = dbuffer; 125 | uint8_t* sref = dbuffer; 126 | uint8_t* lref = dbuffer; 127 | *bsize = 0; 128 | 129 | int count = cbuf[0]; 130 | if (count <= 0x11) goto l42a57b; 131 | count -= 0x11; 132 | cbuf++; 133 | if (count < 4) goto l42a630; 134 | copy(dbuf, cbuf, count); 135 | goto l42a5ea; 136 | 137 | l42a57b: 138 | count = cbuf[0]; 139 | cbuf++; 140 | if (count >= 0x10) goto l42a63d; 141 | countz(cbuf, count, 0xf); 142 | copyn(dbuf, cbuf, count, 4, 1); 143 | if (count == 0) goto l42a5ea; 144 | if (count < 4) goto l42a5e1; 145 | copy4(dbuf, cbuf, count); 146 | if (count <= 0) goto l42a5ea; 147 | copy(dbuf, cbuf, count); 148 | goto l42a5ea; 149 | l42a5e1: 150 | copy(dbuf, cbuf, count); 151 | 152 | l42a5ea: 153 | count = cbuf[0]; 154 | cbuf++; 155 | if (count >= 0x10) goto l42a63d; 156 | sref = dbuf - count / 4 - cbuf[0] * 4 - 0x801; 157 | cbuf++; 158 | dbuf[0] = sref[0]; 159 | dbuf++; 160 | sref++; 161 | 162 | l42a613: 163 | dbuf[0] = sref[0]; 164 | dbuf[1] = sref[1]; 165 | dbuf++; 166 | dbuf++; 167 | 168 | l42a61e: 169 | count = cbuf[-2] & 3; 170 | if (count == 0) goto l42a57b; 171 | 172 | l42a630: 173 | copy(dbuf, cbuf, count); 174 | count = cbuf[0]; 175 | cbuf++; 176 | 177 | l42a63d: 178 | if (count < 0x40) goto l42a67b; 179 | lref = dbuf - ((count / 4) & 7) - (cbuf[0] * 8) - 1; 180 | count /= 32; 181 | cbuf++; 182 | count--; 183 | 184 | l42a65c: 185 | dbuf[0] = lref[0]; 186 | dbuf[1] = lref[1]; 187 | dbuf++; 188 | lref++; 189 | dbuf++; 190 | lref++; 191 | copy(dbuf, lref, count); 192 | goto l42a61e; 193 | 194 | l42a67b: 195 | if (count < 0x20) goto l42a6b6; 196 | countz(cbuf, count, 0x1f); 197 | lref = dbuf; 198 | lref -= ((cbuf[0] << 0) | (cbuf[1] << 8)) / 4; 199 | cbuf += 2; 200 | lref--; 201 | goto l42a700; 202 | 203 | l42a6b6: 204 | if (count < 0x10) goto l42a74e; 205 | lref = dbuf - (count & 8) * 2048; 206 | countz(cbuf, count, 7); 207 | lref -= ((cbuf[0] << 0) | (cbuf[1] << 8)) / 4; 208 | cbuf += 2; 209 | if (lref - dbuf == 0) { 210 | *bsize = dbuf - dbuffer; 211 | if (cbuf - cend != 0) 212 | return -4; 213 | else 214 | return 0; 215 | } 216 | lref -= 0x4000; 217 | 218 | l42a700: 219 | if (count < 6) goto l42a65c; 220 | if (dbuf - lref < 4) goto l42a65c; 221 | copyn(dbuf, lref, count, 4, 2); 222 | copy4(dbuf, lref, count); 223 | if (count <= 0) goto l42a61e; 224 | copy(dbuf, lref, count); 225 | goto l42a61e; 226 | 227 | l42a74e: 228 | sref = dbuf - count / 4 - cbuf[0] * 4 - 1; 229 | cbuf++; 230 | goto l42a613; 231 | } 232 | 233 | int main(int argc, char const* argv[]) { 234 | if (0) { 235 | uint8_t cbuffer[] = { 236 | 0xEA, 0x01, 0x00, 0x00, 0xF3, 0x00, 0x00, 0x00, 0x0D, 0x08, 0x00, 0x00, 237 | 0x00, 0x1D, 0x63, 0x00, 0x5E, 0x2E, 0x77, 0x6F, 0x77, 0xB4, 0x00, 0x00, 238 | 0x00, 0x7E, 0x00, 0x03, 0x00, 0xC0, 0x00, 0x00, 0x02, 0xFF, 0xFF, 0x00, 239 | 0x5F, 0x6D, 0x61, 0x69, 0x6E, 0x5F, 0x6E, 0x65, 0x77, 0x67, 0x61, 0x6D, 240 | 0x65, 0x00, 0x77, 0x6F, 0x77, 0xC8, 0x03, 0x20, 0x05, 0x1A, 0x00, 0x80, 241 | 0x3F, 0x30, 0x9C, 0x00, 0x20, 0x09, 0x4D, 0x00, 0x06, 0x90, 0x07, 0xDE, 242 | 0x05, 0xFC, 0xFC, 0x95, 0x01, 0xFF, 0xC0, 0x00, 0x01, 0x1C, 0x63, 0x00, 243 | 0x5E, 0x60, 0x02, 0x06, 0xE2, 0x02, 0x05, 0x12, 0x04, 0x00, 0x00, 0x00, 244 | 0x29, 0x4D, 0x18, 0x9E, 0x7F, 0x17, 0x67, 0x61, 0x6F, 0x7C, 0x02, 0x02, 245 | 0xA0, 0x20, 0x00, 0x00, 0x23, 0x62, 0x01, 0x10, 0x83, 0x75, 0x00, 0x00, 246 | 0xD4, 0x08, 0x8C, 0x01, 0xF0, 0x00, 0x38, 0x4C, 0x00, 0x01, 0xBB, 0xD6, 247 | 0x99, 0xBE, 0x4C, 0x00, 0x07, 0x3E, 0x00, 0x00, 0xA0, 0x40, 0x00, 0x00, 248 | 0x80, 0x3F, 0x02, 0x8A, 0x06, 0x80, 0xBF, 0x4C, 0x01, 0xEC, 0x00, 0x44, 249 | 0x1B, 0x7E, 0x07, 0x80, 0x3F, 0x60, 0x12, 0x78, 0x03, 0xFF, 0x00, 0x00, 250 | 0x00, 0x7F, 0x5D, 0x11, 0x31, 0x5C, 0x11, 0x06, 0x0E, 0x00, 0x00, 0x00, 251 | 0x57, 0x50, 0x5F, 0x61, 0x69, 0x6D, 0x27, 0x2E, 0x61, 0x13, 0x08, 0x45, 252 | 0x02, 0x2F, 0x45, 0x17, 0x30, 0x4D, 0x00, 0x10, 0x74, 0x15, 0x54, 0x04, 253 | 0x02, 0x2E, 0x6F, 0x76, 0x61, 0x2D, 0x9F, 0x00, 0x66, 0x63, 0x20, 0x60, 254 | 0x09, 0x3D, 0x0D, 0x00, 0x24, 0x2D, 0x7C, 0x00, 0x6C, 0x07, 0x2D, 0x48, 255 | 0x00, 0x98, 0x01, 0x0D, 0x0C, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 256 | 0xB0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 257 | }; 258 | 259 | uint8_t dbuffer[] = { 260 | 0x08, 0x00, 0x00, 0x00, 0x1D, 0x63, 0x00, 0x5E, 0x2E, 0x77, 0x6F, 0x77, 261 | 0xB4, 0x00, 0x00, 0x00, 0x2E, 0x77, 0x6F, 0x77, 0x03, 0x00, 0x00, 0x00, 262 | 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x5F, 0x6D, 0x61, 0x69, 263 | 0x6E, 0x5F, 0x6E, 0x65, 0x77, 0x67, 0x61, 0x6D, 0x65, 0x00, 0x77, 0x6F, 264 | 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 265 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 266 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 267 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3F, 268 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 269 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3F, 0x00, 0x00, 0x00, 0x00, 270 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 271 | 0x00, 0x00, 0x80, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 272 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3F, 273 | 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3F, 0x00, 0x00, 0x00, 0x00, 274 | 0x00, 0xFC, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 275 | 0x00, 0x00, 0x00, 0x00, 0x1C, 0x63, 0x00, 0x5E, 0x00, 0x00, 0x00, 0x00, 276 | 0xE2, 0x02, 0x05, 0x12, 0x04, 0x00, 0x00, 0x00, 0x29, 0x63, 0x00, 0x5E, 277 | 0x9E, 0x00, 0x00, 0x00, 0x2E, 0x67, 0x61, 0x6F, 0x00, 0x00, 0x00, 0x00, 278 | 0xA0, 0x20, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x10, 0x83, 0x00, 279 | 0x00, 0x00, 0x00, 0x00, 0x80, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 280 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 281 | 0x80, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 282 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3F, 0x00, 0x00, 283 | 0x00, 0x00, 0xBB, 0xD6, 0x99, 0xBE, 0xBB, 0xD6, 0x99, 0x3E, 0x00, 0x00, 284 | 0xA0, 0x40, 0x00, 0x00, 0x80, 0x3F, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 285 | 0x80, 0xBF, 0x00, 0x00, 0x80, 0xBF, 0x00, 0x00, 0x80, 0xBF, 0x00, 0x00, 286 | 0x00, 0x3F, 0x00, 0x00, 0x80, 0x3F, 0x00, 0x00, 0x80, 0x3F, 0xFF, 0xFF, 287 | 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 288 | 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x31, 0x63, 0x00, 0x5E, 289 | 0x0E, 0x00, 0x00, 0x00, 0x57, 0x50, 0x5F, 0x61, 0x69, 0x67, 0x61, 0x6D, 290 | 0x65, 0x2E, 0x67, 0x61, 0x6F, 0x00, 0x08, 0x00, 0x00, 0x00, 0x2F, 0x63, 291 | 0x00, 0x5E, 0x30, 0x63, 0x00, 0x5E, 0x10, 0x00, 0x00, 0x00, 0x2E, 0x63, 292 | 0x00, 0x5E, 0x2E, 0x6F, 0x76, 0x61, 0x2D, 0x63, 0x00, 0x5E, 0x2E, 0x6F, 293 | 0x66, 0x63, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 294 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 295 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 296 | 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 297 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2D, 0x63, 0x00, 0x5E, 0x00, 0x00, 298 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 299 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x04, 0x00, 300 | 0x00, 0x00, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 301 | }; 302 | 303 | size_t dsize = (cbuffer[0] << 0) | (cbuffer[1] << 8) | (cbuffer[2] << 16) 304 | | (cbuffer[3] << 24); 305 | size_t csize = (cbuffer[4] << 0) | (cbuffer[5] << 8) | (cbuffer[6] << 16) 306 | | (cbuffer[7] << 24); 307 | 308 | decompress_args args; 309 | args.dbuffer = new uint8_t[dsize]; 310 | std::memset(args.dbuffer, 0, dsize); 311 | 312 | args.cbuffer = new uint8_t[csize + 8]; 313 | std::memcpy(args.cbuffer, cbuffer, csize + 8); 314 | 315 | args.dsize = 0; 316 | decompress(args, 1); 317 | assert(std::memcmp(args.dbuffer, dbuffer, dsize) == 0); 318 | 319 | delete[] args.cbuffer; 320 | delete[] args.dbuffer; 321 | } 322 | 323 | { 324 | decompress_args args; 325 | 326 | FILE* out = nullptr; 327 | auto in = std::fopen(argv[1], "rb"); 328 | std::fseek(in, 0, SEEK_END); 329 | size_t fsize = std::ftell(in); 330 | std::fseek(in, 0, SEEK_SET); 331 | 332 | do { 333 | uint8_t cbuffer[8] = {}; 334 | std::fread(cbuffer, 1, 8, in); 335 | 336 | size_t dsize = (cbuffer[0] << 0) | (cbuffer[1] << 8) | (cbuffer[2] << 16) 337 | | (cbuffer[3] << 24); 338 | size_t csize = (cbuffer[4] << 0) | (cbuffer[5] << 8) | (cbuffer[6] << 16) 339 | | (cbuffer[7] << 24); 340 | if (csize == 0 || csize > fsize) break; 341 | 342 | args.cbuffer = new uint8_t[csize + 8]; 343 | std::memcpy(args.cbuffer, cbuffer, 8); 344 | std::fread(args.cbuffer + 8, 1, csize, in); 345 | 346 | args.dbuffer = new uint8_t[dsize]; 347 | std::memset(args.dbuffer, 0, dsize); 348 | 349 | args.dsize = 0; 350 | decompress(args, 1); 351 | 352 | if (!out) out = std::fopen(argv[2], "wb"); 353 | std::fwrite(args.dbuffer, 1, dsize, out); 354 | 355 | delete[] args.cbuffer; 356 | delete[] args.dbuffer; 357 | } while (true); 358 | 359 | if (out) std::fclose(out); 360 | } 361 | 362 | return 0; 363 | } 364 | -------------------------------------------------------------------------------- /beyond-good-and-evil/extract-wow.1sc: -------------------------------------------------------------------------------- 1 | // Beyond Good and Evil 2 | 3 | LittleEndian(); 4 | 5 | local uint32 j; 6 | local uint32 n; 7 | local uint32 size; 8 | local uint32 id; 9 | local string type; 10 | local string name; 11 | local string filename; 12 | 13 | local int64 begin = -1; 14 | local TFindResults results; 15 | 16 | while (FTell() < FileSize() - 8) { 17 | size = ReadUInt(FTell()); 18 | for (j = 0; j < size; j += 8) { 19 | id = ReadUInt(FTell() + j + 4); 20 | type = ReadString(FTell() + j + 8, 4); 21 | Printf("%x%s\n", id, type); 22 | } 23 | FSeek(FTell() + size + 4); 24 | 25 | for (j = 0; j < size; j += 8) { 26 | results = FindAll(".wow", true, false, 0, 0.0, 1, FTell()); 27 | if (results.count == 0) { 28 | FSeek(FileSize()); 29 | break; 30 | } 31 | FSeek(results.start[0] - 4); 32 | 33 | size = ReadUInt(FTell()); 34 | type = ReadString(FTell() + 4, 4); 35 | if (type == ".wow") { 36 | if (begin != -1) { 37 | Printf("%s.wow: %x-%x %x\n", name, begin, FTell(), FTell() - begin); 38 | n = 0; 39 | do { 40 | SPrintf(filename, "%s-%s-%d.wow", GetFileName(), name, n++); 41 | } while (FileExists(filename)); 42 | FileSaveRange(filename, begin, FTell() - begin); 43 | } 44 | begin = FTell(); 45 | name = ReadString(FTell() + 20); 46 | FSeek(FTell() + size); 47 | } 48 | } 49 | 50 | /* 51 | WowList list; 52 | for (j = 0; j < list.size; j += 8) 53 | WowHeader wow; 54 | */ 55 | } 56 | 57 | if (begin != -1) { 58 | Printf("%s.wow: %x-%x %x\n", name, begin, FTell(), FTell() - begin); 59 | n = 0; 60 | do { 61 | SPrintf(filename, "%s-%s-%d.wow", GetFileName(), name, n++); 62 | } while (FileExists(filename)); 63 | FileSaveRange(filename, begin, FTell() - begin); 64 | } 65 | -------------------------------------------------------------------------------- /beyond-good-and-evil/extract.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | #include 13 | 14 | struct decompress_args { 15 | uint8_t* cbuffer; 16 | uint8_t* dbuffer; 17 | size_t dsize; 18 | }; 19 | 20 | bool is_compressed = true; 21 | size_t dblock_size = 0x7d000; 22 | 23 | int decompress_block(size_t csize, 24 | uint8_t* cbuffer, 25 | uint8_t* dbuffer, 26 | size_t* bsize); 27 | 28 | uint8_t* decompress(decompress_args& args, size_t bcount) { 29 | std::printf("decompress: bcount: %d\n", bcount); 30 | 31 | if (is_compressed) { 32 | args.dsize = 0; 33 | uint8_t* dbuf = args.dbuffer; 34 | uint8_t* cbuf = args.cbuffer; 35 | size_t block = 0; 36 | 37 | while (block < bcount) { 38 | size_t dsize 39 | = (cbuf[3] << 24) | (cbuf[2] << 16) | (cbuf[1] << 8) | (cbuf[0] << 0); 40 | cbuf += 4; 41 | if (dsize == 0) break; 42 | 43 | size_t csize 44 | = (cbuf[3] << 24) | (cbuf[2] << 16) | (cbuf[1] << 8) | (cbuf[0] << 0); 45 | cbuf += 4; 46 | 47 | if (csize < dsize) { 48 | std::printf("decompress: csize: %x, dsize: %x\n", csize, dsize); 49 | size_t bsize = dsize; 50 | decompress_block(csize, cbuf, dbuf, &bsize); 51 | std::printf("decompress: bsize: %x\n", bsize); 52 | // assert(bsize == dsize); 53 | } else { 54 | std::memcpy(dbuf, cbuf, csize); 55 | } 56 | 57 | cbuf += csize; 58 | dbuf += dsize; 59 | args.dsize += dsize; 60 | block++; 61 | } 62 | 63 | return cbuf; 64 | } else { 65 | std::memcpy(args.dbuffer, args.cbuffer, dblock_size * bcount); 66 | args.dsize = dblock_size * bcount; 67 | return args.cbuffer + args.dsize; 68 | } 69 | } 70 | #define log(message) \ 71 | std::printf(message \ 72 | ", count: %x, dbuf: %x, cbuf: %x, cend: %x, sref: %x, lref: " \ 73 | "%x, %s:%d\n", \ 74 | count, \ 75 | dbuf - dbuffer, \ 76 | cbuf - cbuffer, \ 77 | cend - cbuffer, \ 78 | sref - dbuffer, \ 79 | lref - dbuffer, \ 80 | __FILE__, \ 81 | __LINE__) 82 | int decompress_block(size_t csize, 83 | uint8_t* cbuffer, 84 | uint8_t* dbuffer, 85 | size_t* bsize) { 86 | #define copy(dst, src, count) \ 87 | do { \ 88 | assert(count > 0); \ 89 | std::memcpy(dst, src, count); \ 90 | dst += count; \ 91 | src += count; \ 92 | count = 0; \ 93 | } while (0) 94 | 95 | #define copy4(dst, src, count) \ 96 | do { \ 97 | assert((count & ~3) > 0); \ 98 | std::memcpy(dst, src, count & ~3); \ 99 | dst += count & ~3; \ 100 | src += count & ~3; \ 101 | count &= 3; \ 102 | } while (0) 103 | 104 | #define copyn(dst, src, count, n, m) \ 105 | do { \ 106 | assert(count > 0); \ 107 | std::memcpy(dst, src, n); \ 108 | dst += n; \ 109 | src += n; \ 110 | count -= m; \ 111 | } while (0) 112 | 113 | #define countz(cbuf, count, value) \ 114 | do { \ 115 | count &= value; \ 116 | if (count == 0) { \ 117 | while (cbuf[0] == 0) { \ 118 | count += 0xff; \ 119 | cbuf++; \ 120 | } \ 121 | count += cbuf[0] + value; \ 122 | cbuf++; \ 123 | } \ 124 | } while (0) 125 | 126 | uint8_t* cbuf = cbuffer; 127 | uint8_t* cend = cbuf + csize; 128 | uint8_t* dbuf = dbuffer; 129 | uint8_t* sref = dbuffer; 130 | uint8_t* lref = dbuffer; 131 | *bsize = 0; 132 | 133 | int count = cbuf[0]; 134 | if (count <= 0x11) goto l42a57b; 135 | count -= 0x11; 136 | cbuf++; 137 | if (count < 4) goto l42a630; 138 | copy(dbuf, cbuf, count); 139 | goto l42a5ea; 140 | 141 | l42a57b: 142 | count = cbuf[0]; 143 | cbuf++; 144 | if (count >= 0x10) goto l42a63d; 145 | countz(cbuf, count, 0xf); 146 | copyn(dbuf, cbuf, count, 4, 1); 147 | if (count == 0) goto l42a5ea; 148 | if (count < 4) goto l42a5e1; 149 | copy4(dbuf, cbuf, count); 150 | if (count <= 0) goto l42a5ea; 151 | copy(dbuf, cbuf, count); 152 | goto l42a5ea; 153 | l42a5e1: 154 | copy(dbuf, cbuf, count); 155 | 156 | l42a5ea: 157 | count = cbuf[0]; 158 | cbuf++; 159 | if (count >= 0x10) goto l42a63d; 160 | sref = dbuf - count / 4 - cbuf[0] * 4 - 0x801; 161 | cbuf++; 162 | dbuf[0] = sref[0]; 163 | dbuf++; 164 | sref++; 165 | 166 | l42a613: 167 | dbuf[0] = sref[0]; 168 | dbuf[1] = sref[1]; 169 | dbuf++; 170 | dbuf++; 171 | 172 | l42a61e: 173 | count = cbuf[-2] & 3; 174 | if (count == 0) goto l42a57b; 175 | 176 | l42a630: 177 | copy(dbuf, cbuf, count); 178 | count = cbuf[0]; 179 | cbuf++; 180 | 181 | l42a63d: 182 | if (count < 0x40) goto l42a67b; 183 | lref = dbuf - ((count / 4) & 7) - (cbuf[0] * 8) - 1; 184 | count /= 32; 185 | cbuf++; 186 | count--; 187 | 188 | l42a65c: 189 | dbuf[0] = lref[0]; 190 | dbuf[1] = lref[1]; 191 | dbuf++; 192 | lref++; 193 | dbuf++; 194 | lref++; 195 | copy(dbuf, lref, count); 196 | goto l42a61e; 197 | 198 | l42a67b: 199 | if (count < 0x20) goto l42a6b6; 200 | countz(cbuf, count, 0x1f); 201 | lref = dbuf; 202 | lref -= ((cbuf[0] << 0) | (cbuf[1] << 8)) / 4; 203 | cbuf += 2; 204 | lref--; 205 | goto l42a700; 206 | 207 | l42a6b6: 208 | if (count < 0x10) goto l42a74e; 209 | lref = dbuf - (count & 8) * 2048; 210 | countz(cbuf, count, 7); 211 | lref -= ((cbuf[0] << 0) | (cbuf[1] << 8)) / 4; 212 | cbuf += 2; 213 | if (lref - dbuf == 0) { 214 | *bsize = dbuf - dbuffer; 215 | if (cbuf - cend != 0) 216 | return -4; 217 | else 218 | return 0; 219 | } 220 | lref -= 0x4000; 221 | 222 | l42a700: 223 | if (count < 6) goto l42a65c; 224 | if (dbuf - lref < 4) goto l42a65c; 225 | copyn(dbuf, lref, count, 4, 2); 226 | copy4(dbuf, lref, count); 227 | if (count <= 0) goto l42a61e; 228 | copy(dbuf, lref, count); 229 | goto l42a61e; 230 | 231 | l42a74e: 232 | sref = dbuf - count / 4 - cbuf[0] * 4 - 1; 233 | cbuf++; 234 | goto l42a613; 235 | } 236 | 237 | struct BIGHeader { 238 | char type[4]; 239 | uint32_t u000; 240 | uint32_t file_count; 241 | uint32_t folder_count; 242 | uint32_t u001; 243 | uint32_t u002; 244 | uint32_t u003; 245 | uint32_t u004; 246 | uint32_t file_capacity; 247 | uint32_t u005; 248 | uint32_t u006; 249 | uint32_t file_count_bis; 250 | uint32_t u007; 251 | uint32_t offset; 252 | uint32_t u008; 253 | uint32_t u009; 254 | uint32_t u010; 255 | }; 256 | 257 | struct BIGEntry { 258 | uint32_t offset; 259 | uint32_t id; 260 | }; 261 | 262 | struct BIGFile { 263 | uint32_t size; 264 | uint32_t next; 265 | uint32_t prev; 266 | uint32_t folder; 267 | uint32_t timestamp; 268 | char name[64]; 269 | }; 270 | 271 | struct BIGFolder { 272 | uint32_t id; 273 | uint32_t child; 274 | uint32_t next; 275 | uint32_t prev; 276 | uint32_t parent; 277 | char name[64]; 278 | }; 279 | 280 | int main(int argc, char const* argv[]) { 281 | { 282 | uint8_t cbuffer[] = { 283 | 0xEA, 0x01, 0x00, 0x00, 0xF3, 0x00, 0x00, 0x00, 0x0D, 0x08, 0x00, 0x00, 284 | 0x00, 0x1D, 0x63, 0x00, 0x5E, 0x2E, 0x77, 0x6F, 0x77, 0xB4, 0x00, 0x00, 285 | 0x00, 0x7E, 0x00, 0x03, 0x00, 0xC0, 0x00, 0x00, 0x02, 0xFF, 0xFF, 0x00, 286 | 0x5F, 0x6D, 0x61, 0x69, 0x6E, 0x5F, 0x6E, 0x65, 0x77, 0x67, 0x61, 0x6D, 287 | 0x65, 0x00, 0x77, 0x6F, 0x77, 0xC8, 0x03, 0x20, 0x05, 0x1A, 0x00, 0x80, 288 | 0x3F, 0x30, 0x9C, 0x00, 0x20, 0x09, 0x4D, 0x00, 0x06, 0x90, 0x07, 0xDE, 289 | 0x05, 0xFC, 0xFC, 0x95, 0x01, 0xFF, 0xC0, 0x00, 0x01, 0x1C, 0x63, 0x00, 290 | 0x5E, 0x60, 0x02, 0x06, 0xE2, 0x02, 0x05, 0x12, 0x04, 0x00, 0x00, 0x00, 291 | 0x29, 0x4D, 0x18, 0x9E, 0x7F, 0x17, 0x67, 0x61, 0x6F, 0x7C, 0x02, 0x02, 292 | 0xA0, 0x20, 0x00, 0x00, 0x23, 0x62, 0x01, 0x10, 0x83, 0x75, 0x00, 0x00, 293 | 0xD4, 0x08, 0x8C, 0x01, 0xF0, 0x00, 0x38, 0x4C, 0x00, 0x01, 0xBB, 0xD6, 294 | 0x99, 0xBE, 0x4C, 0x00, 0x07, 0x3E, 0x00, 0x00, 0xA0, 0x40, 0x00, 0x00, 295 | 0x80, 0x3F, 0x02, 0x8A, 0x06, 0x80, 0xBF, 0x4C, 0x01, 0xEC, 0x00, 0x44, 296 | 0x1B, 0x7E, 0x07, 0x80, 0x3F, 0x60, 0x12, 0x78, 0x03, 0xFF, 0x00, 0x00, 297 | 0x00, 0x7F, 0x5D, 0x11, 0x31, 0x5C, 0x11, 0x06, 0x0E, 0x00, 0x00, 0x00, 298 | 0x57, 0x50, 0x5F, 0x61, 0x69, 0x6D, 0x27, 0x2E, 0x61, 0x13, 0x08, 0x45, 299 | 0x02, 0x2F, 0x45, 0x17, 0x30, 0x4D, 0x00, 0x10, 0x74, 0x15, 0x54, 0x04, 300 | 0x02, 0x2E, 0x6F, 0x76, 0x61, 0x2D, 0x9F, 0x00, 0x66, 0x63, 0x20, 0x60, 301 | 0x09, 0x3D, 0x0D, 0x00, 0x24, 0x2D, 0x7C, 0x00, 0x6C, 0x07, 0x2D, 0x48, 302 | 0x00, 0x98, 0x01, 0x0D, 0x0C, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 303 | 0xB0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 304 | }; 305 | 306 | uint8_t dbuffer[] = { 307 | 0x08, 0x00, 0x00, 0x00, 0x1D, 0x63, 0x00, 0x5E, 0x2E, 0x77, 0x6F, 0x77, 308 | 0xB4, 0x00, 0x00, 0x00, 0x2E, 0x77, 0x6F, 0x77, 0x03, 0x00, 0x00, 0x00, 309 | 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x5F, 0x6D, 0x61, 0x69, 310 | 0x6E, 0x5F, 0x6E, 0x65, 0x77, 0x67, 0x61, 0x6D, 0x65, 0x00, 0x77, 0x6F, 311 | 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 312 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 313 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 314 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3F, 315 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 316 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3F, 0x00, 0x00, 0x00, 0x00, 317 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 318 | 0x00, 0x00, 0x80, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 319 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3F, 320 | 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3F, 0x00, 0x00, 0x00, 0x00, 321 | 0x00, 0xFC, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 322 | 0x00, 0x00, 0x00, 0x00, 0x1C, 0x63, 0x00, 0x5E, 0x00, 0x00, 0x00, 0x00, 323 | 0xE2, 0x02, 0x05, 0x12, 0x04, 0x00, 0x00, 0x00, 0x29, 0x63, 0x00, 0x5E, 324 | 0x9E, 0x00, 0x00, 0x00, 0x2E, 0x67, 0x61, 0x6F, 0x00, 0x00, 0x00, 0x00, 325 | 0xA0, 0x20, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x10, 0x83, 0x00, 326 | 0x00, 0x00, 0x00, 0x00, 0x80, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 327 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 328 | 0x80, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 329 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3F, 0x00, 0x00, 330 | 0x00, 0x00, 0xBB, 0xD6, 0x99, 0xBE, 0xBB, 0xD6, 0x99, 0x3E, 0x00, 0x00, 331 | 0xA0, 0x40, 0x00, 0x00, 0x80, 0x3F, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 332 | 0x80, 0xBF, 0x00, 0x00, 0x80, 0xBF, 0x00, 0x00, 0x80, 0xBF, 0x00, 0x00, 333 | 0x00, 0x3F, 0x00, 0x00, 0x80, 0x3F, 0x00, 0x00, 0x80, 0x3F, 0xFF, 0xFF, 334 | 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 335 | 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x31, 0x63, 0x00, 0x5E, 336 | 0x0E, 0x00, 0x00, 0x00, 0x57, 0x50, 0x5F, 0x61, 0x69, 0x67, 0x61, 0x6D, 337 | 0x65, 0x2E, 0x67, 0x61, 0x6F, 0x00, 0x08, 0x00, 0x00, 0x00, 0x2F, 0x63, 338 | 0x00, 0x5E, 0x30, 0x63, 0x00, 0x5E, 0x10, 0x00, 0x00, 0x00, 0x2E, 0x63, 339 | 0x00, 0x5E, 0x2E, 0x6F, 0x76, 0x61, 0x2D, 0x63, 0x00, 0x5E, 0x2E, 0x6F, 340 | 0x66, 0x63, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 341 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 342 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 343 | 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 344 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2D, 0x63, 0x00, 0x5E, 0x00, 0x00, 345 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 346 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x04, 0x00, 347 | 0x00, 0x00, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 348 | }; 349 | 350 | size_t dsize = (cbuffer[0] << 0) | (cbuffer[1] << 8) | (cbuffer[2] << 16) 351 | | (cbuffer[3] << 24); 352 | size_t csize = (cbuffer[4] << 0) | (cbuffer[5] << 8) | (cbuffer[6] << 16) 353 | | (cbuffer[7] << 24); 354 | 355 | decompress_args args; 356 | args.dbuffer = new uint8_t[dsize]; 357 | std::memset(args.dbuffer, 0, dsize); 358 | 359 | args.cbuffer = new uint8_t[csize + 8]; 360 | std::memcpy(args.cbuffer, cbuffer, csize + 8); 361 | 362 | args.dsize = 0; 363 | decompress(args, 1); 364 | assert(std::memcmp(args.dbuffer, dbuffer, dsize) == 0); 365 | 366 | delete[] args.cbuffer; 367 | delete[] args.dbuffer; 368 | } 369 | 370 | { 371 | auto in = std::fopen(argv[1], "rb"); 372 | 373 | auto header = BIGHeader{}; 374 | std::fread(&header, 1, sizeof(header), in); 375 | 376 | auto entries = std::vector< BIGEntry >{}; 377 | entries.resize(header.file_count); 378 | 379 | auto files = std::vector< BIGFile >{}; 380 | files.resize(header.file_count); 381 | 382 | auto folders = std::vector< BIGFolder >{}; 383 | folders.resize(header.folder_count); 384 | 385 | std::fseek(in, sizeof(BIGHeader), SEEK_SET); 386 | for (auto& entry : entries) { 387 | std::fread(&entry, 1, sizeof(entry), in); 388 | } 389 | 390 | std::fseek(in, 391 | sizeof(BIGHeader) + header.file_capacity * sizeof(BIGEntry), 392 | SEEK_SET); 393 | for (auto& file : files) { 394 | std::fread(&file, 1, sizeof(file), in); 395 | } 396 | 397 | std::fseek(in, 398 | sizeof(BIGHeader) + header.file_capacity * sizeof(BIGEntry) 399 | + header.file_capacity * sizeof(BIGFile), 400 | SEEK_SET); 401 | for (auto& folder : folders) { 402 | std::fread(&folder, 1, sizeof(folder), in); 403 | } 404 | 405 | auto make_path = [&](BIGFile const& file) { 406 | auto split = std::vector< std::string >{}; 407 | auto i = file.folder; 408 | while (i != 0xffffffff) { 409 | split.push_back(folders[i].name); 410 | i = folders[i].parent; 411 | } 412 | 413 | std::reverse(split.begin(), split.end()); 414 | auto path = std::string{"."}; 415 | for (auto& name : split) { 416 | path += "/" + name; 417 | ::mkdir(path.c_str(), 0755); 418 | } 419 | 420 | return path + "/" + file.name; 421 | }; 422 | 423 | std::printf("%d\n", header.file_count); 424 | std::printf("%d\n", header.folder_count); 425 | for (auto& file : files) { 426 | auto i = &file - &files[0]; 427 | auto path = make_path(file); 428 | 429 | auto buffer = std::vector< uint8_t >{}; 430 | buffer.resize(file.size); 431 | std::fseek(in, entries[i].offset + 4, SEEK_SET); 432 | std::fread(&buffer[0], 1, file.size, in); 433 | 434 | size_t dsize = (buffer[0] << 0) | (buffer[1] << 8) | (buffer[2] << 16) 435 | | (buffer[3] << 24); 436 | size_t csize = (buffer[4] << 0) | (buffer[5] << 8) | (buffer[6] << 16) 437 | | (buffer[7] << 24); 438 | 439 | if (0 && path.substr(path.size() - 4) == ".bin" && csize <= file.size) { 440 | size_t coffset = 0; 441 | auto out = std::fopen((path + ".dec").c_str(), "w"); 442 | 443 | while (coffset < file.size) { 444 | size_t dsize = (buffer[coffset + 0] << 0) | (buffer[coffset + 1] << 8) 445 | | (buffer[coffset + 2] << 16) 446 | | (buffer[coffset + 3] << 24); 447 | size_t csize = (buffer[coffset + 4] << 0) | (buffer[coffset + 5] << 8) 448 | | (buffer[coffset + 6] << 16) 449 | | (buffer[coffset + 7] << 24); 450 | if (csize == 0 || dsize == 0) break; 451 | 452 | decompress_args args; 453 | args.cbuffer = &buffer[coffset + 0]; 454 | args.dbuffer = new uint8_t[dsize]; 455 | std::memset(args.dbuffer, 0, dsize); 456 | 457 | args.dsize = 0; 458 | decompress(args, 1); 459 | coffset += csize + 8; 460 | 461 | std::fwrite(args.dbuffer, 1, dsize, out); 462 | 463 | delete[] args.dbuffer; 464 | } 465 | 466 | std::fflush(out); 467 | std::fclose(out); 468 | } 469 | 470 | { 471 | auto out = std::fopen(path.c_str(), "wb"); 472 | std::fwrite(&buffer[0], 1, file.size, out); 473 | std::fflush(out); 474 | std::fclose(out); 475 | } 476 | 477 | { 478 | auto out = std::fopen((path + ".id").c_str(), "w"); 479 | std::fprintf(out, "%08x", entries[i].id); 480 | std::fflush(out); 481 | std::fclose(out); 482 | } 483 | 484 | std::printf("%s\n", path.c_str()); 485 | } 486 | } 487 | 488 | return 0; 489 | } 490 | -------------------------------------------------------------------------------- /beyond-good-and-evil/wip-gao.bt: -------------------------------------------------------------------------------- 1 | // Beyond Good and Evil 2 | 3 | #include 4 | 5 | LittleEndian(); 6 | 7 | uint32 size ; 8 | Magic type(4, ".gao"); 9 | 10 | local uint64 begin = FTell(); 11 | 12 | uint16 unknown ; 13 | Assert(unknown == 0x00 || 14 | unknown == 0x08 || 15 | unknown == 0x09 || 16 | unknown == 0x00 || 17 | unknown == 0x40 || 18 | unknown == 0x48); 19 | uint16 unknown ; 20 | Assert(unknown == 0x00 || 21 | unknown == 0x00 || 22 | unknown == 0x00 || 23 | unknown == 0x00 || 24 | unknown == 0x01 || 25 | unknown == 0x01 || 26 | unknown == 0x10); 27 | 28 | uint32 unknown ; 29 | uint16 unknown ; 30 | uint16 unknown ; 31 | uint16 unknown ; 32 | uint16 unknown ; 33 | uint16 unknown ; 34 | Matrix unknown(4, 4); 35 | 36 | uint32 unknown ; 37 | Assert(unknown == 0x0 || 38 | unknown == 0x2 || 39 | unknown == 0x4 || 40 | unknown == 0x6 || 41 | unknown == 0xa || 42 | unknown == 0xe); 43 | 44 | struct { 45 | switch (unknown[2]) { 46 | default: byte unknown[size-90] ; 47 | case 0x2080: 48 | Matrix unknown(3, 2); 49 | ResId unknown; 50 | uint32 unknown; 51 | ResId unknown; 52 | uint32 unknown; 53 | uint16 unknown; 54 | uint32 unknown; 55 | break; 56 | case 0x20a0: 57 | Matrix unknown(3, 2); 58 | ResId unknown; 59 | Fixed32 unknown(0); 60 | ResId unknown; 61 | Fixed32 unknown(0); 62 | uint16 unknown; 63 | Fixed32 unknown(127); 64 | ResId unknown; 65 | break; 66 | case 0x5080: 67 | Matrix unknown(3, 2); 68 | ResId unknown; 69 | ResId unknown; 70 | uint32 unknown; 71 | uint32 unknown; 72 | UInt32Array unknown; 73 | break; 74 | case 0x70a0: 75 | Matrix unknown(3, 2); 76 | ResId unknown; 77 | ResId unknown; 78 | uint32 unknown; 79 | uint32 unknown; 80 | UInt32Array unknown; 81 | ResId unknown; 82 | uint16 unknown; 83 | uint32 unknown; 84 | uint32 unknown; 85 | uint32 unknown; 86 | uint32 unknown; 87 | float unknown; 88 | uint32 unknown; 89 | uint32 unknown; 90 | uint32 unknown; 91 | uint32 unknown; 92 | uint32 unknown; 93 | uint32 unknown; 94 | Matrix unknown(3, 2); 95 | uint32 unknown; 96 | uint32 unknown; 97 | uint32 unknown; 98 | uint32 unknown; 99 | uint32 unknown; 100 | uint32 unknown; 101 | uint32 unknown; 102 | 103 | Matrix unknown(3, 2); 104 | ResId unknown; 105 | Matrix unknown(3, 2); 106 | ResId unknown; 107 | uint32 unknown; 108 | uint32 unknown; 109 | ResId unknown; 110 | break; 111 | case 0x15000: 112 | Matrix unknown(3, 2); 113 | ResId unknown; 114 | ResId unknown; 115 | uint32 unknown; 116 | uint32 unknown; 117 | UInt32Array unknown; 118 | break; 119 | case 0x403010: 120 | Matrix unknown(3, 2); 121 | ResId unknown; 122 | Matrix unknown(4, 4); 123 | ResId unknown; 124 | ResId unknown; 125 | uint32 unknown; 126 | uint32 unknown; 127 | uint16 unknown; 128 | uint32 unknown; 129 | uint32 unknown; 130 | ResId unknown; 131 | break; 132 | case 0x405000: 133 | case 0x415000: 134 | Matrix unknown(3, 2); 135 | ResId unknown; 136 | ResId unknown; 137 | uint32 unknown; 138 | uint32 unknown; 139 | UInt32Array unknown; 140 | ResId unknown; 141 | Matrix unknown(4, 4); 142 | uint32 unknown; 143 | break; 144 | case 0x485000: 145 | Matrix unknown(3, 4); 146 | ResId unknown; 147 | ResId unknown; 148 | uint32 unknown; 149 | uint32 unknown; 150 | UInt32Array unknown; 151 | ResId unknown; 152 | Matrix unknown(4, 4); 153 | uint32 unknown; 154 | break; 155 | case 0x95000: 156 | Matrix unknown(3, 4); 157 | ResId unknown; 158 | ResId unknown; 159 | uint32 unknown; 160 | uint32 unknown; 161 | UInt32Array unknown; 162 | break; 163 | case 0x97000: 164 | case 0x97020: 165 | Matrix unknown(3, 4); 166 | ResId unknown; 167 | ResId unknown; 168 | uint32 unknown; 169 | uint32 unknown; 170 | UInt32Array unknown; 171 | ResId unknown; 172 | uint16 unknown; 173 | uint32 unknown; 174 | uint32 unknown; 175 | uint32 unknown; 176 | uint32 unknown; 177 | uint32 unknown; 178 | uint32 unknown; 179 | uint32 unknown; 180 | uint32 unknown; 181 | uint32 unknown; 182 | uint32 unknown; 183 | uint32 unknown; 184 | local uint32 size = unknown[17]; 185 | // GaoHeaderChunk unknown[size] ; 186 | uint32 u006; 187 | float u006; 188 | float u006; 189 | uint32 u006; 190 | uint32 u006; 191 | uint32 u006; 192 | uint32 u006; 193 | uint32 u006; 194 | uint32 u006; 195 | uint32 u006; 196 | float u006; 197 | float u006; 198 | uint32 u006; 199 | uint32 u006; 200 | float u006; 201 | float u006; 202 | uint32 u006; 203 | uint32 u006; 204 | float u006; 205 | float u006; 206 | uint32 u006; 207 | uint32 u006; 208 | float u006; 209 | float u006; 210 | uint32 u006; 211 | uint32 u006; 212 | float u006; 213 | float u006; 214 | uint32 u006; 215 | uint32 u006; 216 | float u006; 217 | float u006; 218 | uint32 u006; 219 | uint32 u006; 220 | float u006; 221 | float u006; 222 | uint32 u006; 223 | uint32 u006; 224 | float u006; 225 | float u006; 226 | uint32 u006; 227 | uint32 u006; 228 | float u006; 229 | float u006; 230 | uint32 u006; 231 | uint32 u006; 232 | float u006; 233 | float u006; 234 | uint32 u006; 235 | uint32 u006; 236 | float u006; 237 | float u006; 238 | uint32 u006; 239 | uint32 u006; 240 | uint32 u006; 241 | uint32 u006; 242 | float u006; 243 | float u006; 244 | uint32 u006; 245 | uint32 u006; 246 | float u006; 247 | float u006; 248 | uint32 u006; 249 | uint32 u006; 250 | float u006; 251 | float u006; 252 | uint32 u006; 253 | ResId u007; 254 | break; 255 | } 256 | } custom; 257 | 258 | SizedString name; -------------------------------------------------------------------------------- /beyond-good-and-evil/wip-wow.bt: -------------------------------------------------------------------------------- 1 | // Beyond Good and Evil 2 | 3 | #include 4 | 5 | LittleEndian(); 6 | 7 | typedef struct (string magic) { 8 | ResId id; 9 | Magic type(4, magic); 10 | } WowEntry ; 11 | string ReadWowEntry(WowEntry& entry) { string out; SPrintf(out, "%08Xh%s", entry.id.data, entry.type.data); return out; } 12 | 13 | struct WowList { 14 | uint32 size ; 15 | 16 | local uint32 i; 17 | for (i = 0; i < size; i += 8) 18 | WowEntry wow(".wow"); 19 | }; 20 | 21 | struct GaoList { 22 | uint32 size ; 23 | 24 | local uint32 i; 25 | for (i = 0; i < size; i += 4) 26 | ResId id; 27 | }; 28 | 29 | struct ResTypeList { 30 | uint32 size ; 31 | 32 | local uint32 i; 33 | for (i = 0; i < size; i += 8) { 34 | ResId id; 35 | PaddedString type(4); 36 | } 37 | }; 38 | 39 | struct ResList { 40 | uint32 size ; 41 | byte data[size]; 42 | }; 43 | 44 | typedef struct { 45 | uint32 count; 46 | uint32 u000[count]; 47 | float u001[count*3]; 48 | } GaoHeaderChunk ; 49 | 50 | struct GaoHeader { 51 | uint32 size ; 52 | local int64 end = FTell() + size; 53 | Magic type(4, ".gao"); 54 | 55 | uint16 unknown ; 56 | Assert(unknown == 0x00 || 57 | unknown == 0x08 || 58 | unknown == 0x09 || 59 | unknown == 0x00 || 60 | unknown == 0x40 || 61 | unknown == 0x48 || 62 | unknown == 0x2000); 63 | uint16 unknown ; 64 | Assert(unknown == 0x00 || 65 | unknown == 0x00 || 66 | unknown == 0x00 || 67 | unknown == 0x00 || 68 | unknown == 0x01 || 69 | unknown == 0x01 || 70 | unknown == 0x10); 71 | 72 | uint32 unknown ; 73 | uint16 unknown ; 74 | uint16 unknown ; 75 | uint16 unknown ; 76 | uint16 unknown ; 77 | uint16 unknown ; 78 | Matrix unknown(4, 4); 79 | 80 | uint32 unknown ; 81 | Assert(unknown == 0x0 || 82 | unknown == 0x2 || 83 | unknown == 0x4 || 84 | unknown == 0x6 || 85 | unknown == 0xa || 86 | unknown == 0xe); 87 | 88 | Matrix unknown(3, 2); 89 | 90 | /* 91 | if ((unknown[2] & 0xff000) == 0x97000) { 92 | Matrix unknown(6, 1); 93 | if (unknown[2] == 0x97920) { 94 | uint32 unknown; 95 | uint32 unknown; 96 | uint32 unknown; 97 | uint32 unknown; 98 | uint32 size; 99 | uint32 values[size]; 100 | uint32 unknown; 101 | uint32 unknown; 102 | if (unknown == 1) 103 | byte _[62]; 104 | else 105 | byte _[22]; 106 | SizedString name; 107 | } else { 108 | byte _[42]; 109 | SizedString name; 110 | } 111 | } else if (unknown[2] == 0x80) { 112 | SizedString name; 113 | } else if (unknown[4] == 0x2020) { 114 | Matrix unknown(6, 1); 115 | byte _[size-90-6*4]; 116 | SizedString name; 117 | } else { 118 | } 119 | 120 | uint32 unknown; 121 | Assert(unknown == 0xffffffff); 122 | */ 123 | local uint32 footer = 4; 124 | while (ReadUInt(end - footer) != footer - 4) 125 | footer++; 126 | 127 | byte _[size-90-6*4-footer]; 128 | SizedString name; 129 | 130 | Printf("%04x %08x %s\n", size-90-6*4-footer, unknown[2], name.value); 131 | }; 132 | 133 | struct WowHeader { 134 | uint32 size ; Assert(size == 180); 135 | Magic type(4, ".wow"); // verified 136 | Fixed32 version(3); // verified 137 | 138 | uint32 unknown; // something to do with memory alloc 139 | Assert(unknown == 0 || 140 | unknown == 1); 141 | uint32 unknown; 142 | 143 | PaddedString name(60); // verified 144 | Matrix rotate(4, 3); // verified 145 | Matrix translate(3, 1); // verified 146 | float scale; // verified 147 | uint32 unknown ; 148 | 149 | float unknown ; 150 | uint32 unknown ; 151 | uint32 unknown ; 152 | uint32 unknown ; 153 | 154 | ResId resid; 155 | ResId resid; 156 | ResId resid; 157 | ResId resid; 158 | ResId resid; 159 | 160 | if (resid[0].data != 0x00000000 && resid[0].data != 0xffffffff) 161 | ResList list3; 162 | if (resid[1].data != 0x00000000 && resid[0].data != 0xffffffff) 163 | ResList list3; 164 | 165 | if (resid[3].data != 0) 166 | GaoList list0; 167 | GaoList list; 168 | 169 | if (resid[0].data != 0x00000000 && resid[0].data != 0xffffffff) 170 | ResList list3; 171 | if (resid[1].data != 0x00000000 && resid[0].data != 0xffffffff) 172 | ResList list3; 173 | 174 | if (resid[3].data != 0) 175 | GaoHeader gao0[list0.size / 4] ; 176 | GaoHeader gao[list.size / 4] ; 177 | }; 178 | 179 | struct SizesChunk { 180 | uint32 size; 181 | uint32 sizes[size / 4]; 182 | }; 183 | 184 | WowHeader wow; 185 | 186 | GaoList list; 187 | Chunk unknown; 188 | Chunk unknown; 189 | 190 | ResTypeList list; 191 | Chunk unknown; 192 | Chunk unknown; 193 | Chunk unknown; 194 | Chunk unknown; -------------------------------------------------------------------------------- /commandos/dir.bt: -------------------------------------------------------------------------------- 1 | #include "../common.bt" 2 | 3 | LittleEndian(); 4 | 5 | enum EntryType { 6 | FILE = 0xcdcdcd00, 7 | DIR = 0xcdcdcd01, 8 | EOD = 0xcdcdcdff 9 | }; 10 | struct Entry { 11 | PaddedString name(32); 12 | EntryType type ; 13 | uint32 size ; 14 | uint32 offset ; 15 | 16 | local uint64 position = FTell(); 17 | if (type == DIR) { 18 | FSeek(offset); 19 | ReadEntries(); 20 | FSeek(position); 21 | } else if (type == FILE) { 22 | FSeek(offset); 23 | byte contents[size] ; 24 | FSeek(position); 25 | } 26 | }; 27 | 28 | void ReadEntries() { 29 | while (true) { 30 | Entry entry; 31 | if (entry.type == EOD) 32 | break; 33 | } 34 | } 35 | 36 | ReadEntries(); 37 | -------------------------------------------------------------------------------- /commandos2/pck.bt: -------------------------------------------------------------------------------- 1 | #include "../common.bt" 2 | 3 | LittleEndian(); 4 | 5 | enum EntryType { 6 | FILE = 0, 7 | DIR = 1, 8 | EOD = 0xff, 9 | }; 10 | struct Entry { 11 | PaddedString name(32); 12 | uint32 unknown; 13 | EntryType type; 14 | uint32 size; 15 | uint32 offset; 16 | 17 | if (type == DIR) { 18 | ReadEntries(); 19 | } else if (type == FILE) { 20 | local uint64 position = FTell(); 21 | FSeek(offset); 22 | byte contents[size] ; 23 | FSeek(position); 24 | } 25 | }; 26 | 27 | void ReadEntries() { 28 | while (true) { 29 | Entry entry; 30 | if (entry.type == EOD) 31 | break; 32 | } 33 | } 34 | 35 | Entry entry; 36 | -------------------------------------------------------------------------------- /common.bt: -------------------------------------------------------------------------------- 1 | // Common 2 | 3 | typedef struct (uint32 count, string magic) { 4 | char data[count] ; 5 | Assert(data == magic); 6 | } Magic ; 7 | string ReadMagic(Magic& value) { return value.data; } 8 | 9 | typedef struct (uint32 value) { 10 | uint32 data ; 11 | Assert(data == value); 12 | } Fixed32 ; 13 | string ReadFixed32(Fixed32& value) { string out; SPrintf(out, "%08Xh", value.data); return out; } 14 | 15 | typedef struct (uint64 value) { 16 | uint64 data ; 17 | Assert(data == value); 18 | } Fixed64 ; 19 | string ReadFixed64(Fixed64& value) { string out; SPrintf(out, "%016LXh", value.data); return out; } 20 | 21 | typedef struct { string value; } String ; 22 | string ReadStr(String& data) { return data.value; } 23 | 24 | typedef struct (uint32 size) { char value[size]; } PaddedString ; 25 | string ReadPaddedString(PaddedString& data) { return data.value; } 26 | 27 | typedef struct { uint32 size; char value[size]; } SizedString ; 28 | string ReadSizedString(SizedString& data) { return data.value; } 29 | 30 | typedef struct { byte size; char value[size]; } Sized8String ; 31 | string ReadSized8String(Sized8String& data) { return data.value; } 32 | 33 | typedef struct { uint32 count; uint32 data[count]; } UInt32Array; 34 | 35 | typedef struct { 36 | uint32 data ; 37 | } ResId ; 38 | string ReadResId(ResId& value) { string out; SPrintf(out, "%08Xh", value.data); return out; } 39 | 40 | typedef struct (uint32 width, uint32 height) { 41 | local uint32 width = width; 42 | local uint32 height = height; 43 | float data[width * height] ; 44 | } Matrix ; 45 | string ReadMatrix(Matrix& value) { 46 | local string out = "{", buf; 47 | local uint32 x,y; 48 | for (y = 0; y < value.height; ++y) { 49 | if (y > 0) out += ",\n"; 50 | out += "{"; 51 | for (x = 0; x < value.width; ++x) { 52 | if (x > 0) out += ","; 53 | SPrintf(buf, "%f", value.data[x + y * value.width]); 54 | out += buf; 55 | } 56 | out += "}"; 57 | } 58 | out += "}"; 59 | return out; 60 | } 61 | 62 | struct Chunk { 63 | uint32 size ; 64 | byte data[size] ; 65 | }; 66 | -------------------------------------------------------------------------------- /fallout/dat.bt: -------------------------------------------------------------------------------- 1 | #include "../common.bt" 2 | 3 | BigEndian(); 4 | 5 | enum FileFlags { NONE=32, LZSS=64, }; 6 | 7 | struct File { 8 | Sized8String name; 9 | FileFlags flags; 10 | uint32 offset; 11 | uint32 size_unpacked; 12 | uint32 size_packed; 13 | 14 | local uint64 position = FTell(); 15 | if (flags == NONE) { 16 | FSeek(offset); 17 | byte contents[size_unpacked] ; 18 | FSeek(position); 19 | } else if (flags == LZSS) { 20 | FSeek(offset); 21 | byte contents[size_packed] ; 22 | FSeek(position); 23 | } 24 | }; 25 | 26 | struct Folder { 27 | uint32 file_count; 28 | uint32 unknown[2]; 29 | uint32 timestamp; 30 | File files[file_count] ; 31 | }; 32 | 33 | struct Header { 34 | uint32 folder_count; 35 | uint32 unknown[2]; 36 | uint32 timestamp; 37 | Sized8String folder_names[folder_count] ; 38 | Folder folders[folder_count] ; 39 | }; 40 | 41 | Header header; 42 | -------------------------------------------------------------------------------- /fallout2/dat.bt: -------------------------------------------------------------------------------- 1 | #include "../common.bt" 2 | 3 | LittleEndian(); 4 | 5 | enum FileFlags { NONE=0, ZLIB=1, }; 6 | 7 | struct File { 8 | SizedString name; 9 | FileFlags flags; 10 | uint32 size_unpacked; 11 | uint32 size_packed; 12 | uint32 offset; 13 | 14 | local uint64 position = FTell(); 15 | if (flags == NONE) { 16 | FSeek(offset); 17 | byte contents[size_unpacked] ; 18 | FSeek(position); 19 | } else if (flags == ZLIB) { 20 | FSeek(offset); 21 | byte contents[size_packed] ; 22 | FSeek(position); 23 | } 24 | }; 25 | 26 | struct Footer { 27 | uint32 index_size; 28 | uint32 file_size; 29 | }; 30 | 31 | struct Index { 32 | uint32 file_count; 33 | File files[file_count] ; 34 | }; 35 | 36 | FSeek(FileSize() - 8); 37 | Footer footer; 38 | FSeek(FileSize() - 8 - footer.index_size); 39 | Index index; 40 | -------------------------------------------------------------------------------- /game-data-reverse-engineering-config-version.cmake: -------------------------------------------------------------------------------- 1 | # This is a basic version file for the Config-mode of find_package(). 2 | # It is used by write_basic_package_version_file() as input file for configure_file() 3 | # to create a version-file which can be installed along a config.cmake file. 4 | # 5 | # The created file sets PACKAGE_VERSION_EXACT if the current version string and 6 | # the requested version string are exactly the same and it sets 7 | # PACKAGE_VERSION_COMPATIBLE if the current version is >= requested version, 8 | # but only if the requested major version is the same as the current one. 9 | # The variable CVF_VERSION must be set before calling configure_file(). 10 | 11 | 12 | set(PACKAGE_VERSION "0.0.0") 13 | 14 | if(PACKAGE_VERSION VERSION_LESS PACKAGE_FIND_VERSION) 15 | set(PACKAGE_VERSION_COMPATIBLE FALSE) 16 | else() 17 | 18 | if("0.0.0" MATCHES "^([0-9]+)\\.") 19 | set(CVF_VERSION_MAJOR "${CMAKE_MATCH_1}") 20 | else() 21 | set(CVF_VERSION_MAJOR "0.0.0") 22 | endif() 23 | 24 | if(PACKAGE_FIND_VERSION_MAJOR STREQUAL CVF_VERSION_MAJOR) 25 | set(PACKAGE_VERSION_COMPATIBLE TRUE) 26 | else() 27 | set(PACKAGE_VERSION_COMPATIBLE FALSE) 28 | endif() 29 | 30 | if(PACKAGE_FIND_VERSION STREQUAL PACKAGE_VERSION) 31 | set(PACKAGE_VERSION_EXACT TRUE) 32 | endif() 33 | endif() 34 | 35 | 36 | # if the installed or the using project don't have CMAKE_SIZEOF_VOID_P set, ignore it: 37 | if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "" OR "8" STREQUAL "") 38 | return() 39 | endif() 40 | 41 | # check that the installed version has the same 32/64bit-ness as the one which is currently searching: 42 | if(NOT CMAKE_SIZEOF_VOID_P STREQUAL "8") 43 | math(EXPR installedBits "8 * 8") 44 | set(PACKAGE_VERSION "${PACKAGE_VERSION} (${installedBits}bit)") 45 | set(PACKAGE_VERSION_UNSUITABLE TRUE) 46 | endif() 47 | -------------------------------------------------------------------------------- /game-data-reverse-engineering-config.cmake: -------------------------------------------------------------------------------- 1 | # AUTOGENERATED 2 | if (TARGET game-data-reverse-engineering::game-data-reverse-engineering) 3 | return() 4 | endif() 5 | add_subdirectory("${CMAKE_CURRENT_LIST_DIR}" 6 | "${CMAKE_BINARY_DIR}/packages/game-data-reverse-engineering" EXCLUDE_FROM_ALL) 7 | message(STATUS "Found game-data-reverse-engineering ${game-data-reverse-engineering_VERSION} (source)") 8 | -------------------------------------------------------------------------------- /neverwinter-nights-2/README: -------------------------------------------------------------------------------- 1 | See https://github.com/berenm/xoreos-tools/tree/wip/granny-decoder for a cleaned-up version of the Granny2 decompression algorithm and conversion tools. 2 | -------------------------------------------------------------------------------- /neverwinter-nights-2/fxa.bt: -------------------------------------------------------------------------------- 1 | LittleEndian(); 2 | 3 | enum Magic { FACE = 0x45434146 }; 4 | 5 | struct String { 6 | uint16 type; 7 | uint32 size; 8 | char value[size]; 9 | }; 10 | 11 | struct { 12 | Magic magic; 13 | 14 | uint32 unknown; 15 | String entry[2] ; 16 | uint16 unknown; 17 | uint32 unknown; 18 | uint32 unknown; 19 | 20 | String entry ; 21 | uint16 unknown; 22 | 23 | uint16 type; 24 | if (type != 1) { 25 | String entry ; 26 | uint16 unknown; 27 | uint32 unknown; 28 | String entry ; 29 | uint16 unknown; 30 | uint32 unknown; 31 | uint32 unknown; 32 | uint32 unknown; 33 | String entry ; 34 | uint16 unknown; 35 | uint32 filesize; 36 | uint16 unknown; 37 | uint16 count; 38 | 39 | struct { 40 | uint32 unknown; 41 | uint32 unknown; 42 | String entry ; 43 | uint16 unknown; 44 | uint32 unknown; 45 | uint16 unknown; 46 | uint16 count; 47 | 48 | struct { 49 | float unknown[4]; 50 | uint16 unknown16; 51 | } data[count] ; 52 | } data[count] ; 53 | 54 | uint32 unknown; 55 | uint32 unknown; 56 | float unknown; 57 | float unknown; 58 | uint32 unknown; 59 | uint32 unknown; 60 | uint32 unknown; 61 | uint32 unknown; 62 | uint16 unknown; 63 | uint32 unknown; 64 | 65 | } else { 66 | uint32 count; 67 | uint32 unknown; 68 | 69 | struct { 70 | uint16 unknown; 71 | String entry ; 72 | uint16 unknown; 73 | float unknown; 74 | float unknown; 75 | float unknown; 76 | float unknown; 77 | float unknown; 78 | float unknown; 79 | float unknown; 80 | float unknown; 81 | float unknown; 82 | float unknown; 83 | float unknown; 84 | float unknown; 85 | uint32 unknown; 86 | } data[count] ; 87 | 88 | uint16 unknown; 89 | uint32 count2; 90 | 91 | struct { 92 | uint32 unknown; 93 | String entry ; 94 | uint16 unknown; 95 | uint16 unknown; 96 | 97 | struct { 98 | uint32 unknown; 99 | uint16 unknown; 100 | String entry ; 101 | uint16 unknown; 102 | float unknown; 103 | float unknown; 104 | float unknown; 105 | float unknown; 106 | float unknown; 107 | float unknown; 108 | float unknown; 109 | } data ; 110 | 111 | uint32 count; 112 | struct { 113 | uint32 unknown; 114 | uint16 unknown; 115 | String entry ; 116 | uint16 unknown; 117 | float unknown; 118 | float unknown; 119 | float unknown; 120 | float unknown; 121 | float unknown; 122 | float unknown; 123 | float unknown; 124 | float unknown; 125 | float unknown; 126 | float unknown; 127 | } data[count] ; 128 | } data2[count2] ; 129 | 130 | uint32 unknown; 131 | uint32 unknown; 132 | uint32 unknown; 133 | 134 | String entry ; 135 | uint16 unknown; 136 | uint16 unknown; 137 | uint32 unknown; 138 | uint32 unknown; 139 | } 140 | 141 | } header ; -------------------------------------------------------------------------------- /neverwinter-nights-2/gr2.bt: -------------------------------------------------------------------------------- 1 | LittleEndian(); 2 | 3 | struct Section; 4 | struct Relocation; 5 | struct Marshalling; 6 | 7 | enum Types { 8 | cCompressed, 9 | cSection, 10 | cRelocation, 11 | cMarshalling, 12 | }; 13 | 14 | struct Array(int type, int start) { 15 | uint32 offset ; 16 | uint32 size ; 17 | 18 | if (size == 0) break; 19 | 20 | local int64 pos=FTell(); 21 | FSeek(offset+start); 22 | switch (type) { 23 | default: break; 24 | case cCompressed: byte data[size] ; break; 25 | case cSection: Section elements[size] ; break; 26 | case cRelocation: Relocation elements[size] ; break; 27 | case cMarshalling: Marshalling elements[size] ; break; 28 | } 29 | FSeek(pos); 30 | }; 31 | 32 | struct Section { 33 | uint32 compression; 34 | 35 | Array compressed(cCompressed, 0) ; 36 | uint32 decompressed_size; 37 | uint32 unknown ; 38 | uint32 parameters[2] ; 39 | 40 | Array relocation(cRelocation, 0) ; 41 | Array marshalling(cMarshalling, 0) ; 42 | }; 43 | 44 | struct Reference { 45 | uint32 section; 46 | uint32 offset ; 47 | }; 48 | 49 | struct Relocation { 50 | uint32 offset ; 51 | Reference target; 52 | }; 53 | 54 | struct Marshalling { 55 | uint32 count; 56 | uint32 offset ; 57 | Reference target; 58 | }; 59 | 60 | struct Type; 61 | 62 | string read_strref(uint32 offset) { if (!offset) return ""; return ReadString(start+offset); } 63 | typedef uint32 strref ; 64 | 65 | struct Type; 66 | 67 | void TypeList(uint32 offset) { 68 | local int64 position=FTell(); 69 | FSeek(start + offset); 70 | 71 | while (ReadUInt(FTell() + 4) > 0) { 72 | Type types; 73 | } 74 | 75 | FSeek(position); 76 | }; 77 | 78 | void StrRef() { 79 | uint32 name_offset ; 80 | if (name_offset == 0) return; 81 | 82 | local int64 position=FTell(); 83 | FSeek(start + name_offset); 84 | string name; 85 | FSeek(position); 86 | } 87 | 88 | local uint32 depth = 0; 89 | struct Type { 90 | uint32 type; 91 | StrRef(); 92 | uint32 next; 93 | uint32 count; 94 | uint32 unknown[4]; 95 | 96 | if (next > 0 && depth < 5) { 97 | depth++; 98 | TypeList(next); 99 | depth--; 100 | } 101 | }; 102 | 103 | struct Header 104 | { 105 | struct { 106 | uint32 magic[4]; 107 | uint32 size ; 108 | uint32 format; 109 | uint32 reserved[2]; 110 | } header; 111 | 112 | local int64 start=FTell(); 113 | struct { 114 | uint32 version; 115 | uint32 file_size ; 116 | uint32 crc32 ; 117 | 118 | Array sections(cSection,start) ; 119 | Reference type; 120 | Reference root; 121 | 122 | uint32 tag; 123 | uint32 extra[4]; 124 | } info; 125 | 126 | start = info.sections.elements[info.type.section].compressed.offset; 127 | 128 | struct { 129 | TypeList(info.type.offset); 130 | } structure; 131 | }; 132 | 133 | Header header ; 134 | -------------------------------------------------------------------------------- /neverwinter-nights-2/gr2raw.bt: -------------------------------------------------------------------------------- 1 | LittleEndian(); 2 | 3 | string read_strref(uint32 offset) { if (!offset) return ""; return ReadString(offset); } 4 | 5 | typedef uint32 strref ; 6 | 7 | struct List; 8 | struct CreateInfo; 9 | struct ExportInfo; 10 | 11 | struct Texture; 12 | struct Material; 13 | struct Skeleton; 14 | struct Vertex; 15 | struct Topology; 16 | struct Mesh; 17 | struct Model; 18 | struct Group; 19 | struct Animation; 20 | struct Property; 21 | struct Image; 22 | struct MipLevel; 23 | struct VertexData; 24 | struct Skeleton; 25 | struct Bone; 26 | struct Transform; 27 | struct VertexAnnotation; 28 | 29 | enum Types { 30 | cUnknown, 31 | cString, 32 | cUInt32, 33 | cInt32, 34 | cFloat, 35 | cCreateInfo, 36 | cExportInfo, 37 | cTexture, 38 | cMaterial, 39 | cSkeleton, 40 | cVertexData, 41 | cTopology, 42 | cMesh, 43 | cModel, 44 | cGroup, 45 | cAnimation, 46 | cProperty, 47 | cImage, 48 | cMipLevel, 49 | cByte, 50 | cBone, 51 | cTransform, 52 | cLightInfo, 53 | cCameraInfo, 54 | cVertexAnnotation, 55 | }; 56 | 57 | struct Value(int type) { 58 | switch (type) { 59 | default: 60 | case cUnknown: 61 | break; 62 | case cString: 63 | string value; 64 | break; 65 | case cByte: 66 | byte value; 67 | break; 68 | case cUInt32: 69 | uint32 value; 70 | break; 71 | case cInt32: 72 | int32 value; 73 | break; 74 | case cFloat: 75 | float value; 76 | break; 77 | case cCreateInfo: 78 | CreateInfo value; 79 | break; 80 | case cExportInfo: 81 | ExportInfo value; 82 | break; 83 | case cTexture: 84 | Texture value; 85 | break; 86 | case cImage: 87 | Image value; 88 | break; 89 | case cMipLevel: 90 | MipLevel value; 91 | break; 92 | case cVertexData: 93 | VertexData value; 94 | break; 95 | case cSkeleton: 96 | Skeleton value; 97 | break; 98 | case cBone: 99 | Bone value; 100 | break; 101 | case cTransform: 102 | Transform value; 103 | break; 104 | case cVertexAnnotation: 105 | VertexAnnotation value; 106 | break; 107 | } 108 | }; 109 | 110 | struct ValueRef(int type) { 111 | uint32 offset ; 112 | if (offset == 0) break; 113 | 114 | local int64 pos = FTell(); 115 | FSeek(offset); 116 | Value value(type); 117 | FSeek(pos); 118 | }; 119 | 120 | struct Array(int type, int refs) { 121 | uint32 size; 122 | uint32 offset ; 123 | 124 | if (size == 0) break; 125 | 126 | local int64 pos = FTell(); 127 | FSeek(offset); 128 | if (refs) { 129 | ValueRef elements(type)[size] ; 130 | } else { 131 | Value elements(type)[size] ; 132 | } 133 | FSeek(pos); 134 | }; 135 | 136 | struct CreateInfo { 137 | ValueRef name(cString); 138 | uint32 version[2]; 139 | float units_per_meter; 140 | float origin[3]; 141 | float rotation[9]; 142 | }; 143 | 144 | struct ExportInfo { 145 | ValueRef name(cString); 146 | uint32 version[4]; 147 | }; 148 | 149 | struct ExtendedData { 150 | uint32 properties_offset; 151 | uint32 values_offset; 152 | 153 | local int64 pos = FTell(); 154 | FSeek(properties_offset); 155 | do { 156 | Property properties; 157 | } while(properties.type > 0); 158 | 159 | FSeek(values_offset); 160 | local uint32 i; 161 | for (i = 0; properties[i].type > 0; ++i) { 162 | switch(properties[i].type) { 163 | case 0x03: 164 | uint32 values ; 165 | break; 166 | case 0x08: 167 | ValueRef values(cString); 168 | break; 169 | case 0x0A: 170 | float values; 171 | break; 172 | case 0x13: 173 | uint32 values; 174 | break; 175 | default: 176 | uint32 values; 177 | break; 178 | } 179 | } 180 | 181 | FSeek(pos); 182 | }; 183 | 184 | struct Property { 185 | uint32 type; 186 | ValueRef name(cString); 187 | uint32 unknown1; 188 | uint32 cardinality; 189 | uint32 unknown2[4]; 190 | }; 191 | 192 | struct Texture { 193 | ValueRef filename(cString); 194 | uint32 type; 195 | uint32 width; 196 | uint32 height; 197 | uint32 encoding; 198 | uint32 subformat; 199 | struct { 200 | uint32 bytes_per_pixel; 201 | uint32 shift_for_component[4]; 202 | uint32 bits_for_component[4]; 203 | } layout; 204 | Array images(cImage, 0); 205 | }; 206 | 207 | struct Image { 208 | Array mipmaps(cMipLevel, 0); 209 | }; 210 | 211 | struct MipLevel { 212 | uint32 stride; 213 | Array pixels(cByte, 0); 214 | }; 215 | 216 | struct VertexData { 217 | struct { 218 | uint32 metadata; 219 | local int64 pos = FTell(); 220 | FSeek(metadata); 221 | do { 222 | Property properties; 223 | } while(properties.type > 0); 224 | FSeek(pos); 225 | Array data(cFloat, 0); 226 | } vertices; 227 | Array components(cString, 1); 228 | Array annotations(cVertexAnnotation, 0); 229 | }; 230 | 231 | struct VertexAnnotation { 232 | ValueRef name(cString); 233 | uint32 unknown; 234 | uint32 indices_maps_from_vertex_to_annotation; 235 | Array indicies(cUInt32, 0); 236 | }; 237 | 238 | struct Skeleton { 239 | ValueRef name(cString); 240 | Array bones(cBone, 0); 241 | }; 242 | 243 | struct Bone { 244 | ValueRef name(cString); 245 | uint32 parent; 246 | Transform transform; 247 | float inverse_world_transform[16]; 248 | 249 | ValueRef light_info(cLightInfo); 250 | ValueRef camera_info(cCameraInfo); 251 | 252 | ExtendedData extended; 253 | }; 254 | 255 | struct Transform { 256 | uint32 dimensions; 257 | float origin[3]; 258 | float rotation[4]; 259 | float transform[9]; 260 | }; 261 | 262 | typedef struct Gr2Raw { 263 | ValueRef create(cCreateInfo); 264 | ValueRef export(cExportInfo); 265 | ValueRef filename(cString); 266 | 267 | Array textures(cTexture, 1); 268 | Array materials(cMaterial, 1); 269 | Array skeletons(cSkeleton, 1); 270 | Array vertexes(cVertexData, 1); 271 | Array topologies(cTopology, 1); 272 | Array meshes(cMesh, 1); 273 | Array models(cModel, 1); 274 | Array groups(cGroup, 1); 275 | Array animations(cAnimation, 1); 276 | 277 | ExtendedData properties; 278 | }; 279 | 280 | Gr2Raw file ; -------------------------------------------------------------------------------- /neverwinter-nights-2/granny.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | namespace gr2 { 13 | 14 | namespace { 15 | 16 | // #include "PLC_DC_TempleE01.gr2.hpp" 17 | #include "N_KoS_UnA_cutsceesdeath01.gr2.hpp" 18 | 19 | struct decoder; 20 | struct dictionary; 21 | struct weighted_window; 22 | struct parameters; 23 | 24 | struct decoder { 25 | uint32_t numer; 26 | uint32_t denom; 27 | uint32_t next_denom; 28 | uint8_t* stream; 29 | 30 | decoder(uint8_t* stream); 31 | 32 | uint16_t decode(uint16_t max); 33 | uint16_t commit(uint16_t max, uint16_t val, uint16_t err); 34 | uint16_t decode_and_commit(uint16_t max); 35 | }; 36 | 37 | struct weighted_window { 38 | uint16_t count_cap; 39 | 40 | std::vector< uint16_t > ranges; 41 | std::vector< uint16_t > values; 42 | std::vector< uint16_t > weights; 43 | uint16_t weight_total; 44 | 45 | uint16_t thresh_increase; 46 | uint16_t thresh_increase_cap; 47 | uint16_t thresh_range_rebuild; 48 | uint16_t thresh_weight_rebuild; 49 | 50 | weighted_window(uint32_t max_value, uint16_t count_cap); 51 | 52 | void rebuild_weights(); 53 | void rebuild_ranges(); 54 | auto try_decode(decoder & dec); 55 | }; 56 | 57 | struct dictionary { 58 | uint32_t decoded_size; 59 | uint32_t backref_size; 60 | 61 | uint32_t decoded_value_max; 62 | uint32_t backref_value_max; 63 | uint32_t lowbit_value_max; 64 | uint32_t midbit_value_max; 65 | uint32_t highbit_value_max; 66 | 67 | weighted_window lowbit_window; 68 | weighted_window highbit_window; 69 | std::vector< weighted_window > midbit_windows; 70 | 71 | std::vector< weighted_window > decoded_windows; 72 | std::vector< weighted_window > size_windows; 73 | 74 | dictionary(parameters& params); 75 | 76 | uint32_t decompress_block(decoder& dec, uint8_t* dbuf); 77 | }; 78 | 79 | struct parameters { 80 | unsigned decoded_value_max : 9; 81 | unsigned backref_value_max : 23; 82 | unsigned decoded_count : 9; 83 | unsigned padding : 10; 84 | unsigned highbit_count : 13; 85 | uint8_t sizes_count[4]; 86 | }; 87 | 88 | static_assert(sizeof(parameters) == 12, ""); 89 | 90 | decoder::decoder(uint8_t* stream) { 91 | this->numer = stream[0] >> 1; 92 | this->denom = 0x80; 93 | this->stream = stream; 94 | } 95 | 96 | uint16_t decoder::decode(uint16_t max) { 97 | for (; this->denom <= 0x800000; this->denom <<= 8) { 98 | this->numer <<= 8; 99 | this->numer |= (this->stream[0] << 7) & 0x80; 100 | this->numer |= (this->stream[1] >> 1) & 0x7f; 101 | this->stream++; 102 | } 103 | 104 | this->next_denom = this->denom / max; 105 | return std::min(this->numer / this->next_denom, max - 1u); 106 | } 107 | 108 | uint16_t decoder::commit(uint16_t max, uint16_t val, uint16_t err) { 109 | this->numer -= this->next_denom * val; 110 | 111 | if (val + err < max) 112 | this->denom = this->next_denom * err; 113 | else 114 | this->denom -= this->next_denom * val; 115 | 116 | return val; 117 | } 118 | 119 | uint16_t decoder::decode_and_commit(uint16_t max) { 120 | return this->commit(max, this->decode(max), 1); 121 | } 122 | 123 | weighted_window::weighted_window(uint32_t max_value, uint16_t count_cap) { 124 | this->weight_total = 4; 125 | this->count_cap = count_cap + 1; 126 | 127 | this->ranges.emplace_back(0); 128 | this->ranges.emplace_back(0x4000); 129 | 130 | this->weights.emplace_back(4); 131 | this->values.emplace_back(0); 132 | 133 | this->thresh_increase = 4; 134 | this->thresh_range_rebuild = 8; 135 | this->thresh_weight_rebuild = std::max(256u, std::min(32 * max_value, 15160u)); 136 | 137 | if (max_value > 64) 138 | this->thresh_increase_cap = std::min(2 * max_value, this->thresh_weight_rebuild / 2 - 32u); 139 | else 140 | this->thresh_increase_cap = 128; 141 | } 142 | 143 | void weighted_window::rebuild_ranges() { 144 | this->ranges.resize(this->weights.size()); 145 | 146 | auto range_weight = 8 * 0x4000 / this->weight_total; 147 | auto range_start = 0; 148 | for (size_t i = 0; i < this->weights.size(); ++i) { 149 | this->ranges[i] = range_start; 150 | range_start += (this->weights[i] * range_weight) / 8; 151 | } 152 | this->ranges.emplace_back(0x4000); 153 | 154 | if (this->thresh_increase > this->thresh_increase_cap / 2) { 155 | this->thresh_range_rebuild = this->weight_total + this->thresh_increase_cap; 156 | } else { 157 | this->thresh_increase *= 2; 158 | this->thresh_range_rebuild = this->weight_total + this->thresh_increase; 159 | } 160 | } 161 | 162 | void weighted_window::rebuild_weights() { 163 | std::transform(std::begin(this->weights), 164 | std::end(this->weights), 165 | std::begin(this->weights), 166 | [](uint16_t& w) { return w / 2; }); 167 | 168 | this->weight_total = std::accumulate(std::begin(this->weights), std::end(this->weights), 0); 169 | 170 | for (uint32_t i = 1; i < this->weights.size(); i++) { 171 | while (i < this->weights.size() && this->weights[i] == 0) { 172 | std::swap(this->weights[i], this->weights.back()); 173 | std::swap(this->values[i], this->values.back()); 174 | 175 | this->weights.pop_back(); 176 | this->values.pop_back(); 177 | } 178 | } 179 | 180 | auto it = std::max_element(std::begin(this->weights) + 1, std::end(this->weights)); 181 | if (it != std::end(this->weights)) { 182 | auto const i = std::distance(std::begin(this->weights), it); 183 | std::swap(this->weights[i], this->weights.back()); 184 | std::swap(this->values[i], this->values.back()); 185 | } 186 | 187 | if ((this->weights.size() < this->count_cap) && (this->weights[0] == 0)) { 188 | this->weights[0] = 1; 189 | this->weight_total++; 190 | } 191 | } 192 | 193 | auto weighted_window::try_decode(decoder & dec) { 194 | if (this->weight_total >= this->thresh_range_rebuild) { 195 | if (this->thresh_range_rebuild >= this->thresh_weight_rebuild) 196 | this->rebuild_weights(); 197 | this->rebuild_ranges(); 198 | } 199 | 200 | auto value = dec.decode(0x4000); 201 | auto rangeit = std::upper_bound(std::begin(this->ranges), std::end(this->ranges), value) - 1; 202 | dec.commit(0x4000, *rangeit, *std::next(rangeit) - *rangeit); 203 | 204 | auto index = std::distance(std::begin(this->ranges), rangeit); 205 | this->weights[index]++; 206 | this->weight_total++; 207 | 208 | if (index > 0) 209 | return std::make_pair((uint16_t*) nullptr, this->values[index]); 210 | 211 | if ((this->weights.size() >= this->ranges.size()) 212 | && (dec.decode_and_commit(2) == 1)) { 213 | auto index = this->ranges.size() + dec.decode_and_commit(this->weights.size() - this->ranges.size() + 1) - 1u; 214 | 215 | this->weights[index] += 2; 216 | this->weight_total += 2; 217 | 218 | return std::make_pair((uint16_t*) nullptr, this->values[index]); 219 | } 220 | 221 | this->values.emplace_back(0); 222 | this->weights.emplace_back(2); 223 | this->weight_total += 2; 224 | 225 | if (this->weights.size() == this->count_cap) { 226 | this->weight_total -= this->weights[0]; 227 | this->weights[0] = 0; 228 | } 229 | 230 | return std::make_pair(&this->values.back(), (uint16_t) 0); 231 | } 232 | 233 | dictionary::dictionary(parameters& params) : 234 | decoded_size(0), 235 | backref_size(0), 236 | 237 | decoded_value_max(params.decoded_value_max), 238 | backref_value_max(params.backref_value_max), 239 | lowbit_value_max(std::min(backref_value_max + 1, 4u)), 240 | midbit_value_max(std::min(backref_value_max / 4 + 1, 256u)), 241 | highbit_value_max(backref_value_max / 1024u + 1), 242 | 243 | lowbit_window(lowbit_value_max - 1, lowbit_value_max), 244 | highbit_window(highbit_value_max - 1, params.highbit_count + 1) { 245 | 246 | for (size_t i = 0; i < this->highbit_value_max; ++i) { 247 | this->midbit_windows.emplace_back(this->midbit_value_max - 1, this->midbit_value_max); 248 | } 249 | 250 | for (size_t i = 0; i < 4; ++i) { 251 | this->decoded_windows.emplace_back(this->decoded_value_max - 1, (uint32_t) params.decoded_count); 252 | } 253 | 254 | for (size_t i = 0; i < 4; ++i) { 255 | for (size_t j = 0; j < 16; ++j) { 256 | this->size_windows.emplace_back(64, params.sizes_count[3 - i]); 257 | } 258 | } 259 | this->size_windows.emplace_back(64, params.sizes_count[0]); 260 | } 261 | 262 | uint32_t dictionary::decompress_block(decoder& dec, uint8_t* dbuf) { 263 | auto d1 = this->size_windows[this->backref_size].try_decode(dec); 264 | 265 | if (d1.first) 266 | d1.second = (*d1.first = dec.decode_and_commit(65)); 267 | this->backref_size = d1.second; 268 | 269 | if (this->backref_size > 0) { 270 | static uint32_t const sizes[] = { 128u, 192u, 256u, 512u }; 271 | 272 | auto backref_size = this->backref_size < 61u ? this->backref_size + 1 : sizes[this->backref_size - 61u]; 273 | auto backref_range = std::min(this->backref_value_max, this->decoded_size); 274 | 275 | auto d3 = this->lowbit_window.try_decode(dec); 276 | if (d3.first) 277 | d3.second = (*d3.first = dec.decode_and_commit(this->lowbit_value_max)); 278 | 279 | auto d4 = this->highbit_window.try_decode(dec); 280 | if (d4.first) 281 | d4.second = (*d4.first = dec.decode_and_commit(backref_range / 1024u + 1)); 282 | 283 | auto d5 = this->midbit_windows[d4.second].try_decode(dec); 284 | if (d5.first) 285 | d5.second = (*d5.first = dec.decode_and_commit(std::min(backref_range / 4 + 1, 256u))); 286 | 287 | auto backref_offset = ((d4.second << 10) + (d5.second << 2) + d3.second + 1); 288 | 289 | this->decoded_size += backref_size; 290 | std::memmove(dbuf, dbuf - backref_offset, backref_size); 291 | 292 | return backref_size; 293 | } else { 294 | auto i = (uintptr_t) dbuf % 4; 295 | auto d2 = this->decoded_windows[i].try_decode(dec); 296 | if (d2.first) 297 | d2.second = (*d2.first = dec.decode_and_commit(this->decoded_value_max)); 298 | 299 | dbuf[0] = d2.second & 0xff; 300 | this->decoded_size++; 301 | 302 | return 1; 303 | } 304 | } 305 | 306 | } // namespace 307 | 308 | void decompress(uint32_t csize, uint8_t* cbuf, uint32_t a4, uint32_t a5, uint32_t dsize, uint8_t* dbuf) { 309 | std::memset(cbuf + csize, 0, (4 - csize) % 4); 310 | 311 | parameters params[3] = {}; 312 | std::memcpy(params, cbuf, sizeof(params)); 313 | 314 | decoder dec = decoder(cbuf + sizeof(params)); 315 | uint32_t steps[] = { a4, a5, dsize }; 316 | uint8_t* dptr = dbuf; 317 | 318 | for (uint32_t i = 0; i < 3; ++i) { 319 | auto dic = std::make_unique< dictionary >(params[i]); 320 | 321 | while (dptr < dbuf + steps[i]) { 322 | dptr += dic->decompress_block(dec, dptr); 323 | } 324 | } 325 | } 326 | 327 | } // namespace gr2 328 | 329 | int main() { 330 | auto cbuf = (uint8_t*) aligned_alloc(4, sizeof(gr2::cdata) + 4); 331 | std::memcpy(cbuf, gr2::cdata, sizeof(gr2::cdata)); 332 | 333 | auto dbuf = (uint8_t*) aligned_alloc(4, sizeof(gr2::ddata)); 334 | std::memset(dbuf, 0, sizeof(gr2::ddata)); 335 | 336 | auto ebuf = (uint8_t*) aligned_alloc(4, sizeof(gr2::ddata)); 337 | std::memcpy(ebuf, gr2::ddata, sizeof(gr2::ddata)); 338 | 339 | gr2::decompress(sizeof(gr2::cdata), cbuf, gr2::pdata[0], gr2::pdata[1], sizeof(gr2::ddata), dbuf); 340 | 341 | assert(std::memcmp(dbuf, ebuf, sizeof(gr2::ddata)) == 0); 342 | 343 | std::free(cbuf); 344 | std::free(dbuf); 345 | std::free(ebuf); 346 | } 347 | -------------------------------------------------------------------------------- /neverwinter-nights-2/mdb.bt: -------------------------------------------------------------------------------- 1 | LittleEndian(); 2 | 3 | enum Magic { NWN2 = 0x324E574E }; 4 | 5 | struct PacketRef { 6 | char fourcc[4]; 7 | uint32 offset; 8 | }; 9 | 10 | struct PacketHead { 11 | char fourcc[4]; 12 | uint32 size; 13 | }; 14 | 15 | struct Triangle { 16 | uint16 indices[3]; 17 | }; 18 | 19 | struct Material { 20 | char map_diffuse[32]; 21 | char map_normal[32]; 22 | char map_tint[32]; 23 | char map_glow[32]; 24 | float color_diffuse[3]; 25 | float color_specular[3]; 26 | float specular_power; 27 | float specular_value; 28 | struct { 29 | uint32 alpha_test : 1; 30 | uint32 alpha_blending : 1; 31 | uint32 additive_blending : 1; 32 | uint32 environment_mapping : 1; 33 | uint32 cutscene_mesh : 1; 34 | uint32 glow_mapping : 1; 35 | uint32 doesnt_cast_shadows : 1; 36 | uint32 projected_texture : 1; 37 | uint32 : 24; 38 | } flags; 39 | }; 40 | 41 | struct SkinVertex { 42 | float position[3]; 43 | float normal[3]; 44 | float bone_weights[4]; 45 | byte bone_indices[4]; 46 | float tangent[3]; 47 | float binormal[3]; 48 | float uvw[3]; 49 | float bone_count; 50 | }; 51 | 52 | struct RigdVertex { 53 | float position[3]; 54 | float normal[3]; 55 | float tangent[3]; 56 | float binormal[3]; 57 | float uvw[3]; 58 | }; 59 | 60 | struct ColVertex { 61 | float position[3]; 62 | float normal[3]; 63 | float uvw[3]; 64 | }; 65 | 66 | struct ColSphere { 67 | uint32 bone_index; 68 | float radius; 69 | }; 70 | 71 | struct WalkVertex { 72 | float position[3]; 73 | }; 74 | 75 | struct WalkTriangle { 76 | uint16 indices[3]; 77 | struct { 78 | uint32 walkable : 1; 79 | uint32 unknown : 2; 80 | uint32 dirt : 1; 81 | uint32 grass : 1; 82 | uint32 stone : 1; 83 | uint32 wood : 1; 84 | uint32 carpet : 1; 85 | uint32 metal : 1; 86 | uint32 swamp : 1; 87 | uint32 mud : 1; 88 | uint32 leaves : 1; 89 | uint32 water : 1; 90 | uint32 puddles : 1; 91 | uint32 padding : 18; 92 | } type; 93 | }; 94 | 95 | enum HairType { 96 | HAIR_LOW =0, 97 | HAIR_SHORT =1, 98 | HAIR_PONYTAIL=2, 99 | }; 100 | 101 | enum HelmType { 102 | HELM_NONE_HIDDEN =0, 103 | HELM_HAIR_HIDDEN =1, 104 | HELM_PARTIAL_HAIR=2, 105 | HELM_HEAD_HIDDEN =3, 106 | }; 107 | 108 | struct { 109 | Magic magic; 110 | uint16 major; 111 | uint16 minor; 112 | uint32 count; 113 | PacketRef reference[count]; 114 | } header ; 115 | 116 | local int32 i; 117 | for (i = 0; i < count; ++i) { 118 | FSeek(reference[i].offset); 119 | 120 | struct { 121 | PacketHead header; 122 | 123 | switch (header.fourcc) { 124 | case "SKIN": 125 | char name[32]; 126 | char skeleton[32]; 127 | Material material; 128 | uint32 vertex_count; 129 | uint32 faces_count; 130 | SkinVertex vertex[vertex_count]; 131 | Triangle faces[faces_count]; 132 | break; 133 | 134 | case "RIGD": 135 | char name[32]; 136 | Material material; 137 | uint32 vertex_count; 138 | uint32 faces_count; 139 | RigdVertex vertex[vertex_count]; 140 | Triangle faces[faces_count]; 141 | break; 142 | 143 | case "COL2": 144 | case "COL3": 145 | char name[32]; 146 | Material material; 147 | uint32 vertex_count; 148 | uint32 faces_count; 149 | ColVertex vertex[vertex_count]; 150 | Triangle faces[faces_count]; 151 | break; 152 | 153 | case "COLS": 154 | uint32 count; 155 | ColSphere spheres[count]; 156 | break; 157 | 158 | case "WALK": 159 | char name[32]; 160 | uint32 unknown; 161 | uint32 vertex_count; 162 | uint32 faces_count; 163 | WalkVertex vertex[vertex_count]; 164 | WalkTriangle faces[faces_count]; 165 | break; 166 | 167 | case "HOOK": 168 | char name[32]; 169 | uint16 type; 170 | uint16 size; 171 | float position[3]; 172 | float orientation[9]; 173 | break; 174 | 175 | case "HAIR": 176 | char name[32]; 177 | HairType type; 178 | float position[3]; 179 | float orientation[9]; 180 | break; 181 | 182 | case "HELM": 183 | char name[32]; 184 | HelmType type; 185 | float position[3]; 186 | float orientation[9]; 187 | break; 188 | } 189 | } packet ; 190 | } 191 | -------------------------------------------------------------------------------- /neverwinter-nights-2/nwn-gr2-raw.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | import sys 4 | 5 | from construct import * 6 | 7 | HexInt = lambda o: ExprAdapter(o, encoder=lambda o,c: o, decoder=lambda o,c: ("{:0x}").format(o)) 8 | PosProbe = lambda n: Probe(n, show_stream=True, show_context=False, show_stack=False, stream_lookahead=100) 9 | 10 | StringEntry = lambda n: Struct(n, ULInt32("offset"), Pointer(lambda ctx: ctx.offset, CString("value"))) 11 | StringRef = lambda n: Struct(n, 12 | ULInt32("offset"), 13 | Anchor("default"), 14 | Pointer(lambda ctx: ctx.offset if ctx.offset > 0 else ctx.default, 15 | StringEntry(n), 16 | ), 17 | ) 18 | 19 | Gr2Raw = Struct("file", 20 | ULInt32("version0"), 21 | ULInt32("version1"), 22 | ULInt32("file_name_offset"), 23 | Pointer(lambda ctx: ctx.file_name_offset, CString("file_name")), 24 | HexInt(ULInt32("u00-0")), 25 | HexInt(ULInt32("u00-1")), 26 | HexInt(ULInt32("u01-0")), 27 | HexInt(ULInt32("u01-1")), 28 | HexInt(ULInt32("u02-0")), 29 | HexInt(ULInt32("u02-1")), 30 | HexInt(ULInt32("u03-0")), 31 | HexInt(ULInt32("u03-1")), 32 | HexInt(ULInt32("u04-0")), 33 | HexInt(ULInt32("u04-1")), 34 | HexInt(ULInt32("u05-0")), 35 | HexInt(ULInt32("u05-1")), 36 | HexInt(ULInt32("u06-0")), 37 | HexInt(ULInt32("u06-1")), 38 | HexInt(ULInt32("u07-0")), 39 | HexInt(ULInt32("u07-1")), 40 | HexInt(ULInt32("u08-0")), 41 | HexInt(ULInt32("u08-1")), 42 | HexInt(ULInt32("u09-0")), 43 | 44 | ULInt32("creator_name_offset_offset"), 45 | StringEntry("creator_name"), 46 | Magic("\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc8\x42\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x3f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x3f\x00\x00\x00\x00\x00\x00\x80\xbf"), 47 | ULInt32("exporter_name_offset_offset"), 48 | StringEntry("exporter_name"), 49 | Magic("\x02\x00\x00\x00\x06\x00\x00\x00\x00\x00\x00\x00\n\x00\x00\x00"), 50 | 51 | ULInt32("name_offset_offset"), 52 | Pointer(lambda ctx: ctx.name_offset_offset, 53 | Struct("listhead", 54 | StringEntry("name"), 55 | ULInt32("count"), 56 | ULInt32("offset_offset"), 57 | StringEntry("name2"), 58 | ), 59 | ), 60 | 61 | Pointer(lambda ctx: 0xb4, 62 | Struct("list", 63 | )), 64 | 65 | PosProbe("probe"), 66 | ) 67 | 68 | with open(sys.argv[1], 'rb') as stream: 69 | print >>sys.stderr, sys.argv[1] 70 | raw = Gr2Raw.parse_stream(stream) 71 | print raw 72 | -------------------------------------------------------------------------------- /neverwinter-nights-2/nwn-gr2.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | import sys 4 | 5 | from construct import * 6 | 7 | HexInt = lambda o: ExprAdapter(o, encoder=lambda o,c: o, decoder=lambda o,c: ("{:0x}").format(o)) 8 | PosProbe = lambda n: Probe(n, show_stream=True, show_context=False, show_stack=False, stream_lookahead=100) 9 | 10 | Gr2 = Struct("file", 11 | Magic("\xb8\x67\xb0\xca\xf8\x6d\xb1\x0f\x84\x72\x8c\x7e\x5e\x19\x00\x1e"), 12 | ULInt32("flags"), # b8 01 00 00 : unprocessed 13 | # 60 01 00 00 : processed 14 | Bytes("u0", 16), 15 | ULInt32("file_size"), 16 | HexInt(ULInt32("u1")), 17 | HexInt(ULInt32("u2")), # 38 00 00 00 18 | PosProbe("probe"), 19 | ) 20 | 21 | with open(sys.argv[1], 'rb') as stream: 22 | print sys.argv[1] 23 | gr2 = Gr2.parse_stream(stream) 24 | print gr2 25 | -------------------------------------------------------------------------------- /neverwinter-nights/gff.bt: -------------------------------------------------------------------------------- 1 | LittleEndian(); 2 | 3 | struct { 4 | char type[4]; 5 | char version[4]; 6 | uint32 structs_offset; 7 | uint32 structs_count; 8 | uint32 fields_offset; 9 | uint32 fields_count; 10 | uint32 labels_offset; 11 | uint32 labels_count; 12 | uint32 field_data_offset; 13 | uint32 field_data_size; 14 | uint32 field_indices_offset; 15 | uint32 field_indices_size; 16 | uint32 list_indices_offset; 17 | uint32 list_indices_size; 18 | } header ; 19 | 20 | FSeek(header.structs_offset); 21 | struct { 22 | uint32 type; 23 | uint32 index_or_offset; 24 | uint32 count; 25 | } structs[header.structs_count] ; 26 | 27 | FSeek(header.fields_offset); 28 | struct { 29 | enum { 30 | uint8_ = 0, 31 | int8_ = 1, 32 | uint16_ = 2, 33 | int16_ = 3, 34 | uint32_ = 4, 35 | int32_ = 5, 36 | uint64_ = 6, 37 | int64_ = 7, 38 | float32_ = 8, 39 | float64_ = 9, 40 | string_ = 10, 41 | resref_ = 11, 42 | loc_string_ = 12, 43 | void_ = 13, 44 | struct_ = 14, 45 | list_ = 15, 46 | } type; 47 | uint32 label_index; 48 | uint32 data_or_offset; 49 | } fields[header.fields_count] ; 50 | 51 | FSeek(header.labels_offset); 52 | struct { 53 | char value[16]; 54 | } labels[header.labels_count] ; 55 | 56 | FSeek(header.field_indices_offset); 57 | uint32 field_indices[header.field_indices_size / 4] ; 58 | 59 | FSeek(header.list_indices_offset); 60 | uint32 list_indices[header.list_indices_size / 4] ; 61 | 62 | 63 | -------------------------------------------------------------------------------- /primordia/adventure-game-studio-clib.bt: -------------------------------------------------------------------------------- 1 | #include "../common.bt" 2 | 3 | LittleEndian(); 4 | 5 | typedef struct (uint32 size, char base) { 6 | local uint32 size = size; 7 | local char base = base; 8 | char data[size]; 9 | } RotString ; 10 | 11 | string ReadRotString(RotString& value) { 12 | string out; 13 | local uint32 i; 14 | for (i = 0; i < value.size && value.data[i]; ++i) 15 | out += value.data[i] - value.base; 16 | return out; 17 | } 18 | 19 | ubyte GetNextRandom(uint32& rand_val) 20 | { 21 | return (((rand_val = rand_val * 214013 + 2531011) >> 16) & 0x7fff) & 0xff; 22 | } 23 | 24 | typedef struct (uint32& base, uint32 size) { 25 | local uint32 size = size; 26 | local ubyte offs[size]; 27 | local uint32 i = 0; 28 | for (i = 0; i < size; ++i) 29 | offs[i] = GetNextRandom(base); 30 | 31 | ubyte data[size]; 32 | local ubyte decrypted[size]; 33 | } RandomizedData; 34 | 35 | void DecryptRandomizedData(RandomizedData& value) { 36 | local uint32 i; 37 | for (i = 0; i < value.size; ++i) 38 | value.decrypted[i] = value.data[i] - value.offs[i]; 39 | } 40 | 41 | typedef struct (uint32& base) { 42 | RandomizedData data(base, 1); 43 | } RandUInt8 ; 44 | 45 | ubyte DecryptRandUInt8(RandUInt8& value) { 46 | DecryptRandomizedData(value.data); 47 | 48 | local ubyte v = 0; 49 | local uint32 i; 50 | for (i = 0; i < 1; ++i) 51 | v = (v << 8) + value.data.decrypted[i]; 52 | 53 | return v; 54 | } 55 | 56 | string ReadRandUInt8(RandUInt8& value) { 57 | string out; 58 | SPrintf(out, "%d", DecryptRandUInt8(value)); 59 | return out; 60 | } 61 | 62 | typedef struct (uint32& base) { 63 | RandomizedData data(base, 4); 64 | } RandUInt32 ; 65 | 66 | uint32 DecryptRandUInt32(RandUInt32& value) { 67 | DecryptRandomizedData(value.data); 68 | 69 | local uint32 v = 0; 70 | local uint32 i; 71 | for (i = 0; i < 4; ++i) 72 | v = (v << 8) + value.data.decrypted[3-i]; 73 | 74 | return v; 75 | } 76 | 77 | string ReadRandUInt32(RandUInt32& value) { 78 | string out; 79 | SPrintf(out, "%d", DecryptRandUInt32(value)); 80 | return out; 81 | } 82 | 83 | typedef struct (uint32& base, uint32 max_size) { 84 | local ubyte offs[max_size]; 85 | local uint32 i = 0; 86 | do { 87 | offs[i++] = GetNextRandom(base); 88 | ubyte data; 89 | } while (data - offs[i - 1] > 0); 90 | local uint32 size = i; 91 | 92 | local ubyte decrypted[size]; 93 | } RandString ; 94 | 95 | string ReadRandString(RandString& value) { 96 | local uint32 i; 97 | for (i = 0; i < value.size; ++i) 98 | value.decrypted[i] = value.data[i] - value.offs[i]; 99 | 100 | string out; 101 | SPrintf(out, "%s", value.decrypted); 102 | return out; 103 | } 104 | 105 | struct Header { 106 | Magic magic(5, "CLIB\x1a"); 107 | byte version; 108 | 109 | if (version >= 10) { 110 | Magic number(1, "\x00"); 111 | 112 | if (version >= 21) { 113 | uint32 rand_seed; 114 | local uint32 rand_value = rand_seed + 9338638; 115 | 116 | RandUInt32 clib_count(rand_value); 117 | RandString clib_name(rand_value, 50)[DecryptRandUInt32(clib_count)] ; 118 | RandUInt32 file_count(rand_value); 119 | RandString file_name(rand_value, 50)[DecryptRandUInt32(file_count)] ; 120 | RandUInt32 file_offs(rand_value)[DecryptRandUInt32(file_count)] ; 121 | RandUInt32 file_size(rand_value)[DecryptRandUInt32(file_count)] ; 122 | RandUInt8 file_uuid(rand_value)[DecryptRandUInt32(file_count)] ; 123 | } else if (version >= 20) { 124 | } else { 125 | } 126 | } else { 127 | byte method; 128 | byte unused; 129 | uint16 file_count; 130 | char password[13]; 131 | 132 | RotString file_name(13, method)[file_count] ; 133 | uint32 file_size[file_count]; 134 | byte file_flag[file_count]; 135 | byte file_ratio[file_count]; 136 | } 137 | }; 138 | 139 | struct Footer { 140 | uint32 offset; 141 | Magic magic(12, "CLIB\x01\x02\x03\x04SIGE"); 142 | }; 143 | 144 | if (ReadString(0, 5) != "CLIB\x1a") { 145 | FSeek(FileSize() - 16); 146 | Footer footer; 147 | FSeek(footer.offset); 148 | } 149 | 150 | Header header; 151 | -------------------------------------------------------------------------------- /primordia/primordia-decrypt.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/berenm/game-data-reverse-engineering/4f217459c180a0331734af9a06adc8b285ae0cb8/primordia/primordia-decrypt.cpp -------------------------------------------------------------------------------- /python/arcanum.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | import os 4 | import sys 5 | import zlib 6 | 7 | 8 | sys.path.append('construct') 9 | from format.arcanum import * 10 | 11 | class DatFile: 12 | def __init__(self, filename): 13 | self.__filename = filename 14 | self.__file = open(filename, 'rb') 15 | self.__dict__.update(Dat.parse_stream(self.__file).__dict__) 16 | 17 | 18 | def unpack(self, target): 19 | for i,f in enumerate(self.index.file): 20 | targetfile = os.path.join(target, *f.name.split('\\')).lower() 21 | targetdir = os.path.dirname(targetfile).lower() 22 | 23 | print 'Extracting %s...' % targetfile 24 | 25 | if not os.path.exists(targetdir): 26 | os.makedirs(targetdir) 27 | 28 | if f.flags == 'FOLDER': 29 | if not os.path.exists(targetfile): 30 | os.makedirs(targetfile) 31 | elif f.flags == 'NONE': 32 | with open(targetfile, 'wb') as o: 33 | o.write(f.contents.value) 34 | else: 35 | with open(targetfile, 'wb') as o: 36 | o.write(zlib.decompress(f.contents.value)) 37 | 38 | 39 | def list(self): 40 | for i,f in enumerate(self.index.file): 41 | print os.path.join(*f.name.split('\\')) 42 | 43 | 44 | if __name__ == '__main__': 45 | if len(sys.argv) < 2: 46 | print """usage: 47 | - arcanum list 48 | - arcanum unpack 49 | """ 50 | 51 | else: 52 | if sys.argv[1] == 'list': 53 | DatFile(sys.argv[2]).list() 54 | 55 | elif sys.argv[1] == 'unpack': 56 | DatFile(sys.argv[2]).unpack(sys.argv[3] if len(sys.argv) > 3 else os.path.basename(sys.argv[2])) 57 | -------------------------------------------------------------------------------- /python/fallout.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | import os 4 | import sys 5 | 6 | import lzss 7 | 8 | sys.path.append('construct') 9 | from format.fallout import * 10 | 11 | class DatFile: 12 | def __init__(self, filename): 13 | self.__filename = filename 14 | self.__file = open(filename, 'rb') 15 | self.__dict__.update(Dat.parse_stream(self.__file).__dict__) 16 | 17 | 18 | def unpack(self, target): 19 | for i,d in enumerate(self.folder): 20 | d = os.path.join(*d.split('\\')) 21 | 22 | for j,f in enumerate(self.filelist[i].file): 23 | targetfile = os.path.join(target, d, f.name).lower() 24 | targetdir = os.path.d(targetfile).lower() 25 | 26 | print 'Extracting %s...' % targetfile 27 | 28 | if not os.path.exists(targetdir): 29 | os.makedirs(targetdir) 30 | 31 | if f.flags == 'NONE': 32 | with open(targetfile, 'wb') as o: 33 | o.write(f.contents.value) 34 | else: 35 | with open(targetfile, 'wb') as o: 36 | lzss2.decompress_string(f.contents.value, o) 37 | 38 | 39 | def list(self): 40 | for i,d in enumerate(self.folder): 41 | d = os.path.join(*d.split('\\')) 42 | 43 | for j,filename in enumerate([ f.name for f in self.filelist[i].file ]): 44 | print os.path.join(d, filename) 45 | 46 | 47 | if __name__ == '__main__': 48 | if len(sys.argv) < 2: 49 | print """usage: 50 | - fallout-dat list 51 | - fallout-dat unpack 52 | """ 53 | 54 | else: 55 | if sys.argv[1] == 'list': 56 | DatFile(sys.argv[2]).list() 57 | 58 | elif sys.argv[1] == 'unpack': 59 | DatFile(sys.argv[2]).unpack(sys.argv[3] if len(sys.argv) > 3 else os.path.basename(sys.argv[2])) 60 | -------------------------------------------------------------------------------- /python/fallout2.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | import os 4 | import sys 5 | import zlib 6 | 7 | 8 | sys.path.append('construct') 9 | from format.fallout2 import * 10 | 11 | class DatFile: 12 | def __init__(self, filename): 13 | self.__filename = filename 14 | self.__file = open(filename, 'rb') 15 | self.__dict__.update(Dat.parse_stream(self.__file).__dict__) 16 | 17 | 18 | def unpack(self, target): 19 | for i,f in enumerate(self.index.file): 20 | targetfile = os.path.join(target, *f.name.split('\\')).lower() 21 | targetdir = os.path.dirname(targetfile).lower() 22 | 23 | print 'Extracting %s...' % targetfile 24 | 25 | if not os.path.exists(targetdir): 26 | os.makedirs(targetdir) 27 | 28 | if f.flags == 'NONE': 29 | with open(targetfile, 'wb') as o: 30 | o.write(f.contents.value) 31 | else: 32 | with open(targetfile, 'wb') as o: 33 | o.write(zlib.decompress(f.contents.value)) 34 | 35 | 36 | def list(self): 37 | for i,f in enumerate(self.index.file): 38 | print os.path.join(*f.name.split('\\')) 39 | 40 | 41 | if __name__ == '__main__': 42 | if len(sys.argv) < 2: 43 | print """usage: 44 | - fallout-dat list 45 | - fallout-dat unpack 46 | """ 47 | 48 | else: 49 | if sys.argv[1] == 'list': 50 | DatFile(sys.argv[2]).list() 51 | 52 | elif sys.argv[1] == 'unpack': 53 | DatFile(sys.argv[2]).unpack(sys.argv[3] if len(sys.argv) > 3 else os.path.basename(sys.argv[2])) 54 | -------------------------------------------------------------------------------- /python/format/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/berenm/game-data-reverse-engineering/4f217459c180a0331734af9a06adc8b285ae0cb8/python/format/__init__.py -------------------------------------------------------------------------------- /python/format/arcanum.py: -------------------------------------------------------------------------------- 1 | from construct import * 2 | 3 | Dat = Struct("file", 4 | Pointer(lambda ctx: -28, 5 | Struct("footer", 6 | Bytes("uuid", 16), 7 | Magic("1TAD"), 8 | ULInt32("filenames_size"), 9 | ULInt32("index_size") 10 | ) 11 | ), 12 | Pointer(lambda ctx: -ctx.footer.index_size, 13 | Struct("index", 14 | ULInt32("count"), 15 | Array(lambda ctx: ctx.count, 16 | Struct("file", 17 | ULInt32("length"), 18 | CString("name"), 19 | Padding(lambda ctx: ctx.length - len(ctx.name) - 1), 20 | ULInt32("name_address"), 21 | Enum(ULInt32("flags"), NONE = 1, ZLIB = 2, FOLDER = 1024), 22 | ULInt32("unpacked_size"), 23 | ULInt32("packed_size"), 24 | ULInt32("offset"), 25 | 26 | OnDemand(Pointer(lambda ctx: ctx.offset, Bytes("contents", lambda ctx: ctx.packed_size if ctx.flags == 'ZLIB' else ctx.packed_size))), 27 | ) 28 | ) 29 | ) 30 | ) 31 | ) 32 | -------------------------------------------------------------------------------- /python/format/fallout.py: -------------------------------------------------------------------------------- 1 | from construct import * 2 | 3 | Dat = Struct("file", 4 | Struct("header", 5 | UBInt32("folder_count"), 6 | UBInt32("unknown_1"), 7 | UBInt32("unknown_2"), 8 | UBInt32("timestamp") 9 | ), 10 | 11 | Array(lambda ctx: ctx.header.folder_count, 12 | PascalString("folder", length_field=UBInt8("length")) 13 | ), 14 | 15 | Array(lambda ctx: ctx.header.folder_count, 16 | Struct("filelist", 17 | UBInt32("count"), 18 | UBInt32("unknown"), 19 | UBInt32("flags"), 20 | UBInt32("timestamp"), 21 | 22 | Array(lambda ctx: ctx.count, 23 | Struct("file", 24 | PascalString("name", length_field=UBInt8("length")), 25 | Enum(UBInt32("flags"), NONE = 32, LZSS = 64), 26 | UBInt32("offset"), 27 | UBInt32("unpacked_size"), 28 | UBInt32("packed_size"), 29 | 30 | OnDemand(Pointer(lambda ctx: ctx.offset, Bytes("contents", lambda ctx: ctx.packed_size if ctx.flags == 'LZSS' else ctx.unpacked_size))), 31 | ) 32 | ) 33 | ) 34 | ) 35 | ) 36 | -------------------------------------------------------------------------------- /python/format/fallout2.py: -------------------------------------------------------------------------------- 1 | from construct import * 2 | 3 | Dat = Struct("file", 4 | Pointer(lambda ctx: -8, 5 | Struct("footer", 6 | ULInt32("index_size"), 7 | ULInt32("file_size") 8 | ) 9 | ), 10 | Pointer(lambda ctx: -8 - ctx.footer.index_size, 11 | Struct("index", 12 | ULInt32("count"), 13 | Array(lambda ctx: ctx.count, 14 | Struct("file", 15 | PascalString("name", length_field=ULInt32("length")), 16 | Enum(ULInt8("flags"), NONE = 0, ZLIB = 1), 17 | ULInt32("unpacked_size"), 18 | ULInt32("packed_size"), 19 | ULInt32("offset"), 20 | 21 | OnDemand(Pointer(lambda ctx: ctx.offset, Bytes("contents", lambda ctx: ctx.unpacked_size if ctx.flags == 'NONE' else ctx.packed_size))), 22 | ) 23 | ) 24 | ) 25 | ) 26 | ) 27 | -------------------------------------------------------------------------------- /python/format/neverwinter_nights.py: -------------------------------------------------------------------------------- 1 | from construct import * 2 | 3 | Extension = { 4 | 1: 'bmp', 5 | 3: 'tga', 6 | 4: 'wav', 7 | 6: 'plt', 8 | 7: 'ini', 9 | 10: 'txt', 10 | 2002: 'mdl', 11 | 2009: 'nss', 12 | 2010: 'ncs', 13 | 2012: 'are', 14 | 2013: 'set', 15 | 2014: 'ifo', 16 | 2015: 'bic', 17 | 2016: 'wok', 18 | 2017: '2da', 19 | 2022: 'txi', 20 | 2023: 'git', 21 | 2025: 'uti', 22 | 2027: 'utc', 23 | 2029: 'dlg', 24 | 2030: 'itp', 25 | 2032: 'utt', 26 | 2033: 'dds', 27 | 2035: 'uts', 28 | 2036: 'ltr', 29 | 2037: 'gff', 30 | 2038: 'fac', 31 | 2040: 'ute', 32 | 2042: 'utd', 33 | 2044: 'utp', 34 | 2045: 'dft', 35 | 2046: 'gic', 36 | 2047: 'gui', 37 | 2051: 'utm', 38 | 2052: 'dwk', 39 | 2053: 'pwk', 40 | 2056: 'jrl', 41 | 2058: 'utw', 42 | 2060: 'ssf', 43 | 2064: 'ndb', 44 | 2065: 'ptm', 45 | 2066: 'ptt', 46 | } 47 | 48 | ContentType = { 49 | 1: 'binary', 50 | 3: 'binary', 51 | 4: 'binary', 52 | 6: 'binary', 53 | 7: 'ini', 54 | 10: 'text', 55 | 2002: 'mdl', 56 | 2009: 'text', 57 | 2010: 'binary', 58 | 2012: 'gff', 59 | 2013: 'ini', 60 | 2014: 'gff', 61 | 2015: 'gff', 62 | 2016: 'mdl', 63 | 2017: 'text', 64 | 2022: 'text', 65 | 2023: 'gff', 66 | 2025: 'gff', 67 | 2027: 'gff', 68 | 2029: 'gff', 69 | 2030: 'gff', 70 | 2032: 'gff', 71 | 2033: 'binary', 72 | 2035: 'gff', 73 | 2036: 'binary', 74 | 2037: 'gff', 75 | 2038: 'gff', 76 | 2040: 'gff', 77 | 2042: 'gff', 78 | 2044: 'gff', 79 | 2045: 'ini', 80 | 2046: 'gff', 81 | 2047: 'gff', 82 | 2051: 'gff', 83 | 2052: 'mdl', 84 | 2053: 'mdl', 85 | 2056: 'gff', 86 | 2058: 'gff', 87 | 2060: 'binary', 88 | 2064: 'binary', 89 | 2065: 'gff', 90 | 2066: 'gff', 91 | } 92 | 93 | Key = Struct("file", 94 | Struct("header", 95 | Magic("KEY "), 96 | Magic("V1 "), 97 | ULInt32("bif_count"), 98 | ULInt32("res_count"), 99 | ULInt32("bif_table_offset"), 100 | ULInt32("res_table_offset"), 101 | ULInt32("build_year"), 102 | ULInt32("build_day"), 103 | Bytes("reserved", 32), 104 | ), 105 | Pointer(lambda ctx: ctx.header.bif_table_offset, 106 | Array(lambda ctx: ctx.header.bif_count, 107 | Struct("bif", 108 | ULInt32("size"), 109 | ULInt32("filename_offset"), 110 | ULInt16("filename_size"), 111 | Pointer(lambda ctx: ctx.filename_offset, 112 | String("filename", lambda ctx: ctx.filename_size, padchar='\x00') 113 | ), 114 | ULInt16("drives"), 115 | ), 116 | ), 117 | ), 118 | Pointer(lambda ctx: ctx.header.res_table_offset, 119 | Array(lambda ctx: ctx.header.res_count, 120 | Struct("res", 121 | String("name", 16, padchar='\x00'), 122 | ULInt16("type"), 123 | ULInt32("id"), 124 | ), 125 | ), 126 | ), 127 | ) 128 | 129 | Biff = Struct("file", 130 | Struct("header", 131 | Magic("BIFF"), 132 | Magic("V1 "), 133 | ULInt32("variable_resource_count"), 134 | ULInt32("fixed_resource_count"), 135 | ULInt32("variable_table_offset"), 136 | ), 137 | Padding(lambda ctx: ctx.header.variable_table_offset - 20), 138 | Array(lambda ctx: ctx.header.variable_resource_count, 139 | Struct("variable_resource_entry", 140 | ULInt32("id"), 141 | ULInt32("offset"), 142 | ULInt32("size"), 143 | ULInt32("type"), 144 | OnDemand(Pointer(lambda ctx: ctx.offset, Bytes("contents", lambda ctx: ctx.size))), 145 | ), 146 | ), 147 | Array(lambda ctx: ctx.header.fixed_resource_count, 148 | Struct("fixed_resource_count", 149 | ULInt32("id"), 150 | ULInt32("offset"), 151 | ULInt32("part_count"), 152 | ULInt32("size"), 153 | ULInt32("type"), 154 | OnDemand(Pointer(lambda ctx: ctx.offset, Bytes("contents", lambda ctx: ctx.size))), 155 | ), 156 | ), 157 | ) 158 | -------------------------------------------------------------------------------- /python/lzss/__init__.py: -------------------------------------------------------------------------------- 1 | from lzss import * 2 | -------------------------------------------------------------------------------- /python/lzss/lzss.pyx: -------------------------------------------------------------------------------- 1 | import struct 2 | 3 | cdef int c_decompress_block(bytes ibuf, int ipos, int iend, bytes obuf, int opos, int oend): 4 | cdef int minlen = 3 5 | cdef int maxlen = 18 6 | cdef int dlen = 4096 7 | 8 | dictionary = ' ' * dlen 9 | 10 | cdef int doff = 0 11 | cdef int dpos = dlen - maxlen 12 | cdef bytes dbuf = dictionary 13 | 14 | cdef int flags = 0 15 | while ipos < iend: 16 | flags = flags >> 1 17 | 18 | if flags & 0x100 == 0: 19 | if ipos == iend: 20 | break 21 | 22 | flags = ord(ibuf[ipos]) 23 | flags = flags | 0xFF00 24 | ipos = ipos + 1 25 | 26 | 27 | if flags & 1: 28 | if ipos == iend: 29 | break 30 | 31 | if opos == oend: 32 | return -1 33 | 34 | dpos = dpos % dlen 35 | 36 | obuf[opos] = ibuf[ipos] 37 | dbuf[dpos] = ibuf[ipos] 38 | ipos = ipos + 1 39 | opos = opos + 1 40 | dpos = dpos + 1 41 | 42 | else: 43 | if ipos >= iend - 1: 44 | break 45 | 46 | doff = ord(ibuf[ipos]) 47 | ipos = ipos + 1 48 | 49 | length = ord(ibuf[ipos]) 50 | ipos = ipos + 1 51 | 52 | doff = doff | ((length & 0xF0) << 4) 53 | length = (length & 0x0F) + minlen 54 | 55 | for i in range(length): 56 | if opos == oend: 57 | return -1 58 | 59 | doff = doff % dlen 60 | dpos = dpos % dlen 61 | 62 | obuf[opos] = dbuf[doff] 63 | dbuf[dpos] = dbuf[doff] 64 | 65 | doff = doff + 1 66 | opos = opos + 1 67 | dpos = dpos + 1 68 | 69 | return opos 70 | 71 | 72 | def decompress_block(ibuf, ipos, iend): 73 | output = '\0' * (2 << 15) 74 | cdef bytes obuf = output 75 | cdef int olen = -1 76 | 77 | while olen < 0: 78 | olen = c_decompress_block(ibuf, ipos, iend, obuf, 0, len(obuf)) 79 | if olen >= 0: 80 | break 81 | 82 | output = '\0' * (len(obuf) * 3 / 2) 83 | obuf = output 84 | 85 | return ''.join(obuf[:olen]) 86 | 87 | 88 | def decompress_string(input, output): 89 | cdef int ipos = 0 90 | cdef int ilen = len(input) 91 | cdef int npos = 0 92 | cdef int rlen = 0 93 | cdef bytes ibuf = input 94 | 95 | while ipos < ilen: 96 | npos = ipos + 2 97 | rlen = struct.unpack(">h", ibuf[ipos:npos])[0] 98 | ipos = npos 99 | 100 | if rlen == 0: 101 | break 102 | 103 | elif rlen < 0: 104 | npos = ipos - rlen 105 | output.write(ibuf[ipos:npos]) 106 | ipos = npos 107 | 108 | elif rlen > 0: 109 | npos = ipos + rlen 110 | output.write(decompress_block(ibuf, ipos, min(npos, ilen))) 111 | ipos = npos 112 | 113 | return output 114 | -------------------------------------------------------------------------------- /python/lzss/setup.py: -------------------------------------------------------------------------------- 1 | from distutils.core import setup 2 | from distutils.extension import Extension 3 | from Cython.Distutils import build_ext 4 | 5 | setup( 6 | name = 'lzss', 7 | cmdclass = {'build': build_ext}, 8 | ext_modules=[ Extension("lzss", ["lzss.pyx"]) ] 9 | ) 10 | -------------------------------------------------------------------------------- /python/neverwinter_nights.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | import os 4 | import sys 5 | import zlib 6 | 7 | 8 | sys.path.append('construct') 9 | from format.neverwinter_nights import * 10 | 11 | class BiffFile: 12 | def __init__(self, filename): 13 | self.__filename = filename 14 | self.__file = open(filename, 'rb') 15 | self.__dict__.update(Biff.parse_stream(self.__file)) 16 | 17 | 18 | def unpack(self, index, target): 19 | with open(target, 'wb') as o: 20 | o.write(self.variable_resource_entry[index].contents.value) 21 | 22 | 23 | class KeyFile: 24 | def __init__(self, filename): 25 | self.__filename = filename 26 | self.__file = open(filename, 'rb') 27 | self.__dict__.update(Key.parse_stream(self.__file)) 28 | 29 | 30 | def unpack(self, target): 31 | bifs = {} 32 | for i,f in enumerate(self.bif): 33 | bifs[f.filename] = BiffFile(os.path.join(os.path.dirname(self.__filename), *f.filename.split('\\'))) 34 | 35 | for i,f in enumerate(self.res): 36 | bifname = self.bif[f.id >> 20].filename 37 | targetfile = os.path.join(os.path.join(*bifname.split('\\')), f.name) + '.' + Extension.get(f.type, str(f.type)) 38 | targetdir = os.path.dirname(targetfile) 39 | 40 | print 'Extracting %s...' % targetfile 41 | 42 | if not os.path.exists(targetdir): 43 | os.makedirs(targetdir) 44 | 45 | bifs[bifname].unpack(f.id & ((1 << 20) - 1), targetfile) 46 | 47 | 48 | def list(self): 49 | for i,f in enumerate(self.res): 50 | targetfile = os.path.join(os.path.join(*self.bif[f.id >> 20].filename.split('\\')), f.name) + '.' + Extension.get(f.type, str(f.type)) 51 | print targetfile 52 | 53 | 54 | if __name__ == '__main__': 55 | if len(sys.argv) < 2: 56 | print """usage: 57 | - neverwinter-nights list 58 | - neverwinter-nights unpack 59 | """ 60 | 61 | else: 62 | if sys.argv[1] == 'list': 63 | KeyFile(sys.argv[2]).list() 64 | 65 | elif sys.argv[1] == 'unpack': 66 | KeyFile(sys.argv[2]).unpack(sys.argv[3] if len(sys.argv) > 3 else os.path.basename(sys.argv[2])) 67 | -------------------------------------------------------------------------------- /src/undertale-game2po.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | 13 | constexpr static uint32_t operator""_4cc(char const* value, size_t size) { 14 | assert(size == 4); 15 | return (value[0] << 0) | (value[1] << 8) | (value[2] << 16) | 16 | (value[3] << 24); 17 | } 18 | 19 | static uint32_t utf8size(char const* string) { 20 | uint32_t len = 0; 21 | while (*string) 22 | len += (*string++ & 0xc0) != 0x80; 23 | return len; 24 | } 25 | 26 | struct chunk_header { 27 | union { 28 | uint32_t magic; 29 | char magic_str[4]; 30 | }; 31 | uint32_t size; 32 | }; 33 | 34 | struct strg_header { 35 | uint32_t count; 36 | }; 37 | 38 | int main(int argc, char const* argv[]) { 39 | if (argc < 3 || std::find_if(argv, argv + argc, [](auto& a) { 40 | return std::strcmp(a, "--help") == 0 || 41 | std::strcmp(a, "-h") == 0; 42 | }) != argv + argc) 43 | return std::printf("Usage: undertale-game2po \n\n" 44 | " Untranslated game.dat or game.unx\n" 45 | " File containing untranslated strings\n"); 46 | 47 | auto offsets = std::vector{}; 48 | auto strings = std::vector{}; 49 | 50 | auto in = std::ifstream{argv[1], std::ios::binary}; 51 | while (in.good()) { 52 | auto chunk = chunk_header{}; 53 | 54 | in.read(reinterpret_cast(&chunk), sizeof(chunk)); 55 | if (!in.good()) 56 | break; 57 | 58 | switch (chunk.magic) { 59 | case "FORM"_4cc: 60 | break; 61 | case "GEN8"_4cc: 62 | case "OPTN"_4cc: 63 | case "EXTN"_4cc: 64 | case "SOND"_4cc: 65 | case "AGRP"_4cc: 66 | case "SPRT"_4cc: 67 | case "BGND"_4cc: 68 | case "PATH"_4cc: 69 | case "SCPT"_4cc: 70 | case "SHDR"_4cc: 71 | case "FONT"_4cc: 72 | case "TMLN"_4cc: 73 | case "OBJT"_4cc: 74 | case "ROOM"_4cc: 75 | case "DAFL"_4cc: 76 | case "TPAG"_4cc: 77 | case "CODE"_4cc: 78 | case "VARI"_4cc: 79 | case "FUNC"_4cc: 80 | case "TXTR"_4cc: 81 | case "AUDO"_4cc: 82 | in.seekg(chunk.size, std::ios::cur); 83 | break; 84 | case "STRG"_4cc: { 85 | auto next = chunk.size + in.tellg(); 86 | auto strg = strg_header{}; 87 | in.read(reinterpret_cast(&strg), sizeof(strg)); 88 | 89 | offsets.resize(strg.count); 90 | strings.resize(strg.count); 91 | in.read(reinterpret_cast(&offsets[0]), 92 | strg.count * sizeof(offsets[0])); 93 | 94 | for (size_t i = 0; i < strg.count; ++i) { 95 | in.seekg(offsets[i], std::ios::beg); 96 | 97 | uint32_t length = 0; 98 | in.read(reinterpret_cast(&length), sizeof(length)); 99 | 100 | std::getline(in, strings[i], '\0'); 101 | assert(length == utf8size(strings[i].c_str())); 102 | } 103 | 104 | in.seekg(next, std::ios::beg); 105 | break; 106 | } 107 | } 108 | } 109 | 110 | auto out = std::ofstream{argv[2]}; 111 | out << "msgid \"\"\n"; 112 | out << "msgstr \"\"\n"; 113 | out << "\"Project-Id-Version: Undertale\\n\"\n"; 114 | out << "\"Language: en_US\\n\"\n"; 115 | out << "\"MIME-Version: 1.0\\n\"\n"; 116 | out << "\"Content-Type: text/plain; charset=UTF-8\\n\"\n"; 117 | out << "\"Content-Transfer-Encoding: 8bit\\n\"\n"; 118 | 119 | for (auto& str : strings) { 120 | size_t line = (&str - &strings[0]); 121 | if (line >= 1950 && line <= 2380) 122 | continue; 123 | if (line >= 19340) 124 | break; 125 | 126 | boost::replace_all(str, "\\", "\\\\"); 127 | boost::replace_all(str, "\"", "\\\""); 128 | boost::replace_all(str, "\n", "\\n"); 129 | boost::replace_all(str, "\r", "\\r"); 130 | out << "msgctxt " << line << "\nmsgid \"" << str << "\"\nmsgstr \"" << str 131 | << "\"\n"; 132 | } 133 | 134 | return 0; 135 | } 136 | -------------------------------------------------------------------------------- /src/undertale-po2game.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | 13 | constexpr static uint32_t operator""_4cc(char const* value, size_t size) { 14 | assert(size == 4); 15 | return (value[0] << 0) | (value[1] << 8) | (value[2] << 16) | 16 | (value[3] << 24); 17 | } 18 | 19 | static uint32_t utf8size(char const* string) { 20 | uint32_t len = 0; 21 | while (*string) 22 | len += (*string++ & 0xc0) != 0x80; 23 | return len; 24 | } 25 | 26 | struct chunk_header { 27 | union { 28 | uint32_t magic; 29 | char magic_str[4]; 30 | }; 31 | uint32_t size; 32 | }; 33 | 34 | struct strg_header { 35 | uint32_t count; 36 | }; 37 | 38 | int main(int argc, char const* argv[]) { 39 | if (argc < 4 || std::find_if(argv, argv + argc, [](auto& a) { 40 | return std::strcmp(a, "--help") == 0 || 41 | std::strcmp(a, "-h") == 0; 42 | }) != argv + argc) 43 | return std::printf("Usage: undertale-po2game \n\n" 44 | " File containing translated strings\n" 45 | " Untranslated game.dat or game.unx\n" 46 | " Output translated game data file\n"); 47 | 48 | auto ioffsets = std::vector{}; 49 | auto ooffsets = std::vector{}; 50 | auto strings = std::vector{}; 51 | 52 | auto in = std::ifstream{argv[2], std::ios::binary}; 53 | auto out = std::ofstream{argv[3], std::ios::binary}; 54 | auto buffer = std::vector{}; 55 | 56 | auto end_file = 0; 57 | while (in.good()) { 58 | auto chunk = chunk_header{}; 59 | 60 | in.read(reinterpret_cast(&chunk), sizeof(chunk)); 61 | if (!in.good()) 62 | break; 63 | 64 | switch (chunk.magic) { 65 | case "FORM"_4cc: 66 | out.write(reinterpret_cast(&chunk), sizeof(chunk)); 67 | end_file = chunk.size + 8; 68 | break; 69 | case "GEN8"_4cc: 70 | case "OPTN"_4cc: 71 | case "EXTN"_4cc: 72 | case "SOND"_4cc: 73 | case "AGRP"_4cc: 74 | case "SPRT"_4cc: 75 | case "BGND"_4cc: 76 | case "PATH"_4cc: 77 | case "SCPT"_4cc: 78 | case "SHDR"_4cc: 79 | case "FONT"_4cc: 80 | case "TMLN"_4cc: 81 | case "OBJT"_4cc: 82 | case "ROOM"_4cc: 83 | case "DAFL"_4cc: 84 | case "TPAG"_4cc: 85 | case "CODE"_4cc: 86 | case "VARI"_4cc: 87 | case "FUNC"_4cc: 88 | case "TXTR"_4cc: 89 | case "AUDO"_4cc: { 90 | out.write(reinterpret_cast(&chunk), sizeof(chunk)); 91 | buffer.resize(chunk.size); 92 | in.read(&buffer[0], buffer.size()); 93 | out.write(&buffer[0], buffer.size()); 94 | break; 95 | } 96 | 97 | case "STRG"_4cc: { 98 | auto next = chunk.size + in.tellg(); 99 | auto strg = strg_header{}; 100 | in.read(reinterpret_cast(&strg), sizeof(strg)); 101 | 102 | ioffsets.resize(strg.count); 103 | strings.resize(strg.count); 104 | in.read(reinterpret_cast(&ioffsets[0]), 105 | strg.count * sizeof(ioffsets[0])); 106 | 107 | auto beg_strings = in.tellg(); 108 | for (size_t i = 0; i < strg.count; ++i) { 109 | in.seekg(ioffsets[i], std::ios::beg); 110 | 111 | uint32_t length = 0; 112 | in.read(reinterpret_cast(&length), sizeof(length)); 113 | 114 | std::getline(in, strings[i], '\0'); 115 | assert(length == strings[i].size()); 116 | } 117 | 118 | out.write(reinterpret_cast(&chunk), sizeof(chunk)); 119 | out.write(reinterpret_cast(&strg), sizeof(strg)); 120 | out.write(reinterpret_cast(&ioffsets[0]), 121 | strg.count * sizeof(ioffsets[0])); 122 | 123 | buffer.resize(next - beg_strings); 124 | in.seekg(beg_strings, std::ios::beg); 125 | in.read(&buffer[0], buffer.size()); 126 | out.write(&buffer[0], buffer.size()); 127 | break; 128 | } 129 | } 130 | } 131 | 132 | auto ins = std::ifstream{argv[1], std::ios::binary}; 133 | while (ins.good()) { 134 | auto _ = std::string{}; 135 | ins >> _; 136 | if (!ins.good()) 137 | break; 138 | 139 | if (_ != "msgctxt" || ins.get() != ' ') { 140 | std::getline(ins, _, '\n'); 141 | } else { 142 | auto line = -1; 143 | ins >> line; 144 | 145 | ins >> _; 146 | assert(_ == "msgid"); 147 | ins.get(); 148 | ins.get(); 149 | 150 | auto msgid = std::string{}; 151 | std::getline(ins, msgid, '\n'); 152 | msgid.pop_back(); 153 | boost::replace_all(msgid, "\\\\", "\\"); 154 | boost::replace_all(msgid, "\\\"", "\""); 155 | boost::replace_all(msgid, "\\n", "\n"); 156 | boost::replace_all(msgid, "\\r", "\r"); 157 | 158 | ins >> _; 159 | assert(_ == "msgstr"); 160 | ins.get(); 161 | ins.get(); 162 | 163 | auto msgstr = std::string{}; 164 | std::getline(ins, msgstr, '\n'); 165 | msgstr.pop_back(); 166 | boost::replace_all(msgstr, "\\\\", "\\"); 167 | boost::replace_all(msgstr, "\\\"", "\""); 168 | boost::replace_all(msgid, "\\n", "\n"); 169 | boost::replace_all(msgid, "\\r", "\r"); 170 | 171 | if (strings[line] == msgid) 172 | strings[line] = msgstr; 173 | else 174 | std::printf("err: %d: %s doestn't match msgid %s\n", line, 175 | strings[line].c_str(), msgid.c_str()); 176 | } 177 | } 178 | 179 | auto chunk = chunk_header{}; 180 | auto strg = strg_header{}; 181 | chunk.magic = "STRG"_4cc; 182 | chunk.size = 4 + 4 * strings.size(); 183 | for (size_t i = 0; i < strings.size(); ++i) { 184 | ooffsets.push_back(end_file + 8 + chunk.size); 185 | chunk.size += sizeof(uint32_t) + strings[i].size() + 1; 186 | strg.count++; 187 | } 188 | 189 | out.write(reinterpret_cast(&chunk), sizeof(chunk)); 190 | out.write(reinterpret_cast(&strg), sizeof(strg)); 191 | out.write(reinterpret_cast(&ooffsets[0]), 192 | strg.count * sizeof(ooffsets[0])); 193 | 194 | for (size_t i = 0; i < strings.size(); ++i) { 195 | uint32_t length = utf8size(strings[i].c_str()); 196 | out.write(reinterpret_cast(&length), sizeof(length)); 197 | out.write(strings[i].c_str(), strings[i].size() + 1); 198 | } 199 | 200 | uint32_t size = static_cast(out.tellp()) - 8; 201 | out.seekp(4, std::ios::beg); 202 | out.write(reinterpret_cast(&size), 4); 203 | 204 | return 0; 205 | } 206 | -------------------------------------------------------------------------------- /undertale/extract-strings-2.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | #include "undertale.h" 11 | 12 | constexpr static uint32_t operator""_4cc(char const* value, size_t size) { 13 | assert(size == 4); 14 | return (value[0] << 0) | (value[1] << 8) | (value[2] << 16) 15 | | (value[3] << 24); 16 | } 17 | 18 | struct chunk_header { 19 | union { 20 | uint32_t magic; 21 | char magic_str[4]; 22 | }; 23 | uint32_t size; 24 | }; 25 | 26 | struct strg_header { 27 | uint32_t count; 28 | }; 29 | 30 | int main(int argc, char const* argv[]) { 31 | if (argc < 2) return -1; 32 | 33 | auto offsets = std::vector< uint32_t >{}; 34 | auto strings = std::vector< std::pair< uint32_t, std::string > >{}; 35 | 36 | std::ifstream ifs{argv[1], std::ifstream::binary}; 37 | kaitai::kstream ks(&ifs); 38 | undertale_t data = undertale_t(&ks); 39 | 40 | for (auto const& str : *data.form()->strg()->data()->strings()) 41 | std::printf("%d %s\n", str->size(), str->string().c_str()); 42 | 43 | return 0; 44 | } 45 | -------------------------------------------------------------------------------- /undertale/extract-strings.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | constexpr static uint32_t operator""_4cc(char const* value, size_t size) { 11 | assert(size == 4); 12 | return (value[0] << 0) | (value[1] << 8) | (value[2] << 16) 13 | | (value[3] << 24); 14 | } 15 | 16 | struct chunk_header { 17 | union { 18 | uint32_t magic; 19 | char magic_str[4]; 20 | }; 21 | uint32_t size; 22 | }; 23 | 24 | struct strg_header { 25 | uint32_t count; 26 | }; 27 | 28 | int main(int argc, char const* argv[]) { 29 | if (argc < 2) return -1; 30 | 31 | auto offsets = std::vector< uint32_t >{}; 32 | auto strings = std::vector< std::pair< uint32_t, std::string > >{}; 33 | 34 | auto in = std::ifstream{argv[1], std::ios::binary}; 35 | while (in.good()) { 36 | auto chunk = chunk_header{}; 37 | 38 | in.read(reinterpret_cast< char* >(&chunk), sizeof(chunk)); 39 | if (!in.good()) break; 40 | 41 | switch (chunk.magic) { 42 | case "FORM"_4cc: break; 43 | case "GEN8"_4cc: 44 | case "OPTN"_4cc: 45 | case "EXTN"_4cc: 46 | case "SOND"_4cc: 47 | case "AGRP"_4cc: 48 | case "SPRT"_4cc: 49 | case "BGND"_4cc: 50 | case "PATH"_4cc: 51 | case "SCPT"_4cc: 52 | case "SHDR"_4cc: 53 | case "FONT"_4cc: 54 | case "TMLN"_4cc: 55 | case "OBJT"_4cc: 56 | case "ROOM"_4cc: 57 | case "DAFL"_4cc: 58 | case "TPAG"_4cc: 59 | case "CODE"_4cc: 60 | case "VARI"_4cc: 61 | case "FUNC"_4cc: 62 | case "TXTR"_4cc: 63 | case "AUDO"_4cc: in.seekg(chunk.size, std::ios::cur); break; 64 | case "STRG"_4cc: { 65 | auto next = chunk.size + in.tellg(); 66 | auto strg = strg_header{}; 67 | in.read(reinterpret_cast< char* >(&strg), sizeof(strg)); 68 | 69 | offsets.resize(strg.count); 70 | strings.resize(strg.count); 71 | in.read(reinterpret_cast< char* >(&offsets[0]), 72 | strg.count * sizeof(offsets[0])); 73 | 74 | for (size_t i = 0; i < strg.count; ++i) { 75 | in.seekg(offsets[i], std::ios::beg); 76 | 77 | uint32_t length = 0; 78 | in.read(reinterpret_cast< char* >(&length), sizeof(length)); 79 | 80 | strings[i].first = length; 81 | std::getline(in, strings[i].second, '\0'); 82 | } 83 | 84 | in.seekg(next, std::ios::beg); 85 | break; 86 | } 87 | } 88 | } 89 | 90 | for (auto& pair : strings) 91 | std::printf("%d %s\n", pair.first, pair.second.c_str()); 92 | 93 | return 0; 94 | } 95 | -------------------------------------------------------------------------------- /undertale/patch-strings.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | constexpr static uint32_t operator""_4cc(char const* value, size_t size) { 11 | assert(size == 4); 12 | return (value[0] << 0) | (value[1] << 8) | (value[2] << 16) 13 | | (value[3] << 24); 14 | } 15 | 16 | struct chunk_header { 17 | union { 18 | uint32_t magic; 19 | char magic_str[4]; 20 | }; 21 | uint32_t size; 22 | }; 23 | 24 | struct strg_header { 25 | uint32_t count; 26 | }; 27 | 28 | int main(int argc, char const* argv[]) { 29 | if (argc < 4) return -1; 30 | 31 | auto ioffsets = std::vector< uint32_t >{}; 32 | auto ooffsets = std::vector< uint32_t >{}; 33 | auto istrings = std::vector< std::pair< uint32_t, std::string > >{}; 34 | auto ostrings = std::vector< std::pair< uint32_t, std::string > >{}; 35 | 36 | auto ins = std::ifstream{argv[2], std::ios::binary}; 37 | while (ins.good()) { 38 | auto length = 0; 39 | ins >> length; 40 | if (!ins.good()) break; 41 | 42 | ostrings.emplace_back(); 43 | ostrings.back().first = length; 44 | assert(ins.get() == ' '); 45 | std::getline(ins, ostrings.back().second, '\n'); 46 | } 47 | 48 | auto in = std::ifstream{argv[1], std::ios::binary}; 49 | auto out = std::ofstream{argv[3], std::ios::binary}; 50 | auto buffer = std::vector< char >{}; 51 | 52 | auto end_file = 0; 53 | while (in.good()) { 54 | auto chunk = chunk_header{}; 55 | 56 | in.read(reinterpret_cast< char* >(&chunk), sizeof(chunk)); 57 | if (!in.good()) break; 58 | 59 | switch (chunk.magic) { 60 | case "FORM"_4cc: 61 | out.write(reinterpret_cast< char* >(&chunk), sizeof(chunk)); 62 | end_file = chunk.size + 8; 63 | break; 64 | case "GEN8"_4cc: 65 | case "OPTN"_4cc: 66 | case "EXTN"_4cc: 67 | case "SOND"_4cc: 68 | case "AGRP"_4cc: 69 | case "SPRT"_4cc: 70 | case "BGND"_4cc: 71 | case "PATH"_4cc: 72 | case "SCPT"_4cc: 73 | case "SHDR"_4cc: 74 | case "FONT"_4cc: 75 | case "TMLN"_4cc: 76 | case "OBJT"_4cc: 77 | case "ROOM"_4cc: 78 | case "DAFL"_4cc: 79 | case "TPAG"_4cc: 80 | case "CODE"_4cc: 81 | case "VARI"_4cc: 82 | case "FUNC"_4cc: 83 | case "TXTR"_4cc: 84 | case "AUDO"_4cc: { 85 | out.write(reinterpret_cast< char* >(&chunk), sizeof(chunk)); 86 | buffer.resize(chunk.size); 87 | in.read(&buffer[0], buffer.size()); 88 | out.write(&buffer[0], buffer.size()); 89 | break; 90 | } 91 | 92 | case "STRG"_4cc: { 93 | auto next = chunk.size + in.tellg(); 94 | auto strg = strg_header{}; 95 | in.read(reinterpret_cast< char* >(&strg), sizeof(strg)); 96 | 97 | ioffsets.resize(strg.count); 98 | istrings.resize(strg.count); 99 | in.read(reinterpret_cast< char* >(&ioffsets[0]), 100 | strg.count * sizeof(ioffsets[0])); 101 | 102 | auto beg_strings = in.tellg(); 103 | for (size_t i = 0; i < strg.count; ++i) { 104 | in.seekg(ioffsets[i], std::ios::beg); 105 | 106 | uint32_t length = 0; 107 | in.read(reinterpret_cast< char* >(&length), sizeof(length)); 108 | 109 | istrings[i].first = length; 110 | std::getline(in, istrings[i].second, '\0'); 111 | } 112 | 113 | out.write(reinterpret_cast< char* >(&chunk), sizeof(chunk)); 114 | out.write(reinterpret_cast< char* >(&strg), sizeof(strg)); 115 | out.write(reinterpret_cast< char* >(&ioffsets[0]), 116 | strg.count * sizeof(ioffsets[0])); 117 | 118 | buffer.resize(next - beg_strings); 119 | in.seekg(beg_strings, std::ios::beg); 120 | in.read(&buffer[0], buffer.size()); 121 | out.write(&buffer[0], buffer.size()); 122 | break; 123 | } 124 | } 125 | } 126 | 127 | auto chunk = chunk_header{}; 128 | auto strg = strg_header{}; 129 | chunk.magic = "STRG"_4cc; 130 | chunk.size = 4 + 4 * ostrings.size(); 131 | for (size_t i = 0; i < ostrings.size(); ++i) { 132 | ooffsets.push_back(end_file + 8 + chunk.size); 133 | chunk.size += sizeof(ostrings[i].first) + ostrings[i].second.size() + 1; 134 | strg.count++; 135 | } 136 | 137 | out.write(reinterpret_cast< char* >(&chunk), sizeof(chunk)); 138 | out.write(reinterpret_cast< char* >(&strg), sizeof(strg)); 139 | out.write(reinterpret_cast< char* >(&ooffsets[0]), 140 | strg.count * sizeof(ooffsets[0])); 141 | 142 | for (size_t i = 0; i < ostrings.size(); ++i) { 143 | out.write(reinterpret_cast< char* >(&ostrings[i].first), 144 | sizeof(ostrings[i].first)); 145 | out.write(ostrings[i].second.c_str(), ostrings[i].second.size() + 1); 146 | } 147 | 148 | uint32_t size = static_cast< uint32_t >(out.tellp()) - 8; 149 | out.seekp(4, std::ios::beg); 150 | out.write(reinterpret_cast< char* >(&size), 4); 151 | 152 | return 0; 153 | } 154 | -------------------------------------------------------------------------------- /undertale/undertale.bt: -------------------------------------------------------------------------------- 1 | // Undertale 2 | 3 | typedef struct (uint32 count, string magic) { 4 | char data[count] ; 5 | Assert(data == magic); 6 | } Magic ; 7 | string ReadMagic(Magic& value) { return value.data; } 8 | 9 | typedef struct (uint32 value) { 10 | uint32 data ; 11 | Assert(data == value); 12 | } Fixed32 ; 13 | string ReadFixed32(Fixed32& value) { string out; SPrintf(out, "%08Xh", value.data); return out; } 14 | 15 | typedef struct (uint64 value) { 16 | uint64 data ; 17 | Assert(data == value); 18 | } Fixed64 ; 19 | string ReadFixed64(Fixed64& value) { string out; SPrintf(out, "%016LXh", value.data); return out; } 20 | 21 | typedef struct { string value; } String ; 22 | string ReadStr(String& data) { return data.value; } 23 | 24 | typedef struct (uint32 size) { char value[size]; } PaddedString ; 25 | string ReadPaddedString(PaddedString& data) { return data.value; } 26 | 27 | typedef struct { uint32 size; char value[size]; } SizedString ; 28 | string ReadSizedString(SizedString& data) { return data.value; } 29 | 30 | typedef struct { uint32 size; char value[size+1]; } SizedCString ; 31 | string ReadSizedCString(SizedCString& data) { return data.value; } 32 | 33 | typedef struct { uint32 count; uint32 data[count]; } UInt32Array; 34 | 35 | typedef struct { 36 | uint32 data ; 37 | } ResId ; 38 | string ReadResId(ResId& value) { string out; SPrintf(out, "%08Xh", value.data); return out; } 39 | 40 | typedef struct (uint32 width, uint32 height) { 41 | local uint32 width = width; 42 | local uint32 height = height; 43 | float data[width * height] ; 44 | } Matrix ; 45 | string ReadMatrix(Matrix& value) { 46 | local string out = "{", buf; 47 | local uint32 x,y; 48 | for (y = 0; y < value.height; ++y) { 49 | if (y > 0) out += ",\n"; 50 | out += "{"; 51 | for (x = 0; x < value.width; ++x) { 52 | if (x > 0) out += ","; 53 | SPrintf(buf, "%f", value.data[x + y * value.width]); 54 | out += buf; 55 | } 56 | out += "}"; 57 | } 58 | out += "}"; 59 | return out; 60 | } 61 | 62 | typedef struct (string fourcc) { 63 | Magic magic(4, fourcc); 64 | uint32 size; 65 | byte data[size] ; 66 | } Chunk ; 67 | string ReadChunk(Chunk& value) { 68 | return value.magic.data; 69 | } 70 | 71 | struct STRG { 72 | Magic magic(4, "STRG"); 73 | uint32 size; 74 | 75 | local uint32 pos = FTell(); 76 | 77 | uint32 count; 78 | uint32 offsets[count] ; 79 | SizedCString strings[count] ; 80 | 81 | byte padding[size - (FTell() - pos)]; 82 | }; 83 | 84 | struct FORM { 85 | Magic magic(4, "FORM"); 86 | uint32 size ; 87 | 88 | Chunk gen8("GEN8"); 89 | Chunk optn("OPTN"); 90 | Chunk extn("EXTN"); 91 | Chunk sond("SOND"); 92 | Chunk agrp("AGRP"); 93 | Chunk sprt("SPRT"); 94 | Chunk bgnd("BGND"); 95 | Chunk path("PATH"); 96 | Chunk scpt("SCPT"); 97 | Chunk shdr("SHDR"); 98 | Chunk font("FONT"); 99 | Chunk tmln("TMLN"); 100 | Chunk objt("OBJT"); 101 | Chunk room("ROOM"); 102 | Chunk dafl("DAFL"); 103 | Chunk tpag("TPAG"); 104 | Chunk code("CODE"); 105 | Chunk vari("VARI"); 106 | Chunk func("FUNC"); 107 | // Chunk strg("STRG"); 108 | STRG strg; 109 | Chunk txtr("TXTR"); 110 | Chunk audo("AUDO"); 111 | STRG strg; 112 | }; 113 | 114 | FORM form; 115 | -------------------------------------------------------------------------------- /undertale/undertale.cpp: -------------------------------------------------------------------------------- 1 | // This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild 2 | 3 | #include "undertale.h" 4 | 5 | #include 6 | #include 7 | 8 | undertale_t::undertale_t(kaitai::kstream *p_io, kaitai::kstruct *p_parent, undertale_t *p_root) : kaitai::kstruct(p_io) { 9 | m__parent = p_parent; 10 | m__root = this; 11 | m_form = new form_t(m__io, this, m__root); 12 | } 13 | 14 | undertale_t::~undertale_t() { 15 | delete m_form; 16 | } 17 | 18 | undertale_t::tmln_t::tmln_t(kaitai::kstream *p_io, undertale_t::form_t *p_parent, undertale_t *p_root) : kaitai::kstruct(p_io) { 19 | m__parent = p_parent; 20 | m__root = p_root; 21 | m_magic = m__io->ensure_fixed_contents(std::string("\x54\x4D\x4C\x4E", 4)); 22 | m_size = m__io->read_u4le(); 23 | m_data = m__io->read_bytes(size()); 24 | } 25 | 26 | undertale_t::tmln_t::~tmln_t() { 27 | } 28 | 29 | undertale_t::dafl_t::dafl_t(kaitai::kstream *p_io, undertale_t::form_t *p_parent, undertale_t *p_root) : kaitai::kstruct(p_io) { 30 | m__parent = p_parent; 31 | m__root = p_root; 32 | m_magic = m__io->ensure_fixed_contents(std::string("\x44\x41\x46\x4C", 4)); 33 | m_size = m__io->read_u4le(); 34 | m_data = m__io->read_bytes(size()); 35 | } 36 | 37 | undertale_t::dafl_t::~dafl_t() { 38 | } 39 | 40 | undertale_t::path_t::path_t(kaitai::kstream *p_io, undertale_t::form_t *p_parent, undertale_t *p_root) : kaitai::kstruct(p_io) { 41 | m__parent = p_parent; 42 | m__root = p_root; 43 | m_magic = m__io->ensure_fixed_contents(std::string("\x50\x41\x54\x48", 4)); 44 | m_size = m__io->read_u4le(); 45 | m_data = m__io->read_bytes(size()); 46 | } 47 | 48 | undertale_t::path_t::~path_t() { 49 | } 50 | 51 | undertale_t::gen8_t::gen8_t(kaitai::kstream *p_io, undertale_t::form_t *p_parent, undertale_t *p_root) : kaitai::kstruct(p_io) { 52 | m__parent = p_parent; 53 | m__root = p_root; 54 | m_magic = m__io->ensure_fixed_contents(std::string("\x47\x45\x4E\x38", 4)); 55 | m_size = m__io->read_u4le(); 56 | m_data = m__io->read_bytes(size()); 57 | } 58 | 59 | undertale_t::gen8_t::~gen8_t() { 60 | } 61 | 62 | undertale_t::optn_t::optn_t(kaitai::kstream *p_io, undertale_t::form_t *p_parent, undertale_t *p_root) : kaitai::kstruct(p_io) { 63 | m__parent = p_parent; 64 | m__root = p_root; 65 | m_magic = m__io->ensure_fixed_contents(std::string("\x4F\x50\x54\x4E", 4)); 66 | m_size = m__io->read_u4le(); 67 | m_data = m__io->read_bytes(size()); 68 | } 69 | 70 | undertale_t::optn_t::~optn_t() { 71 | } 72 | 73 | undertale_t::agrp_t::agrp_t(kaitai::kstream *p_io, undertale_t::form_t *p_parent, undertale_t *p_root) : kaitai::kstruct(p_io) { 74 | m__parent = p_parent; 75 | m__root = p_root; 76 | m_magic = m__io->ensure_fixed_contents(std::string("\x41\x47\x52\x50", 4)); 77 | m_size = m__io->read_u4le(); 78 | m_data = m__io->read_bytes(size()); 79 | } 80 | 81 | undertale_t::agrp_t::~agrp_t() { 82 | } 83 | 84 | undertale_t::bgnd_t::bgnd_t(kaitai::kstream *p_io, undertale_t::form_t *p_parent, undertale_t *p_root) : kaitai::kstruct(p_io) { 85 | m__parent = p_parent; 86 | m__root = p_root; 87 | m_magic = m__io->ensure_fixed_contents(std::string("\x42\x47\x4E\x44", 4)); 88 | m_size = m__io->read_u4le(); 89 | m_data = m__io->read_bytes(size()); 90 | } 91 | 92 | undertale_t::bgnd_t::~bgnd_t() { 93 | } 94 | 95 | undertale_t::txtr_t::txtr_t(kaitai::kstream *p_io, undertale_t::form_t *p_parent, undertale_t *p_root) : kaitai::kstruct(p_io) { 96 | m__parent = p_parent; 97 | m__root = p_root; 98 | m_magic = m__io->ensure_fixed_contents(std::string("\x54\x58\x54\x52", 4)); 99 | m_size = m__io->read_u4le(); 100 | m_data = m__io->read_bytes(size()); 101 | } 102 | 103 | undertale_t::txtr_t::~txtr_t() { 104 | } 105 | 106 | undertale_t::tpag_t::tpag_t(kaitai::kstream *p_io, undertale_t::form_t *p_parent, undertale_t *p_root) : kaitai::kstruct(p_io) { 107 | m__parent = p_parent; 108 | m__root = p_root; 109 | m_magic = m__io->ensure_fixed_contents(std::string("\x54\x50\x41\x47", 4)); 110 | m_size = m__io->read_u4le(); 111 | m_data = m__io->read_bytes(size()); 112 | } 113 | 114 | undertale_t::tpag_t::~tpag_t() { 115 | } 116 | 117 | undertale_t::string_t::string_t(kaitai::kstream *p_io, undertale_t::strg_data_t *p_parent, undertale_t *p_root) : kaitai::kstruct(p_io) { 118 | m__parent = p_parent; 119 | m__root = p_root; 120 | m_size = m__io->read_u4le(); 121 | m_string = m__io->read_str_byte_limit((size() + 1), "ascii"); 122 | } 123 | 124 | undertale_t::string_t::~string_t() { 125 | } 126 | 127 | undertale_t::code_t::code_t(kaitai::kstream *p_io, undertale_t::form_t *p_parent, undertale_t *p_root) : kaitai::kstruct(p_io) { 128 | m__parent = p_parent; 129 | m__root = p_root; 130 | m_magic = m__io->ensure_fixed_contents(std::string("\x43\x4F\x44\x45", 4)); 131 | m_size = m__io->read_u4le(); 132 | m_data = m__io->read_bytes(size()); 133 | } 134 | 135 | undertale_t::code_t::~code_t() { 136 | } 137 | 138 | undertale_t::strg_data_t::strg_data_t(kaitai::kstream *p_io, undertale_t::strg_t *p_parent, undertale_t *p_root) : kaitai::kstruct(p_io) { 139 | m__parent = p_parent; 140 | m__root = p_root; 141 | m_count = m__io->read_u4le(); 142 | int l_offsets = count(); 143 | m_offsets = new std::vector(); 144 | m_offsets->reserve(l_offsets); 145 | for (int i = 0; i < l_offsets; i++) { 146 | m_offsets->push_back(m__io->read_u4le()); 147 | } 148 | int l_strings = count(); 149 | m_strings = new std::vector(); 150 | m_strings->reserve(l_strings); 151 | for (int i = 0; i < l_strings; i++) { 152 | m_strings->push_back(new string_t(m__io, this, m__root)); 153 | } 154 | } 155 | 156 | undertale_t::strg_data_t::~strg_data_t() { 157 | delete m_offsets; 158 | for (std::vector::iterator it = m_strings->begin(); it != m_strings->end(); ++it) { 159 | delete *it; 160 | } 161 | delete m_strings; 162 | } 163 | 164 | undertale_t::scpt_t::scpt_t(kaitai::kstream *p_io, undertale_t::form_t *p_parent, undertale_t *p_root) : kaitai::kstruct(p_io) { 165 | m__parent = p_parent; 166 | m__root = p_root; 167 | m_magic = m__io->ensure_fixed_contents(std::string("\x53\x43\x50\x54", 4)); 168 | m_size = m__io->read_u4le(); 169 | m_data = m__io->read_bytes(size()); 170 | } 171 | 172 | undertale_t::scpt_t::~scpt_t() { 173 | } 174 | 175 | undertale_t::font_t::font_t(kaitai::kstream *p_io, undertale_t::form_t *p_parent, undertale_t *p_root) : kaitai::kstruct(p_io) { 176 | m__parent = p_parent; 177 | m__root = p_root; 178 | m_magic = m__io->ensure_fixed_contents(std::string("\x46\x4F\x4E\x54", 4)); 179 | m_size = m__io->read_u4le(); 180 | m_data = m__io->read_bytes(size()); 181 | } 182 | 183 | undertale_t::font_t::~font_t() { 184 | } 185 | 186 | undertale_t::sprt_t::sprt_t(kaitai::kstream *p_io, undertale_t::form_t *p_parent, undertale_t *p_root) : kaitai::kstruct(p_io) { 187 | m__parent = p_parent; 188 | m__root = p_root; 189 | m_magic = m__io->ensure_fixed_contents(std::string("\x53\x50\x52\x54", 4)); 190 | m_size = m__io->read_u4le(); 191 | m_data = m__io->read_bytes(size()); 192 | } 193 | 194 | undertale_t::sprt_t::~sprt_t() { 195 | } 196 | 197 | undertale_t::audo_t::audo_t(kaitai::kstream *p_io, undertale_t::form_t *p_parent, undertale_t *p_root) : kaitai::kstruct(p_io) { 198 | m__parent = p_parent; 199 | m__root = p_root; 200 | m_magic = m__io->ensure_fixed_contents(std::string("\x41\x55\x44\x4F", 4)); 201 | m_size = m__io->read_u4le(); 202 | m_data = m__io->read_bytes(size()); 203 | } 204 | 205 | undertale_t::audo_t::~audo_t() { 206 | } 207 | 208 | undertale_t::vari_t::vari_t(kaitai::kstream *p_io, undertale_t::form_t *p_parent, undertale_t *p_root) : kaitai::kstruct(p_io) { 209 | m__parent = p_parent; 210 | m__root = p_root; 211 | m_magic = m__io->ensure_fixed_contents(std::string("\x56\x41\x52\x49", 4)); 212 | m_size = m__io->read_u4le(); 213 | m_data = m__io->read_bytes(size()); 214 | } 215 | 216 | undertale_t::vari_t::~vari_t() { 217 | } 218 | 219 | undertale_t::extn_t::extn_t(kaitai::kstream *p_io, undertale_t::form_t *p_parent, undertale_t *p_root) : kaitai::kstruct(p_io) { 220 | m__parent = p_parent; 221 | m__root = p_root; 222 | m_magic = m__io->ensure_fixed_contents(std::string("\x45\x58\x54\x4E", 4)); 223 | m_size = m__io->read_u4le(); 224 | m_data = m__io->read_bytes(size()); 225 | } 226 | 227 | undertale_t::extn_t::~extn_t() { 228 | } 229 | 230 | undertale_t::strg_t::strg_t(kaitai::kstream *p_io, undertale_t::form_t *p_parent, undertale_t *p_root) : kaitai::kstruct(p_io) { 231 | m__parent = p_parent; 232 | m__root = p_root; 233 | m_magic = m__io->ensure_fixed_contents(std::string("\x53\x54\x52\x47", 4)); 234 | m_size = m__io->read_u4le(); 235 | m__raw_data = m__io->read_bytes(size()); 236 | m__io__raw_data = new kaitai::kstream(m__raw_data); 237 | m_data = new strg_data_t(m__io__raw_data, this, m__root); 238 | } 239 | 240 | undertale_t::strg_t::~strg_t() { 241 | delete m__io__raw_data; 242 | delete m_data; 243 | } 244 | 245 | undertale_t::func_t::func_t(kaitai::kstream *p_io, undertale_t::form_t *p_parent, undertale_t *p_root) : kaitai::kstruct(p_io) { 246 | m__parent = p_parent; 247 | m__root = p_root; 248 | m_magic = m__io->ensure_fixed_contents(std::string("\x46\x55\x4E\x43", 4)); 249 | m_size = m__io->read_u4le(); 250 | m_data = m__io->read_bytes(size()); 251 | } 252 | 253 | undertale_t::func_t::~func_t() { 254 | } 255 | 256 | undertale_t::room_t::room_t(kaitai::kstream *p_io, undertale_t::form_t *p_parent, undertale_t *p_root) : kaitai::kstruct(p_io) { 257 | m__parent = p_parent; 258 | m__root = p_root; 259 | m_magic = m__io->ensure_fixed_contents(std::string("\x52\x4F\x4F\x4D", 4)); 260 | m_size = m__io->read_u4le(); 261 | m_data = m__io->read_bytes(size()); 262 | } 263 | 264 | undertale_t::room_t::~room_t() { 265 | } 266 | 267 | undertale_t::form_t::form_t(kaitai::kstream *p_io, undertale_t *p_parent, undertale_t *p_root) : kaitai::kstruct(p_io) { 268 | m__parent = p_parent; 269 | m__root = p_root; 270 | m_magic = m__io->ensure_fixed_contents(std::string("\x46\x4F\x52\x4D", 4)); 271 | m_size = m__io->read_u4le(); 272 | m_gen8 = new gen8_t(m__io, this, m__root); 273 | m_optn = new optn_t(m__io, this, m__root); 274 | m_extn = new extn_t(m__io, this, m__root); 275 | m_sond = new sond_t(m__io, this, m__root); 276 | m_agrp = new agrp_t(m__io, this, m__root); 277 | m_sprt = new sprt_t(m__io, this, m__root); 278 | m_bgnd = new bgnd_t(m__io, this, m__root); 279 | m_path = new path_t(m__io, this, m__root); 280 | m_scpt = new scpt_t(m__io, this, m__root); 281 | m_shdr = new shdr_t(m__io, this, m__root); 282 | m_font = new font_t(m__io, this, m__root); 283 | m_tmln = new tmln_t(m__io, this, m__root); 284 | m_objt = new objt_t(m__io, this, m__root); 285 | m_room = new room_t(m__io, this, m__root); 286 | m_dafl = new dafl_t(m__io, this, m__root); 287 | m_tpag = new tpag_t(m__io, this, m__root); 288 | m_code = new code_t(m__io, this, m__root); 289 | m_vari = new vari_t(m__io, this, m__root); 290 | m_func = new func_t(m__io, this, m__root); 291 | m_strg = new strg_t(m__io, this, m__root); 292 | m_txtr = new txtr_t(m__io, this, m__root); 293 | m_audo = new audo_t(m__io, this, m__root); 294 | n_l18n = true; 295 | if (size() > _io()->pos()) { 296 | n_l18n = false; 297 | m_l18n = new strg_t(m__io, this, m__root); 298 | } 299 | } 300 | 301 | undertale_t::form_t::~form_t() { 302 | delete m_gen8; 303 | delete m_optn; 304 | delete m_extn; 305 | delete m_sond; 306 | delete m_agrp; 307 | delete m_sprt; 308 | delete m_bgnd; 309 | delete m_path; 310 | delete m_scpt; 311 | delete m_shdr; 312 | delete m_font; 313 | delete m_tmln; 314 | delete m_objt; 315 | delete m_room; 316 | delete m_dafl; 317 | delete m_tpag; 318 | delete m_code; 319 | delete m_vari; 320 | delete m_func; 321 | delete m_strg; 322 | delete m_txtr; 323 | delete m_audo; 324 | if (!n_l18n) { 325 | delete m_l18n; 326 | } 327 | } 328 | 329 | undertale_t::objt_t::objt_t(kaitai::kstream *p_io, undertale_t::form_t *p_parent, undertale_t *p_root) : kaitai::kstruct(p_io) { 330 | m__parent = p_parent; 331 | m__root = p_root; 332 | m_magic = m__io->ensure_fixed_contents(std::string("\x4F\x42\x4A\x54", 4)); 333 | m_size = m__io->read_u4le(); 334 | m_data = m__io->read_bytes(size()); 335 | } 336 | 337 | undertale_t::objt_t::~objt_t() { 338 | } 339 | 340 | undertale_t::sond_t::sond_t(kaitai::kstream *p_io, undertale_t::form_t *p_parent, undertale_t *p_root) : kaitai::kstruct(p_io) { 341 | m__parent = p_parent; 342 | m__root = p_root; 343 | m_magic = m__io->ensure_fixed_contents(std::string("\x53\x4F\x4E\x44", 4)); 344 | m_size = m__io->read_u4le(); 345 | m_data = m__io->read_bytes(size()); 346 | } 347 | 348 | undertale_t::sond_t::~sond_t() { 349 | } 350 | 351 | undertale_t::shdr_t::shdr_t(kaitai::kstream *p_io, undertale_t::form_t *p_parent, undertale_t *p_root) : kaitai::kstruct(p_io) { 352 | m__parent = p_parent; 353 | m__root = p_root; 354 | m_magic = m__io->ensure_fixed_contents(std::string("\x53\x48\x44\x52", 4)); 355 | m_size = m__io->read_u4le(); 356 | m_data = m__io->read_bytes(size()); 357 | } 358 | 359 | undertale_t::shdr_t::~shdr_t() { 360 | } 361 | -------------------------------------------------------------------------------- /undertale/undertale.h: -------------------------------------------------------------------------------- 1 | #ifndef UNDERTALE_H_ 2 | #define UNDERTALE_H_ 3 | 4 | // This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild 5 | 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | class undertale_t : public kaitai::kstruct { 14 | 15 | public: 16 | class tmln_t; 17 | class dafl_t; 18 | class path_t; 19 | class gen8_t; 20 | class optn_t; 21 | class agrp_t; 22 | class bgnd_t; 23 | class txtr_t; 24 | class tpag_t; 25 | class string_t; 26 | class code_t; 27 | class strg_data_t; 28 | class scpt_t; 29 | class font_t; 30 | class sprt_t; 31 | class audo_t; 32 | class vari_t; 33 | class extn_t; 34 | class strg_t; 35 | class func_t; 36 | class room_t; 37 | class form_t; 38 | class objt_t; 39 | class sond_t; 40 | class shdr_t; 41 | 42 | undertale_t(kaitai::kstream* p_io, kaitai::kstruct* p_parent = 0, undertale_t* p_root = 0); 43 | ~undertale_t(); 44 | 45 | class tmln_t : public kaitai::kstruct { 46 | 47 | public: 48 | 49 | tmln_t(kaitai::kstream* p_io, undertale_t::form_t* p_parent = 0, undertale_t* p_root = 0); 50 | ~tmln_t(); 51 | 52 | private: 53 | std::string m_magic; 54 | uint32_t m_size; 55 | std::string m_data; 56 | undertale_t* m__root; 57 | undertale_t::form_t* m__parent; 58 | 59 | public: 60 | std::string magic() const { return m_magic; } 61 | uint32_t size() const { return m_size; } 62 | std::string data() const { return m_data; } 63 | undertale_t* _root() const { return m__root; } 64 | undertale_t::form_t* _parent() const { return m__parent; } 65 | }; 66 | 67 | class dafl_t : public kaitai::kstruct { 68 | 69 | public: 70 | 71 | dafl_t(kaitai::kstream* p_io, undertale_t::form_t* p_parent = 0, undertale_t* p_root = 0); 72 | ~dafl_t(); 73 | 74 | private: 75 | std::string m_magic; 76 | uint32_t m_size; 77 | std::string m_data; 78 | undertale_t* m__root; 79 | undertale_t::form_t* m__parent; 80 | 81 | public: 82 | std::string magic() const { return m_magic; } 83 | uint32_t size() const { return m_size; } 84 | std::string data() const { return m_data; } 85 | undertale_t* _root() const { return m__root; } 86 | undertale_t::form_t* _parent() const { return m__parent; } 87 | }; 88 | 89 | class path_t : public kaitai::kstruct { 90 | 91 | public: 92 | 93 | path_t(kaitai::kstream* p_io, undertale_t::form_t* p_parent = 0, undertale_t* p_root = 0); 94 | ~path_t(); 95 | 96 | private: 97 | std::string m_magic; 98 | uint32_t m_size; 99 | std::string m_data; 100 | undertale_t* m__root; 101 | undertale_t::form_t* m__parent; 102 | 103 | public: 104 | std::string magic() const { return m_magic; } 105 | uint32_t size() const { return m_size; } 106 | std::string data() const { return m_data; } 107 | undertale_t* _root() const { return m__root; } 108 | undertale_t::form_t* _parent() const { return m__parent; } 109 | }; 110 | 111 | class gen8_t : public kaitai::kstruct { 112 | 113 | public: 114 | 115 | gen8_t(kaitai::kstream* p_io, undertale_t::form_t* p_parent = 0, undertale_t* p_root = 0); 116 | ~gen8_t(); 117 | 118 | private: 119 | std::string m_magic; 120 | uint32_t m_size; 121 | std::string m_data; 122 | undertale_t* m__root; 123 | undertale_t::form_t* m__parent; 124 | 125 | public: 126 | std::string magic() const { return m_magic; } 127 | uint32_t size() const { return m_size; } 128 | std::string data() const { return m_data; } 129 | undertale_t* _root() const { return m__root; } 130 | undertale_t::form_t* _parent() const { return m__parent; } 131 | }; 132 | 133 | class optn_t : public kaitai::kstruct { 134 | 135 | public: 136 | 137 | optn_t(kaitai::kstream* p_io, undertale_t::form_t* p_parent = 0, undertale_t* p_root = 0); 138 | ~optn_t(); 139 | 140 | private: 141 | std::string m_magic; 142 | uint32_t m_size; 143 | std::string m_data; 144 | undertale_t* m__root; 145 | undertale_t::form_t* m__parent; 146 | 147 | public: 148 | std::string magic() const { return m_magic; } 149 | uint32_t size() const { return m_size; } 150 | std::string data() const { return m_data; } 151 | undertale_t* _root() const { return m__root; } 152 | undertale_t::form_t* _parent() const { return m__parent; } 153 | }; 154 | 155 | class agrp_t : public kaitai::kstruct { 156 | 157 | public: 158 | 159 | agrp_t(kaitai::kstream* p_io, undertale_t::form_t* p_parent = 0, undertale_t* p_root = 0); 160 | ~agrp_t(); 161 | 162 | private: 163 | std::string m_magic; 164 | uint32_t m_size; 165 | std::string m_data; 166 | undertale_t* m__root; 167 | undertale_t::form_t* m__parent; 168 | 169 | public: 170 | std::string magic() const { return m_magic; } 171 | uint32_t size() const { return m_size; } 172 | std::string data() const { return m_data; } 173 | undertale_t* _root() const { return m__root; } 174 | undertale_t::form_t* _parent() const { return m__parent; } 175 | }; 176 | 177 | class bgnd_t : public kaitai::kstruct { 178 | 179 | public: 180 | 181 | bgnd_t(kaitai::kstream* p_io, undertale_t::form_t* p_parent = 0, undertale_t* p_root = 0); 182 | ~bgnd_t(); 183 | 184 | private: 185 | std::string m_magic; 186 | uint32_t m_size; 187 | std::string m_data; 188 | undertale_t* m__root; 189 | undertale_t::form_t* m__parent; 190 | 191 | public: 192 | std::string magic() const { return m_magic; } 193 | uint32_t size() const { return m_size; } 194 | std::string data() const { return m_data; } 195 | undertale_t* _root() const { return m__root; } 196 | undertale_t::form_t* _parent() const { return m__parent; } 197 | }; 198 | 199 | class txtr_t : public kaitai::kstruct { 200 | 201 | public: 202 | 203 | txtr_t(kaitai::kstream* p_io, undertale_t::form_t* p_parent = 0, undertale_t* p_root = 0); 204 | ~txtr_t(); 205 | 206 | private: 207 | std::string m_magic; 208 | uint32_t m_size; 209 | std::string m_data; 210 | undertale_t* m__root; 211 | undertale_t::form_t* m__parent; 212 | 213 | public: 214 | std::string magic() const { return m_magic; } 215 | uint32_t size() const { return m_size; } 216 | std::string data() const { return m_data; } 217 | undertale_t* _root() const { return m__root; } 218 | undertale_t::form_t* _parent() const { return m__parent; } 219 | }; 220 | 221 | class tpag_t : public kaitai::kstruct { 222 | 223 | public: 224 | 225 | tpag_t(kaitai::kstream* p_io, undertale_t::form_t* p_parent = 0, undertale_t* p_root = 0); 226 | ~tpag_t(); 227 | 228 | private: 229 | std::string m_magic; 230 | uint32_t m_size; 231 | std::string m_data; 232 | undertale_t* m__root; 233 | undertale_t::form_t* m__parent; 234 | 235 | public: 236 | std::string magic() const { return m_magic; } 237 | uint32_t size() const { return m_size; } 238 | std::string data() const { return m_data; } 239 | undertale_t* _root() const { return m__root; } 240 | undertale_t::form_t* _parent() const { return m__parent; } 241 | }; 242 | 243 | class string_t : public kaitai::kstruct { 244 | 245 | public: 246 | 247 | string_t(kaitai::kstream* p_io, undertale_t::strg_data_t* p_parent = 0, undertale_t* p_root = 0); 248 | ~string_t(); 249 | 250 | private: 251 | uint32_t m_size; 252 | std::string m_string; 253 | undertale_t* m__root; 254 | undertale_t::strg_data_t* m__parent; 255 | 256 | public: 257 | uint32_t size() const { return m_size; } 258 | std::string string() const { return m_string; } 259 | undertale_t* _root() const { return m__root; } 260 | undertale_t::strg_data_t* _parent() const { return m__parent; } 261 | }; 262 | 263 | class code_t : public kaitai::kstruct { 264 | 265 | public: 266 | 267 | code_t(kaitai::kstream* p_io, undertale_t::form_t* p_parent = 0, undertale_t* p_root = 0); 268 | ~code_t(); 269 | 270 | private: 271 | std::string m_magic; 272 | uint32_t m_size; 273 | std::string m_data; 274 | undertale_t* m__root; 275 | undertale_t::form_t* m__parent; 276 | 277 | public: 278 | std::string magic() const { return m_magic; } 279 | uint32_t size() const { return m_size; } 280 | std::string data() const { return m_data; } 281 | undertale_t* _root() const { return m__root; } 282 | undertale_t::form_t* _parent() const { return m__parent; } 283 | }; 284 | 285 | class strg_data_t : public kaitai::kstruct { 286 | 287 | public: 288 | 289 | strg_data_t(kaitai::kstream* p_io, undertale_t::strg_t* p_parent = 0, undertale_t* p_root = 0); 290 | ~strg_data_t(); 291 | 292 | private: 293 | uint32_t m_count; 294 | std::vector* m_offsets; 295 | std::vector* m_strings; 296 | undertale_t* m__root; 297 | undertale_t::strg_t* m__parent; 298 | 299 | public: 300 | uint32_t count() const { return m_count; } 301 | std::vector* offsets() const { return m_offsets; } 302 | std::vector* strings() const { return m_strings; } 303 | undertale_t* _root() const { return m__root; } 304 | undertale_t::strg_t* _parent() const { return m__parent; } 305 | }; 306 | 307 | class scpt_t : public kaitai::kstruct { 308 | 309 | public: 310 | 311 | scpt_t(kaitai::kstream* p_io, undertale_t::form_t* p_parent = 0, undertale_t* p_root = 0); 312 | ~scpt_t(); 313 | 314 | private: 315 | std::string m_magic; 316 | uint32_t m_size; 317 | std::string m_data; 318 | undertale_t* m__root; 319 | undertale_t::form_t* m__parent; 320 | 321 | public: 322 | std::string magic() const { return m_magic; } 323 | uint32_t size() const { return m_size; } 324 | std::string data() const { return m_data; } 325 | undertale_t* _root() const { return m__root; } 326 | undertale_t::form_t* _parent() const { return m__parent; } 327 | }; 328 | 329 | class font_t : public kaitai::kstruct { 330 | 331 | public: 332 | 333 | font_t(kaitai::kstream* p_io, undertale_t::form_t* p_parent = 0, undertale_t* p_root = 0); 334 | ~font_t(); 335 | 336 | private: 337 | std::string m_magic; 338 | uint32_t m_size; 339 | std::string m_data; 340 | undertale_t* m__root; 341 | undertale_t::form_t* m__parent; 342 | 343 | public: 344 | std::string magic() const { return m_magic; } 345 | uint32_t size() const { return m_size; } 346 | std::string data() const { return m_data; } 347 | undertale_t* _root() const { return m__root; } 348 | undertale_t::form_t* _parent() const { return m__parent; } 349 | }; 350 | 351 | class sprt_t : public kaitai::kstruct { 352 | 353 | public: 354 | 355 | sprt_t(kaitai::kstream* p_io, undertale_t::form_t* p_parent = 0, undertale_t* p_root = 0); 356 | ~sprt_t(); 357 | 358 | private: 359 | std::string m_magic; 360 | uint32_t m_size; 361 | std::string m_data; 362 | undertale_t* m__root; 363 | undertale_t::form_t* m__parent; 364 | 365 | public: 366 | std::string magic() const { return m_magic; } 367 | uint32_t size() const { return m_size; } 368 | std::string data() const { return m_data; } 369 | undertale_t* _root() const { return m__root; } 370 | undertale_t::form_t* _parent() const { return m__parent; } 371 | }; 372 | 373 | class audo_t : public kaitai::kstruct { 374 | 375 | public: 376 | 377 | audo_t(kaitai::kstream* p_io, undertale_t::form_t* p_parent = 0, undertale_t* p_root = 0); 378 | ~audo_t(); 379 | 380 | private: 381 | std::string m_magic; 382 | uint32_t m_size; 383 | std::string m_data; 384 | undertale_t* m__root; 385 | undertale_t::form_t* m__parent; 386 | 387 | public: 388 | std::string magic() const { return m_magic; } 389 | uint32_t size() const { return m_size; } 390 | std::string data() const { return m_data; } 391 | undertale_t* _root() const { return m__root; } 392 | undertale_t::form_t* _parent() const { return m__parent; } 393 | }; 394 | 395 | class vari_t : public kaitai::kstruct { 396 | 397 | public: 398 | 399 | vari_t(kaitai::kstream* p_io, undertale_t::form_t* p_parent = 0, undertale_t* p_root = 0); 400 | ~vari_t(); 401 | 402 | private: 403 | std::string m_magic; 404 | uint32_t m_size; 405 | std::string m_data; 406 | undertale_t* m__root; 407 | undertale_t::form_t* m__parent; 408 | 409 | public: 410 | std::string magic() const { return m_magic; } 411 | uint32_t size() const { return m_size; } 412 | std::string data() const { return m_data; } 413 | undertale_t* _root() const { return m__root; } 414 | undertale_t::form_t* _parent() const { return m__parent; } 415 | }; 416 | 417 | class extn_t : public kaitai::kstruct { 418 | 419 | public: 420 | 421 | extn_t(kaitai::kstream* p_io, undertale_t::form_t* p_parent = 0, undertale_t* p_root = 0); 422 | ~extn_t(); 423 | 424 | private: 425 | std::string m_magic; 426 | uint32_t m_size; 427 | std::string m_data; 428 | undertale_t* m__root; 429 | undertale_t::form_t* m__parent; 430 | 431 | public: 432 | std::string magic() const { return m_magic; } 433 | uint32_t size() const { return m_size; } 434 | std::string data() const { return m_data; } 435 | undertale_t* _root() const { return m__root; } 436 | undertale_t::form_t* _parent() const { return m__parent; } 437 | }; 438 | 439 | class strg_t : public kaitai::kstruct { 440 | 441 | public: 442 | 443 | strg_t(kaitai::kstream* p_io, undertale_t::form_t* p_parent = 0, undertale_t* p_root = 0); 444 | ~strg_t(); 445 | 446 | private: 447 | std::string m_magic; 448 | uint32_t m_size; 449 | strg_data_t* m_data; 450 | undertale_t* m__root; 451 | undertale_t::form_t* m__parent; 452 | std::string m__raw_data; 453 | kaitai::kstream* m__io__raw_data; 454 | 455 | public: 456 | std::string magic() const { return m_magic; } 457 | uint32_t size() const { return m_size; } 458 | strg_data_t* data() const { return m_data; } 459 | undertale_t* _root() const { return m__root; } 460 | undertale_t::form_t* _parent() const { return m__parent; } 461 | std::string _raw_data() const { return m__raw_data; } 462 | kaitai::kstream* _io__raw_data() const { return m__io__raw_data; } 463 | }; 464 | 465 | class func_t : public kaitai::kstruct { 466 | 467 | public: 468 | 469 | func_t(kaitai::kstream* p_io, undertale_t::form_t* p_parent = 0, undertale_t* p_root = 0); 470 | ~func_t(); 471 | 472 | private: 473 | std::string m_magic; 474 | uint32_t m_size; 475 | std::string m_data; 476 | undertale_t* m__root; 477 | undertale_t::form_t* m__parent; 478 | 479 | public: 480 | std::string magic() const { return m_magic; } 481 | uint32_t size() const { return m_size; } 482 | std::string data() const { return m_data; } 483 | undertale_t* _root() const { return m__root; } 484 | undertale_t::form_t* _parent() const { return m__parent; } 485 | }; 486 | 487 | class room_t : public kaitai::kstruct { 488 | 489 | public: 490 | 491 | room_t(kaitai::kstream* p_io, undertale_t::form_t* p_parent = 0, undertale_t* p_root = 0); 492 | ~room_t(); 493 | 494 | private: 495 | std::string m_magic; 496 | uint32_t m_size; 497 | std::string m_data; 498 | undertale_t* m__root; 499 | undertale_t::form_t* m__parent; 500 | 501 | public: 502 | std::string magic() const { return m_magic; } 503 | uint32_t size() const { return m_size; } 504 | std::string data() const { return m_data; } 505 | undertale_t* _root() const { return m__root; } 506 | undertale_t::form_t* _parent() const { return m__parent; } 507 | }; 508 | 509 | class form_t : public kaitai::kstruct { 510 | 511 | public: 512 | 513 | form_t(kaitai::kstream* p_io, undertale_t* p_parent = 0, undertale_t* p_root = 0); 514 | ~form_t(); 515 | 516 | private: 517 | std::string m_magic; 518 | uint32_t m_size; 519 | gen8_t* m_gen8; 520 | optn_t* m_optn; 521 | extn_t* m_extn; 522 | sond_t* m_sond; 523 | agrp_t* m_agrp; 524 | sprt_t* m_sprt; 525 | bgnd_t* m_bgnd; 526 | path_t* m_path; 527 | scpt_t* m_scpt; 528 | shdr_t* m_shdr; 529 | font_t* m_font; 530 | tmln_t* m_tmln; 531 | objt_t* m_objt; 532 | room_t* m_room; 533 | dafl_t* m_dafl; 534 | tpag_t* m_tpag; 535 | code_t* m_code; 536 | vari_t* m_vari; 537 | func_t* m_func; 538 | strg_t* m_strg; 539 | txtr_t* m_txtr; 540 | audo_t* m_audo; 541 | strg_t* m_l18n; 542 | bool n_l18n; 543 | 544 | public: 545 | bool _is_null_l18n() { l18n(); return n_l18n; }; 546 | 547 | private: 548 | undertale_t* m__root; 549 | undertale_t* m__parent; 550 | 551 | public: 552 | std::string magic() const { return m_magic; } 553 | uint32_t size() const { return m_size; } 554 | gen8_t* gen8() const { return m_gen8; } 555 | optn_t* optn() const { return m_optn; } 556 | extn_t* extn() const { return m_extn; } 557 | sond_t* sond() const { return m_sond; } 558 | agrp_t* agrp() const { return m_agrp; } 559 | sprt_t* sprt() const { return m_sprt; } 560 | bgnd_t* bgnd() const { return m_bgnd; } 561 | path_t* path() const { return m_path; } 562 | scpt_t* scpt() const { return m_scpt; } 563 | shdr_t* shdr() const { return m_shdr; } 564 | font_t* font() const { return m_font; } 565 | tmln_t* tmln() const { return m_tmln; } 566 | objt_t* objt() const { return m_objt; } 567 | room_t* room() const { return m_room; } 568 | dafl_t* dafl() const { return m_dafl; } 569 | tpag_t* tpag() const { return m_tpag; } 570 | code_t* code() const { return m_code; } 571 | vari_t* vari() const { return m_vari; } 572 | func_t* func() const { return m_func; } 573 | strg_t* strg() const { return m_strg; } 574 | txtr_t* txtr() const { return m_txtr; } 575 | audo_t* audo() const { return m_audo; } 576 | strg_t* l18n() const { return m_l18n; } 577 | undertale_t* _root() const { return m__root; } 578 | undertale_t* _parent() const { return m__parent; } 579 | }; 580 | 581 | class objt_t : public kaitai::kstruct { 582 | 583 | public: 584 | 585 | objt_t(kaitai::kstream* p_io, undertale_t::form_t* p_parent = 0, undertale_t* p_root = 0); 586 | ~objt_t(); 587 | 588 | private: 589 | std::string m_magic; 590 | uint32_t m_size; 591 | std::string m_data; 592 | undertale_t* m__root; 593 | undertale_t::form_t* m__parent; 594 | 595 | public: 596 | std::string magic() const { return m_magic; } 597 | uint32_t size() const { return m_size; } 598 | std::string data() const { return m_data; } 599 | undertale_t* _root() const { return m__root; } 600 | undertale_t::form_t* _parent() const { return m__parent; } 601 | }; 602 | 603 | class sond_t : public kaitai::kstruct { 604 | 605 | public: 606 | 607 | sond_t(kaitai::kstream* p_io, undertale_t::form_t* p_parent = 0, undertale_t* p_root = 0); 608 | ~sond_t(); 609 | 610 | private: 611 | std::string m_magic; 612 | uint32_t m_size; 613 | std::string m_data; 614 | undertale_t* m__root; 615 | undertale_t::form_t* m__parent; 616 | 617 | public: 618 | std::string magic() const { return m_magic; } 619 | uint32_t size() const { return m_size; } 620 | std::string data() const { return m_data; } 621 | undertale_t* _root() const { return m__root; } 622 | undertale_t::form_t* _parent() const { return m__parent; } 623 | }; 624 | 625 | class shdr_t : public kaitai::kstruct { 626 | 627 | public: 628 | 629 | shdr_t(kaitai::kstream* p_io, undertale_t::form_t* p_parent = 0, undertale_t* p_root = 0); 630 | ~shdr_t(); 631 | 632 | private: 633 | std::string m_magic; 634 | uint32_t m_size; 635 | std::string m_data; 636 | undertale_t* m__root; 637 | undertale_t::form_t* m__parent; 638 | 639 | public: 640 | std::string magic() const { return m_magic; } 641 | uint32_t size() const { return m_size; } 642 | std::string data() const { return m_data; } 643 | undertale_t* _root() const { return m__root; } 644 | undertale_t::form_t* _parent() const { return m__parent; } 645 | }; 646 | 647 | private: 648 | form_t* m_form; 649 | undertale_t* m__root; 650 | kaitai::kstruct* m__parent; 651 | 652 | public: 653 | form_t* form() const { return m_form; } 654 | undertale_t* _root() const { return m__root; } 655 | kaitai::kstruct* _parent() const { return m__parent; } 656 | }; 657 | 658 | #endif // UNDERTALE_H_ 659 | --------------------------------------------------------------------------------