chore: remove extra platforms

Former-commit-id: 694fbd23b097e1ff1f72875fa27da2dd070d195d
Former-commit-id: 64da130bc04b6e9a766f2491e6f7e7c4169f1e1b
This commit is contained in:
Muhammad Nauman Raza 2024-03-23 20:13:27 +00:00
parent 1b9f5eff2c
commit 900cf18f46
142 changed files with 25 additions and 16257 deletions

424
Cargo.lock generated
View file

@ -2,21 +2,6 @@
# It is not intended for manual editing.
version = 3
[[package]]
name = "addr2line"
version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b6a2d3371669ab3ca9797670853d61402b03d0b4b9ebf33d677dfa720203072"
dependencies = [
"gimli",
]
[[package]]
name = "adler"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee2a4ec343196209d6594e19543ae87a39f96d5534d7174822a3ad825dd6ed7e"
[[package]]
name = "adler32"
version = "1.2.0"
@ -32,25 +17,6 @@ dependencies = [
"memchr",
]
[[package]]
name = "android_liblog-sys"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aaf82c031178ca72b38595a54d16df8a257df9deea7d97a8992870e5c6a738e7"
dependencies = [
"libc",
]
[[package]]
name = "android_log"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cc00e0d3a060cce3fa338f9644ce9a93901c79f5405330891aeca69c9957009a"
dependencies = [
"android_liblog-sys",
"log 0.3.9",
]
[[package]]
name = "ansi_term"
version = "0.11.0"
@ -81,7 +47,7 @@ dependencies = [
"enum-primitive-derive",
"gdbstub",
"gdbstub_arch",
"log 0.4.11",
"log",
"num",
"num-traits 0.2.12",
"rustboyadvance-utils",
@ -128,20 +94,6 @@ version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
[[package]]
name = "backtrace"
version = "0.3.51"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec1931848a574faa8f7c71a12ea00453ff5effbb5f51afe7f77d7a48cace6ac1"
dependencies = [
"addr2line",
"cfg-if 0.1.10",
"libc",
"miniz_oxide 0.4.2",
"object",
"rustc-demangle",
]
[[package]]
name = "base-x"
version = "0.2.6"
@ -265,12 +217,6 @@ version = "1.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de"
[[package]]
name = "bytes"
version = "0.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0e4cec68f03f32e44924783795810fa50a7035d8c8ebe78580ad7e6c703fba38"
[[package]]
name = "bytesize"
version = "1.0.1"
@ -292,12 +238,6 @@ version = "1.0.60"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ef611cc68ff783f18535d77ddd080185275713d852c4f5cbb6122c462a7a825c"
[[package]]
name = "cesu8"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c"
[[package]]
name = "cfg-if"
version = "0.1.10"
@ -360,27 +300,6 @@ dependencies = [
"winapi",
]
[[package]]
name = "combine"
version = "4.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2809f67365382d65fd2b6d9c22577231b954ed27400efeafbe687bda75abcc0b"
dependencies = [
"bytes",
"memchr",
"pin-project-lite",
]
[[package]]
name = "console_error_panic_hook"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8d976903543e0c48546a91908f21588a680a8c8f984df9a5d69feccb2b2a211"
dependencies = [
"cfg-if 0.1.10",
"wasm-bindgen",
]
[[package]]
name = "const_fn"
version = "0.4.2"
@ -639,29 +558,6 @@ dependencies = [
"syn 0.11.11",
]
[[package]]
name = "env_logger"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36"
dependencies = [
"atty",
"humantime",
"log 0.4.11",
"regex",
"termcolor",
]
[[package]]
name = "error-chain"
version = "0.12.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2d2f06b9cac1506ece98fe3231e3cc9c4410ec3d5b1f24ae1c8946f0742cdefc"
dependencies = [
"backtrace",
"version_check",
]
[[package]]
name = "fake-simd"
version = "0.1.2"
@ -677,7 +573,7 @@ dependencies = [
"cfg-if 0.1.10",
"crc32fast",
"libc",
"miniz_oxide 0.3.7",
"miniz_oxide",
]
[[package]]
@ -688,7 +584,7 @@ checksum = "515fb7f6541dafe542c87c12a7ab6a52190cccb6c348b5951ef62d9978189ae8"
dependencies = [
"chrono",
"glob",
"log 0.4.11",
"log",
"regex",
"yansi",
]
@ -701,12 +597,6 @@ dependencies = [
"rustboyadvance-utils",
]
[[package]]
name = "futures"
version = "0.1.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b980f2816d6ee8673b6517b52cb0e808a180efc92e5c19d02cdda79066703ef"
[[package]]
name = "fuzzy-matcher"
version = "0.3.5"
@ -724,7 +614,7 @@ checksum = "32c95766e0414f8bfc1d07055574c621b67739466d6ba516c4fef8e99d30d2e6"
dependencies = [
"bitflags",
"cfg-if 1.0.0",
"log 0.4.11",
"log",
"managed",
"num-traits 0.2.12",
"paste",
@ -760,12 +650,6 @@ dependencies = [
"wasi 0.9.0+wasi-snapshot-preview1",
]
[[package]]
name = "gimli"
version = "0.22.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aaf91faf136cb47367fa430cd46e37a788775e7fa104f8b4bcb3861dc389b724"
[[package]]
name = "glob"
version = "0.3.0"
@ -778,7 +662,7 @@ version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d20fd25aa456527ce4f544271ae4fea65d2eda4a6561ea56f39fb3ee4f7e3884"
dependencies = [
"log 0.4.11",
"log",
"plain",
"scroll",
]
@ -836,27 +720,6 @@ dependencies = [
"itertools 0.4.19",
]
[[package]]
name = "humantime"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f"
dependencies = [
"quick-error",
]
[[package]]
name = "instant"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "63312a18f7ea8760cdd0a7c5aac1a619752a246b833545e3e36d1f81f7cd9e66"
dependencies = [
"cfg-if 0.1.10",
"js-sys",
"wasm-bindgen",
"web-sys",
]
[[package]]
name = "itertools"
version = "0.4.19"
@ -884,26 +747,6 @@ version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c8af84674fe1f223a982c933a0ee1086ac4d4052aa0fb8060c12c6ad838e754"
[[package]]
name = "jni"
version = "0.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "36bcc950632e48b86da402c5c077590583da5ac0d480103611d5374e7c967a3c"
dependencies = [
"cesu8",
"combine",
"error-chain",
"jni-sys",
"log 0.4.11",
"walkdir",
]
[[package]]
name = "jni-sys"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130"
[[package]]
name = "js-sys"
version = "0.3.45"
@ -938,40 +781,12 @@ version = "0.2.132"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8371e4e5341c3a96db127eb2465ac681ced4c433e01dd0e938adbef26ba93ba5"
[[package]]
name = "libretro-backend"
version = "0.2.1"
source = "git+https://github.com/michelhe/libretro-backend.git?branch=rustboyadvance#cb525222a9151d10fe61fba95369ea6325dbc318"
dependencies = [
"libc",
"libretro-sys",
"log 0.4.11",
]
[[package]]
name = "libretro-sys"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "207b060b02cecbcee6df3d0f5ed38691d5c4df1379dd1acd5c49c9b25d20b439"
dependencies = [
"libc",
]
[[package]]
name = "linked-hash-map"
version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8dd5a6d5999d9907cda8ed67bbd137d3af8085216c2ac62de5be860bd41f304a"
[[package]]
name = "log"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b"
dependencies = [
"log 0.4.11",
]
[[package]]
name = "log"
version = "0.4.11"
@ -1023,12 +838,6 @@ dependencies = [
"autocfg",
]
[[package]]
name = "memory_units"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8452105ba047068f40ff7093dd1d9da90898e63dd61736462e9cdda6a90ad3c3"
[[package]]
name = "miniz_oxide"
version = "0.3.7"
@ -1038,16 +847,6 @@ dependencies = [
"adler32",
]
[[package]]
name = "miniz_oxide"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c60c0dfe32c10b43a144bad8fc83538c52f58302c92300ea7ec7bf7b38d5a7b9"
dependencies = [
"adler",
"autocfg",
]
[[package]]
name = "nix"
version = "0.18.0"
@ -1182,12 +981,6 @@ dependencies = [
"libc",
]
[[package]]
name = "object"
version = "0.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ab52be62400ca80aa00285d25253d7f7c437b7375c4de678f5405d3afe82ca5"
[[package]]
name = "odds"
version = "0.2.26"
@ -1218,12 +1011,6 @@ version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1de2e551fb905ac83f73f7aedf2f0cb4a0da7e35efa24a202a936269f1f18e1"
[[package]]
name = "pin-project-lite"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4fe74897791e156a0cd8cce0db31b9b2198e67877316bf3086c3acd187f719f0"
[[package]]
name = "plain"
version = "0.2.3"
@ -1249,7 +1036,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
dependencies = [
"proc-macro-error-attr",
"proc-macro2 1.0.23",
"proc-macro2",
"quote 1.0.7",
"syn 1.0.42",
"version_check",
@ -1261,7 +1048,7 @@ version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
dependencies = [
"proc-macro2 1.0.23",
"proc-macro2",
"quote 1.0.7",
"version_check",
]
@ -1272,15 +1059,6 @@ version = "0.5.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "99c605b9a0adc77b7211c6b1f722dcb613d68d66859a44f3d485a6da332b0598"
[[package]]
name = "proc-macro2"
version = "0.4.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759"
dependencies = [
"unicode-xid 0.1.0",
]
[[package]]
name = "proc-macro2"
version = "1.0.23"
@ -1290,34 +1068,19 @@ dependencies = [
"unicode-xid 0.2.1",
]
[[package]]
name = "quick-error"
version = "1.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
[[package]]
name = "quote"
version = "0.3.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a"
[[package]]
name = "quote"
version = "0.6.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1"
dependencies = [
"proc-macro2 0.4.30",
]
[[package]]
name = "quote"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37"
dependencies = [
"proc-macro2 1.0.23",
"proc-macro2",
]
[[package]]
@ -1433,7 +1196,7 @@ dependencies = [
"hex-literal",
"hexdump",
"lazy_static",
"log 0.4.11",
"log",
"memmem",
"nom",
"num",
@ -1449,32 +1212,6 @@ dependencies = [
"zip",
]
[[package]]
name = "rustboyadvance-jni"
version = "0.1.0"
dependencies = [
"android_log",
"env_logger",
"jni",
"log 0.4.11",
"rustboyadvance-core",
"rustboyadvance-utils",
]
[[package]]
name = "rustboyadvance-libretro"
version = "0.1.0"
dependencies = [
"bit",
"libc",
"libretro-backend",
"libretro-sys",
"log 0.4.11",
"rustboyadvance-core",
"rustboyadvance-utils",
"unsafe_unwrap",
]
[[package]]
name = "rustboyadvance-sdl2"
version = "0.1.0"
@ -1482,7 +1219,7 @@ dependencies = [
"bit",
"bytesize",
"flexi_logger",
"log 0.4.11",
"log",
"ringbuf",
"rustboyadvance-core",
"rustboyadvance-utils",
@ -1497,34 +1234,10 @@ name = "rustboyadvance-utils"
version = "0.1.0"
dependencies = [
"goblin",
"instant",
"log 0.4.11",
"log",
"ringbuf",
]
[[package]]
name = "rustboyadvance-wasm"
version = "0.1.0"
dependencies = [
"bit",
"console_error_panic_hook",
"js-sys",
"log 0.4.11",
"rustboyadvance-core",
"rustboyadvance-utils",
"wasm-bindgen",
"wasm-bindgen-console-logger",
"wasm-bindgen-test",
"web-sys",
"wee_alloc",
]
[[package]]
name = "rustc-demangle"
version = "0.1.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783"
[[package]]
name = "rustc_version"
version = "0.2.3"
@ -1543,7 +1256,7 @@ dependencies = [
"cfg-if 0.1.10",
"dirs-next",
"libc",
"log 0.4.11",
"log",
"memchr",
"nix",
"scopeguard",
@ -1568,12 +1281,6 @@ dependencies = [
"winapi-util",
]
[[package]]
name = "scoped-tls"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2"
[[package]]
name = "scopeguard"
version = "1.1.0"
@ -1595,7 +1302,7 @@ version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e367622f934864ffa1c704ba2b82280aab856e3d8213c84c5720257eb34b15b9"
dependencies = [
"proc-macro2 1.0.23",
"proc-macro2",
"quote 1.0.7",
"syn 1.0.42",
]
@ -1662,7 +1369,7 @@ version = "1.0.116"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f630a6370fd8e457873b4bd2ffdae75408bc291ba72be773772a4c2a065d9ae8"
dependencies = [
"proc-macro2 1.0.23",
"proc-macro2",
"quote 1.0.7",
"syn 1.0.42",
]
@ -1704,7 +1411,7 @@ checksum = "48047e77b528151aaf841a10a9025f9459da80ba820e425ff7eb005708a76dc7"
dependencies = [
"atty",
"colored 2.0.0",
"log 0.4.11",
"log",
"time 0.3.14",
"winapi",
]
@ -1715,7 +1422,7 @@ version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "133659a15339456eeeb07572eb02a91c91e9815e9cbc89566944d2c8d3efdbf6"
dependencies = [
"proc-macro2 1.0.23",
"proc-macro2",
"quote 1.0.7",
"syn 1.0.42",
]
@ -1765,7 +1472,7 @@ version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c87a60a40fccc84bef0652345bbbbbe20a605bf5d0ce81719fc476f5c03b50ef"
dependencies = [
"proc-macro2 1.0.23",
"proc-macro2",
"quote 1.0.7",
"serde",
"serde_derive",
@ -1779,7 +1486,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "58fa5ff6ad0d98d1ffa8cb115892b6e69d67799f6763e162a1c9db421dc22e11"
dependencies = [
"base-x",
"proc-macro2 1.0.23",
"proc-macro2",
"quote 1.0.7",
"serde",
"serde_derive",
@ -1819,7 +1526,7 @@ checksum = "dcb5ae327f9cc13b68763b5749770cb9e048a99bd9dfdfa58d0cf05d5f64afe0"
dependencies = [
"heck",
"proc-macro-error",
"proc-macro2 1.0.23",
"proc-macro2",
"quote 1.0.7",
"syn 1.0.42",
]
@ -1841,7 +1548,7 @@ version = "1.0.42"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c51d92969d209b54a98397e1b91c8ae82d8c87a7bb87df0b29aa2ad81454228"
dependencies = [
"proc-macro2 1.0.23",
"proc-macro2",
"quote 1.0.7",
"unicode-xid 0.2.1",
]
@ -1855,15 +1562,6 @@ dependencies = [
"unicode-xid 0.0.4",
]
[[package]]
name = "termcolor"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bb6bfa289a4d7c5766392812c0a1f4c1ba45afa1ad47803c11e1f407d846d75f"
dependencies = [
"winapi-util",
]
[[package]]
name = "textwrap"
version = "0.11.0"
@ -1888,7 +1586,7 @@ version = "1.0.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bd80fc12f73063ac132ac92aceea36734f04a1d93c1240c6944e23a3b8841793"
dependencies = [
"proc-macro2 1.0.23",
"proc-macro2",
"quote 1.0.7",
"syn 1.0.42",
]
@ -1963,7 +1661,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5c3be1edfad6027c69f5491cf4cb310d1a71ecd6af742788c6ff8bced86b8fa"
dependencies = [
"proc-macro-hack",
"proc-macro2 1.0.23",
"proc-macro2",
"quote 1.0.7",
"standback",
"syn 1.0.42",
@ -2012,24 +1710,12 @@ version = "0.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc"
[[package]]
name = "unicode-xid"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
[[package]]
name = "unicode-xid"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"
[[package]]
name = "unsafe_unwrap"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1230ec65f13e0f9b28d789da20d2d419511893ea9dac2c1f4ef67b8b14e5da80"
[[package]]
name = "utf8parse"
version = "0.2.0"
@ -2089,36 +1775,13 @@ checksum = "f22b422e2a757c35a73774860af8e112bff612ce6cb604224e8e47641a9e4f68"
dependencies = [
"bumpalo",
"lazy_static",
"log 0.4.11",
"proc-macro2 1.0.23",
"log",
"proc-macro2",
"quote 1.0.7",
"syn 1.0.42",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-console-logger"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7530a275e7faf7b5b83aabdf78244fb8d9a68a2ec4b26935a05ecc0c9b0185ed"
dependencies = [
"log 0.4.11",
"wasm-bindgen",
]
[[package]]
name = "wasm-bindgen-futures"
version = "0.3.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "83420b37346c311b9ed822af41ec2e82839bfe99867ec6c54e2da43b7538771c"
dependencies = [
"cfg-if 0.1.10",
"futures",
"js-sys",
"wasm-bindgen",
"web-sys",
]
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.68"
@ -2135,7 +1798,7 @@ version = "0.2.68"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f249f06ef7ee334cc3b8ff031bfc11ec99d00f34d86da7498396dc1e3b1498fe"
dependencies = [
"proc-macro2 1.0.23",
"proc-macro2",
"quote 1.0.7",
"syn 1.0.42",
"wasm-bindgen-backend",
@ -2148,31 +1811,6 @@ version = "0.2.68"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d649a3145108d7d3fbcde896a468d1bd636791823c9921135218ad89be08307"
[[package]]
name = "wasm-bindgen-test"
version = "0.2.50"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2d9693b63a742d481c7f80587e057920e568317b2806988c59cd71618bc26c1"
dependencies = [
"console_error_panic_hook",
"futures",
"js-sys",
"scoped-tls",
"wasm-bindgen",
"wasm-bindgen-futures",
"wasm-bindgen-test-macro",
]
[[package]]
name = "wasm-bindgen-test-macro"
version = "0.2.50"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0789dac148a8840bbcf9efe13905463b733fa96543bfbf263790535c11af7ba5"
dependencies = [
"proc-macro2 0.4.30",
"quote 0.6.13",
]
[[package]]
name = "web-sys"
version = "0.3.45"
@ -2183,18 +1821,6 @@ dependencies = [
"wasm-bindgen",
]
[[package]]
name = "wee_alloc"
version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dbb3b5a6b2bb17cb6ad44a2e68a43e8d2722c997da10e928665c72ec6c0a0b8e"
dependencies = [
"cfg-if 0.1.10",
"libc",
"memory_units",
"winapi",
]
[[package]]
name = "winapi"
version = "0.3.9"

View file

@ -4,9 +4,6 @@ members = [
"arm7tdmi",
"utils",
"platform/rustboyadvance-sdl2",
"platform/rustboyadvance-libretro",
"platform/rustboyadvance-wasm",
"platform/rustboyadvance-jni",
"fps_bench"
]
resolver = "1"

View file

@ -1,129 +0,0 @@
use log::info;
use simple_logger::SimpleLogger;
use gdbstub::common::Signal;
use gdbstub::conn::{Connection, ConnectionExt};
use gdbstub::stub::{run_blocking, GdbStub, SingleThreadStopReason};
use gdbstub::target::Target;
use arm7tdmi::gdb::wait_for_connection;
use arm7tdmi::{Arm7tdmiCore, SimpleMemory};
use rustboyadvance_utils::Shared;
struct SimpleEmulator {
cpu: Arm7tdmiCore<SimpleMemory>,
}
impl SimpleEmulator {
fn new(program: &[u8]) -> SimpleEmulator {
let mut memory = SimpleMemory::new(0x4000);
memory.load_program(program);
let bus = Shared::new(memory);
let mut cpu = Arm7tdmiCore::new(bus);
cpu.reset();
SimpleEmulator { cpu }
}
}
impl run_blocking::BlockingEventLoop for SimpleEmulator {
type Target = Arm7tdmiCore<SimpleMemory>;
type Connection = Box<dyn ConnectionExt<Error = std::io::Error>>;
type StopReason = SingleThreadStopReason<u32>;
fn wait_for_stop_reason(
target: &mut Self::Target,
conn: &mut Self::Connection,
) -> Result<
run_blocking::Event<SingleThreadStopReason<u32>>,
run_blocking::WaitForStopReasonError<
<Self::Target as Target>::Error,
<Self::Connection as Connection>::Error,
>,
> {
let mut steps = 0;
loop {
if conn.peek().map(|b| b.is_some()).unwrap_or(true) {
let byte = conn
.read()
.map_err(run_blocking::WaitForStopReasonError::Connection)?;
return Ok(run_blocking::Event::IncomingData(byte));
} else {
target.step();
if target.check_breakpoint().is_some() {
return Ok(run_blocking::Event::TargetStopped(
SingleThreadStopReason::SwBreak(()),
));
}
steps += 1;
if steps % 1024 == 0 {
return Ok(run_blocking::Event::TargetStopped(
SingleThreadStopReason::SwBreak(()),
));
}
}
}
}
fn on_interrupt(
_target: &mut Arm7tdmiCore<SimpleMemory>,
) -> Result<Option<SingleThreadStopReason<u32>>, <Arm7tdmiCore<SimpleMemory> as Target>::Error>
{
// Because this emulator runs as part of the GDB stub loop, there isn't any
// special action that needs to be taken to interrupt the underlying target. It
// is implicitly paused whenever the stub isn't within the
// `wait_for_stop_reason` callback.
Ok(Some(SingleThreadStopReason::Signal(Signal::SIGINT)))
}
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
SimpleLogger::new().env().init().unwrap();
let mut emulator = SimpleEmulator::new(include_bytes!("test_program/test.bin"));
let conn: Box<dyn ConnectionExt<Error = std::io::Error>> = Box::new(wait_for_connection(1337)?);
let gdb = GdbStub::new(conn);
let result = gdb.run_blocking::<SimpleEmulator>(&mut emulator.cpu);
info!("emulator stopped, gdb result {:?}", result);
Ok(())
}
#[cfg(test)]
mod test {
use super::*;
use arm7tdmi::memory::DebugRead;
use rustboyadvance_utils::elf::read_symbols;
#[test]
fn test_breakpoint() -> Result<(), Box<dyn std::error::Error>> {
let mut emulator = SimpleEmulator::new(include_bytes!("test_program/test.bin"));
let symbol_map = read_symbols(include_bytes!("test_program/test.elf"))?;
let breakpoint_addr = *symbol_map.get("breakpoint_on_me").unwrap();
println!("breakpoint_addr = {:08x}", breakpoint_addr);
let breakpoint_counter_addr = *symbol_map.get("breakpoint_count").unwrap();
emulator.cpu.breakpoints.push(breakpoint_addr);
for x in 0..10 {
println!("{}", x);
let timeout = std::time::Instant::now() + std::time::Duration::from_secs(1);
loop {
emulator.cpu.step();
if let Some(addr) = emulator.cpu.check_breakpoint() {
emulator.cpu.step();
assert_eq!(addr, breakpoint_addr);
assert_eq!(emulator.cpu.bus.debug_read_32(breakpoint_counter_addr), x);
break;
}
assert!(std::time::Instant::now() < timeout);
}
}
Ok(())
}
}

View file

@ -1,2 +0,0 @@
/*.o
/*.gdb_history

View file

@ -1,37 +0,0 @@
# Easiest to build this using `docker run -it --rm -v $(pwd):/code -w /code devkitpro/devkitarm:latest make
TOOLCHAIN := ${DEVKITARM}/bin/arm-none-eabi
CC := ${TOOLCHAIN}-gcc
OBJCOPY := ${TOOLCHAIN}-objcopy
OBJDUMP := ${TOOLCHAIN}-objdump
TARGET := test
CFLAGS := -O0 -g -std=c11 -march=armv4t -mthumb
LDFLAGS := -Wl,-static
SOURCES := $(wildcard *.[cs])
OBJECTS := $(filter %.o,$(SOURCES:%.c=%.o))
OBJECTS += $(filter %.o,$(SOURCES:%.s=%.o))
all: ${TARGET}.bin objdump
${OBJECTS}: ${SOURCES}
${CC} -c ${CFLAGS} $^
${TARGET}.elf ${TARGET}.map: ${OBJECTS} ${TARGET}.ld
${CC} ${LDFLAGS} -Wl,-Map=${TARGET}.map -Wl,-T${TARGET}.ld ${OBJECTS} -o $@
${TARGET}.bin: ${TARGET}.elf
$(OBJCOPY) -v -O binary $^ $@
objdump: ${TARGET}.elf
${OBJDUMP} -d $^
clean:
rm -f ${TARGET}.elf
rm -f ${TARGET}.bin
rm -f ${TARGET}.map
rm -f *.o
.PHONY: all clean

View file

@ -1,40 +0,0 @@
.section ".init"
.global _interrupt_vector
.align 4
.arm
.section ".init.vector"
_interrupt_vector:
b _reset
b _not_implemented
b _not_implemented
b _not_implemented
b _not_implemented
b _not_implemented
b _not_implemented
b _not_implemented
.section ".init.text"
.global _reset
_reset:
mrs r1, cpsr @ save the mode bits from CPSR
bic r0, r1, #0x1F
orr r0, r0, #0x13 @ supervisor
ldr sp, =_stack_top
mov r0, #0
mov r1, #0
mov r2, #0
mov r3, #0
mov r4, #0
mov r5, #0
mov r6, #0
mov r7, #0
mov r9, #0
mov r10, #0
mov r11, #0
mov r12, #0
b main
_not_implemented:
b _not_implemented

View file

@ -1,17 +0,0 @@
volatile int breakpoint_count = 0;
volatile int breakpoint_on_me() {
breakpoint_count++;
}
int main() {
int x = 1337;
for (;;) {
x += 1;
if (x == 7331) {
breakpoint_on_me();
x = 1337;
}
}
return 0;
}

View file

@ -1,32 +0,0 @@
ENTRY(_reset)
MEMORY {
RAM : ORIGIN = 0x00000000, LENGTH = 16K
}
SECTIONS {
. = ORIGIN(RAM);
.init : {
*(.init.vector);
*(.init*);
} > RAM
.text : ALIGN(4) {
*(.text)
*(.text.*)
} > RAM
.data : ALIGN(4) {
*(.rodata*);
*(.data*);
} > RAM
.bss : ALIGN(4) {
*(.bss*)
} > RAM
.stack : AT (0x00003000) {
_stack_bottom = .;
. += 0xfe0;
_stack_top = .;
} > RAM
}

View file

@ -1,162 +0,0 @@
Memory Configuration
Name Origin Length Attributes
RAM 0x0000000000000000 0x0000000000004000
*default* 0x0000000000000000 0xffffffffffffffff
Linker script and memory map
LOAD /opt/devkitpro/devkitARM/bin/../lib/gcc/arm-none-eabi/12.1.0/crti.o
LOAD /opt/devkitpro/devkitARM/bin/../lib/gcc/arm-none-eabi/12.1.0/crtbegin.o
0x0000000000000000 . = ORIGIN (RAM)
.init 0x0000000000000000 0x88
*(.init.vector)
.init.vector 0x0000000000000000 0x20 reset.o
0x0000000000000000 _interrupt_vector
*(.init*)
.init 0x0000000000000020 0xc /opt/devkitpro/devkitARM/bin/../lib/gcc/arm-none-eabi/12.1.0/crti.o
0x0000000000000020 _init
.init_array 0x000000000000002c 0x4 /opt/devkitpro/devkitARM/bin/../lib/gcc/arm-none-eabi/12.1.0/crtbegin.o
.init 0x0000000000000030 0x0 reset.o
.init.text 0x0000000000000030 0x4c reset.o
0x0000000000000030 _reset
.init 0x000000000000007c 0xc /opt/devkitpro/devkitARM/bin/../lib/gcc/arm-none-eabi/12.1.0/crtn.o
.text 0x0000000000000088 0xbc
*(.text)
.text 0x0000000000000088 0x0 /opt/devkitpro/devkitARM/bin/../lib/gcc/arm-none-eabi/12.1.0/crti.o
.text 0x0000000000000088 0x0 /opt/devkitpro/devkitARM/bin/../lib/gcc/arm-none-eabi/12.1.0/crtbegin.o
.text 0x0000000000000088 0x4c test.o
0x0000000000000088 breakpoint_on_me
0x00000000000000a8 main
.text 0x00000000000000d4 0x0 reset.o
.text 0x00000000000000d4 0x0 /opt/devkitpro/devkitARM/bin/../lib/gcc/arm-none-eabi/12.1.0/crtend.o
.text 0x00000000000000d4 0x0 /opt/devkitpro/devkitARM/bin/../lib/gcc/arm-none-eabi/12.1.0/crtn.o
*(.text.*)
.text.__do_global_dtors_aux
0x00000000000000d4 0x40 /opt/devkitpro/devkitARM/bin/../lib/gcc/arm-none-eabi/12.1.0/crtbegin.o
.text.frame_dummy
0x0000000000000114 0x30 /opt/devkitpro/devkitARM/bin/../lib/gcc/arm-none-eabi/12.1.0/crtbegin.o
.glue_7 0x0000000000000144 0x0
.glue_7 0x0000000000000144 0x0 linker stubs
.glue_7t 0x0000000000000144 0x0
.glue_7t 0x0000000000000144 0x0 linker stubs
.vfp11_veneer 0x0000000000000144 0x0
.vfp11_veneer 0x0000000000000144 0x0 linker stubs
.v4_bx 0x0000000000000144 0x0
.v4_bx 0x0000000000000144 0x0 linker stubs
.fini 0x0000000000000144 0x18
.fini 0x0000000000000144 0xc /opt/devkitpro/devkitARM/bin/../lib/gcc/arm-none-eabi/12.1.0/crti.o
0x0000000000000144 _fini
.fini 0x0000000000000150 0xc /opt/devkitpro/devkitARM/bin/../lib/gcc/arm-none-eabi/12.1.0/crtn.o
.iplt 0x000000000000015c 0x0
.iplt 0x000000000000015c 0x0 /opt/devkitpro/devkitARM/bin/../lib/gcc/arm-none-eabi/12.1.0/crtbegin.o
.eh_frame 0x000000000000015c 0x4
.eh_frame 0x000000000000015c 0x0 /opt/devkitpro/devkitARM/bin/../lib/gcc/arm-none-eabi/12.1.0/crtbegin.o
.eh_frame 0x000000000000015c 0x4 /opt/devkitpro/devkitARM/bin/../lib/gcc/arm-none-eabi/12.1.0/crtend.o
.rel.dyn 0x0000000000000160 0x0
.rel.iplt 0x0000000000000160 0x0 /opt/devkitpro/devkitARM/bin/../lib/gcc/arm-none-eabi/12.1.0/crtbegin.o
.data 0x0000000000000160 0x4c
*(.rodata*)
.rodata.all_implied_fbits
0x0000000000000160 0x24 /opt/devkitpro/devkitARM/bin/../lib/gcc/arm-none-eabi/12.1.0/crtbegin.o
.rodata.all_implied_fbits
0x0000000000000184 0x24 /opt/devkitpro/devkitARM/bin/../lib/gcc/arm-none-eabi/12.1.0/crtend.o
*(.data*)
.data 0x00000000000001a8 0x0 /opt/devkitpro/devkitARM/bin/../lib/gcc/arm-none-eabi/12.1.0/crti.o
.data 0x00000000000001a8 0x0 /opt/devkitpro/devkitARM/bin/../lib/gcc/arm-none-eabi/12.1.0/crtbegin.o
.data.__dso_handle
0x00000000000001a8 0x4 /opt/devkitpro/devkitARM/bin/../lib/gcc/arm-none-eabi/12.1.0/crtbegin.o
0x00000000000001a8 __dso_handle
.data 0x00000000000001ac 0x0 test.o
.data 0x00000000000001ac 0x0 reset.o
.data 0x00000000000001ac 0x0 /opt/devkitpro/devkitARM/bin/../lib/gcc/arm-none-eabi/12.1.0/crtend.o
.data 0x00000000000001ac 0x0 /opt/devkitpro/devkitARM/bin/../lib/gcc/arm-none-eabi/12.1.0/crtn.o
.fini_array 0x00000000000001ac 0x4
.fini_array 0x00000000000001ac 0x4 /opt/devkitpro/devkitARM/bin/../lib/gcc/arm-none-eabi/12.1.0/crtbegin.o
.igot.plt 0x00000000000001b0 0x0
.igot.plt 0x00000000000001b0 0x0 /opt/devkitpro/devkitARM/bin/../lib/gcc/arm-none-eabi/12.1.0/crtbegin.o
.bss 0x00000000000001b0 0x20
*(.bss*)
.bss 0x00000000000001b0 0x0 /opt/devkitpro/devkitARM/bin/../lib/gcc/arm-none-eabi/12.1.0/crti.o
.bss 0x00000000000001b0 0x0 /opt/devkitpro/devkitARM/bin/../lib/gcc/arm-none-eabi/12.1.0/crtbegin.o
.bss.completed.1
0x00000000000001b0 0x1 /opt/devkitpro/devkitARM/bin/../lib/gcc/arm-none-eabi/12.1.0/crtbegin.o
*fill* 0x00000000000001b1 0x3
.bss.object.0 0x00000000000001b4 0x18 /opt/devkitpro/devkitARM/bin/../lib/gcc/arm-none-eabi/12.1.0/crtbegin.o
.bss 0x00000000000001cc 0x4 test.o
0x00000000000001cc breakpoint_count
.bss 0x00000000000001d0 0x0 reset.o
.bss 0x00000000000001d0 0x0 /opt/devkitpro/devkitARM/bin/../lib/gcc/arm-none-eabi/12.1.0/crtend.o
.bss 0x00000000000001d0 0x0 /opt/devkitpro/devkitARM/bin/../lib/gcc/arm-none-eabi/12.1.0/crtn.o
.stack 0x00000000000001d0 0xfe0 load address 0x0000000000003000
0x00000000000001d0 _stack_bottom = .
0x00000000000011b0 . = (. + 0xfe0)
*fill* 0x00000000000001d0 0xfe0
0x00000000000011b0 _stack_top = .
LOAD test.o
LOAD reset.o
START GROUP
LOAD /opt/devkitpro/devkitARM/bin/../lib/gcc/arm-none-eabi/12.1.0/libgcc.a
LOAD /opt/devkitpro/devkitARM/bin/../lib/gcc/arm-none-eabi/12.1.0/../../../../arm-none-eabi/lib/libc.a
LOAD /opt/devkitpro/devkitARM/bin/../lib/gcc/arm-none-eabi/12.1.0/../../../../arm-none-eabi/lib/libsysbase.a
END GROUP
LOAD /opt/devkitpro/devkitARM/bin/../lib/gcc/arm-none-eabi/12.1.0/crtend.o
LOAD /opt/devkitpro/devkitARM/bin/../lib/gcc/arm-none-eabi/12.1.0/crtn.o
OUTPUT(test.elf elf32-littlearm)
LOAD linker stubs
.ARM.attributes
0x0000000000000000 0x26
.ARM.attributes
0x0000000000000000 0x1c /opt/devkitpro/devkitARM/bin/../lib/gcc/arm-none-eabi/12.1.0/crti.o
.ARM.attributes
0x000000000000001c 0x2a /opt/devkitpro/devkitARM/bin/../lib/gcc/arm-none-eabi/12.1.0/crtbegin.o
.ARM.attributes
0x0000000000000046 0x2a test.o
.ARM.attributes
0x0000000000000070 0x1a reset.o
.ARM.attributes
0x000000000000008a 0x2a /opt/devkitpro/devkitARM/bin/../lib/gcc/arm-none-eabi/12.1.0/crtend.o
.ARM.attributes
0x00000000000000b4 0x1c /opt/devkitpro/devkitARM/bin/../lib/gcc/arm-none-eabi/12.1.0/crtn.o
.comment 0x0000000000000000 0x23
.comment 0x0000000000000000 0x23 /opt/devkitpro/devkitARM/bin/../lib/gcc/arm-none-eabi/12.1.0/crtbegin.o
0x24 (size before relaxing)
.comment 0x0000000000000023 0x24 test.o
.comment 0x0000000000000023 0x24 /opt/devkitpro/devkitARM/bin/../lib/gcc/arm-none-eabi/12.1.0/crtend.o
.debug_info 0x0000000000000000 0x7e
.debug_info 0x0000000000000000 0x7e test.o
.debug_abbrev 0x0000000000000000 0x77
.debug_abbrev 0x0000000000000000 0x77 test.o
.debug_aranges 0x0000000000000000 0x20
.debug_aranges
0x0000000000000000 0x20 test.o
.debug_line 0x0000000000000000 0x51
.debug_line 0x0000000000000000 0x51 test.o
.debug_str 0x0000000000000000 0x69
.debug_str 0x0000000000000000 0x69 test.o
.debug_frame 0x0000000000000000 0x4c
.debug_frame 0x0000000000000000 0x4c test.o

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 134 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 152 KiB

View file

@ -1,14 +0,0 @@
*.iml
.gradle
/local.properties
/.idea/caches
/.idea/libraries
/.idea/modules.xml
/.idea/workspace.xml
/.idea/navEditor.xml
/.idea/assetWizardSettings.xml
.DS_Store
/build
/captures
.externalNativeBuild
.cxx

View file

@ -1 +0,0 @@
RustdroidAdvance

View file

@ -1,116 +0,0 @@
<component name="ProjectCodeStyleConfiguration">
<code_scheme name="Project" version="173">
<codeStyleSettings language="XML">
<indentOptions>
<option name="CONTINUATION_INDENT_SIZE" value="4" />
</indentOptions>
<arrangement>
<rules>
<section>
<rule>
<match>
<AND>
<NAME>xmlns:android</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>xmlns:.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:id</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:name</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>name</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>style</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
<order>ANDROID_ATTRIBUTE_ORDER</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>.*</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
</rules>
</arrangement>
</codeStyleSettings>
</code_scheme>
</component>

View file

@ -1,20 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GradleMigrationSettings" migrationVersion="1" />
<component name="GradleSettings">
<option name="linkedExternalProjectsSettings">
<GradleProjectSettings>
<option name="testRunner" value="PLATFORM" />
<option name="distributionType" value="DEFAULT_WRAPPED" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="modules">
<set>
<option value="$PROJECT_DIR$" />
<option value="$PROJECT_DIR$/app" />
</set>
</option>
<option name="resolveModulePerSourceSet" value="false" />
</GradleProjectSettings>
</option>
</component>
</project>

View file

@ -1,9 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
<component name="ProjectType">
<option name="id" value="Android" />
</component>
</project>

View file

@ -1,12 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RunConfigurationProducerService">
<option name="ignoredProducers">
<set>
<option value="org.jetbrains.plugins.gradle.execution.test.runner.AllInPackageGradleConfigurationProducer" />
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestClassGradleConfigurationProducer" />
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestMethodGradleConfigurationProducer" />
</set>
</option>
</component>
</project>

View file

@ -1,7 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$/../.." vcs="Git" />
<mapping directory="$PROJECT_DIR$/.." vcs="Git" />
</component>
</project>

View file

@ -1,3 +0,0 @@
# RustdroidAdvance
RustdroidAdvance is an android frontend for my rustboyadvance emulator core

View file

@ -1 +0,0 @@
/build

View file

@ -1,59 +0,0 @@
apply plugin: 'com.android.application'
android {
compileSdkVersion 29
buildToolsVersion "29.0.3"
defaultConfig {
applicationId "com.mrmichel.rustdroid_emu"
minSdkVersion 21
targetSdkVersion 26
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
apply plugin: 'org.mozilla.rust-android-gradle.rust-android'
cargo {
prebuiltToolchains = true
verbose = true
profile = 'release'
module = "../../../platform/rustboyadvance-jni"
targetDirectory = '../../../target'
libname = "rustboyadvance_jni"
targets = ['x86', 'arm64']
apiLevel = 21
}
afterEvaluate {
// The `cargoBuild` task isn't available until after evaluation.
android.applicationVariants.all { variant ->
def productFlavor = ""
variant.productFlavors.each {
productFlavor += "${it.name.capitalize()}"
}
def buildType = "${variant.buildType.name.capitalize()}"
tasks["generate${productFlavor}${buildType}Assets"].dependsOn(tasks["cargoBuild"])
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'androidx.appcompat:appcompat:1.0.2'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
implementation 'com.google.android.material:material:1.1.0'
implementation "androidx.documentfile:documentfile:1.0.1"
implementation 'androidx.preference:preference:1.1.0'
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
implementation 'commons-io:commons-io:2.6'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
}

View file

@ -1,21 +0,0 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile

View file

@ -1,27 +0,0 @@
package com.mrmichel.rustdroid_emu;
import android.content.Context;
import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.junit.Assert.*;
/**
* Instrumented test, which will execute on an Android device.
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {
@Test
public void useAppContext() {
// Context of the app under test.
Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
assertEquals("com.mrmichel.rustdroid_emu", appContext.getPackageName());
}
}

View file

@ -1,55 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.mrmichel.rustdroid_emu">
<uses-feature
android:glEsVersion="0x00200000"
android:required="true" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application
android:allowBackup="true"
android:hardwareAccelerated="true"
android:icon="@mipmap/ic_launcher"
android:isGame="true"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<!-- Needed for Android >= Nougat for file access -->
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="com.mrmichel.rustdroid_emu.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths" />
</provider>
<activity android:name=".ui.snapshots.SnapshotPickerActivity" />
<activity
android:name=".ui.snapshots.SnapshotListFragment"
android:label="@string/title_activity_snapshot" />
<activity
android:name=".ui.library.RomListActivity"
android:label="@string/title_activity_rom_list" />
<activity
android:name=".ui.EmulatorActivity"
android:label="@string/title_activity_emulator" />
<activity
android:name=".ui.SettingsActivity"
android:label="Settings" />
<activity android:name=".ui.SplashActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

View file

@ -1,123 +0,0 @@
package com.mrmichel.rustboyadvance;
/**
* JNI wrapper to the rust core
*/
public class EmulatorBindings {
static {
System.loadLibrary("rustboyadvance_jni");
}
/**
* Open a new emulator context
*
* @param bios bytearray of the GBA bios
* @param rom bytearray of the rom to run
* @param renderer renderer instance
* @param audioPlayer audio player instance
* @param keypad Keypad instance
* @param save_name name of the save file TODO remove this
* @param skipBios skip bios
* @return the emulator context to use pass to other methods in this class
* @throws NativeBindingException
*/
public static native long openEmulator(byte[] bios, byte[] rom, IFrameRenderer renderer, IAudioPlayer audioPlayer, Keypad keypad, String save_name, boolean skipBios) throws NativeBindingException;
/**
* Open a new emulator context from a saved state buffer
*
* @param bios bytearray of the GBA bios
* @param rom bytearray of the rom to run
* @param savedState saved state buffer
* @param renderer renderer instance
* @param audioPlayer audio player instance
* @param keypad Keypad instance
* @return
* @throws NativeBindingException
*/
public static native long openSavedState(byte[] bios, byte[] rom, byte[] savedState, IFrameRenderer renderer, IAudioPlayer audioPlayer, Keypad keypad) throws NativeBindingException;
/**
* Destroys the emulator instance
* should be put in a finalizer or else the emulator context may leak.
*
* @param ctx
*/
public static native void closeEmulator(long ctx);
/**
* Run the emulation thread
*
* @param ctx
*/
public static native void runMainLoop(long ctx);
public static native void pause(long ctx);
public static native void resume(long ctx);
public static native void setTurbo(long ctx, boolean turbo);
public static native void stop(long ctx);
public static native int[] getFrameBuffer(long ctx);
// /**
// * Runs the emulation for a single frame.
// * @param ctx
// * @param frame_buffer will be filled with the frame buffer to render
// */
// public static native void runFrame(long ctx, int[] frame_buffer);
/**
* @param ctx
* @return The loaded ROM title
*/
public static native String getGameTitle(long ctx);
/**
* @param ctx
* @return The loaded ROM game code
*/
public static native String getGameCode(long ctx);
/**
* Sets the keystate
*
* @param keyState
*/
public static native void setKeyState(long ctx, int keyState);
/**
* Saves the state
*
* @param ctx
* @return save state buffer
* @throws NativeBindingException
*/
public static native byte[] saveState(long ctx) throws NativeBindingException;
/**
* Loads a save state
*
* @param ctx
* @param state save state buffer
* @throws NativeBindingException
*/
public static native void loadState(long ctx, byte[] state) throws NativeBindingException;
/**
* Logs the emulator state
*
* @return non-zero value on failure
*/
public static native void log(long ctx);
public class NativeBindingException extends Exception {
public NativeBindingException(String errorMessage) {
super(errorMessage);
}
}
}

View file

@ -1,15 +0,0 @@
package com.mrmichel.rustboyadvance;
public interface IAudioPlayer {
int audioWrite(short[] buffer, int offsetInShorts, int sizeInShorts);
void pause();
void play();
int getSampleCount();
int getSampleRate();
int availableBufferSize();
}

View file

@ -1,5 +0,0 @@
package com.mrmichel.rustboyadvance;
public interface IFrameRenderer {
void renderFrame(int[] framebuffer);
}

View file

@ -1,44 +0,0 @@
package com.mrmichel.rustboyadvance;
public class Keypad {
private int keyState;
public Keypad() {
reset();
}
public void reset() {
this.keyState = 0xffff;
}
public void onKeyDown(Key key) {
this.keyState = this.keyState & ~(1 << key.keyBit);
}
public void onKeyUp(Key key) {
this.keyState = this.keyState | (1 << key.keyBit);
}
public int getKeyState() {
return keyState;
}
public enum Key {
ButtonA(0),
ButtonB(1),
Select(2),
Start(3),
Right(4),
Left(5),
Up(6),
Down(7),
ButtonR(8),
ButtonL(9);
private final int keyBit;
Key(int keyBit) {
this.keyBit = keyBit;
}
}
}

View file

@ -1,12 +0,0 @@
package com.mrmichel.rustboyadvance;
public class RomHelper {
static {
System.loadLibrary("rustboyadvance_jni");
}
public static native String getGameCode(byte[] romData);
public static native String getGameTitle(byte[] romData);
}

View file

@ -1,164 +0,0 @@
package com.mrmichel.rustdroid_emu;
import android.app.Activity;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Build;
import android.util.Log;
import androidx.appcompat.app.AlertDialog;
import androidx.core.content.FileProvider;
import com.mrmichel.rustdroid_emu.ui.EmulatorActivity;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
public class Util {
private static final String TAG = "Util";
public static void startEmulator(Context context, byte[] bios, int romId) {
Intent intent = new Intent(context, EmulatorActivity.class);
intent.putExtra("bios", bios);
intent.putExtra("romId", romId);
context.startActivity(intent);
}
public static void showAlertDialogAndExit(final Activity activity, Exception e) {
new AlertDialog.Builder(activity)
.setTitle(e.toString())
.setMessage(e.getMessage())
// Specifying a listener allows you to take an action before dismissing the dialog.
// The dialog is automatically dismissed when a dialog button is clicked.
.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
activity.finishAffinity();
}
})
.setIcon(android.R.drawable.ic_dialog_alert)
.show();
}
public static void showAlertDialog(final Activity activity, Exception e) {
new AlertDialog.Builder(activity)
.setTitle(e.toString())
.setMessage(e.getMessage())
.setIcon(android.R.drawable.ic_dialog_alert)
.show();
}
public static byte[] compressBitmapToByteArray(Bitmap bitmap) {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 10, byteArrayOutputStream);
return byteArrayOutputStream.toByteArray();
}
public static void writeCompressedFile(File file, byte[] bytes) {
try {
FileOutputStream fos = new FileOutputStream(file);
GZIPOutputStream gos = new GZIPOutputStream(fos);
gos.write(bytes);
gos.close();
fos.close();
} catch (Exception e) {
Log.e(TAG, "failed to write compressed file " + file.toString() + " error: " + e.getMessage());
}
}
public static byte[] readCompressedFile(File file) {
try {
byte[] buffer = new byte[8192];
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
GZIPInputStream gis = new GZIPInputStream(new FileInputStream(file));
int len;
while ((len = gis.read(buffer, 0, 8192)) != -1) {
outputStream.write(buffer, 0, len);
}
gis.close();
return outputStream.toByteArray();
} catch (Exception e) {
Log.e(TAG, "failed to read compressed file " + file.toString() + " error: " + e.getMessage());
return null;
}
}
public static byte[] readFile(File file) throws IOException {
byte[] buffer = new byte[8192];
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
FileInputStream fis = new FileInputStream(file);
int len;
while ((len = fis.read(buffer, 0, 8192)) != -1) {
outputStream.write(buffer, 0, len);
}
fis.close();
return outputStream.toByteArray();
}
public static String byteArrayToHexString(final byte[] bytes) {
StringBuilder sb = new StringBuilder();
for (byte b : bytes) {
sb.append(String.format("%02x", b & 0xff));
}
return sb.toString();
}
public static String getHash(final byte[] bytes) {
MessageDigest md;
try {
md = MessageDigest.getInstance("SHA-256");
} catch (NoSuchAlgorithmException e) {
// impossible
Log.e("SnapshotManager", "SHA-256 algo not found");
return null;
}
md.update(bytes);
return byteArrayToHexString(md.digest());
}
public static void shareFile(Context context, File file, String message) throws FileNotFoundException {
if (!file.exists()) {
throw new FileNotFoundException("file does not exist");
}
final Uri uri;
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
uri = Uri.fromFile(file);
} else {
uri = FileProvider.getUriForFile(context, context.getPackageName() + ".provider", file);
}
if (uri == null) {
throw new FileNotFoundException("could not find file to share");
}
Intent intentShareFile = new Intent(Intent.ACTION_SEND);
intentShareFile.setType("*/*");
intentShareFile.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intentShareFile.putExtra(Intent.EXTRA_STREAM, uri);
intentShareFile.putExtra(Intent.EXTRA_TEXT, message);
context.startActivity(Intent.createChooser(intentShareFile, message));
}
}

View file

@ -1,89 +0,0 @@
package com.mrmichel.rustdroid_emu.core;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioTrack;
import android.os.Build;
import android.util.Log;
import com.mrmichel.rustboyadvance.IAudioPlayer;
/**
* Simple wrapper around the android AudioTrack class that implements IAudioPlayer
*/
public class AndroidAudioPlayer implements IAudioPlayer {
private static final String TAG = "AndroidAudioPlayer";
private static final int BUFFER_SIZE_IN_BYTES = 8192;
private static int SAMPLE_RATE_HZ = 44100;
private AudioTrack audioTrack;
public AndroidAudioPlayer() {
if (Build.VERSION.SDK_INT >= 23) {
AudioTrack.Builder audioTrackBuilder = new AudioTrack.Builder()
.setAudioFormat(new AudioFormat.Builder()
.setEncoding(AudioFormat.ENCODING_PCM_16BIT)
.setSampleRate(SAMPLE_RATE_HZ)
.setChannelMask(AudioFormat.CHANNEL_IN_STEREO | AudioFormat.CHANNEL_OUT_STEREO)
.build()
)
.setBufferSizeInBytes(AndroidAudioPlayer.BUFFER_SIZE_IN_BYTES)
.setTransferMode(AudioTrack.MODE_STREAM);
if (Build.VERSION.SDK_INT >= 26) {
audioTrackBuilder.setPerformanceMode(AudioTrack.PERFORMANCE_MODE_LOW_LATENCY);
}
this.audioTrack = audioTrackBuilder.build();
} else {
this.audioTrack = new AudioTrack(
AudioManager.STREAM_MUSIC,
SAMPLE_RATE_HZ,
AudioFormat.CHANNEL_IN_STEREO | AudioFormat.CHANNEL_OUT_STEREO,
AudioFormat.ENCODING_PCM_16BIT,
AndroidAudioPlayer.BUFFER_SIZE_IN_BYTES,
AudioTrack.MODE_STREAM);
}
Log.d(TAG, "sampleCount = " + this.getSampleCount());
}
@Override
public int audioWrite(short[] buffer, int offsetInShorts, int sizeInShorts) {
if (Build.VERSION.SDK_INT >= 23) {
return this.audioTrack.write(buffer, offsetInShorts, sizeInShorts, AudioTrack.WRITE_NON_BLOCKING);
} else {
// Native bindings will do its best to make sure this doesn't block anyway
return this.audioTrack.write(buffer, offsetInShorts, sizeInShorts);
}
}
@Override
public void pause() {
this.audioTrack.pause();
}
@Override
public void play() {
this.audioTrack.play();
}
@Override
public int getSampleCount() {
if (Build.VERSION.SDK_INT >= 23) {
return this.audioTrack.getBufferSizeInFrames();
} else {
return BUFFER_SIZE_IN_BYTES / 2;
}
}
@Override
public int getSampleRate() {
return this.audioTrack.getSampleRate();
}
@Override
public int availableBufferSize() {
return 2;
}
}

View file

@ -1,127 +0,0 @@
package com.mrmichel.rustdroid_emu.core;
import com.mrmichel.rustboyadvance.EmulatorBindings;
import com.mrmichel.rustboyadvance.IFrameRenderer;
import com.mrmichel.rustboyadvance.Keypad;
public class Emulator {
public Keypad keypad;
/// context received by the native binding
private long ctx = -1;
private AndroidAudioPlayer audioPlayer;
private IFrameRenderer frameRenderer;
public Emulator(IFrameRenderer frameRenderer, AndroidAudioPlayer audioPlayer) {
this.keypad = new Keypad();
this.frameRenderer = frameRenderer;
this.audioPlayer = audioPlayer;
}
public Emulator(long ctx, IFrameRenderer frameRenderer, AndroidAudioPlayer audioPlayer) {
this.ctx = ctx;
this.frameRenderer = frameRenderer;
this.audioPlayer = audioPlayer;
this.keypad = new Keypad();
}
/**
* Get the native emulator handle for caching
*/
public long getCtx() {
return ctx;
}
public void runMainLoop() {
EmulatorBindings.runMainLoop(this.ctx);
}
public void pause() {
EmulatorBindings.pause(this.ctx);
this.audioPlayer.pause();
}
public void resume() {
EmulatorBindings.resume(this.ctx);
this.audioPlayer.play();
}
public void setTurbo(boolean turbo) {
EmulatorBindings.setTurbo(ctx, turbo);
}
public void stop() {
EmulatorBindings.stop(this.ctx);
this.audioPlayer.pause();
}
public int[] getFrameBuffer() {
return EmulatorBindings.getFrameBuffer(this.ctx);
}
public synchronized byte[] saveState() throws EmulatorBindings.NativeBindingException {
return EmulatorBindings.saveState(this.ctx);
}
public synchronized void loadState(byte[] state) throws EmulatorBindings.NativeBindingException, EmulatorException {
if (ctx != -1) {
EmulatorBindings.loadState(this.ctx, state);
} else {
throw new EmulatorException("Call open() first");
}
}
public synchronized void open(byte[] bios, byte[] rom, String saveName, boolean skipBios) throws EmulatorBindings.NativeBindingException {
this.ctx = EmulatorBindings.openEmulator(bios, rom, this.frameRenderer, this.audioPlayer, this.keypad, saveName, skipBios);
}
public synchronized void openSavedState(byte[] bios, byte[] rom, byte[] savedState) throws EmulatorBindings.NativeBindingException {
this.ctx = EmulatorBindings.openSavedState(bios, rom, savedState, this.frameRenderer, this.audioPlayer, this.keypad);
}
public synchronized void close() {
if (this.ctx != -1) {
EmulatorBindings.closeEmulator(this.ctx);
this.ctx = -1;
}
}
public String getGameCode() {
if (ctx != -1) {
return EmulatorBindings.getGameCode(ctx);
} else {
return null;
}
}
public String getGameTitle() {
if (ctx != -1) {
return EmulatorBindings.getGameTitle(ctx);
} else {
return null;
}
}
public boolean isOpen() {
return this.ctx != -1;
}
@Override
protected void finalize() throws Throwable {
super.finalize();
close();
}
public synchronized void log() {
EmulatorBindings.log(this.ctx);
}
public class EmulatorException extends Exception {
public EmulatorException(String errorMessage) {
super(errorMessage);
}
}
}

View file

@ -1,321 +0,0 @@
package com.mrmichel.rustdroid_emu.core;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.util.Log;
import android.widget.Toast;
import androidx.annotation.Nullable;
import androidx.documentfile.provider.DocumentFile;
import com.mrmichel.rustboyadvance.RomHelper;
import com.mrmichel.rustdroid_emu.Util;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.sql.Timestamp;
import java.util.ArrayList;
public class RomManager {
private static final String TAG = "RomManager";
private static RomManager instance;
private RomDatabaseHelper dbHelper;
private Context context;
public RomManager(Context context) {
this.context = context;
this.dbHelper = new RomDatabaseHelper(this.context, 1);
}
public static RomManager getInstance(Context context) {
if (instance == null) {
instance = new RomManager(context);
}
return instance;
}
private static String byteArrayToHexString(final byte[] bytes) {
StringBuilder sb = new StringBuilder();
for (byte b : bytes) {
sb.append(String.format("%02x", b & 0xff));
}
return sb.toString();
}
private static String getHash(final byte[] bytes) {
MessageDigest md;
try {
md = MessageDigest.getInstance("SHA-256");
} catch (NoSuchAlgorithmException e) {
// impossible
Log.e(TAG, "SHA-256 algo not found");
return null;
}
md.update(bytes);
return byteArrayToHexString(md.digest());
}
public ArrayList<RomMetadataEntry> getAllRomMetaData() {
return this.dbHelper.queryRomMetadata("SELECT * FROM " + RomDatabaseHelper.TABLE_METADATA + " ORDER BY lastPlayed DESC");
}
public RomMetadataEntry getRomMetadata(byte[] romData) {
String romHash = getHash(romData);
ArrayList<RomMetadataEntry> metadataEntries = dbHelper.queryRomMetadata(
"SELECT * FROM " + RomDatabaseHelper.TABLE_METADATA + " where hash == '" + romHash + "'");
if (metadataEntries.size() > 0) {
return metadataEntries.get(0);
} else {
return null;
}
}
public RomMetadataEntry getRomMetadata(int romId) {
ArrayList<RomMetadataEntry> metadataEntries = dbHelper.queryRomMetadata(
"SELECT * FROM " + RomDatabaseHelper.TABLE_METADATA + " where id = '" + romId + "'");
if (metadataEntries.size() > 0) {
return metadataEntries.get(0);
} else {
return null;
}
}
private byte[] readFromUri(Uri uri) throws IOException {
ContentResolver cr = context.getContentResolver();
InputStream is = cr.openInputStream(uri);
byte[] data = new byte[is.available()];
is.read(data);
return data;
}
public void importRom(DocumentFile documentFile) {
Uri uri = documentFile.getUri();
byte[] romData;
try {
romData = readFromUri(uri);
} catch (Exception e) {
Log.e(TAG, "could not read rom file");
return;
}
if (null != getRomMetadata(romData)) {
Toast.makeText(context, "This rom is already imported!", Toast.LENGTH_LONG).show();
return;
}
String hash = getHash(romData);
String gameCode = RomHelper.getGameCode(romData);
String gameTitle = RomHelper.getGameTitle(romData);
String romFileName = documentFile.getName();
// Multiple roms can have the same title+code combo, so we rely on a hash to be a unique identifier.
File baseDir = new File(context.getFilesDir(), hash);
baseDir.mkdirs();
File romFile = new File(baseDir, romFileName);
// cache the rom
try {
FileOutputStream fileOutputStream = new FileOutputStream(romFile);
fileOutputStream.write(romData);
} catch (Exception e) {
Log.e(TAG, "cannot cache rom file");
}
File backupFile = new File(baseDir, romFileName + ".sav");
SQLiteDatabase db = dbHelper.getWritableDatabase();
ContentValues cv = new ContentValues();
cv.put("name", romFileName);
cv.put("gameTitle", gameTitle);
cv.put("gameCode", gameCode);
cv.put("hash", hash);
cv.put("path", romFile.getPath());
cv.put("backupPath", backupFile.getPath());
db.insertOrThrow(RomDatabaseHelper.TABLE_METADATA, null, cv);
db.close();
}
public void deleteRomMetadata(RomMetadataEntry romMetadataEntry) {
SQLiteDatabase db = dbHelper.getWritableDatabase();
db.delete(RomDatabaseHelper.TABLE_METADATA, "id=" + romMetadataEntry.getId(), null);
}
public void updateLastPlayed(int romId) {
Timestamp now = new Timestamp(System.currentTimeMillis());
ContentValues cv = new ContentValues();
cv.put("lastPlayed", now.toString());
SQLiteDatabase db = dbHelper.getWritableDatabase();
db.update(RomDatabaseHelper.TABLE_METADATA, cv, "id=" + romId, null);
}
public void updateScreenshot(int romId, Bitmap bitmap) {
ContentValues cv = new ContentValues();
cv.put("screenshot", Util.compressBitmapToByteArray(bitmap));
SQLiteDatabase db = dbHelper.getWritableDatabase();
db.update(RomDatabaseHelper.TABLE_METADATA, cv, "id=" + romId, null);
}
public class RomMetadataEntry {
int id;
String name;
String gameTitle;
String gameCode;
File romFile;
File backupFile;
Bitmap screenshot;
Timestamp lastPlayed;
private RomMetadataEntry(int id, String name, String gameTitle, String gameCode, File romFile, File backupFile, Bitmap screenshot, Timestamp lastPlayed) {
this.id = id;
this.name = name;
this.gameTitle = gameTitle;
this.gameCode = gameCode;
this.romFile = romFile;
this.backupFile = backupFile;
this.screenshot = screenshot;
this.lastPlayed = lastPlayed;
}
public String getName() {
return name;
}
public int getId() {
return id;
}
public Bitmap getScreenshot() {
return screenshot;
}
public File getBackupFile() {
return backupFile;
}
public File getRomFile() {
return romFile;
}
public String getGameTitle() {
return gameTitle;
}
public String getGameCode() {
return gameCode;
}
public Timestamp getLastPlayed() {
return lastPlayed;
}
}
private class RomDatabaseHelper extends SQLiteOpenHelper {
private static final String DATABASE_NAME = "rom_db";
private static final String TABLE_METADATA = "rom_metadata";
public RomDatabaseHelper(@Nullable Context context, int version) {
super(context, DATABASE_NAME, null, version);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("create table " + TABLE_METADATA +
" (id INTEGER PRIMARY KEY," +
"name TEXT UNIQUE," +
"hash TEXT UNIQUE," +
"gameTitle TEXT," +
"gameCode TEXT," +
"screenshot BLOB," +
"lastPlayed TIMESTAMP," +
"path TEXT UNIQUE," +
"backupPath TEXT UNIQUE" +
")");
}
public ArrayList<RomMetadataEntry> queryRomMetadata(String query) {
ArrayList<RomMetadataEntry> arrayList = new ArrayList<>();
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.rawQuery(query, null);
if (cursor.moveToFirst()) {
do {
String name = cursor.getString(cursor.getColumnIndex("name"));
File romFile = new File(cursor.getString(cursor.getColumnIndex("path")));
File backupFile = new File(cursor.getString(cursor.getColumnIndex("backupPath")));
byte[] screenshotBlob = cursor.getBlob(cursor.getColumnIndex("screenshot"));
Bitmap screenshot;
if (null != screenshotBlob) {
screenshot = BitmapFactory.decodeByteArray(screenshotBlob, 0, screenshotBlob.length);
} else {
screenshot = null;
}
String gameTitle = cursor.getString(cursor.getColumnIndex("gameTitle"));
String gameCode = cursor.getString(cursor.getColumnIndex("gameCode"));
int id = cursor.getInt(cursor.getColumnIndex("id"));
String lastPlayedString = cursor.getString(cursor.getColumnIndex("lastPlayed"));
Timestamp lastPlayed;
if (lastPlayedString != null) {
lastPlayed = Timestamp.valueOf(lastPlayedString);
} else {
lastPlayed = null;
}
arrayList.add(new RomMetadataEntry(id, name, gameTitle, gameCode, romFile, backupFile, screenshot, lastPlayed));
} while (cursor.moveToNext());
}
cursor.close();
db.close();
return arrayList;
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS " + TABLE_METADATA);
onCreate(db);
}
}
}

View file

@ -1,55 +0,0 @@
package com.mrmichel.rustdroid_emu.core;
import android.graphics.Bitmap;
import com.mrmichel.rustdroid_emu.Util;
import java.io.File;
public class Snapshot {
private Bitmap preview;
private String gameCode;
private String gameTitle;
private long timestamp;
private File file;
public Snapshot(File file, String gameCode, String gameTitle, Bitmap preview) {
this.file = file;
this.gameCode = gameCode;
this.gameTitle = gameTitle;
this.preview = preview;
this.timestamp = System.currentTimeMillis();
}
public Snapshot(File file, String gameCode, String gameTitle, Bitmap preview, long timestamp) {
this.file = file;
this.gameCode = gameCode;
this.gameTitle = gameTitle;
this.preview = preview;
this.timestamp = timestamp;
}
public File getFile() {
return file;
}
public String getGameCode() {
return gameCode;
}
public String getGameTitle() {
return gameTitle;
}
public long getTimestamp() {
return timestamp;
}
public Bitmap getPreview() {
return preview;
}
public byte[] load() {
return Util.readCompressedFile(this.file);
}
}

View file

@ -1,169 +0,0 @@
package com.mrmichel.rustdroid_emu.core;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import com.mrmichel.rustdroid_emu.Util;
import java.io.File;
import java.sql.Timestamp;
import java.util.ArrayList;
public class SnapshotManager {
private static final String TAG = "SnapshotManager";
private static final String SNAPSHOT_ROOT = "snapshots";
private static final String DB_NAME = "snapshots";
static SnapshotManager instance;
private Context context;
private SnapshotDatabaseHelper dbHelper;
private SnapshotManager(Context context) {
this.context = context;
this.dbHelper = new SnapshotDatabaseHelper(this.context);
// this.snapshotDB = context.openOrCreateDatabase("snapshots", Context.MODE_PRIVATE, null);
}
public static SnapshotManager getInstance(Context context) {
if (instance == null) {
instance = new SnapshotManager(context);
}
return instance;
}
private File getPreviewsDir(String gameCode) {
File d = new File(context.getFilesDir(), SNAPSHOT_ROOT + "/previews");
d.mkdirs();
return d;
}
private File getSnapshotDir(String gameCode) {
File d = new File(context.getFilesDir(), SNAPSHOT_ROOT + "/data");
d.mkdirs();
return d;
}
public void saveSnapshot(String gameCode, String gameTitle, Bitmap previewImage, byte[] data) {
byte[] previewImageBytes = Util.compressBitmapToByteArray(previewImage);
String hash = Util.getHash(data);
File previewsDir = getPreviewsDir(gameCode);
File snapshotsDir = getSnapshotDir(gameCode);
File previewFile = new File(previewsDir, hash);
Util.writeCompressedFile(previewFile, previewImageBytes);
File snapshotFile = new File(snapshotsDir, hash);
Util.writeCompressedFile(snapshotFile, data);
this.dbHelper.insertSnapshot(gameCode, gameTitle, previewFile, snapshotFile);
}
public void deleteSnapshot(Snapshot snapshot) {
SQLiteDatabase db = dbHelper.getWritableDatabase();
File file = snapshot.getFile();
db.delete(SnapshotDatabaseHelper.TABLE_NAME, "dataFile = '" + file.toString() + "'", null);
file.delete();
}
public ArrayList<Snapshot> getAllSnapshots() {
return this.dbHelper.getEntries();
}
public ArrayList<Snapshot> getByGameCode(String gameCode) {
return this.dbHelper.getEntries(gameCode);
}
public class SnapshotDBEntry {
String gameCode;
String gameTitle;
File previewFile;
File snapshotFile;
Timestamp timestamp;
public SnapshotDBEntry(String gameCode, File previewFile, File snapshotFile, Timestamp timestamp) {
this.gameCode = gameCode;
this.previewFile = previewFile;
this.snapshotFile = snapshotFile;
this.timestamp = timestamp;
}
}
public class SnapshotDatabaseHelper extends SQLiteOpenHelper {
public static final String TABLE_NAME = "snapshot_table";
private Context context;
public SnapshotDatabaseHelper(Context context) {
super(context, DB_NAME, null, 1);
this.context = context;
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("create table " + TABLE_NAME +
" (id INTEGER PRIMARY KEY, gameCode TEXT, gameTitle TEXT, timestamp DATETIME DEFAULT CURRENT_TIMESTAMP, previewImageFile TEXT, dataFile TEXT)"
);
}
public void insertSnapshot(String gameCode, String gameTitle, File previewCacheFile, File snapshotDataFile) {
SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues();
values.put("gameCode", gameCode);
values.put("gameTitle", gameTitle);
values.put("previewImageFile", previewCacheFile.getPath());
values.put("dataFile", snapshotDataFile.getPath());
db.insertOrThrow(TABLE_NAME, null, values);
db.close();
}
public ArrayList<Snapshot> getEntriesByQuery(String query) {
ArrayList<Snapshot> arrayList = new ArrayList<>();
SQLiteDatabase db = this.getWritableDatabase();
Cursor cursor = db.rawQuery(query, null);
if (cursor.moveToFirst()) {
do {
String gameCode = cursor.getString(1);
String gameTitle = cursor.getString(2);
Timestamp timestamp = Timestamp.valueOf(cursor.getString(3));
File previewImageFile = new File(cursor.getString(4));
File dataFile = new File(cursor.getString(5));
byte[] previewData = Util.readCompressedFile(previewImageFile);
Bitmap previewBitmap = BitmapFactory.decodeByteArray(previewData, 0, previewData.length);
arrayList.add(new Snapshot(dataFile, gameCode, gameTitle, previewBitmap, timestamp.getTime()));
} while (cursor.moveToNext());
}
cursor.close();
db.close();
return arrayList;
}
public ArrayList<Snapshot> getEntries() {
return getEntriesByQuery("SELECT * FROM " + TABLE_NAME + " ORDER BY timestamp DESC ");
}
public ArrayList<Snapshot> getEntries(String gameCode) {
return getEntriesByQuery("SELECT * FROM " + TABLE_NAME + " where gameCode = '" + gameCode + "' ORDER BY timestamp DESC ");
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
}

View file

@ -1,49 +0,0 @@
package com.mrmichel.rustdroid_emu.ui;
import android.util.Log;
import com.mrmichel.rustdroid_emu.core.Emulator;
public class EmulationThread extends Thread {
private static final String TAG = "EmulationThread";
public static final long NANOSECONDS_PER_MILLISECOND = 1000000;
public static final long FRAME_TIME = 1000000000 / 60;
private Emulator emulator;
private ScreenView screenView;
private boolean running;
public EmulationThread(Emulator emulator, ScreenView screenView) {
this.emulator = emulator;
this.screenView = screenView;
this.running = false;
}
public void pauseEmulation() {
this.emulator.pause();
}
public void resumeEmulation() {
this.emulator.resume();
}
@Override
public void run() {
super.run();
// wait until renderer is ready
while (!screenView.getRenderer().isReady());
while (!emulator.isOpen());
running = true;
emulator.runMainLoop();
Log.d(TAG, "Native runMainLoop returned!");
running = false;
}
}

View file

@ -1,573 +0,0 @@
package com.mrmichel.rustdroid_emu.ui;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.widget.CompoundButton;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.preference.PreferenceManager;
import com.mrmichel.rustboyadvance.EmulatorBindings;
import com.mrmichel.rustboyadvance.Keypad;
import com.mrmichel.rustdroid_emu.R;
import com.mrmichel.rustdroid_emu.Util;
import com.mrmichel.rustdroid_emu.core.AndroidAudioPlayer;
import com.mrmichel.rustdroid_emu.core.Emulator;
import com.mrmichel.rustdroid_emu.core.RomManager;
import com.mrmichel.rustdroid_emu.core.Snapshot;
import com.mrmichel.rustdroid_emu.core.SnapshotManager;
import com.mrmichel.rustdroid_emu.ui.snapshots.SnapshotPickerActivity;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
public class EmulatorActivity extends AppCompatActivity implements View.OnClickListener, View.OnTouchListener {
private static final String TAG = "EmulatorActivty";
private static final String TAG_EMULATOR_STATE = "EmulatorStateFragment";
private static final int LOAD_ROM_REQUESTCODE = 123;
private static final int LOAD_SNAPSHOT_REQUESTCODE = 124;
private Menu menu;
private RomManager.RomMetadataEntry romMetadata;
private byte[] bios;
private EmulationThread emulationThread;
private AndroidAudioPlayer audioPlayer;
private byte[] on_resume_saved_state = null;
private Emulator emulator;
private ScreenView screenView;
private CompoundButton turboButton;
private boolean isEmulatorRunning() {
return emulator.isOpen() && emulationThread != null;
}
@Override
public void onClick(View v) {
if (v.getId() == R.id.tbTurbo) {
if (!isEmulatorRunning()) {
return;
}
emulator.setTurbo(((CompoundButton) findViewById(R.id.tbTurbo)).isChecked());
}
}
@Override
public boolean onTouch(View v, MotionEvent event) {
Keypad.Key key = null;
switch (v.getId()) {
case R.id.bDpadUp:
key = Keypad.Key.Up;
break;
case R.id.bDpadDown:
key = Keypad.Key.Down;
break;
case R.id.bDpadLeft:
key = Keypad.Key.Left;
break;
case R.id.bDpadRight:
key = Keypad.Key.Right;
break;
case R.id.buttonA:
key = Keypad.Key.ButtonA;
break;
case R.id.buttonB:
key = Keypad.Key.ButtonB;
break;
case R.id.buttonL:
key = Keypad.Key.ButtonL;
break;
case R.id.buttonR:
key = Keypad.Key.ButtonR;
break;
case R.id.bStart:
key = Keypad.Key.Start;
break;
case R.id.bSelect:
key = Keypad.Key.Select;
break;
}
int action = event.getAction();
if (key != null) {
if (action == MotionEvent.ACTION_DOWN) {
v.setPressed(true);
emulator.keypad.onKeyDown(key);
} else if (action == MotionEvent.ACTION_UP) {
v.setPressed(false);
emulator.keypad.onKeyUp(key);
} else if (action == MotionEvent.ACTION_OUTSIDE) {
v.setPressed(false);
emulator.keypad.onKeyUp(key);
}
}
return true;
}
public Keypad.Key keyCodeToGbaKey(int keyCode) {
switch (keyCode) {
case KeyEvent.KEYCODE_DPAD_UP:
return Keypad.Key.Up;
case KeyEvent.KEYCODE_DPAD_DOWN:
return Keypad.Key.Down;
case KeyEvent.KEYCODE_DPAD_LEFT:
return Keypad.Key.Left;
case KeyEvent.KEYCODE_DPAD_RIGHT:
return Keypad.Key.Right;
case KeyEvent.KEYCODE_Z:
return Keypad.Key.ButtonB;
case KeyEvent.KEYCODE_X:
return Keypad.Key.ButtonA;
case KeyEvent.KEYCODE_A:
return Keypad.Key.ButtonL;
case KeyEvent.KEYCODE_S:
return Keypad.Key.ButtonR;
case KeyEvent.KEYCODE_DEL:
return Keypad.Key.Select;
case KeyEvent.KEYCODE_COMMA:
return Keypad.Key.Start;
}
return null;
}
@Override
public boolean onKeyLongPress(int keyCode, KeyEvent event) {
if (!isEmulatorRunning()) {
return false;
}
Keypad.Key key = keyCodeToGbaKey(keyCode);
Log.d(TAG, "onKeyLongPress(: keyCode = " + keyCode + " GBAKey:" + key);
if (null != key) {
this.emulator.keypad.onKeyDown(key);
return false;
} else {
return super.onKeyDown(keyCode, event);
}
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (!isEmulatorRunning()) {
return false;
}
Keypad.Key key = keyCodeToGbaKey(keyCode);
Log.d(TAG, "onKeyDown: keyCode = " + keyCode + " GBAKey:" + key);
if (null != key) {
switch (event.getAction()) {
case KeyEvent.ACTION_DOWN:
this.emulator.keypad.onKeyDown(key);
break;
case KeyEvent.ACTION_UP:
this.emulator.keypad.onKeyUp(key);
break;
}
return event.getAction() == KeyEvent.ACTION_DOWN;
} else {
return super.onKeyDown(keyCode, event);
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK) {
// if (requestCode == LOAD_ROM_REQUESTCODE) {
// Uri uri = data.getData();
// try {
// InputStream inputStream = getContentResolver().openInputStream(uri);
// byte[] rom = new byte[inputStream.available()];
// inputStream.read(rom);
// inputStream.close();
//
// String filename = new File(uri.getPath()).getName();
//
// File saveRoot = getFilesDir();
// String savePath = saveRoot.getAbsolutePath() + "/" + filename + ".sav";
// onRomLoaded(rom, savePath);
// } catch (Exception e) {
// Log.e(TAG, "got error while reading rom file");
// Util.showAlertDialogAndExit(this, e);
// }
// }
if (requestCode == LOAD_SNAPSHOT_REQUESTCODE) {
Snapshot pickedSnapshot = SnapshotPickerActivity.obtainPickedSnapshot();
Toast.makeText(this, "Loading snapshot from " + pickedSnapshot.getTimestamp(), Toast.LENGTH_LONG).show();
boolean emulatorWasRunning = isEmulatorRunning();
pauseEmulation();
try {
emulator.loadState(pickedSnapshot.load());
} catch (Exception e) {
Util.showAlertDialogAndExit(this, e);
}
resumeEmulation();
if (!emulatorWasRunning) {
createThreads();
}
}
} else {
Log.e(TAG, "got error for request code " + requestCode);
}
}
private void killThreads() {
if (emulationThread != null) {
try {
emulator.stop();
emulationThread.join();
} catch (InterruptedException e) {
Log.e(TAG, "emulation thread join interrupted");
}
emulationThread = null;
}
}
private void createThreads() {
emulationThread = new EmulationThread(emulator, screenView);
emulator.setTurbo(turboButton.isChecked());
emulationThread.start();
}
public void onRomLoaded(byte[] rom, String savePath) {
// killThreads();
//
// try {
// emulator.open(bios, rom, savePath);
// } catch (EmulatorBindings.NativeBindingException e) {
// Util.showAlertDialogAndExit(this, e);
// }
//
// createThreads();
}
public void doLoadRom() {
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
intent.setType("*/*");
intent.putExtra("android.content.extra.SHOW_ADVANCED", true);
startActivityForResult(intent, LOAD_ROM_REQUESTCODE);
}
@Override
protected void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState);
if (!isEmulatorRunning()) {
return;
}
// save the emulator state
try {
byte[] savedState = emulator.saveState();
File saveFile = new File(getCacheDir(), "saved_state");
FileOutputStream fis = new FileOutputStream(saveFile);
fis.write(savedState);
fis.close();
outState.putString("saveFile", saveFile.getPath());
outState.putInt("romId", this.romMetadata.getId());
outState.putBoolean("turbo", false);
} catch (Exception e) {
Util.showAlertDialogAndExit(this, e);
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_emulator);
this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
this.audioPlayer = new AndroidAudioPlayer();
findViewById(R.id.bStart).setOnTouchListener(this);
findViewById(R.id.bSelect).setOnTouchListener(this);
findViewById(R.id.buttonA).setOnTouchListener(this);
findViewById(R.id.buttonB).setOnTouchListener(this);
findViewById(R.id.buttonL).setOnTouchListener(this);
findViewById(R.id.buttonR).setOnTouchListener(this);
findViewById(R.id.bDpadUp).setOnTouchListener(this);
findViewById(R.id.bDpadDown).setOnTouchListener(this);
findViewById(R.id.bDpadLeft).setOnTouchListener(this);
findViewById(R.id.bDpadRight).setOnTouchListener(this);
turboButton = findViewById(R.id.tbTurbo);
turboButton.setOnClickListener(this);
this.bios = getIntent().getByteArrayExtra("bios");
this.screenView = findViewById(R.id.gba_view);
this.emulator = new Emulator(this.screenView, this.audioPlayer);
final String saveFilePath;
SharedPreferences sharedPreferences =
PreferenceManager.getDefaultSharedPreferences(this /* Activity context */);
boolean skipBios = sharedPreferences.getBoolean("skip_bios", false);
if (null != savedInstanceState && (saveFilePath = savedInstanceState.getString("saveFile")) != null) {
final EmulatorActivity thisActivity = this;
int romId = getIntent().getIntExtra("romId", -1);
// busy wait until surface view is ready
try {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
byte[] buffer = new byte[4096];
File saveFile = new File(saveFilePath);
FileInputStream fis = new FileInputStream(saveFile);
int read = 0;
while ((read = fis.read(buffer)) != -1) {
outputStream.write(buffer);
}
fis.close();
saveFile.delete();
byte[] savedState = outputStream.toByteArray();
RomManager romManager = RomManager.getInstance(this);
romManager.updateLastPlayed(romId);
this.romMetadata = romManager.getRomMetadata(romId);
byte[] romData;
try {
romData = Util.readFile(romMetadata.getRomFile());
} catch (Exception e) {
Util.showAlertDialogAndExit(this, e);
return;
}
emulator.openSavedState(this.bios, romData, savedState);
createThreads();
boolean turbo = savedInstanceState.getBoolean("turbo");
turboButton.setPressed(turbo);
emulator.setTurbo(turbo);
} catch (Exception e) {
Util.showAlertDialogAndExit(thisActivity, e);
}
} else {
int romId = getIntent().getIntExtra("romId", -1);
if (-1 != romId) {
RomManager romManager = RomManager.getInstance(this);
romManager.updateLastPlayed(romId);
this.romMetadata = romManager.getRomMetadata(romId);
byte[] romData;
try {
romData = Util.readFile(romMetadata.getRomFile());
this.emulator.open(bios, romData, romMetadata.getBackupFile().getAbsolutePath(), skipBios);
} catch (Exception e) {
Util.showAlertDialogAndExit(this, e);
return;
}
createThreads();
}
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
getMenuInflater().inflate(R.menu.menu_emulator, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.action_load_rom:
doLoadRom();
return true;
case R.id.action_view_snapshots:
doViewSnapshots();
return true;
case R.id.action_save_snapshot:
doSaveSnapshot();
return true;
case R.id.action_set_library_image:
doSaveScreenshotToLibrary();
return true;
case R.id.action_settings:
Intent intent = new Intent(this, SettingsActivity.class);
startActivity(intent);
return true;
default:
return super.onOptionsItemSelected(item);
}
}
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
menu.findItem(R.id.action_save_snapshot).setEnabled(isEmulatorRunning());
return super.onPrepareOptionsMenu(menu);
}
private void pauseEmulation() {
if (null != emulationThread) {
emulationThread.pauseEmulation();
}
}
private void resumeEmulation() {
if (null != emulationThread) {
emulationThread.resumeEmulation();
}
}
@Override
protected void onDestroy() {
super.onDestroy();
pauseEmulation();
if (this.romMetadata != null) {
if (this.romMetadata.getScreenshot() == null) {
// Save current screenshot
Bitmap screenshot = Bitmap.createBitmap(
emulator.getFrameBuffer(),
240,
160,
Bitmap.Config.RGB_565);
RomManager.getInstance(this).updateScreenshot(this.romMetadata.getId(), screenshot);
}
}
killThreads();
}
@Override
protected void onPause() {
super.onPause();
pauseEmulation();
screenView.onPause();
}
@Override
protected void onResume() {
super.onResume();
screenView.onResume();
resumeEmulation();
audioPlayer.play();
}
public void doSaveScreenshotToLibrary() {
if (!isEmulatorRunning() || null == this.romMetadata) {
Toast.makeText(this, "No game is running!", Toast.LENGTH_LONG).show();
return;
}
pauseEmulation();
Bitmap screenshot = Bitmap.createBitmap(
emulator.getFrameBuffer(),
240,
160,
Bitmap.Config.RGB_565);
RomManager.getInstance(this).updateScreenshot(this.romMetadata.getId(), screenshot);
resumeEmulation();
}
public void doSaveSnapshot() {
if (!isEmulatorRunning()) {
Toast.makeText(this, "No game is running!", Toast.LENGTH_LONG).show();
return;
}
SnapshotManager snapshotManager = SnapshotManager.getInstance(this);
pauseEmulation();
try {
String gameCode = emulator.getGameCode();
String gameTitle = emulator.getGameTitle();
byte[] saveState = emulator.saveState();
Bitmap preview = Bitmap.createBitmap(emulator.getFrameBuffer(), 240, 160, Bitmap.Config.RGB_565);
snapshotManager.saveSnapshot(gameCode, gameTitle, preview, saveState);
Toast.makeText(this, "Snapshot saved", Toast.LENGTH_LONG).show();
} catch (EmulatorBindings.NativeBindingException e) {
Log.e(TAG, e.toString());
Util.showAlertDialogAndExit(this, e);
} finally {
resumeEmulation();
}
}
public void doViewSnapshots() {
Intent intent = new Intent(this, SnapshotPickerActivity.class);
if (emulator.isOpen()) {
intent.putExtra("gameCode", emulator.getGameCode());
}
startActivityForResult(intent, LOAD_SNAPSHOT_REQUESTCODE);
}
@Override
public void onBackPressed() {
boolean emulatorIsRunning = isEmulatorRunning();
if (!emulatorIsRunning) {
super.onBackPressed();
return;
}
new AlertDialog.Builder(this)
.setIcon(android.R.drawable.ic_dialog_alert)
.setTitle("Closing Emulator")
.setCancelable(false)
.setMessage("Are you sure you want to close the emulator?")
.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
EmulatorActivity.super.onBackPressed();
}
})
.setNeutralButton("Yes - but save snapshot", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
doSaveSnapshot();
EmulatorActivity.super.onBackPressed();
}
})
.setNegativeButton(android.R.string.no, null)
.show();
}
}

View file

@ -1,265 +0,0 @@
package com.mrmichel.rustdroid_emu.ui;
import android.content.Context;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.opengl.GLES20;
import android.opengl.GLSurfaceView;
import android.opengl.GLUtils;
import androidx.preference.PreferenceManager;
import com.mrmichel.rustdroid_emu.R;
import org.apache.commons.io.IOUtils;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.charset.StandardCharsets;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
public class ScreenRenderer implements GLSurfaceView.Renderer {
private ScreenTexture texture;
private boolean ready = false;
private Context context;
public ScreenRenderer(Context context) {
this.context = context;
}
public void updateTexture(int[] frameBuffer) {
this.texture.update(frameBuffer);
}
public void initTextureIfNotInitialized() {
if (this.texture == null) {
this.texture = new ScreenTexture(this.context);
}
}
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
initTextureIfNotInitialized();
ready = true;
}
@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
gl.glViewport(0, 0, width, height);
}
@Override
public void onDrawFrame(GL10 gl) {
this.texture.render();
}
public boolean isReady() {
return ready;
}
public void setColorCorrection(boolean colorCorrection) {
this.texture.setColorCorrection(colorCorrection);
}
/**
* Private class to manage the screen texture rendering
*/
private class ScreenTexture {
int normalShaderProgram;
int colorCorrectionShaderProgram;
int currentShaderProgram;
int positionHandle;
int texCoordHandle;
int samplerHandle;
int textureId;
private FloatBuffer vertexBuffer;
private FloatBuffer textureBuffer;
private ByteBuffer indicesBuffer;
private Bitmap bitmap;
private Context context;
// square vertices
private float[] vertices = {
-1.0f, 1.0f, 0.0f, // top left
-1.0f, -1.0f, 0.0f, // bottom left
1.0f, -1.0f, 0.0f, // bottom right
1.0f, 1.0f, 0.0f, // top right
};
// texture space vertices
private float[] textureVertices = {
0.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f,
1.0f, 0.0f
};
// two triangles compose a rect
private byte[] indicies = {
0, 1, 2,
0, 2, 3
};
public ScreenTexture(Context context) {
this.context = context;
this.bitmap = Bitmap.createBitmap(240, 160, Bitmap.Config.RGB_565);
GLES20.glEnable(GLES20.GL_TEXTURE_2D);
// create vertex array
vertexBuffer = ByteBuffer.allocateDirect(vertices.length * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
vertexBuffer.put(vertices);
vertexBuffer.position(0);
// create texture coordinate array
textureBuffer = ByteBuffer.allocateDirect(textureVertices.length * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
textureBuffer.put(textureVertices);
textureBuffer.position(0);
// create triangle index array
indicesBuffer = ByteBuffer.allocateDirect(indicies.length).order(ByteOrder.nativeOrder());
indicesBuffer.put(indicies);
indicesBuffer.position(0);
textureId = createTexture();
String vertexShader = readShaderResource(R.raw.screen_texture_vertex_shader);
String normalFragmentShader = readShaderResource(R.raw.screen_texture_fragment_shader);
String colorCorrectionFragmentShader = readShaderResource(R.raw.screen_texture_color_correction_fragment_shader);
normalShaderProgram = createShaderProgram(vertexShader, normalFragmentShader);
colorCorrectionShaderProgram = createShaderProgram(vertexShader, colorCorrectionFragmentShader);
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this.context);
boolean colorCorrection = sharedPreferences.getBoolean("color_correction", false);
setColorCorrection(colorCorrection);
GLES20.glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
}
private void setColorCorrection(boolean colorCorrection) {
if (colorCorrection) {
currentShaderProgram = colorCorrectionShaderProgram;
} else {
currentShaderProgram = normalShaderProgram;
}
// use the program
GLES20.glUseProgram(currentShaderProgram);
positionHandle = GLES20.glGetAttribLocation(currentShaderProgram, "a_position");
texCoordHandle = GLES20.glGetAttribLocation(currentShaderProgram, "a_texCoord");
samplerHandle = GLES20.glGetUniformLocation(currentShaderProgram, "s_texture");
// load the vertex position
GLES20.glVertexAttribPointer(positionHandle, 3, GLES20.GL_FLOAT, false, 0, vertexBuffer);
GLES20.glEnableVertexAttribArray(positionHandle);
// load texture coordinate
GLES20.glVertexAttribPointer(texCoordHandle, 2, GLES20.GL_FLOAT, false, 0, textureBuffer);
GLES20.glEnableVertexAttribArray(texCoordHandle);
GLES20.glVertexAttribPointer(positionHandle, 3, GLES20.GL_FLOAT, false, 0, vertexBuffer);
GLES20.glEnableVertexAttribArray(positionHandle);
// load texture coordinate
GLES20.glVertexAttribPointer(texCoordHandle, 2, GLES20.GL_FLOAT, false, 0, textureBuffer);
GLES20.glEnableVertexAttribArray(texCoordHandle);
}
private int compileShader(int type, String code) {
int shader = GLES20.glCreateShader(type);
GLES20.glShaderSource(shader, code);
GLES20.glCompileShader(shader);
return shader;
}
private void update(int[] frameBuffer) {
bitmap.setPixels(frameBuffer, 0, 240, 0, 0, 240, 160);
}
private int createShaderProgram(String vertexShaderCode, String fragmentShaderCode) {
int vertexShader = compileShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode);
int fragmentShader = compileShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode);
int program = GLES20.glCreateProgram();
GLES20.glAttachShader(program, vertexShader);
GLES20.glAttachShader(program, fragmentShader);
GLES20.glLinkProgram(program);
return program;
}
private int createTexture() {
int[] texturesIds = new int[1];
GLES20.glGenTextures(1, texturesIds, 0);
if (texturesIds[0] == GLES20.GL_FALSE) {
throw new RuntimeException("Error loading texture");
}
// bind the texture
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texturesIds[0]);
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
// set the parameters
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
return texturesIds[0];
}
private String readShaderResource(int resourceId) {
InputStream in = context.getResources().openRawResource(resourceId);
String code;
try {
code = IOUtils.toString(in, StandardCharsets.UTF_8);
} catch (IOException e) {
code = "";
}
return code;
}
protected void destroy() {
GLES20.glDeleteProgram(normalShaderProgram);
GLES20.glDeleteProgram(colorCorrectionShaderProgram);
int[] textures = {textureId};
GLES20.glDeleteTextures(1, textures, 0);
}
public void render() {
// use the shader program
GLES20.glUseProgram(currentShaderProgram);
// clear the color buffer
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
// bind the texture
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureId);
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
// Set the sampler texture unit to 0
GLES20.glUniform1i(samplerHandle, 0);
GLES20.glDrawElements(GLES20.GL_TRIANGLE_STRIP, 6, GLES20.GL_UNSIGNED_BYTE, indicesBuffer);
}
}
}

View file

@ -1,55 +0,0 @@
package com.mrmichel.rustdroid_emu.ui;
import android.content.Context;
import android.content.SharedPreferences;
import android.opengl.GLSurfaceView;
import android.util.AttributeSet;
import androidx.preference.PreferenceManager;
import com.mrmichel.rustboyadvance.IFrameRenderer;
public class ScreenView extends GLSurfaceView implements SharedPreferences.OnSharedPreferenceChangeListener, IFrameRenderer {
private ScreenRenderer mRenderer;
public ScreenView(Context context) {
super(context);
init();
}
public ScreenView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
this.setEGLContextClientVersion(2);
this.setPreserveEGLContextOnPause(true);
SharedPreferences sharedPreferences =
PreferenceManager.getDefaultSharedPreferences(getContext());
sharedPreferences.registerOnSharedPreferenceChangeListener(this);
mRenderer = new ScreenRenderer(getContext());
this.setRenderer(mRenderer);
this.setRenderMode(RENDERMODE_WHEN_DIRTY);
}
public ScreenRenderer getRenderer() {
return mRenderer;
}
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
if (key.equals("color_correction")) {
boolean colorCorrection = sharedPreferences.getBoolean("color_correction", false);
mRenderer.setColorCorrection(colorCorrection);
}
}
@Override
public void renderFrame(int[] frameBuffer) {
mRenderer.updateTexture(frameBuffer);
requestRender();
}
}

View file

@ -1,33 +0,0 @@
package com.mrmichel.rustdroid_emu.ui;
import android.os.Bundle;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity;
import androidx.preference.PreferenceFragmentCompat;
import com.mrmichel.rustdroid_emu.R;
public class SettingsActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_settings);
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.settings, new SettingsFragment())
.commit();
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
actionBar.setDisplayHomeAsUpEnabled(true);
}
}
public static class SettingsFragment extends PreferenceFragmentCompat {
@Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
setPreferencesFromResource(R.xml.app_preferences, rootKey);
}
}
}

View file

@ -1,17 +0,0 @@
package com.mrmichel.rustdroid_emu.ui;
import android.os.Bundle;
import androidx.preference.PreferenceFragment;
import androidx.preference.PreferenceFragmentCompat;
import com.mrmichel.rustdroid_emu.R;
public class SettingsFragment extends PreferenceFragmentCompat {
@Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
setPreferencesFromResource(R.xml.app_preferences, rootKey);
}
}

View file

@ -1,148 +0,0 @@
package com.mrmichel.rustdroid_emu.ui;
import android.Manifest;
import android.app.ActivityManager;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.ConfigurationInfo;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import com.mrmichel.rustdroid_emu.R;
import com.mrmichel.rustdroid_emu.ui.library.RomListActivity;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
public class SplashActivity extends AppCompatActivity {
private static final String TAG = "SplashActivity";
private static final int REQUEST_PERMISSION_CODE = 55;
private static final int BIOS_REQUEST_CODE = 66;
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == REQUEST_PERMISSION_CODE) {
if (permissions.length == 1 && permissions[0].equals(Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
initCacheBios();
} else {
Toast.makeText(this, "WRITE_EXTERNAL_STORAGE not granted, need to quit", Toast.LENGTH_LONG).show();
this.finishAffinity();
}
}
}
}
private void checkOpenGLES20() {
ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
ConfigurationInfo configurationInfo = am.getDeviceConfigurationInfo();
if (configurationInfo.reqGlEsVersion >= 0x20000) {
// Supported
} else {
new AlertDialog.Builder(this)
.setTitle("OpenGLES 2")
.setMessage("Your device doesn't support GLES20. reqGLEsVersion = " + configurationInfo.reqGlEsVersion)
.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
finishAffinity();
}
})
.setIcon(android.R.drawable.ic_dialog_alert)
.show();
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.splash_activity);
checkOpenGLES20();
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.WRITE_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED) {
// No explanation needed; request the permission
ActivityCompat.requestPermissions(this
,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE},
REQUEST_PERMISSION_CODE);
} else {
// Permission has already been granted
initCacheBios();
}
}
private void cacheBiosInAppFiles(byte[] bios) throws IOException {
FileOutputStream fos = openFileOutput("gba_bios.bin", MODE_PRIVATE);
fos.write(bios);
fos.close();
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK) {
if (requestCode == BIOS_REQUEST_CODE) {
Uri uri = data.getData();
try {
InputStream inputStream = getContentResolver().openInputStream(uri);
byte[] bios = new byte[inputStream.available()];
inputStream.read(bios);
inputStream.close();
cacheBiosInAppFiles(bios);
startLibraryActivity(bios);
} catch (Exception e) {
Log.e(TAG, "can't open bios file");
this.finishAffinity();
}
}
} else {
Log.e(TAG, "get error for request code " + requestCode);
}
}
private void initCacheBios() {
try {
FileInputStream fis = openFileInput("gba_bios.bin");
byte[] bios = new byte[fis.available()];
fis.read(bios);
startLibraryActivity(bios);
} catch (FileNotFoundException e) {
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
intent.setType("*/*");
intent.putExtra("android.content.extra.SHOW_ADVANCED", true);
intent.putExtra(Intent.EXTRA_TITLE, "Please load the gba_bios.bin file");
startActivityForResult(intent, BIOS_REQUEST_CODE);
} catch (IOException e) {
Log.e(TAG, "Got IOException while reading from bios");
}
}
private void startLibraryActivity(byte[] bios) {
Intent intent = new Intent(this, RomListActivity.class);
intent.putExtra("bios", bios);
startActivity(intent);
finish();
}
}

View file

@ -1,261 +0,0 @@
package com.mrmichel.rustdroid_emu.ui.library;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.util.Log;
import android.view.ContextMenu;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.GridView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.documentfile.provider.DocumentFile;
import com.mrmichel.rustdroid_emu.R;
import com.mrmichel.rustdroid_emu.Util;
import com.mrmichel.rustdroid_emu.core.RomManager;
import com.mrmichel.rustdroid_emu.ui.SettingsActivity;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
public class RomListActivity extends AppCompatActivity {
private static final String TAG = "RomListActivity";
private static final int REQUEST_IMPORT_ROM = 100;
private static final int REQUEST_IMPORT_DIR = 101;
private static final int REQUEST_SET_IMAGE = 102;
private static final int REQUEST_IMPORT_SAVE = 103;
private static String[] ALLOWED_EXTENSIONS = {"gba", "zip", "bin"};
private GridView mGridView;
private RomListItemAdapter itemAdapter;
private RomManager.RomMetadataEntry selectedEntry;
private byte[] bios;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_rom_list);
this.bios = getIntent().getByteArrayExtra("bios");
mGridView = findViewById(R.id.gridview_rom_list);
final RomManager romManager = RomManager.getInstance(this);
ArrayList<RomManager.RomMetadataEntry> entries = romManager.getAllRomMetaData();
itemAdapter = new RomListItemAdapter(this, entries);
mGridView.setAdapter(itemAdapter);
final Context context = this;
mGridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
RomManager.RomMetadataEntry entry = itemAdapter.getItem(position);
romManager.updateLastPlayed(entry.getId());
Util.startEmulator(context, bios, entry.getId());
}
});
registerForContextMenu(mGridView);
}
@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
if (v.getId() == R.id.gridview_rom_list) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu_context_rom, menu);
}
}
@Override
public boolean onContextItemSelected(@NonNull MenuItem item) {
AdapterView.AdapterContextMenuInfo menuInfo = (AdapterView.AdapterContextMenuInfo)item.getMenuInfo();
RomManager romManager = RomManager.getInstance(this);
RomManager.RomMetadataEntry entry = itemAdapter.getItem(menuInfo.position);
selectedEntry = entry;
switch (item.getItemId()) {
case R.id.action_play:
romManager.updateLastPlayed(entry.getId());
Util.startEmulator(this, this.bios, entry.getId());
this.itemAdapter.notifyDataSetChanged();
return true;
case R.id.action_delete:
romManager.deleteRomMetadata(itemAdapter.getItem(menuInfo.position));
return true;
case R.id.action_set_screenshot:
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
intent.setType("image/*");
intent.putExtra("romId", entry.getId());
startActivityForResult(intent, REQUEST_SET_IMAGE);
return true;
case R.id.action_export_save_file:
File backupFile = entry.getBackupFile();
try {
Util.shareFile(this, backupFile, "Sending " + backupFile.getName());
} catch (FileNotFoundException e) {
Util.showAlertDialog(this, e);
}
return true;
case R.id.action_import_save_file:
intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("*/*");
startActivityForResult(intent, REQUEST_IMPORT_SAVE);
return true;
default:
return super.onContextItemSelected(item);
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
getMenuInflater().inflate(R.menu.menu_rom_list, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.action_import_rom:
doImportRom();
return true;
case R.id.action_import_directory:
doImportDirectory();
return true;
case R.id.action_settings:
Intent intent = new Intent(this, SettingsActivity.class);
startActivity(intent);
return true;
default:
return super.onOptionsItemSelected(item);
}
}
String getFileExtension(String name) {
if (name == null) {
return "";
}
int i = name.lastIndexOf('.');
String ext = i > 0 ? name.substring(i + 1) : "";
return ext;
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK) {
ContentResolver contentResolver = getContentResolver();
RomManager romManager = RomManager.getInstance(this);
switch (requestCode) {
case REQUEST_IMPORT_ROM:
Uri uri = data.getData();
contentResolver.takePersistableUriPermission(uri, Intent.FLAG_GRANT_READ_URI_PERMISSION);
romManager.importRom(DocumentFile.fromSingleUri(this, uri));
break;
case REQUEST_IMPORT_DIR:
Uri treeUri = data.getData();
contentResolver.takePersistableUriPermission(treeUri, Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
DocumentFile pickedDir = DocumentFile.fromTreeUri(this, treeUri);
for (DocumentFile file : pickedDir.listFiles()) {
String extension = getFileExtension(file.getName());
if (Arrays.asList(ALLOWED_EXTENSIONS).contains(extension)) {
Log.d(TAG, "Importing ROM " + file.getName() + " with size " + file.length() + " and type: " + extension);
romManager.importRom(file);
}
}
break;
case REQUEST_SET_IMAGE:
int romId = selectedEntry.getId();
Bitmap bitmap;
try {
bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), data.getData());
}
catch (Exception e) {
Util.showAlertDialogAndExit(this, e);
return;
}
Log.d(TAG, "found bitmap");
romManager.updateScreenshot(romId, bitmap);
break;
case REQUEST_IMPORT_SAVE:
try {
InputStream inputStream = getContentResolver().openInputStream(data.getData());
byte[] saveData = new byte[inputStream.available()];
inputStream.read(saveData);
inputStream.close();
File file = selectedEntry.getBackupFile();
Log.d(TAG, "Saving imported save to " + file.getAbsolutePath());
FileOutputStream fos = new FileOutputStream(file);
fos.write(saveData);
fos.close();
} catch (Exception e) {
Util.showAlertDialogAndExit(this, e);
}
break;
}
this.itemAdapter.notifyDataSetChanged();
mGridView.setAdapter(new RomListItemAdapter(this, romManager.getAllRomMetaData()));
mGridView.invalidate();
} else {
Log.e(TAG, "got error for request code " + requestCode);
}
}
void doImportRom() {
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("*/*");
Log.d(TAG, "pressed import rom");
Intent chooser = Intent.createChooser(intent, "choose GBA rom file to import");
startActivityForResult(chooser, REQUEST_IMPORT_ROM);
}
void doImportDirectory() {
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
startActivityForResult(intent, REQUEST_IMPORT_DIR);
}
}

View file

@ -1,61 +0,0 @@
package com.mrmichel.rustdroid_emu.ui.library;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.mrmichel.rustdroid_emu.R;
import com.mrmichel.rustdroid_emu.core.RomManager.RomMetadataEntry;
import java.util.ArrayList;
public class RomListItemAdapter extends ArrayAdapter<RomMetadataEntry> {
Context context;
ArrayList<RomMetadataEntry> items;
public RomListItemAdapter(Context context, ArrayList<RomMetadataEntry> romEntries) {
super(context, 0, romEntries);
this.context = context;
this.items = romEntries;
}
@Override
public long getItemId(int position) {
return 0;
}
@NonNull
@Override
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
RomMetadataEntry item = getItem(position);
if (convertView == null) {
convertView = LayoutInflater.from(getContext()).inflate(R.layout.rom_item, parent, false);
}
ImageView screenshotImageView = convertView.findViewById(R.id.imageview_screenshot);
Bitmap screenshot = item.getScreenshot();
if (screenshot != null) {
screenshotImageView.setImageBitmap(screenshot);
} else {
screenshotImageView.setImageBitmap(BitmapFactory.decodeResource(context.getResources(), R.mipmap.ic_launcher));
}
TextView tvTitle = convertView.findViewById(R.id.textview_game_title);
tvTitle.setText(item.getName());
return convertView;
}
}

View file

@ -1,8 +0,0 @@
package com.mrmichel.rustdroid_emu.ui.snapshots;
import com.mrmichel.rustdroid_emu.core.Snapshot;
public interface ISnapshotListener {
public void onSnapshotClicked(Snapshot snapshot);
}

View file

@ -1,63 +0,0 @@
package com.mrmichel.rustdroid_emu.ui.snapshots;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.mrmichel.rustdroid_emu.R;
import com.mrmichel.rustdroid_emu.core.Snapshot;
import java.sql.Timestamp;
import java.util.ArrayList;
public class SnapshotItemAdapter extends ArrayAdapter<Snapshot> {
Context context;
ArrayList<Snapshot> items;
public SnapshotItemAdapter(Context context, ArrayList<Snapshot> items) {
super(context, 0, items);
this.context = context;
this.items = items;
}
@Override
public int getCount() {
return items.size();
}
@Override
public long getItemId(int position) {
return 0;
}
@NonNull
@Override
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
Snapshot snapshot = getItem(position);
if (convertView == null) {
convertView = LayoutInflater.from(getContext()).inflate(R.layout.snapshot_item, parent, false);
}
ImageView preview = (ImageView) convertView.findViewById(R.id.imageview_snapshot_preview);
preview.setImageBitmap(snapshot.getPreview());
TextView tvTitle = (TextView) convertView.findViewById(R.id.textview_snapshot_title);
tvTitle.setText(snapshot.getGameTitle());
TextView tvTimestamp = (TextView) convertView.findViewById(R.id.textview_snapshot_timestmap);
Timestamp timestamp = new Timestamp(snapshot.getTimestamp());
tvTimestamp.setText(timestamp.toString());
return convertView;
}
}

View file

@ -1,116 +0,0 @@
package com.mrmichel.rustdroid_emu.ui.snapshots;
import android.os.Bundle;
import android.util.Log;
import android.view.ContextMenu;
import android.view.LayoutInflater;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.GridView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import com.mrmichel.rustdroid_emu.R;
import com.mrmichel.rustdroid_emu.core.Snapshot;
import com.mrmichel.rustdroid_emu.core.SnapshotManager;
import java.util.ArrayList;
public class SnapshotListFragment extends Fragment {
private static final String TAG = "SnapshotListFragment";
private GridView mGridView;
private ArrayList<Snapshot> snapshots;
private ISnapshotListener mListener;
public SnapshotListFragment() {
super();
mListener = new ISnapshotListener() {
@Override
public void onSnapshotClicked(Snapshot snapshot) {
Log.d(TAG, "stub onSnapshotClicked");
}
};
}
public SnapshotListFragment(ISnapshotListener listener) {
super();
mListener = listener;
}
public static SnapshotListFragment newInstance(ISnapshotListener listener) {
return new SnapshotListFragment(listener);
}
@Override
public void onCreateContextMenu(@NonNull ContextMenu menu, @NonNull View v, @Nullable ContextMenu.ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
if (v.getId() == R.id.gridview_snapshots) {
MenuInflater inflater = getActivity().getMenuInflater();
inflater.inflate(R.menu.menu_context_snapshot, menu);
}
}
@Override
public boolean onContextItemSelected(@NonNull MenuItem item) {
AdapterView.AdapterContextMenuInfo menuInfo = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
Snapshot snapshot = snapshots.get(menuInfo.position);
switch (item.getItemId()) {
case R.id.action_delete:
SnapshotManager.getInstance(getContext()).deleteSnapshot(snapshot);
snapshots.remove(menuInfo.position);
SnapshotItemAdapter adapter = new SnapshotItemAdapter(getContext(), snapshots);
mGridView.setAdapter(adapter);
mGridView.invalidate();
return true;
default:
return super.onContextItemSelected(item);
}
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.snapshot_list_fragment, container, false);
}
@Override
public void onStart() {
super.onStart();
Bundle args = getArguments();
SnapshotManager manager = SnapshotManager.getInstance(getContext());
String gameCode;
if (args != null && (gameCode = args.getString("gameCode")) != null) {
snapshots = manager.getByGameCode(gameCode);
} else {
snapshots = manager.getAllSnapshots();
}
mGridView = getActivity().findViewById(R.id.gridview_snapshots);
SnapshotItemAdapter adapter = new SnapshotItemAdapter(getContext(), snapshots);
mGridView.setAdapter(adapter);
mGridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
final Snapshot snapshot = snapshots.get(position);
mListener.onSnapshotClicked(snapshot);
}
});
registerForContextMenu(mGridView);
}
}

View file

@ -1,39 +0,0 @@
package com.mrmichel.rustdroid_emu.ui.snapshots;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import com.mrmichel.rustdroid_emu.R;
import com.mrmichel.rustdroid_emu.core.Snapshot;
public class SnapshotPickerActivity extends AppCompatActivity implements ISnapshotListener {
static Snapshot pickedSnapshot;
public static Snapshot obtainPickedSnapshot() {
Snapshot ret = pickedSnapshot;
pickedSnapshot = null;
return ret;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.snapshot_picker_activity);
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction()
.replace(R.id.container, SnapshotListFragment.newInstance(this))
.commitNow();
}
}
@Override
public void onSnapshotClicked(Snapshot snapshot) {
Intent data = new Intent();
pickedSnapshot = snapshot;
setResult(RESULT_OK, data);
finish();
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

View file

@ -1,5 +0,0 @@
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="@color/colorAccent" />
<corners android:radius="500dp" />
</shape>

View file

@ -1,18 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.EmulatorActivity">
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent">
<include layout="@layout/content_emulator" />
</FrameLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View file

@ -1,123 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:keepScreenOn="true"
android:background="@color/gbaBackground"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.mrmichel.rustdroid_emu.ui.ScreenView
android:id="@+id/gba_view"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginTop="16dp"
android:layout_marginBottom="16dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintDimensionRatio="V, 3:2"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.0" />
<include
android:id="@+id/include"
layout="@layout/dpad"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:alpha=".5"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<Button
android:id="@+id/buttonB"
style="@style/Widget.AppCompat.Button.Small"
android:layout_width="52dp"
android:layout_height="54dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="32dp"
android:background="@drawable/round_button"
android:text="B"
android:alpha=".5"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/buttonA"
tools:text="B" />
<Button
android:id="@+id/buttonA"
style="@style/Widget.AppCompat.Button.Small"
android:layout_width="52dp"
android:layout_height="54dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="48dp"
android:background="@drawable/round_button"
android:text="A"
android:alpha=".5"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
tools:text="A" />
<Button
android:id="@+id/bSelect"
style="@style/Widget.AppCompat.Button.Small"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:text="select"
android:textSize="8dp"
app:layout_constraintBottom_toTopOf="@+id/bStart"
app:layout_constraintStart_toStartOf="parent" />
<Button
android:id="@+id/bStart"
style="@style/Widget.AppCompat.Button.Small"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginBottom="20dp"
android:text="start"
android:textSize="8dp"
app:layout_constraintBottom_toTopOf="@+id/include"
app:layout_constraintStart_toStartOf="parent" />
<Button
android:id="@+id/buttonL"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:text="L"
android:alpha=".5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/buttonR"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:text="R"
android:alpha=".5"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ToggleButton
android:id="@+id/tbTurbo"
android:layout_width="98dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginBottom="16dp"
android:checked="false"
android:text="Turbo Mode"
android:textOff="Turbo OFF"
android:textOn="Turbo ON"
app:layout_constraintBottom_toTopOf="@+id/bSelect"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -1,18 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/gbaBackground"
tools:context=".ui.EmulatorActivity">
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent">
<include layout="@layout/content_emulator" />
</FrameLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View file

@ -1,47 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context=".ui.library.RomListActivity">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/app_bar"
android:layout_width="match_parent"
android:layout_height="@dimen/app_bar_height"
android:fitsSystemWindows="true"
android:theme="@style/AppTheme.AppBarOverlay">
<com.google.android.material.appbar.CollapsingToolbarLayout
android:id="@+id/toolbar_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
app:contentScrim="?attr/colorAccent"
app:layout_scrollFlags="scroll|exitUntilCollapsed"
app:toolbarId="@+id/toolbar">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_collapseMode="pin"
app:popupTheme="@style/AppTheme.PopupOverlay" />
</com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="@dimen/fab_margin"
app:layout_anchor="@id/app_bar"
app:layout_anchorGravity="bottom|end"
app:srcCompat="@android:drawable/ic_media_play" />
<include layout="@layout/content_rom_list" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View file

@ -1,9 +0,0 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:id="@+id/settings"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>

View file

@ -1,124 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:keepScreenOn="true"
android:background="@color/gbaBackground"
android:layout_width="match_parent"
android:layout_height="match_parent">
<include
android:id="@+id/include"
layout="@layout/dpad"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginBottom="64dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<com.mrmichel.rustdroid_emu.ui.ScreenView
android:id="@+id/gba_view"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginTop="32dp"
app:layout_constraintDimensionRatio="H, 3:2"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.517"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/buttonB"
style="@style/Widget.AppCompat.Button.Small"
android:layout_width="52dp"
android:layout_height="54dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="12dp"
android:background="@drawable/round_button"
android:text="B"
app:layout_constraintEnd_toStartOf="@+id/buttonA"
app:layout_constraintTop_toTopOf="@+id/include"
tools:text="B" />
<Button
android:id="@+id/buttonA"
style="@style/Widget.AppCompat.Button.Small"
android:layout_width="52dp"
android:layout_height="54dp"
android:layout_marginEnd="24dp"
android:background="@drawable/round_button"
android:text="A"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@+id/include"
tools:text="A" />
<Button
android:id="@+id/bSelect"
style="@style/Widget.AppCompat.Button.Small"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="120dp"
android:layout_marginEnd="12dp"
android:layout_marginBottom="16dp"
android:background="@drawable/round_button"
android:text="select"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/bStart"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="@+id/include" />
<Button
android:id="@+id/bStart"
style="@style/Widget.AppCompat.Button.Small"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:layout_marginBottom="16dp"
android:background="@drawable/round_button"
android:text="start"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@+id/bSelect" />
<Button
android:id="@+id/buttonL"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="2dp"
android:layout_marginTop="24dp"
android:text="L"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/gba_view" />
<Button
android:id="@+id/buttonR"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:layout_marginEnd="2dp"
android:text="R"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/gba_view" />
<Switch
android:id="@+id/tbTurbo"
android:layout_width="98dp"
android:layout_height="wrap_content"
android:layout_marginEnd="24dp"
android:layout_marginBottom="16dp"
android:checked="false"
android:text="Turbo Mode"
android:textOff="Turbo OFF"
android:textOn="Turbo ON"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
<TextView
android:id="@+id/tvFPS"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
app:layout_constraintTop_toBottomOf="@+id/gba_view"
tools:layout_editor_absoluteX="176dp" />
</androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -1,19 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:context=".ui.library.RomListActivity"
tools:showIn="@layout/activity_rom_list">
<GridView
android:id="@+id/gridview_rom_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:numColumns="auto_fit"
tools:context=".ui.library.RomListActivity"></GridView>
</LinearLayout>

View file

@ -1,58 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ImageButton
android:id="@+id/bDpadUp"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_marginStart="48dp"
android:layout_marginEnd="48dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@android:drawable/arrow_up_float" />
<ImageButton
android:id="@+id/bDpadRight"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_marginStart="48dp"
android:layout_marginTop="48dp"
android:layout_marginBottom="48dp"
android:rotation="90"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@+id/bDpadLeft"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@android:drawable/arrow_up_float" />
<ImageButton
android:id="@+id/bDpadLeft"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_marginTop="48dp"
android:layout_marginEnd="48dp"
android:layout_marginBottom="48dp"
android:rotation="90"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/bDpadRight"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@android:drawable/arrow_down_float" />
<ImageButton
android:id="@+id/bDpadDown"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_marginStart="48dp"
android:layout_marginTop="48dp"
android:layout_marginEnd="48dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/bDpadUp"
app:srcCompat="@android:drawable/arrow_down_float" />
</androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -1,38 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:padding="5dp"
>
<ImageView
android:id="@+id/imageview_screenshot"
android:layout_width="180dp"
android:layout_height="120dp"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_margin="5dp"
android:scaleType="centerCrop"
android:background="@drawable/round_button"
app:srcCompat="@mipmap/ic_launcher" />
<TextView
android:id="@+id/textview_game_title"
android:layout_width="180dp"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:paddingLeft="8dp"
android:paddingTop="4dp"
android:paddingBottom="4dp"
android:paddingRight="8dp"
android:text="Cool Game - III"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
android:textSize="12sp"
android:textStyle="bold"
android:layout_below="@+id/imageview_screenshot"
/>
</RelativeLayout>

View file

@ -1,39 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:layout_margin="10dp"
>
<ImageView
android:id="@+id/imageview_snapshot_preview"
android:layout_width="180dp"
android:layout_height="120dp"
android:scaleType="centerCrop"
app:srcCompat="@mipmap/ic_launcher" />
<TextView
android:id="@+id/textview_snapshot_title"
android:layout_width="180dp"
android:layout_height="wrap_content"
android:text="Cool Game - III"
android:gravity="center_horizontal"
android:paddingTop="4dp"
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:textStyle="bold"
android:textSize="12sp"
android:textAppearance="@style/TextAppearance.AppCompat.Medium" />
<TextView
android:id="@+id/textview_snapshot_timestmap"
android:layout_width="180dp"
android:layout_height="wrap_content"
android:text="1.1.2020"
android:gravity="center_horizontal"
android:textSize="12sp"
/>
</LinearLayout>

View file

@ -1,42 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorAccent"
tools:context=".ui.snapshots.SnapshotListFragment">
<EditText
android:id="@+id/edittext_snapshot_filter"
style="@style/Widget.AppCompat.EditText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:ems="10"
android:hint="Search.."
android:inputType="textFilter|textPersonName"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<GridView
android:id="@+id/gridview_snapshots"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="8dp"
android:gravity="center"
android:numColumns="auto_fit"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/edittext_snapshot_filter"
tools:context=".ui.snapshots.SnapshotListFragment"
tools:showIn="@layout/snapshot_list_fragment">
</GridView>
</androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -1,7 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.snapshots.SnapshotPickerActivity" />

View file

@ -1,25 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.SplashActivity">
<ImageView
android:id="@+id/imageView2"
android:layout_width="240dp"
android:layout_height="wrap_content"
android:layout_marginStart="80dp"
android:layout_marginTop="285dp"
android:layout_marginEnd="80dp"
android:layout_marginBottom="286dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@mipmap/ic_launcher" />
</androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -1,41 +0,0 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/menu_context_rom"
tools:context="com.mrmichel.rustdroid_emu.ui.library.RomListActivity">
<item
android:id="@+id/action_play"
android:icon="@android:drawable/ic_media_play"
android:title="@string/action_load_rom"
app:showAsAction="ifRoom|withText" />
<item
android:id="@+id/action_set_screenshot"
android:title="@string/action_set_screenshot" />
<item
android:id="@+id/action_view_snapshots"
android:title="@string/action_view_snapshot"
app:showAsAction="withText" />
<item
android:id="@+id/action_delete"
android:icon="@android:drawable/ic_menu_delete"
android:title="@string/action_delete"
app:showAsAction="ifRoom|withText" />
<item
android:id="@+id/action_import_save_file"
android:icon="@android:drawable/ic_menu_save"
android:title="Import Save File" />
<item
android:id="@+id/action_export_save_file"
android:icon="@android:drawable/ic_menu_share"
android:title="Export Save File" />
</menu>

View file

@ -1,12 +0,0 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
>
<item
android:id="@+id/action_delete"
android:icon="@android:drawable/ic_menu_delete"
android:title="@string/action_delete"
app:showAsAction="ifRoom|withText" />
</menu>

View file

@ -1,45 +0,0 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context="com.mrmichel.rustdroid_emu.ui.EmulatorActivity">
<item
android:id="@+id/action_load_rom"
android:orderInCategory="1"
android:title="@string/action_load_rom" />
<!-- <item-->
<!-- android:title="@string/submenu_snapshots"-->
<!-- android:orderInCategory="2"-->
<!-- >-->
<!-- <menu>-->
<item
android:id="@+id/action_save_snapshot"
android:enabled="false"
android:icon="@android:drawable/ic_menu_save"
android:orderInCategory="100"
android:title="@string/action_save_snapshot"
app:showAsAction="ifRoom|withText" />
<item
android:id="@+id/action_view_snapshots"
android:icon="@android:drawable/ic_menu_gallery"
android:orderInCategory="101"
android:title="@string/action_view_snapshot"
app:showAsAction="ifRoom|withText" />
<!-- </menu>-->
<!-- </item>-->
<item
android:id="@+id/action_set_library_image"
android:icon="@android:drawable/ic_menu_camera"
android:title="@string/action_set_library_image" />
<item
android:id="@+id/action_settings"
android:menuCategory="system"
android:orderInCategory="100"
android:title="@string/action_settings"
app:showAsAction="never" />
</menu>

View file

@ -1,17 +0,0 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context="com.mrmichel.rustdroid_emu.ui.library.RomListActivity">
<item
android:title="@string/action_load_rom"
android:id="@+id/action_import_rom" />
<item
android:title="@string/action_import_directory"
android:id="@+id/action_import_directory" />
<item
android:id="@+id/action_settings"
android:orderInCategory="100"
android:title="@string/action_settings"
app:showAsAction="never" />
</menu>

View file

@ -1,10 +0,0 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context="com.mrmichel.rustdroid_emu.ui.snapshots.SnapshotListFragment">
<item
android:id="@+id/action_settings"
android:orderInCategory="100"
android:title="@string/action_settings"
app:showAsAction="never" />
</menu>

View file

@ -1,5 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_launcher_background"/>
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
</adaptive-icon>

View file

@ -1,5 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_launcher_background"/>
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
</adaptive-icon>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

View file

@ -1,21 +0,0 @@
/*
Port of byuu's color correction shader as described in https://byuu.net/video/color-emulation
*/
precision mediump float;
varying vec2 v_texCoord;
uniform sampler2D s_texture;
void main()
{
float lcdGamma = 4.0, outGamma = 2.2;
vec4 color = texture2D( s_texture, v_texCoord );
color.rgb = pow(color.rgb, vec3(lcdGamma));
gl_FragColor.r = pow(( 0.0 * color.b + 50.0 * color.g + 255.0 * color.r) / 255.0, 1.0 / outGamma) * 255.0 / 280.0;
gl_FragColor.g = pow(( 30.0 * color.b + 230.0 * color.g + 10.0 * color.r) / 255.0, 1.0 / outGamma) * 255.0 / 280.0;
gl_FragColor.b = pow((220.0 * color.b + 10.0 * color.g + 50.0 * color.r) / 255.0, 1.0 / outGamma) * 255.0 / 280.0;
gl_FragColor.a = 1.0;
}

View file

@ -1,8 +0,0 @@
precision mediump float;
varying vec2 v_texCoord;
uniform sampler2D s_texture;
void main()
{
vec4 color = texture2D( s_texture, v_texCoord );
gl_FragColor = color;
}

View file

@ -1,8 +0,0 @@
attribute vec4 a_position;
attribute vec2 a_texCoord;
varying vec2 v_texCoord;
void main()
{
gl_Position = a_position;
v_texCoord = a_texCoord;
}

View file

@ -1,7 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="colorPrimary">#6c45c0</color>
<color name="colorPrimaryDark">#331573</color>
<color name="colorAccent">#ad8cf4</color>
<color name="gbaBackground">#6c45c0</color>
</resources>

View file

@ -1,5 +0,0 @@
<resources>
<dimen name="fab_margin">16dp</dimen>
<dimen name="app_bar_height">180dp</dimen>
<dimen name="text_margin">16dp</dimen>
</resources>

View file

@ -1,4 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="ic_launcher_background">#A4A5DF</color>
</resources>

View file

@ -1,25 +0,0 @@
<resources>
<string name="app_name">RustdroidAdvance</string>
<string name="title_activity_emulator">RustdroidAdvance</string>
<string name="title_activity_rom_list">Rom Library</string>
<string name="action_load_rom">Load ROM</string>
<string name="action_import_directory">Import Directory</string>
<string name="action_settings">Settings</string>
<string name="submenu_snapshots">Snapshots</string>
<string name="action_save_snapshot">Save Snapshot</string>
<string name="action_view_snapshot">View Snapshots</string>
<string name="action_set_screenshot">Set Image</string>
<string name="action_delete">Delete</string>
<string name="action_set_library_image"> Take screenshot for library view </string>
<string name="title_activity_snapshot">Snapshot Manager</string>
<string name="color_correction_setting">Apply color correction shader</string>
<string name="color_correction_summary">
Makes colors look closer to the real GBA LCD screen.
</string>
</resources>

View file

@ -1,20 +0,0 @@
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
<style name="AppTheme.NoActionBar">
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
</style>
<style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" />
<style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" />
</resources>

View file

@ -1,18 +0,0 @@
<PreferenceScreen
xmlns:app="http://schemas.android.com/apk/res-auto">
<PreferenceCategory app:title="Emulation">
<SwitchPreferenceCompat
app:key="skip_bios"
app:title="Skip bios boot animation"/>
</PreferenceCategory>
<PreferenceCategory app:title="Graphics">
<SwitchPreferenceCompat
app:key="color_correction"
app:title="@string/color_correction_setting"
app:summary="@string/color_correction_summary"
/>
</PreferenceCategory>
</PreferenceScreen>

View file

@ -1,4 +0,0 @@
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<files-path name="internal_files" path="./"/>
<files-path name="snapshots" path="snapshots/"/>
</paths>

View file

@ -1,17 +0,0 @@
package com.mrmichel.rustdroid_emu;
import org.junit.Test;
import static org.junit.Assert.*;
/**
* Example local unit test, which will execute on the development machine (host).
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
public class ExampleUnitTest {
@Test
public void addition_isCorrect() {
assertEquals(4, 2 + 2);
}
}

View file

@ -1,31 +0,0 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
google()
jcenter()
maven {
url "https://plugins.gradle.org/m2/"
}
}
dependencies {
classpath 'com.android.tools.build:gradle:3.5.3'
classpath 'gradle.plugin.org.mozilla.rust-android-gradle:plugin:0.8.3'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
google()
jcenter()
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}

View file

@ -1,20 +0,0 @@
# Project-wide Gradle settings.
# IDE (e.g. Android Studio) users:
# Gradle settings configured through the IDE *will override*
# any settings specified in this file.
# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
org.gradle.jvmargs=-Xmx1536m
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
# AndroidX package structure to make it clearer which packages are bundled with the
# Android operating system, and which are packaged with your app's APK
# https://developer.android.com/topic/libraries/support-library/androidx-rn
android.useAndroidX=true
# Automatically convert third-party libraries to use AndroidX
android.enableJetifier=true

View file

@ -1,6 +0,0 @@
#Sat Feb 22 01:01:17 IST 2020
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip

View file

@ -1,172 +0,0 @@
#!/usr/bin/env sh
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn () {
echo "$*"
}
die () {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=$(save "$@")
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
cd "$(dirname "$0")"
fi
exec "$JAVACMD" "$@"

Some files were not shown because too many files have changed in this diff Show more