From c7dd713605825dbc2fa97889adc1580beb45745b Mon Sep 17 00:00:00 2001 From: Michel Heily Date: Sat, 3 Aug 2019 00:18:59 +0300 Subject: [PATCH] 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 --- Cargo.lock | 73 ++++--- Cargo.toml | 1 + src/backend.rs | 9 +- src/bin/main.rs | 4 +- src/core/arm7tdmi/alu.rs | 5 +- src/core/arm7tdmi/arm/display.rs | 1 - src/core/arm7tdmi/arm/exec.rs | 13 +- src/core/arm7tdmi/bus.rs | 14 +- src/core/arm7tdmi/cpu.rs | 6 - src/core/arm7tdmi/thumb/display.rs | 2 - src/core/arm7tdmi/thumb/exec.rs | 1 - src/core/cartridge.rs | 8 - src/core/dma.rs | 128 +++++------ src/core/gba.rs | 114 ++++------ src/core/gpu.rs | 334 ++++++++++++----------------- src/core/interrupt.rs | 36 +++- src/core/ioregs.rs | 138 +++++++----- src/core/sysbus.rs | 66 ++---- src/debugger/command.rs | 48 ++--- src/debugger/render_view.rs | 7 +- src/debugger/tile_view.rs | 12 +- src/lib.rs | 2 + src/minifb_backend.rs | 1 - 23 files changed, 471 insertions(+), 552 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d4a7ba8..3f59d6f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -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" diff --git a/Cargo.toml b/Cargo.toml index 1d16ca4..9c1afd0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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 diff --git a/src/backend.rs b/src/backend.rs index 4fbed7e..14c9b55 100644 --- a/src/backend.rs +++ b/src/backend.rs @@ -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) {} + fn render(&mut self, buffer: Vec); 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) {} } diff --git a/src/bin/main.rs b/src/bin/main.rs index 460c56a..6599576 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -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!(), }; diff --git a/src/core/arm7tdmi/alu.rs b/src/core/arm7tdmi/alu.rs index 6c0255d..1723ad4 100644 --- a/src/core/arm7tdmi/alu.rs +++ b/src/core/arm7tdmi/alu.rs @@ -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 { diff --git a/src/core/arm7tdmi/arm/display.rs b/src/core/arm7tdmi/arm/display.rs index 8fe254b..467c262 100644 --- a/src/core/arm7tdmi/arm/display.rs +++ b/src/core/arm7tdmi/arm/display.rs @@ -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), } } } diff --git a/src/core/arm7tdmi/arm/exec.rs b/src/core/arm7tdmi/arm/exec.rs index c9b81a8..540cade 100644 --- a/src/core/arm7tdmi/arm/exec.rs +++ b/src/core/arm7tdmi/arm/exec.rs @@ -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()); diff --git a/src/core/arm7tdmi/bus.rs b/src/core/arm7tdmi/bus.rs index fd8c05d..71d82e5 100644 --- a/src/core/arm7tdmi/bus.rs +++ b/src/core/arm7tdmi/bus.rs @@ -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) -> Vec { + let mut bytes = Vec::new(); + for b in range { + bytes.push(self.read_8(b)); + } + bytes + } } diff --git a/src/core/arm7tdmi/cpu.rs b/src/core/arm7tdmi/cpu.rs index 6faf1eb..4d3cfdb 100644 --- a/src/core/arm7tdmi/cpu.rs +++ b/src/core/arm7tdmi/cpu.rs @@ -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 } diff --git a/src/core/arm7tdmi/thumb/display.rs b/src/core/arm7tdmi/thumb/display.rs index ce4efe4..1a20011 100644 --- a/src/core/arm7tdmi/thumb/display.rs +++ b/src/core/arm7tdmi/thumb/display.rs @@ -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), } } } diff --git a/src/core/arm7tdmi/thumb/exec.rs b/src/core/arm7tdmi/thumb/exec.rs index 8502be4..896df06 100644 --- a/src/core/arm7tdmi/thumb/exec.rs +++ b/src/core/arm7tdmi/thumb/exec.rs @@ -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), } } } diff --git a/src/core/cartridge.rs b/src/core/cartridge.rs index b3a5fd9..6934f5d 100644 --- a/src/core/cartridge.rs +++ b/src/core/cartridge.rs @@ -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, diff --git a/src/core/dma.rs b/src/core/dma.rs index a6b7eb7..4bf1094 100644 --- a/src/core/dma.rs +++ b/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) { - // TODO - (0, None) - } -} +// impl EmuIoDev for DmaChannel { +// fn step(&mut self, cycles: usize, sysbus: &mut SysBus) -> (usize, Option) { +// // TODO +// (0, None) +// } +// } diff --git a/src/core/gba.rs b/src/core/gba.rs index 02cd3b9..fea2cc8 100644 --- a/src/core/gba.rs +++ b/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, 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>, } impl GameBoyAdvance { @@ -35,90 +43,60 @@ impl GameBoyAdvance { gamepak: Cartridge, backend: Box, ) -> 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 { 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) diff --git a/src/core/gpu.rs b/src/core/gpu.rs index 60f6995..633921a 100644 --- a/src/core/gpu.rs +++ b/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 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 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 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 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 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 { - 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 { - 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) { + fn step(&mut self, cycles: usize, sb: &mut SysBus) -> (usize, Option) { 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 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; } diff --git a/src/core/interrupt.rs b/src/core/interrupt.rs index 18a024f..70401f1 100644 --- a/src/core/interrupt.rs +++ b/src/core/interrupt.rs @@ -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); + } + } +} diff --git a/src/core/ioregs.rs b/src/core/ioregs.rs index 3a4faa0..b9793e5 100644 --- a/src/core/ioregs.rs +++ b/src/core/ioregs.rs @@ -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>, + 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::() - .unwrap(); - result - } - - pub fn write_reg(&mut self, addr: Addr, value: u16) { - self.get_bytes_mut(addr - IO_BASE) - .write_u16::(value) - .unwrap(); + pub fn new(io: Rc>) -> 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::().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::(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 diff --git a/src/core/sysbus.rs b/src/core/sysbus.rs index cc7cd4a..57d3e53 100644 --- a/src/core/sysbus.rs +++ b/src/core/sysbus.rs @@ -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, gamepak: Cartridge) -> SysBus { + pub fn new(bios_rom: Vec, 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) } diff --git a/src/debugger/command.rs b/src/debugger/command.rs index 49c4e98..3322900 100644 --- a/src/debugger/command.rs +++ b/src/debugger/command.rs @@ -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::::new(addr, bytes); - for (_, line) in disass.take(n) { + let disass = Disassembler::::new(addr, &bytes); + for (_, line) in disass.take(n as usize) { println!("{}", line) } } DisassMode::ModeThumb => { - let disass = Disassembler::::new(addr, bytes); - for (_, line) in disass.take(n) { + let disass = Disassembler::::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) -> DebuggerResult<(Addr, usize)> { + fn get_disassembler_args(&self, args: Vec) -> 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])?; diff --git a/src/debugger/render_view.rs b/src/debugger/render_view.rs index 2bc0e5e..b3ea2dd 100644 --- a/src/debugger/render_view.rs +++ b/src/debugger/render_view.rs @@ -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(); } } diff --git a/src/debugger/tile_view.rs b/src/debugger/tile_view.rs index 221e879..2a88f5b 100644 --- a/src/debugger/tile_view.rs +++ b/src/debugger/tile_view.rs @@ -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 for Rgb15 { fn into(self) -> Color { @@ -26,12 +22,13 @@ fn draw_tile( p: Point, canvas: &mut Canvas, ) { + 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(); diff --git a/src/lib.rs b/src/lib.rs index 956a9d3..1c28254 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,6 +4,8 @@ extern crate num; extern crate num_traits; extern crate bit; +#[macro_use] +extern crate bitfield; extern crate byteorder; diff --git a/src/minifb_backend.rs b/src/minifb_backend.rs index 30bb2f4..7fd0292 100644 --- a/src/minifb_backend.rs +++ b/src/minifb_backend.rs @@ -1,7 +1,6 @@ use std::time; use crate::bit::BitIndex; -use std::thread; extern crate minifb;