diff --git a/Cargo.lock b/Cargo.lock index 40422e2..80c14cc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -116,9 +116,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.15" +version = "0.6.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526" +checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" dependencies = [ "anstyle", "anstyle-parse", @@ -131,36 +131,36 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.8" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" +checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" [[package]] name = "anstyle-parse" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb" +checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.1.1" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a" +checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.4" +version = "3.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8" +checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125" dependencies = [ "anstyle", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -274,7 +274,7 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn 2.0.82", + "syn 2.0.89", ] [[package]] @@ -325,9 +325,9 @@ checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] name = "bytemuck" -version = "1.19.0" +version = "1.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8334215b81e418a0a7bdb8ef0849474f40bb10c8b71f1c4ed315cff49f32494d" +checksum = "8b37c88a63ffd85d15b406896cc343916d7cf57838a847b3a6f2ca5d39a5695a" [[package]] name = "byteorder" @@ -343,9 +343,9 @@ checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" [[package]] name = "bytes" -version = "1.7.2" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" +checksum = "9ac0150caa2ae65ca5bd83f25c7de183dea78d4d366469f148435e2acfbad0da" [[package]] name = "cairo-sys-rs" @@ -389,9 +389,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.1.31" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2e7962b54006dcfcc61cb72735f4d89bb97061dd6a7ed882ec6b8ee53714c6f" +checksum = "fd9de9f2205d5ef3fd67e685b0df337994ddd4495e2a28d185500d0e1edfea47" dependencies = [ "jobserver", "libc", @@ -517,9 +517,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.20" +version = "4.5.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b97f376d85a664d5837dbae44bf546e6477a679ff6610010f17276f686d867e8" +checksum = "fb3b4b9e5a7c7514dfa52869339ee98b3156b0bfb4e8a77c4ff4babb64b1604f" dependencies = [ "clap_builder", "clap_derive", @@ -527,9 +527,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.20" +version = "4.5.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19bc80abd44e4bed93ca373a0704ccbd1b710dc5749406201bb018272808dc54" +checksum = "b17a95aa67cc7b5ebd32aa5370189aa0d79069ef1c64ce893bd30fb24bff20ec" dependencies = [ "anstream", "anstyle", @@ -546,14 +546,14 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.82", + "syn 2.0.89", ] [[package]] name = "clap_lex" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" +checksum = "afb84c814227b90d6895e01398aee0d8033c00e7466aca416fb6a8e0eb19d8a7" [[package]] name = "clipboard-win" @@ -567,9 +567,9 @@ dependencies = [ [[package]] name = "cmake" -version = "0.1.51" +version = "0.1.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb1e43aa7fd152b1f968787f7dbcdeb306d1867ff373c69955211876c053f91a" +checksum = "c682c223677e0e5b6b7f63a64b9351844c3f1b1678a68b7ee617e30fb082620e" dependencies = [ "cc", ] @@ -628,9 +628,9 @@ checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" [[package]] name = "colorchoice" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" +checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" [[package]] name = "combine" @@ -834,7 +834,7 @@ dependencies = [ "anes", "cast", "ciborium", - "clap 4.5.20", + "clap 4.5.21", "criterion-plot", "is-terminal", "itertools 0.10.5", @@ -968,6 +968,17 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.89", +] + [[package]] name = "dlib" version = "0.5.2" @@ -999,9 +1010,9 @@ dependencies = [ [[package]] name = "dynasm" -version = "3.0.0" +version = "3.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "767de053f78ef46295114c1d3bd46dff9e2542c817c9c0f313f2a6a95eaad2de" +checksum = "697c04882d6b25c9eb2583d2737bea1947a28c9d7544dddec76d85e6e1545c92" dependencies = [ "bitflags 2.6.0", "byteorder", @@ -1009,14 +1020,14 @@ dependencies = [ "proc-macro-error2", "proc-macro2", "quote", - "syn 2.0.82", + "syn 2.0.89", ] [[package]] name = "dynasmrt" -version = "3.0.0" +version = "3.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f814029fdd01bc8c85a5783a10932b25edae8d22f25d3152db086a6f444538d8" +checksum = "1718a074cf8317b3509228d7ea9a99d7014b17483109d701c733699065fe5e35" dependencies = [ "byteorder", "dynasm", @@ -1045,9 +1056,9 @@ dependencies = [ [[package]] name = "embed-resource" -version = "2.5.0" +version = "2.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4e24052d7be71f0efb50c201557f6fe7d237cfd5a64fd5bcd7fd8fe32dbbffa" +checksum = "b68b6f9f63a0b6a38bc447d4ce84e2b388f3ec95c99c641c8ff0dd3ef89a6379" dependencies = [ "cc", "memchr", @@ -1118,18 +1129,18 @@ dependencies = [ [[package]] name = "fdeflate" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8090f921a24b04994d9929e204f50b498a33ea6ba559ffaa05e04f7ee7fb5ab" +checksum = "07c6f4c64c1d33a3111c4466f7365ebdcc37c5bd1ea0d62aae2e3d722aacbedb" dependencies = [ "simd-adler32", ] [[package]] name = "flate2" -version = "1.0.34" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1b589b4dc103969ad3cf85c950899926ec64300a1a46d76c03a6072957036f0" +checksum = "c936bfdafb507ebbf50b8074c54fa31c5be9a1e7e5f467dd659697041407d07c" dependencies = [ "crc32fast", "miniz_oxide", @@ -1154,9 +1165,9 @@ dependencies = [ [[package]] name = "flexi_logger" -version = "0.29.3" +version = "0.29.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "719236bdbcf6033a3395165f797076b31056018e6723ccff616eb25fc9c99de1" +checksum = "d26948e37cfcb1f2c2cd38e0602d3a8ab6b9472c0c6eff4516fc8def9a3124d7" dependencies = [ "chrono", "log", @@ -1236,7 +1247,7 @@ checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" dependencies = [ "proc-macro2", "quote", - "syn 2.0.82", + "syn 2.0.89", ] [[package]] @@ -1338,7 +1349,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.82", + "syn 2.0.89", ] [[package]] @@ -1453,9 +1464,9 @@ dependencies = [ name = "gameroy-native" version = "0.3.1" dependencies = [ - "clap 4.5.20", - "embed-resource 2.5.0", - "flexi_logger 0.29.3", + "clap 4.5.21", + "embed-resource 2.5.1", + "flexi_logger 0.29.6", "gameroy", "gameroy-jit", "log", @@ -1716,9 +1727,9 @@ checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" [[package]] name = "hashbrown" -version = "0.15.0" +version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" [[package]] name = "heck" @@ -1785,6 +1796,124 @@ dependencies = [ "cc", ] +[[package]] +name = "icu_collections" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locid" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_locid_transform" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_locid_transform_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_locid_transform_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" + +[[package]] +name = "icu_normalizer" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "utf16_iter", + "utf8_iter", + "write16", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" + +[[package]] +name = "icu_properties" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_locid_transform", + "icu_properties_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" + +[[package]] +name = "icu_provider" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_provider_macros", + "stable_deref_trait", + "tinystr", + "writeable", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_provider_macros" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.89", +] + [[package]] name = "ident_case" version = "1.0.1" @@ -1793,19 +1922,30 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "idna" -version = "0.5.0" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" dependencies = [ - "unicode-bidi", - "unicode-normalization", + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" +dependencies = [ + "icu_normalizer", + "icu_properties", ] [[package]] name = "image" -version = "0.25.4" +version = "0.25.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc144d44a31d753b02ce64093d532f55ff8dc4ebf2ffb8a63c0dda691385acae" +checksum = "cd6f44aed642f18953a158afeb30206f4d50da59fbc66ecb53c66488de73563b" dependencies = [ "bytemuck", "byteorder-lite", @@ -1836,7 +1976,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ "equivalent", - "hashbrown 0.15.0", + "hashbrown 0.15.2", ] [[package]] @@ -1887,9 +2027,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.11" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" +checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" [[package]] name = "jni" @@ -2000,9 +2140,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.161" +version = "0.2.166" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1" +checksum = "c2ccc108bbc0b1331bd061864e7cd823c0cab660bbe6970e66e2c0614decde36" [[package]] name = "libloading" @@ -2030,6 +2170,12 @@ version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" +[[package]] +name = "litemap" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104" + [[package]] name = "lock_api" version = "0.4.12" @@ -2600,9 +2746,9 @@ checksum = "5be167a7af36ee22fe3115051bc51f6e6c7054c9348e28deb4f49bd6f705a315" [[package]] name = "pin-project-lite" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" +checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff" [[package]] name = "pin-utils" @@ -2695,14 +2841,14 @@ dependencies = [ "proc-macro-error-attr2", "proc-macro2", "quote", - "syn 2.0.82", + "syn 2.0.89", ] [[package]] name = "proc-macro2" -version = "1.0.88" +version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c3a7fc5db1e57d5a779a352c8cdb57b29aa4c40cc69c3a68a7fedc815fbf2f9" +checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" dependencies = [ "unicode-ident", ] @@ -2807,9 +2953,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.11.0" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38200e5ee88914975b69f657f0801b6f6dccafd44fd9326302a4aaeecfacb1d8" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" dependencies = [ "aho-corasick", "memchr", @@ -2819,9 +2965,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.8" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" dependencies = [ "aho-corasick", "memchr", @@ -2941,9 +3087,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.37" +version = "0.38.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8acb788b847c24f28525660c4d7758620a7210875711f79e7f663cc152726811" +checksum = "d7f649912bc1495e167a6edee79151c84b1bad49748cb4f1f1167f459f6224f6" dependencies = [ "bitflags 2.6.0", "errno", @@ -3030,29 +3176,29 @@ checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" [[package]] name = "serde" -version = "1.0.210" +version = "1.0.215" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" +checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.210" +version = "1.0.215" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" +checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.82", + "syn 2.0.89", ] [[package]] name = "serde_json" -version = "1.0.132" +version = "1.0.133" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d726bfaff4b320266d395898905d0eba0345aae23b54aee3a737e260fd46db03" +checksum = "c7fceb2473b9166b2294ef05efcb65a3db80803f0b03ef86a5fc88a2b85ee377" dependencies = [ "itoa", "memchr", @@ -3217,6 +3363,12 @@ dependencies = [ "winit 0.27.5", ] +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + [[package]] name = "stdweb" version = "0.1.3" @@ -3273,15 +3425,26 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.82" +version = "2.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83540f837a8afc019423a8edb95b52a8effe46957ee402287f4292fae35be021" +checksum = "44d46482f1c1c87acd84dea20c1bf5ebff4c757009ed6bf19cfd36fb10e92c4e" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] +[[package]] +name = "synstructure" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.89", +] + [[package]] name = "system-deps" version = "6.2.2" @@ -3347,22 +3510,22 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.64" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.64" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.82", + "syn 2.0.89", ] [[package]] @@ -3434,6 +3597,16 @@ dependencies = [ "strict-num", ] +[[package]] +name = "tinystr" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" +dependencies = [ + "displaydoc", + "zerovec", +] + [[package]] name = "tinytemplate" version = "1.2.1" @@ -3557,9 +3730,9 @@ checksum = "2281c8c1d221438e373249e065ca4989c4c36952c211ff21a0ee91c44a3869e7" [[package]] name = "unicode-ident" -version = "1.0.13" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" +checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" [[package]] name = "unicode-linebreak" @@ -3567,15 +3740,6 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f" -[[package]] -name = "unicode-normalization" -version = "0.1.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" -dependencies = [ - "tinyvec", -] - [[package]] name = "unicode-script" version = "0.5.7" @@ -3614,9 +3778,9 @@ dependencies = [ [[package]] name = "url" -version = "2.5.2" +version = "2.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" +checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" dependencies = [ "form_urlencoded", "idna", @@ -3690,6 +3854,18 @@ dependencies = [ "tiny-skia-path 0.10.0", ] +[[package]] +name = "utf16_iter" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + [[package]] name = "utf8parse" version = "0.2.2" @@ -3772,7 +3948,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.82", + "syn 2.0.89", "wasm-bindgen-shared", ] @@ -3806,7 +3982,7 @@ checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" dependencies = [ "proc-macro2", "quote", - "syn 2.0.82", + "syn 2.0.89", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -4429,6 +4605,18 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "write16" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" + +[[package]] +name = "writeable" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" + [[package]] name = "x11-clipboard" version = "0.7.1" @@ -4479,9 +4667,9 @@ checksum = "0ef33da6b1660b4ddbfb3aef0ade110c8b8a781a3b6382fa5f2b5b040fd55f61" [[package]] name = "xml-rs" -version = "0.8.22" +version = "0.8.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af4e2e2f7cba5a093896c1e150fbfe177d1883e7448200efb81d40b9d339ef26" +checksum = "af310deaae937e48a26602b730250b4949e125f468f11e6990be3e5304ddd96f" [[package]] name = "xmlparser" @@ -4495,6 +4683,30 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec7a2a501ed189703dba8b08142f057e887dfc4b2cc4db2d343ac6376ba3e0b9" +[[package]] +name = "yoke" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" +dependencies = [ + "serde", + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.89", + "synstructure", +] + [[package]] name = "zerocopy" version = "0.7.35" @@ -4513,5 +4725,48 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.82", + "syn 2.0.89", +] + +[[package]] +name = "zerofrom" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cff3ee08c995dee1859d998dea82f7374f2826091dd9cd47def953cae446cd2e" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.89", + "synstructure", +] + +[[package]] +name = "zerovec" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.89", ] diff --git a/core/src/gameboy/cartridge.rs b/core/src/gameboy/cartridge.rs index 397be68..e553d2b 100644 --- a/core/src/gameboy/cartridge.rs +++ b/core/src/gameboy/cartridge.rs @@ -1,4 +1,4 @@ -use std::{convert::TryInto, io::Read}; +use std::{convert::TryInto, fmt::Write, io::Read}; use crate::save_state::{LoadStateError, SaveState, SaveStateContext}; @@ -8,6 +8,31 @@ const NINTENDOO_LOGO: [u8; 48] = [ 0xBB, 0xBB, 0x67, 0x63, 0x6E, 0x0E, 0xEC, 0xCC, 0xDD, 0xDC, 0x99, 0x9F, 0xBB, 0xB9, 0x33, 0x3E, ]; +// The size of the ROM in bytes, for each type of ROM size. +const ROM_SIZES: &[usize] = &[ + 2 * 0x4000, // no ROM Banking + 4 * 0x4000, + 8 * 0x4000, + 16 * 0x4000, + 32 * 0x4000, + 64 * 0x4000, + 128 * 0x4000, + 256 * 0x4000, + 512 * 0x4000, + // 72 * 0x2000, + // 80 * 0x2000, + // 96 * 0x2000, +]; + +const RAM_SIZES: &[usize] = &[ + 0, + 0x800, + 0x2000, // Single Bank + 4 * 0x2000, + 16 * 0x2000, + 8 * 0x2000, +]; + fn mbc_type_name(code: u8) -> &'static str { match code { 0x00 => "ROM ONLY", @@ -114,27 +139,9 @@ impl CartridgeHeader { self.logo[..0x18] == NINTENDOO_LOGO[..0x18] } - pub fn rom_size_in_bytes(&self) -> Result { - let rom_sizes = [ - 2 * 0x4000, // no ROM Banking - 4 * 0x4000, - 8 * 0x4000, - 16 * 0x4000, - 32 * 0x4000, - 64 * 0x4000, - 128 * 0x4000, - 256 * 0x4000, - 512 * 0x4000, - // 72 * 0x2000, - // 80 * 0x2000, - // 96 * 0x2000, - ]; + pub fn rom_size_in_bytes(&self) -> Option { let rom_size_type = self.rom_size; - let rom_size = rom_sizes - .get(rom_size_type as usize) - .copied() - .ok_or_else(|| format!("Rom size '{:02x}' is no supported", rom_size_type))?; - Ok(rom_size) + ROM_SIZES.get(rom_size_type as usize).copied() } pub fn title_as_string(&self) -> String { @@ -159,6 +166,174 @@ enum Mbc { Mbc5(Mbc5), } +enum MbcKind { + Mbc0, + Mbc1, + Mbc1M, + Mbc2, + Mbc3, + Mbc5, +} + +pub struct MbcSpecification { + // The mbc type, as indicated in the cartridge header. + kind: MbcKind, + // The rom size, in bytes. Should be a value in ROM_SIZES. + rom_size: usize, + // The ram size, in bytes. Should be a value in RAM_SIZES. + ram_size: usize, +} + +impl MbcSpecification { + fn from_str(string: &str) -> Result { + let mut parts = string.split(','); + + let error_message = "expected 3 comma separated values"; + + let kind = parts.next().ok_or(error_message)?; + let rom_size = parts.next().ok_or(error_message)?; + let ram_size = parts.next().ok_or(error_message)?; + + if parts.next().is_some() { + return Err(error_message.to_string()); + } + + let kind = match kind { + "MBC1" => MbcKind::Mbc1, + "MBC1M" => MbcKind::Mbc1M, + "MBC2" => MbcKind::Mbc2, + "MBC3" => MbcKind::Mbc3, + "MBC5" => MbcKind::Mbc5, + _ => return Err(format!("invalid mbc type '{}'", kind)), + }; + + let rom_size = crate::parser::parse_size(rom_size) + .ok() + .or_else(|| crate::parser::parse_number(rom_size).ok()) + .ok_or_else(|| format!("invalid rom size '{}'", rom_size))? + as usize; + + ROM_SIZES + .iter() + .find(|&&x| x == rom_size) + .ok_or_else(|| format!("invalid rom size '{}'", rom_size))?; + + let ram_size = crate::parser::parse_size(ram_size) + .ok() + .or_else(|| crate::parser::parse_number(ram_size).ok()) + .ok_or_else(|| format!("invalid ram size '{}'", ram_size))? + as usize; + + RAM_SIZES + .iter() + .find(|&&x| x == ram_size) + .ok_or_else(|| format!("invalid ram size '{}'", ram_size))?; + + Ok(Self { + kind, + rom_size, + ram_size, + }) + } + + fn from_header(header: &CartridgeHeader, error: &mut String, rom: &[u8]) -> Option { + let rom_size = header + .rom_size_in_bytes() + .ok_or_else(|| format!("Rom size type '{:02x}' is not supported", header.rom_size)); + + let rom_size = match rom_size { + Ok(rom_size) if rom_size != rom.len() => { + let size = *ROM_SIZES.iter().find(|&&x| x >= rom.len()).unwrap(); + writeln!( + error, + "The ROM header expected rom size as '{}' bytes, but the given rom has '{}' bytes. Deducing size from ROM size as {}.", + rom_size, + rom.len(), + size, + ).unwrap(); + size + } + Ok(size) => size, + Err(err) => { + let size = *ROM_SIZES.iter().find(|&&x| x >= rom.len()).unwrap(); + writeln!(error, "{}, deducing size from ROM size as {}", err, size,).unwrap(); + size + } + }; + + // Cartridge Type + let mbc_kind = header.cartridge_type; + let kind = match mbc_kind { + 0 | 8 | 9 => MbcKind::Mbc0, + 1..=3 => 'mbc1: { + // Detect if it is a MBC1M card + if header.rom_size == 5 { + let mut number_of_games = 0; + for i in 0..4 { + let header = match CartridgeHeader::from_bytes(&rom[i * 0x40000..]) { + Ok(x) | Err((Some(x), _)) => x, + Err((None, _)) => continue, + }; + if header.check_logo() { + number_of_games += 1; + } + } + // multicarts will have, at least, a game selecion screen, and two other games. + if number_of_games >= 3 { + break 'mbc1 MbcKind::Mbc1M; + } + } + MbcKind::Mbc1 + } + 5 | 6 => MbcKind::Mbc2, + 0x0F..=0x13 => MbcKind::Mbc3, + 0x19..=0x1E => MbcKind::Mbc5, + _ => { + writeln!( + error, + "MBC type '{}' ({:02x}) is not supported", + mbc_type_name(mbc_kind), + mbc_kind + ) + .unwrap(); + return None; + } + }; + + let ram_size_type = header.ram_size; + + let ram_size = if let MbcKind::Mbc2 = kind { + if ram_size_type != 0 { + writeln!( + error, + "Cartridge use MBC2, with a integrated ram (type '00'), but report the ram type '{:02x}'", + ram_size_type, + ).unwrap(); + } + 0x200 + } else { + match RAM_SIZES.get(ram_size_type as usize).copied() { + Some(x) => x, + None => { + writeln!( + error, + "Ram size type '{:02x}' is not supported, using RAM size as 0x2000", + ram_size_type, + ) + .unwrap(); + 0x2000 + } + } + }; + + Some(Self { + kind, + rom_size, + ram_size, + }) + } +} + #[derive(PartialEq, Eq, Clone)] pub struct Cartridge { pub header: CartridgeHeader, @@ -170,6 +345,21 @@ pub struct Cartridge { pub ram: Vec, mbc: Mbc, } + +impl std::fmt::Debug for Cartridge { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("Cartridge") + // .field("header", &self.header) + .field("lower_bank", &self.lower_bank) + .field("upper_bank", &self.upper_bank) + .field("rom.len()", &self.rom.len()) + .field("ram.len()", &self.ram.len()) + // .field("mbc", &self.mbc) + .field("kind_name", &self.kind_name()) + .finish() + } +} + impl SaveState for Cartridge { fn save_state( &self, @@ -207,89 +397,79 @@ impl SaveState for Cartridge { Ok(()) } } + +#[allow(clippy::result_large_err)] impl Cartridge { - pub fn new(rom: Vec) -> Result { - let header = match CartridgeHeader::from_bytes(&rom) { - Ok(x) | Err((Some(x), _)) => x, - Err((None, err)) => return Err(err), - }; + pub fn new(rom: Vec) -> Result)> { + Self::new_maybe_with_spec(rom, None) + } - let rom_size = header.rom_size_in_bytes()?; + pub fn new_with_spec_str( + rom: Vec, + spec: Option<&str>, + ) -> Result)> { + Self::new_maybe_with_spec( + rom, + match spec { + None => None, + Some(spec) => Some(MbcSpecification::from_str(spec).map_err(|x| (x, None))?), + }, + ) + } - if rom_size != rom.len() { - return Err(format!( - "In the rom header the expected size is '{}' bytes, but the given rom has '{}' bytes", - rom_size, - rom.len() - )); - } + /// Create a new cartridge from the given ROM. If the ROM is invalid, return the a error + /// message and a deduced cartridge, if possible. + fn new_maybe_with_spec( + mut rom: Vec, + spec: Option, + ) -> Result)> { + let mut error = String::new(); - // Cartridge Type - let mbc_kind = header.cartridge_type; - let mbc = match mbc_kind { - 0 | 8 | 9 => Mbc::None(Mbc0 {}), - 1..=3 => 'mbc1: { - // Detect if it is a MBC1M card - if header.rom_size == 5 { - let mut number_of_games = 0; - for i in 0..4 { - let header = match CartridgeHeader::from_bytes(&rom[i * 0x40000..]) { - Ok(x) | Err((Some(x), _)) => x, - Err((None, _)) => continue, - }; - if header.check_logo() { - number_of_games += 1; - } - } - // multicarts will have, at least, a game selecion screen, and two other games. - if number_of_games >= 3 { - break 'mbc1 Mbc::Mbc1M(Mbc1M::new()); - } - } - Mbc::Mbc1(Mbc1::new()) - } - 5 | 6 => Mbc::Mbc2(Mbc2::new()), - 0x0F..=0x13 => Mbc::Mbc3(Mbc3::new()), - 0x19..=0x1E => Mbc::Mbc5(Mbc5::new()), - _ => { - return Err(format!( - "MBC type '{}' ({:02x}) is not supported", - mbc_type_name(mbc_kind), - mbc_kind - )) + let header = match CartridgeHeader::from_bytes(&rom) { + Ok(x) => x, + Err((Some(x), err)) => { + writeln!(&mut error, "{}", err).unwrap(); + x } + Err((None, err)) => return Err((err, None)), }; - let ram_sizes = [ - 0, - 0x800, - 0x2000, // Single Bank - 4 * 0x2000, - 16 * 0x2000, - 8 * 0x2000, - ]; - let ram_size_type = header.ram_size; + let spec = match spec { + Some(spec) => spec, + None => match MbcSpecification::from_header(&header, &mut error, &rom) { + Some(v) => v, + None => return Err((error, None)), + }, + }; - let ram_size = if let Mbc::Mbc2(_) = mbc { - if ram_size_type != 0 { - return Err(format!("Cartridge use MBC2, with a integrated ram (type '00'), but report the ram type '{:02x}'", ram_size_type)); - } - 0x200 - } else { - ram_sizes - .get(ram_size_type as usize) - .copied() - .ok_or_else(|| format!("Ram size '{:02x}' is no supported", ram_size_type))? + let rom_size = spec.rom_size; + + // resize the rom in case the header expected a different size + rom.resize(rom_size, 0); + + let mbc = match spec.kind { + MbcKind::Mbc0 => Mbc::None(Mbc0 {}), + MbcKind::Mbc1 => Mbc::Mbc1(Mbc1::new()), + MbcKind::Mbc1M => Mbc::Mbc1M(Mbc1M::new()), + MbcKind::Mbc2 => Mbc::Mbc2(Mbc2::new()), + MbcKind::Mbc3 => Mbc::Mbc3(Mbc3::new()), + MbcKind::Mbc5 => Mbc::Mbc5(Mbc5::new()), }; - Ok(Self { + let cartridge = Self { header, lower_bank: 0, upper_bank: 1, rom, - ram: vec![0; ram_size], + ram: vec![0; spec.ram_size], mbc, - }) + }; + + if !error.is_empty() { + return Err((error, Some(cartridge))); + } + + Ok(cartridge) } /// A Cartridge filled with HALT instructions. Used as a test cartridge, when the CPU does not diff --git a/core/src/parser/mod.rs b/core/src/parser/mod.rs index 97eff52..8043184 100644 --- a/core/src/parser/mod.rs +++ b/core/src/parser/mod.rs @@ -1,5 +1,9 @@ use std::io::{Read, Seek, SeekFrom}; +mod size; + +pub use size::{parse_number, parse_size}; + fn read_u32(file: &mut impl Read) -> Result { let mut value = [0; 4]; file.read_exact(&mut value)?; diff --git a/core/src/parser/size.rs b/core/src/parser/size.rs new file mode 100644 index 0000000..392dcd4 --- /dev/null +++ b/core/src/parser/size.rs @@ -0,0 +1,114 @@ +use std::num::ParseIntError; + +#[derive(Debug, PartialEq)] +pub enum ParseSizeError { + InvalidFormat, + InvalidSuffix, + NumberTooLarge, + ParseError(ParseIntError), +} + +pub fn parse_number(input: &str) -> Result { + if let Some(stripped) = input.strip_prefix("0x") { + u64::from_str_radix(stripped, 16) + } else { + input.parse() + } +} + +pub fn parse_size(input: &str) -> Result { + if input.is_empty() { + return Err(ParseSizeError::InvalidFormat); + } + + let (num_part, suffix) = input.trim().split_at( + input + .find(|c: char| !c.is_ascii_digit() && c != 'x') + .unwrap_or(input.len()), + ); + + let num = parse_number(num_part).map_err(ParseSizeError::ParseError)?; + + let multiplier = match suffix.trim() { + "B" => 1, + "kB" => 1_024, + "MB" => 1_024 * 1_024, + "GB" => 1_024 * 1_024 * 1_024, + "" => return Err(ParseSizeError::InvalidFormat), + _ => return Err(ParseSizeError::InvalidSuffix), + }; + + let result = num + .checked_mul(multiplier as u64) + .ok_or(ParseSizeError::NumberTooLarge)?; + + if result > u32::MAX as u64 { + return Err(ParseSizeError::NumberTooLarge); + } + + Ok(result) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_parse_number_decimal() { + assert_eq!(parse_number("123"), Ok(123)); + assert_eq!(parse_number("0"), Ok(0)); + } + + #[test] + fn test_parse_number_hexadecimal() { + assert_eq!(parse_number("0x10"), Ok(16)); + assert_eq!(parse_number("0x1F4"), Ok(500)); + } + + #[test] + fn test_parse_number_invalid() { + assert!(parse_number("not_a_number").is_err()); + assert!(parse_number("0xZZZ").is_err()); + } + + #[test] + fn test_parse_size_with_hexadecimal() { + assert_eq!(parse_size("0x100B"), Ok(256)); + assert_eq!(parse_size("0x1kB"), Ok(1_024)); + assert_eq!(parse_size("0x2MB"), Ok(2 * 1_024 * 1_024)); + } + + #[test] + fn test_valid_sizes() { + assert_eq!(parse_size("0B"), Ok(0)); + assert_eq!(parse_size("256B"), Ok(256)); + assert_eq!(parse_size("1kB"), Ok(1_024)); + assert_eq!(parse_size("2MB"), Ok(2 * 1_024 * 1_024)); + assert_eq!(parse_size("1GB"), Ok(1_024 * 1_024 * 1_024)); + } + + #[test] + fn test_invalid_formats() { + assert_eq!(parse_size(""), Err(ParseSizeError::InvalidFormat)); + assert_eq!(parse_size("256"), Err(ParseSizeError::InvalidFormat)); + assert_eq!(parse_size("256MBExtra"), Err(ParseSizeError::InvalidSuffix)); + } + + #[test] + fn test_invalid_suffix() { + assert_eq!(parse_size("256mB"), Err(ParseSizeError::InvalidSuffix)); + assert_eq!(parse_size("256TB"), Err(ParseSizeError::InvalidSuffix)); + } + + #[test] + fn test_parse_errors() { + assert!(matches!( + parse_size("not_a_numberMB"), + Err(ParseSizeError::ParseError(_)) + )); + assert!(matches!( + parse_size("0xnot_hexB"), + Err(ParseSizeError::ParseError(_)) + )); + } +} diff --git a/core/tests/check_interrupt_prediction.rs b/core/tests/check_interrupt_prediction.rs index 5d10ba2..ec002f8 100644 --- a/core/tests/check_interrupt_prediction.rs +++ b/core/tests/check_interrupt_prediction.rs @@ -100,7 +100,7 @@ fn test_interrupt_prediction(rom: &str, timeout: u64) -> bool { let rom = std::fs::read(rom_path).unwrap(); let cartridge = match Cartridge::new(rom) { Ok(x) => x, - Err(x) => { + Err((x, _)) => { eprintln!("Error reading rom: {}", x); return true; } diff --git a/jit/tests/check_jit_compilation.rs b/jit/tests/check_jit_compilation.rs index 87ef54e..c06c405 100644 --- a/jit/tests/check_jit_compilation.rs +++ b/jit/tests/check_jit_compilation.rs @@ -162,7 +162,7 @@ fn test_interrupt_prediction(rom: &str, timeout: u64) -> bool { }; let cartridge = match Cartridge::new(rom) { Ok(x) => x, - Err(x) => { + Err((x, _)) => { eprintln!("Error reading rom: {}", x); return true; } diff --git a/libretro/src/lib.rs b/libretro/src/lib.rs index 487fd7b..1b50498 100644 --- a/libretro/src/lib.rs +++ b/libretro/src/lib.rs @@ -174,12 +174,16 @@ extern "C" fn retro_load_game(info: Option<&retro_game_info>) -> bool { log::info!("retro load game"); // load rom data into core - let Some(info) = info else { return false } ; + let Some(info) = info else { return false }; let data = unsafe { std::slice::from_raw_parts(info.data as *const u8, info.size as usize) }; let cartridge = match Cartridge::new(data.to_vec()) { - Ok(x) => x, - Err(err) => { + Ok(rom) => rom, + Err((err, Some(rom))) => { + log::warn!("Warnings when loading rom: {}", err); + rom + } + Err((err, None)) => { log::error!("Error loading rom: {}", err); return false; } @@ -371,7 +375,10 @@ impl log::Log for RetroLogger { let Ok(mut file) = std::fs::OpenOptions::new() .create(true) .append(true) - .open(path) else { return }; + .open(path) + else { + return; + }; let _ = writeln!( &mut file, diff --git a/license/about-android.toml b/license/about-android.toml index 41b94d3..ed1b991 100644 --- a/license/about-android.toml +++ b/license/about-android.toml @@ -1,5 +1,12 @@ ignore-dev-dependencies = true ignore-build-dependencies = true -accepted = ["Apache-2.0", "MIT", "Unicode-DFS-2016", "ISC", "BSD-3-Clause"] +accepted = [ + "Apache-2.0", + "MIT", + "Unicode-DFS-2016", + "Unicode-3.0", + "ISC", + "BSD-3-Clause", +] targets = ["aarch64-linux-android"] diff --git a/license/about-linux.toml b/license/about-linux.toml index e85862d..d80ba07 100644 --- a/license/about-linux.toml +++ b/license/about-linux.toml @@ -4,6 +4,7 @@ accepted = [ "Apache-2.0", "MIT", "Unicode-DFS-2016", + "Unicode-3.0", "BSD-2-Clause", "BSD-3-Clause", "ISC", diff --git a/license/about-windows.toml b/license/about-windows.toml index 2424b62..c372409 100644 --- a/license/about-windows.toml +++ b/license/about-windows.toml @@ -4,6 +4,7 @@ accepted = [ "Apache-2.0", "MIT", "Unicode-DFS-2016", + "Unicode-3.0", "ISC", "BSD-3-Clause", "BSL-1.0", diff --git a/native/src/main.rs b/native/src/main.rs index 5d77978..268b30b 100644 --- a/native/src/main.rs +++ b/native/src/main.rs @@ -11,7 +11,7 @@ use std::path::PathBuf; use clap::{ArgAction, Args, Parser, Subcommand}; use gameroy_lib::config::parse_screen_size; -use gameroy_lib::{config, gameroy, rom_loading::load_gameboy, RomFile}; +use gameroy_lib::{config, gameroy, rom_loading::load_gameboy_with_spec, RomFile}; mod bench; @@ -35,7 +35,7 @@ pub struct Cli { // // The disassembly produced follows no particular synxtax, and don't show all instructions or // data. It only shows instructions that are statically reachable from the entry point. - #[arg(long)] + #[arg(long, requires("rom_path"))] disassembly: bool, /// Play the given .vbm file @@ -74,6 +74,17 @@ pub struct Cli { #[arg(long, value_name = "WIDTHxHEIGHT")] screen_size: Option, + /// The MBC type of the rom + /// + /// Overrides the MBC type of the rom, useful in case its is not correctly detected. Must be a + /// string in the format ",,", where is the MBC type (either + /// "MBC1", "MBC1M", "MBC2", "MBC3" or "MBC5"), is the size of the rom in bytes, and + /// is the size of the ram in bytes. The sizes must be a power of 2 multiple of + /// 0x4000. The size can be in decimal or hexadecimal format, and can have a suffix of "B", + /// + #[arg(long)] + mbc: Option, + #[command(subcommand)] command: Option, } @@ -202,7 +213,7 @@ pub fn main() { Err(e) => return eprintln!("failed to load '{}': {}", rom_path, e), }; - let gb = load_gameboy(rom, None); + let gb = load_gameboy_with_spec(rom, None, args.mbc.as_deref()); let mut gb = match gb { Ok(x) => x, Err(e) => return eprintln!("failed to load rom: {}", e), @@ -230,7 +241,7 @@ pub fn main() { let file = RomFile::from_path(PathBuf::from(rom_path)); - let gb = load_gameboy(rom, None); + let gb = load_gameboy_with_spec(rom, None, args.mbc.as_deref()); match gb { Ok(x) => Some((file, x)), Err(e) => return eprintln!("failed to load rom: {}", e), diff --git a/src/rom_loading.rs b/src/rom_loading.rs index 3a962bc..498037d 100644 --- a/src/rom_loading.rs +++ b/src/rom_loading.rs @@ -20,9 +20,25 @@ cfg_if::cfg_if! { } pub fn load_gameboy(rom: Vec, ram: Option>) -> Result, String> { + load_gameboy_with_spec(rom, ram, None) +} + +pub fn load_gameboy_with_spec( + rom: Vec, + ram: Option>, + spec: Option<&str>, +) -> Result, String> { let boot_rom = load_boot_rom(); - let mut cartridge = Cartridge::new(rom)?; + let mut cartridge = match Cartridge::new_with_spec_str(rom, spec) { + Ok(rom) => Ok(rom), + Err((warn, Some(rom))) => { + println!("Warning: {}", warn.strip_suffix('\n').unwrap_or(&warn)); + log::warn!("{}", warn); + Ok(rom) + } + Err((err, None)) => Err(err), + }?; log::info!("Cartridge type: {}", cartridge.kind_name()); if let Some(ram) = ram {