├── .gitignore ├── LICENSE ├── README.md ├── _testdata ├── cur-32x64.png ├── cur-64x128.png ├── cursor.cur ├── en.ico ├── fr.ico ├── icons.json ├── image.bmp ├── image.dib ├── rh.exe ├── test.json └── vs0.exe ├── defaulticon_go1.16.go ├── defaulticon_other.go ├── go.mod ├── go.sum ├── icon.png ├── icon16.png ├── main.go ├── main_test.go ├── resdir.go ├── resdir_test.go └── winres ├── icon128.png ├── icon16.png ├── icon256.png ├── icon64.png └── winres.json /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | .private 3 | /*.exe 4 | /*.syso 5 | /_testdata/tmp 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2021 Thomas Combeléran 2 | 3 | Permission to use, copy, modify, and/or distribute this software for any 4 | purpose with or without fee is hereby granted. 5 | 6 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 7 | REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 8 | AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 9 | INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 10 | LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 11 | OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 12 | PERFORMANCE OF THIS SOFTWARE. 13 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # go-winres 2 | 3 | A simple command line tool for embedding usual resources in Windows executables built with Go: 4 | 5 | - A manifest 6 | - An application icon 7 | - Version information (the Details tab in file properties) 8 | - Other icons and cursors 9 | 10 | You might want to directly use winres as a library too: [github.com/tc-hib/winres](https://github.com/tc-hib/winres) 11 | 12 | ## Installation 13 | 14 | To install the go-winres command, run: 15 | 16 | ```shell 17 | go install github.com/tc-hib/go-winres@latest 18 | ``` 19 | 20 | ## Usage 21 | 22 | Please type `go-winres help` to get a list of commands and options. 23 | 24 | Typical usage would be: 25 | 26 | * Run `go-winres init` to create a `winres` directory 27 | * Modify the contents of `winres.json` 28 | * Before `go build`, run `go-winres make` 29 | 30 | `go-winres make` creates files named `rsrc_windows_*.syso` that `go build` automatically embeds in the executable. 31 | 32 | The suffix `_windows_amd64` is very important. 33 | Thanks to it, `go build` knows it should not include that object in a Linux or 386 build. 34 | 35 | ### Automatic version from git 36 | 37 | The `--file-version` and `--product-version` flags can take a special value: `git-tag`. 38 | This will retrieve the current tag with `git describe --tags` and add it to the file properties of the executable. 39 | 40 | ### Using `go generate` 41 | 42 | You can use a `//go:generate` comment as well: 43 | 44 | ``` 45 | //go:generate go-winres make --product-version=git-tag 46 | ``` 47 | 48 | ### Subcommands 49 | 50 | There are other subcommands: 51 | 52 | * `go-winres simply` is a simpler `make` that does not rely on a json file. 53 | * `go-winres extract` extracts resources from an `exe` file or a `dll`. 54 | * `go-winres patch` replaces resources directly in an `exe` file or a `dll`. 55 | For example, to enhance a 7z self extracting archive, you may change its icon, 56 | and add a manifest to make it look better on high DPI screens. 57 | 58 | ## JSON format 59 | 60 | The JSON file follows this hierarchy: 61 | 62 | * Resource type (e.g. `"RT_GROUP_ICON"` or `"#42"` or `"MY_TYPE"`) 63 | * Resource name (e.g. `"MY_ICON"` or `"#1"`) 64 | * Language ID (e.g. `"0409"` for en-US) 65 | * Actual resource: a filename or a json structure 66 | 67 | Standard resource types can be found [there](https://docs.microsoft.com/en-us/windows/win32/menurc/resource-types). But 68 | please never use `RT_ICON` or `RT_CURSOR`. Use `RT_GROUP_ICON` and `RT_GROUP_CURSOR` instead. 69 | 70 | ### Icon JSON 71 | 72 | ```json 73 | { 74 | "RT_GROUP_ICON": { 75 | "APP": { 76 | "0000": [ 77 | "icon_64.png", 78 | "icon_48.png", 79 | "icon_32.png", 80 | "icon_16.png" 81 | ] 82 | }, 83 | "OTHER": { 84 | "0000": "icon.png" 85 | }, 86 | "#42": { 87 | "0409": "icon_EN.ico", 88 | "040C": "icon_FR.ico" 89 | } 90 | } 91 | } 92 | ``` 93 | 94 | This example contains 3 icons: 95 | 96 | * `"APP"` 97 | * `"OTHER"` 98 | * `42` 99 | 100 | Windows Explorer will display `"APP"` because it is the first one. Icons are sorted by name in case sensitive ascending 101 | order, then by ID. 102 | 103 | `42` is an ID, not a name, this is why it comes last. 104 | 105 | * `"APP"` is made of 4 png files. 106 | * `"OTHER"` will be generated from one png file. It will be resized to 256x256, 64x64, 48x48, 32x32, and 16x16. 107 | * `42` is a native icon, it probably already contains several images. 108 | 109 | Finally, `42` will display a different icon for french users. 110 | 111 | * `"0409"` means en-US, which is the default. 112 | * `"040C"` means fr-FR. 113 | 114 | You can find other language IDs [there](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-lcid/). 115 | 116 | ### Cursor JSON 117 | 118 | ```json 119 | { 120 | "RT_GROUP_CURSOR": { 121 | "ARROW": { 122 | "0000": [ 123 | { 124 | "image": "arrow_32.png", 125 | "x": 28, 126 | "y": 4 127 | }, 128 | { 129 | "image": "arrow_48.png", 130 | "x": 40, 131 | "y": 6 132 | } 133 | ] 134 | }, 135 | "MOVE": { 136 | "0409": "move_EN.cur", 137 | "040C": "move_FR.cur" 138 | }, 139 | "#1": { 140 | "0000": { 141 | "image": "cross.png", 142 | "x": 16, 143 | "y": 16 144 | } 145 | } 146 | } 147 | } 148 | ``` 149 | 150 | This example contains 3 cursors: 151 | 152 | * `"ARROW"` contains two images (one for higher DPI). It is a json array. 153 | * `"MOVE"` uses cur files directly. It is different in French. It is a string. 154 | * `1` contains one image. It is an object. 155 | 156 | When a cursor is made with a png file, you have to provide the coordinates of the "hot spot", that is, the pixel that 157 | clicks. 158 | 159 | ### Manifest 160 | 161 | The manifest should be defined as resource `1` with language `0409`. 162 | 163 | #### As a JSON object 164 | 165 | ```json 166 | { 167 | "RT_MANIFEST": { 168 | "#1": { 169 | "0409": { 170 | "identity": { 171 | "name": "", 172 | "version": "" 173 | }, 174 | "description": "", 175 | "minimum-os": "win7", 176 | "execution-level": "as invoker", 177 | "ui-access": false, 178 | "auto-elevate": false, 179 | "dpi-awareness": "system", 180 | "disable-theming": false, 181 | "disable-window-filtering": false, 182 | "high-resolution-scrolling-aware": false, 183 | "ultra-high-resolution-scrolling-aware": false, 184 | "long-path-aware": false, 185 | "printer-driver-isolation": false, 186 | "gdi-scaling": false, 187 | "segment-heap": false, 188 | "use-common-controls-v6": false 189 | } 190 | } 191 | } 192 | } 193 | ``` 194 | 195 | All boolean values default to `false`. 196 | 197 | It is recommended to omit `identity` if your program is a plain application, not meant to be a side-by-side 198 | dependency. 199 | 200 | ##### Values for `"execution-level"`: 201 | 202 | - `""` (default) 203 | - `"highest"`: elevates to the highest level available to the current user 204 | - `"administrator"`: require the user to be an administrator and elevate to this level 205 | 206 | ##### Values for `"minimum-os"`: 207 | 208 | - `"vista"` 209 | - `"win7"` (default) 210 | - `"win8"` 211 | - `"win8.1"` 212 | - `"win10"` 213 | 214 | ##### Values for `"dpi-awareness"`: 215 | 216 | - `"unaware"` 217 | - `"system"` (default) 218 | - `"per monitor"` 219 | - `"per monitor v2"` (recommended) 220 | 221 | #### As an XML file 222 | 223 | ```json 224 | { 225 | "RT_MANIFEST": { 226 | "#1": { 227 | "0409": "my_manifest.xml" 228 | } 229 | } 230 | } 231 | ``` 232 | 233 | ### VersionInfo JSON 234 | 235 | Here is an example JSON file containing every standard info field, a French translation, and every possible flag. 236 | `"0409"` and `"040C"` are language code identifiers (LCID) for `en-US` and `fr-FR` respectively. 237 | 238 | ```json 239 | { 240 | "RT_VERSION": { 241 | "#1": { 242 | "0000": { 243 | "fixed": { 244 | "file_version": "1.2.3.4", 245 | "product_version": "1.2.3.42", 246 | "flags": "Debug,Prerelease,Patched,PrivateBuild,SpecialBuild", 247 | "timestamp": "2020-12-18T23:00:00+01:00" 248 | }, 249 | "info": { 250 | "0409": { 251 | "Comments": "Comments", 252 | "CompanyName": "Company", 253 | "FileDescription": "A description", 254 | "FileVersion": "1.2.3.4", 255 | "InternalName": "", 256 | "LegalCopyright": "© You", 257 | "LegalTrademarks": "", 258 | "OriginalFilename": "X.EXE", 259 | "PrivateBuild": "", 260 | "ProductName": "Product", 261 | "ProductVersion": "1.2.3.42 beta", 262 | "SpecialBuild": "" 263 | }, 264 | "040C": { 265 | "Comments": "Commentaire", 266 | "CompanyName": "Compagnie", 267 | "FileDescription": "Une description", 268 | "FileVersion": "1.2.3.4", 269 | "InternalName": "", 270 | "LegalCopyright": "© Vous", 271 | "LegalTrademarks": "", 272 | "OriginalFilename": "X.EXE", 273 | "PrivateBuild": "", 274 | "ProductName": "Produit", 275 | "ProductVersion": "1.2.3.42 bêta", 276 | "SpecialBuild": "" 277 | } 278 | } 279 | } 280 | } 281 | } 282 | } 283 | ``` 284 | 285 | ## Alternatives 286 | 287 | This project is similar to [akavel/rsrc](https://www.github.com/akavel/rsrc/) 288 | and [josephspurrier/goversioninfo](https://github.com/josephspurrier/goversioninfo). 289 | 290 | Additional features are: 291 | 292 | - Multilingual resources 293 | - Multilingual VersionInfo that works in Windows Explorer 294 | - Explicitly named resources, by ID or by string (so you can use them in runtime) 295 | - Extracting resources from `exe` or `dll` files 296 | - Replacing resources in `exe` or `dll` files 297 | - Simplified VersionInfo definition 298 | - Simplified manifest definition 299 | - Support for custom information in VersionInfo 300 | - Making an icon or a cursor from a PNG file 301 | - Embedding custom resources 302 | 303 | It might be closer to Microsoft specifications too. 304 | 305 | ## Limitations 306 | 307 | `go-winres` is not a real resource compiler, which means it won't help you embed these UI templates: 308 | 309 | - `ACCELERATORS` 310 | - `DIALOGEX` 311 | - `MENUEX` 312 | - `POPUP` 313 | 314 | If you ever need them, you can use one of those tools instead: 315 | 316 | - `rc.exe` and `cvtres.exe` from Visual Studio 317 | - `windres` from GNU Binary Utilities 318 | - `llvm-rc` and `llvm-cvtres` from LLVM tools 319 | 320 | See [Resource Compiler](https://docs.microsoft.com/en-us/windows/win32/menurc/resource-compiler) for more information. 321 | 322 | ## Thanks 323 | 324 | Many thanks to [akavel](https://github.com/akavel) for his help. 325 | 326 | This project uses these very helpful libs: 327 | 328 | - [nfnt/resize](https://github.com/nfnt/resize) - pure Go image resizing 329 | - [urfave/cli](https://github.com/urfave/cli) - makes building a CLI easier 330 | -------------------------------------------------------------------------------- /_testdata/cur-32x64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tc-hib/go-winres/c4d55a3dfc2e22a4a9fb95ae0280ce106daadce9/_testdata/cur-32x64.png -------------------------------------------------------------------------------- /_testdata/cur-64x128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tc-hib/go-winres/c4d55a3dfc2e22a4a9fb95ae0280ce106daadce9/_testdata/cur-64x128.png -------------------------------------------------------------------------------- /_testdata/cursor.cur: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tc-hib/go-winres/c4d55a3dfc2e22a4a9fb95ae0280ce106daadce9/_testdata/cursor.cur -------------------------------------------------------------------------------- /_testdata/en.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tc-hib/go-winres/c4d55a3dfc2e22a4a9fb95ae0280ce106daadce9/_testdata/en.ico -------------------------------------------------------------------------------- /_testdata/fr.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tc-hib/go-winres/c4d55a3dfc2e22a4a9fb95ae0280ce106daadce9/_testdata/fr.ico -------------------------------------------------------------------------------- /_testdata/icons.json: -------------------------------------------------------------------------------- 1 | { 2 | "RT_GROUP_ICON": { 3 | "APP": { 4 | "0000": [ 5 | "cur-32x64.png", 6 | "cur-64x128.png" 7 | ] 8 | }, 9 | "#42": { 10 | "040C": "fr.ico", 11 | "0409": "en.ico" 12 | }, 13 | "#1": { 14 | "0000": "../icon.png" 15 | } 16 | }, 17 | "RT_GROUP_CURSOR": { 18 | "ARROW": { 19 | "0000": { 20 | "x": 58, 21 | "y": 34, 22 | "image": "cur-64x128.png" 23 | } 24 | }, 25 | "ARROW2": { 26 | "0000": [ 27 | { 28 | "x": 29, 29 | "y": 17, 30 | "image": "cur-32x64.png" 31 | }, 32 | { 33 | "x": 58, 34 | "y": 34, 35 | "image": "cur-64x128.png" 36 | } 37 | ] 38 | }, 39 | "ARROW3": { 40 | "0000": "cursor.cur" 41 | } 42 | } 43 | } -------------------------------------------------------------------------------- /_testdata/image.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tc-hib/go-winres/c4d55a3dfc2e22a4a9fb95ae0280ce106daadce9/_testdata/image.bmp -------------------------------------------------------------------------------- /_testdata/image.dib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tc-hib/go-winres/c4d55a3dfc2e22a4a9fb95ae0280ce106daadce9/_testdata/image.dib -------------------------------------------------------------------------------- /_testdata/rh.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tc-hib/go-winres/c4d55a3dfc2e22a4a9fb95ae0280ce106daadce9/_testdata/rh.exe -------------------------------------------------------------------------------- /_testdata/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "RT_VERSION": { 3 | "#1": { 4 | "0409": { 5 | "info": { 6 | "0409": { 7 | "FileDescription": "go-winres command line tool", 8 | "InternalName": "go-winres", 9 | "LegalCopyright": "© Thomas Combeléran", 10 | "OriginalFilename": "go-winres.exe", 11 | "ProductName": "go-winres" 12 | } 13 | } 14 | } 15 | } 16 | }, 17 | "RT_BITMAP": { 18 | "IMAGE": { 19 | "0000": "image.bmp", 20 | "0042": "image.dib" 21 | } 22 | }, 23 | "CUSTOM DATA": { 24 | "#1": { 25 | "0042": "image.dib" 26 | } 27 | }, 28 | "RT_MANIFEST": { 29 | "#1": { 30 | "0409": { 31 | "dpi-awareness": "per monitor v2" 32 | } 33 | } 34 | }, 35 | "RT_GROUP_ICON": { 36 | "APP": { 37 | "0000": [ 38 | "cur-32x64.png", 39 | "cur-64x128.png" 40 | ] 41 | }, 42 | "#42": { 43 | "040C": "fr.ico", 44 | "0409": "en.ico" 45 | }, 46 | "#1": { 47 | "0000": "../icon.png" 48 | } 49 | }, 50 | "RT_GROUP_CURSOR": { 51 | "ARROW": { 52 | "0000": { 53 | "x": 58, 54 | "y": 34, 55 | "image": "cur-64x128.png" 56 | } 57 | }, 58 | "ARROW2": { 59 | "0000": [ 60 | { 61 | "x": 29, 62 | "y": 17, 63 | "image": "cur-32x64.png" 64 | }, 65 | { 66 | "x": 58, 67 | "y": 34, 68 | "image": "cur-64x128.png" 69 | } 70 | ] 71 | }, 72 | "ARROW3": { 73 | "0000": "cursor.cur" 74 | } 75 | } 76 | } -------------------------------------------------------------------------------- /_testdata/vs0.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tc-hib/go-winres/c4d55a3dfc2e22a4a9fb95ae0280ce106daadce9/_testdata/vs0.exe -------------------------------------------------------------------------------- /defaulticon_go1.16.go: -------------------------------------------------------------------------------- 1 | // +build go1.16 2 | 3 | package main 4 | 5 | import _ "embed" 6 | 7 | //go:embed icon.png 8 | var initIcon []byte 9 | 10 | //go:embed icon16.png 11 | var initIcon16 []byte 12 | -------------------------------------------------------------------------------- /defaulticon_other.go: -------------------------------------------------------------------------------- 1 | // +build !go1.16 2 | 3 | package main 4 | 5 | var initIcon []byte = []byte{ 6 | 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A, 0x00, 0x00, 0x00, 0x0D, 0x49, 0x48, 0x44, 0x52, 7 | 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x06, 0x00, 0x00, 0x00, 0x5C, 0x72, 0xA8, 8 | 0x66, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, 0x47, 0x42, 0x00, 0xAE, 0xCE, 0x1C, 0xE9, 0x00, 0x00, 9 | 0x00, 0x04, 0x67, 0x41, 0x4D, 0x41, 0x00, 0x00, 0xB1, 0x8F, 0x0B, 0xFC, 0x61, 0x05, 0x00, 0x00, 10 | 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0E, 0xC0, 0x00, 0x00, 0x0E, 0xC0, 0x01, 0x6A, 11 | 0xD6, 0x89, 0x09, 0x00, 0x00, 0x25, 0x23, 0x49, 0x44, 0x41, 0x54, 0x78, 0x5E, 0xED, 0xDD, 0x07, 12 | 0x78, 0x14, 0x45, 0x1B, 0x07, 0xF0, 0x97, 0x10, 0x52, 0x08, 0x25, 0xA1, 0x24, 0x40, 0xE8, 0x09, 13 | 0x49, 0xE8, 0x01, 0x42, 0x13, 0x10, 0xA4, 0x23, 0x08, 0xA2, 0xF0, 0x21, 0x45, 0x8A, 0x8A, 0x52, 14 | 0xA4, 0xF7, 0x5E, 0x24, 0x14, 0x41, 0x04, 0x44, 0x94, 0x8E, 0x34, 0x01, 0x01, 0x15, 0x54, 0xBA, 15 | 0x88, 0x40, 0xE8, 0xBD, 0x43, 0xE8, 0x25, 0x21, 0xB4, 0x50, 0x53, 0x48, 0xE0, 0xDB, 0x77, 0x32, 16 | 0x47, 0x42, 0x72, 0x77, 0xC9, 0x25, 0xB7, 0x47, 0xD6, 0xFD, 0xFF, 0x9E, 0x67, 0x9F, 0xBD, 0x9B, 17 | 0xDB, 0xDB, 0xA3, 0xEC, 0xFC, 0x77, 0x76, 0x76, 0x77, 0x36, 0xC3, 0xCB, 0x97, 0x2F, 0x09, 0x00, 18 | 0xF4, 0xC9, 0x4E, 0xCE, 0x01, 0x40, 0x87, 0x10, 0x00, 0x00, 0x3A, 0x86, 0x00, 0x00, 0xD0, 0x31, 19 | 0x04, 0x00, 0x80, 0x8E, 0x21, 0x00, 0x00, 0x74, 0x0C, 0x01, 0x00, 0xA0, 0x63, 0x08, 0x00, 0x00, 20 | 0x1D, 0x43, 0x00, 0x00, 0xE8, 0x18, 0x02, 0x00, 0x40, 0xC7, 0x10, 0x00, 0x00, 0x3A, 0x86, 0x00, 21 | 0x00, 0xD0, 0x31, 0x04, 0x00, 0x80, 0x8E, 0x21, 0x00, 0x00, 0x74, 0x0C, 0x01, 0x00, 0xA0, 0x63, 22 | 0x08, 0x00, 0x00, 0x1D, 0x43, 0x00, 0x00, 0xE8, 0x18, 0x02, 0x00, 0x40, 0xC7, 0x10, 0x00, 0x00, 23 | 0x3A, 0x86, 0x00, 0x00, 0xD0, 0x31, 0x04, 0x00, 0x80, 0x8E, 0x21, 0x00, 0x00, 0x74, 0xCC, 0xE6, 24 | 0xA3, 0x02, 0x67, 0xC8, 0x90, 0xC1, 0x55, 0x99, 0xB5, 0x53, 0xA6, 0x06, 0xCA, 0xE4, 0xAF, 0x4C, 25 | 0xF9, 0x95, 0x09, 0x40, 0xAF, 0x6E, 0x28, 0xD3, 0x51, 0x65, 0xDA, 0xA4, 0x4C, 0x4B, 0x95, 0xFA, 26 | 0x18, 0xCE, 0x85, 0xB6, 0x62, 0xB3, 0x00, 0x50, 0x2A, 0xBE, 0x93, 0x32, 0x1B, 0xA6, 0x4C, 0xFD, 27 | 0x95, 0x89, 0x5F, 0x93, 0x63, 0xCE, 0x42, 0xE4, 0x5A, 0xBA, 0x21, 0xBF, 0x04, 0xD0, 0xA5, 0xF0, 28 | 0x13, 0x1B, 0x29, 0xEA, 0xDE, 0x55, 0xF9, 0x8E, 0x22, 0x95, 0x69, 0x8A, 0x32, 0x05, 0x2A, 0xF5, 29 | 0x92, 0x5F, 0xAB, 0xCE, 0x26, 0x01, 0xA0, 0x54, 0x7E, 0x6F, 0x65, 0xF6, 0xAB, 0x32, 0x95, 0xE2, 30 | 0x4A, 0x9F, 0xBF, 0xE9, 0xB0, 0xE0, 0x6C, 0xC5, 0x6A, 0xDC, 0x73, 0xF2, 0xF0, 0x2E, 0x9E, 0x21, 31 | 0xA3, 0x7D, 0x36, 0xB1, 0x10, 0x80, 0x0E, 0xBD, 0x8C, 0x8D, 0x79, 0x14, 0x79, 0x3B, 0xF8, 0xCC, 32 | 0xA3, 0x0B, 0x3B, 0x73, 0xDE, 0x58, 0x17, 0xE8, 0x2D, 0xC3, 0xE0, 0xA4, 0x32, 0x35, 0x57, 0xEA, 33 | 0x66, 0x30, 0xBF, 0x51, 0x93, 0xEA, 0x01, 0x20, 0x2B, 0xFF, 0x4E, 0xA5, 0xE2, 0xE7, 0x71, 0xAF, 34 | 0xDE, 0xF1, 0x9E, 0x67, 0x93, 0x21, 0x2F, 0xEC, 0x32, 0x39, 0xE6, 0x8E, 0xFB, 0x14, 0x00, 0x0C, 35 | 0x5E, 0x3C, 0x8F, 0xBA, 0x73, 0xF3, 0x8F, 0x09, 0x76, 0x61, 0xBB, 0x16, 0xE5, 0x54, 0x82, 0x20, 36 | 0x54, 0x29, 0xAA, 0xA1, 0x76, 0x08, 0xA8, 0x1A, 0x00, 0xB2, 0xD9, 0x7F, 0x40, 0xA9, 0xFC, 0xA5, 37 | 0x0A, 0xB7, 0x99, 0x7A, 0x3B, 0x67, 0x85, 0x0F, 0x3C, 0xE2, 0x3E, 0x01, 0x00, 0x53, 0xEE, 0x1D, 38 | 0x5A, 0x7B, 0xFB, 0xCA, 0xF2, 0xBE, 0x1E, 0x4A, 0x08, 0x70, 0x4B, 0xA0, 0xA2, 0x52, 0x47, 0x55, 39 | 0x3B, 0x1C, 0x50, 0xFB, 0x2C, 0x00, 0x1F, 0xF3, 0x97, 0xE2, 0x3D, 0x3F, 0x2A, 0x3F, 0x40, 0xCA, 40 | 0x70, 0x5D, 0xE1, 0x3A, 0xA3, 0xBC, 0x2C, 0xA5, 0x4C, 0x5C, 0x87, 0x54, 0xA3, 0x5A, 0x0B, 0x40, 41 | 0xF6, 0xF6, 0x87, 0x28, 0x7B, 0x7F, 0xA7, 0x72, 0x13, 0xCF, 0xDD, 0x41, 0xB3, 0x1F, 0x20, 0xE5, 42 | 0xF8, 0x70, 0xE0, 0xC8, 0x60, 0xDF, 0xDC, 0x4A, 0x2B, 0x80, 0xF7, 0xFE, 0x79, 0x95, 0x7A, 0xAA, 43 | 0xCA, 0xD9, 0x01, 0x35, 0x5B, 0x00, 0x7C, 0xAA, 0xCF, 0x89, 0x3B, 0xFC, 0x50, 0xF9, 0x01, 0x2C, 44 | 0xC3, 0x75, 0x86, 0xEB, 0x8E, 0xF2, 0x92, 0x0F, 0xA3, 0xB9, 0x2E, 0xA9, 0x42, 0xCD, 0x00, 0xE0, 45 | 0xF3, 0xFC, 0xC4, 0xBD, 0xFD, 0xE2, 0x1D, 0x00, 0x58, 0x24, 0xAB, 0x77, 0xB5, 0xFB, 0xF2, 0x65, 46 | 0x1D, 0x39, 0xB7, 0x3A, 0x35, 0x03, 0xC0, 0x9F, 0x4F, 0xF9, 0xF1, 0xA9, 0x3E, 0xF9, 0x1E, 0x00, 47 | 0x2C, 0xE0, 0x9C, 0xC7, 0xC7, 0x8F, 0xEB, 0x90, 0x22, 0x40, 0x14, 0xA8, 0x40, 0xCD, 0x00, 0xC8, 48 | 0xCF, 0x17, 0xF9, 0xE0, 0x3C, 0x3F, 0x40, 0xEA, 0x70, 0xDD, 0x91, 0x17, 0xCA, 0xA9, 0x76, 0xB5, 49 | 0xAC, 0xDA, 0x67, 0x01, 0x00, 0x20, 0x1D, 0x43, 0x00, 0x00, 0xE8, 0x18, 0x02, 0x00, 0x40, 0xC7, 50 | 0x10, 0x00, 0x00, 0x3A, 0x86, 0x00, 0x00, 0xD0, 0x31, 0x04, 0x00, 0x80, 0x8E, 0x21, 0x00, 0x00, 51 | 0x74, 0x0C, 0x01, 0x00, 0xA0, 0x63, 0x08, 0x00, 0x00, 0x1D, 0x43, 0x00, 0x00, 0xE8, 0x98, 0x9A, 52 | 0xB7, 0x03, 0xBF, 0xF4, 0x6F, 0x31, 0x88, 0x02, 0x3A, 0x4E, 0x94, 0x25, 0x00, 0x60, 0xA9, 0x83, 53 | 0x8B, 0x06, 0xD3, 0xD1, 0xD5, 0x93, 0x48, 0xA9, 0xA7, 0x19, 0x64, 0x91, 0x55, 0xA9, 0x1A, 0x00, 54 | 0x5F, 0x7C, 0xF1, 0x05, 0xFD, 0xF8, 0xE3, 0x8F, 0xB2, 0x04, 0x00, 0x2C, 0xD5, 0xA5, 0x4B, 0x17, 55 | 0x9A, 0x3D, 0x7B, 0xB6, 0x6A, 0x01, 0x80, 0x43, 0x00, 0x00, 0x1D, 0x43, 0x00, 0x00, 0xE8, 0x18, 56 | 0x02, 0x00, 0x40, 0xC7, 0x10, 0x00, 0x00, 0x3A, 0x86, 0x00, 0x00, 0xD0, 0x31, 0x04, 0x00, 0x80, 57 | 0x8E, 0x21, 0x00, 0x00, 0x74, 0x0C, 0x01, 0x00, 0xA0, 0x63, 0x08, 0x00, 0x00, 0x1D, 0x43, 0x00, 58 | 0x00, 0xE8, 0x18, 0x02, 0x00, 0x40, 0xC7, 0x10, 0x00, 0x00, 0x3A, 0x86, 0x00, 0x00, 0xD0, 0x31, 59 | 0x04, 0x00, 0x80, 0x8E, 0x21, 0x00, 0x00, 0x74, 0x0C, 0x01, 0x00, 0xA0, 0x63, 0x08, 0x00, 0x00, 60 | 0x1D, 0xFB, 0xCF, 0x8C, 0x08, 0xC4, 0x7F, 0x8F, 0x88, 0x88, 0x08, 0x8A, 0x8A, 0x8A, 0xA2, 0xE8, 61 | 0xE8, 0x68, 0x8A, 0x8D, 0x8D, 0x95, 0x9F, 0x00, 0x58, 0x47, 0xC6, 0x8C, 0x19, 0xC9, 0xC1, 0xC1, 62 | 0x81, 0x1C, 0x1D, 0x1D, 0xC9, 0xD9, 0xD9, 0x99, 0xB7, 0x71, 0xF9, 0x89, 0x7A, 0x30, 0x22, 0x50, 63 | 0x0A, 0x70, 0xC5, 0x0F, 0x0B, 0x0B, 0xA3, 0xF0, 0xF0, 0x70, 0xF1, 0x1A, 0x95, 0x1F, 0xD4, 0xC0, 64 | 0xDB, 0x15, 0x6F, 0x5F, 0xBC, 0x9D, 0xF1, 0xF6, 0xC6, 0xAF, 0xB5, 0x4E, 0xD3, 0x01, 0xC0, 0x7B, 65 | 0xFD, 0x87, 0x0F, 0x1F, 0xD2, 0x83, 0x07, 0x0F, 0x50, 0xE9, 0xC1, 0xA6, 0x78, 0x7B, 0xE3, 0xED, 66 | 0x8E, 0xB7, 0x3F, 0xB5, 0x5A, 0xD1, 0xB6, 0xA0, 0xE9, 0x00, 0x78, 0xF4, 0xE8, 0x11, 0x3D, 0x7D, 67 | 0xFA, 0x54, 0xBE, 0x03, 0xB0, 0x3D, 0xDE, 0xFE, 0x78, 0x3B, 0xD4, 0x2A, 0xCD, 0x06, 0x00, 0x37, 68 | 0xBF, 0x50, 0xF9, 0x21, 0x3D, 0xE0, 0xED, 0x50, 0xAB, 0x87, 0x03, 0x9A, 0x0C, 0x00, 0x6E, 0x72, 69 | 0x69, 0x39, 0x75, 0xE1, 0xBF, 0x87, 0xB7, 0x47, 0x2D, 0x1E, 0x0A, 0x68, 0x32, 0x00, 0xD0, 0xD1, 70 | 0x07, 0xE9, 0x8D, 0xA1, 0x83, 0x50, 0x6B, 0x34, 0x19, 0x00, 0x7C, 0xAA, 0x0F, 0x20, 0xBD, 0xD1, 71 | 0xE2, 0x76, 0xA9, 0xC9, 0x00, 0xE0, 0xF3, 0xFC, 0x00, 0xE9, 0x8D, 0x16, 0xB7, 0x4B, 0x4D, 0x06, 72 | 0x00, 0x9A, 0xFF, 0x90, 0x1E, 0x69, 0x71, 0xBB, 0xD4, 0x64, 0x00, 0x00, 0x80, 0x75, 0x20, 0x00, 73 | 0x00, 0x74, 0x0C, 0x01, 0x00, 0xA0, 0x63, 0x08, 0x00, 0x00, 0x1D, 0x43, 0x00, 0x68, 0xC8, 0xED, 74 | 0xB0, 0xBB, 0x74, 0xE7, 0xEE, 0x3D, 0xF9, 0x0E, 0x20, 0xED, 0x10, 0x00, 0x1A, 0x11, 0x12, 0x7A, 75 | 0x9B, 0x3E, 0xFE, 0xAC, 0x27, 0xB5, 0xFD, 0xA4, 0x07, 0x5D, 0xB9, 0x76, 0x43, 0x96, 0x02, 0xA4, 76 | 0x0D, 0x02, 0x40, 0x23, 0x12, 0xDE, 0x7B, 0xAE, 0xFE, 0x5D, 0xE8, 0xA0, 0x17, 0x08, 0x00, 0x8D, 77 | 0xC8, 0xE3, 0xE1, 0x4E, 0x4B, 0xE6, 0xCD, 0xA0, 0xE5, 0x0B, 0x66, 0x52, 0xA1, 0x82, 0xF9, 0x65, 78 | 0x29, 0x40, 0xDA, 0x20, 0x00, 0x34, 0xC4, 0xC3, 0x3D, 0x17, 0xE5, 0xCA, 0x95, 0x43, 0xBE, 0x03, 79 | 0x48, 0x3B, 0x04, 0x00, 0x80, 0x8E, 0x21, 0x00, 0x00, 0x74, 0x4C, 0x93, 0x83, 0x82, 0xDE, 0xBA, 80 | 0x75, 0x4B, 0xBE, 0x4A, 0x1F, 0xF8, 0xF4, 0xDC, 0xF1, 0x93, 0xA7, 0xA9, 0x70, 0xC1, 0x02, 0x54, 81 | 0xCC, 0xBB, 0x88, 0x2C, 0x35, 0x2E, 0x68, 0xDF, 0x41, 0x71, 0xDF, 0x78, 0xB5, 0x2A, 0x15, 0x65, 82 | 0x89, 0x71, 0x1B, 0x36, 0xFF, 0x4D, 0xCF, 0x9F, 0xC7, 0x50, 0xD3, 0xC6, 0xF5, 0x65, 0x09, 0xD1, 83 | 0x9F, 0x1B, 0xB7, 0x89, 0x79, 0xE3, 0x86, 0x75, 0xC4, 0x3C, 0xA1, 0xED, 0xFF, 0x06, 0x89, 0xF9, 84 | 0x3B, 0x6F, 0xBF, 0x25, 0xE6, 0x6C, 0x67, 0xD0, 0x3E, 0x3A, 0x7C, 0xF4, 0x24, 0x85, 0x29, 0x7F, 85 | 0xBE, 0xAC, 0x59, 0xB3, 0x50, 0xE1, 0x42, 0x05, 0xC8, 0x47, 0xF9, 0xF3, 0x95, 0xF7, 0x2F, 0x2D, 86 | 0x97, 0x30, 0x6E, 0xE3, 0x96, 0x7F, 0xC8, 0xDB, 0xAB, 0x30, 0x79, 0x17, 0x2D, 0x2C, 0xDE, 0xEF, 87 | 0xDE, 0x7B, 0x80, 0x4E, 0x9E, 0x3A, 0x47, 0x77, 0xEF, 0xDD, 0xA7, 0xFC, 0x9E, 0xF9, 0xA8, 0x43, 88 | 0xDB, 0x16, 0xA2, 0x3C, 0xB1, 0x4B, 0x97, 0xAF, 0xD2, 0x99, 0x73, 0xC1, 0xCA, 0x74, 0x81, 0x1E, 89 | 0x3F, 0x7E, 0xA2, 0xFC, 0x5B, 0x14, 0x15, 0xBF, 0x57, 0x29, 0xA0, 0x9C, 0x5C, 0xC2, 0xBC, 0x5D, 90 | 0x41, 0xFB, 0xC5, 0xF7, 0xAF, 0xDF, 0x88, 0xFB, 0xFF, 0x75, 0xCF, 0x9D, 0x93, 0x8A, 0xFB, 0x16, 91 | 0xA3, 0x3A, 0xEF, 0x54, 0x17, 0xEF, 0xB5, 0x20, 0x5F, 0xBE, 0x7C, 0xF2, 0x95, 0x75, 0x60, 0x50, 92 | 0x50, 0x0D, 0x78, 0x16, 0x11, 0x41, 0x93, 0xA7, 0xFD, 0x48, 0x2B, 0xD7, 0xAE, 0x97, 0x25, 0xA6, 93 | 0xCD, 0x5B, 0xF4, 0x33, 0x2D, 0x5C, 0xB2, 0x4A, 0xBE, 0x33, 0xEE, 0xE1, 0xA3, 0xC7, 0xF4, 0xED, 94 | 0xCC, 0x79, 0x74, 0xE8, 0xC8, 0x71, 0x59, 0x12, 0xE7, 0xB7, 0xF5, 0x1B, 0x69, 0xC1, 0xE2, 0x15, 95 | 0xF2, 0xDD, 0xEB, 0xD6, 0xFD, 0xB9, 0x99, 0x26, 0x4C, 0x99, 0x29, 0x5E, 0x9F, 0x3C, 0x7D, 0x8E, 96 | 0x3E, 0xEB, 0x3E, 0x80, 0xBE, 0x9A, 0x38, 0x5D, 0x84, 0x86, 0x73, 0x66, 0x67, 0x0A, 0xBE, 0x74, 97 | 0x45, 0x7C, 0x77, 0xF0, 0xC8, 0x09, 0xB4, 0x7C, 0xD5, 0xAF, 0x62, 0x39, 0x63, 0xC2, 0xEE, 0xDC, 98 | 0xA5, 0xA9, 0xDF, 0xCD, 0xA1, 0x83, 0x87, 0x8F, 0x89, 0xF7, 0xD3, 0x67, 0xCD, 0xA7, 0x31, 0xE3, 99 | 0xBF, 0xA5, 0x35, 0xBF, 0xFF, 0x45, 0xB7, 0x42, 0x6F, 0xD3, 0xB2, 0x95, 0x6B, 0x29, 0xF4, 0x76, 100 | 0x98, 0xF8, 0xCC, 0x20, 0x2A, 0x3A, 0x9A, 0x26, 0x7E, 0x33, 0x93, 0xBA, 0xF4, 0x1A, 0x42, 0x3F, 101 | 0xCE, 0x5F, 0x42, 0xB7, 0x42, 0x6E, 0x53, 0x4C, 0x4C, 0x2C, 0x2D, 0x5E, 0xBE, 0x9A, 0x86, 0x8F, 102 | 0x9D, 0x2C, 0x7E, 0xF3, 0xA1, 0x99, 0x01, 0x5C, 0x38, 0x40, 0x07, 0x0E, 0x1F, 0x47, 0x63, 0x27, 103 | 0x4E, 0xA3, 0x03, 0x47, 0x8E, 0x51, 0x46, 0x7B, 0x7B, 0x7A, 0xFA, 0xEC, 0x19, 0x6D, 0xDF, 0xB1, 104 | 0x9B, 0x26, 0x7D, 0x3B, 0x8B, 0xBA, 0xF6, 0x1C, 0x2C, 0x97, 0x04, 0x6B, 0x43, 0x00, 0x58, 0x41, 105 | 0x11, 0x65, 0xCF, 0xCA, 0xF6, 0xEC, 0x3B, 0x24, 0xE6, 0xA6, 0xF0, 0x86, 0x7E, 0xE3, 0x66, 0x08, 106 | 0x5D, 0xBB, 0x7E, 0x93, 0x9E, 0x3C, 0x31, 0x3D, 0x9C, 0xD9, 0x1E, 0xA5, 0x95, 0xC0, 0xEA, 0xD7, 107 | 0xAD, 0x29, 0xE6, 0x96, 0x38, 0x79, 0xFA, 0x2C, 0xF5, 0x1D, 0x3C, 0x86, 0x0A, 0xE5, 0xF7, 0xA4, 108 | 0x25, 0x73, 0xA7, 0xD3, 0xE6, 0x75, 0xCB, 0x69, 0xF8, 0xC0, 0x9E, 0x34, 0xEF, 0xFB, 0xC9, 0x34, 109 | 0x6B, 0xEA, 0x38, 0xF2, 0xF3, 0xF5, 0xA2, 0x45, 0x4B, 0x7F, 0x11, 0x15, 0x3A, 0x39, 0xB3, 0x17, 110 | 0x2C, 0x11, 0x01, 0xC2, 0x7B, 0x7C, 0x5E, 0xCF, 0xF7, 0x53, 0x03, 0x69, 0xB1, 0xB2, 0x4E, 0x3E, 111 | 0x23, 0x61, 0x70, 0xFA, 0xCC, 0x79, 0xEA, 0xDE, 0x67, 0x18, 0x1D, 0x51, 0x5A, 0x1A, 0x43, 0xFA, 112 | 0x7F, 0x49, 0xEB, 0x7F, 0x59, 0x44, 0x53, 0x27, 0x8E, 0xA2, 0xC0, 0xD1, 0x83, 0xC4, 0x77, 0x06, 113 | 0xF6, 0xE9, 0x46, 0x47, 0x8E, 0x9D, 0xA4, 0x5E, 0x03, 0x46, 0x8B, 0xBF, 0x7F, 0x62, 0xDC, 0x1A, 114 | 0x0A, 0x9C, 0xFC, 0x9D, 0xD8, 0xF3, 0x8F, 0x1E, 0xD6, 0x97, 0xE6, 0xCC, 0x98, 0x44, 0xA3, 0x86, 115 | 0xF4, 0xA6, 0x6F, 0x26, 0x8C, 0xA4, 0x35, 0x3F, 0xCF, 0xA3, 0xA1, 0xFD, 0x7B, 0x28, 0xC1, 0xF3, 116 | 0x7A, 0xE0, 0x80, 0xF5, 0x20, 0x00, 0xAC, 0xA4, 0x66, 0xF5, 0x2A, 0x4A, 0x93, 0xFD, 0x39, 0x5D, 117 | 0x08, 0xBE, 0x2C, 0x4B, 0x92, 0xFA, 0x77, 0xD7, 0x5E, 0xCA, 0x99, 0xC3, 0x4D, 0xBC, 0xDE, 0x7F, 118 | 0xE8, 0xA8, 0x98, 0x1B, 0x13, 0xB4, 0x37, 0x2E, 0x48, 0x92, 0x3B, 0x4C, 0x30, 0x66, 0xD6, 0x9C, 119 | 0xC5, 0x14, 0x50, 0xBE, 0x0C, 0x8D, 0x50, 0x2A, 0x91, 0x87, 0x47, 0x6E, 0x59, 0x1A, 0xC7, 0x5B, 120 | 0x69, 0x92, 0x4F, 0xFF, 0x7A, 0x2C, 0x79, 0xB8, 0xE7, 0xA4, 0xF5, 0x7F, 0x6D, 0x95, 0xA5, 0xC6, 121 | 0x3D, 0x79, 0xF2, 0x8C, 0xB6, 0x6C, 0xDB, 0xA9, 0x54, 0xE6, 0x91, 0xD4, 0xB6, 0xD5, 0x07, 0xB2, 122 | 0x94, 0x4F, 0x47, 0xBE, 0xBE, 0xCE, 0x39, 0x0B, 0x97, 0x51, 0x44, 0x44, 0x24, 0xCD, 0xFE, 0x6E, 123 | 0xD2, 0x6B, 0x87, 0x1F, 0x06, 0x75, 0x95, 0xE6, 0xFB, 0xF7, 0xDF, 0x06, 0x2A, 0xAD, 0x82, 0x50, 124 | 0xFA, 0x75, 0xDD, 0x06, 0x59, 0x1A, 0x6F, 0xD3, 0xD6, 0x1D, 0x74, 0x56, 0x39, 0x64, 0xE8, 0xD7, 125 | 0xE3, 0x73, 0x7A, 0xAB, 0x72, 0x80, 0x2C, 0x8D, 0x57, 0xEB, 0xED, 0xAA, 0xF4, 0xFB, 0xAA, 0x05, 126 | 0xF2, 0x1D, 0x58, 0x1B, 0x02, 0xC0, 0x4A, 0xEA, 0xBE, 0x53, 0x43, 0xCC, 0xF7, 0xEC, 0x37, 0xDD, 127 | 0x0A, 0xE0, 0x63, 0xF2, 0xAA, 0x95, 0xCB, 0x93, 0x5B, 0xF6, 0x6C, 0xB4, 0xEF, 0xC0, 0x11, 0x59, 128 | 0x9A, 0xD4, 0x7E, 0xA5, 0xF9, 0x5D, 0xAA, 0x84, 0xAF, 0x7C, 0x67, 0x99, 0x67, 0x4A, 0x65, 0x1C, 129 | 0x3F, 0xDA, 0x74, 0x93, 0x99, 0x2F, 0x28, 0x7A, 0xFF, 0xBD, 0x46, 0xA2, 0x42, 0x9A, 0x6B, 0xB1, 130 | 0x6C, 0xDB, 0xBE, 0x93, 0x1A, 0x37, 0xAA, 0xAB, 0xFC, 0x39, 0xFC, 0x64, 0x49, 0x52, 0xDB, 0xFE, 131 | 0xD9, 0x4D, 0xA7, 0xCF, 0x5E, 0xA0, 0x4F, 0x3B, 0x7C, 0x44, 0xAE, 0xAE, 0xD9, 0x65, 0x69, 0x52, 132 | 0xDC, 0x97, 0x50, 0xBF, 0x4E, 0x0D, 0xFA, 0x75, 0xFD, 0x06, 0x7A, 0xF8, 0xF0, 0xF5, 0x43, 0x81, 133 | 0xAB, 0xF2, 0xAA, 0xC6, 0x8A, 0x15, 0xFC, 0xC5, 0x1C, 0x6C, 0x0B, 0x01, 0x60, 0x25, 0x95, 0x2B, 134 | 0xC6, 0x75, 0x74, 0x99, 0xAA, 0x54, 0x8F, 0x1E, 0x3F, 0xA6, 0xB3, 0xE7, 0x2F, 0x52, 0xB9, 0xB2, 135 | 0xA5, 0xC8, 0x5F, 0x99, 0xF6, 0xED, 0x37, 0x1E, 0x00, 0xC7, 0x4E, 0x9C, 0xA6, 0x17, 0xB1, 0xB1, 136 | 0x4A, 0x85, 0x79, 0x5B, 0x96, 0x58, 0xA6, 0xDD, 0x47, 0xCD, 0xE5, 0x2B, 0xD3, 0x0C, 0x61, 0x65, 137 | 0xEE, 0xBE, 0x82, 0x7B, 0x0F, 0xC2, 0xC5, 0xDE, 0xDB, 0x9C, 0x15, 0xBF, 0xFC, 0x46, 0xBE, 0xDE, 138 | 0x5E, 0x54, 0xBB, 0x66, 0x35, 0x59, 0x62, 0x5A, 0xE3, 0x86, 0xF5, 0x94, 0xE6, 0x3E, 0xD1, 0x3F, 139 | 0x3B, 0xF7, 0xC8, 0x92, 0x38, 0x86, 0x4E, 0xE8, 0x90, 0x44, 0xFD, 0x0A, 0x60, 0x1B, 0x08, 0x00, 140 | 0x2B, 0x2A, 0x59, 0xDC, 0x87, 0x2E, 0x5E, 0xBE, 0x6A, 0xB4, 0xC3, 0xEB, 0xDF, 0xDD, 0xFB, 0xC4, 141 | 0xDE, 0xB7, 0x6A, 0xA5, 0x0A, 0xA2, 0x89, 0xFE, 0x2C, 0x32, 0x82, 0x2E, 0x5C, 0x4C, 0x7A, 0xB8, 142 | 0xC0, 0x67, 0x09, 0x58, 0xCD, 0xEA, 0x55, 0xC5, 0xDC, 0x52, 0xBE, 0x3E, 0x5E, 0xF2, 0x95, 0x69, 143 | 0xD9, 0xB3, 0x65, 0x25, 0xBB, 0x0C, 0xE6, 0x03, 0x80, 0x15, 0xF0, 0x34, 0xDD, 0xA3, 0x7D, 0xFD, 144 | 0x66, 0x08, 0x5D, 0xBD, 0x7E, 0x53, 0x39, 0xAC, 0x88, 0x3B, 0x53, 0x90, 0x1C, 0x43, 0x3F, 0x49, 145 | 0x68, 0xD8, 0x1D, 0x31, 0x37, 0x28, 0x50, 0xC0, 0x53, 0xCC, 0x0F, 0x1C, 0x34, 0x7D, 0x48, 0x04, 146 | 0xEA, 0x41, 0x00, 0x58, 0x91, 0xE1, 0x18, 0xF8, 0xC0, 0xA1, 0xD7, 0x7B, 0xEF, 0x59, 0xD0, 0xDE, 147 | 0x83, 0x4A, 0xE5, 0x2F, 0x4F, 0xF6, 0xF6, 0xF6, 0x54, 0xB1, 0x7C, 0x59, 0x51, 0x76, 0xE8, 0xC8, 148 | 0x09, 0x31, 0x4F, 0xE8, 0xE0, 0xE1, 0xE3, 0x54, 0x50, 0xA9, 0x14, 0xCE, 0xCE, 0x4E, 0xB2, 0x24, 149 | 0xE5, 0x9C, 0x9C, 0x1C, 0xCC, 0x56, 0xDA, 0x84, 0x5C, 0xDD, 0x5C, 0xE9, 0xCE, 0xBD, 0xFB, 0xF2, 150 | 0x5D, 0x52, 0x75, 0x6A, 0x99, 0xDF, 0xAB, 0x5F, 0xBB, 0x76, 0x5D, 0xCC, 0xFD, 0xCB, 0x94, 0xA4, 151 | 0x98, 0x98, 0x98, 0x64, 0x27, 0x7B, 0xFB, 0x8C, 0x22, 0x74, 0x42, 0x12, 0x75, 0xE8, 0x35, 0x6E, 152 | 0x50, 0x9B, 0xBC, 0x0A, 0x17, 0xA4, 0x85, 0x4B, 0x57, 0xD1, 0xDA, 0xDF, 0x93, 0xF6, 0x11, 0x80, 153 | 0xBA, 0x10, 0x00, 0x56, 0x64, 0x38, 0x5F, 0x7D, 0x20, 0x51, 0x07, 0x1F, 0x8F, 0x15, 0xC7, 0x15, 154 | 0xBB, 0x72, 0xC5, 0xF2, 0xE2, 0x3D, 0x1F, 0x2F, 0xF3, 0xF9, 0xED, 0xC4, 0xCB, 0xF1, 0x29, 0x38, 155 | 0x3E, 0x07, 0x5E, 0xBF, 0x76, 0xEA, 0x9A, 0xFF, 0x39, 0x94, 0x4A, 0x9D, 0x52, 0x99, 0xEC, 0x1D, 156 | 0x94, 0x43, 0x8D, 0x17, 0xF2, 0x5D, 0x52, 0x39, 0xDC, 0xE2, 0x3A, 0x2B, 0x4D, 0xE1, 0xBD, 0x3F, 157 | 0x0B, 0xFC, 0x7A, 0x06, 0xBD, 0xFB, 0x41, 0xFB, 0x14, 0x4D, 0x2F, 0x94, 0xD6, 0xFE, 0x6D, 0x23, 158 | 0x3D, 0xFA, 0x93, 0xC7, 0x8F, 0xA0, 0x4A, 0x15, 0xFD, 0xC5, 0x29, 0xC4, 0x2F, 0x7A, 0x0E, 0xA6, 159 | 0xCD, 0xDB, 0x76, 0xC8, 0x4F, 0x40, 0x6D, 0x08, 0x00, 0x2B, 0x72, 0xC9, 0x9C, 0x99, 0x3C, 0xF3, 160 | 0xE5, 0xA1, 0x3D, 0xFB, 0xE3, 0x9A, 0xF1, 0x06, 0x3B, 0x76, 0xED, 0x13, 0xF3, 0x1A, 0x6F, 0x55, 161 | 0x12, 0x73, 0x56, 0x29, 0xC0, 0x9F, 0x4E, 0x9C, 0x3A, 0x2B, 0x7A, 0xD0, 0x0D, 0x82, 0x64, 0xFF, 162 | 0x41, 0x8D, 0x6A, 0xF1, 0xCB, 0x59, 0xC2, 0x92, 0x41, 0x29, 0x33, 0xD0, 0x4B, 0x7A, 0xF1, 0xC2, 163 | 0x74, 0x00, 0xE4, 0xCA, 0x69, 0x3E, 0x00, 0xEE, 0xDF, 0x0F, 0x17, 0xF3, 0x4F, 0xDA, 0x7F, 0x44, 164 | 0x9F, 0x7F, 0xD2, 0xD6, 0xE4, 0xF4, 0xC5, 0xA7, 0xED, 0xC4, 0xD4, 0xE5, 0xD3, 0x8F, 0xC5, 0x64, 165 | 0xEC, 0xD4, 0x66, 0x96, 0x2C, 0x2E, 0x34, 0x6E, 0xC4, 0x40, 0x1A, 0xD4, 0xA7, 0x1B, 0xBD, 0x54, 166 | 0xFE, 0x0E, 0x53, 0xA6, 0xCF, 0xA6, 0xEE, 0x7D, 0x87, 0xD3, 0xCE, 0xA0, 0xFD, 0x72, 0x09, 0x50, 167 | 0x0B, 0x02, 0xC0, 0xCA, 0xB8, 0x92, 0x47, 0x46, 0x46, 0x8B, 0xCA, 0x6D, 0xB0, 0xEF, 0xC0, 0x61, 168 | 0x2A, 0x5D, 0xD2, 0x4F, 0x6C, 0xE8, 0x06, 0xDC, 0x0F, 0xC0, 0x12, 0x5E, 0xEC, 0x73, 0x58, 0x39, 169 | 0x24, 0xE0, 0x33, 0x04, 0x79, 0xF3, 0x78, 0xC8, 0x12, 0xCB, 0xC4, 0xC6, 0xA6, 0xFC, 0xAA, 0xCE, 170 | 0xE7, 0x4A, 0xB3, 0x3C, 0xD6, 0x4C, 0x00, 0xF0, 0xA3, 0xB0, 0xCD, 0x71, 0xCF, 0x9D, 0x4B, 0xCC, 171 | 0x2B, 0x2B, 0x41, 0xD6, 0xE2, 0xFD, 0xC6, 0x26, 0xA7, 0x0F, 0x9B, 0xBD, 0x2B, 0xA6, 0x0F, 0x9A, 172 | 0x35, 0x12, 0x53, 0xF3, 0xA6, 0x8D, 0xC4, 0xF7, 0x8C, 0xE1, 0x16, 0xD4, 0x9C, 0xEF, 0x27, 0xD3, 173 | 0x80, 0xDE, 0x5D, 0x94, 0x77, 0x2F, 0xE9, 0xAB, 0x89, 0xD3, 0x68, 0xD2, 0xD4, 0xEF, 0xE9, 0xE9, 174 | 0xD3, 0x67, 0x71, 0x0B, 0x80, 0xD5, 0x21, 0x00, 0xAC, 0xEC, 0x1D, 0xD9, 0x23, 0xCE, 0x4D, 0x7E, 175 | 0x83, 0x7D, 0xFB, 0x0F, 0x53, 0xD5, 0xCA, 0x15, 0xE4, 0xBB, 0x38, 0xBE, 0xC5, 0xBC, 0x28, 0xAB, 176 | 0x8B, 0x0B, 0x1D, 0x3A, 0x1A, 0xDF, 0x0F, 0xC0, 0x61, 0x90, 0x96, 0xCB, 0x5E, 0xCD, 0xED, 0xD1, 177 | 0x13, 0xE3, 0x33, 0x0D, 0xB1, 0x31, 0xA6, 0x5B, 0x0C, 0xC9, 0xB5, 0x26, 0xDC, 0xDD, 0xE3, 0x02, 178 | 0xE0, 0xE6, 0xAD, 0x50, 0x31, 0xB7, 0xA6, 0x7A, 0xCA, 0x21, 0x10, 0x5F, 0x74, 0xD4, 0xEE, 0xA3, 179 | 0x0F, 0xC4, 0xA9, 0x46, 0xBE, 0x7A, 0x12, 0xD4, 0x81, 0x00, 0xB0, 0x32, 0xEE, 0xED, 0x76, 0x51, 180 | 0x2A, 0xF6, 0x81, 0xC3, 0x71, 0xC7, 0xF7, 0x07, 0x0E, 0x1D, 0xA3, 0x67, 0x91, 0x91, 0xE2, 0x42, 181 | 0xA1, 0xC4, 0xAA, 0x54, 0x2E, 0xAF, 0x04, 0x45, 0x5C, 0x00, 0x70, 0x60, 0xF0, 0x5E, 0xB9, 0xFA, 182 | 0x5B, 0x95, 0xC5, 0xFB, 0xD4, 0x88, 0xB1, 0xE0, 0x10, 0x80, 0x97, 0x8D, 0x35, 0xD3, 0x07, 0x90, 183 | 0xDC, 0xBA, 0x3C, 0xDC, 0xE3, 0x2E, 0x08, 0xBA, 0x19, 0x62, 0xFD, 0x00, 0x30, 0x68, 0xDF, 0xA6, 184 | 0x05, 0x35, 0xAA, 0xFF, 0x0E, 0xFD, 0xB9, 0x69, 0x9B, 0xB8, 0xDC, 0x1A, 0xAC, 0x0F, 0x01, 0xA0, 185 | 0x82, 0x1A, 0x6F, 0x55, 0xA4, 0xE0, 0x8B, 0x57, 0x44, 0xA7, 0x1E, 0x37, 0xFF, 0x8B, 0x14, 0x2E, 186 | 0x40, 0xB9, 0x73, 0xE5, 0x94, 0x9F, 0xC6, 0xAB, 0x52, 0xA9, 0x02, 0xDD, 0x0E, 0x0B, 0xA3, 0xCB, 187 | 0x57, 0xAE, 0x89, 0xBD, 0xBF, 0x9D, 0xD2, 0xEC, 0x2E, 0xE1, 0x57, 0x4C, 0x7E, 0x6A, 0x39, 0x73, 188 | 0x15, 0x3A, 0xB1, 0xD8, 0x17, 0xB1, 0xF4, 0xE2, 0xA5, 0xE9, 0xE5, 0x93, 0x6B, 0x01, 0x14, 0xF7, 189 | 0xF5, 0x16, 0x21, 0xF0, 0xC7, 0x86, 0xBF, 0x65, 0x89, 0x3A, 0xCA, 0x96, 0x2E, 0x21, 0xE6, 0xA7, 190 | 0x4E, 0x9F, 0x17, 0x73, 0xB0, 0x2E, 0x04, 0x80, 0x0A, 0xAA, 0xCB, 0xCE, 0x3E, 0xDE, 0xFB, 0xEF, 191 | 0x3B, 0x78, 0x98, 0xAA, 0x57, 0x35, 0xDE, 0xA9, 0x17, 0x50, 0x4E, 0xF6, 0x03, 0x28, 0x87, 0x01, 192 | 0x87, 0x0E, 0x1F, 0xA3, 0x3A, 0x35, 0x93, 0x5E, 0x4A, 0x6B, 0x09, 0x6E, 0xD6, 0xA7, 0x14, 0x87, 193 | 0x45, 0x6C, 0x6C, 0x8C, 0x7C, 0x97, 0x3A, 0x6D, 0xFE, 0xD7, 0x4C, 0x04, 0x18, 0xDF, 0xB9, 0x98, 194 | 0x12, 0x91, 0x91, 0x96, 0x3F, 0x3B, 0xCF, 0x70, 0xB6, 0xC1, 0x70, 0x1D, 0x01, 0x58, 0x17, 0x02, 195 | 0x40, 0x05, 0x95, 0xE4, 0x65, 0xAD, 0xFB, 0x0F, 0x1E, 0x55, 0x2A, 0xC8, 0x3D, 0xAA, 0x59, 0x23, 196 | 0x69, 0xF3, 0x9F, 0xF1, 0xB9, 0x7E, 0x3F, 0x1F, 0x2F, 0x71, 0xCB, 0xEE, 0x15, 0x65, 0x43, 0xAF, 197 | 0x56, 0xD5, 0xF2, 0x6B, 0xFF, 0x13, 0xB2, 0xE4, 0x10, 0x80, 0x2B, 0x3F, 0x9F, 0x96, 0x4B, 0x8B, 198 | 0x46, 0xF5, 0x6B, 0x8B, 0xCB, 0x7C, 0x67, 0xCE, 0xFE, 0xE9, 0xD5, 0xED, 0xC8, 0xA6, 0xCC, 0x9E, 199 | 0xBF, 0x94, 0x9A, 0xFE, 0xAF, 0x93, 0x7C, 0x17, 0x8F, 0x3B, 0xF9, 0xCC, 0xD9, 0xBD, 0xE7, 0x80, 200 | 0xB8, 0xDA, 0x10, 0x23, 0x21, 0xA9, 0x03, 0x01, 0xA0, 0x92, 0x2A, 0x15, 0xCB, 0x8B, 0xFB, 0x02, 201 | 0xF8, 0x9E, 0xF6, 0x82, 0xF9, 0xE3, 0xAE, 0x76, 0x33, 0xA6, 0x4A, 0x25, 0xEE, 0x07, 0x88, 0xBB, 202 | 0xF5, 0xD6, 0xD8, 0xCD, 0x30, 0x96, 0x78, 0x69, 0xA6, 0x49, 0x9F, 0x98, 0x25, 0x67, 0x0C, 0xCC, 203 | 0x19, 0xD8, 0xB7, 0x9B, 0x08, 0x31, 0xBE, 0x15, 0x99, 0x3B, 0xEB, 0x78, 0xEC, 0x00, 0xBE, 0x1D, 204 | 0x98, 0xEF, 0x76, 0x3C, 0xAC, 0xB4, 0x6C, 0x56, 0xAC, 0xFE, 0x9D, 0x3E, 0xE9, 0xDA, 0x4F, 0xDC, 205 | 0x7D, 0x68, 0xEC, 0xF0, 0xE6, 0xD8, 0x89, 0x33, 0xD4, 0xE4, 0xC3, 0x0E, 0xF4, 0xDB, 0xFA, 0x0D, 206 | 0xE2, 0xCE, 0x42, 0x3E, 0xF4, 0x08, 0xBD, 0x7D, 0x47, 0x59, 0xCF, 0x41, 0x1A, 0x34, 0x3C, 0x50, 207 | 0xDC, 0x39, 0xD9, 0xB3, 0xDB, 0x27, 0x72, 0x69, 0xB0, 0x36, 0x04, 0x80, 0x4A, 0x0C, 0xE7, 0xF2, 208 | 0xDF, 0x36, 0xD2, 0xF9, 0x97, 0x10, 0x5F, 0x1A, 0xCC, 0x0C, 0x57, 0x07, 0xA6, 0x85, 0x25, 0x7D, 209 | 0x00, 0x86, 0x6B, 0xF0, 0xD3, 0xAA, 0x70, 0xC1, 0xFC, 0xE2, 0xD6, 0xDD, 0xD6, 0x2D, 0x9B, 0x89, 210 | 0x43, 0x01, 0x1E, 0x3B, 0xA0, 0xE3, 0x17, 0x7D, 0xE8, 0x83, 0x36, 0x9D, 0xC5, 0x38, 0x00, 0x0B, 211 | 0x16, 0xAF, 0x14, 0x57, 0x36, 0x4E, 0x19, 0x3F, 0x9C, 0xA6, 0x7D, 0x3D, 0x46, 0x7E, 0x2B, 0x5E, 212 | 0xDB, 0x56, 0xCD, 0x95, 0xBD, 0x7B, 0x4E, 0x9A, 0x35, 0x77, 0x09, 0xF5, 0x1E, 0x34, 0x9A, 0x1A, 213 | 0x35, 0xFF, 0x98, 0xDA, 0x77, 0xEE, 0xA5, 0xAC, 0x67, 0x2A, 0x39, 0x3A, 0x3A, 0x2A, 0xDF, 0x1B, 214 | 0x91, 0xEC, 0x20, 0x2B, 0x90, 0x7A, 0x18, 0x11, 0xE8, 0x3F, 0xC2, 0x70, 0x41, 0x51, 0x4A, 0x2F, 215 | 0x21, 0x36, 0xB7, 0xFC, 0x0B, 0xE5, 0xD8, 0xC0, 0x8E, 0xAF, 0xDB, 0x4D, 0x05, 0xBE, 0xE7, 0x3F, 216 | 0xF8, 0xD2, 0x65, 0xB2, 0xCB, 0x60, 0x47, 0xF9, 0x3D, 0xF3, 0x8A, 0x0B, 0xA3, 0xEC, 0xEC, 0x92, 217 | 0xDF, 0xCF, 0xF0, 0x7D, 0x11, 0xF7, 0xEE, 0x3D, 0x10, 0x83, 0xA1, 0x78, 0xE6, 0xF3, 0xA0, 0x7C, 218 | 0x79, 0xF3, 0x58, 0x74, 0x65, 0x63, 0x7A, 0x81, 0x11, 0x81, 0xE0, 0x8D, 0xE0, 0x8A, 0x6C, 0xC9, 219 | 0xFD, 0x03, 0xE6, 0x96, 0x4F, 0x6D, 0xE5, 0x67, 0x3C, 0x72, 0x31, 0x8F, 0x63, 0xC0, 0xD7, 0x3D, 220 | 0x14, 0xC8, 0x9F, 0x2F, 0x45, 0x95, 0x9F, 0x15, 0xF3, 0x2A, 0x22, 0x0E, 0x87, 0x1A, 0xD4, 0xAD, 221 | 0x29, 0x6E, 0x41, 0xD6, 0x62, 0xE5, 0xD7, 0x22, 0x04, 0x00, 0x80, 0x8E, 0x21, 0x00, 0x00, 0x74, 222 | 0x0C, 0x01, 0x00, 0xA0, 0x63, 0x08, 0x00, 0x00, 0x1D, 0x43, 0x00, 0x00, 0xE8, 0x18, 0x02, 0x00, 223 | 0x40, 0xC7, 0x34, 0x19, 0x00, 0xC9, 0xDD, 0xAB, 0x0E, 0xF0, 0x26, 0x68, 0x71, 0xBB, 0xD4, 0x64, 224 | 0x00, 0x64, 0xCA, 0x94, 0x49, 0xBE, 0x02, 0x48, 0x3F, 0xB4, 0xB8, 0x5D, 0x6A, 0x32, 0x00, 0x9C, 225 | 0x9C, 0x2C, 0x1F, 0x30, 0x13, 0x40, 0x6D, 0x5A, 0xDC, 0x2E, 0x35, 0x19, 0x00, 0xCE, 0xCE, 0xCE, 226 | 0x38, 0x0C, 0x80, 0x74, 0x85, 0xB7, 0x47, 0xDE, 0x2E, 0xB5, 0x46, 0x93, 0x01, 0xC0, 0xE3, 0xEB, 227 | 0x67, 0xCB, 0x96, 0x4D, 0xBE, 0x03, 0x78, 0xF3, 0x78, 0x7B, 0xE4, 0xED, 0x52, 0x6B, 0x34, 0x19, 228 | 0x00, 0x8C, 0xD3, 0x36, 0x73, 0xE6, 0xCC, 0xF2, 0x1D, 0xC0, 0x9B, 0xC3, 0xDB, 0xA1, 0x16, 0xF7, 229 | 0xFE, 0x4C, 0xB3, 0x01, 0xC0, 0xB2, 0x67, 0xCF, 0x8E, 0x10, 0x80, 0x37, 0x8A, 0xB7, 0x3F, 0xDE, 230 | 0x0E, 0xB5, 0x4A, 0xD3, 0x01, 0xC0, 0x4D, 0x2E, 0x57, 0x57, 0x57, 0x72, 0x73, 0x73, 0x43, 0x9F, 231 | 0x00, 0xD8, 0x14, 0x6F, 0x6F, 0xBC, 0xDD, 0xF1, 0xF6, 0xA7, 0xC5, 0xA6, 0xBF, 0x81, 0xA6, 0x03, 232 | 0xC0, 0x80, 0x9B, 0x5F, 0xEE, 0xEE, 0xEE, 0xE2, 0x3F, 0x83, 0x7B, 0x62, 0x11, 0x06, 0xA0, 0x06, 233 | 0xDE, 0xAE, 0x78, 0xFB, 0xE2, 0xED, 0x8C, 0xB7, 0x37, 0xAD, 0x36, 0xFB, 0x13, 0xD2, 0xE4, 0x80, 234 | 0x20, 0x00, 0x7A, 0x81, 0x01, 0x41, 0x00, 0x40, 0x35, 0x08, 0x00, 0x00, 0x1D, 0x43, 0x00, 0x00, 235 | 0xE8, 0x18, 0x02, 0x00, 0x40, 0xC7, 0x10, 0x00, 0x00, 0x3A, 0x86, 0x00, 0x00, 0xD0, 0x31, 0x04, 236 | 0x00, 0x80, 0x8E, 0x21, 0x00, 0x00, 0x74, 0x0C, 0x01, 0x00, 0xA0, 0x63, 0x08, 0x00, 0x00, 0x1D, 237 | 0x43, 0x00, 0x00, 0xE8, 0x18, 0x02, 0x00, 0x40, 0xC7, 0x10, 0x00, 0x00, 0x3A, 0xF6, 0x9F, 0xB9, 238 | 0x1B, 0x90, 0xFF, 0x1E, 0x11, 0x11, 0x11, 0x14, 0x15, 0x15, 0x45, 0xD1, 0xD1, 0xD1, 0x14, 0x1B, 239 | 0x1B, 0x2B, 0x3F, 0x01, 0xB0, 0x0E, 0xBE, 0x1D, 0xD8, 0xC1, 0xC1, 0x81, 0x1C, 0x1D, 0x1D, 0xC5, 240 | 0xAD, 0xC0, 0xB6, 0x18, 0x07, 0x00, 0x77, 0x03, 0xA6, 0x00, 0x57, 0xFC, 0xB0, 0xB0, 0x30, 0x0A, 241 | 0x0F, 0x0F, 0x17, 0xAF, 0x51, 0xF9, 0x41, 0x0D, 0xBC, 0x5D, 0xF1, 0xF6, 0xC5, 0xDB, 0x19, 0x6F, 242 | 0x6F, 0xFC, 0x5A, 0xEB, 0x34, 0x1D, 0x00, 0xBC, 0xD7, 0x7F, 0xF8, 0xF0, 0x21, 0x3D, 0x78, 0xF0, 243 | 0x00, 0x95, 0x1E, 0x6C, 0x8A, 0xB7, 0x37, 0xDE, 0xEE, 0x78, 0xFB, 0x53, 0xAB, 0x15, 0x6D, 0x0B, 244 | 0x9A, 0x0E, 0x80, 0x47, 0x8F, 0x1E, 0xD1, 0xD3, 0xA7, 0x4F, 0xE5, 0x3B, 0x00, 0xDB, 0xE3, 0xED, 245 | 0x8F, 0xB7, 0x43, 0xAD, 0xD2, 0x6C, 0x00, 0x70, 0xF3, 0x0B, 0x95, 0x1F, 0xD2, 0x03, 0xDE, 0x0E, 246 | 0xB5, 0x7A, 0x38, 0xA0, 0xC9, 0x00, 0xE0, 0x26, 0x97, 0x96, 0x53, 0x17, 0xFE, 0x7B, 0x78, 0x7B, 247 | 0xD4, 0xE2, 0xA1, 0x80, 0x26, 0x03, 0x00, 0x1D, 0x7D, 0x90, 0xDE, 0x18, 0x3A, 0x08, 0xB5, 0x46, 248 | 0x93, 0x01, 0xC0, 0xA7, 0xFA, 0x00, 0xD2, 0x1B, 0x2D, 0x6E, 0x97, 0x9A, 0x0C, 0x00, 0x3E, 0xCF, 249 | 0x0F, 0x90, 0xDE, 0x68, 0x71, 0xBB, 0xD4, 0x64, 0x00, 0xA0, 0xF9, 0x0F, 0xE9, 0x91, 0x16, 0xB7, 250 | 0x4B, 0x4D, 0x06, 0x00, 0x00, 0x58, 0x07, 0x02, 0x00, 0x40, 0xC7, 0x10, 0x00, 0x00, 0x3A, 0x86, 251 | 0x00, 0x00, 0xD0, 0x31, 0x04, 0x00, 0x80, 0x8E, 0x21, 0x00, 0x00, 0x74, 0x0C, 0x01, 0x00, 0xA0, 252 | 0x63, 0x08, 0x00, 0x00, 0x1D, 0x43, 0x00, 0x00, 0xE8, 0x18, 0x02, 0x00, 0x40, 0xC7, 0x10, 0x00, 253 | 0x00, 0x3A, 0x86, 0x00, 0x00, 0xD0, 0x31, 0x04, 0x80, 0x85, 0x34, 0x3C, 0xFC, 0x1B, 0x40, 0x12, 254 | 0x08, 0x80, 0x54, 0x40, 0x08, 0xC0, 0x7F, 0x85, 0x26, 0x9F, 0x0B, 0x70, 0xEB, 0xD6, 0x2D, 0xF9, 255 | 0xCA, 0xF6, 0xF8, 0x9F, 0xCB, 0x06, 0xC3, 0xC1, 0xA7, 0x09, 0xFF, 0x19, 0x43, 0x42, 0x6E, 0x51, 256 | 0xD8, 0x9D, 0x3B, 0x14, 0xA2, 0xFC, 0x5B, 0xDD, 0x51, 0xE6, 0x3C, 0x8C, 0xF5, 0x8D, 0x1B, 0x37, 257 | 0xE2, 0x16, 0x50, 0xFE, 0x02, 0xBC, 0x4C, 0xB6, 0xEC, 0xD9, 0x28, 0x7B, 0xD6, 0x6C, 0xFC, 0x0D, 258 | 0x51, 0xCC, 0xE3, 0xDD, 0x17, 0x29, 0x52, 0x84, 0xBC, 0xBD, 0xBD, 0xC5, 0x64, 0x6F, 0x6F, 0x2F, 259 | 0xCA, 0x21, 0xE5, 0xF2, 0xE5, 0xCB, 0x27, 0x5F, 0x59, 0x87, 0xDA, 0xCF, 0x05, 0x40, 0x00, 0x68, 260 | 0x18, 0xFF, 0xD7, 0x85, 0x3F, 0x7A, 0x48, 0xBB, 0x82, 0xF6, 0xD0, 0xE1, 0xC3, 0x47, 0x68, 0xEF, 261 | 0x9E, 0x20, 0x0A, 0x0D, 0x09, 0xA1, 0xB0, 0xD0, 0x10, 0xB9, 0x44, 0xDA, 0x14, 0xF5, 0xF2, 0x12, 262 | 0x41, 0xC0, 0xA1, 0xE0, 0xEB, 0xE3, 0x43, 0x95, 0x2A, 0x55, 0x12, 0xAF, 0xC1, 0x34, 0x04, 0x80, 263 | 0x84, 0x00, 0x50, 0xC7, 0xF5, 0xEB, 0xD7, 0x69, 0xDF, 0xFE, 0xFD, 0xCA, 0x74, 0x80, 0xF6, 0x2A, 264 | 0xF3, 0x4B, 0xE7, 0xCF, 0x89, 0xF2, 0x6C, 0x39, 0x72, 0x51, 0xD1, 0x92, 0x65, 0xC4, 0x6B, 0x96, 265 | 0xDF, 0xDB, 0x97, 0x72, 0x78, 0xE4, 0x53, 0x26, 0x0F, 0xCA, 0xE6, 0x96, 0x8B, 0xB2, 0x64, 0x77, 266 | 0xA5, 0xEC, 0x39, 0x73, 0x93, 0xD8, 0x8A, 0xB8, 0x09, 0xA3, 0x4C, 0x91, 0xCF, 0x9E, 0x50, 0x74, 267 | 0xA4, 0x61, 0x18, 0xAB, 0x97, 0xCA, 0xEB, 0x48, 0x0A, 0xBB, 0x71, 0x85, 0xAE, 0x9E, 0x3B, 0x43, 268 | 0xD7, 0xCE, 0x9D, 0xA6, 0xD8, 0xD8, 0x18, 0xF1, 0xC9, 0xA5, 0x53, 0xC7, 0xE9, 0xD1, 0xFD, 0xBB, 269 | 0xE2, 0xB5, 0x5F, 0x89, 0x12, 0xF4, 0xEE, 0xBB, 0x8D, 0xE9, 0xFD, 0xF7, 0x9B, 0x51, 0xD1, 0xC2, 270 | 0x45, 0xC4, 0xAA, 0x20, 0x1E, 0x02, 0x40, 0x42, 0x00, 0x58, 0x4F, 0xA4, 0x52, 0x31, 0x7F, 0xFF, 271 | 0xFD, 0x77, 0x5A, 0xBC, 0x78, 0x31, 0x1D, 0x3D, 0x7A, 0x54, 0x94, 0x19, 0x2A, 0xBC, 0xA3, 0x53, 272 | 0x66, 0x2A, 0x5B, 0xE3, 0x1D, 0xAA, 0x58, 0xA7, 0x91, 0x52, 0xD9, 0xF3, 0x8A, 0xCF, 0xAC, 0x2D, 273 | 0xFC, 0x4E, 0x18, 0x9D, 0x3F, 0x7A, 0x90, 0xF6, 0x6D, 0xFE, 0x83, 0xC2, 0xEF, 0xDE, 0x7E, 0x15, 274 | 0x08, 0x5E, 0x3E, 0xBE, 0xD4, 0xA0, 0x61, 0x23, 0x6A, 0xDA, 0xB8, 0x11, 0x95, 0x2A, 0x59, 0x0A, 275 | 0x61, 0xA0, 0x40, 0x00, 0x48, 0x08, 0x80, 0xB4, 0x3B, 0x73, 0xE6, 0x0C, 0x2D, 0x5A, 0xB4, 0x88, 276 | 0x7E, 0xFD, 0xF5, 0x57, 0x31, 0xF6, 0x3C, 0x57, 0xFA, 0x12, 0x15, 0xDF, 0xA2, 0x72, 0x6F, 0xD7, 277 | 0xA1, 0x80, 0x3A, 0x0D, 0xC9, 0x35, 0x97, 0xBB, 0x5C, 0xD2, 0xB6, 0x2E, 0x9F, 0x39, 0x41, 0x7F, 278 | 0xFD, 0x34, 0x9B, 0xEE, 0xDF, 0x0E, 0x79, 0x15, 0x06, 0x6F, 0xD7, 0xAA, 0x45, 0x23, 0x47, 0x8C, 279 | 0xA0, 0xE2, 0x7E, 0x7E, 0x72, 0x29, 0x7D, 0x42, 0x00, 0x48, 0x08, 0x80, 0xD4, 0x5B, 0xBD, 0x7A, 280 | 0x35, 0xCD, 0x9B, 0x37, 0x8F, 0x4E, 0x9C, 0x38, 0xF1, 0x6A, 0x4F, 0xEF, 0x57, 0xA1, 0x32, 0xBD, 281 | 0xDB, 0xFE, 0x0B, 0x72, 0xC9, 0x96, 0x5D, 0x2E, 0x95, 0x3E, 0xDC, 0xBA, 0x1C, 0x4C, 0xAB, 0x66, 282 | 0x4C, 0xA2, 0x63, 0xBB, 0xFF, 0xA1, 0x27, 0xE1, 0xF7, 0xE9, 0x83, 0x0F, 0x5B, 0xD0, 0xD0, 0xA1, 283 | 0x43, 0xC8, 0xC3, 0xFD, 0xCD, 0x84, 0xD3, 0x9B, 0xA6, 0xB5, 0x00, 0xC0, 0x69, 0x40, 0x1B, 0xE0, 284 | 0x8C, 0x7D, 0xA1, 0x4C, 0x3C, 0x37, 0x97, 0xB7, 0x97, 0x2E, 0x5D, 0xA2, 0xA6, 0x4D, 0x9B, 0x52, 285 | 0xAF, 0x5E, 0xBD, 0xE8, 0xEA, 0xCD, 0x10, 0x0A, 0xA8, 0xDD, 0x80, 0x06, 0xCE, 0x5A, 0x42, 0x23, 286 | 0x16, 0xAE, 0xA1, 0x96, 0x5F, 0x0E, 0x4C, 0x77, 0x95, 0x9F, 0xE5, 0x2B, 0xE2, 0x4D, 0xBD, 0xBF, 287 | 0x9D, 0x4B, 0x13, 0x56, 0x6F, 0xA1, 0x80, 0xBA, 0x8D, 0x68, 0xF3, 0xB6, 0xBF, 0xA9, 0x4A, 0xE5, 288 | 0xCA, 0x34, 0x65, 0xCA, 0x14, 0x3C, 0xB9, 0x49, 0x03, 0x10, 0x00, 0x2A, 0x38, 0x79, 0xF2, 0xA4, 289 | 0xB2, 0x17, 0x1C, 0x4A, 0x25, 0x4A, 0x94, 0x24, 0x4F, 0x4F, 0x4F, 0xCA, 0x9F, 0xDF, 0x93, 0x8A, 290 | 0x16, 0x2D, 0x42, 0x35, 0xDE, 0xA9, 0x4D, 0x9F, 0x76, 0xFE, 0x9C, 0x7E, 0x54, 0x12, 0xFD, 0xC4, 291 | 0x89, 0x93, 0xAF, 0x82, 0x21, 0x3A, 0x26, 0x86, 0xA6, 0x4E, 0xFF, 0x8E, 0x6A, 0xD7, 0xAE, 0x4D, 292 | 0x17, 0x2E, 0x5F, 0xA5, 0xEA, 0xEF, 0x7D, 0x48, 0xD3, 0x36, 0x04, 0xD1, 0x90, 0x39, 0x2B, 0xA8, 293 | 0x78, 0x40, 0x15, 0xB9, 0xD6, 0xF4, 0x2D, 0x4F, 0xC1, 0xC2, 0x34, 0x68, 0xD6, 0x52, 0x1A, 0xF4, 294 | 0xC3, 0x52, 0x2A, 0x51, 0xB9, 0x3A, 0xCD, 0xFF, 0x69, 0x09, 0x55, 0xAB, 0x56, 0x8D, 0xF6, 0xEF, 295 | 0xDF, 0x2F, 0x97, 0x80, 0xF4, 0x08, 0x87, 0x00, 0x56, 0xB6, 0x69, 0xD3, 0x26, 0xEA, 0xDC, 0xB9, 296 | 0x33, 0xB9, 0x64, 0x77, 0x23, 0xAF, 0x52, 0xFE, 0xB2, 0x34, 0xDE, 0xC5, 0x93, 0x47, 0x5F, 0xF5, 297 | 0xA8, 0xD7, 0x6B, 0xD2, 0x8C, 0xDA, 0x77, 0xF9, 0x92, 0xC6, 0x0C, 0xEA, 0x4B, 0x61, 0x21, 0x21, 298 | 0xA2, 0xA9, 0xDF, 0xF2, 0xCB, 0x01, 0x4A, 0x73, 0x5F, 0x1B, 0x95, 0xDE, 0x9C, 0x2D, 0xCB, 0x17, 299 | 0xD0, 0xF2, 0x69, 0x13, 0x28, 0x26, 0xF2, 0x19, 0x2D, 0x5D, 0xBA, 0x94, 0x2A, 0x2B, 0xAD, 0x82, 300 | 0xC4, 0x12, 0x6E, 0x7A, 0xFF, 0x95, 0x0E, 0x44, 0xF4, 0x01, 0x48, 0x7A, 0x0C, 0x00, 0xDE, 0xDB, 301 | 0xB5, 0x6A, 0xD5, 0x8A, 0x9C, 0xB2, 0x64, 0xA3, 0xC1, 0x3F, 0x2E, 0x25, 0xDF, 0xF2, 0x49, 0x37, 302 | 0xFA, 0xE8, 0xA8, 0x48, 0x3A, 0xB5, 0x6F, 0xB7, 0x72, 0xDC, 0x3C, 0x51, 0xF4, 0xDA, 0xEF, 0xDF, 303 | 0xFA, 0x17, 0x65, 0x51, 0xC2, 0xA2, 0x49, 0xC7, 0x2E, 0xF4, 0x61, 0xB7, 0x7E, 0x72, 0xA9, 0xA4, 304 | 0x2E, 0x1C, 0x3B, 0x44, 0xC7, 0x95, 0xE3, 0xEC, 0x07, 0x77, 0xC2, 0x28, 0xE4, 0x4A, 0x30, 0xE5, 305 | 0x2D, 0xEC, 0x4D, 0x6E, 0xB9, 0xDD, 0x29, 0x5F, 0x51, 0x6F, 0x0A, 0x78, 0xA7, 0x21, 0x65, 0x72, 306 | 0x74, 0x94, 0x4B, 0xA6, 0x1F, 0x47, 0xFE, 0xD9, 0x4C, 0x33, 0x06, 0x76, 0x17, 0x7D, 0x03, 0xDF, 307 | 0xFF, 0xF0, 0x03, 0xD5, 0xAF, 0x57, 0x9F, 0xF6, 0xEC, 0xD9, 0x43, 0xBB, 0x76, 0xEF, 0xA2, 0x93, 308 | 0xA7, 0x4E, 0xD3, 0xF5, 0x6B, 0xD7, 0xE9, 0xE6, 0x8D, 0x6B, 0x14, 0xF3, 0xFC, 0xB9, 0x58, 0xDE, 309 | 0xD5, 0xD5, 0x4D, 0x9C, 0x5E, 0x6C, 0xDD, 0xBA, 0x35, 0x95, 0x2A, 0x55, 0x4A, 0x94, 0x69, 0x0D, 310 | 0x02, 0x40, 0xD2, 0x5B, 0x00, 0x44, 0x45, 0x45, 0x53, 0xE3, 0xC6, 0x8D, 0xE9, 0xE6, 0xED, 0x30, 311 | 0x1A, 0xF9, 0xD3, 0x5A, 0x2A, 0x52, 0xBC, 0xB4, 0xFC, 0xC4, 0xB8, 0xD0, 0xAB, 0x97, 0x69, 0x48, 312 | 0xCB, 0xFA, 0xE4, 0x5D, 0xB6, 0x3C, 0x75, 0x1A, 0x1A, 0x28, 0x8E, 0xA5, 0x13, 0x0B, 0x53, 0x2A, 313 | 0xC7, 0xA2, 0xC0, 0x61, 0x14, 0xA5, 0xEC, 0x45, 0xEF, 0x5E, 0xBB, 0x4C, 0x0E, 0x19, 0x93, 0x6E, 314 | 0x03, 0xA1, 0xA1, 0xA1, 0x64, 0xEF, 0x94, 0x99, 0x8A, 0x2B, 0xAD, 0x86, 0x8E, 0xC3, 0x02, 0xC9, 315 | 0x3D, 0x7F, 0x41, 0xF9, 0x89, 0x75, 0x71, 0x00, 0x9D, 0x08, 0xDA, 0x41, 0xF7, 0xC3, 0x6E, 0x5B, 316 | 0x14, 0x40, 0x57, 0xCF, 0x9D, 0xA6, 0xD1, 0x1F, 0x37, 0x13, 0x21, 0x50, 0xD4, 0xB7, 0x04, 0x05, 317 | 0x9F, 0x39, 0x29, 0xCA, 0x13, 0x5F, 0xB7, 0x60, 0xC0, 0x67, 0x15, 0x78, 0xD9, 0xF9, 0x0B, 0x16, 318 | 0x28, 0x81, 0x51, 0x4F, 0x96, 0x6A, 0x07, 0x02, 0x40, 0xD2, 0x53, 0x00, 0xF0, 0xBF, 0xE1, 0xB2, 319 | 0x9F, 0x57, 0xD0, 0xA0, 0x01, 0xFD, 0xE9, 0xAD, 0x77, 0x9B, 0x53, 0xBF, 0x19, 0x0B, 0xE4, 0x27, 320 | 0xC6, 0x3D, 0x7D, 0xF4, 0x90, 0x86, 0xB7, 0x6E, 0x4C, 0x45, 0x4A, 0x94, 0xA6, 0x9E, 0x93, 0x7F, 321 | 0x90, 0xA5, 0xAF, 0x5B, 0xF0, 0xD5, 0x10, 0x3A, 0xF6, 0xCF, 0x26, 0x51, 0xE9, 0xDF, 0x6D, 0xF2, 322 | 0x1E, 0xF5, 0xEA, 0xF1, 0xA5, 0xB8, 0x2A, 0x2F, 0xB1, 0xE0, 0xE0, 0x60, 0x5A, 0xB0, 0x70, 0x11, 323 | 0xAD, 0x5C, 0xF1, 0x33, 0x45, 0xC7, 0xBE, 0xA4, 0xB2, 0xB5, 0x1A, 0xD0, 0x27, 0x23, 0x26, 0xC8, 324 | 0x4F, 0xD3, 0xC6, 0x5A, 0x01, 0xF4, 0x40, 0x09, 0x8D, 0xBE, 0x4D, 0xAA, 0x8B, 0x43, 0x1F, 0x4F, 325 | 0x6F, 0x1F, 0xEA, 0x38, 0x64, 0x1C, 0x95, 0xAC, 0x5C, 0x9D, 0x1C, 0x9D, 0x9C, 0xE5, 0x12, 0xF1, 326 | 0x2E, 0x1C, 0x3F, 0x4C, 0xE3, 0x3F, 0x6B, 0x45, 0xD1, 0x11, 0x4F, 0x69, 0xED, 0x9A, 0x35, 0x54, 327 | 0xB6, 0x6C, 0x59, 0xF9, 0x49, 0xEA, 0xF1, 0x26, 0x6E, 0xAB, 0x43, 0x0C, 0x9C, 0x05, 0xD0, 0xA1, 328 | 0x07, 0x0F, 0x1E, 0xD0, 0x06, 0xE5, 0xD8, 0x9F, 0x35, 0x68, 0xDB, 0x49, 0xCC, 0x4D, 0xE1, 0xCA, 329 | 0xFF, 0x65, 0xDD, 0x00, 0xCA, 0x95, 0xCF, 0xD3, 0x68, 0xE5, 0xBF, 0x1B, 0x72, 0x93, 0xBE, 0xEA, 330 | 0xF4, 0xA1, 0xA8, 0xFC, 0x5D, 0xBB, 0x75, 0xA3, 0x8B, 0x17, 0x2F, 0xD2, 0x77, 0xD3, 0xA7, 0x19, 331 | 0xAD, 0xFC, 0x8C, 0xCB, 0xC7, 0x07, 0x8E, 0x13, 0xCB, 0xF5, 0xEE, 0xD5, 0x53, 0x7C, 0x8F, 0xBF, 332 | 0xCF, 0xEB, 0x49, 0x0B, 0x0E, 0xA0, 0xC0, 0x0E, 0xEF, 0xD3, 0x9D, 0x8B, 0xA7, 0xA9, 0x66, 0xF9, 333 | 0x32, 0xB4, 0x7D, 0xEB, 0x66, 0xF1, 0x1B, 0x89, 0xA7, 0x23, 0x47, 0x8F, 0x52, 0xB7, 0x2E, 0x5F, 334 | 0x88, 0xE5, 0x78, 0x79, 0xFE, 0x5E, 0x62, 0x6E, 0xEE, 0x1E, 0xF4, 0xDD, 0x96, 0x03, 0x62, 0xAF, 335 | 0x9F, 0xBF, 0x88, 0x0F, 0x95, 0xAF, 0x59, 0xCF, 0x68, 0xE5, 0x67, 0xC5, 0xCA, 0x94, 0xA7, 0xB1, 336 | 0xCB, 0xFF, 0x20, 0x07, 0x67, 0x17, 0x1A, 0x17, 0x18, 0x28, 0x4B, 0x41, 0x2D, 0x08, 0x00, 0x2B, 337 | 0x38, 0x7F, 0xFE, 0x3C, 0xDD, 0xBF, 0x77, 0x57, 0x6C, 0xE0, 0x3E, 0xFE, 0x15, 0x65, 0x69, 0x52, 338 | 0x86, 0xCA, 0xCF, 0x7A, 0x4F, 0x9D, 0x2B, 0xE6, 0x09, 0x71, 0xA5, 0x1D, 0xD0, 0xAC, 0x16, 0x05, 339 | 0x1F, 0x3D, 0x40, 0x1B, 0x37, 0x6E, 0xA0, 0xA1, 0x03, 0xFB, 0xCB, 0x4F, 0x52, 0xA6, 0x5F, 0x9F, 340 | 0xDE, 0xB4, 0x7D, 0xDB, 0x56, 0xBA, 0xA8, 0x7C, 0x9F, 0xD7, 0x93, 0x9A, 0x10, 0x48, 0x18, 0x40, 341 | 0xBD, 0x7B, 0xF7, 0x14, 0x95, 0x7C, 0xDA, 0xB4, 0x6F, 0x4D, 0x06, 0x90, 0x4F, 0xB1, 0x62, 0x34, 342 | 0x41, 0x06, 0x50, 0xFF, 0x7E, 0x7D, 0x4C, 0x06, 0x10, 0x5F, 0x8A, 0x3C, 0x6E, 0xC5, 0x5F, 0x14, 343 | 0x72, 0xF5, 0x12, 0xFD, 0xFB, 0xFB, 0x2A, 0x59, 0x6A, 0x5C, 0x01, 0x6F, 0x5F, 0x2A, 0x55, 0xA5, 344 | 0x06, 0x05, 0xED, 0xDE, 0x4D, 0xA7, 0x4E, 0x9D, 0x92, 0xA5, 0xA9, 0x87, 0x2B, 0x14, 0x4D, 0x43, 345 | 0x00, 0xA4, 0x11, 0x37, 0xFF, 0x6F, 0xDE, 0xBC, 0x49, 0x77, 0xEF, 0xDE, 0x13, 0xBD, 0xFE, 0x0E, 346 | 0x8E, 0x4E, 0xF2, 0x93, 0xA4, 0xBE, 0xED, 0xFD, 0x99, 0x98, 0xF3, 0xDE, 0xD0, 0x45, 0xDC, 0x85, 347 | 0xF7, 0xBA, 0x1F, 0x86, 0xF6, 0xA4, 0x17, 0xCF, 0xA3, 0xE8, 0xCA, 0xD5, 0x6B, 0x54, 0xD2, 0xCF, 348 | 0x57, 0x96, 0x5A, 0xC6, 0xDB, 0xAB, 0x28, 0xDD, 0x0A, 0x09, 0xA1, 0x97, 0xCA, 0x7A, 0x78, 0x7D, 349 | 0x96, 0x30, 0x04, 0x10, 0x07, 0xC8, 0xDF, 0x5B, 0xB7, 0x50, 0xBF, 0xDE, 0xBD, 0xE5, 0x27, 0x29, 350 | 0xD3, 0xAB, 0x47, 0x0F, 0xFA, 0x77, 0xFB, 0xB6, 0x57, 0x01, 0x74, 0x2F, 0x51, 0x08, 0x78, 0x16, 351 | 0x2D, 0x46, 0xD5, 0x9B, 0x7C, 0x40, 0xBF, 0xCE, 0x9E, 0x4E, 0x8F, 0x1F, 0xDC, 0x97, 0xA5, 0xC6, 352 | 0xD5, 0xFB, 0xA8, 0x83, 0x98, 0x2F, 0x5B, 0xB6, 0x4C, 0xCC, 0x41, 0x1D, 0x08, 0x80, 0x34, 0x7A, 353 | 0xFE, 0xFC, 0x39, 0x85, 0x87, 0x87, 0x53, 0x54, 0x74, 0x5C, 0x4F, 0xB6, 0x29, 0x7F, 0x2D, 0x9E, 354 | 0x43, 0xF7, 0x6E, 0x87, 0xD0, 0xA4, 0xB5, 0xDB, 0xC4, 0xDE, 0x30, 0x31, 0x6E, 0x3A, 0xF3, 0x71, 355 | 0xF6, 0xAE, 0x3D, 0xFB, 0x28, 0xA7, 0x5B, 0xD2, 0xCF, 0x2D, 0x91, 0xC5, 0xC5, 0x85, 0x2E, 0x04, 356 | 0x07, 0x8B, 0xF5, 0x19, 0x6B, 0x92, 0x9B, 0xC2, 0x81, 0xC1, 0xC1, 0x71, 0xF3, 0xD6, 0x2D, 0x2A, 357 | 0xE6, 0xED, 0x25, 0x4B, 0x2D, 0xC3, 0x77, 0x0B, 0x72, 0xBF, 0x00, 0xAF, 0x67, 0x96, 0x91, 0x00, 358 | 0xE2, 0x33, 0x1D, 0x39, 0x3C, 0xF2, 0x28, 0xBF, 0xD5, 0x4B, 0x96, 0x18, 0xE7, 0x5B, 0xBE, 0x92, 359 | 0x68, 0x51, 0x1D, 0x3B, 0x76, 0x4C, 0x96, 0x80, 0x1A, 0x10, 0x00, 0x69, 0xF4, 0xE2, 0xC5, 0x0B, 360 | 0x8A, 0x89, 0x89, 0x11, 0x1B, 0xB5, 0x29, 0xE1, 0x77, 0xC3, 0x68, 0xCB, 0xCA, 0xC5, 0x54, 0xAB, 361 | 0x79, 0x2B, 0xA3, 0x9D, 0x64, 0xDC, 0xD9, 0xB6, 0x73, 0xFD, 0x6A, 0x6A, 0xD1, 0xEA, 0x23, 0x2A, 362 | 0x5B, 0xB2, 0xB8, 0x2C, 0x7D, 0x1D, 0x3F, 0x7B, 0x7E, 0xE4, 0xC8, 0x91, 0xE4, 0xEF, 0xEF, 0x2F, 363 | 0x26, 0x7E, 0x6D, 0xEE, 0x79, 0xF4, 0x7C, 0x29, 0xEE, 0xB8, 0xB1, 0xA3, 0x45, 0x93, 0x9C, 0xD7, 364 | 0x9F, 0x1C, 0x43, 0x00, 0x1D, 0x3A, 0x7C, 0x84, 0xB2, 0x66, 0xC9, 0x22, 0x4B, 0xE3, 0x59, 0xF2, 365 | 0xFB, 0x99, 0x33, 0x67, 0x16, 0x9D, 0x93, 0xBC, 0xBE, 0x85, 0x81, 0x43, 0x65, 0x69, 0xBC, 0xB6, 366 | 0xFD, 0x46, 0x24, 0x7B, 0x28, 0xC0, 0x7D, 0x04, 0x7C, 0x96, 0x80, 0xC3, 0x88, 0x43, 0x16, 0xD4, 367 | 0x81, 0x00, 0x48, 0xA3, 0x0C, 0xCA, 0x01, 0xA6, 0x9D, 0x9D, 0x1D, 0x39, 0x39, 0x67, 0x96, 0x25, 368 | 0x49, 0xCD, 0x1D, 0xD5, 0x9F, 0x72, 0xB8, 0x7B, 0x50, 0xB3, 0xCF, 0x7A, 0xC8, 0x92, 0xD7, 0x71, 369 | 0x4F, 0x3B, 0x5F, 0x30, 0x33, 0xF1, 0xAB, 0xD1, 0xB2, 0xE4, 0x75, 0x7C, 0x65, 0xA1, 0x9B, 0x9B, 370 | 0x1B, 0x1D, 0x39, 0x72, 0x84, 0xB6, 0x6C, 0xD9, 0x22, 0x2E, 0x36, 0x3A, 0x74, 0xE8, 0x90, 0x28, 371 | 0xE3, 0xCF, 0x4C, 0xE9, 0xD0, 0xBE, 0xBD, 0xE8, 0xB9, 0xE7, 0xF5, 0x9B, 0xC3, 0x01, 0x21, 0x8E, 372 | 0xF9, 0x7B, 0xF5, 0x34, 0xBA, 0xE7, 0x4F, 0xF8, 0xFB, 0x5B, 0xB7, 0x6E, 0x15, 0x13, 0xBF, 0x36, 373 | 0xF7, 0xFB, 0xEE, 0x32, 0x80, 0x8E, 0xFE, 0xBD, 0x91, 0xEE, 0xDC, 0xBA, 0x2E, 0x4B, 0xE3, 0x14, 374 | 0x55, 0x0E, 0x95, 0xFC, 0x2A, 0x54, 0xA2, 0x1D, 0xBF, 0xAD, 0x94, 0x25, 0xA6, 0x45, 0x2B, 0x2D, 375 | 0xAB, 0x27, 0x4F, 0x9E, 0xC8, 0x77, 0x60, 0x6D, 0x08, 0x80, 0x34, 0xCA, 0x94, 0x29, 0x13, 0x65, 376 | 0x51, 0xF6, 0x98, 0x45, 0x0A, 0x17, 0x16, 0x57, 0xF9, 0x25, 0xDE, 0xDB, 0x1E, 0x0F, 0xDA, 0x41, 377 | 0xB7, 0xAE, 0x5C, 0xA2, 0xFF, 0xF5, 0x18, 0x24, 0x4B, 0x92, 0xE2, 0xD3, 0x6C, 0x6D, 0x3A, 0x74, 378 | 0x22, 0x47, 0x07, 0x07, 0x59, 0x12, 0x8F, 0xF7, 0xB2, 0x7C, 0x15, 0xDD, 0xB3, 0x67, 0xCF, 0x68, 379 | 0xE1, 0xC2, 0x85, 0x94, 0x2B, 0x57, 0x2E, 0x51, 0xB9, 0xF8, 0x66, 0x21, 0x2E, 0xE3, 0xCF, 0xCC, 380 | 0xB5, 0x04, 0x3E, 0x6E, 0xDF, 0x41, 0xAC, 0xDF, 0x1C, 0x0E, 0x08, 0x0E, 0x0A, 0xEE, 0x44, 0x4C, 381 | 0xCC, 0xD8, 0xEF, 0xF3, 0xC4, 0xAF, 0x93, 0xFB, 0x7D, 0x43, 0x00, 0x2D, 0xFC, 0x2A, 0x69, 0x2B, 382 | 0xA0, 0x4D, 0xDF, 0x11, 0x74, 0xFF, 0x76, 0x28, 0xED, 0xDD, 0xB4, 0x5E, 0x96, 0x18, 0xE7, 0x9A, 383 | 0x23, 0x07, 0xC5, 0xC4, 0xC6, 0xCA, 0x77, 0x60, 0x6D, 0x08, 0x80, 0x34, 0xE2, 0xBD, 0x7F, 0x81, 384 | 0x02, 0x05, 0x28, 0x6F, 0x2E, 0x37, 0x71, 0x9E, 0x7B, 0xEB, 0xAA, 0xC5, 0xF2, 0x93, 0x38, 0xEB, 385 | 0xE6, 0xCD, 0xA4, 0xC2, 0x7E, 0x25, 0xC5, 0x31, 0xAD, 0x31, 0x7C, 0x81, 0x0D, 0x37, 0x95, 0x7B, 386 | 0x7C, 0xD9, 0x5D, 0x96, 0xBC, 0x6E, 0xDC, 0xB8, 0x71, 0xA2, 0xA2, 0xF1, 0xEF, 0x30, 0x6E, 0x71, 387 | 0x30, 0xC3, 0x7B, 0xFE, 0x8C, 0x97, 0x31, 0xE5, 0x93, 0x4E, 0x1D, 0xC5, 0xFA, 0xF9, 0x77, 0x4C, 388 | 0xE1, 0x80, 0x68, 0xF8, 0x6E, 0x13, 0xF9, 0xEE, 0x75, 0x86, 0xDF, 0x37, 0x25, 0xB9, 0xDF, 0x6F, 389 | 0xFB, 0xF1, 0xC7, 0x46, 0x03, 0x28, 0xAB, 0x5B, 0x0E, 0xCA, 0x5B, 0xA8, 0x28, 0x6D, 0x59, 0xB1, 390 | 0x48, 0x96, 0x18, 0xE7, 0x94, 0xD9, 0x05, 0x43, 0x93, 0xA9, 0x08, 0x01, 0x60, 0x05, 0xC5, 0x8B, 391 | 0x17, 0x27, 0xB7, 0xAC, 0x59, 0x28, 0xBB, 0x5B, 0x4E, 0xBA, 0x74, 0x32, 0xBE, 0xD3, 0xEA, 0xD4, 392 | 0xBE, 0x5D, 0xA2, 0xE3, 0x8F, 0x2F, 0x90, 0x31, 0x85, 0x2F, 0xEF, 0xE5, 0xBD, 0x64, 0x99, 0x12, 393 | 0xC6, 0x8F, 0xFD, 0xD7, 0xAD, 0x5B, 0x27, 0xE6, 0x7C, 0xB6, 0xA1, 0x7B, 0xF7, 0xEE, 0x74, 0xF7, 394 | 0xEE, 0x5D, 0x31, 0xBE, 0x5F, 0x8F, 0x1E, 0xF1, 0x87, 0x13, 0x86, 0x65, 0x8C, 0x29, 0x58, 0xB0, 395 | 0xA0, 0x58, 0x3F, 0x5F, 0xC5, 0x67, 0x8C, 0x21, 0x80, 0xBA, 0x77, 0xEF, 0x26, 0x4B, 0x5E, 0x97, 396 | 0x70, 0xDD, 0x5D, 0xBB, 0x76, 0x15, 0xBF, 0xCF, 0x13, 0xBF, 0x36, 0x30, 0xF7, 0xFB, 0x9F, 0x76, 397 | 0xEA, 0x64, 0x32, 0x80, 0x5A, 0x74, 0xEF, 0x27, 0x5A, 0x01, 0x37, 0x2F, 0x5D, 0x90, 0x25, 0xF1, 398 | 0xB8, 0x25, 0xC5, 0x57, 0x05, 0x16, 0x54, 0x5A, 0x56, 0x59, 0xB3, 0x64, 0x95, 0xA5, 0x60, 0x6D, 399 | 0x08, 0x00, 0x2B, 0xC8, 0x99, 0x33, 0xA7, 0xB8, 0x62, 0x2D, 0x20, 0xA0, 0x82, 0x38, 0x0C, 0xD8, 400 | 0xB3, 0x31, 0xAE, 0x42, 0x70, 0xCF, 0x3F, 0x5F, 0xF0, 0x93, 0x3D, 0x47, 0x2E, 0xF1, 0xDE, 0x18, 401 | 0xBE, 0xB6, 0xDF, 0x1C, 0x43, 0xF3, 0x9A, 0x03, 0x60, 0xD5, 0xAA, 0x55, 0x94, 0x3B, 0x77, 0x6E, 402 | 0x71, 0xB5, 0x19, 0x8F, 0x19, 0x60, 0x60, 0xEE, 0x10, 0xC0, 0x80, 0x2F, 0xE1, 0x35, 0xC6, 0x10, 403 | 0x40, 0x25, 0x4C, 0x9C, 0x76, 0x4C, 0xB8, 0x6E, 0xFE, 0x4D, 0xFE, 0x7D, 0x9E, 0x52, 0xFA, 0xFB, 404 | 0x85, 0x0A, 0x15, 0x12, 0xEB, 0xE7, 0xDF, 0x49, 0x8C, 0xFB, 0x02, 0xB8, 0xF3, 0x74, 0xF5, 0xF7, 405 | 0x53, 0x64, 0x49, 0xBC, 0xAD, 0x2B, 0x17, 0x8B, 0x16, 0x55, 0x99, 0xE2, 0xBE, 0x4A, 0x0B, 0x20, 406 | 0xA3, 0x2C, 0x05, 0x6B, 0x43, 0x00, 0x58, 0x49, 0xD5, 0xAA, 0x55, 0xA9, 0x71, 0xA3, 0x86, 0x14, 407 | 0xF5, 0xEC, 0x09, 0xCD, 0x19, 0xD9, 0x8F, 0x6E, 0x5F, 0xBF, 0x2A, 0x8E, 0xFD, 0x1B, 0xB5, 0x8B, 408 | 0x3B, 0xF7, 0x6F, 0x0A, 0x5F, 0x57, 0x6F, 0x4E, 0x8B, 0x16, 0x2D, 0xE4, 0xAB, 0x78, 0x7C, 0xE6, 409 | 0x81, 0x03, 0xC1, 0xC0, 0xD8, 0x32, 0x89, 0x99, 0xFA, 0x9D, 0xE4, 0x02, 0x28, 0x25, 0xEB, 0x4E, 410 | 0xC9, 0x32, 0xA6, 0x7E, 0xA7, 0x74, 0xD5, 0xB7, 0xE9, 0xE8, 0xCE, 0xBF, 0x29, 0xE2, 0xE9, 0xEB, 411 | 0x1D, 0x7D, 0x17, 0x4F, 0x1E, 0x21, 0x17, 0x65, 0xCF, 0xFF, 0x7E, 0xD3, 0xA6, 0xB2, 0x04, 0xD4, 412 | 0x80, 0x00, 0xB0, 0x12, 0xEE, 0x0C, 0x6C, 0xDE, 0xBC, 0x39, 0xB5, 0x69, 0xD3, 0x46, 0xEC, 0xB9, 413 | 0xBE, 0xED, 0xFD, 0xA9, 0xE8, 0xF9, 0xE7, 0xCB, 0x5E, 0xCD, 0x49, 0xEE, 0xE6, 0x9D, 0x21, 0x43, 414 | 0x86, 0x88, 0xD3, 0x6A, 0xA6, 0xF0, 0x67, 0xBC, 0x4C, 0x72, 0xF8, 0xE6, 0x1D, 0x63, 0x92, 0x0B, 415 | 0x20, 0x6B, 0xFD, 0xBE, 0xA9, 0xDF, 0x69, 0xD0, 0xF6, 0x53, 0x31, 0xDF, 0xBB, 0x29, 0xFE, 0x30, 416 | 0x22, 0xE8, 0xAF, 0xDF, 0x44, 0xF3, 0xBF, 0x7E, 0xBD, 0xBA, 0x18, 0x85, 0x58, 0x65, 0x08, 0x00, 417 | 0x2B, 0x72, 0x70, 0x70, 0xA0, 0xB1, 0x63, 0xC6, 0x52, 0x99, 0xF2, 0xE5, 0xC5, 0x31, 0x6F, 0x4A, 418 | 0x46, 0xF0, 0x71, 0xCB, 0x6D, 0xFA, 0xFA, 0x01, 0xE6, 0xEC, 0xEC, 0x4C, 0x3B, 0x76, 0xEC, 0x30, 419 | 0x5A, 0x09, 0xB9, 0x8C, 0x3F, 0xE3, 0x65, 0x92, 0xC3, 0x77, 0xEE, 0x19, 0x93, 0x5C, 0x00, 0x59, 420 | 0xEB, 0xF7, 0x4D, 0x05, 0x90, 0xB3, 0x4B, 0x16, 0x71, 0xBE, 0xFF, 0xC8, 0x8E, 0xAD, 0xE2, 0x7D, 421 | 0x64, 0xC4, 0x33, 0x9A, 0x3B, 0x7A, 0x00, 0x45, 0x2B, 0x2D, 0xA9, 0x11, 0x23, 0x46, 0xBC, 0xEA, 422 | 0xF4, 0x04, 0x75, 0x20, 0x00, 0xAC, 0xCC, 0xCE, 0x2E, 0x03, 0x95, 0x2B, 0xEB, 0x2F, 0xAE, 0x62, 423 | 0x6B, 0xDE, 0xA5, 0x8F, 0x2C, 0x35, 0xAD, 0x80, 0x8F, 0x9F, 0xB8, 0x72, 0xEE, 0xDC, 0xF9, 0xA4, 424 | 0x1D, 0x61, 0x06, 0x01, 0x01, 0x01, 0xA2, 0xE3, 0x8D, 0x2B, 0x04, 0x77, 0x38, 0x72, 0x7F, 0x03, 425 | 0xBF, 0xE6, 0x32, 0xFE, 0xCC, 0x9C, 0x4B, 0x57, 0xAE, 0x88, 0xF5, 0xF3, 0x6D, 0xBB, 0xC6, 0xB8, 426 | 0x26, 0x13, 0x40, 0x2C, 0x2D, 0xBF, 0x6F, 0x60, 0x2A, 0x80, 0x18, 0x0F, 0x61, 0xCE, 0xF7, 0x49, 427 | 0xB0, 0x39, 0x23, 0xFA, 0x89, 0x16, 0xD4, 0x98, 0x31, 0x63, 0xC8, 0xC3, 0xC3, 0x43, 0x94, 0x81, 428 | 0x7A, 0x10, 0x00, 0x2A, 0x08, 0xBE, 0x70, 0x5E, 0xEC, 0xD5, 0x92, 0x1B, 0x13, 0x80, 0xF1, 0xBD, 429 | 0xF4, 0x7C, 0x3B, 0xED, 0xFC, 0x85, 0x0B, 0x65, 0x89, 0x71, 0xBC, 0x97, 0x1D, 0x3B, 0x76, 0x2C, 430 | 0x9D, 0x3E, 0x7D, 0x5A, 0x0C, 0x0D, 0xCE, 0xAF, 0x53, 0xB2, 0xE7, 0x5D, 0xB4, 0x78, 0xA9, 0x58, 431 | 0x3F, 0xFF, 0x8E, 0x31, 0x05, 0x65, 0x00, 0x1D, 0x3A, 0x6E, 0xFA, 0x82, 0x22, 0x96, 0xDA, 0xDF, 432 | 0xBF, 0x76, 0xED, 0x9A, 0xD9, 0x00, 0x62, 0xFE, 0xD5, 0x6B, 0x8B, 0x26, 0xFF, 0xAA, 0x99, 0x5F, 433 | 0xD3, 0x91, 0x7F, 0xB7, 0x52, 0xED, 0x3A, 0x75, 0xA8, 0x5D, 0xBB, 0x76, 0xF2, 0x53, 0x50, 0x13, 434 | 0x02, 0x40, 0x05, 0x87, 0x0F, 0x99, 0x3E, 0xE7, 0x9E, 0x18, 0x0F, 0xA4, 0xC1, 0xF7, 0xD2, 0xAF, 435 | 0x59, 0x95, 0xFC, 0x55, 0x71, 0xA9, 0xB1, 0x6A, 0xF9, 0x52, 0xB1, 0x7E, 0x53, 0x03, 0x76, 0x18, 436 | 0x02, 0x68, 0xF1, 0x92, 0x25, 0xB2, 0xC4, 0xBA, 0x96, 0x2C, 0x5D, 0x66, 0x36, 0x80, 0x98, 0x9F, 437 | 0x1C, 0xF7, 0x70, 0xE5, 0xB4, 0x09, 0xE2, 0x1E, 0x82, 0x49, 0x13, 0x27, 0x8A, 0xF7, 0xA0, 0x3E, 438 | 0x04, 0x80, 0x95, 0x9D, 0x3D, 0x7B, 0x96, 0x22, 0x22, 0x22, 0xC8, 0xBD, 0x40, 0x21, 0x59, 0x92, 439 | 0x3C, 0xBE, 0x4E, 0x80, 0x07, 0xF3, 0x98, 0x34, 0xE5, 0x1B, 0x59, 0x62, 0x1D, 0xB3, 0xE6, 0xCE, 440 | 0xA3, 0xA7, 0x91, 0xD1, 0x66, 0xAF, 0x43, 0x30, 0x04, 0xD0, 0x1F, 0x6B, 0xE3, 0x4F, 0xEB, 0x59, 441 | 0xD3, 0x92, 0xC5, 0x3F, 0x99, 0x0D, 0x20, 0x66, 0xE8, 0x07, 0x60, 0x23, 0xC7, 0x8C, 0xB5, 0xFA, 442 | 0xA0, 0x1A, 0x60, 0x1A, 0x02, 0xC0, 0xCA, 0x4E, 0xCA, 0xFB, 0xD7, 0x8B, 0x07, 0x54, 0x15, 0xF3, 443 | 0x94, 0xE0, 0x8E, 0x38, 0x1E, 0xC9, 0x67, 0xE6, 0xCC, 0xEF, 0xE9, 0xCC, 0x39, 0xD3, 0x7D, 0x01, 444 | 0x96, 0xB8, 0x7A, 0xE3, 0x26, 0x4D, 0x08, 0x1C, 0x2F, 0xD6, 0x9B, 0x5C, 0x47, 0x9F, 0x5A, 0x01, 445 | 0xB4, 0x44, 0x69, 0x55, 0x24, 0x17, 0x40, 0x06, 0x86, 0x3F, 0x63, 0xA9, 0x92, 0x25, 0xC5, 0xDC, 446 | 0x12, 0x7C, 0x46, 0x34, 0xC1, 0x59, 0x51, 0xB0, 0x00, 0x02, 0xC0, 0xCA, 0x4E, 0x1C, 0x3F, 0x2E, 447 | 0x3A, 0x00, 0x4B, 0x57, 0x79, 0x5B, 0x96, 0xA4, 0x0C, 0x0F, 0xE3, 0x95, 0xAB, 0x60, 0x11, 0xAA, 448 | 0x54, 0xB1, 0x02, 0xDD, 0x0F, 0x8F, 0xEB, 0x10, 0x4B, 0x2D, 0xFE, 0x7E, 0xA9, 0x12, 0xC5, 0xC5, 449 | 0xFA, 0x52, 0x32, 0x3C, 0x58, 0xC2, 0x00, 0xBA, 0x10, 0x7C, 0x51, 0x96, 0xA6, 0x0D, 0x3F, 0x91, 450 | 0x78, 0xE8, 0x88, 0x51, 0x29, 0x0A, 0x20, 0xC6, 0xAD, 0x04, 0x76, 0x31, 0xD8, 0xF2, 0x00, 0x44, 451 | 0xDD, 0x4F, 0x3D, 0x04, 0x80, 0x95, 0xF1, 0xC8, 0xC0, 0xDC, 0x9C, 0xE5, 0x61, 0xB0, 0x2C, 0xD5, 452 | 0x75, 0xFC, 0x0C, 0xB2, 0xCB, 0xE4, 0x48, 0x85, 0x0A, 0x16, 0xA0, 0x6B, 0xCA, 0x1E, 0x3C, 0x35, 453 | 0x78, 0xCF, 0xCF, 0xDF, 0x7F, 0xF2, 0xF8, 0x31, 0xB5, 0xED, 0x3F, 0x4A, 0x94, 0x3D, 0x79, 0x18, 454 | 0x4E, 0xDB, 0xD7, 0x2E, 0xA7, 0xD9, 0x23, 0xFA, 0x88, 0xD1, 0x7A, 0x78, 0xE2, 0xD7, 0x5C, 0xC6, 455 | 0x9F, 0x31, 0x43, 0x00, 0x55, 0x28, 0x5F, 0x8E, 0x1E, 0xA7, 0xF1, 0xEE, 0x3B, 0xBE, 0x3F, 0xC0, 456 | 0xCB, 0xCB, 0x2B, 0xC5, 0x01, 0xC4, 0x72, 0xE4, 0x89, 0x6B, 0xF6, 0xDF, 0xB8, 0xFE, 0xFA, 0x9D, 457 | 0x83, 0xC9, 0xE1, 0x3D, 0xFF, 0xB3, 0x97, 0x76, 0x08, 0x81, 0x54, 0x42, 0x00, 0x58, 0xD9, 0xB9, 458 | 0x73, 0x71, 0x4F, 0xEB, 0x4D, 0x8D, 0x5C, 0x79, 0x3D, 0x69, 0xF2, 0xEF, 0xFF, 0x90, 0xB7, 0x7F, 459 | 0x45, 0xAA, 0x56, 0xBD, 0x06, 0xCD, 0x5F, 0xF4, 0xFA, 0x8D, 0x45, 0xC9, 0x99, 0x35, 0x67, 0x1E, 460 | 0x95, 0xF0, 0xF5, 0x11, 0x95, 0xBF, 0x45, 0xB7, 0xFE, 0x74, 0xFD, 0xFC, 0x19, 0xFA, 0xBA, 0xEB, 461 | 0xC7, 0xD4, 0xA3, 0x5E, 0x45, 0x9A, 0x39, 0xB0, 0x3B, 0x6D, 0xFE, 0x79, 0x91, 0xB8, 0xEA, 0x8E, 462 | 0x27, 0x7E, 0xCD, 0x65, 0xFC, 0x19, 0x2F, 0x73, 0xF3, 0x52, 0x30, 0x05, 0xD4, 0x6E, 0x44, 0x8F, 463 | 0x95, 0xEF, 0x7A, 0x2A, 0xC7, 0xE0, 0xB7, 0x42, 0x43, 0xE5, 0x5A, 0x2D, 0xC3, 0x7B, 0xFE, 0x3C, 464 | 0x79, 0xF2, 0x50, 0x06, 0x25, 0xC8, 0x38, 0xD0, 0x52, 0xCA, 0x70, 0xB9, 0x34, 0x8F, 0xAE, 0x64, 465 | 0xA9, 0x67, 0x2F, 0x32, 0x20, 0x00, 0x52, 0x09, 0x01, 0x60, 0x45, 0x0F, 0x1F, 0x3E, 0xA4, 0xA8, 466 | 0xA8, 0x28, 0x71, 0x55, 0x60, 0x6A, 0x71, 0x08, 0xF0, 0xA3, 0xC0, 0xB8, 0xE9, 0x3C, 0x7A, 0xF4, 467 | 0x68, 0xB1, 0x27, 0x1D, 0xA9, 0xCC, 0xF9, 0x74, 0x9A, 0x31, 0x7C, 0x9E, 0x7F, 0xE4, 0xD8, 0x71, 468 | 0xE4, 0xE3, 0xEB, 0x4B, 0x03, 0xFA, 0xF4, 0x22, 0xCA, 0x68, 0x4F, 0xFD, 0xBF, 0x5B, 0x44, 0x99, 469 | 0xB3, 0x66, 0xA3, 0x19, 0x03, 0xBA, 0xD0, 0xBE, 0x2D, 0x7F, 0x88, 0xF3, 0xEA, 0xA6, 0xF0, 0x67, 470 | 0xBC, 0x4C, 0xCF, 0xFA, 0x15, 0x29, 0x32, 0xE2, 0xA9, 0x08, 0x0E, 0x0E, 0x81, 0x62, 0xCA, 0xEF, 471 | 0x5A, 0x1A, 0x40, 0x7C, 0xCC, 0x5F, 0xBE, 0x62, 0x65, 0xF2, 0x52, 0x02, 0x6C, 0xCA, 0xBA, 0x1D, 472 | 0xE2, 0xEF, 0x92, 0x52, 0x4E, 0xF2, 0x42, 0xA3, 0xCB, 0x97, 0x2F, 0x8B, 0xB9, 0x25, 0x32, 0x65, 473 | 0x78, 0x49, 0x2F, 0xE4, 0x6B, 0xB0, 0x0C, 0x02, 0xC0, 0x8A, 0x78, 0xEF, 0xC7, 0xB2, 0xBA, 0xBA, 474 | 0x89, 0x79, 0x5A, 0x70, 0xD3, 0x79, 0xD8, 0x4F, 0xBF, 0x51, 0x6E, 0xAF, 0x12, 0xB4, 0xFE, 0xEF, 475 | 0x9D, 0x54, 0xED, 0xED, 0x5A, 0x22, 0x0C, 0x12, 0x4F, 0xA5, 0x4B, 0x96, 0xA4, 0xE9, 0xD3, 0xA7, 476 | 0x53, 0x8E, 0x42, 0x3E, 0x34, 0x6A, 0xD9, 0x1F, 0x34, 0x67, 0xD7, 0x29, 0xF2, 0xF4, 0x2A, 0x46, 477 | 0xAB, 0x67, 0x25, 0xBD, 0xC1, 0x26, 0x39, 0x6B, 0x7F, 0x98, 0x4A, 0xD5, 0x9A, 0x34, 0xA7, 0x3E, 478 | 0xD3, 0xE6, 0x89, 0x20, 0xE9, 0xD9, 0xBD, 0xAB, 0xF8, 0x8D, 0x41, 0xC3, 0x47, 0xD0, 0xA5, 0xCB, 479 | 0x57, 0xE4, 0x52, 0xAF, 0xBB, 0xAE, 0x34, 0xD9, 0xC7, 0x4F, 0x98, 0x40, 0x7E, 0x7E, 0x7E, 0xE2, 480 | 0x98, 0xDF, 0xBF, 0x76, 0x43, 0x11, 0x60, 0x39, 0x65, 0x93, 0x3E, 0xA5, 0x1C, 0x9D, 0xE2, 0xC6, 481 | 0x52, 0xBC, 0x71, 0xE3, 0x86, 0x98, 0xA7, 0x14, 0x5F, 0x28, 0xE8, 0xA4, 0x04, 0xC0, 0x4B, 0xC2, 482 | 0x15, 0x83, 0xA9, 0x81, 0xE7, 0x02, 0x58, 0x51, 0x50, 0x50, 0x10, 0xB5, 0x6C, 0xD9, 0x92, 0x3E, 483 | 0xF8, 0xA4, 0x2B, 0xB5, 0x1D, 0x3A, 0x5E, 0x96, 0x5A, 0x07, 0x5F, 0x5A, 0x9C, 0x92, 0x27, 0x03, 484 | 0xF1, 0x18, 0xFC, 0x5F, 0xD6, 0xAD, 0x40, 0xD1, 0x91, 0x11, 0xE2, 0xA6, 0x21, 0x4B, 0xF0, 0x18, 485 | 0x03, 0x0E, 0x4E, 0xCE, 0xF4, 0xF9, 0xD8, 0x6F, 0xA8, 0x52, 0xBD, 0xC6, 0xE2, 0x36, 0xDD, 0xB5, 486 | 0xB3, 0xA6, 0xA6, 0xEC, 0xB9, 0x00, 0x15, 0xAB, 0x52, 0xA7, 0x61, 0x81, 0x94, 0x3B, 0x5F, 0x01, 487 | 0xF9, 0x89, 0x65, 0xA2, 0x9E, 0x3C, 0xA2, 0x36, 0xFE, 0x85, 0x28, 0x63, 0xC6, 0x8C, 0x26, 0x5B, 488 | 0x3B, 0xA6, 0xC4, 0x28, 0x9B, 0x30, 0xFF, 0x4D, 0x1D, 0xD2, 0x41, 0x06, 0xE0, 0xC1, 0x20, 0x92, 489 | 0x1E, 0x03, 0x60, 0xCD, 0x9A, 0x35, 0xD4, 0xB3, 0x67, 0x4F, 0x6A, 0xD7, 0x6B, 0x10, 0x35, 0xEF, 490 | 0x31, 0x58, 0x96, 0xDA, 0x4E, 0xE8, 0xB5, 0x2B, 0x34, 0xA4, 0x45, 0x3D, 0xB2, 0x7F, 0x19, 0x4B, 491 | 0xED, 0x5A, 0x7F, 0x44, 0x4B, 0x7F, 0x5E, 0x41, 0xF7, 0x1F, 0x3C, 0x90, 0x9F, 0x9A, 0x97, 0xC3, 492 | 0xCD, 0x8D, 0xDA, 0xB6, 0x69, 0x4D, 0xCB, 0x96, 0xFF, 0x2C, 0xBE, 0xC3, 0x4F, 0xFB, 0xF5, 0xF1, 493 | 0x8F, 0xBF, 0xCC, 0x37, 0xA5, 0x01, 0x94, 0x5A, 0x2F, 0x62, 0x63, 0xA8, 0x4F, 0xC3, 0x2A, 0x74, 494 | 0xE3, 0xF2, 0x45, 0xDA, 0xBB, 0x77, 0xAF, 0x18, 0x64, 0x25, 0xA5, 0xF8, 0x01, 0xAB, 0x1C, 0x00, 495 | 0xF6, 0x08, 0x00, 0x8B, 0xE1, 0x10, 0xC0, 0x8A, 0x78, 0xA0, 0x0E, 0xE6, 0x62, 0x64, 0x50, 0x4D, 496 | 0xB5, 0x71, 0x05, 0x9D, 0xDA, 0xE5, 0x23, 0x0A, 0x28, 0x53, 0x92, 0xB6, 0xFC, 0xB9, 0x8E, 0xBA, 497 | 0x7D, 0xFE, 0x19, 0xFD, 0xB1, 0xF6, 0x17, 0x6A, 0x50, 0xB7, 0x8E, 0xA8, 0xDC, 0xA6, 0xF0, 0x67, 498 | 0xBC, 0x0C, 0x2F, 0xDB, 0xBD, 0xF3, 0xA7, 0xE2, 0xBB, 0xB5, 0x6B, 0xD5, 0xA4, 0x79, 0x43, 0xBF, 499 | 0x7C, 0x6D, 0x10, 0x8F, 0x62, 0x65, 0x2B, 0x88, 0x11, 0x7D, 0x3F, 0x1B, 0x35, 0x49, 0x34, 0xF1, 500 | 0x79, 0xCE, 0xEF, 0xAB, 0x36, 0x6C, 0x96, 0xE6, 0xCA, 0xCF, 0xEC, 0x94, 0x43, 0x8E, 0x32, 0x95, 501 | 0xAB, 0x89, 0xD7, 0x7C, 0x58, 0x61, 0x09, 0xAE, 0x19, 0xE9, 0xA0, 0xEE, 0x6B, 0x12, 0x02, 0xC0, 502 | 0x8A, 0xF8, 0xE6, 0x18, 0xE6, 0x6C, 0xE3, 0x00, 0xE0, 0x53, 0x79, 0x73, 0x87, 0x74, 0xA7, 0x4A, 503 | 0xE5, 0xCA, 0xD2, 0xAC, 0x69, 0x53, 0xC9, 0x45, 0x76, 0xA8, 0x71, 0xE5, 0x9E, 0x3E, 0xE5, 0x6B, 504 | 0x51, 0xB9, 0xC7, 0x8D, 0x1A, 0x41, 0x3E, 0xC5, 0xE2, 0xAF, 0xC7, 0xE7, 0xD7, 0x5C, 0xC6, 0x9F, 505 | 0xF1, 0x32, 0x86, 0x90, 0xE0, 0xEF, 0xF2, 0x3A, 0x2A, 0x97, 0x2B, 0x23, 0xD6, 0x69, 0x38, 0x4D, 506 | 0x68, 0x0B, 0x99, 0x1C, 0x52, 0x17, 0x24, 0xDC, 0x0F, 0x80, 0x00, 0x48, 0x1D, 0x04, 0x80, 0x15, 507 | 0xDD, 0xBF, 0x1F, 0xF7, 0xB0, 0x0B, 0x97, 0x2C, 0xC9, 0xDF, 0x06, 0x6C, 0x4D, 0xB3, 0x06, 0xF7, 508 | 0xA0, 0x7C, 0xB9, 0x73, 0xD2, 0xA8, 0x21, 0xC6, 0x07, 0x1E, 0xE5, 0xCA, 0xDD, 0xA2, 0xF9, 0xFB, 509 | 0xB4, 0xEE, 0x97, 0x95, 0x74, 0xF6, 0xE8, 0x21, 0x31, 0xF1, 0x6B, 0x2E, 0x33, 0xD5, 0x3A, 0x18, 510 | 0x39, 0x64, 0xB0, 0x58, 0x27, 0xAF, 0xDB, 0x56, 0x9C, 0x5D, 0xE2, 0x82, 0x2B, 0x24, 0x24, 0x44, 511 | 0xCC, 0x2D, 0x81, 0x00, 0x48, 0x1D, 0x04, 0x80, 0x0A, 0xEC, 0xD2, 0x70, 0x1A, 0x30, 0x35, 0xB8, 512 | 0x93, 0xAE, 0x74, 0x59, 0x7F, 0xF9, 0xCE, 0xB4, 0xA0, 0xBD, 0xFB, 0xA8, 0x73, 0xF7, 0x1E, 0x62, 513 | 0xDA, 0x7B, 0xE0, 0xA0, 0x2C, 0x35, 0xAD, 0x6C, 0xD9, 0x32, 0xC9, 0x8E, 0x28, 0x6C, 0x4D, 0x4E, 514 | 0x99, 0xE3, 0x5A, 0x4E, 0xFC, 0x9C, 0x05, 0xB0, 0x0D, 0x04, 0x80, 0x0A, 0xEC, 0xEC, 0x6D, 0x1B, 515 | 0x00, 0x85, 0xFC, 0x4A, 0xD2, 0xA6, 0xAD, 0xDB, 0xE8, 0xA9, 0x99, 0xD1, 0x7B, 0x17, 0x2C, 0x59, 516 | 0x46, 0xFD, 0x87, 0x0C, 0xA3, 0x9D, 0xBB, 0x83, 0xE8, 0xC4, 0xB9, 0x60, 0xEA, 0x3B, 0x70, 0x30, 517 | 0xCD, 0x5F, 0xB2, 0x5C, 0x7E, 0x9A, 0x14, 0xAF, 0x6B, 0xC3, 0xD6, 0xED, 0x62, 0xDD, 0xB6, 0x92, 518 | 0x59, 0x0E, 0xA0, 0x62, 0x68, 0x49, 0x81, 0xFA, 0x10, 0x00, 0x56, 0x64, 0xD8, 0x73, 0xD9, 0x5B, 519 | 0xA1, 0x53, 0xCC, 0x12, 0xED, 0x07, 0x8D, 0xA5, 0xBC, 0x3E, 0xA5, 0xE8, 0x7F, 0x1D, 0x3F, 0xA3, 520 | 0x65, 0x2B, 0x56, 0x89, 0xBB, 0x11, 0x0D, 0xB8, 0x22, 0x8F, 0x9E, 0x30, 0x89, 0xE6, 0x2D, 0x58, 521 | 0x48, 0x11, 0xCF, 0xE3, 0xFE, 0x7C, 0x05, 0x0B, 0x17, 0xA1, 0x22, 0xBE, 0xC5, 0xC5, 0x33, 0xF8, 522 | 0xF9, 0xB3, 0x84, 0xC1, 0xC1, 0xDF, 0x5D, 0xBA, 0x72, 0x95, 0x58, 0x17, 0xAF, 0x93, 0xD7, 0x6D, 523 | 0x2B, 0x99, 0xB3, 0xC4, 0x3D, 0x2F, 0xD1, 0xDC, 0x30, 0xE4, 0xA6, 0x60, 0xE0, 0xA0, 0xD4, 0x41, 524 | 0x00, 0x58, 0x91, 0xE1, 0xD8, 0xD5, 0xCD, 0x3D, 0xAF, 0x98, 0xDB, 0x12, 0x5F, 0xBC, 0x53, 0xA1, 525 | 0x61, 0x73, 0x9A, 0x3E, 0x67, 0x3E, 0xD5, 0x79, 0xF7, 0xBD, 0x57, 0x4D, 0xFD, 0x7A, 0x8D, 0x9B, 526 | 0xD2, 0x0A, 0xA5, 0x42, 0x17, 0xF6, 0x29, 0x4E, 0x45, 0x95, 0x4A, 0xCF, 0x5C, 0x1C, 0xED, 0xE9, 527 | 0xEF, 0xCD, 0x1B, 0xA9, 0x78, 0x89, 0x12, 0xE2, 0x33, 0x5E, 0xC6, 0xB0, 0x3C, 0x7F, 0x77, 0xC6, 528 | 0xEC, 0xF9, 0x62, 0x5D, 0xE2, 0x82, 0x20, 0x1B, 0x72, 0x92, 0xC3, 0x7F, 0x3F, 0x7A, 0xF4, 0x48, 529 | 0xCC, 0x41, 0x7D, 0x08, 0x00, 0x15, 0xA4, 0xB6, 0x37, 0x3B, 0xAD, 0x5A, 0xF5, 0x1C, 0x44, 0x73, 530 | 0x76, 0x9E, 0xA4, 0x0E, 0xA3, 0x26, 0xD3, 0xD9, 0xCB, 0xD7, 0x44, 0x73, 0xDF, 0x23, 0x6F, 0x3E, 531 | 0x5A, 0xB6, 0x7C, 0x39, 0xED, 0xDC, 0xBE, 0x95, 0xB2, 0x3B, 0xC5, 0x1D, 0x9A, 0xF0, 0x7F, 0x7A, 532 | 0xB6, 0xAC, 0x59, 0xC5, 0x23, 0xBE, 0xFA, 0xF4, 0xED, 0x2B, 0xCE, 0xFB, 0xF3, 0xF2, 0xAE, 0x3E, 533 | 0x65, 0xA8, 0xA3, 0xF2, 0x5D, 0x5E, 0x07, 0xAF, 0xCB, 0xD6, 0x0C, 0x0F, 0x4D, 0x45, 0x00, 0xD8, 534 | 0x0E, 0x02, 0x40, 0x05, 0x19, 0x33, 0x25, 0x7D, 0xC4, 0x97, 0xAD, 0xF0, 0x39, 0xF9, 0xEA, 0x4D, 535 | 0x3E, 0x24, 0x9F, 0x72, 0x15, 0xC5, 0xFB, 0xDD, 0xBB, 0x76, 0x52, 0x9B, 0xD6, 0xAD, 0x29, 0xB3, 536 | 0xB3, 0x33, 0x45, 0x45, 0x46, 0x8A, 0xB2, 0x48, 0x39, 0x77, 0x72, 0x72, 0xA2, 0x11, 0xC3, 0x87, 537 | 0x8B, 0xD7, 0xBC, 0x7C, 0xC7, 0x61, 0x13, 0xA8, 0x9A, 0xF2, 0x5D, 0x6B, 0x9C, 0xD7, 0x4F, 0x0D, 538 | 0x7B, 0x33, 0x8F, 0x56, 0x07, 0x75, 0x20, 0x00, 0xAC, 0x8C, 0xC7, 0x02, 0x70, 0x71, 0xCD, 0x21, 539 | 0xDF, 0xBD, 0x39, 0x3C, 0xC8, 0x66, 0x99, 0xB2, 0x65, 0xC5, 0x03, 0x3C, 0x0D, 0xF8, 0x31, 0xE6, 540 | 0x09, 0xE7, 0xCC, 0xD5, 0xD5, 0x95, 0x7C, 0x4A, 0x95, 0x79, 0x35, 0x28, 0xE7, 0x9B, 0x84, 0x00, 541 | 0xB0, 0x3D, 0x04, 0x80, 0x95, 0xF1, 0x58, 0x00, 0x0E, 0xF2, 0xC6, 0x96, 0x37, 0x2D, 0x61, 0xBF, 542 | 0xD8, 0x85, 0x0B, 0x17, 0xE8, 0xCA, 0x95, 0xB8, 0x1B, 0x7A, 0x78, 0xCE, 0x8F, 0xEF, 0x7E, 0x25, 543 | 0x9D, 0x0C, 0xA7, 0x93, 0xC9, 0xC8, 0xC3, 0x51, 0x41, 0x5D, 0x08, 0x00, 0x2B, 0xCA, 0x96, 0x2D, 544 | 0x9B, 0x18, 0xDD, 0xD6, 0xD0, 0xD4, 0x7E, 0x93, 0xCA, 0xD5, 0xA8, 0x4D, 0x97, 0xAF, 0xDF, 0xA4, 545 | 0xBA, 0x75, 0xEB, 0xD2, 0xA8, 0x51, 0xA3, 0xA8, 0xC9, 0x7B, 0xEF, 0x91, 0x4B, 0x76, 0x37, 0x6A, 546 | 0xFE, 0x79, 0x2F, 0x31, 0x6F, 0xD2, 0xA4, 0x89, 0xB8, 0xDD, 0xB8, 0x5E, 0xBD, 0x7A, 0x14, 0x1A, 547 | 0x12, 0x42, 0x65, 0xAA, 0xD5, 0x92, 0xDF, 0x7C, 0x73, 0x32, 0xDA, 0xF8, 0xF4, 0x29, 0x20, 0x00, 548 | 0xAC, 0x2A, 0x7B, 0xF6, 0xEC, 0xE2, 0xFE, 0x7A, 0x73, 0xF7, 0xDF, 0xDB, 0x4A, 0x93, 0x4F, 0xBA, 549 | 0x53, 0xC3, 0x36, 0x9D, 0xE8, 0xC0, 0x91, 0x63, 0x62, 0x08, 0xEF, 0xD0, 0x3B, 0xF7, 0xA8, 0x4D, 550 | 0xDF, 0xE1, 0xD4, 0x6E, 0xE0, 0x68, 0x6A, 0xD7, 0x7F, 0x24, 0x85, 0x28, 0xEF, 0x79, 0xEC, 0x7D, 551 | 0xFE, 0xBC, 0x7E, 0xEB, 0x8E, 0xD4, 0xEC, 0x33, 0xDB, 0x5D, 0xF1, 0x67, 0x4A, 0x06, 0x3B, 0x3C, 552 | 0x03, 0xD0, 0xD6, 0x10, 0x00, 0x2A, 0x48, 0x2F, 0xA7, 0xA4, 0x5B, 0xF5, 0x1E, 0x4A, 0xB3, 0xFF, 553 | 0x3D, 0x4E, 0xDF, 0xAC, 0xDF, 0x49, 0x3F, 0xFC, 0x73, 0x8C, 0xEA, 0x7D, 0xD4, 0x41, 0x94, 0xD7, 554 | 0xF9, 0xDF, 0xC7, 0xA2, 0x7C, 0xC6, 0x86, 0x20, 0x9A, 0xBD, 0xF3, 0x04, 0xB5, 0xEE, 0x33, 0x4C, 555 | 0x94, 0xBF, 0x69, 0x69, 0xFD, 0x77, 0xC3, 0xC0, 0xA0, 0x96, 0x43, 0x00, 0xFC, 0xC7, 0xF1, 0xFD, 556 | 0xFD, 0x85, 0x8B, 0x97, 0x7A, 0x35, 0xE2, 0x8E, 0x01, 0x97, 0x7B, 0x16, 0x2B, 0x4E, 0x0E, 0xE9, 557 | 0xA8, 0xE3, 0xCD, 0xC5, 0x2D, 0x87, 0xE8, 0x44, 0x05, 0xDB, 0xD1, 0x64, 0x00, 0xF0, 0xA0, 0x11, 558 | 0xE9, 0x11, 0x3F, 0x36, 0x9B, 0x3D, 0x7D, 0x8C, 0xF3, 0xD8, 0xA9, 0xE1, 0xE4, 0x9C, 0x59, 0x74, 559 | 0xA2, 0x86, 0x3F, 0x7C, 0xF3, 0x67, 0x24, 0x52, 0x23, 0xBD, 0x6E, 0x97, 0xE6, 0x68, 0x32, 0x00, 560 | 0xD2, 0x32, 0xE6, 0x9E, 0x9A, 0x1C, 0xE5, 0xF9, 0xF3, 0xD8, 0x98, 0xE7, 0x62, 0x0E, 0xA9, 0xA3, 561 | 0xD5, 0x0B, 0x81, 0xD2, 0xEB, 0x76, 0x69, 0x8E, 0x26, 0x03, 0x80, 0x2F, 0x60, 0x49, 0xCF, 0x2C, 562 | 0x1D, 0x8A, 0x0B, 0xAC, 0xE3, 0x4D, 0xDF, 0x0F, 0x90, 0xDE, 0xB7, 0x4B, 0x63, 0x34, 0x19, 0x00, 563 | 0xFC, 0x50, 0xCA, 0xF4, 0xDC, 0xDC, 0x7A, 0x19, 0x1B, 0x2B, 0x5F, 0x81, 0x5E, 0xF0, 0xF6, 0x98, 564 | 0x92, 0x87, 0xA5, 0xA6, 0x37, 0x9A, 0x0C, 0x00, 0x7E, 0x66, 0x3C, 0x9F, 0x73, 0x4F, 0x6F, 0xF2, 565 | 0xE6, 0x8D, 0xBB, 0x09, 0xE8, 0x5E, 0x68, 0xEA, 0x1E, 0xEA, 0x01, 0xDA, 0xC5, 0xDB, 0x23, 0x6F, 566 | 0x97, 0x5A, 0xA3, 0xC9, 0x00, 0x60, 0x9C, 0xB6, 0x99, 0x13, 0xF5, 0x6C, 0xBF, 0x69, 0x86, 0x56, 567 | 0x49, 0x2C, 0x06, 0xB4, 0xD0, 0x15, 0xDE, 0x0E, 0xB5, 0xB8, 0xF7, 0x67, 0x9A, 0x0D, 0x00, 0xC6, 568 | 0x17, 0xDE, 0xA4, 0xB7, 0x10, 0x60, 0x2F, 0x70, 0x08, 0xA0, 0x1B, 0xBC, 0xFD, 0xF1, 0x76, 0xA8, 569 | 0x55, 0x9A, 0x0E, 0x00, 0x6E, 0x72, 0xF1, 0xCD, 0x2C, 0x7C, 0xC3, 0x4B, 0x7A, 0xE8, 0x13, 0xB0, 570 | 0xB7, 0xB7, 0x17, 0xF3, 0xC8, 0xA7, 0x69, 0x7B, 0xB6, 0x1E, 0xA4, 0x7F, 0xBC, 0xBD, 0xF1, 0x76, 571 | 0xC7, 0xDB, 0x9F, 0x16, 0x9B, 0xFE, 0x06, 0x9A, 0x0E, 0x00, 0x03, 0x6E, 0x7E, 0xB9, 0xBB, 0xBB, 572 | 0x8B, 0xFF, 0x0C, 0xEE, 0x89, 0x7D, 0x53, 0x61, 0x60, 0xE8, 0x03, 0x78, 0x70, 0xE7, 0xB6, 0x98, 573 | 0x83, 0xE5, 0x4A, 0x95, 0x0B, 0x48, 0xD5, 0x23, 0xC2, 0x6D, 0x81, 0xB7, 0x2B, 0xDE, 0xBE, 0x78, 574 | 0x3B, 0xE3, 0xED, 0x4D, 0xAB, 0xCD, 0xFE, 0x84, 0x34, 0xF9, 0x60, 0x90, 0xF4, 0x2E, 0xE6, 0xC5, 575 | 0x4B, 0xF1, 0xBC, 0x7D, 0xB0, 0x1C, 0x3F, 0x7D, 0xC8, 0xDE, 0x4E, 0xBB, 0x7B, 0x54, 0x6B, 0xC3, 576 | 0x93, 0x81, 0x00, 0x74, 0x0C, 0x4F, 0x06, 0x02, 0x00, 0xD5, 0x20, 0x00, 0x00, 0x74, 0x0C, 0x01, 577 | 0x00, 0xA0, 0x63, 0x08, 0x00, 0x00, 0x1D, 0x43, 0x00, 0x00, 0xE8, 0x98, 0x9A, 0x01, 0x10, 0x2A, 578 | 0xE7, 0x00, 0x90, 0x36, 0xAA, 0xD5, 0x25, 0x35, 0x03, 0xE0, 0xE8, 0xC6, 0x8D, 0x1B, 0xF9, 0x39, 579 | 0x6F, 0xB8, 0x33, 0x06, 0x20, 0x15, 0xB8, 0xEE, 0x70, 0x1D, 0x52, 0x1C, 0x15, 0x05, 0x2A, 0x50, 580 | 0x33, 0x00, 0x36, 0x5D, 0xBD, 0x7A, 0x95, 0xD6, 0xAC, 0x59, 0x13, 0xFF, 0xA0, 0x3A, 0x00, 0x48, 581 | 0x31, 0xAE, 0x3B, 0x5C, 0x87, 0x14, 0x9B, 0x44, 0x81, 0x0A, 0xD4, 0xBC, 0x10, 0x88, 0x07, 0x77, 582 | 0xBB, 0x5E, 0xA8, 0x50, 0x21, 0xA7, 0xF3, 0xE7, 0xCF, 0xDF, 0x77, 0x70, 0x70, 0x78, 0xF3, 0x4F, 583 | 0xCB, 0x00, 0xD0, 0x88, 0xE8, 0xE8, 0xE8, 0xFB, 0x3E, 0x3E, 0x3E, 0x39, 0x94, 0x00, 0xE0, 0x31, 584 | 0xE6, 0x0B, 0x28, 0xF5, 0x54, 0x95, 0xA1, 0xA6, 0x55, 0x6B, 0x01, 0xC8, 0x3F, 0xF0, 0x4C, 0x4E, 585 | 0xB0, 0xC9, 0x93, 0x27, 0x63, 0x8C, 0x2C, 0x00, 0x0B, 0x70, 0x9D, 0x91, 0x7B, 0xFF, 0x99, 0x6A, 586 | 0x55, 0x7E, 0xA6, 0xF6, 0x59, 0x80, 0x31, 0xCA, 0x74, 0x76, 0xEE, 0xDC, 0xB9, 0x1E, 0x7F, 0xFE, 587 | 0xF9, 0x67, 0xDC, 0xA3, 0x73, 0x01, 0xC0, 0x2C, 0xAE, 0x2B, 0x5C, 0x67, 0x94, 0x97, 0x67, 0x95, 588 | 0x89, 0xEB, 0x90, 0x6A, 0x54, 0x3B, 0x04, 0x30, 0x50, 0x0E, 0x05, 0xFC, 0x94, 0xD9, 0x76, 0xE5, 589 | 0x50, 0x20, 0x4F, 0xE7, 0xCE, 0x9D, 0x6F, 0x0F, 0x18, 0x30, 0x20, 0x13, 0x0E, 0x07, 0x00, 0x92, 590 | 0xE2, 0x66, 0x3F, 0xEF, 0xF9, 0xB9, 0xF2, 0x2B, 0x7B, 0x7F, 0xEE, 0xF9, 0x7F, 0x47, 0xA9, 0x9F, 591 | 0x1C, 0x02, 0xAA, 0x51, 0x3D, 0x00, 0x98, 0x0C, 0x81, 0x5F, 0x95, 0xC9, 0x4F, 0x09, 0x02, 0x1A, 592 | 0x36, 0x6C, 0x58, 0x70, 0xCB, 0x96, 0x2D, 0x9D, 0x5D, 0x5D, 0x5D, 0x3D, 0xC5, 0x02, 0x00, 0x3A, 593 | 0x16, 0x1E, 0x1E, 0x7E, 0xF3, 0x97, 0x5F, 0x7E, 0x89, 0x08, 0x0C, 0x0C, 0xF4, 0x96, 0xCD, 0x7E, 594 | 0xAE, 0xF4, 0xCD, 0xD5, 0xAE, 0xFC, 0xCC, 0x26, 0x01, 0xC0, 0x94, 0x10, 0xC8, 0xA2, 0xCC, 0x46, 595 | 0x29, 0xD3, 0x97, 0xCA, 0xE4, 0xC4, 0x41, 0xD0, 0xB0, 0x61, 0x43, 0xFE, 0x08, 0x40, 0xD7, 0xF8, 596 | 0x54, 0x9F, 0xAC, 0xF8, 0xDC, 0xE1, 0x37, 0x53, 0x99, 0xC6, 0x28, 0xF5, 0xD2, 0x26, 0xA3, 0xCA, 597 | 0xD8, 0x2C, 0x00, 0x0C, 0xE4, 0xD9, 0x81, 0x76, 0xCA, 0xD4, 0x40, 0x99, 0xFC, 0x95, 0x29, 0x8F, 598 | 0x32, 0x01, 0xE8, 0x15, 0x37, 0xF5, 0xF9, 0x3C, 0x3F, 0x9F, 0xEA, 0x5B, 0xAA, 0xD4, 0x47, 0x9B, 599 | 0x3E, 0x58, 0xD2, 0xE6, 0x01, 0x00, 0x00, 0xE9, 0x87, 0xDA, 0x67, 0x01, 0x00, 0x20, 0x1D, 0x43, 600 | 0x00, 0x00, 0xE8, 0x18, 0x02, 0x00, 0x40, 0xC7, 0x10, 0x00, 0x00, 0x3A, 0x86, 0x00, 0x00, 0xD0, 601 | 0x31, 0x04, 0x00, 0x80, 0x8E, 0x21, 0x00, 0x00, 0x74, 0x0C, 0x01, 0x00, 0xA0, 0x63, 0x08, 0x00, 602 | 0x00, 0x1D, 0x43, 0x00, 0x00, 0xE8, 0x18, 0x02, 0x00, 0x40, 0xC7, 0x10, 0x00, 0x00, 0x3A, 0x86, 603 | 0x00, 0x00, 0xD0, 0x31, 0x04, 0x00, 0x80, 0x8E, 0x21, 0x00, 0x00, 0x74, 0x0C, 0x01, 0x00, 0xA0, 604 | 0x63, 0x08, 0x00, 0x00, 0x1D, 0x43, 0x00, 0x00, 0xE8, 0x18, 0x02, 0x00, 0x40, 0xC7, 0x10, 0x00, 605 | 0x00, 0x3A, 0x86, 0x00, 0x00, 0xD0, 0x2D, 0xA2, 0xFF, 0x03, 0x8D, 0x89, 0x1E, 0xAF, 0x79, 0x58, 606 | 0x8B, 0x33, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4E, 0x44, 0xAE, 0x42, 0x60, 0x82, 607 | } 608 | 609 | var initIcon16 = []byte{ 610 | 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A, 0x00, 0x00, 0x00, 0x0D, 0x49, 0x48, 0x44, 0x52, 611 | 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x08, 0x06, 0x00, 0x00, 0x00, 0x73, 0x7A, 0x7A, 612 | 0xF4, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, 0x47, 0x42, 0x00, 0xAE, 0xCE, 0x1C, 0xE9, 0x00, 0x00, 613 | 0x00, 0x04, 0x67, 0x41, 0x4D, 0x41, 0x00, 0x00, 0xB1, 0x8F, 0x0B, 0xFC, 0x61, 0x05, 0x00, 0x00, 614 | 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0E, 0xC3, 0x00, 0x00, 0x0E, 0xC3, 0x01, 0xC7, 615 | 0x6F, 0xA8, 0x64, 0x00, 0x00, 0x03, 0xF0, 0x49, 0x44, 0x41, 0x54, 0x58, 0x47, 0xED, 0x96, 0x5F, 616 | 0x4C, 0x5B, 0x55, 0x1C, 0xC7, 0xBF, 0xFD, 0x97, 0x14, 0xBA, 0x01, 0x83, 0x2A, 0xC5, 0x82, 0xBB, 617 | 0x94, 0x41, 0xD1, 0x75, 0x53, 0x32, 0xB2, 0xB8, 0x05, 0x45, 0x34, 0xFE, 0x99, 0xC9, 0x12, 0x75, 618 | 0x66, 0x71, 0x71, 0xCE, 0x18, 0xA3, 0x89, 0x0F, 0x3E, 0x18, 0x9F, 0x7C, 0xF4, 0xD5, 0x17, 0xE3, 619 | 0xC3, 0x5E, 0x94, 0x87, 0x19, 0x62, 0x66, 0xE2, 0xA6, 0x6E, 0x71, 0x0D, 0x8E, 0x0C, 0x1D, 0x6E, 620 | 0xE8, 0x82, 0x63, 0x0E, 0x0A, 0x14, 0x0A, 0xAC, 0x93, 0x3F, 0x05, 0x5A, 0x68, 0x21, 0xFC, 0x59, 621 | 0x6F, 0x5B, 0xAE, 0xBF, 0x73, 0xEE, 0x29, 0x5D, 0x71, 0x5C, 0x8A, 0x14, 0x7D, 0xD0, 0x4F, 0xFB, 622 | 0xEB, 0xF9, 0x9D, 0xDF, 0x3D, 0xB7, 0xF7, 0x7B, 0x7E, 0xF7, 0xFE, 0xCE, 0x3D, 0xF8, 0xCF, 0xA3, 623 | 0x13, 0x2D, 0x76, 0xEF, 0xAB, 0x7F, 0x36, 0x1E, 0x93, 0x0F, 0x2D, 0xEB, 0x0C, 0x56, 0x11, 0xDA, 624 | 0x0A, 0x96, 0x13, 0xD1, 0xC5, 0xE6, 0x61, 0x6F, 0xE7, 0x69, 0xD1, 0x4F, 0x09, 0x70, 0xEE, 0x3D, 625 | 0xF0, 0x89, 0xF9, 0xE5, 0x93, 0x6F, 0x58, 0xA4, 0x9A, 0x1D, 0x22, 0x94, 0x75, 0x94, 0x44, 0x0C, 626 | 0xF3, 0x2D, 0x1F, 0xDF, 0xF1, 0x7C, 0xFD, 0x51, 0x05, 0xF9, 0xE3, 0x2C, 0xA6, 0xE7, 0x47, 0x08, 627 | 0x36, 0xF3, 0xAD, 0xBC, 0x38, 0x43, 0x67, 0x30, 0xC1, 0x94, 0x5F, 0x6C, 0xB6, 0x94, 0x3D, 0x52, 628 | 0x25, 0x42, 0xA9, 0x0C, 0x3C, 0x54, 0xF3, 0x78, 0xD3, 0x87, 0x5F, 0xB4, 0x1D, 0x17, 0xDD, 0x2D, 629 | 0xA3, 0xED, 0x6C, 0x23, 0x2E, 0x9D, 0xF9, 0xAC, 0xE1, 0x56, 0x4F, 0xC7, 0x4F, 0x22, 0xA4, 0xE2, 630 | 0xDA, 0x57, 0xD7, 0xA4, 0xFC, 0x03, 0x7C, 0x7A, 0xF2, 0x73, 0xA5, 0xB6, 0xB6, 0xF6, 0x49, 0x71, 631 | 0xD9, 0xD4, 0x2D, 0xF8, 0xB7, 0xD8, 0xB4, 0x80, 0xEF, 0xDD, 0x2D, 0xF8, 0xE6, 0x9C, 0x5B, 0xF4, 632 | 0x36, 0xCE, 0xA6, 0x05, 0x98, 0xCD, 0x66, 0xE4, 0xE6, 0x98, 0x45, 0x6F, 0xE3, 0x68, 0x0A, 0xE8, 633 | 0xE9, 0xEB, 0x47, 0x9F, 0xD7, 0xC7, 0xFD, 0xA9, 0x60, 0x88, 0xFC, 0x01, 0x2C, 0x2D, 0x2D, 0xF1, 634 | 0x7E, 0x57, 0x77, 0x2F, 0xC2, 0x91, 0x59, 0x94, 0xDA, 0x6D, 0x90, 0x76, 0x96, 0xF1, 0x58, 0x6F, 635 | 0xDF, 0x00, 0x37, 0x36, 0xF6, 0xC6, 0x4D, 0x0F, 0x46, 0x46, 0xC7, 0x78, 0x5C, 0x0B, 0xA3, 0x68, 636 | 0xFF, 0x02, 0x3D, 0x2F, 0xB8, 0x7E, 0xA3, 0x0B, 0xE1, 0xF0, 0x2C, 0xAA, 0x9D, 0xBB, 0xD0, 0xF9, 637 | 0x7B, 0x37, 0xFA, 0x07, 0x86, 0xD0, 0x50, 0x7F, 0x10, 0xDB, 0x2C, 0x16, 0xFC, 0xD8, 0xD6, 0x8E, 638 | 0xA3, 0x47, 0x0E, 0xE3, 0xE7, 0xF6, 0x6B, 0x58, 0x5C, 0xBC, 0x03, 0x67, 0xD5, 0x2E, 0xB4, 0x5F, 639 | 0xEB, 0xC0, 0xC2, 0x82, 0x2A, 0x30, 0xC9, 0xB1, 0xA3, 0x2F, 0xE2, 0x3E, 0x6B, 0x11, 0x74, 0xBA, 640 | 0x95, 0x82, 0x4B, 0x43, 0x33, 0x03, 0x95, 0x15, 0xE5, 0xBC, 0x0D, 0x4D, 0xCF, 0x60, 0x74, 0x2C, 641 | 0x80, 0x82, 0x82, 0x7C, 0x4C, 0x4E, 0x06, 0x11, 0x98, 0x9C, 0xE2, 0x71, 0x5B, 0xF1, 0xFD, 0xBC, 642 | 0x5D, 0xCD, 0xBB, 0x6F, 0x9F, 0x40, 0x7D, 0xDD, 0x63, 0xDC, 0x8F, 0x44, 0xE6, 0x78, 0xBB, 0x16, 643 | 0x9A, 0x02, 0x2A, 0x1C, 0x12, 0xFD, 0x2A, 0xF0, 0xDF, 0x1E, 0xA1, 0x99, 0x2D, 0xC0, 0x59, 0xE9, 644 | 0xC0, 0x04, 0x09, 0x98, 0x21, 0x41, 0x0E, 0xA9, 0x8C, 0x67, 0x89, 0xBE, 0x7C, 0x0C, 0xF3, 0xA9, 645 | 0x81, 0x25, 0x37, 0x07, 0x46, 0xA3, 0x11, 0x79, 0xF9, 0xDB, 0x79, 0x5C, 0x96, 0xA3, 0xEA, 0xB1, 646 | 0x35, 0x58, 0x53, 0x00, 0x3B, 0xC9, 0x5A, 0x54, 0x08, 0x93, 0xC9, 0x08, 0xDF, 0xD0, 0x30, 0xEC, 647 | 0xF6, 0x12, 0x3C, 0x50, 0x62, 0xC3, 0x4C, 0x38, 0x8C, 0x20, 0x09, 0x28, 0x2F, 0xDF, 0x29, 0x46, 648 | 0xA6, 0x23, 0xC7, 0x64, 0xE1, 0xA9, 0x24, 0x96, 0x97, 0x85, 0x77, 0x6F, 0x34, 0x33, 0xC0, 0x44, 649 | 0x38, 0xCA, 0x25, 0x4C, 0x4D, 0x4D, 0xA3, 0xAC, 0xD4, 0x4E, 0x02, 0x8A, 0xF9, 0x8C, 0xE7, 0xE6, 650 | 0xE6, 0xF9, 0x83, 0xA7, 0xCE, 0x5A, 0xCD, 0x02, 0xF3, 0xD9, 0x47, 0x96, 0xE3, 0xDC, 0x4F, 0xC4, 651 | 0x13, 0xA9, 0x38, 0x73, 0xD6, 0x63, 0xF5, 0x4A, 0x98, 0x48, 0x24, 0x94, 0x78, 0x3C, 0x9E, 0x35, 652 | 0x4B, 0x92, 0xF1, 0x4A, 0x48, 0x63, 0xB3, 0x66, 0x5A, 0xAC, 0x7B, 0x0B, 0x98, 0x45, 0xA8, 0xDE, 653 | 0x59, 0xDD, 0xCF, 0x84, 0x23, 0xF0, 0x0E, 0x0C, 0x52, 0x9A, 0x65, 0x1E, 0x1F, 0xBA, 0xE5, 0xE7, 654 | 0xF5, 0x3E, 0x1E, 0x98, 0x58, 0x19, 0x7B, 0xFB, 0x8F, 0x51, 0x2A, 0xD9, 0x2E, 0x78, 0x7A, 0xBD, 655 | 0x2B, 0x31, 0x66, 0x6B, 0xA1, 0x99, 0x81, 0x24, 0x13, 0x54, 0x76, 0x97, 0xAF, 0xFC, 0x8A, 0xE6, 656 | 0x8B, 0xAD, 0x68, 0xB9, 0xD4, 0xC6, 0x85, 0x9C, 0xBB, 0xF0, 0x03, 0xDC, 0xCD, 0xAD, 0xE8, 0xF7, 657 | 0x0D, 0xE1, 0xEC, 0x77, 0x6E, 0x5A, 0x74, 0xC6, 0xF1, 0x5B, 0xE7, 0x4D, 0x9C, 0xBF, 0x70, 0x11, 658 | 0x81, 0x89, 0x20, 0xAE, 0xFE, 0xD2, 0x81, 0x79, 0xAA, 0x9C, 0xF5, 0xC8, 0x28, 0x03, 0xAA, 0x18, 659 | 0x85, 0xD7, 0xFD, 0x3B, 0x6F, 0x1D, 0xE7, 0x19, 0x18, 0x19, 0x19, 0xC3, 0x1E, 0x57, 0x35, 0xEA, 660 | 0x0E, 0xEC, 0xE7, 0xC7, 0xFA, 0x7D, 0x83, 0x98, 0xA6, 0xEA, 0x60, 0xBE, 0xF4, 0x60, 0x29, 0xDE, 661 | 0x3C, 0xF1, 0x2A, 0x95, 0x64, 0xEE, 0x5D, 0xE7, 0xDF, 0x1B, 0x4D, 0x01, 0xAB, 0x31, 0x52, 0x49, 662 | 0x9A, 0xA8, 0xC6, 0xD9, 0x12, 0xCC, 0xE8, 0xF6, 0xF4, 0xE1, 0xDB, 0xF3, 0x6E, 0x18, 0x0C, 0x06, 663 | 0x04, 0x43, 0xD3, 0xA8, 0x79, 0x74, 0x0F, 0x2D, 0xCD, 0x25, 0x68, 0xBD, 0x7C, 0x05, 0xA7, 0x9A, 664 | 0xBE, 0xA2, 0x55, 0x34, 0xC2, 0xC7, 0x69, 0xB1, 0x21, 0x01, 0x45, 0x3B, 0x0A, 0xD4, 0xB6, 0xB0, 665 | 0x90, 0xB7, 0xAE, 0xDD, 0xD5, 0x78, 0xFD, 0xD8, 0x2B, 0x68, 0x78, 0xE2, 0x20, 0x5E, 0x78, 0xEE, 666 | 0x69, 0x7E, 0x1B, 0x9E, 0x7F, 0xE6, 0x29, 0xEC, 0x75, 0x3D, 0x8C, 0x68, 0x54, 0xC6, 0xE8, 0x78, 667 | 0x80, 0x8F, 0xD3, 0x62, 0x43, 0x02, 0x92, 0xB0, 0xF5, 0x80, 0x5D, 0xC4, 0xD3, 0xE3, 0x45, 0xD3, 668 | 0xE9, 0x33, 0x34, 0xE3, 0xAB, 0xF4, 0x3E, 0x58, 0xC2, 0xE0, 0xB0, 0x1F, 0x8D, 0xA7, 0xBE, 0x44, 669 | 0x97, 0xA7, 0x97, 0xDF, 0xAE, 0xCA, 0x0A, 0x87, 0x38, 0x23, 0x03, 0x56, 0xAF, 0x03, 0xB1, 0x58, 670 | 0x4C, 0x89, 0x46, 0xA3, 0x9A, 0x46, 0x6F, 0x46, 0x25, 0x18, 0x0A, 0xA5, 0xC5, 0x28, 0xED, 0x4A, 671 | 0x64, 0x76, 0x36, 0x2D, 0x46, 0xCF, 0x8C, 0xF8, 0xD7, 0x2C, 0xEF, 0x88, 0xF4, 0x7A, 0x3D, 0xF2, 672 | 0xB6, 0xB3, 0x35, 0x3F, 0x45, 0x2E, 0xBD, 0x0B, 0x72, 0x68, 0x8F, 0x90, 0x29, 0x9B, 0x12, 0x90, 673 | 0x0D, 0xD2, 0x04, 0x50, 0xDA, 0x85, 0xA7, 0xCE, 0x8E, 0x3D, 0xDD, 0x49, 0x53, 0x68, 0x03, 0x1D, 674 | 0xD7, 0x1B, 0xD7, 0x35, 0x7A, 0xF1, 0xA7, 0x9D, 0x97, 0x34, 0xC6, 0xDD, 0xFF, 0x9F, 0x64, 0x65, 675 | 0x97, 0x50, 0xE5, 0xDA, 0xFF, 0xDA, 0x91, 0x97, 0x0E, 0x37, 0xDA, 0x6C, 0xB6, 0xBF, 0xBF, 0xBF, 676 | 0xCA, 0x80, 0x82, 0xBC, 0x6D, 0x0B, 0x1F, 0xBC, 0xFF, 0x9E, 0x33, 0x14, 0x0A, 0xF1, 0xED, 0x52, 677 | 0xDA, 0x36, 0xC5, 0x6A, 0xB5, 0xDA, 0x25, 0x49, 0xAA, 0x14, 0xDD, 0x2D, 0xC1, 0xEF, 0xF7, 0xFB, 678 | 0x92, 0x17, 0xFF, 0x1F, 0x00, 0xF8, 0x13, 0x90, 0x56, 0x15, 0xED, 0x2E, 0x93, 0x40, 0x49, 0x00, 679 | 0x00, 0x00, 0x00, 0x49, 0x45, 0x4E, 0x44, 0xAE, 0x42, 0x60, 0x82, 680 | } 681 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/tc-hib/go-winres 2 | 3 | go 1.19 4 | 5 | require ( 6 | github.com/tc-hib/winres v0.3.1 7 | github.com/urfave/cli/v2 v2.27.1 8 | ) 9 | 10 | require ( 11 | github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect 12 | github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect 13 | github.com/russross/blackfriday/v2 v2.1.0 // indirect 14 | github.com/xrash/smetrics v0.0.0-20240312152122-5f08fbb34913 // indirect 15 | golang.org/x/image v0.15.0 // indirect 16 | ) 17 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/cpuguy83/go-md2man/v2 v2.0.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lVfRxZq4= 2 | github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= 3 | github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ= 4 | github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8= 5 | github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= 6 | github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= 7 | github.com/tc-hib/winres v0.3.1 h1:CwRjEGrKdbi5CvZ4ID+iyVhgyfatxFoizjPhzez9Io4= 8 | github.com/tc-hib/winres v0.3.1/go.mod h1:C/JaNhH3KBvhNKVbvdlDWkbMDO9H4fKKDaN7/07SSuk= 9 | github.com/urfave/cli/v2 v2.27.1 h1:8xSQ6szndafKVRmfyeUMxkNUJQMjL1F2zmsZ+qHpfho= 10 | github.com/urfave/cli/v2 v2.27.1/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ= 11 | github.com/xrash/smetrics v0.0.0-20240312152122-5f08fbb34913 h1:+qGGcbkzsfDQNPPe9UDgpxAWQrhbbBXOYJFQDq/dtJw= 12 | github.com/xrash/smetrics v0.0.0-20240312152122-5f08fbb34913/go.mod h1:4aEEwZQutDLsQv2Deui4iYQ6DWTxR14g6m8Wv88+Xqk= 13 | golang.org/x/image v0.15.0 h1:kOELfmgrmJlw4Cdb7g/QGuB3CvDrXbqEIww/pNtNBm8= 14 | golang.org/x/image v0.15.0/go.mod h1:HUYqC05R2ZcZ3ejNQsIHQDQiwWM4JBqmm6MKANTp4LE= 15 | -------------------------------------------------------------------------------- /icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tc-hib/go-winres/c4d55a3dfc2e22a4a9fb95ae0280ce106daadce9/icon.png -------------------------------------------------------------------------------- /icon16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tc-hib/go-winres/c4d55a3dfc2e22a4a9fb95ae0280ce106daadce9/icon16.png -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "image" 7 | "io/ioutil" 8 | "log" 9 | "os" 10 | "os/exec" 11 | "path/filepath" 12 | "strings" 13 | 14 | "github.com/tc-hib/winres" 15 | "github.com/tc-hib/winres/version" 16 | "github.com/urfave/cli/v2" 17 | ) 18 | 19 | const ( 20 | defaultJSONFile = "winres/winres.json" 21 | defaultIconFile = "winres/icon.png" 22 | defaultIcon16File = "winres/icon16.png" 23 | defaultOutDir = "winres" 24 | defaultArch = "amd64,386" 25 | 26 | flagArch = "arch" 27 | flagOutput = "out" 28 | flagOutputDir = "dir" 29 | flagInput = "in" 30 | flagNoSuffix = "no-suffix" 31 | flagNoBackup = "no-backup" 32 | flagDelete = "delete" 33 | flagXMLManifest = "xml-manifest" 34 | 35 | flagProductVersion = "product-version" 36 | flagFileVersion = "file-version" 37 | 38 | flagInfoDescription = "file-description" 39 | flagInfoProductName = "product-name" 40 | flagInfoCopyright = "copyright" 41 | flagInfoFilename = "original-filename" 42 | 43 | flagIconFile = "icon" 44 | flagRequireAdmin = "admin" 45 | flagManifest = "manifest" 46 | 47 | manifestNone = "none" 48 | manifestCLI = "cli" 49 | manifestGUI = "gui" 50 | 51 | flagAuthenticode = "authenticode" 52 | 53 | authenticodeIgnore = "ignore" 54 | authenticodeRemove = "remove" 55 | 56 | gitTag = "git-tag" 57 | ) 58 | 59 | //go:generate go-winres make --product-version=git-tag --file-version=git-tag 60 | 61 | func main() { 62 | versionFlags := []cli.Flag{ 63 | &cli.StringFlag{ 64 | Name: flagProductVersion, 65 | Usage: `set product version (special value: "` + gitTag + `")`, 66 | }, 67 | &cli.StringFlag{ 68 | Name: flagFileVersion, 69 | Usage: `set file version (special value: "` + gitTag + `")`, 70 | }, 71 | } 72 | 73 | commonMakeFlags := append([]cli.Flag{ 74 | &cli.StringFlag{ 75 | Name: flagArch, 76 | Usage: "comma separated list of target architectures", 77 | Value: defaultArch, 78 | EnvVars: []string{"GOARCH"}, 79 | }, 80 | &cli.StringFlag{ 81 | Name: flagOutput, 82 | Usage: "name or prefix of the object file (syso)", 83 | Value: "rsrc", 84 | }, 85 | &cli.BoolFlag{ 86 | Name: flagNoSuffix, 87 | Usage: "don't add target suffixes such as \"_windows_386\"", 88 | Value: false, 89 | }, 90 | }, versionFlags...) 91 | 92 | app := cli.App{ 93 | Name: "go-winres", 94 | Usage: "A tool for embedding resources in Windows executables", 95 | Commands: []*cli.Command{ 96 | { 97 | Name: "init", 98 | Usage: "Create an initial ./winres/winres.json", 99 | Action: cmdInit, 100 | ArgsUsage: " ", 101 | }, 102 | { 103 | Name: "make", 104 | Usage: "Make syso files for the \"go build\" command", 105 | Action: cmdMake, 106 | ArgsUsage: " ", 107 | Flags: append([]cli.Flag{ 108 | &cli.StringFlag{ 109 | Name: flagInput, 110 | Usage: "name of the input json file", 111 | Value: defaultJSONFile, 112 | TakesFile: true, 113 | }, 114 | }, 115 | commonMakeFlags...), 116 | }, 117 | { 118 | Name: "simply", 119 | Usage: "Make syso files for the \"go build\" command (simplified)", 120 | Action: cmdSimply, 121 | ArgsUsage: " ", 122 | Flags: append(commonMakeFlags, []cli.Flag{ 123 | &cli.StringFlag{ 124 | Name: flagManifest, 125 | Value: manifestCLI, 126 | Usage: "type of manifest: \"cli\", \"gui\" or \"none\"", 127 | }, 128 | &cli.BoolFlag{ 129 | Name: flagRequireAdmin, 130 | Value: false, 131 | Usage: "set execution level to \"Require Administrator\"", 132 | }, 133 | &cli.StringFlag{ 134 | Name: flagInfoDescription, 135 | Usage: "set file description", 136 | }, 137 | &cli.StringFlag{ 138 | Name: flagInfoProductName, 139 | Usage: "set product name", 140 | }, 141 | &cli.StringFlag{ 142 | Name: flagInfoCopyright, 143 | Usage: "set copyright notice", 144 | }, 145 | &cli.StringFlag{ 146 | Name: flagInfoFilename, 147 | Usage: "original filename", 148 | }, 149 | &cli.StringFlag{ 150 | Name: flagIconFile, 151 | Usage: "icon file (ico, png, ...)", 152 | Value: defaultIconFile, 153 | TakesFile: true, 154 | }, 155 | }...), 156 | }, 157 | { 158 | Name: "extract", 159 | Usage: "Extract all resources from an executable", 160 | Action: cmdExtract, 161 | ArgsUsage: "source_file.exe", 162 | Flags: []cli.Flag{ 163 | &cli.StringFlag{ 164 | Name: flagOutputDir, 165 | Usage: "name of the output directory", 166 | Value: defaultOutDir, 167 | }, 168 | &cli.BoolFlag{ 169 | Name: flagXMLManifest, 170 | Usage: "extract the manifest as an xml file (not a json object)", 171 | Value: false, 172 | }, 173 | }, 174 | }, 175 | { 176 | Name: "patch", 177 | Usage: "Replace resources in an executable file (exe, dll)", 178 | Action: cmdPatch, 179 | ArgsUsage: "target_file.exe", 180 | Flags: append([]cli.Flag{ 181 | &cli.StringFlag{ 182 | Name: flagInput, 183 | Usage: "name of the input json file", 184 | Value: defaultJSONFile, 185 | }, 186 | &cli.BoolFlag{ 187 | Name: flagDelete, 188 | Usage: "delete all resources before adding the new ones", 189 | Value: false, 190 | }, 191 | &cli.BoolFlag{ 192 | Name: flagNoBackup, 193 | Usage: "don't leave a copy of the original executable", 194 | Value: false, 195 | }, 196 | &cli.StringFlag{ 197 | Name: flagAuthenticode, 198 | Usage: `specify what to do with signed executables: "ignore" or "remove" signature`, 199 | Value: "", 200 | }, 201 | }, versionFlags...), 202 | }, 203 | }, 204 | } 205 | err := app.Run(os.Args) 206 | if err != nil { 207 | log.Fatal(err) 208 | } 209 | } 210 | 211 | func cmdInit(_ *cli.Context) error { 212 | err := os.MkdirAll(filepath.Dir(defaultJSONFile), 0755) 213 | if err != nil { 214 | return err 215 | } 216 | err = ioutil.WriteFile(defaultJSONFile, []byte(initJSON), 0644) 217 | if err != nil { 218 | return err 219 | } 220 | err = ioutil.WriteFile(defaultIconFile, initIcon, 0644) 221 | if err != nil { 222 | return err 223 | } 224 | err = ioutil.WriteFile(defaultIcon16File, initIcon16, 0644) 225 | if err != nil { 226 | return err 227 | } 228 | 229 | fmt.Println("Created", defaultJSONFile) 230 | 231 | return nil 232 | } 233 | 234 | func cmdMake(ctx *cli.Context) error { 235 | targets, err := getTargets(ctx) 236 | if err != nil { 237 | return err 238 | } 239 | 240 | rs := &winres.ResourceSet{} 241 | err = importResources(rs, ctx.String(flagInput)) 242 | if err != nil { 243 | return err 244 | } 245 | 246 | err = setVersions(rs, ctx) 247 | if err != nil { 248 | return err 249 | } 250 | 251 | for _, t := range targets { 252 | err = writeObjectFile(rs, t.name, t.arch) 253 | if err != nil { 254 | return err 255 | } 256 | } 257 | 258 | return nil 259 | } 260 | 261 | func cmdSimply(ctx *cli.Context) error { 262 | targets, err := getTargets(ctx) 263 | if err != nil { 264 | return err 265 | } 266 | 267 | rs := &winres.ResourceSet{} 268 | 269 | err = simplySetIcon(rs, ctx) 270 | if err != nil { 271 | return err 272 | } 273 | 274 | err = simplySetManifest(rs, ctx) 275 | if err != nil { 276 | return err 277 | } 278 | 279 | err = simplySetVersionInfo(rs, ctx) 280 | if err != nil { 281 | return err 282 | } 283 | 284 | for _, t := range targets { 285 | err = writeObjectFile(rs, t.name, t.arch) 286 | if err != nil { 287 | return err 288 | } 289 | } 290 | 291 | return nil 292 | } 293 | 294 | func cmdExtract(ctx *cli.Context) error { 295 | if ctx.NArg() != 1 { 296 | cli.ShowSubcommandHelpAndExit(ctx, 1) 297 | } 298 | 299 | f, err := os.Open(ctx.Args().Get(0)) 300 | if err != nil { 301 | return err 302 | } 303 | defer f.Close() 304 | 305 | rs, err := winres.LoadFromEXE(f) 306 | if err != nil { 307 | return err 308 | } 309 | 310 | f.Close() 311 | 312 | out := ctx.String(flagOutputDir) 313 | err = os.MkdirAll(out, 0755) 314 | if err != nil { 315 | return err 316 | } 317 | 318 | exportResources(out, rs, !ctx.Bool(flagXMLManifest)) 319 | 320 | return nil 321 | } 322 | 323 | func cmdPatch(ctx *cli.Context) error { 324 | if ctx.NArg() != 1 { 325 | cli.ShowSubcommandHelpAndExit(ctx, 1) 326 | } 327 | 328 | exe := ctx.Args().Get(0) 329 | 330 | in, err := os.Open(exe) 331 | if err != nil { 332 | return err 333 | } 334 | defer in.Close() 335 | 336 | signed, err := winres.IsSignedEXE(in) 337 | if err != nil { 338 | return err 339 | } 340 | if signed { 341 | switch ctx.String(flagAuthenticode) { 342 | case authenticodeRemove, authenticodeIgnore: 343 | default: 344 | return fmt.Errorf(`Cannot patch a signed file. 345 | 346 | You might want to use --%[1]s=%[2]s or --%[1]s=%[3]s to either remove or ignore the code signature.`, flagAuthenticode, authenticodeRemove, authenticodeIgnore) 347 | } 348 | } 349 | 350 | var rs *winres.ResourceSet 351 | 352 | if ctx.Bool(flagDelete) { 353 | rs = &winres.ResourceSet{} 354 | } else { 355 | rs, err = winres.LoadFromEXE(in) 356 | if err != nil && err != winres.ErrNoResources { 357 | return err 358 | } 359 | } 360 | 361 | err = importResources(rs, ctx.String(flagInput)) 362 | if err != nil { 363 | return err 364 | } 365 | 366 | err = setVersions(rs, ctx) 367 | if err != nil { 368 | return err 369 | } 370 | 371 | out, err := os.Create(exe + ".tmp") 372 | if err != nil { 373 | return err 374 | } 375 | defer out.Close() 376 | 377 | switch ctx.String(flagAuthenticode) { 378 | case authenticodeRemove: 379 | err = rs.WriteToEXE(out, in, winres.WithAuthenticode(winres.RemoveSignature)) 380 | case authenticodeIgnore: 381 | err = rs.WriteToEXE(out, in, winres.WithAuthenticode(winres.IgnoreSignature)) 382 | default: 383 | err = rs.WriteToEXE(out, in) 384 | } 385 | if err != nil { 386 | return err 387 | } 388 | 389 | in.Close() 390 | err = out.Close() 391 | if err != nil { 392 | return err 393 | } 394 | 395 | if ctx.Bool(flagNoBackup) { 396 | err = os.Remove(exe) 397 | if err != nil { 398 | return err 399 | } 400 | } else { 401 | err = os.Rename(exe, exe+".bak") 402 | if err != nil { 403 | return err 404 | } 405 | } 406 | 407 | return os.Rename(exe+".tmp", exe) 408 | } 409 | 410 | func getTargets(ctx *cli.Context) ([]target, error) { 411 | var ( 412 | ns = ctx.Bool(flagNoSuffix) 413 | arch = strings.Split(ctx.String(flagArch), ",") 414 | name = ctx.String(flagOutput) 415 | ) 416 | 417 | if ns && len(arch) > 1 { 418 | return nil, errors.New("cannot use --no-suffix with several targets") 419 | } 420 | 421 | t := make([]target, len(arch)) 422 | for i := range arch { 423 | t[i].arch = winres.Arch(strings.TrimSpace(arch[i])) 424 | switch t[i].arch { 425 | case winres.ArchAMD64, winres.ArchI386, winres.ArchARM, winres.ArchARM64: 426 | default: 427 | return nil, errors.New("unknown architecture: " + arch[i]) 428 | } 429 | t[i].name = name 430 | if !ns { 431 | t[i].name += "_windows_" + string(t[i].arch) + ".syso" 432 | } 433 | } 434 | 435 | return t, nil 436 | } 437 | 438 | func simplySetManifest(rs *winres.ResourceSet, ctx *cli.Context) error { 439 | var m *winres.AppManifest 440 | 441 | switch ctx.String(flagManifest) { 442 | case manifestCLI: 443 | m = &winres.AppManifest{} 444 | 445 | case manifestGUI: 446 | m = &winres.AppManifest{DPIAwareness: winres.DPIPerMonitorV2, UseCommonControlsV6: true} 447 | 448 | case manifestNone: 449 | 450 | default: 451 | return errors.New("invalid manifest type: " + ctx.String(flagManifest)) 452 | } 453 | if ctx.Bool(flagRequireAdmin) { 454 | if m == nil { 455 | m = &winres.AppManifest{} 456 | } 457 | m.ExecutionLevel = winres.RequireAdministrator 458 | } 459 | 460 | if m != nil { 461 | rs.SetManifest(*m) 462 | } 463 | 464 | return nil 465 | } 466 | 467 | func simplySetVersionInfo(rs *winres.ResourceSet, ctx *cli.Context) error { 468 | var ( 469 | vi version.Info 470 | b bool 471 | ) 472 | 473 | if s := ctx.String(flagInfoDescription); s != "" { 474 | vi.Set(version.LangDefault, version.FileDescription, s) 475 | b = true 476 | } 477 | if s := ctx.String(flagInfoProductName); s != "" { 478 | vi.Set(version.LangDefault, version.ProductName, s) 479 | b = true 480 | } 481 | if s := ctx.String(flagInfoFilename); s != "" { 482 | vi.Set(version.LangDefault, version.OriginalFilename, s) 483 | b = true 484 | } 485 | if s := ctx.String(flagInfoCopyright); s != "" { 486 | vi.Set(version.LangDefault, version.LegalCopyright, s) 487 | b = true 488 | } 489 | 490 | fileVersion, prodVersion, err := getInputVersions(ctx) 491 | if err != nil { 492 | return err 493 | } 494 | if fileVersion != "" { 495 | vi.SetFileVersion(fileVersion) 496 | b = true 497 | } 498 | if prodVersion != "" { 499 | vi.SetProductVersion(prodVersion) 500 | b = true 501 | } 502 | 503 | if b { 504 | rs.SetVersionInfo(vi) 505 | } 506 | 507 | return nil 508 | } 509 | 510 | type target struct { 511 | arch winres.Arch 512 | name string 513 | } 514 | 515 | func getInputVersions(ctx *cli.Context) (fileVersion string, prodVersion string, err error) { 516 | fileVersion = ctx.String(flagFileVersion) 517 | prodVersion = ctx.String(flagProductVersion) 518 | if fileVersion != gitTag && prodVersion != gitTag { 519 | return 520 | } 521 | tag, err := getGitTag() 522 | if err != nil { 523 | fileVersion = "" 524 | prodVersion = "" 525 | return 526 | } 527 | if fileVersion == gitTag { 528 | fileVersion = tag 529 | } 530 | if prodVersion == gitTag { 531 | prodVersion = tag 532 | } 533 | return 534 | } 535 | 536 | func setVersions(rs *winres.ResourceSet, ctx *cli.Context) error { 537 | fileVersion, prodVersion, err := getInputVersions(ctx) 538 | if err != nil { 539 | return err 540 | } 541 | 542 | done := false 543 | rs.WalkType(winres.RT_VERSION, func(resID winres.Identifier, langID uint16, data []byte) bool { 544 | var vi *version.Info 545 | vi, err = version.FromBytes(data) 546 | if err != nil { 547 | return false 548 | } 549 | 550 | if fileVersion != "" { 551 | vi.SetFileVersion(fileVersion) 552 | } 553 | 554 | if prodVersion != "" { 555 | vi.SetProductVersion(prodVersion) 556 | } 557 | 558 | rs.SetVersionInfo(*vi) 559 | 560 | done = true 561 | 562 | return true 563 | }) 564 | 565 | if err != nil { 566 | return err 567 | } 568 | 569 | if !done { 570 | vi := version.Info{} 571 | if fileVersion != "" { 572 | vi.SetFileVersion(fileVersion) 573 | } 574 | if prodVersion != "" { 575 | vi.SetProductVersion(prodVersion) 576 | } 577 | rs.SetVersionInfo(vi) 578 | } 579 | 580 | return nil 581 | } 582 | 583 | func getGitTag() (string, error) { 584 | w := strings.Builder{} 585 | cmd := exec.Command("git", "describe", "--tags") 586 | cmd.Stdout = &w 587 | err := cmd.Run() 588 | if err != nil { 589 | // git describe --tags returns exit code 128 if none found. 590 | if cmd.ProcessState.ExitCode() == 128 { 591 | return "0.0.0.0", nil 592 | } 593 | return "", fmt.Errorf("failed resolving git tag: %w", err) 594 | } 595 | return strings.TrimSpace(w.String()), nil 596 | } 597 | 598 | func simplySetIcon(rs *winres.ResourceSet, ctx *cli.Context) error { 599 | name := ctx.String(flagIconFile) 600 | f, err := os.Open(name) 601 | if err != nil { 602 | if !os.IsNotExist(err) { 603 | return err 604 | } 605 | log.Println("did not find icon ", name) 606 | return nil 607 | } 608 | defer f.Close() 609 | 610 | var icon *winres.Icon 611 | if strings.ToLower(filepath.Ext(name)) == ".ico" { 612 | icon, err = winres.LoadICO(f) 613 | if err != nil { 614 | return err 615 | } 616 | } else { 617 | img, _, err := image.Decode(f) 618 | if err != nil { 619 | return err 620 | } 621 | icon, err = winres.NewIconFromResizedImage(img, nil) 622 | if err != nil { 623 | return err 624 | } 625 | } 626 | 627 | return rs.SetIcon(winres.ID(1), icon) 628 | } 629 | 630 | func writeObjectFile(rs *winres.ResourceSet, name string, arch winres.Arch) error { 631 | f, err := os.Create(name) 632 | if err != nil { 633 | return err 634 | } 635 | defer f.Close() 636 | 637 | err = rs.WriteObject(f, arch) 638 | if err != nil { 639 | return err 640 | } 641 | 642 | return f.Close() 643 | } 644 | 645 | // language=json 646 | const initJSON = `{ 647 | "RT_GROUP_ICON": { 648 | "APP": { 649 | "0000": [ 650 | "icon.png", 651 | "icon16.png" 652 | ] 653 | } 654 | }, 655 | "RT_MANIFEST": { 656 | "#1": { 657 | "0409": { 658 | "identity": { 659 | "name": "", 660 | "version": "" 661 | }, 662 | "description": "", 663 | "minimum-os": "win7", 664 | "execution-level": "as invoker", 665 | "ui-access": false, 666 | "auto-elevate": false, 667 | "dpi-awareness": "system", 668 | "disable-theming": false, 669 | "disable-window-filtering": false, 670 | "high-resolution-scrolling-aware": false, 671 | "ultra-high-resolution-scrolling-aware": false, 672 | "long-path-aware": false, 673 | "printer-driver-isolation": false, 674 | "gdi-scaling": false, 675 | "segment-heap": false, 676 | "use-common-controls-v6": false 677 | } 678 | } 679 | }, 680 | "RT_VERSION": { 681 | "#1": { 682 | "0000": { 683 | "fixed": { 684 | "file_version": "0.0.0.0", 685 | "product_version": "0.0.0.0" 686 | }, 687 | "info": { 688 | "0409": { 689 | "Comments": "", 690 | "CompanyName": "", 691 | "FileDescription": "", 692 | "FileVersion": "", 693 | "InternalName": "", 694 | "LegalCopyright": "", 695 | "LegalTrademarks": "", 696 | "OriginalFilename": "", 697 | "PrivateBuild": "", 698 | "ProductName": "", 699 | "ProductVersion": "", 700 | "SpecialBuild": "" 701 | } 702 | } 703 | } 704 | } 705 | } 706 | }` 707 | -------------------------------------------------------------------------------- /main_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bytes" 5 | "crypto/md5" 6 | "io" 7 | "io/ioutil" 8 | "os" 9 | "os/exec" 10 | "path/filepath" 11 | "testing" 12 | ) 13 | 14 | const tmpDir = "_testdata/tmp" 15 | 16 | func Test_Extract(t *testing.T) { 17 | a := os.Args 18 | defer func() { os.Args = a }() 19 | 20 | f := makeTmpDir(t) 21 | defer f() 22 | 23 | os.Args = []string{"./go-winres.exe", "extract", "--dir", "_testdata/tmp", "_testdata/rh.exe"} 24 | main() 25 | if loadJSON(t, "winres.json") != jsonRHM { 26 | t.Error("json is different (json manifest)") 27 | } 28 | checkFile(t, "#1_0000.ico", []byte{0x00, 0x24, 0x99, 0x66, 0x72, 0xaf, 0x62, 0x12, 0x35, 0x22, 0x9b, 0x7b, 0x2, 0x2f, 0xe5, 0x94}) 29 | checkFile(t, "APP_040C.ico", []byte{0xdd, 0xaf, 0x55, 0xb5, 0xd7, 0x3c, 0x65, 0xc3, 0x59, 0xb7, 0x3a, 0x39, 0x48, 0x62, 0xb3, 0x10}) 30 | checkFile(t, "APP_0409.ico", []byte{0xee, 0x29, 0x1d, 0xaa, 0xc1, 0x3d, 0x24, 0xfc, 0xc5, 0xe, 0x64, 0x71, 0x44, 0xf0, 0x1e, 0x46}) 31 | checkFile(t, "CURSOR_0000.cur", []byte{0x9f, 0x41, 0xe3, 0x26, 0xcc, 0x10, 0xb1, 0xed, 0xd9, 0x96, 0x38, 0x59, 0xc6, 0x93, 0x37, 0x9e}) 32 | checkFile(t, "PNG_CUR-64X128_0000.png", []byte{0x40, 0x83, 0x52, 0xdb, 0x5, 0xe7, 0xc2, 0x32, 0x5b, 0xc1, 0x40, 0x15, 0x5b, 0x16, 0x9f, 0x4d}) 33 | checkFile(t, "ICON16_0000.bmp", []byte{0xd7, 0x0c, 0xa6, 0x11, 0x23, 0xf6, 0x81, 0xef, 0xaa, 0xd3, 0x01, 0x61, 0x5f, 0x3e, 0x68, 0x1a}) 34 | } 35 | 36 | func Test_Init(t *testing.T) { 37 | a := os.Args 38 | defer func() { os.Args = a }() 39 | 40 | f := makeTmpDir(t) 41 | defer f() 42 | 43 | func() { 44 | f := moveToTmpDir(t) 45 | defer f() 46 | 47 | os.Args = []string{"./go-winres.exe", "init"} 48 | main() 49 | 50 | s, err := os.Stat("winres/winres.json") 51 | if err != nil || s.Size() == 0 { 52 | t.Fatal(err) 53 | } 54 | s, err = os.Stat("winres/icon.png") 55 | if err != nil || s.Size() == 0 { 56 | t.Fatal(err) 57 | } 58 | s, err = os.Stat("winres/icon16.png") 59 | if err != nil || s.Size() == 0 { 60 | t.Fatal(err) 61 | } 62 | }() 63 | } 64 | 65 | func Test_Extract_XMLManifest(t *testing.T) { 66 | a := os.Args 67 | defer func() { os.Args = a }() 68 | 69 | f := makeTmpDir(t) 70 | defer f() 71 | 72 | os.Args = []string{"./go-winres.exe", "extract", "--dir", "_testdata/tmp", "--xml-manifest", "_testdata/rh.exe"} 73 | main() 74 | if loadJSON(t, "winres.json") != jsonRH { 75 | t.Error("json is different (xml manifest)") 76 | } 77 | checkFile(t, "#1_0000.manifest", []byte{0x21, 0x19, 0x26, 0x2f, 0x8a, 0x5b, 0x5f, 0x64, 0x0e, 0x6e, 0xe7, 0x01, 0x20, 0xdb, 0xd2, 0x05}) 78 | checkFile(t, "#1_0000.ico", []byte{0x00, 0x24, 0x99, 0x66, 0x72, 0xaf, 0x62, 0x12, 0x35, 0x22, 0x9b, 0x7b, 0x2, 0x2f, 0xe5, 0x94}) 79 | checkFile(t, "APP_040C.ico", []byte{0xdd, 0xaf, 0x55, 0xb5, 0xd7, 0x3c, 0x65, 0xc3, 0x59, 0xb7, 0x3a, 0x39, 0x48, 0x62, 0xb3, 0x10}) 80 | checkFile(t, "APP_0409.ico", []byte{0xee, 0x29, 0x1d, 0xaa, 0xc1, 0x3d, 0x24, 0xfc, 0xc5, 0xe, 0x64, 0x71, 0x44, 0xf0, 0x1e, 0x46}) 81 | checkFile(t, "CURSOR_0000.cur", []byte{0x9f, 0x41, 0xe3, 0x26, 0xcc, 0x10, 0xb1, 0xed, 0xd9, 0x96, 0x38, 0x59, 0xc6, 0x93, 0x37, 0x9e}) 82 | checkFile(t, "PNG_CUR-64X128_0000.png", []byte{0x40, 0x83, 0x52, 0xdb, 0x5, 0xe7, 0xc2, 0x32, 0x5b, 0xc1, 0x40, 0x15, 0x5b, 0x16, 0x9f, 0x4d}) 83 | checkFile(t, "ICON16_0000.bmp", []byte{0xd7, 0x0c, 0xa6, 0x11, 0x23, 0xf6, 0x81, 0xef, 0xaa, 0xd3, 0x01, 0x61, 0x5f, 0x3e, 0x68, 0x1a}) 84 | } 85 | 86 | func Test_Patch(t *testing.T) { 87 | a := os.Args 88 | defer func() { os.Args = a }() 89 | 90 | f := makeTmpDir(t) 91 | defer f() 92 | 93 | copyFile(t, "_testdata/vs0.exe", "_testdata/tmp/temp.exe") 94 | os.Args = []string{"./go-winres.exe", "patch", "--in", "_testdata/icons.json", "--product-version", "1.2.3.4", "_testdata/tmp/temp.exe"} 95 | main() 96 | checkFile(t, "temp.exe", []byte{0xae, 0x96, 0xc0, 0xfd, 0x7a, 0x9c, 0x95, 0xab, 0xd8, 0xe1, 0x8e, 0x55, 0x91, 0xd2, 0xbc, 0xa0}) 97 | checkFile(t, "temp.exe.bak", []byte{0x29, 0x13, 0xa7, 0xc5, 0x4a, 0xf9, 0x47, 0xef, 0xd6, 0x4f, 0x37, 0xc5, 0x62, 0xba, 0xd4, 0x39}) 98 | } 99 | 100 | func Test_Patch_Add(t *testing.T) { 101 | a := os.Args 102 | defer func() { os.Args = a }() 103 | 104 | f := makeTmpDir(t) 105 | defer f() 106 | 107 | copyFile(t, "_testdata/rh.exe", "_testdata/tmp/temp.exe") 108 | os.Args = []string{"./go-winres.exe", "patch", "--in", "_testdata/icons.json", "--no-backup", "_testdata/tmp/temp.exe"} 109 | main() 110 | checkFile(t, "temp.exe", []byte{0xc4, 0x4a, 0x7f, 0x74, 0xe9, 0x0c, 0xfb, 0x37, 0x9a, 0x62, 0x82, 0x28, 0xbc, 0x68, 0x77, 0xc2}) 111 | if _, err := os.Stat("_testdata/tmp/temp.exe.bak"); err == nil { 112 | t.Error("temp.exe.bak should not exist") 113 | } 114 | } 115 | 116 | func Test_Patch_Replace(t *testing.T) { 117 | a := os.Args 118 | defer func() { os.Args = a }() 119 | 120 | f := makeTmpDir(t) 121 | defer f() 122 | 123 | copyFile(t, "_testdata/rh.exe", "_testdata/tmp/temp.exe") 124 | 125 | os.Args = []string{"./go-winres.exe", "patch", "--in", "_testdata/test.json", "--delete", "--file-version", "1.2", "_testdata/tmp/temp.exe"} 126 | main() 127 | checkFile(t, "temp.exe", []byte{0x67, 0x5b, 0xc5, 0x8a, 0xb3, 0x48, 0xfc, 0xf0, 0xaf, 0xea, 0xa5, 0xc0, 0x5f, 0xba, 0x8d, 0xc3}) 128 | checkFile(t, "temp.exe.bak", []byte{0x79, 0xbc, 0x0f, 0x27, 0x2b, 0x3f, 0x82, 0x69, 0xfa, 0xc1, 0x42, 0x1d, 0xc7, 0xdb, 0x68, 0x6c}) 129 | } 130 | 131 | func Test_GitTag(t *testing.T) { 132 | a := os.Args 133 | defer func() { os.Args = a }() 134 | 135 | f := makeTmpDir(t) 136 | defer f() 137 | 138 | copyFile(t, "_testdata/vs0.exe", "_testdata/tmp/temp1.exe") 139 | copyFile(t, "_testdata/rh.exe", "_testdata/tmp/temp2.exe") 140 | 141 | func() { 142 | f := moveToTmpDir(t) 143 | defer f() 144 | 145 | createTmpGitTag(t, "v1.42.3.24") 146 | 147 | os.Args = []string{"./go-winres.exe", "patch", "--in", "../icons.json", "--file-version", "git-tag", "temp1.exe"} 148 | main() 149 | os.Args = []string{"./go-winres.exe", "patch", "--in", "../test.json", "--product-version", "git-tag", "temp2.exe"} 150 | main() 151 | }() 152 | 153 | checkFile(t, "temp1.exe", []byte{0x70, 0xb9, 0x34, 0x4d, 0x62, 0xe3, 0xdb, 0x62, 0xe9, 0xb5, 0xc8, 0x85, 0x48, 0xaa, 0xe7, 0x65}) 154 | checkFile(t, "temp2.exe", []byte{0xd9, 0x19, 0x0c, 0xc2, 0x72, 0x3c, 0xc4, 0x6b, 0x9e, 0x6e, 0xbe, 0x58, 0xb1, 0x26, 0xa7, 0x4b}) 155 | } 156 | 157 | func Test_Simply(t *testing.T) { 158 | a := os.Args 159 | defer func() { os.Args = a }() 160 | 161 | f := makeTmpDir(t) 162 | defer f() 163 | 164 | os.Args = []string{ 165 | "./go-winres.exe", 166 | "simply", 167 | "--arch", 168 | " amd64, 386 , arm, arm64 ", 169 | "--out", 170 | "_testdata/tmp/simply", 171 | "--product-version", 172 | "v42.5.3.8 alpha", 173 | "--file-version", 174 | "1.2.3.4.5.6.7", 175 | "--manifest", 176 | "gui", 177 | "--admin", 178 | "--file-description", 179 | "description", 180 | "--product-name", 181 | "Product name", 182 | "--copyright", 183 | "©", 184 | "--original-filename", 185 | "xxx.exe", 186 | "--icon", 187 | "_testdata/fr.ico", 188 | } 189 | main() 190 | checkFile(t, "simply_windows_arm64.syso", []byte{0xb1, 0x1b, 0x8f, 0x79, 0xea, 0xac, 0x72, 0xae, 0x0e, 0x8a, 0xa6, 0xf2, 0x2c, 0x61, 0x10, 0x8d}) 191 | checkFile(t, "simply_windows_arm.syso", []byte{0x66, 0xe5, 0x83, 0xd1, 0x62, 0xe8, 0x51, 0x10, 0xb1, 0x2e, 0x5b, 0xdc, 0x57, 0x23, 0xd9, 0x8c}) 192 | checkFile(t, "simply_windows_amd64.syso", []byte{0xc4, 0xfe, 0x6e, 0x34, 0xb2, 0xe5, 0x9e, 0x93, 0x00, 0xf7, 0x1f, 0x5a, 0x62, 0x9b, 0xea, 0x37}) 193 | checkFile(t, "simply_windows_386.syso", []byte{0xa0, 0x02, 0x97, 0x0f, 0xc9, 0x0d, 0x2c, 0x28, 0xf1, 0x23, 0xd0, 0x31, 0x6b, 0x3f, 0x0d, 0x73}) 194 | } 195 | 196 | func Test_SimplyGitTag(t *testing.T) { 197 | a := os.Args 198 | defer func() { os.Args = a }() 199 | 200 | f := makeTmpDir(t) 201 | defer f() 202 | 203 | copyFile(t, "_testdata/cur-32x64.png", "_testdata/tmp/icon.png") 204 | 205 | func() { 206 | f := moveToTmpDir(t) 207 | defer f() 208 | 209 | createTmpGitTag(t, "v1.42.3.24") 210 | 211 | os.Args = []string{"./go-winres.exe", "simply", "--arch", "amd64", "--file-version", "git-tag", "--icon", "icon.png"} 212 | main() 213 | os.Args = []string{"./go-winres.exe", "simply", "--arch", "arm64", "--product-version", "git-tag", "--icon", "icon.png"} 214 | main() 215 | }() 216 | 217 | checkFile(t, "rsrc_windows_amd64.syso", []byte{0x66, 0x4b, 0xca, 0x71, 0xad, 0x35, 0x0f, 0x91, 0xca, 0xdf, 0xd1, 0x11, 0x9b, 0x5d, 0x42, 0xc7}) 218 | checkFile(t, "rsrc_windows_arm64.syso", []byte{0x29, 0xa1, 0xde, 0x27, 0xf2, 0x5a, 0x96, 0x4e, 0xc2, 0x59, 0xbf, 0xa3, 0x60, 0x11, 0xe0, 0xed}) 219 | } 220 | 221 | func Test_Simply_PNGIcon(t *testing.T) { 222 | a := os.Args 223 | defer func() { os.Args = a }() 224 | 225 | f := makeTmpDir(t) 226 | defer f() 227 | 228 | os.Args = []string{ 229 | "./go-winres.exe", 230 | "simply", 231 | "--out", 232 | "_testdata/tmp/rsrc.syso", 233 | "--arch", 234 | "386", 235 | "--no-suffix", 236 | "--icon", 237 | "icon.png", 238 | } 239 | main() 240 | checkFile(t, "rsrc.syso", []byte{0x8e, 0xc8, 0xe5, 0x44, 0x8e, 0x93, 0xd2, 0xab, 0x84, 0x10, 0x67, 0x16, 0xac, 0x70, 0x1a, 0xad}) 241 | } 242 | 243 | func Test_Make(t *testing.T) { 244 | a := os.Args 245 | defer func() { os.Args = a }() 246 | 247 | f := makeTmpDir(t) 248 | defer f() 249 | 250 | os.Args = []string{ 251 | "./go-winres.exe", 252 | "make", 253 | "--arch", 254 | " amd64, 386 , arm, arm64 ", 255 | "--out", 256 | "_testdata/tmp/make", 257 | "--product-version", 258 | "v42.5.3.8 alpha", 259 | "--file-version", 260 | "1.2.3.4.5.6.7", 261 | "--in", 262 | "_testdata/test.json", 263 | } 264 | main() 265 | checkFile(t, "make_windows_arm64.syso", []byte{0x5e, 0xc2, 0xf1, 0xb3, 0x6c, 0x49, 0x56, 0x25, 0xa8, 0x1e, 0x68, 0x49, 0x5b, 0x92, 0x3d, 0x9c}) 266 | checkFile(t, "make_windows_arm.syso", []byte{0x9e, 0xdf, 0x5a, 0x08, 0x38, 0x95, 0x38, 0x07, 0x13, 0xa1, 0x14, 0xba, 0xd7, 0x35, 0xbf, 0x11}) 267 | checkFile(t, "make_windows_amd64.syso", []byte{0x05, 0x6f, 0xa2, 0x0a, 0x06, 0xef, 0x64, 0x7f, 0xcd, 0x69, 0x07, 0x63, 0xc2, 0xa8, 0xc1, 0xa1}) 268 | checkFile(t, "make_windows_386.syso", []byte{0x35, 0xcc, 0x28, 0x6e, 0x57, 0x1c, 0x58, 0xf4, 0xaf, 0x82, 0x8a, 0xf1, 0x85, 0x5a, 0x9e, 0x61}) 269 | } 270 | 271 | func copyFile(t *testing.T, src, dst string) { 272 | s, err := os.Open(src) 273 | if err != nil { 274 | t.Fatal(err) 275 | } 276 | defer s.Close() 277 | 278 | d, err := os.Create(dst) 279 | if err != nil { 280 | t.Fatal(err) 281 | } 282 | defer d.Close() 283 | 284 | io.Copy(d, s) 285 | } 286 | 287 | func makeTmpDir(t *testing.T) func() { 288 | os.RemoveAll(tmpDir) 289 | 290 | err := os.MkdirAll(tmpDir, 0666) 291 | if err != nil { 292 | t.Fatal(err) 293 | } 294 | 295 | return func() { 296 | err = os.RemoveAll(tmpDir) 297 | if err != nil { 298 | t.Log(err) 299 | } 300 | } 301 | } 302 | 303 | func moveToTmpDir(t *testing.T) func() { 304 | dir, err := os.Getwd() 305 | if err != nil { 306 | t.Fatal(err) 307 | } 308 | 309 | err = os.Chdir(tmpDir) 310 | if err != nil { 311 | t.Fatal(err) 312 | } 313 | 314 | return func() { 315 | err = os.Chdir(dir) 316 | if err != nil { 317 | t.Fatal(err) 318 | } 319 | } 320 | } 321 | 322 | func createTmpGitTag(t *testing.T, tag string) { 323 | err := ioutil.WriteFile("tmp.txt", []byte{}, 0666) 324 | if err != nil { 325 | t.Fatal(err) 326 | } 327 | cmd := exec.Command("git", "init") 328 | err = cmd.Run() 329 | if err != nil { 330 | t.Fatal(err) 331 | } 332 | cmd = exec.Command("git", "add", "tmp.txt") 333 | err = cmd.Run() 334 | if err != nil { 335 | t.Fatal(err) 336 | } 337 | cmd = exec.Command("git", "commit", "-m", ".") 338 | err = cmd.Run() 339 | if err != nil { 340 | t.Fatal(err) 341 | } 342 | cmd = exec.Command("git", "tag", "-a", tag, "-m", ".") 343 | err = cmd.Run() 344 | if err != nil { 345 | t.Fatal(err) 346 | } 347 | } 348 | 349 | func loadJSON(t *testing.T, file string) string { 350 | d, err := ioutil.ReadFile(filepath.Join(tmpDir, file)) 351 | if err != nil { 352 | t.Fatal(err) 353 | } 354 | return string(d) 355 | } 356 | 357 | func checkFile(t *testing.T, file string, hash []byte) { 358 | f, err := os.Open(filepath.Join(tmpDir, file)) 359 | if err != nil { 360 | t.Fatal(err) 361 | } 362 | defer f.Close() 363 | 364 | h := md5.New() 365 | io.Copy(h, f) 366 | if !bytes.Equal(h.Sum(nil), hash) { 367 | t.Errorf("wrong hash for %s %x", file, h.Sum(nil)) 368 | } 369 | } 370 | 371 | // language=json 372 | const jsonRHM = `{ 373 | "PNG": { 374 | "CUR-64X128": { 375 | "0000": "PNG_CUR-64X128_0000.png" 376 | } 377 | }, 378 | "RT_BITMAP": { 379 | "ICON16": { 380 | "0000": "ICON16_0000.bmp" 381 | } 382 | }, 383 | "RT_GROUP_CURSOR": { 384 | "CURSOR": { 385 | "0000": "CURSOR_0000.cur" 386 | } 387 | }, 388 | "RT_GROUP_ICON": { 389 | "#1": { 390 | "0000": "#1_0000.ico" 391 | }, 392 | "APP": { 393 | "0409": "APP_0409.ico", 394 | "040C": "APP_040C.ico" 395 | } 396 | }, 397 | "RT_MANIFEST": { 398 | "#1": { 399 | "0000": { 400 | "identity": {}, 401 | "description": "", 402 | "minimum-os": "win7", 403 | "execution-level": "", 404 | "ui-access": false, 405 | "auto-elevate": false, 406 | "dpi-awareness": "system", 407 | "disable-theming": false, 408 | "disable-window-filtering": false, 409 | "high-resolution-scrolling-aware": false, 410 | "ultra-high-resolution-scrolling-aware": false, 411 | "long-path-aware": false, 412 | "printer-driver-isolation": false, 413 | "gdi-scaling": false, 414 | "segment-heap": false, 415 | "use-common-controls-v6": false 416 | } 417 | } 418 | }, 419 | "RT_VERSION": { 420 | "#1": { 421 | "0409": { 422 | "fixed": { 423 | "file_version": "1.2.3.4", 424 | "product_version": "5.6.7.8" 425 | }, 426 | "info": { 427 | "0409": { 428 | "CompanyName": "WinRes Corp.", 429 | "FileDescription": "WinRes", 430 | "FileVersion": "1.2.3.4 (Build.42.42)", 431 | "InternalName": "winres", 432 | "LegalCopyright": "© WinRes.", 433 | "OriginalFilename": "WINRES.EXE", 434 | "ProductName": "WinRes CLI", 435 | "ProductVersion": "5.6.7.8" 436 | } 437 | } 438 | } 439 | } 440 | } 441 | }` 442 | 443 | // language=json 444 | const jsonRH = `{ 445 | "PNG": { 446 | "CUR-64X128": { 447 | "0000": "PNG_CUR-64X128_0000.png" 448 | } 449 | }, 450 | "RT_BITMAP": { 451 | "ICON16": { 452 | "0000": "ICON16_0000.bmp" 453 | } 454 | }, 455 | "RT_GROUP_CURSOR": { 456 | "CURSOR": { 457 | "0000": "CURSOR_0000.cur" 458 | } 459 | }, 460 | "RT_GROUP_ICON": { 461 | "#1": { 462 | "0000": "#1_0000.ico" 463 | }, 464 | "APP": { 465 | "0409": "APP_0409.ico", 466 | "040C": "APP_040C.ico" 467 | } 468 | }, 469 | "RT_MANIFEST": { 470 | "#1": { 471 | "0000": "#1_0000.manifest" 472 | } 473 | }, 474 | "RT_VERSION": { 475 | "#1": { 476 | "0409": { 477 | "fixed": { 478 | "file_version": "1.2.3.4", 479 | "product_version": "5.6.7.8" 480 | }, 481 | "info": { 482 | "0409": { 483 | "CompanyName": "WinRes Corp.", 484 | "FileDescription": "WinRes", 485 | "FileVersion": "1.2.3.4 (Build.42.42)", 486 | "InternalName": "winres", 487 | "LegalCopyright": "© WinRes.", 488 | "OriginalFilename": "WINRES.EXE", 489 | "ProductName": "WinRes CLI", 490 | "ProductVersion": "5.6.7.8" 491 | } 492 | } 493 | } 494 | } 495 | } 496 | }` 497 | -------------------------------------------------------------------------------- /resdir.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bytes" 5 | "encoding/binary" 6 | "encoding/json" 7 | "errors" 8 | "fmt" 9 | "image" 10 | "io/ioutil" 11 | "log" 12 | "os" 13 | "path/filepath" 14 | "sort" 15 | "strconv" 16 | "strings" 17 | 18 | "github.com/tc-hib/winres" 19 | "github.com/tc-hib/winres/version" 20 | ) 21 | 22 | const ( 23 | errInvalidSet = "invalid resource set definition" 24 | errInvalidCursor = "invalid cursor definition" 25 | errInvalidIcon = "invalid icon definition" 26 | ) 27 | 28 | type jsonDef map[string]map[string]map[string]interface{} 29 | 30 | var typeIDToString = map[winres.ID]string{ 31 | winres.RT_CURSOR: "RT_CURSOR", 32 | winres.RT_BITMAP: "RT_BITMAP", 33 | winres.RT_ICON: "RT_ICON", 34 | winres.RT_MENU: "RT_MENU", 35 | winres.RT_DIALOG: "RT_DIALOG", 36 | winres.RT_STRING: "RT_STRING", 37 | winres.RT_FONTDIR: "RT_FONTDIR", 38 | winres.RT_FONT: "RT_FONT", 39 | winres.RT_ACCELERATOR: "RT_ACCELERATOR", 40 | winres.RT_RCDATA: "RT_RCDATA", 41 | winres.RT_MESSAGETABLE: "RT_MESSAGETABLE", 42 | winres.RT_GROUP_CURSOR: "RT_GROUP_CURSOR", 43 | winres.RT_GROUP_ICON: "RT_GROUP_ICON", 44 | winres.RT_VERSION: "RT_VERSION", 45 | winres.RT_PLUGPLAY: "RT_PLUGPLAY", 46 | winres.RT_VXD: "RT_VXD", 47 | winres.RT_ANICURSOR: "RT_ANICURSOR", 48 | winres.RT_ANIICON: "RT_ANIICON", 49 | winres.RT_HTML: "RT_HTML", 50 | winres.RT_MANIFEST: "RT_MANIFEST", 51 | } 52 | 53 | var typeIDFromString = map[string]winres.ID{ 54 | "RT_CURSOR": winres.RT_CURSOR, 55 | "RT_BITMAP": winres.RT_BITMAP, 56 | "RT_ICON": winres.RT_ICON, 57 | "RT_MENU": winres.RT_MENU, 58 | "RT_DIALOG": winres.RT_DIALOG, 59 | "RT_STRING": winres.RT_STRING, 60 | "RT_FONTDIR": winres.RT_FONTDIR, 61 | "RT_FONT": winres.RT_FONT, 62 | "RT_ACCELERATOR": winres.RT_ACCELERATOR, 63 | "RT_RCDATA": winres.RT_RCDATA, 64 | "RT_MESSAGETABLE": winres.RT_MESSAGETABLE, 65 | "RT_GROUP_CURSOR": winres.RT_GROUP_CURSOR, 66 | "RT_GROUP_ICON": winres.RT_GROUP_ICON, 67 | "RT_VERSION": winres.RT_VERSION, 68 | "RT_PLUGPLAY": winres.RT_PLUGPLAY, 69 | "RT_VXD": winres.RT_VXD, 70 | "RT_ANICURSOR": winres.RT_ANICURSOR, 71 | "RT_ANIICON": winres.RT_ANIICON, 72 | "RT_HTML": winres.RT_HTML, 73 | "RT_MANIFEST": winres.RT_MANIFEST, 74 | } 75 | 76 | func exportResources(dir string, rs *winres.ResourceSet, manifestInJSON bool) { 77 | res := jsonDef{} 78 | jsonName := filepath.Join(dir, "winres.json") 79 | 80 | rs.Walk(func(typeID, resID winres.Identifier, langID uint16, data []byte) bool { 81 | switch typeID { 82 | case winres.RT_CURSOR, winres.RT_ICON: 83 | return true 84 | } 85 | 86 | t, r, l := idsToStrings(typeID, resID, langID) 87 | filename := filepath.Join(dir, exportedName(res[t] == nil, data, typeID, resID, langID)) 88 | 89 | if res[t] == nil { 90 | res[t] = make(map[string]map[string]interface{}) 91 | } 92 | if res[t][r] == nil { 93 | res[t][r] = make(map[string]interface{}) 94 | } 95 | 96 | printError := func(err error) { 97 | log.Printf("[%s][%s][%s] %v", t, r, l, err) 98 | } 99 | 100 | switch typeID { 101 | case winres.RT_GROUP_ICON: 102 | err := saveIcon(filename, rs, resID, langID) 103 | if err != nil { 104 | printError(err) 105 | return true 106 | } 107 | res[t][r][l] = filepath.Base(filename) 108 | return true 109 | case winres.RT_GROUP_CURSOR: 110 | err := saveCursor(filename, rs, resID, langID) 111 | if err != nil { 112 | printError(err) 113 | return true 114 | } 115 | res[t][r][l] = filepath.Base(filename) 116 | return true 117 | case winres.RT_BITMAP: 118 | err := saveBitmap(filename, data) 119 | if err != nil { 120 | printError(err) 121 | return true 122 | } 123 | res[t][r][l] = filepath.Base(filename) 124 | return true 125 | case winres.RT_VERSION: 126 | vi, err := version.FromBytes(data) 127 | if err != nil { 128 | printError(err) 129 | return true 130 | } 131 | res[t][r][l] = vi 132 | return true 133 | case winres.RT_MANIFEST: 134 | if manifestInJSON { 135 | m, err := winres.AppManifestFromXML(data) 136 | if err != nil { 137 | printError(err) 138 | return true 139 | } 140 | res[t][r][l] = m 141 | return true 142 | } 143 | } 144 | err := ioutil.WriteFile(filename, data, 0666) 145 | if err != nil { 146 | printError(err) 147 | return true 148 | } 149 | res[t][r][l] = filepath.Base(filename) 150 | return true 151 | }) 152 | 153 | b, err := json.MarshalIndent(res, "", " ") 154 | if err != nil { 155 | log.Println(err) 156 | return 157 | } 158 | 159 | err = ioutil.WriteFile(jsonName, b, 0666) 160 | if err != nil { 161 | log.Println(err) 162 | } 163 | } 164 | 165 | func saveIcon(filename string, rs *winres.ResourceSet, resID winres.Identifier, langID uint16) error { 166 | icon, err := rs.GetIconTranslation(resID, langID) 167 | if err != nil { 168 | return err 169 | } 170 | 171 | f, err := os.Create(filename) 172 | if err != nil { 173 | return err 174 | } 175 | defer f.Close() 176 | 177 | err = icon.SaveICO(f) 178 | if err != nil { 179 | return err 180 | } 181 | 182 | return f.Close() 183 | } 184 | 185 | func saveCursor(filename string, rs *winres.ResourceSet, resID winres.Identifier, langID uint16) error { 186 | cursor, err := rs.GetCursorTranslation(resID, langID) 187 | if err != nil { 188 | return err 189 | } 190 | 191 | f, err := os.Create(filename) 192 | if err != nil { 193 | return err 194 | } 195 | defer f.Close() 196 | 197 | err = cursor.SaveCUR(f) 198 | if err != nil { 199 | return err 200 | } 201 | 202 | return f.Close() 203 | } 204 | 205 | func saveBitmap(filename string, dib []byte) error { 206 | f, err := os.Create(filename) 207 | if err != nil { 208 | return err 209 | } 210 | defer f.Close() 211 | 212 | _, err = f.Write(dibToBMP(dib)) 213 | if err != nil { 214 | return err 215 | } 216 | 217 | return f.Close() 218 | } 219 | 220 | func dibToBMP(dib []byte) []byte { 221 | dibHeader := struct { 222 | Size uint32 223 | Width int32 224 | Height int32 225 | Planes uint16 226 | BitCount uint16 227 | Compression uint32 228 | SizeImage uint32 229 | XPelsPerMeter int32 230 | YPelsPerMeter int32 231 | ClrUsed uint32 232 | }{} 233 | 234 | const ( 235 | BI_PNG = 4 236 | BI_JPEG = 5 237 | ) 238 | 239 | err := binary.Read(bytes.NewReader(dib), binary.LittleEndian, &dibHeader) 240 | if err != nil || dibHeader.Size < 40 { 241 | return dib 242 | } 243 | 244 | bitsOffset := 14 + dibHeader.Size 245 | // https://docs.microsoft.com/en-us/previous-versions/dd183376(v=vs.85) 246 | // Several things don't seem to be true anymore: 247 | // BI_BITFIELD and ClrUsed don't seem to have any effect on 16bpp, 24bpp or 32bpp RGB bitmaps 248 | if dibHeader.Compression != BI_PNG && dibHeader.Compression != BI_JPEG { 249 | switch dibHeader.BitCount { 250 | case 1, 4, 8: 251 | if dibHeader.ClrUsed == 0 { 252 | dibHeader.ClrUsed = 1 << dibHeader.BitCount 253 | } 254 | bitsOffset += dibHeader.ClrUsed * 4 255 | case 16, 24, 32: 256 | // dibHeader.ClrUsed and dibHeader.Compression are ignored on purpose. 257 | // They don't seem to have any effect anymore. 258 | bitsOffset += dibHeader.ClrUsed * 4 259 | default: 260 | return dib 261 | } 262 | } 263 | 264 | fileSize := uint32(len(dib) + 14) 265 | bmp := make([]byte, 0, fileSize) 266 | buf := bytes.NewBuffer(bmp) 267 | buf.Write([]byte("BM")) 268 | binary.Write(buf, binary.LittleEndian, fileSize) 269 | buf.Write([]byte{0, 0, 0, 0}) 270 | binary.Write(buf, binary.LittleEndian, bitsOffset) 271 | buf.Write(dib) 272 | 273 | return buf.Bytes() 274 | } 275 | 276 | func idsToStrings(typeID, resID winres.Identifier, langID uint16) (t, r, l string) { 277 | switch ident := typeID.(type) { 278 | case winres.ID: 279 | if s, ok := typeIDToString[ident]; ok { 280 | t = s 281 | } else { 282 | t = fmt.Sprintf("#%d", ident) 283 | } 284 | case winres.Name: 285 | t = fmt.Sprintf("%s", ident) 286 | } 287 | 288 | switch ident := resID.(type) { 289 | case winres.ID: 290 | r = fmt.Sprintf("#%d", ident) 291 | case winres.Name: 292 | r = fmt.Sprintf("%s", ident) 293 | } 294 | 295 | l = fmt.Sprintf("%04X", langID) 296 | 297 | return 298 | } 299 | 300 | func idsFromStrings(t, r, l string) (winres.Identifier, winres.Identifier, uint16, error) { 301 | var ( 302 | typeID winres.Identifier 303 | resID winres.Identifier 304 | langID uint16 305 | ) 306 | 307 | if id, ok := typeIDFromString[t]; ok { 308 | typeID = id 309 | } else { 310 | typeID = stringToIdentifier(t) 311 | } 312 | if typeID == nil { 313 | return nil, nil, 0, errors.New("invalid type identifier") 314 | } 315 | 316 | resID = stringToIdentifier(r) 317 | if resID == nil { 318 | return nil, nil, 0, errors.New("invalid resource identifier") 319 | } 320 | 321 | n, err := strconv.ParseUint(l, 16, 16) 322 | if err != nil { 323 | return nil, nil, 0, errors.New("invalid language identifier") 324 | } 325 | langID = uint16(n) 326 | 327 | return typeID, resID, langID, nil 328 | } 329 | 330 | func stringToIdentifier(s string) winres.Identifier { 331 | if s == "" { 332 | return nil 333 | } 334 | if s[0] == '#' { 335 | n, err := strconv.ParseInt(s[1:], 10, 16) 336 | if err == nil { 337 | return winres.ID(n) 338 | } 339 | } 340 | return winres.Name(s) 341 | } 342 | 343 | func exportedName(first bool, data []byte, typeID, resID winres.Identifier, langID uint16) string { 344 | ext := "bin" 345 | t, r, l := idsToStrings(typeID, resID, langID) 346 | switch typeID { 347 | case winres.RT_MANIFEST: 348 | if resID == winres.ID(1) && langID == winres.LCIDDefault { 349 | return "app.manifest" 350 | } 351 | ext = "manifest" 352 | t = "" 353 | case winres.RT_GROUP_ICON: 354 | ext = "ico" 355 | t = "" 356 | case winres.RT_GROUP_CURSOR: 357 | ext = "cur" 358 | t = "" 359 | case winres.RT_BITMAP: 360 | ext = "bmp" 361 | t = "" 362 | case winres.RT_ANICURSOR: 363 | ext = "ani" 364 | case winres.RT_ANIICON: 365 | ext = "ani" 366 | case winres.RT_VERSION: 367 | if first { 368 | return "info.json" 369 | } 370 | t = "info" 371 | ext = "json" 372 | } 373 | if ext == "bin" { 374 | if len(data) > 8 && string(data[:8]) == "\x89PNG\r\n\x1a\n" { 375 | cfg, s, _ := image.DecodeConfig(bytes.NewReader(data)) 376 | if s == "png" && cfg.ColorModel != nil && cfg.Width != 0 && cfg.Height != 0 { 377 | ext = "png" 378 | } 379 | } 380 | } 381 | if t == "" { 382 | return fmt.Sprintf("%s_%s.%s", r, l, ext) 383 | } 384 | return fmt.Sprintf("%s_%s_%s.%s", t, r, l, ext) 385 | } 386 | 387 | func importResources(rs *winres.ResourceSet, jsonName string) error { 388 | dir := filepath.Dir(jsonName) 389 | b, err := ioutil.ReadFile(jsonName) 390 | if err != nil { 391 | return err 392 | } 393 | 394 | res := jsonDef{} 395 | err = json.Unmarshal(b, &res) 396 | if err != nil { 397 | return err 398 | } 399 | 400 | for tid, t := range res { 401 | for _, r := range sortedRes(t) { 402 | for _, l := range sortedLang(r.langs) { 403 | typeID, resID, langID, err := idsFromStrings(tid, r.id, l.id) 404 | if err != nil { 405 | return err 406 | } 407 | switch typeID { 408 | case winres.RT_ICON: 409 | return errors.New("cannot import RT_ICON resources directly, use RT_GROUP_ICON instead") 410 | case winres.RT_CURSOR: 411 | return errors.New("cannot import RT_CURSOR resources directly, use RT_GROUP_CURSOR instead") 412 | case winres.RT_GROUP_CURSOR: 413 | cursor, err := loadCursor(dir, l.data) 414 | if err != nil { 415 | return err 416 | } 417 | err = rs.SetCursorTranslation(resID, langID, cursor) 418 | if err != nil { 419 | return err 420 | } 421 | case winres.RT_GROUP_ICON: 422 | icon, err := loadIcon(dir, l.data) 423 | if err != nil { 424 | return err 425 | } 426 | err = rs.SetIconTranslation(resID, langID, icon) 427 | if err != nil { 428 | return err 429 | } 430 | case winres.RT_VERSION: 431 | vi := version.Info{} 432 | j, _ := json.Marshal(l.data) 433 | err = json.Unmarshal(j, &vi) 434 | if err != nil { 435 | return err 436 | } 437 | rs.SetVersionInfo(vi) 438 | case winres.RT_BITMAP: 439 | filename, ok := l.data.(string) 440 | if !ok { 441 | return errors.New(errInvalidSet) 442 | } 443 | dib, err := loadBMP(filepath.Join(dir, filename)) 444 | if err != nil { 445 | return err 446 | } 447 | err = rs.Set(winres.RT_BITMAP, resID, langID, dib) 448 | if err != nil { 449 | return err 450 | } 451 | case winres.RT_MANIFEST: 452 | switch val := l.data.(type) { 453 | case string: 454 | data, err := ioutil.ReadFile(filepath.Join(dir, val)) 455 | if err != nil { 456 | return err 457 | } 458 | err = rs.Set(typeID, resID, langID, data) 459 | if err != nil { 460 | return err 461 | } 462 | default: 463 | j, _ := json.Marshal(val) 464 | m := winres.AppManifest{} 465 | err = json.Unmarshal(j, &m) 466 | if err != nil { 467 | return err 468 | } 469 | rs.SetManifest(m) 470 | } 471 | default: 472 | filename, ok := l.data.(string) 473 | if !ok { 474 | return errors.New(errInvalidSet) 475 | } 476 | data, err := ioutil.ReadFile(filepath.Join(dir, filename)) 477 | if err != nil { 478 | return err 479 | } 480 | err = rs.Set(typeID, resID, langID, data) 481 | if err != nil { 482 | return err 483 | } 484 | } 485 | } 486 | } 487 | } 488 | 489 | return nil 490 | } 491 | 492 | type resource struct { 493 | id string 494 | langs map[string]interface{} 495 | } 496 | 497 | type lang struct { 498 | id string 499 | data interface{} 500 | } 501 | 502 | func sortedRes(m map[string]map[string]interface{}) []resource { 503 | var res []resource 504 | for id, langs := range m { 505 | res = append(res, resource{id, langs}) 506 | } 507 | sort.Slice(res, func(i, j int) bool { 508 | return res[i].id < res[j].id 509 | }) 510 | return res 511 | } 512 | 513 | func sortedLang(m map[string]interface{}) []lang { 514 | var l []lang 515 | for id, data := range m { 516 | l = append(l, lang{id, data}) 517 | } 518 | sort.Slice(l, func(i, j int) bool { 519 | return l[i].id < l[j].id 520 | }) 521 | return l 522 | } 523 | 524 | func loadCursor(dir string, c interface{}) (*winres.Cursor, error) { 525 | switch c := c.(type) { 526 | case string: 527 | return loadCUR(filepath.Join(dir, c)) 528 | 529 | case []interface{}: 530 | var images []winres.CursorImage 531 | for i := range c { 532 | o, ok := c[i].(map[string]interface{}) 533 | if !ok { 534 | return nil, errors.New(errInvalidCursor) 535 | } 536 | curImg, err := loadCursorImage(dir, o) 537 | if err != nil { 538 | return nil, err 539 | } 540 | images = append(images, curImg) 541 | } 542 | return winres.NewCursorFromImages(images) 543 | 544 | case map[string]interface{}: 545 | curImg, err := loadCursorImage(dir, c) 546 | if err != nil { 547 | return nil, err 548 | } 549 | return winres.NewCursorFromImages([]winres.CursorImage{curImg}) 550 | } 551 | 552 | return nil, errors.New(errInvalidCursor) 553 | } 554 | 555 | func loadCursorImage(dir string, c map[string]interface{}) (winres.CursorImage, error) { 556 | x, xOK := c["x"].(float64) 557 | y, yOK := c["y"].(float64) 558 | f, fOK := c["image"].(string) 559 | if !fOK || !xOK || !yOK { 560 | return winres.CursorImage{}, errors.New(errInvalidCursor) 561 | } 562 | 563 | img, err := loadImage(filepath.Join(dir, f)) 564 | if err != nil { 565 | return winres.CursorImage{}, err 566 | } 567 | 568 | return winres.CursorImage{ 569 | Image: img, 570 | HotSpot: winres.HotSpot{X: uint16(x), Y: uint16(y)}, 571 | }, nil 572 | } 573 | 574 | func loadIcon(dir string, x interface{}) (*winres.Icon, error) { 575 | switch x := x.(type) { 576 | case string: 577 | if strings.ToLower(filepath.Ext(x)) == ".ico" { 578 | return loadICO(filepath.Join(dir, x)) 579 | } 580 | img, err := loadImage(filepath.Join(dir, x)) 581 | if err != nil { 582 | return nil, err 583 | } 584 | return winres.NewIconFromResizedImage(img, nil) 585 | case []interface{}: 586 | var images []image.Image 587 | for i := range x { 588 | f, ok := x[i].(string) 589 | if !ok { 590 | return nil, errors.New(errInvalidIcon) 591 | } 592 | img, err := loadImage(filepath.Join(dir, f)) 593 | if err != nil { 594 | return nil, err 595 | } 596 | images = append(images, img) 597 | } 598 | return winres.NewIconFromImages(images) 599 | } 600 | return nil, errors.New(errInvalidIcon) 601 | } 602 | 603 | func loadImage(name string) (image.Image, error) { 604 | f, err := os.Open(name) 605 | if err != nil { 606 | return nil, err 607 | } 608 | defer f.Close() 609 | 610 | img, _, err := image.Decode(f) 611 | return img, err 612 | } 613 | 614 | func loadCUR(name string) (*winres.Cursor, error) { 615 | f, err := os.Open(name) 616 | if err != nil { 617 | return nil, err 618 | } 619 | defer f.Close() 620 | 621 | return winres.LoadCUR(f) 622 | } 623 | 624 | func loadICO(name string) (*winres.Icon, error) { 625 | f, err := os.Open(name) 626 | if err != nil { 627 | return nil, err 628 | } 629 | defer f.Close() 630 | 631 | return winres.LoadICO(f) 632 | } 633 | 634 | func loadBMP(name string) ([]byte, error) { 635 | b, err := ioutil.ReadFile(name) 636 | if err != nil { 637 | return nil, err 638 | } 639 | 640 | if len(b) > 14 && b[0] == 'B' && b[1] == 'M' && int(b[5])<<24|int(b[4])<<16|int(b[3])<<8|int(b[2]) == len(b) { 641 | return b[14:], nil 642 | } 643 | 644 | return b, nil 645 | } 646 | -------------------------------------------------------------------------------- /resdir_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bytes" 5 | "image" 6 | "image/png" 7 | "reflect" 8 | "testing" 9 | 10 | "github.com/tc-hib/winres" 11 | ) 12 | 13 | func Test_exportedName(t *testing.T) { 14 | var ( 15 | pngBuf bytes.Buffer 16 | fakePng = []byte{0x89, 'P', 'N', 'G', 0xD, 0xA, 0x1A, 0xA, 0xFF} 17 | ) 18 | 19 | img := image.NewNRGBA(image.Rectangle{Min: image.Point{0, 0}, Max: image.Point{1, 1}}) 20 | png.Encode(&pngBuf, img) 21 | 22 | type args struct { 23 | first bool 24 | data []byte 25 | typeID winres.Identifier 26 | resID winres.Identifier 27 | langID uint16 28 | } 29 | tests := []struct { 30 | name string 31 | args args 32 | want string 33 | }{ 34 | { 35 | args: args{true, fakePng, winres.Name("PNG"), winres.ID(1), 0x409}, 36 | want: "PNG_#1_0409.bin", 37 | }, 38 | { 39 | args: args{true, pngBuf.Bytes(), winres.Name("PNG"), winres.ID(1), 0x409}, 40 | want: "PNG_#1_0409.png", 41 | }, 42 | { 43 | args: args{true, pngBuf.Bytes(), winres.RT_MANIFEST, winres.ID(1), 0x409}, 44 | want: "app.manifest", 45 | }, 46 | { 47 | args: args{false, pngBuf.Bytes(), winres.RT_MANIFEST, winres.ID(1), 0x40C}, 48 | want: "#1_040C.manifest", 49 | }, 50 | { 51 | args: args{true, pngBuf.Bytes(), winres.RT_VERSION, winres.Name("Hey"), 0x409}, 52 | want: "info.json", 53 | }, 54 | { 55 | args: args{false, pngBuf.Bytes(), winres.RT_VERSION, winres.Name("Hey"), 0x409}, 56 | want: "info_Hey_0409.json", 57 | }, 58 | { 59 | args: args{true, pngBuf.Bytes(), winres.RT_RCDATA, winres.Name("Hey"), 0x409}, 60 | want: "RT_RCDATA_Hey_0409.png", 61 | }, 62 | { 63 | args: args{true, nil, winres.RT_RCDATA, winres.Name("Hey"), 0x409}, 64 | want: "RT_RCDATA_Hey_0409.bin", 65 | }, 66 | { 67 | args: args{true, nil, winres.ID(42), winres.Name("Hey"), 0x409}, 68 | want: "#42_Hey_0409.bin", 69 | }, 70 | { 71 | args: args{false, pngBuf.Bytes(), winres.RT_BITMAP, winres.Name("Hey"), 0x409}, 72 | want: "Hey_0409.bmp", 73 | }, 74 | { 75 | args: args{false, pngBuf.Bytes(), winres.RT_ANIICON, winres.ID(42), 0x409}, 76 | want: "RT_ANIICON_#42_0409.ani", 77 | }, 78 | { 79 | args: args{true, pngBuf.Bytes(), winres.RT_ANICURSOR, winres.ID(42), 0x409}, 80 | want: "RT_ANICURSOR_#42_0409.ani", 81 | }, 82 | { 83 | args: args{false, pngBuf.Bytes(), winres.RT_GROUP_CURSOR, winres.ID(42), 0x401}, 84 | want: "#42_0401.cur", 85 | }, 86 | { 87 | args: args{true, pngBuf.Bytes(), winres.RT_GROUP_ICON, winres.Name("APPICON"), 0x402}, 88 | want: "APPICON_0402.ico", 89 | }, 90 | } 91 | for _, tt := range tests { 92 | t.Run(tt.name, func(t *testing.T) { 93 | if got := exportedName(tt.args.first, tt.args.data, tt.args.typeID, tt.args.resID, tt.args.langID); got != tt.want { 94 | t.Errorf("exportedName() = %v, want %v", got, tt.want) 95 | } 96 | }) 97 | } 98 | } 99 | 100 | func Test_idsFromStrings(t *testing.T) { 101 | type args struct { 102 | t string 103 | r string 104 | l string 105 | } 106 | type want struct { 107 | t winres.Identifier 108 | r winres.Identifier 109 | l uint16 110 | err bool 111 | } 112 | tests := []struct { 113 | name string 114 | args args 115 | want want 116 | }{ 117 | { 118 | args: args{"RT_ICON", "RT_ICON", "RT_ICON"}, 119 | want: want{nil, nil, 0, true}, 120 | }, 121 | { 122 | args: args{"RT_ICON", "#1", "#1"}, 123 | want: want{nil, nil, 0, true}, 124 | }, 125 | { 126 | args: args{"#1", "#1", "040C"}, 127 | want: want{winres.ID(1), winres.ID(1), 0x40C, false}, 128 | }, 129 | { 130 | args: args{"#24", "Hello", "FFFF"}, 131 | want: want{winres.RT_MANIFEST, winres.Name("Hello"), 0xFFFF, false}, 132 | }, 133 | { 134 | args: args{"#24", "Hello", "1FFFF"}, 135 | want: want{nil, nil, 0, true}, 136 | }, 137 | { 138 | args: args{"é", "é", "é"}, 139 | want: want{nil, nil, 0, true}, 140 | }, 141 | { 142 | args: args{"é", "é", "0"}, 143 | want: want{winres.Name("é"), winres.Name("é"), 0, false}, 144 | }, 145 | { 146 | args: args{"A", "", "0"}, 147 | want: want{nil, nil, 0, true}, 148 | }, 149 | { 150 | args: args{"", "A", "0"}, 151 | want: want{nil, nil, 0, true}, 152 | }, 153 | { 154 | args: args{"##1", "1", "0"}, 155 | want: want{winres.Name("##1"), winres.Name("1"), 0, false}, 156 | }, 157 | { 158 | args: args{"1", "##1", "0"}, 159 | want: want{winres.Name("1"), winres.Name("##1"), 0, false}, 160 | }, 161 | { 162 | // Fails later in winres 163 | args: args{"\x00", "A", "42"}, 164 | want: want{winres.Name("\x00"), winres.Name("A"), 0x42, false}, 165 | }, 166 | { 167 | // Fails later in winres 168 | args: args{"A", "\x00", "42"}, 169 | want: want{winres.Name("A"), winres.Name("\x00"), 0x42, false}, 170 | }, 171 | } 172 | for _, tt := range tests { 173 | t.Run(tt.name, func(t *testing.T) { 174 | gotT, gotR, gotL, err := idsFromStrings(tt.args.t, tt.args.r, tt.args.l) 175 | got := want{gotT, gotR, gotL, err != nil} 176 | if !reflect.DeepEqual(got, tt.want) { 177 | t.Errorf("idsFromStrings() got = %v, want %v", got, tt.want) 178 | } 179 | }) 180 | } 181 | } 182 | 183 | func Test_dibToBMP(t *testing.T) { 184 | type args struct { 185 | dib []byte 186 | } 187 | tests := []struct { 188 | name string 189 | args args 190 | want uint32 191 | }{ 192 | { 193 | name: "1bpp-1", 194 | args: args{[]byte{40, 0x04: 1, 0x08: 1, 0x0C: 1, 0x0E: 1, 0x20: 1, 0x2F: 0}}, 195 | want: 0x3A, 196 | }, 197 | { 198 | name: "1bpp-0", 199 | args: args{[]byte{40, 0x04: 1, 0x08: 1, 0x0C: 1, 0x0E: 1, 0x20: 0, 0x33: 0}}, 200 | want: 0x3E, 201 | }, 202 | { 203 | name: "4bpp-5", 204 | args: args{[]byte{40, 0x04: 5, 0x08: 5, 0x0C: 1, 0x0E: 4, 0x20: 5, 0x7B: 0}}, 205 | want: 0x4A, 206 | }, 207 | { 208 | name: "4bpp-0", 209 | args: args{[]byte{40, 0x04: 5, 0x08: 5, 0x0C: 1, 0x0E: 4, 0x20: 0, 0xA7: 0}}, 210 | want: 0x76, 211 | }, 212 | { 213 | name: "8bpp-25", 214 | args: args{[]byte{40, 0x04: 5, 0x08: 5, 0x0C: 1, 0x0E: 8, 0x20: 25, 0xB3: 0}}, 215 | want: 0x9A, 216 | }, 217 | { 218 | name: "8bpp-0", 219 | args: args{[]byte{40, 0x04: 5, 0x08: 5, 0x0C: 1, 0x0E: 8, 0x20: 0, 0x44F: 0}}, 220 | want: 0x436, 221 | }, 222 | { 223 | name: "16bpp", 224 | args: args{[]byte{40, 0x04: 5, 0x08: 5, 0x0C: 1, 0x0E: 16, 0x63: 0}}, 225 | want: 0x36, 226 | }, 227 | { 228 | name: "24bpp", 229 | args: args{[]byte{40, 0x04: 5, 0x08: 5, 0x0C: 1, 0x0E: 24, 0x77: 0}}, 230 | want: 0x36, 231 | }, 232 | { 233 | name: "32bpp", 234 | args: args{[]byte{40, 0x04: 5, 0x08: 5, 0x0C: 1, 0x0E: 32, 0x95: 0}}, 235 | want: 0x36, 236 | }, 237 | { 238 | name: "2bpp", 239 | args: args{[]byte{40, 0x04: 5, 0x08: 5, 0x0C: 1, 0x0E: 2, 0x95: 0}}, 240 | want: 0, 241 | }, 242 | { 243 | name: "not dib", 244 | args: args{[]byte{10, 0x04: 5, 0x08: 5, 0x0C: 1, 0x0E: 2, 0x95: 0}}, 245 | want: 0, 246 | }, 247 | { 248 | name: "eof", 249 | args: args{[]byte{10, 0x04: 5, 0x08: 5, 0x0C: 1, 0x0E: 1}}, 250 | want: 0, 251 | }, 252 | } 253 | for _, tt := range tests { 254 | t.Run(tt.name, func(t *testing.T) { 255 | bmp := dibToBMP(tt.args.dib) 256 | if tt.want != 0 || !bytes.Equal(bmp, tt.args.dib) { 257 | size := uint32(bmp[2]) | uint32(bmp[3])<<8 | uint32(bmp[4])<<16 | uint32(bmp[5])<<24 258 | offset := uint32(bmp[10]) | uint32(bmp[11])<<8 | uint32(bmp[12])<<16 | uint32(bmp[13])<<24 259 | wantedSize := uint32(14 + len(tt.args.dib)) 260 | if size != wantedSize || offset != tt.want { 261 | t.Errorf("dibToBMP() = (%v, %v), want (%v, %v)", size, offset, wantedSize, tt.want) 262 | } 263 | } 264 | }) 265 | } 266 | } 267 | -------------------------------------------------------------------------------- /winres/icon128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tc-hib/go-winres/c4d55a3dfc2e22a4a9fb95ae0280ce106daadce9/winres/icon128.png -------------------------------------------------------------------------------- /winres/icon16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tc-hib/go-winres/c4d55a3dfc2e22a4a9fb95ae0280ce106daadce9/winres/icon16.png -------------------------------------------------------------------------------- /winres/icon256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tc-hib/go-winres/c4d55a3dfc2e22a4a9fb95ae0280ce106daadce9/winres/icon256.png -------------------------------------------------------------------------------- /winres/icon64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tc-hib/go-winres/c4d55a3dfc2e22a4a9fb95ae0280ce106daadce9/winres/icon64.png -------------------------------------------------------------------------------- /winres/winres.json: -------------------------------------------------------------------------------- 1 | { 2 | "RT_GROUP_ICON": { 3 | "APP": { 4 | "0000": [ 5 | "icon256.png", 6 | "icon128.png", 7 | "icon64.png", 8 | "icon16.png" 9 | ] 10 | } 11 | }, 12 | "RT_MANIFEST": { 13 | "#1": { 14 | "0409": {} 15 | } 16 | }, 17 | "RT_VERSION": { 18 | "#1": { 19 | "0409": { 20 | "info": { 21 | "0409": { 22 | "FileDescription": "Command line tool for embedding resources in Go applications", 23 | "InternalName": "go-winres", 24 | "LegalCopyright": "© Thomas Combeléran", 25 | "OriginalFilename": "go-winres.exe", 26 | "ProductName": "go-winres" 27 | } 28 | } 29 | } 30 | } 31 | } 32 | } --------------------------------------------------------------------------------