chore: remove extra platforms
Former-commit-id: 694fbd23b097e1ff1f72875fa27da2dd070d195d Former-commit-id: 64da130bc04b6e9a766f2491e6f7e7c4169f1e1b
424
Cargo.lock
generated
|
@ -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"
|
||||
|
|
|
@ -4,9 +4,6 @@ members = [
|
|||
"arm7tdmi",
|
||||
"utils",
|
||||
"platform/rustboyadvance-sdl2",
|
||||
"platform/rustboyadvance-libretro",
|
||||
"platform/rustboyadvance-wasm",
|
||||
"platform/rustboyadvance-jni",
|
||||
"fps_bench"
|
||||
]
|
||||
resolver = "1"
|
||||
|
|
|
@ -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(())
|
||||
}
|
||||
}
|
2
arm7tdmi/examples/test_program/.gitignore
vendored
|
@ -1,2 +0,0 @@
|
|||
/*.o
|
||||
/*.gdb_history
|
|
@ -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
|
|
@ -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
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
|
@ -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
|
Before Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 134 KiB |
Before Width: | Height: | Size: 152 KiB |
14
platform/android/.gitignore
vendored
|
@ -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
|
|
@ -1 +0,0 @@
|
|||
RustdroidAdvance
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -1,3 +0,0 @@
|
|||
# RustdroidAdvance
|
||||
|
||||
RustdroidAdvance is an android frontend for my rustboyadvance emulator core
|
1
platform/android/app/.gitignore
vendored
|
@ -1 +0,0 @@
|
|||
/build
|
|
@ -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'
|
||||
}
|
21
platform/android/app/proguard-rules.pro
vendored
|
@ -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
|
|
@ -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());
|
||||
}
|
||||
}
|
|
@ -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>
|
Before Width: | Height: | Size: 40 KiB |
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
|
@ -1,5 +0,0 @@
|
|||
package com.mrmichel.rustboyadvance;
|
||||
|
||||
public interface IFrameRenderer {
|
||||
void renderFrame(int[] framebuffer);
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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));
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
Before Width: | Height: | Size: 3.7 KiB |
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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" />
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
Before Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 6 KiB |
Before Width: | Height: | Size: 4.7 KiB |
Before Width: | Height: | Size: 3.7 KiB |
Before Width: | Height: | Size: 6.6 KiB |
Before Width: | Height: | Size: 8.5 KiB |
Before Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 20 KiB |
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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>
|
|
@ -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>
|
|
@ -1,4 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="ic_launcher_background">#A4A5DF</color>
|
||||
</resources>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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
|
||||
|
BIN
platform/android/gradle/wrapper/gradle-wrapper.jar
vendored
|
@ -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
|
172
platform/android/gradlew
vendored
|
@ -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" "$@"
|