The big ioregs refactoring.
This commit refactors the ioregs: * Use bitfield crate to implement the GPU ioregs. * IoRegs are stored in their own variables bindings (i.e, Gpu related ioregs are now fields of the Gpu struct) - This optimize performance quiet alot from my testings - since every scanline was accessing deseralizing ioregs from sysbus. (Getting constant 59fps now) * For now, comment out DMA model Also, cleaned the code up to eliminate rustc warnings. Former-commit-id: 9077695c446ebd1a71783acfdd9819245aa02d7a
This commit is contained in:
parent
9f0df9af06
commit
c7dd713605
73
Cargo.lock
generated
73
Cargo.lock
generated
|
@ -55,7 +55,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
|
||||
[[package]]
|
||||
name = "backtrace"
|
||||
version = "0.3.33"
|
||||
version = "0.3.34"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"backtrace-sys 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -69,7 +69,7 @@ name = "backtrace-sys"
|
|||
version = "0.1.31"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cc 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cc 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
|
@ -78,6 +78,11 @@ name = "bit"
|
|||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "bitfield"
|
||||
version = "0.13.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.1.0"
|
||||
|
@ -99,7 +104,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.37"
|
||||
version = "1.0.38"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
|
@ -156,16 +161,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
|
||||
[[package]]
|
||||
name = "dirs"
|
||||
version = "2.0.1"
|
||||
version = "2.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"dirs-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"dirs-sys 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dirs-sys"
|
||||
version = "0.3.3"
|
||||
version = "0.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -189,7 +194,7 @@ name = "failure"
|
|||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"backtrace 0.3.33 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"backtrace 0.3.34 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
|
@ -200,7 +205,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
dependencies = [
|
||||
"proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syn 0.15.39 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
|
@ -253,14 +258,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
|
||||
[[package]]
|
||||
name = "lexical-core"
|
||||
version = "0.4.2"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ryu 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"stackvector 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"static_assertions 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"static_assertions 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -270,7 +275,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.7"
|
||||
version = "0.4.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -286,7 +291,7 @@ name = "minifb"
|
|||
version = "0.11.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cc 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cc 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gdi32-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"orbclient 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -302,7 +307,7 @@ version = "0.14.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cc 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cc 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -318,7 +323,7 @@ name = "nom"
|
|||
version = "5.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"lexical-core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lexical-core 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
@ -426,7 +431,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "pkg-config"
|
||||
version = "0.3.14"
|
||||
version = "0.3.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
|
@ -593,6 +598,7 @@ version = "0.1.0"
|
|||
dependencies = [
|
||||
"ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bit 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitfield 0.13.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"colored 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -625,9 +631,9 @@ name = "rustyline"
|
|||
version = "5.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"dirs 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"dirs 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"nix 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unicode-segmentation 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -638,7 +644,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "0.2.8"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
|
@ -692,7 +698,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "static_assertions"
|
||||
version = "0.2.5"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
|
@ -712,7 +718,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "0.15.39"
|
||||
version = "0.15.42"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -735,7 +741,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
dependencies = [
|
||||
"proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syn 0.15.39 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
|
@ -861,7 +867,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
dependencies = [
|
||||
"lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pkg-config 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -877,21 +883,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
"checksum arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b8d73f9beda665eaa98ab9e4f7442bd4e7de6652587de55b2525e52e29c1b0ba"
|
||||
"checksum atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1803c647a3ec87095e7ae7acfca019e98de5ec9a7d01343f611cf3152ed71a90"
|
||||
"checksum autocfg 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "22130e92352b948e7e82a49cdb0aa94f2211761117f29e052dd397c1ac33542b"
|
||||
"checksum backtrace 0.3.33 (registry+https://github.com/rust-lang/crates.io-index)" = "88fb679bc9af8fa639198790a77f52d345fe13656c08b43afa9424c206b731c6"
|
||||
"checksum backtrace 0.3.34 (registry+https://github.com/rust-lang/crates.io-index)" = "b5164d292487f037ece34ec0de2fcede2faa162f085dd96d2385ab81b12765ba"
|
||||
"checksum backtrace-sys 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)" = "82a830b4ef2d1124a711c71d263c5abdc710ef8e907bd508c88be475cebc422b"
|
||||
"checksum bit 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2b645c5c09a7d4035949cfce1a915785aaad6f17800c35fda8a8c311c491f284"
|
||||
"checksum bitfield 0.13.2 (registry+https://github.com/rust-lang/crates.io-index)" = "46afbd2983a5d5a7bd740ccb198caf5b82f45c40c09c0eed36052d91cb92e719"
|
||||
"checksum bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3d155346769a6855b86399e9bc3814ab343cd3d62c7e985113d46a0ec3c281fd"
|
||||
"checksum blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6d530bdd2d52966a6d03b7a964add7ae1a288d25214066fd4b600f0f796400"
|
||||
"checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5"
|
||||
"checksum cc 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)" = "39f75544d7bbaf57560d2168f28fd649ff9c76153874db88bdbdfd839b1a7e7d"
|
||||
"checksum cc 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)" = "ce400c638d48ee0e9ab75aef7997609ec57367ccfe1463f21bf53c3eca67bf46"
|
||||
"checksum cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "b486ce3ccf7ffd79fdeb678eac06a9e6c09fc88d33836340becb8fffe87c5e33"
|
||||
"checksum cgmath 0.16.1 (registry+https://github.com/rust-lang/crates.io-index)" = "64a4b57c8f4e3a2e9ac07e0f6abc9c24b6fc9e1b54c3478cfb598f3d0023e51c"
|
||||
"checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9"
|
||||
"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
|
||||
"checksum colored 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6cdb90b60f2927f8d76139c72dbde7e10c3a2bc47c8594c9c7a66529f2687c03"
|
||||
"checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e"
|
||||
"checksum dirs 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1c4ef5a8b902d393339e2a2c7fe573af92ce7e0ee5a3ff827b4c9ad7e07e4fa1"
|
||||
"checksum dirs-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "937756392ec77d1f2dd9dc3ac9d69867d109a2121479d72c364e42f4cab21e2d"
|
||||
"checksum dirs 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "13aea89a5c93364a98e9b37b2fa237effbb694d5cfe01c5b70941f7eb087d5e3"
|
||||
"checksum dirs-sys 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "afa0b23de8fd801745c471deffa6e12d248f962c9fd4b4c33787b055599bde7b"
|
||||
"checksum enum-primitive-derive 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e2b90e520ec62c1864c8c78d637acbfe8baf5f63240f2fb8165b8325c07812dd"
|
||||
"checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2"
|
||||
"checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1"
|
||||
|
@ -902,9 +909,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
|
||||
"checksum lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73"
|
||||
"checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14"
|
||||
"checksum lexical-core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3f8673fab7063c2cac37d299c8a1a7beb720e78f71500098e4a3c137fdf025bf"
|
||||
"checksum lexical-core 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b8b0f90c979adde96d19eb10eb6431ba0c441e2f9e9bdff868b2f6f5114ff519"
|
||||
"checksum libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)" = "d44e80633f007889c7eff624b709ab43c92d708caad982295768a7b13ca3b5eb"
|
||||
"checksum log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "c275b6ad54070ac2d665eef9197db647b32239c9d244bfb6f041a766d00da5b3"
|
||||
"checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7"
|
||||
"checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e"
|
||||
"checksum minifb 0.11.2 (registry+https://github.com/rust-lang/crates.io-index)" = "85c2cedede43aad485232acf318a3e191ee5a3c2250ca8a3556b849a48e8b901"
|
||||
"checksum nix 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6c722bee1037d430d0f8e687bbdbf222f27cc6e4e68d5caf630857bb2b6dbdce"
|
||||
|
@ -921,7 +928,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
"checksum num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "6ba9a427cfca2be13aa6f6403b0b7e7368fe982bfa16fccc450ce74c46cd9b32"
|
||||
"checksum odds 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)" = "4eae0151b9dacf24fcc170d9995e511669a082856a91f958a2fe380bfab3fb22"
|
||||
"checksum orbclient 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "a6bf65f618983a876b7a71e5cdb171c9e9e8264b519bcd6b9bd1805c30d7d980"
|
||||
"checksum pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "676e8eb2b1b4c9043511a9b7bea0915320d7e502b0a079fb03f9635a5252b18c"
|
||||
"checksum pkg-config 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c1d2cfa5a714db3b5f24f0915e74fcdf91d09d496ba61329705dda7774d2af"
|
||||
"checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759"
|
||||
"checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a"
|
||||
"checksum quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1"
|
||||
|
@ -943,17 +950,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
"checksum rustc-demangle 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "a7f4dccf6f4891ebcc0c39f9b6eb1a83b9bf5d747cb439ec6fba4f3b977038af"
|
||||
"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
|
||||
"checksum rustyline 5.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "67e12e40e0240de07f0dab4f4dd01bdb15d74dc977026d4ba91666c41c679ade"
|
||||
"checksum ryu 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "b96a9549dc8d48f2c283938303c4b5a77aa29bfbc5b54b084fb1630408899a8f"
|
||||
"checksum ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c92464b447c0ee8c4fb3824ecc8383b81717b9f1e74ba2e72540aef7b9f82997"
|
||||
"checksum scoped_threadpool 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1d51f5df5af43ab3f1360b429fa5e0152ac5ce8c0bd6485cae490332e96846a8"
|
||||
"checksum sdl2 0.32.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d051a07231e303f5f719da78cb6f7394f6d5b54f733aef5b0b447804a83edd7b"
|
||||
"checksum sdl2-sys 0.32.6 (registry+https://github.com/rust-lang/crates.io-index)" = "34e71125077d297d57e4c1acfe8981b5bdfbf5a20e7b589abfdcb33bf1127f86"
|
||||
"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
|
||||
"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
|
||||
"checksum stackvector 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "1c4725650978235083241fab0fdc8e694c3de37821524e7534a1a9061d1068af"
|
||||
"checksum static_assertions 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "c19be23126415861cb3a23e501d34a708f7f9b2183c5252d690941c2e69199d5"
|
||||
"checksum static_assertions 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b4f8de36da215253eb5f24020bfaa0646613b48bf7ebe36cdfa37c3b3b33b241"
|
||||
"checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
|
||||
"checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad"
|
||||
"checksum syn 0.15.39 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d960b829a55e56db167e861ddb43602c003c7be0bee1d345021703fac2fb7c"
|
||||
"checksum syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)" = "eadc09306ca51a40555dd6fc2b415538e9e18bc9f870e47b1a524a79fe2dcf5e"
|
||||
"checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6"
|
||||
"checksum synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "02353edf96d6e4dc81aea2d8490a7e9db177bf8acb0e951c24940bf866cb313f"
|
||||
"checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
|
||||
|
|
|
@ -19,6 +19,7 @@ hexdump = "0.1.0"
|
|||
sdl2 = "0.32.2"
|
||||
minifb = "0.11.2"
|
||||
time = "0.1.42"
|
||||
bitfield = "0.13.1"
|
||||
|
||||
[profile.dev]
|
||||
opt-level = 1
|
||||
|
|
|
@ -1,13 +1,9 @@
|
|||
use crate::bit::BitIndex;
|
||||
|
||||
use super::core::gba::GameBoyAdvance;
|
||||
use super::core::ioregs::consts::*;
|
||||
use super::core::keypad;
|
||||
|
||||
pub use super::minifb_backend::MinifbBackend;
|
||||
|
||||
pub trait EmulatorBackend {
|
||||
fn render(&mut self, buffer: Vec<u32>) {}
|
||||
fn render(&mut self, buffer: Vec<u32>);
|
||||
|
||||
fn get_key_state(&self) -> u16;
|
||||
}
|
||||
|
@ -15,7 +11,7 @@ pub trait EmulatorBackend {
|
|||
pub struct DummyBackend;
|
||||
|
||||
impl DummyBackend {
|
||||
fn new() -> DummyBackend {
|
||||
pub fn new() -> DummyBackend {
|
||||
DummyBackend {}
|
||||
}
|
||||
}
|
||||
|
@ -24,4 +20,5 @@ impl EmulatorBackend for DummyBackend {
|
|||
fn get_key_state(&self) -> u16 {
|
||||
keypad::KEYINPUT_ALL_RELEASED
|
||||
}
|
||||
fn render(&mut self, _buffer: Vec<u32>) {}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
use std::time;
|
||||
use std::time::Duration;
|
||||
|
||||
#[macro_use]
|
||||
extern crate clap;
|
||||
|
@ -11,7 +10,6 @@ extern crate rustboyadvance_ng;
|
|||
use rustboyadvance_ng::backend::*;
|
||||
use rustboyadvance_ng::core::arm7tdmi::Core;
|
||||
use rustboyadvance_ng::core::cartridge::Cartridge;
|
||||
use rustboyadvance_ng::core::gpu;
|
||||
use rustboyadvance_ng::core::{GBAResult, GameBoyAdvance};
|
||||
use rustboyadvance_ng::debugger::Debugger;
|
||||
use rustboyadvance_ng::util::read_bin_file;
|
||||
|
@ -30,7 +28,7 @@ fn run_emulator(matches: &ArgMatches) -> GBAResult<()> {
|
|||
Some("sdl2") => panic!("sdl2 not implemented"),
|
||||
Some("minifb") => Box::new(MinifbBackend::new()),
|
||||
// None => DummyBackend::new(),
|
||||
None => Box::new(DummyBackend {}),
|
||||
None => Box::new(DummyBackend::new()),
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
use bit::BitIndex;
|
||||
use num::FromPrimitive;
|
||||
|
||||
use super::{Core, CpuError, CpuResult, REG_PC};
|
||||
|
||||
|
@ -109,7 +108,7 @@ impl Core {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn lsr(&mut self, val: u32, amount: u32, carry_in: bool, immediate: bool) -> u32 {
|
||||
pub fn lsr(&mut self, val: u32, amount: u32, _carry_in: bool, immediate: bool) -> u32 {
|
||||
match amount {
|
||||
0 | 32 => {
|
||||
if immediate {
|
||||
|
@ -130,7 +129,7 @@ impl Core {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn asr(&mut self, val: u32, amount: u32, carry_in: bool, immediate: bool) -> u32 {
|
||||
pub fn asr(&mut self, val: u32, amount: u32, _carry_in: bool, immediate: bool) -> u32 {
|
||||
match amount {
|
||||
0 => {
|
||||
if immediate {
|
||||
|
|
|
@ -426,7 +426,6 @@ impl fmt::Display for ArmInstruction {
|
|||
LDR_STR_HS_REG => self.fmt_ldr_str_hs(f),
|
||||
SWI => self.fmt_swi(f),
|
||||
SWP => self.fmt_swp(f),
|
||||
_ => write!(f, "({:?})", self),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,9 +4,7 @@ use super::super::alu::*;
|
|||
use crate::core::arm7tdmi::bus::Bus;
|
||||
use crate::core::arm7tdmi::cpu::{Core, CpuExecResult};
|
||||
use crate::core::arm7tdmi::psr::RegPSR;
|
||||
use crate::core::arm7tdmi::{
|
||||
Addr, CpuError, CpuMode, CpuResult, CpuState, DecodedInstruction, REG_PC,
|
||||
};
|
||||
use crate::core::arm7tdmi::{Addr, CpuError, CpuMode, CpuResult, CpuState, REG_PC};
|
||||
|
||||
use super::*;
|
||||
|
||||
|
@ -30,11 +28,6 @@ impl Core {
|
|||
ArmFormat::MUL_MLA => self.exec_mul_mla(bus, insn),
|
||||
ArmFormat::MULL_MLAL => self.exec_mull_mlal(bus, insn),
|
||||
ArmFormat::SWP => self.exec_arm_swp(bus, insn),
|
||||
_ => Err(CpuError::UnimplementedCpuInstruction(
|
||||
insn.pc,
|
||||
insn.raw,
|
||||
DecodedInstruction::Arm(insn),
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -417,7 +410,7 @@ impl Core {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn exec_mul_mla(&mut self, bus: &mut Bus, insn: ArmInstruction) -> CpuExecResult {
|
||||
fn exec_mul_mla(&mut self, _bus: &mut Bus, insn: ArmInstruction) -> CpuExecResult {
|
||||
let (rd, rn, rs, rm) = (insn.rd(), insn.rn(), insn.rs(), insn.rm());
|
||||
|
||||
// check validity
|
||||
|
@ -454,7 +447,7 @@ impl Core {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn exec_mull_mlal(&mut self, bus: &mut Bus, insn: ArmInstruction) -> CpuExecResult {
|
||||
fn exec_mull_mlal(&mut self, _bus: &mut Bus, insn: ArmInstruction) -> CpuExecResult {
|
||||
let (rd_hi, rd_lo, rn, rs, rm) =
|
||||
(insn.rd_hi(), insn.rd_lo(), insn.rn(), insn.rs(), insn.rm());
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
use std::fmt;
|
||||
use std::io;
|
||||
use std::ops::Add;
|
||||
|
||||
use super::Addr;
|
||||
|
@ -54,12 +53,15 @@ pub trait Bus {
|
|||
fn write_32(&mut self, addr: Addr, value: u32);
|
||||
fn write_16(&mut self, addr: Addr, value: u16);
|
||||
fn write_8(&mut self, addr: Addr, value: u8);
|
||||
/// Return a slice of bytes
|
||||
fn get_bytes(&self, addr: Addr) -> &[u8];
|
||||
|
||||
/// Return a mutable slice of bytes
|
||||
fn get_bytes_mut(&mut self, addr: Addr) -> &mut [u8];
|
||||
|
||||
/// returns the number of cycles needed for this memory access
|
||||
fn get_cycles(&self, addr: Addr, access: MemoryAccess) -> usize;
|
||||
|
||||
fn get_bytes(&self, range: std::ops::Range<u32>) -> Vec<u8> {
|
||||
let mut bytes = Vec::new();
|
||||
for b in range {
|
||||
bytes.push(self.read_8(b));
|
||||
}
|
||||
bytes
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
use std::fmt;
|
||||
|
||||
use ansi_term::{Colour, Style};
|
||||
use num_traits::Num;
|
||||
|
||||
pub use super::exception::Exception;
|
||||
use super::{
|
||||
alu::*,
|
||||
arm::*,
|
||||
bus::{Bus, MemoryAccess, MemoryAccessType, MemoryAccessType::*, MemoryAccessWidth::*},
|
||||
psr::RegPSR,
|
||||
|
@ -207,10 +205,6 @@ impl Core {
|
|||
}
|
||||
}
|
||||
|
||||
fn advance_pc(&mut self) {
|
||||
self.pc = self.pc.wrapping_add(self.word_size() as u32)
|
||||
}
|
||||
|
||||
pub fn cycles(&self) -> usize {
|
||||
self.cycles
|
||||
}
|
||||
|
|
|
@ -37,7 +37,6 @@ impl ThumbInstruction {
|
|||
}
|
||||
|
||||
fn fmt_thumb_alu_ops(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
use ShiftRegisterBy::ByRegister;
|
||||
let (op, shft) = self.alu_opcode();
|
||||
if let Some(BarrelShifterValue::ShiftedRegister(x)) = shft {
|
||||
write!(f, "{}", x.bs_op)?;
|
||||
|
@ -308,7 +307,6 @@ impl fmt::Display for ThumbInstruction {
|
|||
ThumbFormat::Swi => self.fmt_thumb_swi(f),
|
||||
ThumbFormat::Branch => self.fmt_thumb_branch(f),
|
||||
ThumbFormat::BranchLongWithLink => self.fmt_thumb_branch_long_with_link(f),
|
||||
_ => write!(f, "({:?})", self),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -446,7 +446,6 @@ impl Core {
|
|||
ThumbFormat::Swi => self.exec_swi(),
|
||||
ThumbFormat::Branch => self.exec_thumb_branch(bus, insn),
|
||||
ThumbFormat::BranchLongWithLink => self.exec_thumb_branch_long_with_link(bus, insn),
|
||||
_ => unimplemented!("thumb not implemented {:#x?}", insn),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -126,14 +126,6 @@ impl Bus for Cartridge {
|
|||
(&mut self.bytes[addr as usize..]).write_u8(value).unwrap()
|
||||
}
|
||||
|
||||
fn get_bytes(&self, addr: Addr) -> &[u8] {
|
||||
&self.bytes[addr as usize..]
|
||||
}
|
||||
|
||||
fn get_bytes_mut(&mut self, addr: Addr) -> &mut [u8] {
|
||||
&mut self.bytes[addr as usize..]
|
||||
}
|
||||
|
||||
fn get_cycles(&self, _addr: Addr, access: MemoryAccess) -> usize {
|
||||
match access.1 {
|
||||
MemoryAccessWidth::MemoryAccess8 => self.ws.access8,
|
||||
|
|
128
src/core/dma.rs
128
src/core/dma.rs
|
@ -1,74 +1,74 @@
|
|||
use super::arm7tdmi::{Addr, Bus};
|
||||
use super::ioregs::consts::*;
|
||||
use super::sysbus::SysBus;
|
||||
use super::{EmuIoDev, Interrupt};
|
||||
// use super::arm7tdmi::{Addr, Bus};
|
||||
// use super::ioregs::consts::*;
|
||||
// use super::sysbus::SysBus;
|
||||
// use super::{EmuIoDev, Interrupt};
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
#[derive(Debug)]
|
||||
pub struct DmaChannel {
|
||||
src_ioreg: Addr, /* Source Address register */
|
||||
dst_ioreg: Addr, /* Destination Address register */
|
||||
wc_ioreg: Addr, /* Word Count 14bit */
|
||||
}
|
||||
// #[allow(non_camel_case_types)]
|
||||
// #[derive(Debug)]
|
||||
// pub struct DmaChannel {
|
||||
// src_ioreg: Addr, /* Source Address register */
|
||||
// dst_ioreg: Addr, /* Destination Address register */
|
||||
// wc_ioreg: Addr, /* Word Count 14bit */
|
||||
// }
|
||||
|
||||
#[derive(Debug, Primitive)]
|
||||
enum DmaAddrControl {
|
||||
Increment = 0,
|
||||
Decrement = 1,
|
||||
Fixed = 2,
|
||||
IncrementReloadProhibited = 3,
|
||||
}
|
||||
// #[derive(Debug, Primitive)]
|
||||
// enum DmaAddrControl {
|
||||
// Increment = 0,
|
||||
// Decrement = 1,
|
||||
// Fixed = 2,
|
||||
// IncrementReloadProhibited = 3,
|
||||
// }
|
||||
|
||||
#[derive(Debug)]
|
||||
enum DmaTransferType {
|
||||
Xfer16bit,
|
||||
Xfer32bit,
|
||||
}
|
||||
// #[derive(Debug)]
|
||||
// enum DmaTransferType {
|
||||
// Xfer16bit,
|
||||
// Xfer32bit,
|
||||
// }
|
||||
|
||||
#[derive(Debug, Primitive)]
|
||||
enum DmaStartTiming {
|
||||
Immediately = 0,
|
||||
VBlank = 1,
|
||||
HBlank = 2,
|
||||
Special = 3,
|
||||
}
|
||||
// #[derive(Debug, Primitive)]
|
||||
// enum DmaStartTiming {
|
||||
// Immediately = 0,
|
||||
// VBlank = 1,
|
||||
// HBlank = 2,
|
||||
// Special = 3,
|
||||
// }
|
||||
|
||||
#[derive(Debug)]
|
||||
struct DmaControl {
|
||||
dst_addr_ctl: DmaAddrControl,
|
||||
src_addr_ctl: DmaAddrControl,
|
||||
repeat: bool,
|
||||
xfer: DmaTransferType,
|
||||
start_timing: DmaStartTiming,
|
||||
irq_upon_end_of_wc: bool,
|
||||
enable: bool,
|
||||
}
|
||||
// #[derive(Debug)]
|
||||
// struct DmaControl {
|
||||
// dst_addr_ctl: DmaAddrControl,
|
||||
// src_addr_ctl: DmaAddrControl,
|
||||
// repeat: bool,
|
||||
// xfer: DmaTransferType,
|
||||
// start_timing: DmaStartTiming,
|
||||
// irq_upon_end_of_wc: bool,
|
||||
// enable: bool,
|
||||
// }
|
||||
|
||||
impl DmaChannel {
|
||||
pub fn new(src_ioreg: Addr, dst_ioreg: Addr, wc_ioreg: Addr) -> DmaChannel {
|
||||
DmaChannel {
|
||||
src_ioreg,
|
||||
dst_ioreg,
|
||||
wc_ioreg,
|
||||
}
|
||||
}
|
||||
// impl DmaChannel {
|
||||
// pub fn new(src_ioreg: Addr, dst_ioreg: Addr, wc_ioreg: Addr) -> DmaChannel {
|
||||
// DmaChannel {
|
||||
// src_ioreg,
|
||||
// dst_ioreg,
|
||||
// wc_ioreg,
|
||||
// }
|
||||
// }
|
||||
|
||||
fn src_addr(&self, sysbus: &SysBus) -> Addr {
|
||||
sysbus.ioregs.read_32(self.src_ioreg - IO_BASE) as Addr
|
||||
}
|
||||
// // fn src_addr(&self, sysbus: &SysBus) -> Addr {
|
||||
// // sysbus.ioregs.read_32(self.src_ioreg - IO_BASE) as Addr
|
||||
// // }
|
||||
|
||||
fn dst_addr(&self, sysbus: &SysBus) -> Addr {
|
||||
sysbus.ioregs.read_32(self.dst_ioreg - IO_BASE) as Addr
|
||||
}
|
||||
// // fn dst_addr(&self, sysbus: &SysBus) -> Addr {
|
||||
// // sysbus.ioregs.read_32(self.dst_ioreg - IO_BASE) as Addr
|
||||
// // }
|
||||
|
||||
fn word_count(&self, sysbus: &SysBus) -> usize {
|
||||
sysbus.ioregs.read_reg(self.wc_ioreg) as usize
|
||||
}
|
||||
}
|
||||
// // fn word_count(&self, sysbus: &SysBus) -> usize {
|
||||
// // sysbus.ioregs.read_reg(self.wc_ioreg) as usize
|
||||
// // }
|
||||
// }
|
||||
|
||||
impl EmuIoDev for DmaChannel {
|
||||
fn step(&mut self, cycles: usize, sysbus: &mut SysBus) -> (usize, Option<Interrupt>) {
|
||||
// TODO
|
||||
(0, None)
|
||||
}
|
||||
}
|
||||
// impl EmuIoDev for DmaChannel {
|
||||
// fn step(&mut self, cycles: usize, sysbus: &mut SysBus) -> (usize, Option<Interrupt>) {
|
||||
// // TODO
|
||||
// (0, None)
|
||||
// }
|
||||
// }
|
||||
|
|
114
src/core/gba.rs
114
src/core/gba.rs
|
@ -1,31 +1,39 @@
|
|||
/// Struct containing everything
|
||||
///
|
||||
use super::arm7tdmi::{exception::*, Core, DecodedInstruction};
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
|
||||
use super::arm7tdmi::{Core, DecodedInstruction};
|
||||
use super::cartridge::Cartridge;
|
||||
use super::dma::DmaChannel;
|
||||
use super::gpu::*;
|
||||
use super::interrupt::*;
|
||||
use super::ioregs::consts::*;
|
||||
use super::ioregs::IoRegs;
|
||||
use super::sysbus::SysBus;
|
||||
use super::EmuIoDev;
|
||||
use super::{GBAError, GBAResult};
|
||||
use super::GBAResult;
|
||||
use crate::backend::*;
|
||||
|
||||
use crate::bit::BitIndex;
|
||||
#[derive(Debug)]
|
||||
pub struct IoDevices {
|
||||
pub intc: InterruptController,
|
||||
pub gpu: Gpu,
|
||||
}
|
||||
|
||||
impl IoDevices {
|
||||
pub fn new() -> IoDevices {
|
||||
IoDevices {
|
||||
intc: InterruptController::new(),
|
||||
gpu: Gpu::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct GameBoyAdvance {
|
||||
backend: Box<EmulatorBackend>,
|
||||
pub cpu: Core,
|
||||
pub sysbus: SysBus,
|
||||
|
||||
// io devices
|
||||
pub gpu: Gpu,
|
||||
pub dma0: DmaChannel,
|
||||
pub dma1: DmaChannel,
|
||||
pub dma2: DmaChannel,
|
||||
pub dma3: DmaChannel,
|
||||
|
||||
post_bool_flags: bool,
|
||||
pub io: Rc<RefCell<IoDevices>>,
|
||||
}
|
||||
|
||||
impl GameBoyAdvance {
|
||||
|
@ -35,90 +43,60 @@ impl GameBoyAdvance {
|
|||
gamepak: Cartridge,
|
||||
backend: Box<EmulatorBackend>,
|
||||
) -> GameBoyAdvance {
|
||||
let sysbus = SysBus::new(bios_rom, gamepak);
|
||||
let io = Rc::new(RefCell::new(IoDevices::new()));
|
||||
|
||||
let ioregs = IoRegs::new(io.clone());
|
||||
let sysbus = SysBus::new(bios_rom, gamepak, ioregs);
|
||||
|
||||
GameBoyAdvance {
|
||||
backend: backend,
|
||||
cpu: cpu,
|
||||
sysbus: sysbus,
|
||||
|
||||
gpu: Gpu::new(),
|
||||
dma0: DmaChannel::new(REG_DMA0SAD, REG_DMA0DAD, REG_DMA0DAD),
|
||||
dma1: DmaChannel::new(REG_DMA1SAD, REG_DMA1DAD, REG_DMA1DAD),
|
||||
dma2: DmaChannel::new(REG_DMA2SAD, REG_DMA2DAD, REG_DMA2DAD),
|
||||
dma3: DmaChannel::new(REG_DMA3SAD, REG_DMA3DAD, REG_DMA3DAD),
|
||||
|
||||
post_bool_flags: false,
|
||||
io: io.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn frame(&mut self) {
|
||||
self.update_key_state();
|
||||
while self.gpu.state != GpuState::VBlank {
|
||||
self.emulate();
|
||||
while self.io.borrow().gpu.state != GpuState::VBlank {
|
||||
let cycles = self.emulate_cpu();
|
||||
self.emulate_peripherals(cycles);
|
||||
}
|
||||
self.backend.render(self.gpu.render());
|
||||
while self.gpu.state == GpuState::VBlank {
|
||||
self.emulate();
|
||||
self.backend.render(self.io.borrow().gpu.render());
|
||||
while self.io.borrow().gpu.state == GpuState::VBlank {
|
||||
let cycles = self.emulate_cpu();
|
||||
self.emulate_peripherals(cycles);
|
||||
}
|
||||
}
|
||||
|
||||
fn update_key_state(&mut self) {
|
||||
let keyinput = self.backend.get_key_state();
|
||||
self.sysbus.ioregs.write_reg(REG_KEYINPUT, keyinput);
|
||||
self.sysbus.ioregs.keyinput = self.backend.get_key_state();
|
||||
}
|
||||
|
||||
pub fn emulate(&mut self) {
|
||||
pub fn emulate_cpu(&mut self) -> usize {
|
||||
let previous_cycles = self.cpu.cycles;
|
||||
self.cpu.step(&mut self.sysbus).unwrap();
|
||||
let cycles = self.cpu.cycles - previous_cycles;
|
||||
let (_, irq) = self.gpu.step(cycles, &mut self.sysbus);
|
||||
self.cpu.cycles - previous_cycles
|
||||
}
|
||||
|
||||
pub fn emulate_peripherals(&mut self, cycles: usize) {
|
||||
let mut io = self.io.borrow_mut();
|
||||
let (_, irq) = io.gpu.step(cycles, &mut self.sysbus);
|
||||
if let Some(irq) = irq {
|
||||
self.request_irq(irq);
|
||||
}
|
||||
}
|
||||
|
||||
fn interrupts_disabled(&self) -> bool {
|
||||
self.cpu.cpsr.irq_disabled() | (self.sysbus.ioregs.read_reg(REG_IME) & 1 == 0)
|
||||
}
|
||||
|
||||
fn request_irq(&mut self, irq: Interrupt) {
|
||||
if self.interrupts_disabled() {
|
||||
return;
|
||||
}
|
||||
let irq_bit_index = irq as usize;
|
||||
let reg_ie = self.sysbus.ioregs.read_reg(REG_IE);
|
||||
if reg_ie.bit(irq_bit_index) {
|
||||
self.sysbus
|
||||
.ioregs
|
||||
.write_reg(REG_IF, (1 << irq_bit_index) as u16);
|
||||
self.cpu.exception(Exception::Irq);
|
||||
io.intc.request_irq(&mut self.cpu, irq);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn step(&mut self) -> GBAResult<DecodedInstruction> {
|
||||
let previous_cycles = self.cpu.cycles;
|
||||
let executed_insn = self.cpu.step_one(&mut self.sysbus)?;
|
||||
let cycles = self.cpu.cycles - previous_cycles;
|
||||
|
||||
let mut cycles = self.cpu.cycles - previous_cycles;
|
||||
self.emulate_peripherals(cycles);
|
||||
|
||||
// // drop interrupts at the moment
|
||||
|
||||
// let (dma_cycles, _) = self.dma0.step(cycles, &mut self.sysbus);
|
||||
// cycles += dma_cycles;
|
||||
|
||||
// let (dma_cycles, _) = self.dma1.step(cycles, &mut self.sysbus);
|
||||
// cycles += dma_cycles;
|
||||
|
||||
// let (dma_cycles, _) = self.dma2.step(cycles, &mut self.sysbus);
|
||||
// cycles += dma_cycles;
|
||||
|
||||
// let (dma_cycles, _) = self.dma3.step(cycles, &mut self.sysbus);
|
||||
// cycles += dma_cycles;
|
||||
|
||||
let (_, irq) = self.gpu.step(cycles, &mut self.sysbus);
|
||||
if let Some(irq) = irq {
|
||||
self.request_irq(irq);
|
||||
if self.io.borrow().gpu.state == GpuState::HBlank {
|
||||
self.backend.render(self.io.borrow().gpu.render());
|
||||
}
|
||||
|
||||
Ok(executed_insn)
|
||||
|
|
334
src/core/gpu.rs
334
src/core/gpu.rs
|
@ -1,16 +1,15 @@
|
|||
use std::fmt;
|
||||
|
||||
use super::arm7tdmi::{Addr, Bus};
|
||||
use super::ioregs::consts::*;
|
||||
use super::palette::{Palette, PixelFormat, Rgb15};
|
||||
use super::palette::{PixelFormat, Rgb15};
|
||||
use super::*;
|
||||
|
||||
use crate::bit::BitIndex;
|
||||
use crate::bitfield::Bit;
|
||||
use crate::num::FromPrimitive;
|
||||
|
||||
const VRAM_ADDR: Addr = 0x0600_0000;
|
||||
|
||||
#[derive(Debug, Primitive)]
|
||||
#[derive(Debug, Primitive, Clone, Copy)]
|
||||
enum BGMode {
|
||||
BGMode0 = 0,
|
||||
BGMode1 = 1,
|
||||
|
@ -20,104 +19,77 @@ enum BGMode {
|
|||
BGMode5 = 5,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct DisplayControl {
|
||||
bg_mode: BGMode,
|
||||
display_frame: usize,
|
||||
hblank_interval_free: bool,
|
||||
obj_character_vram_mapping: bool, // true - 1 dimentional, false - 2 dimentional
|
||||
forced_blank: bool,
|
||||
disp_bg: [bool; 4],
|
||||
disp_obj: bool,
|
||||
disp_window0: bool,
|
||||
disp_window1: bool,
|
||||
disp_obj_window: bool,
|
||||
}
|
||||
|
||||
impl From<u16> for DisplayControl {
|
||||
fn from(v: u16) -> Self {
|
||||
DisplayControl {
|
||||
bg_mode: BGMode::from_u8(v.bit_range(0..3) as u8).unwrap(),
|
||||
// bit 3 is unused
|
||||
display_frame: v.bit(4) as usize,
|
||||
hblank_interval_free: v.bit(5),
|
||||
obj_character_vram_mapping: v.bit(6),
|
||||
forced_blank: v.bit(7),
|
||||
disp_bg: [v.bit(8), v.bit(9), v.bit(10), v.bit(11)],
|
||||
disp_obj: v.bit(12),
|
||||
disp_window0: v.bit(13),
|
||||
disp_window1: v.bit(14),
|
||||
disp_obj_window: v.bit(15),
|
||||
}
|
||||
impl From<u16> for BGMode {
|
||||
fn from(v: u16) -> BGMode {
|
||||
BGMode::from_u16(v).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct DisplayStatus {
|
||||
vblank_flag: bool,
|
||||
hblank_flag: bool,
|
||||
vcount_flag: bool,
|
||||
vblank_irq_enable: bool,
|
||||
hblank_irq_enable: bool,
|
||||
vcount_irq_enable: bool,
|
||||
vcount_setting: u8,
|
||||
raw_value: u16,
|
||||
bitfield! {
|
||||
pub struct DisplayControl(u16);
|
||||
impl Debug;
|
||||
u16;
|
||||
into BGMode, mode, set_mode: 2, 0;
|
||||
display_frame, set_display_frame: 4, 4;
|
||||
hblank_interval_free, _: 5;
|
||||
obj_character_vram_mapping, _: 6;
|
||||
forst_vblank, _: 7;
|
||||
disp_bg0, _ : 8;
|
||||
disp_bg1, _ : 9;
|
||||
disp_bg2, _ : 10;
|
||||
disp_bg3, _ : 11;
|
||||
disp_obj, _ : 12;
|
||||
disp_window0, _ : 13;
|
||||
disp_window1, _ : 14;
|
||||
disp_obj_window, _ : 15;
|
||||
}
|
||||
|
||||
impl From<u16> for DisplayStatus {
|
||||
fn from(v: u16) -> Self {
|
||||
DisplayStatus {
|
||||
vblank_flag: v.bit(0),
|
||||
hblank_flag: v.bit(1),
|
||||
vcount_flag: v.bit(2),
|
||||
vblank_irq_enable: v.bit(3),
|
||||
hblank_irq_enable: v.bit(4),
|
||||
vcount_irq_enable: v.bit(5),
|
||||
// bits 6-7 are unused in GBA
|
||||
vcount_setting: v.bit_range(8..16) as u8,
|
||||
raw_value: v,
|
||||
}
|
||||
impl DisplayControl {
|
||||
fn disp_bg(&self, bg: usize) -> bool {
|
||||
self.0.bit(8 + bg)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct BgControl {
|
||||
bg_priority: u8,
|
||||
character_base_block: u8,
|
||||
moasic: bool,
|
||||
palette256: bool, // 0=16/16, 1=256/1)
|
||||
screen_base_block: u8,
|
||||
affine_wraparound: bool,
|
||||
bg_size: u32,
|
||||
bitfield! {
|
||||
pub struct DisplayStatus(u16);
|
||||
impl Debug;
|
||||
u16;
|
||||
get_vblank, set_vblank: 0;
|
||||
get_hblank, set_hblank: 1;
|
||||
get_vcount, set_vcount: 2;
|
||||
vblank_irq_enable, _ : 3;
|
||||
hblank_irq_enable, _ : 4;
|
||||
vcount_irq_enable, _ : 5;
|
||||
vcount_setting, _ : 15, 8;
|
||||
}
|
||||
|
||||
impl From<u16> for BgControl {
|
||||
fn from(v: u16) -> Self {
|
||||
BgControl {
|
||||
bg_priority: v.bit_range(0..2) as u8,
|
||||
character_base_block: v.bit_range(2..4) as u8,
|
||||
moasic: v.bit(6),
|
||||
palette256: v.bit(7),
|
||||
screen_base_block: v.bit_range(8..13) as u8,
|
||||
affine_wraparound: v.bit(13),
|
||||
bg_size: v.bit_range(14..16) as u32,
|
||||
}
|
||||
}
|
||||
bitfield! {
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct BgControl(u16);
|
||||
impl Debug;
|
||||
u16;
|
||||
bg_priority, _: 1, 0;
|
||||
character_base_block, _: 3, 2;
|
||||
moasic, _ : 6;
|
||||
palette256, _ : 7;
|
||||
screen_base_block, _: 12, 8;
|
||||
affine_wraparound, _: 13;
|
||||
bg_size, _ : 15, 14;
|
||||
}
|
||||
|
||||
const SCREEN_BLOCK_SIZE: u32 = 0x800;
|
||||
|
||||
impl BgControl {
|
||||
pub fn char_block(&self) -> Addr {
|
||||
VRAM_ADDR + (self.character_base_block as u32) * 0x4000
|
||||
VRAM_ADDR + (self.character_base_block() as u32) * 0x4000
|
||||
}
|
||||
|
||||
pub fn screen_block(&self) -> Addr {
|
||||
VRAM_ADDR + (self.screen_base_block as u32) * SCREEN_BLOCK_SIZE
|
||||
VRAM_ADDR + (self.screen_base_block() as u32) * SCREEN_BLOCK_SIZE
|
||||
}
|
||||
|
||||
fn size_regular(&self) -> (u32, u32) {
|
||||
match self.bg_size {
|
||||
match self.bg_size() {
|
||||
0b00 => (256, 256),
|
||||
0b01 => (512, 256),
|
||||
0b10 => (256, 512),
|
||||
|
@ -127,7 +99,7 @@ impl BgControl {
|
|||
}
|
||||
|
||||
pub fn tile_format(&self) -> (u32, PixelFormat) {
|
||||
if self.palette256 {
|
||||
if self.palette256() {
|
||||
(2 * Gpu::TILE_SIZE, PixelFormat::BPP8)
|
||||
} else {
|
||||
(Gpu::TILE_SIZE, PixelFormat::BPP4)
|
||||
|
@ -176,6 +148,23 @@ impl std::ops::IndexMut<usize> for FrameBuffer {
|
|||
|
||||
#[derive(Debug)]
|
||||
pub struct Gpu {
|
||||
// registers
|
||||
pub dispcnt: DisplayControl,
|
||||
pub dispstat: DisplayStatus,
|
||||
pub bgcnt: [BgControl; 4],
|
||||
pub bgvofs: [u16; 4],
|
||||
pub bghofs: [u16; 4],
|
||||
pub win0h: u16,
|
||||
pub win1h: u16,
|
||||
pub win0v: u16,
|
||||
pub win1v: u16,
|
||||
pub winin: u16,
|
||||
pub winout: u16,
|
||||
pub mosaic: u16,
|
||||
pub bldcnt: u16,
|
||||
pub bldalpha: u16,
|
||||
pub bldy: u16,
|
||||
|
||||
cycles: usize,
|
||||
|
||||
pub pixeldata: FrameBuffer,
|
||||
|
@ -198,6 +187,22 @@ impl Gpu {
|
|||
|
||||
pub fn new() -> Gpu {
|
||||
Gpu {
|
||||
dispcnt: DisplayControl(0x80),
|
||||
dispstat: DisplayStatus(0),
|
||||
bgcnt: [BgControl(0), BgControl(0), BgControl(0), BgControl(0)],
|
||||
bgvofs: [0; 4],
|
||||
bghofs: [0; 4],
|
||||
win0h: 0,
|
||||
win1h: 0,
|
||||
win0v: 0,
|
||||
win1v: 0,
|
||||
winin: 0,
|
||||
winout: 0,
|
||||
mosaic: 0,
|
||||
bldcnt: 0,
|
||||
bldalpha: 0,
|
||||
bldy: 0,
|
||||
|
||||
state: HDraw,
|
||||
current_scanline: 0,
|
||||
cycles: 0,
|
||||
|
@ -205,61 +210,6 @@ impl Gpu {
|
|||
}
|
||||
}
|
||||
|
||||
fn palette(&self, sysbus: &SysBus) -> Palette {
|
||||
Palette::from(sysbus.get_bytes(0x0500_0000))
|
||||
}
|
||||
|
||||
fn update_regs(&self, dispstat: DisplayStatus, sysbus: &mut SysBus) {
|
||||
let mut v = dispstat.raw_value;
|
||||
v.set_bit(0, dispstat.vblank_flag);
|
||||
v.set_bit(1, dispstat.hblank_flag);
|
||||
v.set_bit(2, dispstat.vcount_flag);
|
||||
sysbus.ioregs.write_reg(REG_DISPSTAT, v);
|
||||
}
|
||||
|
||||
pub fn set_hblank(&mut self, sysbus: &mut SysBus) -> Option<Interrupt> {
|
||||
let dispstat = DisplayStatus::from(sysbus.ioregs.read_reg(REG_DISPSTAT));
|
||||
let mut v = dispstat.raw_value;
|
||||
v.set_bit(1, true);
|
||||
self.state = HBlank;
|
||||
sysbus.ioregs.write_reg(REG_DISPSTAT, v);
|
||||
|
||||
if dispstat.hblank_irq_enable {
|
||||
Some(Interrupt::LCD_HBlank)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_vblank(&mut self, sysbus: &mut SysBus) -> Option<Interrupt> {
|
||||
let dispstat = DisplayStatus::from(sysbus.ioregs.read_reg(REG_DISPSTAT));
|
||||
let mut v = dispstat.raw_value;
|
||||
v.set_bit(1, false);
|
||||
v.set_bit(0, true);
|
||||
self.state = VBlank;
|
||||
sysbus.ioregs.write_reg(REG_DISPSTAT, v);
|
||||
|
||||
if dispstat.vblank_irq_enable {
|
||||
Some(Interrupt::LCD_VBlank)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_hdraw(&mut self) {
|
||||
self.state = HDraw;
|
||||
}
|
||||
|
||||
fn bgcnt(&self, bg: u32, sysbus: &SysBus) -> BgControl {
|
||||
BgControl::from(sysbus.ioregs.read_reg(REG_BG0CNT + 2 * bg))
|
||||
}
|
||||
|
||||
fn bgofs(&self, bg: u32, sysbus: &SysBus) -> (u32, u32) {
|
||||
let hofs = sysbus.ioregs.read_reg(REG_BG0HOFS + 4 * bg) & 0x1ff;
|
||||
let vofs = sysbus.ioregs.read_reg(REG_BG0VOFS + 4 * bg) & 0x1ff;
|
||||
(hofs as u32, vofs as u32)
|
||||
}
|
||||
|
||||
/// helper method that reads the palette index from a base address and x + y
|
||||
pub fn read_pixel_index(
|
||||
&self,
|
||||
|
@ -289,14 +239,13 @@ impl Gpu {
|
|||
.into()
|
||||
}
|
||||
|
||||
fn scanline_mode0(&mut self, bg: u32, sb: &mut SysBus) {
|
||||
let bgcnt = self.bgcnt(bg, sb);
|
||||
let (h_ofs, v_ofs) = self.bgofs(bg, sb);
|
||||
let tileset_base = bgcnt.char_block() - VRAM_ADDR;
|
||||
let tilemap_base = bgcnt.screen_block() - VRAM_ADDR;
|
||||
let (tile_size, pixel_format) = bgcnt.tile_format();
|
||||
fn scanline_mode0(&mut self, bg: usize, sb: &mut SysBus) {
|
||||
let (h_ofs, v_ofs) = (self.bghofs[bg] as u32, self.bgvofs[bg] as u32);
|
||||
let tileset_base = self.bgcnt[bg].char_block() - VRAM_ADDR;
|
||||
let tilemap_base = self.bgcnt[bg].screen_block() - VRAM_ADDR;
|
||||
let (tile_size, pixel_format) = self.bgcnt[bg].tile_format();
|
||||
|
||||
let (bg_width, bg_height) = bgcnt.size_regular();
|
||||
let (bg_width, bg_height) = self.bgcnt[bg].size_regular();
|
||||
|
||||
let screen_y = self.current_scanline as u32;
|
||||
let mut screen_x = 0;
|
||||
|
@ -330,20 +279,20 @@ impl Gpu {
|
|||
let map_addr = tilemap_base
|
||||
+ SCREEN_BLOCK_SIZE * screen_block
|
||||
+ 2 * (index2d!((se_row + t) % 32, se_column, 32) as u32);
|
||||
let entry = TileMapEntry::from(sb.vram.read_16(map_addr - VRAM_ADDR));
|
||||
let tile_addr = tileset_base + entry.tile_index * tile_size;
|
||||
let entry = TileMapEntry(sb.vram.read_16(map_addr - VRAM_ADDR));
|
||||
let tile_addr = tileset_base + entry.tile_index() * tile_size;
|
||||
|
||||
for tile_px in start_tile_x..=7 {
|
||||
let tile_py = (bg_y % 8) as u32;
|
||||
let index = self.read_pixel_index(
|
||||
sb,
|
||||
tile_addr,
|
||||
if entry.x_flip { 7 - tile_px } else { tile_px },
|
||||
if entry.y_flip { 7 - tile_py } else { tile_py },
|
||||
if entry.x_flip() { 7 - tile_px } else { tile_px },
|
||||
if entry.y_flip() { 7 - tile_py } else { tile_py },
|
||||
pixel_format,
|
||||
);
|
||||
let palette_bank = match pixel_format {
|
||||
PixelFormat::BPP4 => entry.palette_bank as u32,
|
||||
PixelFormat::BPP4 => entry.palette_bank() as u32,
|
||||
PixelFormat::BPP8 => 0u32,
|
||||
};
|
||||
let color = self.get_palette_color(sb, index as u32, palette_bank);
|
||||
|
@ -364,7 +313,7 @@ impl Gpu {
|
|||
}
|
||||
}
|
||||
|
||||
fn scanline_mode3(&mut self, bg: u32, sb: &mut SysBus) {
|
||||
fn scanline_mode3(&mut self, _bg: u32, sb: &mut SysBus) {
|
||||
let y = self.current_scanline;
|
||||
|
||||
for x in 0..Self::DISPLAY_WIDTH {
|
||||
|
@ -374,8 +323,8 @@ impl Gpu {
|
|||
}
|
||||
}
|
||||
|
||||
fn scanline_mode4(&mut self, bg: u32, dispcnt: &DisplayControl, sb: &mut SysBus) {
|
||||
let page_ofs: u32 = match dispcnt.display_frame {
|
||||
fn scanline_mode4(&mut self, _bg: u32, sb: &mut SysBus) {
|
||||
let page_ofs: u32 = match self.dispcnt.display_frame() {
|
||||
0 => 0x0600_0000 - VRAM_ADDR,
|
||||
1 => 0x0600_a000 - VRAM_ADDR,
|
||||
_ => unreachable!(),
|
||||
|
@ -391,28 +340,26 @@ impl Gpu {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn scanline(&mut self, sysbus: &mut SysBus) {
|
||||
let dispcnt = DisplayControl::from(sysbus.ioregs.read_reg(REG_DISPCNT));
|
||||
|
||||
match dispcnt.bg_mode {
|
||||
pub fn scanline(&mut self, sb: &mut SysBus) {
|
||||
match self.dispcnt.mode() {
|
||||
BGMode::BGMode0 => {
|
||||
for bg in (0..3).rev() {
|
||||
if dispcnt.disp_bg[bg] {
|
||||
self.scanline_mode0(bg as u32, sysbus);
|
||||
if self.dispcnt.disp_bg(bg) {
|
||||
self.scanline_mode0(bg, sb);
|
||||
}
|
||||
}
|
||||
}
|
||||
BGMode::BGMode2 => {
|
||||
self.scanline_mode0(2, sysbus);
|
||||
self.scanline_mode0(3, sysbus);
|
||||
self.scanline_mode0(2, sb);
|
||||
self.scanline_mode0(3, sb);
|
||||
}
|
||||
BGMode::BGMode3 => {
|
||||
self.scanline_mode3(2, sysbus);
|
||||
self.scanline_mode3(2, sb);
|
||||
}
|
||||
BGMode::BGMode4 => {
|
||||
self.scanline_mode4(2, &dispcnt, sysbus);
|
||||
self.scanline_mode4(2, sb);
|
||||
}
|
||||
_ => panic!("{:?} not supported", dispcnt.bg_mode),
|
||||
_ => panic!("{:?} not supported", self.dispcnt.mode()),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -430,17 +377,15 @@ impl Gpu {
|
|||
}
|
||||
|
||||
impl EmuIoDev for Gpu {
|
||||
fn step(&mut self, cycles: usize, sysbus: &mut SysBus) -> (usize, Option<Interrupt>) {
|
||||
fn step(&mut self, cycles: usize, sb: &mut SysBus) -> (usize, Option<Interrupt>) {
|
||||
self.cycles += cycles;
|
||||
|
||||
sysbus
|
||||
.ioregs
|
||||
.write_reg(REG_VCOUNT, self.current_scanline as u16);
|
||||
let mut dispstat = DisplayStatus::from(sysbus.ioregs.read_reg(REG_DISPSTAT));
|
||||
|
||||
dispstat.vcount_flag = dispstat.vcount_setting as usize == self.current_scanline;
|
||||
if dispstat.vcount_irq_enable {
|
||||
println!("VCOUNT IRQ NOT IMPL");
|
||||
if self.dispstat.vcount_setting() != 0 {
|
||||
self.dispstat
|
||||
.set_vcount(self.dispstat.vcount_setting() == self.current_scanline as u16);
|
||||
}
|
||||
if self.dispstat.vcount_irq_enable() && self.dispstat.get_vcount() {
|
||||
return (0, Some(Interrupt::LCD_VCounterMatch));
|
||||
}
|
||||
|
||||
match self.state {
|
||||
|
@ -450,19 +395,19 @@ impl EmuIoDev for Gpu {
|
|||
self.cycles -= Gpu::CYCLES_HDRAW;
|
||||
|
||||
let (new_state, irq) = if self.current_scanline < Gpu::DISPLAY_HEIGHT {
|
||||
self.scanline(sysbus);
|
||||
self.scanline(sb);
|
||||
// HBlank
|
||||
dispstat.hblank_flag = true;
|
||||
let irq = if dispstat.hblank_irq_enable {
|
||||
self.dispstat.set_hblank(true);
|
||||
let irq = if self.dispstat.hblank_irq_enable() {
|
||||
Some(Interrupt::LCD_HBlank)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
(HBlank, irq)
|
||||
} else {
|
||||
self.scanline(sysbus);
|
||||
dispstat.vblank_flag = true;
|
||||
let irq = if dispstat.vblank_irq_enable {
|
||||
self.scanline(sb);
|
||||
self.dispstat.set_vblank(true);
|
||||
let irq = if self.dispstat.vblank_irq_enable() {
|
||||
Some(Interrupt::LCD_VBlank)
|
||||
} else {
|
||||
None
|
||||
|
@ -470,7 +415,6 @@ impl EmuIoDev for Gpu {
|
|||
(VBlank, irq)
|
||||
};
|
||||
self.state = new_state;
|
||||
self.update_regs(dispstat, sysbus);
|
||||
return (0, irq);
|
||||
}
|
||||
}
|
||||
|
@ -478,8 +422,8 @@ impl EmuIoDev for Gpu {
|
|||
if self.cycles > Gpu::CYCLES_HBLANK {
|
||||
self.cycles -= Gpu::CYCLES_HBLANK;
|
||||
self.state = HDraw;
|
||||
dispstat.hblank_flag = false;
|
||||
self.update_regs(dispstat, sysbus);
|
||||
self.dispstat.set_hblank(false);
|
||||
self.dispstat.set_vblank(false);
|
||||
return (0, None);
|
||||
}
|
||||
}
|
||||
|
@ -487,10 +431,10 @@ impl EmuIoDev for Gpu {
|
|||
if self.cycles > Gpu::CYCLES_VBLANK {
|
||||
self.cycles -= Gpu::CYCLES_VBLANK;
|
||||
self.state = HDraw;
|
||||
dispstat.vblank_flag = false;
|
||||
self.dispstat.set_hblank(false);
|
||||
self.dispstat.set_vblank(false);
|
||||
self.current_scanline = 0;
|
||||
self.scanline(sysbus);
|
||||
self.update_regs(dispstat, sysbus);
|
||||
self.scanline(sb);
|
||||
return (0, None);
|
||||
}
|
||||
}
|
||||
|
@ -500,21 +444,11 @@ impl EmuIoDev for Gpu {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct TileMapEntry {
|
||||
tile_index: u32,
|
||||
x_flip: bool,
|
||||
y_flip: bool,
|
||||
palette_bank: usize,
|
||||
}
|
||||
|
||||
impl From<u16> for TileMapEntry {
|
||||
fn from(t: u16) -> TileMapEntry {
|
||||
TileMapEntry {
|
||||
tile_index: t.bit_range(0..10) as u32,
|
||||
x_flip: t.bit(10),
|
||||
y_flip: t.bit(11),
|
||||
palette_bank: t.bit_range(12..16) as usize,
|
||||
}
|
||||
}
|
||||
bitfield! {
|
||||
struct TileMapEntry(u16);
|
||||
u16;
|
||||
u32, tile_index, _: 9, 0;
|
||||
x_flip, _ : 10;
|
||||
y_flip, _ : 11;
|
||||
palette_bank, _ : 15, 12;
|
||||
}
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
use super::arm7tdmi::{exception::Exception, Core};
|
||||
|
||||
use crate::bit::BitIndex;
|
||||
|
||||
#[derive(Debug, Primitive, Copy, Clone, PartialEq)]
|
||||
#[allow(non_camel_case_types)]
|
||||
pub enum Interrupt {
|
||||
|
@ -17,4 +21,34 @@ pub enum Interrupt {
|
|||
GamePak = 13,
|
||||
}
|
||||
|
||||
pub struct InterruptController;
|
||||
#[derive(Debug)]
|
||||
pub struct InterruptController {
|
||||
pub interrupt_master_enable: bool,
|
||||
pub interrupt_enable: u16,
|
||||
pub interrupt_flags: u16,
|
||||
}
|
||||
|
||||
impl InterruptController {
|
||||
pub fn new() -> InterruptController {
|
||||
InterruptController {
|
||||
interrupt_master_enable: false,
|
||||
interrupt_enable: 0,
|
||||
interrupt_flags: 0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn interrupts_disabled(&self, cpu: &Core) -> bool {
|
||||
cpu.cpsr.irq_disabled() | (self.interrupt_master_enable)
|
||||
}
|
||||
|
||||
pub fn request_irq(&mut self, cpu: &mut Core, irq: Interrupt) {
|
||||
if self.interrupts_disabled(cpu) {
|
||||
return;
|
||||
}
|
||||
let irq_bit_index = irq as usize;
|
||||
if self.interrupt_enable.bit(irq_bit_index) {
|
||||
self.interrupt_flags = 1 << irq_bit_index;
|
||||
cpu.exception(Exception::Irq);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
use std::io;
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
|
||||
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
|
||||
|
||||
use crate::core::arm7tdmi::{Addr, Bus, MemoryAccess};
|
||||
use super::arm7tdmi::{Addr, Bus, MemoryAccess};
|
||||
use super::gba::IoDevices;
|
||||
use super::keypad;
|
||||
|
||||
pub mod consts {
|
||||
use super::*;
|
||||
|
@ -123,74 +124,113 @@ use consts::*;
|
|||
|
||||
#[derive(Debug)]
|
||||
pub struct IoRegs {
|
||||
bytes: Box<[u8]>,
|
||||
}
|
||||
|
||||
impl Default for IoRegs {
|
||||
fn default() -> IoRegs {
|
||||
let mut ioregs = IoRegs {
|
||||
bytes: vec![0; 4096].into_boxed_slice(),
|
||||
};
|
||||
|
||||
// init default values
|
||||
ioregs.write_reg(REG_DISPCNT, 0x0080);
|
||||
|
||||
ioregs
|
||||
}
|
||||
pub io: Rc<RefCell<IoDevices>>,
|
||||
pub keyinput: u16,
|
||||
pub post_boot_flag: bool,
|
||||
}
|
||||
|
||||
impl IoRegs {
|
||||
pub fn read_reg(&self, addr: Addr) -> u16 {
|
||||
let result = self
|
||||
.get_bytes(addr - IO_BASE)
|
||||
.read_u16::<LittleEndian>()
|
||||
.unwrap();
|
||||
result
|
||||
}
|
||||
|
||||
pub fn write_reg(&mut self, addr: Addr, value: u16) {
|
||||
self.get_bytes_mut(addr - IO_BASE)
|
||||
.write_u16::<LittleEndian>(value)
|
||||
.unwrap();
|
||||
pub fn new(io: Rc<RefCell<IoDevices>>) -> IoRegs {
|
||||
IoRegs {
|
||||
io: io,
|
||||
post_boot_flag: false,
|
||||
keyinput: keypad::KEYINPUT_ALL_RELEASED,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Bus for IoRegs {
|
||||
fn read_32(&self, addr: Addr) -> u32 {
|
||||
self.get_bytes(addr).read_u32::<LittleEndian>().unwrap()
|
||||
(self.read_16(addr + 2) as u32) << 16 | (self.read_16(addr) as u32)
|
||||
}
|
||||
|
||||
fn read_16(&self, addr: Addr) -> u16 {
|
||||
self.read_reg(IO_BASE + addr)
|
||||
let io = self.io.borrow();
|
||||
match addr + IO_BASE {
|
||||
REG_DISPCNT => io.gpu.dispcnt.0,
|
||||
REG_DISPSTAT => io.gpu.dispstat.0,
|
||||
REG_VCOUNT => io.gpu.current_scanline as u16,
|
||||
REG_BG0CNT => io.gpu.bgcnt[0].0,
|
||||
REG_BG1CNT => io.gpu.bgcnt[1].0,
|
||||
REG_BG2CNT => io.gpu.bgcnt[2].0,
|
||||
REG_BG3CNT => io.gpu.bgcnt[3].0,
|
||||
REG_WIN0H => io.gpu.win0h,
|
||||
REG_WIN1H => io.gpu.win1h,
|
||||
REG_WIN0V => io.gpu.win0v,
|
||||
REG_WIN1V => io.gpu.win1v,
|
||||
REG_WININ => io.gpu.winin,
|
||||
REG_WINOUT => io.gpu.winout,
|
||||
REG_MOSAIC => io.gpu.mosaic,
|
||||
REG_BLDCNT => io.gpu.bldcnt,
|
||||
REG_BLDALPHA => io.gpu.bldalpha,
|
||||
REG_BLDY => io.gpu.bldy,
|
||||
|
||||
REG_IME => io.intc.interrupt_master_enable as u16,
|
||||
REG_IE => io.intc.interrupt_enable as u16,
|
||||
REG_IF => io.intc.interrupt_flags as u16,
|
||||
|
||||
REG_POSTFLG => self.post_boot_flag as u16,
|
||||
REG_HALTCNT => 0,
|
||||
REG_KEYINPUT => self.keyinput as u16,
|
||||
_ => {
|
||||
println!("tried to read register {:#x}", addr + IO_BASE);
|
||||
0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn read_8(&self, addr: Addr) -> u8 {
|
||||
self.read_reg(IO_BASE + addr) as u8
|
||||
self.read_16(addr) as u8
|
||||
}
|
||||
|
||||
fn write_32(&mut self, addr: Addr, value: u32) {
|
||||
self.get_bytes_mut(addr)
|
||||
.write_u32::<LittleEndian>(value)
|
||||
.unwrap()
|
||||
self.write_16(addr, (value & 0xffff) as u16);
|
||||
self.write_16(addr, (value >> 16) as u16);
|
||||
}
|
||||
|
||||
fn write_16(&mut self, addr: Addr, value: u16) {
|
||||
self.write_reg(IO_BASE + addr, value);
|
||||
let mut io = self.io.borrow_mut();
|
||||
match addr + IO_BASE {
|
||||
REG_DISPCNT => io.gpu.dispcnt.0 |= value,
|
||||
REG_DISPSTAT => io.gpu.dispstat.0 |= value,
|
||||
REG_BG0CNT => io.gpu.bgcnt[0].0 |= value,
|
||||
REG_BG1CNT => io.gpu.bgcnt[1].0 |= value,
|
||||
REG_BG2CNT => io.gpu.bgcnt[2].0 |= value,
|
||||
REG_BG3CNT => io.gpu.bgcnt[3].0 |= value,
|
||||
REG_BG0HOFS => io.gpu.bghofs[0] = value,
|
||||
REG_BG0VOFS => io.gpu.bgvofs[0] = value,
|
||||
REG_BG1HOFS => io.gpu.bghofs[1] = value,
|
||||
REG_BG1VOFS => io.gpu.bgvofs[1] = value,
|
||||
REG_BG2HOFS => io.gpu.bghofs[2] = value,
|
||||
REG_BG2VOFS => io.gpu.bgvofs[2] = value,
|
||||
REG_BG3HOFS => io.gpu.bghofs[3] = value,
|
||||
REG_BG3VOFS => io.gpu.bgvofs[3] = value,
|
||||
REG_WIN0H => io.gpu.win0h = value,
|
||||
REG_WIN1H => io.gpu.win1h = value,
|
||||
REG_WIN0V => io.gpu.win0v = value,
|
||||
REG_WIN1V => io.gpu.win1v = value,
|
||||
REG_WININ => io.gpu.winin = value,
|
||||
REG_WINOUT => io.gpu.winout = value,
|
||||
REG_MOSAIC => io.gpu.mosaic = value,
|
||||
REG_BLDCNT => io.gpu.bldcnt = value,
|
||||
REG_BLDALPHA => io.gpu.bldalpha = value,
|
||||
REG_BLDY => io.gpu.bldy = value,
|
||||
|
||||
REG_IME => io.intc.interrupt_master_enable = value == 1,
|
||||
REG_IE => io.intc.interrupt_enable = value,
|
||||
REG_IF => io.intc.interrupt_flags &= !value,
|
||||
|
||||
REG_POSTFLG => self.post_boot_flag = value != 0,
|
||||
REG_HALTCNT => {}
|
||||
_ => {
|
||||
println!("tried to write register {:#x}", addr + IO_BASE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn write_8(&mut self, addr: Addr, value: u8) {
|
||||
let new_value = self.read_reg(IO_BASE + addr) & 0xff00 | (value as u16);
|
||||
self.write_reg(IO_BASE + addr, new_value);
|
||||
}
|
||||
|
||||
/// Return a slice of bytes
|
||||
fn get_bytes(&self, addr: Addr) -> &[u8] {
|
||||
&self.bytes[addr as usize..]
|
||||
}
|
||||
|
||||
/// Return a mutable slice of bytes
|
||||
fn get_bytes_mut(&mut self, addr: Addr) -> &mut [u8] {
|
||||
&mut self.bytes[addr as usize..]
|
||||
let t = self.read_16(addr);
|
||||
self.write_16(addr, (t & 0xff) | ((value as u16) << 8));
|
||||
}
|
||||
|
||||
/// returns the number of cycles needed for this memory access
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
use std::io;
|
||||
|
||||
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
|
||||
|
||||
use super::{cartridge::Cartridge, ioregs::IoRegs};
|
||||
|
@ -96,14 +94,6 @@ impl Bus for BoxedMemory {
|
|||
.unwrap()
|
||||
}
|
||||
|
||||
fn get_bytes(&self, addr: Addr) -> &[u8] {
|
||||
&self.mem[(addr & self.mask) as usize..]
|
||||
}
|
||||
|
||||
fn get_bytes_mut(&mut self, addr: Addr) -> &mut [u8] {
|
||||
&mut self.mem[(addr & self.mask) as usize..]
|
||||
}
|
||||
|
||||
fn get_cycles(&self, _addr: Addr, access: MemoryAccess) -> usize {
|
||||
match access.1 {
|
||||
MemoryAccessWidth::MemoryAccess8 => self.ws.access8,
|
||||
|
@ -135,14 +125,6 @@ impl Bus for DummyBus {
|
|||
|
||||
fn write_8(&mut self, _addr: Addr, _value: u8) {}
|
||||
|
||||
fn get_bytes(&self, _addr: Addr) -> &[u8] {
|
||||
&self.0
|
||||
}
|
||||
|
||||
fn get_bytes_mut(&mut self, _addr: Addr) -> &mut [u8] {
|
||||
&mut self.0
|
||||
}
|
||||
|
||||
fn get_cycles(&self, _addr: Addr, _access: MemoryAccess) -> usize {
|
||||
1
|
||||
}
|
||||
|
@ -163,7 +145,7 @@ pub struct SysBus {
|
|||
}
|
||||
|
||||
impl SysBus {
|
||||
pub fn new(bios_rom: Vec<u8>, gamepak: Cartridge) -> SysBus {
|
||||
pub fn new(bios_rom: Vec<u8>, gamepak: Cartridge, ioregs: IoRegs) -> SysBus {
|
||||
SysBus {
|
||||
bios: BoxedMemory::new(bios_rom.into_boxed_slice(), 0xff_ffff),
|
||||
onboard_work_ram: BoxedMemory::new_with_waitstate(
|
||||
|
@ -175,7 +157,7 @@ impl SysBus {
|
|||
vec![0; INTERNAL_RAM_SIZE].into_boxed_slice(),
|
||||
0x7fff,
|
||||
),
|
||||
ioregs: IoRegs::default(),
|
||||
ioregs: ioregs,
|
||||
palette_ram: BoxedMemory::new_with_waitstate(
|
||||
vec![0; PALETTE_RAM_SIZE].into_boxed_slice(),
|
||||
(PALETTE_RAM_SIZE as u32) - 1,
|
||||
|
@ -193,30 +175,30 @@ impl SysBus {
|
|||
}
|
||||
|
||||
fn map(&self, addr: Addr) -> &Bus {
|
||||
match addr as usize {
|
||||
0x0000_0000...0x0000_3fff => &self.bios,
|
||||
0x0200_0000...0x02ff_ffff => &self.onboard_work_ram,
|
||||
0x0300_0000...0x03ff_ffff => &self.internal_work_ram,
|
||||
0x0400_0000...0x0400_03fe => &self.ioregs,
|
||||
0x0500_0000...0x05ff_ffff => &self.palette_ram,
|
||||
0x0600_0000...0x06ff_ffff => &self.vram,
|
||||
0x0700_0000...0x0700_03ff => &self.oam,
|
||||
0x0800_0000...0x09ff_ffff => &self.gamepak,
|
||||
match (addr & 0xff000000) as usize {
|
||||
0x00000000 => &self.bios,
|
||||
0x02000000 => &self.onboard_work_ram,
|
||||
0x03000000 => &self.internal_work_ram,
|
||||
0x04000000 => &self.ioregs,
|
||||
0x05000000 => &self.palette_ram,
|
||||
0x06000000 => &self.vram,
|
||||
0x07000000 => &self.oam,
|
||||
0x08000000 => &self.gamepak,
|
||||
_ => &self.dummy,
|
||||
}
|
||||
}
|
||||
|
||||
/// TODO proc-macro for generating this function
|
||||
fn map_mut(&mut self, addr: Addr) -> &mut Bus {
|
||||
match addr as usize {
|
||||
0x0000_0000...0x0000_3fff => &mut self.bios,
|
||||
0x0200_0000...0x02ff_ffff => &mut self.onboard_work_ram,
|
||||
0x0300_0000...0x03ff_ffff => &mut self.internal_work_ram,
|
||||
0x0400_0000...0x0400_03fe => &mut self.ioregs,
|
||||
0x0500_0000...0x05ff_ffff => &mut self.palette_ram,
|
||||
0x0600_0000...0x06ff_ffff => &mut self.vram,
|
||||
0x0700_0000...0x0700_03ff => &mut self.oam,
|
||||
0x0800_0000...0x09ff_ffff => &mut self.gamepak,
|
||||
match (addr & 0xff000000) as usize {
|
||||
0x00000000 => &mut self.bios,
|
||||
0x02000000 => &mut self.onboard_work_ram,
|
||||
0x03000000 => &mut self.internal_work_ram,
|
||||
0x04000000 => &mut self.ioregs,
|
||||
0x05000000 => &mut self.palette_ram,
|
||||
0x06000000 => &mut self.vram,
|
||||
0x07000000 => &mut self.oam,
|
||||
0x08000000 => &mut self.gamepak,
|
||||
_ => &mut self.dummy,
|
||||
}
|
||||
}
|
||||
|
@ -247,14 +229,6 @@ impl Bus for SysBus {
|
|||
self.map_mut(addr).write_8(addr & 0xff_ffff, value)
|
||||
}
|
||||
|
||||
fn get_bytes(&self, addr: Addr) -> &[u8] {
|
||||
self.map(addr).get_bytes(addr & 0xff_ffff)
|
||||
}
|
||||
|
||||
fn get_bytes_mut(&mut self, addr: Addr) -> &mut [u8] {
|
||||
self.map_mut(addr).get_bytes_mut(addr & 0xff_ffff)
|
||||
}
|
||||
|
||||
fn get_cycles(&self, addr: Addr, access: MemoryAccess) -> usize {
|
||||
self.map(addr).get_cycles(addr & 0xff_ffff, access)
|
||||
}
|
||||
|
|
|
@ -2,8 +2,6 @@ use crate::core::arm7tdmi::arm::ArmInstruction;
|
|||
use crate::core::arm7tdmi::bus::Bus;
|
||||
use crate::core::arm7tdmi::thumb::ThumbInstruction;
|
||||
use crate::core::arm7tdmi::{Addr, CpuState};
|
||||
use crate::core::gpu::*;
|
||||
use crate::core::ioregs::consts::*;
|
||||
use crate::core::GBAError;
|
||||
use crate::disass::Disassembler;
|
||||
|
||||
|
@ -31,8 +29,8 @@ pub enum Command {
|
|||
Continue,
|
||||
Frame(usize),
|
||||
Render,
|
||||
HexDump(Addr, usize),
|
||||
Disass(DisassMode, Addr, usize),
|
||||
HexDump(Addr, u32),
|
||||
Disass(DisassMode, Addr, u32),
|
||||
AddBreakpoint(Addr),
|
||||
DelBreakpoint(Addr),
|
||||
PaletteView,
|
||||
|
@ -48,25 +46,7 @@ impl Command {
|
|||
use Command::*;
|
||||
match *self {
|
||||
Info => println!("{}", debugger.gba.cpu),
|
||||
DisplayInfo => {
|
||||
println!(
|
||||
"DISPCNT: {:#?}",
|
||||
DisplayControl::from(debugger.gba.sysbus.ioregs.read_reg(REG_DISPCNT))
|
||||
);
|
||||
println!(
|
||||
"DISPSTAT: {:#?}",
|
||||
DisplayStatus::from(debugger.gba.sysbus.ioregs.read_reg(REG_DISPSTAT))
|
||||
);
|
||||
println!(
|
||||
"VCOUNT: {:?}",
|
||||
debugger.gba.sysbus.ioregs.read_reg(REG_VCOUNT)
|
||||
);
|
||||
for bg in 0..4 {
|
||||
let bgcnt =
|
||||
BgControl::from(debugger.gba.sysbus.ioregs.read_reg(REG_BG0CNT + 2 * bg));
|
||||
println!("BG{}CNT: {:#?}", bg, bgcnt);
|
||||
}
|
||||
}
|
||||
DisplayInfo => println!("GPU: {:#?}", debugger.gba.io.borrow().gpu),
|
||||
Step(count) => {
|
||||
for _ in 0..count {
|
||||
if let Some(bp) = debugger.check_breakpoint() {
|
||||
|
@ -135,21 +115,21 @@ impl Command {
|
|||
}
|
||||
Render => create_render_view(&debugger.gba),
|
||||
HexDump(addr, nbytes) => {
|
||||
let bytes = debugger.gba.sysbus.get_bytes(addr);
|
||||
hexdump::hexdump(&bytes[0..nbytes]);
|
||||
let bytes = debugger.gba.sysbus.get_bytes(addr..addr + nbytes);
|
||||
hexdump::hexdump(&bytes);
|
||||
}
|
||||
Disass(mode, addr, n) => {
|
||||
let bytes = debugger.gba.sysbus.get_bytes(addr);
|
||||
let bytes = debugger.gba.sysbus.get_bytes(addr..addr + n);
|
||||
match mode {
|
||||
DisassMode::ModeArm => {
|
||||
let disass = Disassembler::<ArmInstruction>::new(addr, bytes);
|
||||
for (_, line) in disass.take(n) {
|
||||
let disass = Disassembler::<ArmInstruction>::new(addr, &bytes);
|
||||
for (_, line) in disass.take(n as usize) {
|
||||
println!("{}", line)
|
||||
}
|
||||
}
|
||||
DisassMode::ModeThumb => {
|
||||
let disass = Disassembler::<ThumbInstruction>::new(addr, bytes);
|
||||
for (_, line) in disass.take(n) {
|
||||
let disass = Disassembler::<ThumbInstruction>::new(addr, &bytes);
|
||||
for (_, line) in disass.take(n as usize) {
|
||||
println!("{}", line)
|
||||
}
|
||||
}
|
||||
|
@ -176,7 +156,7 @@ impl Command {
|
|||
println!("[{}] 0x{:08x}", i, b)
|
||||
}
|
||||
}
|
||||
PaletteView => create_palette_view(debugger.gba.sysbus.get_bytes(0x0500_0000)),
|
||||
PaletteView => create_palette_view(&debugger.gba.sysbus.palette_ram.mem),
|
||||
TileView(bg) => create_tile_view(bg, &debugger.gba),
|
||||
Reset => {
|
||||
println!("resetting cpu...");
|
||||
|
@ -188,13 +168,13 @@ impl Command {
|
|||
}
|
||||
|
||||
impl Debugger {
|
||||
fn get_disassembler_args(&self, args: Vec<Value>) -> DebuggerResult<(Addr, usize)> {
|
||||
fn get_disassembler_args(&self, args: Vec<Value>) -> DebuggerResult<(Addr, u32)> {
|
||||
match args.len() {
|
||||
2 => {
|
||||
let addr = self.val_address(&args[0])?;
|
||||
let n = self.val_number(&args[1])?;
|
||||
|
||||
Ok((addr, n as usize))
|
||||
Ok((addr, n))
|
||||
}
|
||||
1 => {
|
||||
let addr = self.val_address(&args[0])?;
|
||||
|
@ -258,7 +238,7 @@ impl Debugger {
|
|||
let addr = self.val_address(&args[0])?;
|
||||
let n = self.val_number(&args[1])?;
|
||||
|
||||
(addr, n as usize)
|
||||
(addr, n)
|
||||
}
|
||||
1 => {
|
||||
let addr = self.val_address(&args[0])?;
|
||||
|
|
|
@ -37,13 +37,16 @@ pub fn create_render_view(gba: &GameBoyAdvance) {
|
|||
canvas.set_draw_color(Color::RGB(0xfa, 0xfa, 0xfa));
|
||||
canvas.clear();
|
||||
|
||||
let io = gba.io.borrow();
|
||||
for y in 0..Gpu::DISPLAY_HEIGHT {
|
||||
for x in 0..Gpu::DISPLAY_WIDTH {
|
||||
let index = (x as usize) + (y as usize) * (512 as usize);
|
||||
let color = gba.gpu.pixeldata[index];
|
||||
let color = io.gpu.pixeldata[index];
|
||||
let rgb24: Color = color.into();
|
||||
canvas.set_draw_color(rgb24);
|
||||
canvas.draw_point(Point::from((x as i32, y as i32)));
|
||||
canvas
|
||||
.draw_point(Point::from((x as i32, y as i32)))
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -5,12 +5,8 @@ use sdl2::pixels::Color;
|
|||
use sdl2::rect::{Point, Rect};
|
||||
use sdl2::render::Canvas;
|
||||
|
||||
use crate::core::arm7tdmi::bus::Bus;
|
||||
use crate::core::gba::GameBoyAdvance;
|
||||
use crate::core::gpu::*;
|
||||
use crate::core::ioregs::consts::*;
|
||||
use crate::core::palette::*;
|
||||
use crate::core::sysbus::SysBus;
|
||||
|
||||
impl Into<Color> for Rgb15 {
|
||||
fn into(self) -> Color {
|
||||
|
@ -26,12 +22,13 @@ fn draw_tile(
|
|||
p: Point,
|
||||
canvas: &mut Canvas<sdl2::video::Window>,
|
||||
) {
|
||||
let io = gba.io.borrow();
|
||||
for y in 0..8 {
|
||||
for x in 0..8 {
|
||||
let index = gba
|
||||
let index = io
|
||||
.gpu
|
||||
.read_pixel_index(&gba.sysbus, tile_addr, x, y, pixel_format);
|
||||
let color = gba.gpu.get_palette_color(&gba.sysbus, index as u32, 0);
|
||||
let color = io.gpu.get_palette_color(&gba.sysbus, index as u32, 0);
|
||||
let (r, g, b) = color.get_rgb24();
|
||||
|
||||
canvas.set_draw_color(Color::RGB(r, g, b));
|
||||
|
@ -55,9 +52,8 @@ pub fn create_tile_view(bg: u32, gba: &GameBoyAdvance) {
|
|||
|
||||
let mut canvas = window.into_canvas().build().unwrap();
|
||||
|
||||
let bgcnt = BgControl::from(gba.sysbus.ioregs.read_reg(REG_BG0CNT + 2 * bg));
|
||||
let bgcnt = gba.io.borrow().gpu.bgcnt[bg as usize].clone();
|
||||
|
||||
let palette = Palette::from(gba.sysbus.get_bytes(0x0500_0000));
|
||||
let (tile_size, pixel_format) = bgcnt.tile_format();
|
||||
let tileset_addr = bgcnt.char_block();
|
||||
let tilemap_addr = bgcnt.screen_block();
|
||||
|
|
|
@ -4,6 +4,8 @@ extern crate num;
|
|||
extern crate num_traits;
|
||||
|
||||
extern crate bit;
|
||||
#[macro_use]
|
||||
extern crate bitfield;
|
||||
|
||||
extern crate byteorder;
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
use std::time;
|
||||
|
||||
use crate::bit::BitIndex;
|
||||
use std::thread;
|
||||
|
||||
extern crate minifb;
|
||||
|
||||
|
|
Reference in a new issue