Compare commits
2 commits
6e10d022e5
...
e53b2faa0f
Author | SHA1 | Date | |
---|---|---|---|
e53b2faa0f | |||
04979ce11d |
15 changed files with 1333 additions and 727 deletions
9
.gitignore
vendored
9
.gitignore
vendored
|
@ -1,5 +1,4 @@
|
|||
/.vs
|
||||
/x64
|
||||
/test
|
||||
/oo2core_8_win64.dll
|
||||
/oo2net_9_win64.dll
|
||||
/target
|
||||
/data
|
||||
oo2core_8_win64.dll
|
||||
oo2net_9_win64.dll
|
||||
|
|
546
Cargo.lock
generated
Normal file
546
Cargo.lock
generated
Normal file
|
@ -0,0 +1,546 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "addr2line"
|
||||
version = "0.17.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b"
|
||||
dependencies = [
|
||||
"gimli",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "adler"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
|
||||
|
||||
[[package]]
|
||||
name = "atty"
|
||||
version = "0.2.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
|
||||
dependencies = [
|
||||
"hermit-abi",
|
||||
"libc",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "backtrace"
|
||||
version = "0.3.66"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cab84319d616cfb654d03394f38ab7e6f0919e181b1b57e1fd15e7fb4077d9a7"
|
||||
dependencies = [
|
||||
"addr2line",
|
||||
"cc",
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"miniz_oxide",
|
||||
"object",
|
||||
"rustc-demangle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "1.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.74"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "581f5dba903aac52ea3feb5ec4810848460ee833876f1f9b0fdeab1f19091574"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.0.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "426eed9136e68a14d9de937db20cfd79fcc25c09709872e8005897c618a8365e"
|
||||
dependencies = [
|
||||
"atty",
|
||||
"bitflags",
|
||||
"clap_derive",
|
||||
"clap_lex",
|
||||
"once_cell",
|
||||
"strsim",
|
||||
"termcolor",
|
||||
"unicase",
|
||||
"unicode-width",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_derive"
|
||||
version = "4.0.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "685fbc59da060ed2cd3d79c86970ee95386b5e5fc69d9cad881912dca0c18807"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro-error",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_lex"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0d4198f73e42b4936b35b5bb248d81d2b595ecb170da0bac7655c54eedfa8da8"
|
||||
dependencies = [
|
||||
"os_str_bytes",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "color-eyre"
|
||||
version = "0.6.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5a667583cca8c4f8436db8de46ea8233c42a7d9ae424a82d338f2e4675229204"
|
||||
dependencies = [
|
||||
"backtrace",
|
||||
"color-spantrace",
|
||||
"eyre",
|
||||
"indenter",
|
||||
"once_cell",
|
||||
"owo-colors",
|
||||
"tracing-error",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "color-spantrace"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1ba75b3d9449ecdccb27ecbc479fdc0b87fa2dd43d2f8298f9bf0e59aacc8dce"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
"owo-colors",
|
||||
"tracing-core",
|
||||
"tracing-error",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "eyre"
|
||||
version = "0.6.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4c2b6b5a29c02cdc822728b7d7b8ae1bab3e3b05d44522770ddd49722eeac7eb"
|
||||
dependencies = [
|
||||
"indenter",
|
||||
"once_cell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gimli"
|
||||
version = "0.26.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d"
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9"
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.1.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "indenter"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683"
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.137"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fc7fcc620a3bff7cdd7a365be3376c97191aeaccc2a603e600951e452615bf89"
|
||||
|
||||
[[package]]
|
||||
name = "libloading"
|
||||
version = "0.7.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "matchers"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558"
|
||||
dependencies = [
|
||||
"regex-automata",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
|
||||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
version = "0.5.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "96590ba8f175222643a85693f33d26e9c8a015f599c216509b1a6894af675d34"
|
||||
dependencies = [
|
||||
"adler",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nu-ansi-term"
|
||||
version = "0.46.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84"
|
||||
dependencies = [
|
||||
"overload",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "object"
|
||||
version = "0.29.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "21158b2c33aa6d4561f1c0a6ea283ca92bc54802a93b263e910746d679a7eb53"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.16.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860"
|
||||
|
||||
[[package]]
|
||||
name = "oodle-cli"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"clap",
|
||||
"color-eyre",
|
||||
"libloading",
|
||||
"tracing",
|
||||
"tracing-error",
|
||||
"tracing-subscriber",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "os_str_bytes"
|
||||
version = "6.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3baf96e39c5359d2eb0dd6ccb42c62b91d9678aa68160d261b9e0ccbf9e9dea9"
|
||||
|
||||
[[package]]
|
||||
name = "overload"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
|
||||
|
||||
[[package]]
|
||||
name = "owo-colors"
|
||||
version = "3.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f"
|
||||
|
||||
[[package]]
|
||||
name = "pin-project-lite"
|
||||
version = "0.2.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-error"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
|
||||
dependencies = [
|
||||
"proc-macro-error-attr",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-error-attr"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.47"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e076559ef8e241f2ae3479e36f97bd5741c0330689e217ad51ce2c76808b868a"
|
||||
dependencies = [
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-automata"
|
||||
version = "0.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132"
|
||||
dependencies = [
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.6.28"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848"
|
||||
|
||||
[[package]]
|
||||
name = "rustc-demangle"
|
||||
version = "0.1.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342"
|
||||
|
||||
[[package]]
|
||||
name = "sharded-slab"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "smallvec"
|
||||
version = "1.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0"
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.103"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a864042229133ada95abf3b54fdc62ef5ccabe9515b64717bcb9a1919e59445d"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "termcolor"
|
||||
version = "1.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755"
|
||||
dependencies = [
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thread_local"
|
||||
version = "1.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5516c27b78311c50bf42c071425c560ac799b11c30b31f87e3081965fe5e0180"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing"
|
||||
version = "0.1.37"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"pin-project-lite",
|
||||
"tracing-attributes",
|
||||
"tracing-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing-attributes"
|
||||
version = "0.1.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing-core"
|
||||
version = "0.1.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
"valuable",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing-error"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d686ec1c0f384b1277f097b2f279a2ecc11afe8c133c1aabf036a27cb4cd206e"
|
||||
dependencies = [
|
||||
"tracing",
|
||||
"tracing-subscriber",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing-log"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"log",
|
||||
"tracing-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing-subscriber"
|
||||
version = "0.3.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a6176eae26dd70d0c919749377897b54a9276bd7061339665dd68777926b5a70"
|
||||
dependencies = [
|
||||
"matchers",
|
||||
"nu-ansi-term",
|
||||
"once_cell",
|
||||
"regex",
|
||||
"sharded-slab",
|
||||
"smallvec",
|
||||
"thread_local",
|
||||
"tracing",
|
||||
"tracing-core",
|
||||
"tracing-log",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicase"
|
||||
version = "2.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6"
|
||||
dependencies = [
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-width"
|
||||
version = "0.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"
|
||||
|
||||
[[package]]
|
||||
name = "valuable"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d"
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
||||
dependencies = [
|
||||
"winapi-i686-pc-windows-gnu",
|
||||
"winapi-x86_64-pc-windows-gnu",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-i686-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-util"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-x86_64-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
23
Cargo.toml
Normal file
23
Cargo.toml
Normal file
|
@ -0,0 +1,23 @@
|
|||
[package]
|
||||
name = "oodle-cli"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
byteorder = "1.4.3"
|
||||
clap = { version = "4.0.20", features = ["cargo", "color", "unicode", "std", "derive"] }
|
||||
color-eyre = "0.6.2"
|
||||
libloading = "0.7.4"
|
||||
tracing = "0.1.37"
|
||||
tracing-error = "0.2.0"
|
||||
tracing-subscriber = { version = "0.3.16", features = ["env-filter"] }
|
||||
|
||||
[profile.release]
|
||||
strip = "debuginfo"
|
||||
lto = true
|
||||
|
||||
#debug-assertions = true
|
||||
#overflow-checks = true
|
||||
#opt-level = 0
|
230
oodle-cli.cpp
230
oodle-cli.cpp
|
@ -1,230 +0,0 @@
|
|||
// oodle-cli.cpp : This file contains the 'main' function. Program execution begins and ends there.
|
||||
//
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <sstream>
|
||||
#include <iterator>
|
||||
#include <locale>
|
||||
#include <codecvt>
|
||||
#include <filesystem>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <windows.h>
|
||||
#include <libloaderapi.h>
|
||||
|
||||
#include "oodle2.h"
|
||||
|
||||
const LPCWSTR LIB_NAME = L"oo2core_8_win64";
|
||||
// Printing a `LPCWSTR` is a pain, so it's much easier to just have this second variable.
|
||||
// It's not like this is going to change often.
|
||||
const char* LIB_FILE = "oo2core_8_win64.dll";
|
||||
|
||||
typedef decltype(OodleLZ_Decompress)* decompress_func;
|
||||
typedef decltype(OodleCore_Plugins_SetPrintf)* setprintf_func;
|
||||
|
||||
|
||||
void usage() {
|
||||
std::cerr <<
|
||||
"Usage: oodle-cli [OPTIONS] [--] <in_file> <out_file> <uncompressed_size>\n"
|
||||
"Decompress a <in_file> to <out_file> using the Oodle algorithm.\n"
|
||||
"The size of the uncompressed data must be known.\n"
|
||||
"\n"
|
||||
"Options:\n"
|
||||
" -v Increase Oodle's verbosity. May be specified up to three times.\n"
|
||||
" -c Only check if the library can be found and used.\n"
|
||||
" --fuzz-safe Use fuzz safe decompression.\n"
|
||||
" --check-crc Check CRC during decompression.\n"
|
||||
"\n"
|
||||
"The following environmental variables are recognized:\n"
|
||||
" DLL_SEARCH_PATH: A color (':') separated list of directories to search for the Oodle library. May be relative to the current working directory.\n";
|
||||
}
|
||||
|
||||
|
||||
void printf_callback(int verboseLevel, const char* file, int line, const char* fmt, ...) {
|
||||
std::cout << "[OODLE] ";
|
||||
|
||||
// For some reason, this doesn't actually map to the config value.
|
||||
switch (verboseLevel) {
|
||||
case 0:
|
||||
std::cout << "EXTRAORDINARILY IMPORTANT: ";
|
||||
break;
|
||||
case 1:
|
||||
std::cout << "EXTERMELY IMPORTANT: ";
|
||||
break;
|
||||
case 2:
|
||||
std::cout << "VERY IMPORTANT: ";
|
||||
break;
|
||||
}
|
||||
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
vfprintf(stdout, fmt, args);
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
int verbosity = 0;
|
||||
bool check_lib = FALSE;
|
||||
OodleLZ_FuzzSafe fuzz_safe = OodleLZ_FuzzSafe_No;
|
||||
OodleLZ_CheckCRC check_crc = OodleLZ_CheckCRC_No;
|
||||
int i = 1;
|
||||
|
||||
for (; i < argc; i++) {
|
||||
char* arg = argv[i];
|
||||
|
||||
if (strcmp(arg, "--") == 0 || arg[0] != '-') {
|
||||
break;
|
||||
}
|
||||
|
||||
if (strcmp(arg, "--help") == 0) {
|
||||
usage();
|
||||
return 0;
|
||||
}
|
||||
else if (strcmp(arg, "-c") == 0) {
|
||||
check_lib = TRUE;
|
||||
}
|
||||
else if (strcmp(arg, "-v") == 0) {
|
||||
verbosity++;
|
||||
}
|
||||
else if (strcmp(arg, "--fuzz-safe") == 0) {
|
||||
fuzz_safe = OodleLZ_FuzzSafe_Yes;
|
||||
}
|
||||
else if (strcmp(arg, "--check-crc") == 0) {
|
||||
check_crc = OodleLZ_CheckCRC_Yes;
|
||||
}
|
||||
else {
|
||||
std::cerr << "ERROR: Unknown option '" << arg << "'!\n\n";
|
||||
usage();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
char* var;
|
||||
size_t len;
|
||||
DWORD load_flags = 0;
|
||||
if (_dupenv_s(&var, &len, "DLL_SEARCH_PATH") == 0) {
|
||||
if (var) {
|
||||
std::string search_path(var, len);
|
||||
std::istringstream ss(search_path);
|
||||
std::string token;
|
||||
|
||||
while (std::getline(ss, token, ':')) {
|
||||
auto path = std::filesystem::path(token);
|
||||
if (!path.is_absolute()) {
|
||||
path = std::filesystem::absolute(path);
|
||||
}
|
||||
|
||||
if (!path.is_absolute() || !AddDllDirectory(path.c_str())) {
|
||||
std::cerr << "WARN: Failed to add DLL search path: '" << token << "'!\n";
|
||||
}
|
||||
else {
|
||||
std::cout << "INFO: Added DLL search path: '" << path << "'.\n";
|
||||
}
|
||||
}
|
||||
|
||||
load_flags = LOAD_LIBRARY_SEARCH_DEFAULT_DIRS;
|
||||
free(var);
|
||||
}
|
||||
}
|
||||
else {
|
||||
std::cerr << "ERROR: Failed to read environment variable 'DLL_SEARCH_PATH'. Skipping.\n";
|
||||
}
|
||||
|
||||
HINSTANCE hDLL = LoadLibraryEx(LIB_NAME, NULL, load_flags);
|
||||
if (hDLL == NULL) {
|
||||
std::cerr << "ERROR: Couldn't find library file '" << LIB_FILE << "'!\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
auto decompress = reinterpret_cast<decompress_func>(GetProcAddress((HMODULE)hDLL, "OodleLZ_Decompress"));
|
||||
if (decompress == NULL) {
|
||||
std::cerr << "ERROR: The library is incompatible!\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (check_lib) {
|
||||
std::cout << "INFO: '" << LIB_FILE << "' found and loaded.\n";
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (argc - i < 3) {
|
||||
std::cerr << "ERROR: Arguments missing!\n\n";
|
||||
usage();
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::string in_name = argv[i];
|
||||
std::string out_name = argv[i + 1];
|
||||
size_t raw_buffer_size = std::stoi(argv[i + 2]);
|
||||
|
||||
std::cout << "INFO: Attempting to decompress from '" << in_name << "' to '" << out_name << "' (" << raw_buffer_size << " bytes).\n";
|
||||
|
||||
if (verbosity > 0) {
|
||||
auto fn = reinterpret_cast<setprintf_func>(GetProcAddress((HMODULE)hDLL, "OodleCore_Plugins_SetPrintf"));
|
||||
if (fn == NULL) {
|
||||
std::cerr << "ERROR: The library is incompatible!\n";
|
||||
return 1;
|
||||
}
|
||||
reinterpret_cast<void*>(fn(printf_callback));
|
||||
}
|
||||
|
||||
std::ifstream in_file(in_name, std::ios::binary | std::ios::ate);
|
||||
if (!in_file) {
|
||||
std::cerr << "ERROR: Failed to open compressed file!\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::streamsize compressed_buffer_size = in_file.tellg();
|
||||
in_file.seekg(0, std::ios::beg);
|
||||
|
||||
std::vector<char> compressed_buffer(compressed_buffer_size);
|
||||
in_file.read(compressed_buffer.data(), compressed_buffer_size);
|
||||
|
||||
if (in_file.fail()) {
|
||||
std::cerr << "ERROR: Failed to read compressed file!\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::vector<char> raw_buffer(raw_buffer_size);
|
||||
|
||||
intptr_t res = decompress(
|
||||
compressed_buffer.data(),
|
||||
compressed_buffer.size(),
|
||||
raw_buffer.data(),
|
||||
raw_buffer_size,
|
||||
fuzz_safe,
|
||||
check_crc,
|
||||
(OodleLZ_Verbosity)verbosity,
|
||||
nullptr,
|
||||
0,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
0,
|
||||
OodleLZ_Decode_Unthreaded
|
||||
);
|
||||
|
||||
if (res != raw_buffer_size) {
|
||||
std::cerr << "ERROR: Failed to decompress!\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::ofstream out_file(out_name, std::ios::binary);
|
||||
if (!out_file) {
|
||||
std::cerr << "ERROR: Failed to open output file!\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
out_file.write(raw_buffer.data(), res);
|
||||
|
||||
if (out_file.fail()) {
|
||||
std::cerr << "ERROR: Failed to write output file!\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::cout << "INFO: Done!\n";
|
||||
}
|
|
@ -1,31 +0,0 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.3.32929.385
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "oodle-cli", "oodle-cli.vcxproj", "{59D962DA-674C-48D9-ADB5-DE09A89E449A}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|x64 = Debug|x64
|
||||
Debug|x86 = Debug|x86
|
||||
Release|x64 = Release|x64
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{59D962DA-674C-48D9-ADB5-DE09A89E449A}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{59D962DA-674C-48D9-ADB5-DE09A89E449A}.Debug|x64.Build.0 = Debug|x64
|
||||
{59D962DA-674C-48D9-ADB5-DE09A89E449A}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{59D962DA-674C-48D9-ADB5-DE09A89E449A}.Debug|x86.Build.0 = Debug|Win32
|
||||
{59D962DA-674C-48D9-ADB5-DE09A89E449A}.Release|x64.ActiveCfg = Release|x64
|
||||
{59D962DA-674C-48D9-ADB5-DE09A89E449A}.Release|x64.Build.0 = Release|x64
|
||||
{59D962DA-674C-48D9-ADB5-DE09A89E449A}.Release|x86.ActiveCfg = Release|Win32
|
||||
{59D962DA-674C-48D9-ADB5-DE09A89E449A}.Release|x86.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {21081A0D-BD2A-41A1-AE1D-90EBE2E6E87F}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
|
@ -1,140 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>16.0</VCProjectVersion>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<ProjectGuid>{59d962da-674c-48d9-adb5-de09a89e449a}</ProjectGuid>
|
||||
<RootNamespace>oodlecli</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="oodle-cli.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="oodle2.h" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
|
@ -1,27 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Resource Files">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="oodle-cli.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="oodle2.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -1,7 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LocalDebuggerCommandArguments> -v -v -v test\compressed.data 100</LocalDebuggerCommandArguments>
|
||||
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
||||
</PropertyGroup>
|
||||
</Project>
|
287
oodle2.h
287
oodle2.h
|
@ -1,287 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
// header version :
|
||||
// the DLL is incompatible when MAJOR is bumped
|
||||
// MINOR is for internal revs and bug fixes that don't affect API compatibility
|
||||
// TODO: Check if the DLL gives a minor version
|
||||
#define OODLE2_VERSION_MAJOR 8
|
||||
#define OODLE2_VERSION_MINOR 14
|
||||
|
||||
// OodleVersion string is 1 . MAJOR . MINOR
|
||||
#define OodleVersion "2.8.14"
|
||||
|
||||
|
||||
// Default verbosity selection of 0 will not even log when it sees corruption
|
||||
// Verbosity of LZ functions
|
||||
typedef enum OodleLZ_Verbosity {
|
||||
OodleLZ_Verbosity_None = 0,
|
||||
OodleLZ_Verbosity_Minimal = 1,
|
||||
OodleLZ_Verbosity_Some = 2,
|
||||
OodleLZ_Verbosity_Lots = 3,
|
||||
OodleLZ_Verbosity_Force32 = 0x40000000
|
||||
} OodleLZ_Verbosity;
|
||||
|
||||
|
||||
typedef enum OodleLZ_Compressor {
|
||||
OodleLZ_Compressor_Invalid = -1,
|
||||
OodleLZ_Compressor_None = 3, // None = memcpy, pass through uncompressed bytes
|
||||
// NEW COMPRESSORS :
|
||||
OodleLZ_Compressor_Kraken = 8, // Fast decompression and high compression ratios, amazing!
|
||||
OodleLZ_Compressor_Leviathan = 13,// Leviathan = Kraken's big brother with higher compression, slightly slower decompression.
|
||||
OodleLZ_Compressor_Mermaid = 9, // Mermaid is between Kraken & Selkie - crazy fast, still decent compression.
|
||||
OodleLZ_Compressor_Selkie = 11, // Selkie is a super-fast relative of Mermaid. For maximum decode speed.
|
||||
OodleLZ_Compressor_Hydra = 12, // Hydra, the many-headed beast = Leviathan, Kraken, Mermaid, or Selkie (see $OodleLZ_About_Hydra)
|
||||
OodleLZ_Compressor_BitKnit = 10,
|
||||
OodleLZ_Compressor_LZB16 = 4, // DEPRECATED but still supported
|
||||
OodleLZ_Compressor_LZNA = 7,
|
||||
OodleLZ_Compressor_LZH = 0,
|
||||
OodleLZ_Compressor_LZHLW = 1,
|
||||
OodleLZ_Compressor_LZNIB = 2,
|
||||
OodleLZ_Compressor_LZBLW = 5,
|
||||
OodleLZ_Compressor_LZA = 6,
|
||||
OodleLZ_Compressor_Count = 14,
|
||||
OodleLZ_Compressor_Force32 = 0x40000000
|
||||
} OodleLZ_Compressor;
|
||||
|
||||
|
||||
typedef enum OodleLZ_CheckCRC {
|
||||
OodleLZ_CheckCRC_No = 0,
|
||||
OodleLZ_CheckCRC_Yes = 1,
|
||||
OodleLZ_CheckCRC_Force32 = 0x40000000
|
||||
} OodleLZ_CheckCRC;
|
||||
|
||||
/* Selection of compression encoder complexity
|
||||
|
||||
Higher numerical value of CompressionLevel = slower compression, but smaller compressed data.
|
||||
|
||||
The compressed stream is always decodable with the same decompressors.
|
||||
CompressionLevel controls the amount of work the encoder does to find the best compressed bit stream.
|
||||
CompressionLevel does not primary affect decode speed, it trades off encode speed for compressed bit stream quality.
|
||||
|
||||
I recommend starting with OodleLZ_CompressionLevel_Normal, then try up or down if you want
|
||||
faster encoding or smaller output files.
|
||||
|
||||
The Optimal levels are good for distribution when you compress rarely and decompress often;
|
||||
they provide very high compression ratios but are slow to encode. Optimal2 is the recommended level
|
||||
to start with of the optimal levels.
|
||||
Optimal4 and 5 are not recommended for common use, they are very slow and provide the maximum compression ratio,
|
||||
but the gain over Optimal3 is usually small.
|
||||
|
||||
The HyperFast levels have negative numeric CompressionLevel values.
|
||||
They are faster than SuperFast for when you're encoder CPU time constrained or want
|
||||
something closer to symmetric compression vs. decompression time.
|
||||
The HyperFast levels are currently only available in Kraken, Mermaid & Selkie.
|
||||
Higher levels of HyperFast are faster to encode, eg. HyperFast4 is the fastest.
|
||||
|
||||
The CompressionLevel does not affect decode speed much. Higher compression level does not mean
|
||||
slower to decode. To trade off decode speed vs ratio, use _spaceSpeedTradeoffBytes_ in $OodleLZ_CompressOptions
|
||||
*/
|
||||
typedef enum OodleLZ_CompressionLevel {
|
||||
OodleLZ_CompressionLevel_None = 0, // don't compress, just copy raw bytes
|
||||
OodleLZ_CompressionLevel_SuperFast = 1, // super fast mode, lower compression ratio
|
||||
OodleLZ_CompressionLevel_VeryFast = 2, // fastest LZ mode with still decent compression ratio
|
||||
OodleLZ_CompressionLevel_Fast = 3, // fast - good for daily use
|
||||
OodleLZ_CompressionLevel_Normal = 4, // standard medium speed LZ mode
|
||||
|
||||
OodleLZ_CompressionLevel_Optimal1 = 5, // optimal parse level 1 (faster optimal encoder)
|
||||
OodleLZ_CompressionLevel_Optimal2 = 6, // optimal parse level 2 (recommended baseline optimal encoder)
|
||||
OodleLZ_CompressionLevel_Optimal3 = 7, // optimal parse level 3 (slower optimal encoder)
|
||||
OodleLZ_CompressionLevel_Optimal4 = 8, // optimal parse level 4 (very slow optimal encoder)
|
||||
OodleLZ_CompressionLevel_Optimal5 = 9, // optimal parse level 5 (don't care about encode speed, maximum compression)
|
||||
|
||||
OodleLZ_CompressionLevel_HyperFast1 = -1, // faster than SuperFast, less compression
|
||||
OodleLZ_CompressionLevel_HyperFast2 = -2, // faster than HyperFast1, less compression
|
||||
OodleLZ_CompressionLevel_HyperFast3 = -3, // faster than HyperFast2, less compression
|
||||
OodleLZ_CompressionLevel_HyperFast4 = -4, // fastest, less compression
|
||||
|
||||
// aliases :
|
||||
OodleLZ_CompressionLevel_HyperFast = OodleLZ_CompressionLevel_HyperFast1, // alias hyperfast base level
|
||||
OodleLZ_CompressionLevel_Optimal = OodleLZ_CompressionLevel_Optimal2, // alias optimal standard level
|
||||
OodleLZ_CompressionLevel_Max = OodleLZ_CompressionLevel_Optimal5, // maximum compression level
|
||||
OodleLZ_CompressionLevel_Min = OodleLZ_CompressionLevel_HyperFast4, // fastest compression level
|
||||
|
||||
OodleLZ_CompressionLevel_Force32 = 0x40000000,
|
||||
OodleLZ_CompressionLevel_Invalid = OodleLZ_CompressionLevel_Force32
|
||||
} OodleLZ_CompressionLevel;
|
||||
|
||||
|
||||
typedef enum OodleLZ_Decode_ThreadPhase {
|
||||
OodleLZ_Decode_ThreadPhase1 = 1,
|
||||
OodleLZ_Decode_ThreadPhase2 = 2,
|
||||
OodleLZ_Decode_ThreadPhaseAll = 3,
|
||||
OodleLZ_Decode_Unthreaded = OodleLZ_Decode_ThreadPhaseAll
|
||||
} OodleLZ_Decode_ThreadPhase;
|
||||
|
||||
|
||||
typedef enum OodleLZ_FuzzSafe {
|
||||
OodleLZ_FuzzSafe_No = 0,
|
||||
OodleLZ_FuzzSafe_Yes = 1
|
||||
} OodleLZ_FuzzSafe;
|
||||
|
||||
|
||||
/* Compress some data from memory to memory, synchronously, with OodleLZ
|
||||
|
||||
$:compressor which OodleLZ variant to use in compression
|
||||
$:rawBuf raw data to compress
|
||||
$:rawLen number of bytes in rawBuf to compress
|
||||
$:compBuf pointer to write compressed data to ; should be at least $OodleLZ_GetCompressedBufferSizeNeeded
|
||||
$:level OodleLZ_CompressionLevel controls how much CPU effort is put into maximizing compression
|
||||
$:pOptions (optional) options; if NULL, $OodleLZ_CompressOptions_GetDefault is used
|
||||
$:dictionaryBase (optional) if not NULL, provides preceding data to prime the dictionary; must be contiguous with rawBuf, the data between the pointers _dictionaryBase_ and _rawBuf_ is used as the preconditioning data. The exact same precondition must be passed to encoder and decoder.
|
||||
$:lrm (optional) long range matcher
|
||||
$:scratchMem (optional) pointer to scratch memory
|
||||
$:scratchSize (optional) size of scratch memory (see $OodleLZ_GetCompressScratchMemBound)
|
||||
$:return size of compressed data written, or $OODLELZ_FAILED for failure
|
||||
|
||||
Performs synchronous memory to memory LZ compression.
|
||||
|
||||
In tools, you should generally use $OodleXLZ_Compress_AsyncAndWait instead to get parallelism. (in the Oodle2 Ext lib)
|
||||
|
||||
You can compress a large buffer in several calls by setting _dictionaryBase_ to the start
|
||||
of the buffer, and then making _rawBuf_ and _rawLen_ select portions of that buffer. As long
|
||||
as _rawLen_ is a multiple of $OODLELZ_BLOCK_LEN , the compressed chunks can simply be
|
||||
concatenated together.
|
||||
|
||||
If _scratchMem_ is provided, it will be used for the compressor's scratch memory needs before OodleMalloc is
|
||||
called. If the scratch is big enough, no malloc will be done. If the scratch is not big enough, the compress
|
||||
will not fail, instead OodleMalloc will be used. OodleMalloc should not return null. There is currently no way
|
||||
to make compress fail cleanly due to using too much memory, it must either succeed or abort the process.
|
||||
|
||||
If _scratchSize_ is at least $OodleLZ_GetCompressScratchMemBound , additional allocations will not be needed.
|
||||
|
||||
See $OodleLZ_About for tips on setting the compression options.
|
||||
|
||||
If _dictionaryBase_ is provided, the backup distance from _rawBuf_ must be a multiple of $OODLELZ_BLOCK_LEN
|
||||
|
||||
If $(OodleLZ_CompressOptions:seekChunkReset) is enabled, and _dictionaryBase_ is not NULL or _rawBuf_ , then the
|
||||
seek chunk boundaries are relative to _dictionaryBase_, not to _rawBuf_.
|
||||
|
||||
*/
|
||||
extern "C" intptr_t __stdcall OodleLZ_Compress(
|
||||
OodleLZ_Compressor compressor,
|
||||
const void* raw_buffer,
|
||||
size_t raw_len,
|
||||
void* compressed_buffer,
|
||||
OodleLZ_CompressionLevel level,
|
||||
void* options, // Default: null
|
||||
size_t dictionary_base, // Default: null
|
||||
const void* lrm, // Default: null
|
||||
void* scratch_memory, // Default: null
|
||||
size_t scratch_size // Default: null
|
||||
);
|
||||
|
||||
// Decompress returns raw (decompressed) len received
|
||||
// Decompress returns 0 (OODLELZ_FAILED) if it detects corruption
|
||||
/* Decompress a some data from memory to memory, synchronously.
|
||||
|
||||
$:compBuf pointer to compressed data
|
||||
$:compBufSize number of compressed bytes available (must be greater or equal to the number consumed)
|
||||
$:rawBuf pointer to output uncompressed data into
|
||||
$:rawLen number of uncompressed bytes to output
|
||||
$:fuzzSafe (optional) should the decode fail if it contains non-fuzz safe codecs?
|
||||
$:checkCRC (optional) if data could be corrupted and you want to know about it, pass OodleLZ_CheckCRC_Yes
|
||||
$:verbosity (optional) if not OodleLZ_Verbosity_None, logs some info
|
||||
$:decBufBase (optional) if not NULL, provides preceding data to prime the dictionary; must be contiguous with rawBuf, the data between the pointers _dictionaryBase_ and _rawBuf_ is used as the preconditioning data. The exact same precondition must be passed to encoder and decoder. The decBufBase must be a reset point.
|
||||
$:decBufSize (optional) size of decode buffer starting at decBufBase, if 0, _rawLen_ is assumed
|
||||
$:fpCallback (optional) OodleDecompressCallback to call incrementally as decode proceeds
|
||||
$:callbackUserData (optional) passed as userData to fpCallback
|
||||
$:decoderMemory (optional) pre-allocated memory for the Decoder, of size _decoderMemorySize_
|
||||
$:decoderMemorySize (optional) size of the buffer at _decoderMemory_; must be at least $OodleLZDecoder_MemorySizeNeeded bytes to be used
|
||||
$:threadPhase (optional) for threaded decode; see $OodleLZ_About_ThreadPhasedDecode (default OodleLZ_Decode_Unthreaded)
|
||||
$:return the number of decompressed bytes output, $OODLELZ_FAILED (0) if none can be decompressed
|
||||
|
||||
Decodes data encoded with any $OodleLZ_Compressor.
|
||||
|
||||
Note : _rawLen_ must be the actual number of bytes to output, the same as the number that were encoded with the corresponding
|
||||
OodleLZ_Compress size. You must store this somewhere in your own header and pass it in to this call. _compBufSize_ does NOT
|
||||
need to be the exact number of compressed bytes, is the number of bytes available in the buffer, it must be greater or equal to
|
||||
the actual compressed length.
|
||||
|
||||
Note that the new compressors (Kraken,Mermaid,Selkie,BitKnit) are all fuzz safe and you can use OodleLZ_FuzzSafe_Yes
|
||||
with them and no padding of the decode target buffer.
|
||||
|
||||
If checkCRC is OodleLZ_CheckCRC_Yes, then corrupt data will be detected and the decode aborted.
|
||||
|
||||
If checkCRC is OodleLZ_CheckCRC_No, then corruption might result in invalid data, but no detection of any error (garbage in, garbage out).
|
||||
|
||||
If corruption is possible, _fuzzSafe_ is No and _checkCRC_ is OodleLZ_CheckCRC_No, $OodleLZ_GetDecodeBufferSize must be used to allocate
|
||||
_rawBuf_ large enough to prevent overrun.
|
||||
|
||||
$OodleLZ_GetDecodeBufferSize should always be used to ensure _rawBuf_ is large enough, even when corruption is not
|
||||
possible (when fuzzSafe is No).
|
||||
|
||||
_compBuf_ and _rawBuf_ are allowed to overlap for "in place" decoding, but then _rawBuf_ must be allocated to
|
||||
the size given by $OodleLZ_GetInPlaceDecodeBufferSize , and the compressed data must be at the end of that buffer.
|
||||
|
||||
An easy way to take the next step to parallel decoding is with $OodleXLZ_Decompress_MakeSeekTable_Wide_Async (in the Oodle2 Ext lib)
|
||||
|
||||
NOTE : the return value is the *total* number of decompressed bytes output so far. If rawBuf is > decBufBase, that means
|
||||
the initial inset of (rawBuf - decBufBase) is included! (eg. you won't just get _rawLen_)
|
||||
|
||||
If _decBufBase_ is provided, the backup distance from _rawBuf_ must be a multiple of $OODLELZ_BLOCK_LEN
|
||||
|
||||
About fuzz safety:
|
||||
|
||||
OodleLZ_Decompress is guaranteed not to crash even if the data is corrupted when _fuzzSafe_ is set to OodleLZ_FuzzSafe_Yes.
|
||||
|
||||
When _fuzzSafe_ is Yes, the target buffer (_rawBuf_ and _rawLen_) will never be overrun. Note that corrupted data might not
|
||||
be detected (the return value might indicate success).
|
||||
|
||||
Fuzz Safe decodes will not crash on corrupt data. They may or may not return failure, and produce garbage output.
|
||||
|
||||
Fuzz safe decodes will not read out of bounds. They won't put data on the stack or previously in memory
|
||||
into the output buffer.
|
||||
|
||||
Fuzz safe decodes will not output more than the uncompressed size. (eg. the output buffer does not need to
|
||||
be padded like OodleLZ_GetDecodeBufferSize)
|
||||
|
||||
If you ask for a fuzz safe decode and the compressor doesn't satisfy OodleLZ_Compressor_CanDecodeFuzzSafe
|
||||
then it will return failure.
|
||||
|
||||
The _fuzzSafe_ argument should always be OodleLZ_FuzzSafe_Yes as of Oodle 2.9.0 ; older compressors did not
|
||||
support fuzz safety but they now all do.
|
||||
|
||||
Use of OodleLZ_FuzzSafe_No is deprecated.
|
||||
|
||||
*/
|
||||
extern "C" intptr_t __stdcall OodleLZ_Decompress(
|
||||
const void* compressed_buffer,
|
||||
size_t compressed_length,
|
||||
void* raw_buffer,
|
||||
size_t raw_length,
|
||||
OodleLZ_FuzzSafe fuzz_safe, // Default: OodleLZ_FuzzSafe_Yes
|
||||
OodleLZ_CheckCRC check_crc, // Default: OodleLZ_CheckCRC_No
|
||||
OodleLZ_Verbosity verbosity, // Default: OodleLZ_Verbosity_None
|
||||
void* decBufBase, // Default: null
|
||||
size_t decBufSize, // Default: 0
|
||||
void* callback, // Default: null
|
||||
void* callback_user_data, // Default: null
|
||||
void* decoder_memory, // Default: null
|
||||
size_t decoder_memory_size, // Default: 0
|
||||
OodleLZ_Decode_ThreadPhase thread_phase // Default: OodleLZ_Decode_Unthreaded
|
||||
);
|
||||
|
||||
/* Function pointer to Oodle Core printf
|
||||
$:verboseLevel verbosity of the message; 0-2 ; lower = more important
|
||||
$:file C file that sent the message
|
||||
$:line C line that sent the message
|
||||
$:fmt vararg printf format string
|
||||
The logging function installed here must parse varargs like printf.
|
||||
_verboseLevel_ may be used to omit verbose messages.
|
||||
*/
|
||||
extern "C" typedef void(__stdcall t_fp_OodleCore_Plugin_Printf)(int verboseLevel, const char* file, int line, const char* fmt, ...);
|
||||
|
||||
/* Install the callback used by Oodle Core for logging
|
||||
$:fp_rrRawPrintf function pointer to your log function; may be NULL to disable all logging
|
||||
$:return returns the previous function pointer
|
||||
Use this function to install your own printf for Oodle Core.
|
||||
The default implementation in debug builds, if you install nothing, uses the C stdio printf for logging.
|
||||
On Microsoft platforms, it uses OutputDebugString and not stdio.
|
||||
To disable all logging, call OodleCore_Plugins_SetPrintf(NULL)
|
||||
WARNING : this function is NOT thread safe! It should be done only once and done in a place where the caller can guarantee thread safety.
|
||||
In the debug build of Oodle, you can install OodleCore_Plugin_Printf_Verbose to get more verbose logging
|
||||
*/
|
||||
t_fp_OodleCore_Plugin_Printf* __stdcall OodleCore_Plugins_SetPrintf(t_fp_OodleCore_Plugin_Printf* fp_rrRawPrintf);
|
2
rust-toolchain.toml
Normal file
2
rust-toolchain.toml
Normal file
|
@ -0,0 +1,2 @@
|
|||
[toolchain]
|
||||
channel = "nightly"
|
20
rustfmt.toml
Normal file
20
rustfmt.toml
Normal file
|
@ -0,0 +1,20 @@
|
|||
# Copyright (C) 2022 Lucas Schwiderski
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
#
|
||||
unstable_features = true
|
||||
hard_tabs = false
|
||||
max_width = 100
|
||||
edition = "2021"
|
||||
use_field_init_shorthand = true
|
127
src/binary.rs
Normal file
127
src/binary.rs
Normal file
|
@ -0,0 +1,127 @@
|
|||
#![allow(dead_code)]
|
||||
use std::io::{Read, Seek, SeekFrom, Write};
|
||||
|
||||
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
|
||||
use color_eyre::eyre::WrapErr;
|
||||
use color_eyre::{Help, Result, SectionExt};
|
||||
|
||||
fn read_u8_impl<R>(r: &mut R) -> Result<u8>
|
||||
where
|
||||
R: Read,
|
||||
{
|
||||
r.read_u8().wrap_err("failed to read u8")
|
||||
}
|
||||
|
||||
fn read_u32_le_impl<R>(r: &mut R) -> Result<u32>
|
||||
where
|
||||
R: Read,
|
||||
{
|
||||
r.read_u32::<LittleEndian>().wrap_err("failed to read u32")
|
||||
}
|
||||
|
||||
fn read_u64_le_impl<R>(r: &mut R) -> Result<u64>
|
||||
where
|
||||
R: Read,
|
||||
{
|
||||
r.read_u64::<LittleEndian>().wrap_err("failed to read u64")
|
||||
}
|
||||
|
||||
macro_rules! make_read {
|
||||
($func:ident, $op:ident, $type:ty) => {
|
||||
pub(crate) fn $func<R>(r: &mut R) -> Result<$type>
|
||||
where
|
||||
R: Read + Seek,
|
||||
{
|
||||
let res = $op(r);
|
||||
|
||||
if res.is_err() {
|
||||
let pos = r.stream_position();
|
||||
if pos.is_ok() {
|
||||
res.with_section(|| {
|
||||
format!("{pos:#X} ({pos})", pos = pos.unwrap()).header("Position: ")
|
||||
})
|
||||
} else {
|
||||
res
|
||||
}
|
||||
} else {
|
||||
res
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
fn write_u32_le_impl<W>(w: &mut W, val: u32) -> Result<()>
|
||||
where
|
||||
W: Write,
|
||||
{
|
||||
w.write_u32::<LittleEndian>(val)
|
||||
.wrap_err("failed to write u32")
|
||||
}
|
||||
|
||||
macro_rules! make_write {
|
||||
($func:ident, $op:ident, $type:ty) => {
|
||||
pub(crate) fn $func<W>(w: &mut W, val: $type) -> Result<()>
|
||||
where
|
||||
W: Write + Seek,
|
||||
{
|
||||
let res = $op(w, val);
|
||||
|
||||
if res.is_err() {
|
||||
let pos = w.stream_position();
|
||||
if pos.is_ok() {
|
||||
res.with_section(|| {
|
||||
format!("{pos:#X} ({pos})", pos = pos.unwrap()).header("Position: ")
|
||||
})
|
||||
} else {
|
||||
res
|
||||
}
|
||||
} else {
|
||||
res
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
make_read!(read_u8, read_u8_impl, u8);
|
||||
make_read!(read_u32, read_u32_le_impl, u32);
|
||||
make_read!(read_u64, read_u64_le_impl, u64);
|
||||
|
||||
make_write!(write_u32, write_u32_le_impl, u32);
|
||||
|
||||
pub(crate) fn read_up_to<R>(r: &mut R, buf: &mut Vec<u8>) -> Result<usize>
|
||||
where
|
||||
R: Read + Seek,
|
||||
{
|
||||
let pos = r.stream_position()?;
|
||||
|
||||
let err = {
|
||||
match r.read_exact(buf) {
|
||||
Ok(_) => return Ok(buf.len()),
|
||||
Err(err) if err.kind() == std::io::ErrorKind::UnexpectedEof => {
|
||||
r.seek(SeekFrom::Start(pos))?;
|
||||
match r.read_to_end(buf) {
|
||||
Ok(read) => return Ok(read),
|
||||
Err(err) => err,
|
||||
}
|
||||
}
|
||||
Err(err) => err,
|
||||
}
|
||||
};
|
||||
|
||||
Err(err).with_section(|| format!("{pos:#X} ({pos})", pos = pos).header("Position: "))
|
||||
}
|
||||
|
||||
pub fn write_padding<W>(w: &mut W, offset: u64) -> Result<usize>
|
||||
where
|
||||
W: Write + Seek,
|
||||
{
|
||||
let pos = w.stream_position()? + offset;
|
||||
let size = 16 - (pos % 16) as usize;
|
||||
|
||||
if size > 0 && size < 16 {
|
||||
w.seek(SeekFrom::Current(size as i64))?;
|
||||
Ok(size)
|
||||
} else {
|
||||
Ok(0)
|
||||
}
|
||||
}
|
317
src/main.rs
Normal file
317
src/main.rs
Normal file
|
@ -0,0 +1,317 @@
|
|||
#![feature(c_size_t)]
|
||||
|
||||
use std::fs::File;
|
||||
use std::io::{Cursor, Read, Seek, SeekFrom, Write};
|
||||
use std::path::PathBuf;
|
||||
|
||||
use clap::{command, value_parser, Arg, ArgAction, ArgMatches, Command};
|
||||
use color_eyre::eyre::{self, Context};
|
||||
use color_eyre::Result;
|
||||
use tracing_error::ErrorLayer;
|
||||
use tracing_subscriber::prelude::*;
|
||||
use tracing_subscriber::EnvFilter;
|
||||
|
||||
mod binary;
|
||||
mod oodle;
|
||||
mod types;
|
||||
|
||||
use binary::*;
|
||||
use oodle::{Oodle, CHUNK_SIZE};
|
||||
use types::*;
|
||||
|
||||
const LIB_NAME: &str = "oo2core_8_win64";
|
||||
|
||||
#[tracing::instrument]
|
||||
fn main() -> Result<()> {
|
||||
color_eyre::install()?;
|
||||
|
||||
let matches = command!()
|
||||
.about("Perform Oodle 2 compression and decompression for Darktide Bitsquid bundles.")
|
||||
.subcommand_required(true)
|
||||
.arg(
|
||||
Arg::new("verbosity")
|
||||
.help("Set verbosity for the Oodle library.")
|
||||
.global(true)
|
||||
.short('v')
|
||||
.long("verbose")
|
||||
.default_value("none")
|
||||
.value_parser(value_parser!(OodleLZ_Verbosity)),
|
||||
)
|
||||
.arg(
|
||||
Arg::new("library")
|
||||
.help(
|
||||
"Library to load. This may either be:\n\
|
||||
- A library name that will be searched for in the system's default paths.\n\
|
||||
- A file path relative to the current working directory.\n\
|
||||
- An absolute file path.",
|
||||
)
|
||||
.long("library")
|
||||
.default_value(LIB_NAME),
|
||||
)
|
||||
.subcommand(
|
||||
Command::new("compress")
|
||||
.about("Compress an arbitrary binary stream in chunks.")
|
||||
.arg(
|
||||
Arg::new("offset")
|
||||
.help(
|
||||
"The offset of the compressed data stream within the full bundle file.\
|
||||
\nThis needs to be known during decompression to correctly calculate \
|
||||
the padding within each chunk.",
|
||||
)
|
||||
.long("offset")
|
||||
.required(true)
|
||||
.value_parser(value_parser!(u64)),
|
||||
)
|
||||
.arg(
|
||||
Arg::new("in_file")
|
||||
.help("The input file")
|
||||
.required(true)
|
||||
.value_parser(value_parser!(PathBuf)),
|
||||
)
|
||||
.arg(
|
||||
Arg::new("out_file")
|
||||
.help("The output file")
|
||||
.required(true)
|
||||
.value_parser(value_parser!(PathBuf)),
|
||||
),
|
||||
)
|
||||
.subcommand(
|
||||
Command::new("decompress")
|
||||
.about("Decompress a stream of chunks.")
|
||||
.arg(
|
||||
Arg::new("offset")
|
||||
.help(
|
||||
"The offset of the compressed data stream within the full bundle file.\
|
||||
\nThis needs to be known during decompression to correctly calculate \
|
||||
the padding within each chunk.",
|
||||
)
|
||||
.long("offset")
|
||||
.required(true)
|
||||
.value_parser(value_parser!(u64)),
|
||||
)
|
||||
.arg(
|
||||
Arg::new("fuzz_safe")
|
||||
.long("fuzz-safe")
|
||||
.action(ArgAction::SetTrue),
|
||||
)
|
||||
.arg(
|
||||
Arg::new("check_crc")
|
||||
.long("check-crc")
|
||||
.action(ArgAction::SetTrue),
|
||||
)
|
||||
.arg(
|
||||
Arg::new("in_file")
|
||||
.help("The input file")
|
||||
.required(true)
|
||||
.value_parser(value_parser!(PathBuf)),
|
||||
)
|
||||
.arg(
|
||||
Arg::new("out_file")
|
||||
.help("The output file")
|
||||
.required(true)
|
||||
.value_parser(value_parser!(PathBuf)),
|
||||
),
|
||||
)
|
||||
.get_matches();
|
||||
|
||||
{
|
||||
let fmt_layer = tracing_subscriber::fmt::layer().pretty();
|
||||
let filter_layer =
|
||||
EnvFilter::try_from_default_env().or_else(|_| EnvFilter::try_new("info"))?;
|
||||
|
||||
tracing_subscriber::registry()
|
||||
.with(filter_layer)
|
||||
.with(fmt_layer)
|
||||
.with(ErrorLayer::new(
|
||||
tracing_subscriber::fmt::format::Pretty::default(),
|
||||
))
|
||||
.init();
|
||||
}
|
||||
|
||||
let lib = {
|
||||
let name = matches.get_one::<String>("library").unwrap();
|
||||
let lib = Oodle::new(name).wrap_err_with(|| format!("Failed to load library {}", name))?;
|
||||
tracing::info!("Using library {}", name);
|
||||
lib
|
||||
};
|
||||
|
||||
match matches.subcommand() {
|
||||
Some(("compress", sub_matches)) => compress(lib, sub_matches),
|
||||
Some(("decompress", sub_matches)) => decompress(lib, sub_matches),
|
||||
_ => unreachable!(
|
||||
"clap is configured to require a subcommand, and they're all handled above"
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
fn skip_padding<S>(stream: &mut S, offset: u64) -> Result<()>
|
||||
where
|
||||
S: Seek,
|
||||
{
|
||||
let pos = stream.stream_position()? + offset;
|
||||
let padding_size = 16 - (pos % 16);
|
||||
|
||||
tracing::trace!(pos, padding_size);
|
||||
|
||||
if padding_size < 16 && padding_size > 0 {
|
||||
stream.seek(SeekFrom::Current(padding_size as i64))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
fn decompress(lib: Oodle, matches: &ArgMatches) -> Result<()> {
|
||||
let in_path = matches.get_one::<PathBuf>("in_file").unwrap();
|
||||
let out_path = matches.get_one::<PathBuf>("out_file").unwrap();
|
||||
|
||||
tracing::debug!("Reading from '{}'", in_path.display());
|
||||
tracing::debug!("Writing to '{}'", out_path.display());
|
||||
|
||||
let fuzz_safe = OodleLZ_FuzzSafe::from(matches.get_flag("fuzz_safe"));
|
||||
let check_crc = OodleLZ_CheckCRC::from(matches.get_flag("check_crc"));
|
||||
let verbosity = *matches
|
||||
.get_one::<OodleLZ_Verbosity>("verbosity")
|
||||
.unwrap_or(&OodleLZ_Verbosity::None);
|
||||
|
||||
tracing::trace!(?fuzz_safe, ?check_crc, ?verbosity);
|
||||
|
||||
let offset = *matches.get_one::<u64>("offset").unwrap();
|
||||
|
||||
tracing::debug!(offset);
|
||||
|
||||
let mut in_file = File::open(in_path)
|
||||
.wrap_err_with(|| format!("failed to open input file: {}", in_path.display()))?;
|
||||
let mut out_file = File::create(out_path)
|
||||
.wrap_err_with(|| format!("failed to open output file: {}", out_path.display()))?;
|
||||
|
||||
let num_chunks = read_u32(&mut in_file)?;
|
||||
skip_padding(&mut in_file, offset)?;
|
||||
|
||||
tracing::debug!(num_chunks);
|
||||
|
||||
for chunk_index in 0..num_chunks {
|
||||
let _span = tracing::debug_span!("Decompressing chunk", chunk_index);
|
||||
let chunk_size = read_u32(&mut in_file)? as usize;
|
||||
|
||||
tracing::trace!(chunk_size);
|
||||
|
||||
skip_padding(&mut in_file, offset)?;
|
||||
|
||||
let mut compressed_buffer = vec![0u8; CHUNK_SIZE];
|
||||
read_up_to(&mut in_file, &mut compressed_buffer)?;
|
||||
|
||||
// TODO: Optimize to not reallocate?
|
||||
let raw_buffer = lib.decompress(&compressed_buffer, fuzz_safe, check_crc, verbosity)?;
|
||||
|
||||
out_file.write_all(&raw_buffer)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
fn compress(lib: Oodle, matches: &ArgMatches) -> Result<()> {
|
||||
let in_path = matches.get_one::<PathBuf>("in_file").unwrap();
|
||||
let out_path = matches.get_one::<PathBuf>("out_file").unwrap();
|
||||
|
||||
tracing::info!("Reading from '{}'", in_path.display());
|
||||
tracing::info!("Writing to '{}'", out_path.display());
|
||||
|
||||
let offset = *matches.get_one::<u64>("offset").unwrap();
|
||||
|
||||
tracing::debug!(offset);
|
||||
|
||||
let mut out_file = File::create(out_path)
|
||||
.wrap_err_with(|| format!("failed to open output file: {}", out_path.display()))?;
|
||||
|
||||
let mut r = {
|
||||
let mut in_file = File::open(in_path)
|
||||
.wrap_err_with(|| format!("failed to open input file: {}", in_path.display()))?;
|
||||
|
||||
// TODO: Is it faster to check metadata for size and pre-allocate?
|
||||
let mut buf = Vec::new();
|
||||
in_file
|
||||
.read_to_end(&mut buf)
|
||||
.wrap_err("failed to read input file into memory")?;
|
||||
Cursor::new(buf)
|
||||
};
|
||||
|
||||
// I'm not sure how Fatshark does this efficiently.
|
||||
// Within each chunk, there is a padding whos size depends on the position where the padding is
|
||||
// written.
|
||||
// And that position is affected by both the size of previous chunks and the total number of
|
||||
// chunks, since list of chunk sizes is written before all chunks.
|
||||
// Because of that, all chunks have to be compressed and buffered before any of them can be
|
||||
// written to the output.
|
||||
let mut chunks: Vec<Vec<u8>> = Vec::new();
|
||||
|
||||
let mut chunk_index = 0;
|
||||
|
||||
loop {
|
||||
let _span = tracing::info_span!("decompress_chunk", chunk_index);
|
||||
|
||||
let mut raw_buffer = vec![0u8; CHUNK_SIZE];
|
||||
let read = read_up_to(&mut r, &mut raw_buffer)?;
|
||||
|
||||
let is_eof = read < CHUNK_SIZE;
|
||||
|
||||
tracing::debug!(is_eof);
|
||||
|
||||
{
|
||||
let remaining = CHUNK_SIZE - read;
|
||||
if remaining >= 4 {
|
||||
for val in raw_buffer.iter_mut().skip(remaining).take(4) {
|
||||
*val = 0x66;
|
||||
}
|
||||
} else {
|
||||
eyre::bail!(
|
||||
"Not enough space left in buffer to add end marker. \
|
||||
Don't know how to proceed."
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
let compressed = lib
|
||||
.compress(raw_buffer)
|
||||
.wrap_err_with(|| format!("failed to compress chunk {}", chunk_index))?;
|
||||
|
||||
chunks.push(compressed);
|
||||
|
||||
if is_eof {
|
||||
break;
|
||||
}
|
||||
|
||||
chunk_index += 1;
|
||||
}
|
||||
|
||||
let out = &mut out_file;
|
||||
|
||||
write_u32(out, chunks.len() as u32)?;
|
||||
|
||||
{
|
||||
let _span = tracing::trace_span!("write_chunk_sizes");
|
||||
for (chunk_index, chunk) in chunks.iter().enumerate() {
|
||||
tracing::trace!(chunk_index);
|
||||
write_u32(out, chunk.len() as u32)?;
|
||||
}
|
||||
}
|
||||
write_padding(out, offset)?;
|
||||
|
||||
let unpacked_size = chunks.iter().fold(0, |total, chunk| total + chunk.len());
|
||||
write_u32(out, unpacked_size as u32)?;
|
||||
write_u32(out, 0)?;
|
||||
|
||||
{
|
||||
let _span = tracing::trace_span!("write_chunk_data");
|
||||
for (chunk_index, chunk) in chunks.iter().enumerate() {
|
||||
tracing::trace!(chunk_index);
|
||||
write_u32(out, chunk.len() as u32)?;
|
||||
write_padding(out, offset)?;
|
||||
out.write_all(chunk)
|
||||
.wrap_err("failed to write chunk data")?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
104
src/oodle.rs
Normal file
104
src/oodle.rs
Normal file
|
@ -0,0 +1,104 @@
|
|||
use std::ffi::OsStr;
|
||||
use std::ptr;
|
||||
|
||||
use color_eyre::eyre;
|
||||
use color_eyre::Result;
|
||||
use libloading::{Library, Symbol};
|
||||
|
||||
use crate::types::*;
|
||||
|
||||
// Hardcoded chunk size of Bitsquid's bundle compression
|
||||
pub const CHUNK_SIZE: usize = 512 * 1024;
|
||||
|
||||
pub struct Oodle {
|
||||
lib: Library,
|
||||
}
|
||||
|
||||
impl Oodle {
|
||||
pub fn new<P>(lib: P) -> Result<Self>
|
||||
where
|
||||
P: AsRef<OsStr>,
|
||||
{
|
||||
let lib = unsafe { Library::new(lib)? };
|
||||
// TODO: Register librarie's printf
|
||||
Ok(Self { lib })
|
||||
}
|
||||
|
||||
#[tracing::instrument(name = "Oodle::decompress", skip(self, data))]
|
||||
pub fn decompress<I>(
|
||||
&self,
|
||||
data: I,
|
||||
fuzz_safe: OodleLZ_FuzzSafe,
|
||||
check_crc: OodleLZ_CheckCRC,
|
||||
verbosity: OodleLZ_Verbosity,
|
||||
) -> Result<Vec<u8>>
|
||||
where
|
||||
I: AsRef<[u8]>,
|
||||
{
|
||||
let data = data.as_ref();
|
||||
let mut out = vec![0; CHUNK_SIZE];
|
||||
|
||||
let ret = unsafe {
|
||||
let decompress: Symbol<OodleLZ_Decompress> = self.lib.get(b"OodleLZ_Decompress")?;
|
||||
|
||||
decompress(
|
||||
data.as_ptr() as *const _,
|
||||
data.len(),
|
||||
out.as_mut_ptr() as *mut _,
|
||||
out.len(),
|
||||
fuzz_safe,
|
||||
check_crc,
|
||||
verbosity,
|
||||
ptr::null_mut(),
|
||||
0,
|
||||
ptr::null_mut(),
|
||||
ptr::null_mut(),
|
||||
ptr::null_mut(),
|
||||
0,
|
||||
OodleLZ_Decode_ThreadPhase::UNTHREADED,
|
||||
)
|
||||
};
|
||||
|
||||
if ret < CHUNK_SIZE as u64 {
|
||||
eyre::bail!("Failed to decompress chunk.");
|
||||
}
|
||||
|
||||
Ok(out)
|
||||
}
|
||||
|
||||
#[tracing::instrument(name = "Oodle::compress", skip(self, data))]
|
||||
pub fn compress<I>(&self, data: I) -> Result<Vec<u8>>
|
||||
where
|
||||
I: AsRef<[u8]>,
|
||||
{
|
||||
let raw = data.as_ref();
|
||||
// TODO: Query oodle for buffer size
|
||||
let mut out = vec![0u8; CHUNK_SIZE];
|
||||
|
||||
let compressor = OodleLZ_Compressor::Kraken;
|
||||
let level = OodleLZ_CompressionLevel::Optimal2;
|
||||
|
||||
let ret = unsafe {
|
||||
let compress: Symbol<OodleLZ_Compress> = self.lib.get(b"OodleLZ_Compress")?;
|
||||
|
||||
compress(
|
||||
compressor,
|
||||
raw.as_ptr() as *const _,
|
||||
raw.len(),
|
||||
out.as_mut_ptr() as *mut _,
|
||||
level,
|
||||
ptr::null_mut(),
|
||||
0,
|
||||
ptr::null_mut(),
|
||||
ptr::null_mut(),
|
||||
0,
|
||||
)
|
||||
};
|
||||
|
||||
if ret == 0 {
|
||||
eyre::bail!("Failed to compress chunk.");
|
||||
}
|
||||
|
||||
Ok(out)
|
||||
}
|
||||
}
|
190
src/types.rs
Normal file
190
src/types.rs
Normal file
|
@ -0,0 +1,190 @@
|
|||
#![allow(dead_code)]
|
||||
use core::ffi::{c_char, c_int, c_size_t, c_ulonglong, c_void};
|
||||
|
||||
use clap::ValueEnum;
|
||||
|
||||
// Type definitions taken from Unreal Engine's `oodle2.h`
|
||||
|
||||
#[repr(C)]
|
||||
#[allow(non_camel_case_types)]
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub enum OodleLZ_FuzzSafe {
|
||||
No = 0,
|
||||
Yes = 1,
|
||||
}
|
||||
|
||||
impl From<bool> for OodleLZ_FuzzSafe {
|
||||
fn from(value: bool) -> Self {
|
||||
if value {
|
||||
Self::Yes
|
||||
} else {
|
||||
Self::No
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[allow(non_camel_case_types)]
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub enum OodleLZ_CheckCRC {
|
||||
No = 0,
|
||||
Yes = 1,
|
||||
Force32 = 0x40000000,
|
||||
}
|
||||
|
||||
impl From<bool> for OodleLZ_CheckCRC {
|
||||
fn from(value: bool) -> Self {
|
||||
if value {
|
||||
Self::Yes
|
||||
} else {
|
||||
Self::No
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[allow(non_camel_case_types)]
|
||||
#[derive(Clone, Copy, Debug, ValueEnum)]
|
||||
pub enum OodleLZ_Verbosity {
|
||||
None = 0,
|
||||
Minimal = 1,
|
||||
Some = 2,
|
||||
Lots = 3,
|
||||
#[clap(hide = true)]
|
||||
Force32 = 0x40000000,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[allow(non_camel_case_types)]
|
||||
#[derive(Clone, Copy, Debug, ValueEnum)]
|
||||
pub enum OodleLZ_Decode_ThreadPhase {
|
||||
Phase1 = 1,
|
||||
Phase2 = 2,
|
||||
PhaseAll = 3,
|
||||
}
|
||||
|
||||
impl OodleLZ_Decode_ThreadPhase {
|
||||
pub const UNTHREADED: Self = OodleLZ_Decode_ThreadPhase::PhaseAll;
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[allow(non_camel_case_types)]
|
||||
#[derive(Clone, Copy, Debug, ValueEnum)]
|
||||
pub enum OodleLZ_Compressor {
|
||||
#[clap(hide = true)]
|
||||
Invalid = -1,
|
||||
// None = memcpy, pass through uncompressed bytes
|
||||
None = 3,
|
||||
|
||||
// NEW COMPRESSORS:
|
||||
// Fast decompression and high compression ratios, amazing!
|
||||
Kraken = 8,
|
||||
// Leviathan = Kraken's big brother with higher compression, slightly slower decompression.
|
||||
Leviathan = 13,
|
||||
// Mermaid is between Kraken & Selkie - crazy fast, still decent compression.
|
||||
Mermaid = 9,
|
||||
// Selkie is a super-fast relative of Mermaid. For maximum decode speed.
|
||||
Selkie = 11,
|
||||
// Hydra, the many-headed beast = Leviathan, Kraken, Mermaid, or Selkie (see $OodleLZ_About_Hydra)
|
||||
Hydra = 12,
|
||||
BitKnit = 10,
|
||||
// DEPRECATED but still supported
|
||||
Lzb16 = 4,
|
||||
Lzna = 7,
|
||||
Lzh = 0,
|
||||
Lzhlw = 1,
|
||||
Lznib = 2,
|
||||
Lzblw = 5,
|
||||
Lza = 6,
|
||||
Count = 14,
|
||||
#[clap(hide = true)]
|
||||
Force32 = 0x40000000,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[allow(non_camel_case_types)]
|
||||
#[derive(Clone, Copy, Debug, ValueEnum)]
|
||||
pub enum OodleLZ_CompressionLevel {
|
||||
// don't compress, just copy raw bytes
|
||||
None = 0,
|
||||
// super fast mode, lower compression ratio
|
||||
SuperFast = 1,
|
||||
// fastest LZ mode with still decent compression ratio
|
||||
VeryFast = 2,
|
||||
// fast - good for daily use
|
||||
Fast = 3,
|
||||
// standard medium speed LZ mode
|
||||
Normal = 4,
|
||||
// optimal parse level 1 (faster optimal encoder)
|
||||
Optimal1 = 5,
|
||||
// optimal parse level 2 (recommended baseline optimal encoder)
|
||||
Optimal2 = 6,
|
||||
// optimal parse level 3 (slower optimal encoder)
|
||||
Optimal3 = 7,
|
||||
// optimal parse level 4 (very slow optimal encoder)
|
||||
Optimal4 = 8,
|
||||
// optimal parse level 5 (don't care about encode speed, maximum compression)
|
||||
Optimal5 = 9,
|
||||
// faster than SuperFast, less compression
|
||||
HyperFast1 = -1,
|
||||
// faster than HyperFast1, less compression
|
||||
HyperFast2 = -2,
|
||||
// faster than HyperFast2, less compression
|
||||
HyperFast3 = -3,
|
||||
// fastest, less compression
|
||||
HyperFast4 = -4,
|
||||
#[clap(hide = true)]
|
||||
Force32 = 0x40000000,
|
||||
}
|
||||
|
||||
impl OodleLZ_CompressionLevel {
|
||||
// alias hyperfast base level
|
||||
pub const HYPERFAST: Self = OodleLZ_CompressionLevel::HyperFast1;
|
||||
// alias optimal standard level
|
||||
pub const OPTIMAL: Self = OodleLZ_CompressionLevel::Optimal2;
|
||||
// maximum compression level
|
||||
pub const MAX: Self = OodleLZ_CompressionLevel::Optimal5;
|
||||
// fastest compression level
|
||||
pub const MIN: Self = OodleLZ_CompressionLevel::HyperFast4;
|
||||
pub const INVALID: Self = OodleLZ_CompressionLevel::Force32;
|
||||
}
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
pub type t_fp_OodleCore_Plugin_Printf =
|
||||
extern "C" fn(level: c_int, file: *mut c_char, line: c_int, fmt: *mut c_char) -> c_void;
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
pub type OodleLZ_Decompress = extern "C" fn(
|
||||
compressed_buffer: *const c_void,
|
||||
compressed_length: c_size_t,
|
||||
raw_buffer: *mut c_void,
|
||||
raw_length: c_size_t,
|
||||
fuzz_safe: OodleLZ_FuzzSafe,
|
||||
check_crc: OodleLZ_CheckCRC,
|
||||
verbosity: OodleLZ_Verbosity,
|
||||
decBufBase: *mut c_void,
|
||||
decBufSize: c_size_t,
|
||||
callback: *const c_void,
|
||||
callback_user_data: *const c_void,
|
||||
decoder_memory: *mut c_void,
|
||||
decoder_memory_size: c_size_t,
|
||||
thread_phase: OodleLZ_Decode_ThreadPhase,
|
||||
) -> c_ulonglong;
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
pub type OodleLZ_Compress = extern "C" fn(
|
||||
compressor: OodleLZ_Compressor,
|
||||
raw_buffer: *const c_void,
|
||||
raw_len: c_size_t,
|
||||
compressed_buffer: *mut c_void,
|
||||
level: OodleLZ_CompressionLevel,
|
||||
options: *const c_void,
|
||||
dictionary_base: c_size_t,
|
||||
lrm: *const c_void,
|
||||
scratch_memory: *mut c_void,
|
||||
scratch_size: c_size_t,
|
||||
) -> c_ulonglong;
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
pub type OodleCore_Plugins_SetPrintf =
|
||||
extern "C" fn(f: t_fp_OodleCore_Plugin_Printf) -> t_fp_OodleCore_Plugin_Printf;
|
Reference in a new issue