diff --git a/.editorconfig b/.editorconfig index 27259f5155..3d0b97c090 100644 --- a/.editorconfig +++ b/.editorconfig @@ -2,3 +2,12 @@ root = true [*] indent_style = tab + +[*.cs] +csharp_new_line_before_open_brace = all +csharp_new_line_before_else = true +csharp_new_line_before_catch = true +csharp_new_line_before_finally = true +csharp_indent_switch_labels = true +csharp_indent_case_contents = true +csharp_indent_labels = one_less_than_current diff --git a/Assets/gamedb/gamedb_goodnes.txt b/Assets/gamedb/gamedb_goodnes.txt index 6c1262745c..f89ab9dae5 100644 --- a/Assets/gamedb/gamedb_goodnes.txt +++ b/Assets/gamedb/gamedb_goodnes.txt @@ -179,7 +179,7 @@ acc01149108010328c2839783c09b030650696a8 G 2-in-1 - Cosmo Cop + Cyber Monster (S 7c4d0353d9f3ff2f064a47b11497fb159f41b1f0 U 2-in-1 - Donkey Kong Country + Jungle Book (Unl) NES 33930c8fd186490d99ee2fe387b987ac0831c123 G 2-in-1 - Donkey Kong Country 4 + Jungle Book 2 (Unl) [!] NES 25943e4d0130c62aed75d92fafab75f8470c0e75 C 2-in-1 - Donkey Kong Country 4 + Jungle Book 2 (Unl) [t1] NES -47fcca3baebba912638d0eda77fb1676e5f0bc8e G 2-in-1 - Family Kid & Aladdin 4 (Ch) [!] NES +47fcca3baebba912638d0eda77fb1676e5f0bc8e G 2-in-1 - Family Kid & Aladdin 4 (Ch) [!] NES fdc4b64f9d981bf024c93c0bf39c332e2189eb2e G 2-in-1 - Mortal Kombat 3 Extra 60 People + Super Shinobi (King005) (Ch) [!] NES ec5e8712f994f929218cea18dc9d7dff7eb55495 G 2-in-1 - Mortal Kombat V Turbo 30 + Super Aladdin (Unl) [p1][!] NES 754512f9474fba9a3bf50cf315ff5b33d106b29c U 2-in-1 - Mortal Kombat VI + Mortal Kombat VII (NT-639) (Ch) NES @@ -521,7 +521,7 @@ ebd9d408ae00cc23b460a60a77c39336008c5671 H Abarenradin (Abarenbou Tengu Hack) NE eafc03f2f232660ed3e9eccf27c2f2527c8fe50b U ABM Study Card v5.0 (Ch) NES 0f75aec9810879bdc65269bbb1596542bd23ddf5 H Abnormal Contra (Hack) NES 64a897591d15f88ffd05773baf690dfa60f0d0d2 U About 8 Eyes (R) (PD) NES -f8287728e18eefd9b190597555f1f370b183a388 U About Advanced Dungeons & Dragons - Heroes of the Lance (R) (PD) NES +f8287728e18eefd9b190597555f1f370b183a388 U About Advanced Dungeons & Dragons - Heroes of the Lance (R) (PD) NES 9f194dc9272c92ffa84f2ac2eee4dd0548f56c54 U About Adventures in the Magic Kingdom (R) (PD) NES c9671a576386702a8dc2242bd2b8f20e53025ffd U About Adventures of Bayou Billy, The (R) (PD) NES 2835208676b1e9ac56a06389762b58cd4caf186b U About Armadillo (R) (PD) NES @@ -563,7 +563,7 @@ a7db1747bc516ed061c4d5c70afcaa474ddb5cb0 U Action53 Games 0.03 by Damian Yerrick e2e0219e2da3727d01306e46d358f69ef83c92e1 U Action53 Games MGC2012_2MBIT by Damian Yerrick (PD) NES d94968e5a043ff6a75d22a4351f86963c444b56f U Action53 Games MGC2012_4MBIT by Damian Yerrick (PD) NES 906b9c03ebb1fdb7ccfe263efcbb97ac19608757 H Actual Haou no Tairiku (Haou no Tairiku Hack) NES -45bb116d48c9726104def6268a49384e628054fe U Add & Sub (Unl) NES +45bb116d48c9726104def6268a49384e628054fe U Add & Sub (Unl) NES 22ad5c56344105eee089b6fa8d00657180ed0e00 U Add Em Up (Ch) (Wxn) NES 08c039c6114ee51b987b27d301b273c3c20114cc G Addams Family, The (E) (M3) [!] NES c831410a86a9b759a1e5ec53e8e1ee6789c79569 G Addams Family, The (U) [!] NES @@ -587,39 +587,39 @@ ec1811b0248129413f5be023c0b0d81a87f6e0d2 T Addams Family, The - Pugsley's Scaven cd6914dd1a78ba33570b4e578f4347df2f4e31b6 C Addams Family, The - Pugsley's Scavenger Hunt (U) [t1] NES cf504f5bc99886f933161057a20a9539b6f86ed6 B Adoventoro Tcheco v1.0 (Kero Kero Keroppi no Daibouken 2 Hack) [o1] NES 93985ed946c8f21bb18f8b88c4830eaf8b62d551 H Adoventoro Tcheco v1.0 (Kero Kero Keroppi no Daibouken 2 Hack) NES -273f99684dbdfcf27cfca58136132898217bfbc5 G Advanced Dungeons & Dragons - Dragon Strike (U) [!] NES -7a888c56b64ffd5a1b2653fa6b6d9c207fb6006f B Advanced Dungeons & Dragons - Dragon Strike (U) [b1] NES -d8737a92ad99191fa6653dc2094be81e6c9a1b9e B Advanced Dungeons & Dragons - Dragon Strike (U) [o1] NES -cca11ec6eb0721d6d2e7decbca51b66d5d8548c8 B Advanced Dungeons & Dragons - Dragon Strike (U) [o2] NES -00ae1a7b6cdf1c9b624b29488f54485103b8dcf1 C Advanced Dungeons & Dragons - Dragon Strike (U) [t1] NES -fba99cd8cfb0d44eaaee300dcd194520b41a92b2 G Advanced Dungeons & Dragons - Dragons of Flame (J) [!] NES -f788bbc014cd740449e1a0299feae7234d69a5cf B Advanced Dungeons & Dragons - Dragons of Flame (J) [b1] NES -071c57824564e1081f721ced5db1981c6d3ca034 B Advanced Dungeons & Dragons - Dragons of Flame (J) [o1] NES -25f20b279a150136b337b10f618a251a34c90b73 T Advanced Dungeons & Dragons - Dragons of Flame (J) [T+Eng1.03_DvD Translations] NES -e40073be785c7cce9c256e4be575b425e8719340 G Advanced Dungeons & Dragons - Heroes of the Lance (J) [!] NES -963bea44db79635410a56faa0eefcec79509ca93 U Advanced Dungeons & Dragons - Heroes of the Lance (U) (Prototype) NES -d9328b02916d365c97ed21074333257968e55f91 G Advanced Dungeons & Dragons - Heroes of the Lance (U) [!] NES -b091cd121984c85dd850979948401f6c10613e5a B Advanced Dungeons & Dragons - Heroes of the Lance (U) [b1] NES -e5564fb5a4b54dbd103803e2e15acd6d390b1cdf B Advanced Dungeons & Dragons - Heroes of the Lance (U) [b2] NES -cc4a023e907b5fa3f415ebb284d64f7b95f92114 B Advanced Dungeons & Dragons - Heroes of the Lance (U) [b3] NES -5207100c4d9eb4dd9cd2e2f8b5814fa4ed3aca6e B Advanced Dungeons & Dragons - Heroes of the Lance (U) [o1] NES -9c2a89479470349deddb38cdbda242b26b6589fd B Advanced Dungeons & Dragons - Heroes of the Lance (U) [o2] NES -2611badd4923ab1ef83db2e98b6c944416dc1367 T Advanced Dungeons & Dragons - Heroes of the Lance (U) [T+Rus0.30_Chief-Net] NES -5bc6b4d5e2b27983e678376a95b041ecb3abe819 G Advanced Dungeons & Dragons - Hillsfar (J) [!] NES -5f86c4b515c1cdaf18dd22f60a2d59116e9b2f05 B Advanced Dungeons & Dragons - Hillsfar (J) [b1] NES -988c9199cafb56b54691af8bedaf161fbf9353d1 B Advanced Dungeons & Dragons - Hillsfar (J) [b2] NES -94af82688883d02b83733b36e300d1e742940e1a B Advanced Dungeons & Dragons - Hillsfar (J) [o1] NES -806eb65696593368bef9b62e63b1d8624c637030 G Advanced Dungeons & Dragons - Hillsfar (U) [!] NES -4aedc8efec6f8df4bfbab548a9523778b6fc9594 B Advanced Dungeons & Dragons - Hillsfar (U) [o1] NES -22261fef73fb2161c513632ff614af0ca17d8105 G Advanced Dungeons & Dragons - Pool of Radiance (J) [!] NES -7eca79e1a9684dbbf30dd282c3b44f0fd25deae4 B Advanced Dungeons & Dragons - Pool of Radiance (J) [b1] NES -8612381815f8d64128310ee201bb1b8560c98ab9 B Advanced Dungeons & Dragons - Pool of Radiance (J) [b1][o1] NES -28eaac4e09ed87fa70a10cca7f70a112502f5c8f B Advanced Dungeons & Dragons - Pool of Radiance (J) [o1] NES -a056d59aae542b15ce5361ab49954e746863029b B Advanced Dungeons & Dragons - Pool of Radiance (J) [o2] NES -81eefb9fa6552b95bb086552a043097d6ecdd051 G Advanced Dungeons & Dragons - Pool of Radiance (U) [!] NES -7ddd3a1811b62e94a59d1f5c17045dfd786640a7 B Advanced Dungeons & Dragons - Pool of Radiance (U) [b1] NES -995527d6333875de6ab0d99b00a77b3b6901db8c B Advanced Dungeons & Dragons - Pool of Radiance (U) [b2] NES -b9aab0a607081b9409da575ce15aa5e1517e52d9 B Advanced Dungeons & Dragons - Pool of Radiance (U) [o1] NES +273f99684dbdfcf27cfca58136132898217bfbc5 G Advanced Dungeons & Dragons - Dragon Strike (U) [!] NES +7a888c56b64ffd5a1b2653fa6b6d9c207fb6006f B Advanced Dungeons & Dragons - Dragon Strike (U) [b1] NES +d8737a92ad99191fa6653dc2094be81e6c9a1b9e B Advanced Dungeons & Dragons - Dragon Strike (U) [o1] NES +cca11ec6eb0721d6d2e7decbca51b66d5d8548c8 B Advanced Dungeons & Dragons - Dragon Strike (U) [o2] NES +00ae1a7b6cdf1c9b624b29488f54485103b8dcf1 C Advanced Dungeons & Dragons - Dragon Strike (U) [t1] NES +fba99cd8cfb0d44eaaee300dcd194520b41a92b2 G Advanced Dungeons & Dragons - Dragons of Flame (J) [!] NES +f788bbc014cd740449e1a0299feae7234d69a5cf B Advanced Dungeons & Dragons - Dragons of Flame (J) [b1] NES +071c57824564e1081f721ced5db1981c6d3ca034 B Advanced Dungeons & Dragons - Dragons of Flame (J) [o1] NES +25f20b279a150136b337b10f618a251a34c90b73 T Advanced Dungeons & Dragons - Dragons of Flame (J) [T+Eng1.03_DvD Translations] NES +e40073be785c7cce9c256e4be575b425e8719340 G Advanced Dungeons & Dragons - Heroes of the Lance (J) [!] NES +963bea44db79635410a56faa0eefcec79509ca93 U Advanced Dungeons & Dragons - Heroes of the Lance (U) (Prototype) NES +d9328b02916d365c97ed21074333257968e55f91 G Advanced Dungeons & Dragons - Heroes of the Lance (U) [!] NES +b091cd121984c85dd850979948401f6c10613e5a B Advanced Dungeons & Dragons - Heroes of the Lance (U) [b1] NES +e5564fb5a4b54dbd103803e2e15acd6d390b1cdf B Advanced Dungeons & Dragons - Heroes of the Lance (U) [b2] NES +cc4a023e907b5fa3f415ebb284d64f7b95f92114 B Advanced Dungeons & Dragons - Heroes of the Lance (U) [b3] NES +5207100c4d9eb4dd9cd2e2f8b5814fa4ed3aca6e B Advanced Dungeons & Dragons - Heroes of the Lance (U) [o1] NES +9c2a89479470349deddb38cdbda242b26b6589fd B Advanced Dungeons & Dragons - Heroes of the Lance (U) [o2] NES +2611badd4923ab1ef83db2e98b6c944416dc1367 T Advanced Dungeons & Dragons - Heroes of the Lance (U) [T+Rus0.30_Chief-Net] NES +5bc6b4d5e2b27983e678376a95b041ecb3abe819 G Advanced Dungeons & Dragons - Hillsfar (J) [!] NES +5f86c4b515c1cdaf18dd22f60a2d59116e9b2f05 B Advanced Dungeons & Dragons - Hillsfar (J) [b1] NES +988c9199cafb56b54691af8bedaf161fbf9353d1 B Advanced Dungeons & Dragons - Hillsfar (J) [b2] NES +94af82688883d02b83733b36e300d1e742940e1a B Advanced Dungeons & Dragons - Hillsfar (J) [o1] NES +806eb65696593368bef9b62e63b1d8624c637030 G Advanced Dungeons & Dragons - Hillsfar (U) [!] NES +4aedc8efec6f8df4bfbab548a9523778b6fc9594 B Advanced Dungeons & Dragons - Hillsfar (U) [o1] NES +22261fef73fb2161c513632ff614af0ca17d8105 G Advanced Dungeons & Dragons - Pool of Radiance (J) [!] NES +7eca79e1a9684dbbf30dd282c3b44f0fd25deae4 B Advanced Dungeons & Dragons - Pool of Radiance (J) [b1] NES +8612381815f8d64128310ee201bb1b8560c98ab9 B Advanced Dungeons & Dragons - Pool of Radiance (J) [b1][o1] NES +28eaac4e09ed87fa70a10cca7f70a112502f5c8f B Advanced Dungeons & Dragons - Pool of Radiance (J) [o1] NES +a056d59aae542b15ce5361ab49954e746863029b B Advanced Dungeons & Dragons - Pool of Radiance (J) [o2] NES +81eefb9fa6552b95bb086552a043097d6ecdd051 G Advanced Dungeons & Dragons - Pool of Radiance (U) [!] NES +7ddd3a1811b62e94a59d1f5c17045dfd786640a7 B Advanced Dungeons & Dragons - Pool of Radiance (U) [b1] NES +995527d6333875de6ab0d99b00a77b3b6901db8c B Advanced Dungeons & Dragons - Pool of Radiance (U) [b2] NES +b9aab0a607081b9409da575ce15aa5e1517e52d9 B Advanced Dungeons & Dragons - Pool of Radiance (U) [o1] NES 1e28999c356e61b1df86830e6a44a28064b5c817 G Adventure Island (E) [!] NES 22ee75b82f4a6412aa6bb940e109704975b95185 G Adventure Island (U) [!] NES 1fda3bdfb434a51ce1b0d8ecc1048bead586aa78 B Adventure Island (U) [b1] NES @@ -762,7 +762,7 @@ a13dd4b5b89d9409f17cddac89d6cd9565ce515f G Adventures of Gilligan's Island, The 3ab83784dae8e89b6008210e0b5cfbd70819afcf C Adventures of Gilligan's Island, The (U) [t1] NES 38b3d3a93b7d6f586eea866323bd3fb9e4eca3a8 H Adventures of Ice Mario (SMB1 Hack) [a1] NES 6f8e6102756ba3bc48ae2a859f6f9d0b29f790df H Adventures of Ice Mario (SMB1 Hack) NES -31c22dc41dc70de595ba39e4851a71072d6c5f2c U Adventures of Lex & Grim, The (PD) NES +31c22dc41dc70de595ba39e4851a71072d6c5f2c U Adventures of Lex & Grim, The (PD) NES c43118388202bf348bae335eb2311ab8a0562bcb U Adventures of Lolo (E) (VC) NES d37c8003bf052404248ffaca106f7d32c75c8076 G Adventures of Lolo (E) [!] NES ad9ef7f61d97ecfc837f5f1eeb952935867306d7 G Adventures of Lolo (J) [!] NES @@ -887,8 +887,8 @@ f532c6e8d7d0443005f236bcfa2e6da52c0ac538 G Ai Senshi Nicol (FDS Conversion) [p2] df393788cf372f5b2e173ae3ee2b488d5d8b9efb B Aigiina no Yogen - From The Legend of Balubalouk (J) [b1] NES e277bdd8af36aaef9637477498834b1ed2074ae8 B Aigiina no Yogen - From The Legend of Balubalouk (J) [b2] NES e58d3146df2f09b3f98e4a35d132e05aa3347843 B Aigiina no Yogen - From The Legend of Balubalouk (J) [p1] NES -a4f42cbcb63f4d827055cbe1ced904ae0ccac4f7 T Aigiina no Yogen - From The Legend of Balubalouk (J) [T+Eng0.30_KP Hacks&Trans] NES -6305751b6a7c3b24aa7f5f182dec3a4358bf3bcc T Aigiina no Yogen - From The Legend of Balubalouk (J) [T+Eng0.30_KP Hacks&Trans][t1] NES +a4f42cbcb63f4d827055cbe1ced904ae0ccac4f7 T Aigiina no Yogen - From The Legend of Balubalouk (J) [T+Eng0.30_KP Hacks&Trans] NES +6305751b6a7c3b24aa7f5f182dec3a4358bf3bcc T Aigiina no Yogen - From The Legend of Balubalouk (J) [T+Eng0.30_KP Hacks&Trans][t1] NES 4bf385b7915e35d7fef3cd311caf9fdc7cb38048 C Aigiina no Yogen - From The Legend of Balubalouk (J) [t1] NES 93e4145c080847cf0d1c95e69d0f78e957fa4101 H Air (SMB1 Hack) NES e6aa612a23d571cf1b2196d13f0a4ec420d15efb U AIR - NES Visual Novel System V20040617 by NES Hack Factory (PD) NES @@ -1558,14 +1558,14 @@ c1dd041495a2ea02ffbbc583344b87137df8e984 B Back to the Future (U) [b4] NES 48404a7e46e0070aa1920130858315926d31b97e B Back to the Future (U) [o1] NES 5f262291edbcb4b4a72ca057bf8b379853af4556 T Back to the Future (U) [T+Pol] NES 24cc7674f742deec05ed246824f1bd6511ffdad6 H Back to the Future 4 by RyanVG (Back to the Future Hack) NES -641de451615a4f7004039308628c043b5ade6c31 H Back to the Future 5 & 6 by RyanVG (Back to the Future II & III Hack) NES +641de451615a4f7004039308628c043b5ade6c31 H Back to the Future 5 & 6 by RyanVG (Back to the Future II & III Hack) NES 4c79761269d0b9aaff4f9f9dcb28d8a106fa92b6 G Back to the Future IV (Unl) [!] NES -42ac1fcea405552892bed982a90a99d1292e4cdb G Back to the Future Part II & III (U) [!] NES -8338134a546f6c068c2b9e1bfdec45cab78d9571 B Back to the Future Part II & III (U) [b1] NES -4476ea6bbd674b081d4b36574c2746afad97abd6 B Back to the Future Part II & III (U) [b2] NES -060e5dde73dc19d931d561b28251a7c501771182 B Back to the Future Part II & III (U) [b3] NES -22ee09afdc4cb6f9790b9f87b0f49bcb19c6dce7 B Back to the Future Part II & III (U) [o1] NES -081f5da36bb4aaa0ad0b3bfafbf71a2ff1062697 C Back to the Future Part II & III (U) [t1] NES +42ac1fcea405552892bed982a90a99d1292e4cdb G Back to the Future Part II & III (U) [!] NES +8338134a546f6c068c2b9e1bfdec45cab78d9571 B Back to the Future Part II & III (U) [b1] NES +4476ea6bbd674b081d4b36574c2746afad97abd6 B Back to the Future Part II & III (U) [b2] NES +060e5dde73dc19d931d561b28251a7c501771182 B Back to the Future Part II & III (U) [b3] NES +22ee09afdc4cb6f9790b9f87b0f49bcb19c6dce7 B Back to the Future Part II & III (U) [o1] NES +081f5da36bb4aaa0ad0b3bfafbf71a2ff1062697 C Back to the Future Part II & III (U) [t1] NES 798d3f6cc1bf9a2dfcbb586c92fbd3e63ae7c172 U Background Music by Tony Young (PD) NES 86d389f46bde561394a7e69ff960f747a5ef297b U Backstroke (Ch) (Wxn) NES 92584bffe7d2ee47a01b480826466f78ff59f7dc U Bad Apple 2 v2009-12-24 (PD) NES @@ -1988,9 +1988,9 @@ fc950662b264fea1ad9f240360fde542283f04e1 U Batman Title Screen Remake by Macbee 91643c910a8c26b65e32cd8e4e8426d78d33713c H Batman V1.1 by Macbee (Batman Hack) NES e517ce0acda2a46341290b96fec12b2be51924ee H Batman V1.2 by Macbee (Batman Hack) NES 1a9fe00ebc831950bced93c556d1116543456460 U Bator Demo (PD) NES -f6177c581ed0b1d4625ec478caec3aa5939dc229 G Batsu & Terii - Makyou no Tetsujin Race (J) [!] NES -6a7a694a7bbcf59df990eec4be2c1157f104d43c B Batsu & Terii - Makyou no Tetsujin Race (J) [o1] NES -b7256a34856009ac3cdfeeb8142dd3fcc9c17c2e G Batsu & Terii - Makyou no Tetsujin Race (R) [!] NES +f6177c581ed0b1d4625ec478caec3aa5939dc229 G Batsu & Terii - Makyou no Tetsujin Race (J) [!] NES +6a7a694a7bbcf59df990eec4be2c1157f104d43c B Batsu & Terii - Makyou no Tetsujin Race (J) [o1] NES +b7256a34856009ac3cdfeeb8142dd3fcc9c17c2e G Batsu & Terii - Makyou no Tetsujin Race (R) [!] NES e3b20fb71dc6b44c911627cd321968a36578ea66 U Battle Ball (1-0) by UDISI (PD) NES 5915f487be763881a1f06cfdce689b1e1a503dd2 U Battle Ball (1-1) by UDISI (PD) NES 19fbe1d547f0cf085c99a80bbd3073f4d1ed33a0 U Battle Ball (1-21) by UDISI (PD) NES @@ -2161,16 +2161,16 @@ bd753272dcf11cb9b4c5d1e8d45436754897c97d B Battleship (U) [b2] NES 086e81e018013de624c9d18fb24771e503d68c47 B Battleship (U) [b4] NES 94dca436e97e7b6bfcfd4e13da6f08c5c81f2e2c B Battletank 2000 (Joust Hack) [o1] NES 5f0c7a2228e747d174590dc54a090daa73c74761 H Battletank 2000 (Joust Hack) NES -a5ab91d6a0df0bce2349a6322c536f4705287a4f G Battletoads & Double Dragon - The Ultimate Team (E) [!] NES -61832d0f955cff169ff059bd557be4f522b15b7c G Battletoads & Double Dragon - The Ultimate Team (U) [!] NES -b87d42a12a0f94a08b8476b1b2a0f1a36e050e3c B Battletoads & Double Dragon - The Ultimate Team (U) [o1] NES -a2f86721e107a039157724de5f69d3c1625ca214 G Battletoads & Double Dragon - The Ultimate Team (U) [p1][!] NES -3af7d0f3d2c7a105f958b205ae71fee6fa31536d B Battletoads & Double Dragon - The Ultimate Team (U) [p2] NES -dfe30b43464bb61470b4306d9f24f6ef43c685c2 B Battletoads & Double Dragon - The Ultimate Team (U) [p3] NES -ecdfa52d66575bede303075206e73c4a0aeb619a C Battletoads & Double Dragon - The Ultimate Team (U) [t1] NES -01ba0fa9342c6f8e196eeb8dbf49a3407df37a34 C Battletoads & Double Dragon - The Ultimate Team (U) [t2] NES -4cea01a1ca8d219a696c4c8b0f04465da3aa872f C Battletoads & Double Dragon - The Ultimate Team (U) [t3] NES -1b7750a413fcd4d907da8654a9b78c7aa0ed423c H Battletoads & Double Dragon - The Ultimate Team by myaso (Hack) NES +a5ab91d6a0df0bce2349a6322c536f4705287a4f G Battletoads & Double Dragon - The Ultimate Team (E) [!] NES +61832d0f955cff169ff059bd557be4f522b15b7c G Battletoads & Double Dragon - The Ultimate Team (U) [!] NES +b87d42a12a0f94a08b8476b1b2a0f1a36e050e3c B Battletoads & Double Dragon - The Ultimate Team (U) [o1] NES +a2f86721e107a039157724de5f69d3c1625ca214 G Battletoads & Double Dragon - The Ultimate Team (U) [p1][!] NES +3af7d0f3d2c7a105f958b205ae71fee6fa31536d B Battletoads & Double Dragon - The Ultimate Team (U) [p2] NES +dfe30b43464bb61470b4306d9f24f6ef43c685c2 B Battletoads & Double Dragon - The Ultimate Team (U) [p3] NES +ecdfa52d66575bede303075206e73c4a0aeb619a C Battletoads & Double Dragon - The Ultimate Team (U) [t1] NES +01ba0fa9342c6f8e196eeb8dbf49a3407df37a34 C Battletoads & Double Dragon - The Ultimate Team (U) [t2] NES +4cea01a1ca8d219a696c4c8b0f04465da3aa872f C Battletoads & Double Dragon - The Ultimate Team (U) [t3] NES +1b7750a413fcd4d907da8654a9b78c7aa0ed423c H Battletoads & Double Dragon - The Ultimate Team by myaso (Hack) NES 37e99fa67463140b2875d1079ade1ea7f3f2821f G Battletoads (E) [!] NES cbe809d8091d4421548e63c7b5e0b7ae972b45cf G Battletoads (J) [!] NES a9fd5d06382c88293462161bd8d882eb859b98d0 C Battletoads (J) [t2] NES @@ -2195,7 +2195,7 @@ a5b0bf325118b719367f8d7816504e04877452e7 B Be-Bop-Highschool - Koukousei Gokurak f07f637a55fa92b6875adb08ab9864446141440c H Beast Machines (Ikari Hack) NES b44a2ba9f96d3810d10801e6e3a4f68f112fbb6a G Beat n Box (K) (Unl) [!] NES 8bd8815ac4c09077145f2640bc37a5ac0e2b41ef G Beauty and the Beast (E) [!] NES -062f1bca6345f1346f96bf776768cb4a5fec7f2b U Beavis & Butt-head Title Screen by Macbee 1.0 (PD) NES +062f1bca6345f1346f96bf776768cb4a5fec7f2b U Beavis & Butt-head Title Screen by Macbee 1.0 (PD) NES b47df8791af3e39ac486b5d09b313109e8aeebcf G Bee 52 (Camerica) [!] NES 4af2961903378200d6db3ebc2cb77a28af7e3c3c B Bee 52 (Camerica) [o1] NES 48a7de1e5288428c6efb51c2d036efcce7f13384 T Bee 52 (Camerica) [T+Rus_Magicteam] NES @@ -2255,16 +2255,16 @@ b77195b1c6bfc9be2e2b7c8e00a4f1e4eb717f52 B Bible Adventures (Wisdom Tree) (V1.3) 9459027fe75f19e2bf8f6c86ffd3410445a2f28e B Bible Buffet (Wisdom Tree) (V6.0) [b1] NES f28787091c0a1d219de7c1ac574b5f8ba94dfe04 B Bible Buffet (Wisdom Tree) (V6.0) [o1] NES 10e4ad1a87f4522960574d651f2a832596ce156f H Bicycle Race (F-1 Race Hack) NES -75c71cc6d187c855b3e982edcea8eccb729ee917 G Big Bird's Hide & Speak (U) [!] NES -12eb07f634424deb6a2336c2c3f0ce34722ebbca B Big Bird's Hide & Speak (U) [b1] NES -396b8bad5215abd2ce509edaf5cd4a65ed0c6548 B Big Bird's Hide & Speak (U) [b1][o1] NES -1fdbfdda17130146dc78c3914976de451726d0e1 B Big Bird's Hide & Speak (U) [b2] NES -5002d3ce6a5c809969e6eda26f58c872045e017c B Big Bird's Hide & Speak (U) [b3] NES -f529a06bd217c6e5678a6eb3e4bf6db5120a7d43 B Big Bird's Hide & Speak (U) [b4] NES -56564ef56008813863efeb82acc0f9008c9a7175 B Big Bird's Hide & Speak (U) [b6] NES -8d9dda7bfb0ee4192f8e1c6ddfed3167b565bb75 B Big Bird's Hide & Speak (U) [b7] NES -91201e10a1e91f10a06b98512275108ebd7d3f1d B Big Bird's Hide & Speak (U) [o1] NES -89d7f554a62ce24f3442b64cfea4cc7bd5ecb0d1 B Big Bird's Hide & Speak (U) [o2] NES +75c71cc6d187c855b3e982edcea8eccb729ee917 G Big Bird's Hide & Speak (U) [!] NES +12eb07f634424deb6a2336c2c3f0ce34722ebbca B Big Bird's Hide & Speak (U) [b1] NES +396b8bad5215abd2ce509edaf5cd4a65ed0c6548 B Big Bird's Hide & Speak (U) [b1][o1] NES +1fdbfdda17130146dc78c3914976de451726d0e1 B Big Bird's Hide & Speak (U) [b2] NES +5002d3ce6a5c809969e6eda26f58c872045e017c B Big Bird's Hide & Speak (U) [b3] NES +f529a06bd217c6e5678a6eb3e4bf6db5120a7d43 B Big Bird's Hide & Speak (U) [b4] NES +56564ef56008813863efeb82acc0f9008c9a7175 B Big Bird's Hide & Speak (U) [b6] NES +8d9dda7bfb0ee4192f8e1c6ddfed3167b565bb75 B Big Bird's Hide & Speak (U) [b7] NES +91201e10a1e91f10a06b98512275108ebd7d3f1d B Big Bird's Hide & Speak (U) [o1] NES +89d7f554a62ce24f3442b64cfea4cc7bd5ecb0d1 B Big Bird's Hide & Speak (U) [o2] NES 6208f86f22c8445d3936ad5fd715069083ab6ab8 H Big Kids Pro-Wrestling by RyanVG (Tag Team Pro-Wrestling Hack) NES 91cf3e24b02ae75b7be395e524d9545bee50ab81 G Big Nose Freaks Out (Camerica) (Aladdin) [!] NES 60550d03da8eba47778b2c6ea708ca96364d0148 B Big Nose Freaks Out (Camerica) (Aladdin) [o1] NES @@ -2312,10 +2312,10 @@ ed31a87395748473cc106d7fa454ba04a53f1dbd B Bikkuriman World - Gekitou Sei Senshi dab4f077c1220c1cee5c56d8c9fdaf797af78d15 B Bikkuriman World - Gekitou Sei Senshi (J) [o2] NES d07fc347b34340ec3bee5b5366d51a97d235f0f5 H Bikkuriman World - Gekitou Sei Senshi (J) [p1][hM02] NES 14de52da6383e9f6c72d812c728d8be95cc4d8ff T Bikkuriman World - Gekitou Sei Senshi (J) [T+Eng] NES -bb3a2c8fcc6801a3658b5cd4e5c10bbbe1a96cb1 G Bill & Ted's Excellent Video Game Adventure (U) [!] NES -e1abcfdf970177b00e8a3c8a37f433bbd66c6f58 B Bill & Ted's Excellent Video Game Adventure (U) [b1] NES -1fd46ea2cb68aa9a02eb7e42703df393af6c65ef B Bill & Ted's Excellent Video Game Adventure (U) [b2] NES -b6e33ffe9574e09443c80bd07f20aa7cbdce98c8 B Bill & Ted's Excellent Video Game Adventure (U) [o1] NES +bb3a2c8fcc6801a3658b5cd4e5c10bbbe1a96cb1 G Bill & Ted's Excellent Video Game Adventure (U) [!] NES +e1abcfdf970177b00e8a3c8a37f433bbd66c6f58 B Bill & Ted's Excellent Video Game Adventure (U) [b1] NES +1fd46ea2cb68aa9a02eb7e42703df393af6c65ef B Bill & Ted's Excellent Video Game Adventure (U) [b2] NES +b6e33ffe9574e09443c80bd07f20aa7cbdce98c8 B Bill & Ted's Excellent Video Game Adventure (U) [o1] NES a677abfc4fa5ddd76092e41ae02cf3fd7eb05f9b G Bill Elliott's NASCAR Challenge (U) [!] NES e81f0dd2d7982ca6caefe8bc9afb09235cc58a47 B Bill Elliott's NASCAR Challenge (U) [b1] NES 3320ccda897692e186aa559d4939dea6cab7aafd B Bill Elliott's NASCAR Challenge (U) [b2] NES @@ -2689,8 +2689,8 @@ ea8923de0101a2fa05aa86b193244e06746d5a9f C Booby Kids (J) [t1] NES d73bff0c21555d9d313b3adaf95e56dcba0fdf94 B Boogerman II (Rex-Soft) [o1] NES 1569ea8845e6bb128da9823fcb493d3aec0cc130 G Boogerman II (Rex-Soft) [U][!].unf NES b2d980ac5e1a19e11e8240fb627973c8642311b7 B Boogerman II (Rex-Soft) [U][o1].unf NES -f3908331337357ec80b4a24f49b73ebbb0f3048d T Boris & Boa Boa (Nuts & Milk Hack) [T+Rus_Cool-Spot] NES -a7346085c5d6b761d04b9b2744a2ede13603fe3e H Boris & Boa Boa (Nuts & Milk Hack) NES +f3908331337357ec80b4a24f49b73ebbb0f3048d T Boris & Boa Boa (Nuts & Milk Hack) [T+Rus_Cool-Spot] NES +a7346085c5d6b761d04b9b2744a2ede13603fe3e H Boris & Boa Boa (Nuts & Milk Hack) NES fbfd34bb9a3a36789b5dac2d7aed0bf85217c2fc H Boss Rush (Castlevania Hack) [a1] NES 1d8a29a5d9c203e7d735696ef2099a9e746226ab H Boss Rush (Castlevania Hack) NES 0096f2938f633e1708c5e310dd0d80e2ec628b67 U Boss Test (PD) NES @@ -2780,7 +2780,7 @@ b65d1ff7c15dc37808fdc6c92919c868b1694b65 B BreakThru (U) [b4] NES bb336fb04e0003ea495afdc19cb13aad1007a230 B BreakThru (U) [o5] NES 8e43fc66fb280ac4330320f2a979a0e48e34fa9a T BreakThru (U) [T+Rus1.2_Multisoft] NES 58114b87cd95478361eb22ce3b0f173ca81729fc G Brilliant Com Pack 2 (K) [!] NES -0538fdcac01639743e5fc053ef83089b6d7654cd G Bruce & Leo (Tom & Jerry) (Unl) [!] NES +0538fdcac01639743e5fc053ef83089b6d7654cd G Bruce & Leo (Tom & Jerry) (Unl) [!] NES c3637f75754e7c3c665f5d9583502663dccf1ea0 B Brush Roller (Unl) [b1] NES 1895e8d17b8721e49f802c0c247765f3dca1a1eb B Brush Roller (Unl) [o1] NES 314700b6c4e1006b4f48ba856fd290b07c54c6d2 U Brush Roller (Unl) NES @@ -3139,8 +3139,8 @@ dc441137c9c0cf5fde9cb7fd8d8ae795777ca372 H Captain Tsubasa Vol. II - Chin3 by Zi 54d55d350114fd3346020c3f11b57774c9b7ea00 H Captain Tsubasa Vol. II - China vs Japan (Hack) NES d9d049618757de596a2e3230726cf7c4a099c961 H Captain Tsubasa Vol. II - Chinese Team Going Forward in Rainstorm (Hack) NES cd12f75b44883312c1c92817a47ca97bb082e585 H Captain Tsubasa Vol. II - Chinese Team Running in the Rain (Hack) NES -45a1cded0f8ab9763fe99476e6c7d7192ad92f37 H Captain Tsubasa Vol. II - Circle & Cross (Hack) NES -b915156298b2e589b7fa1711a19fb61d19f9ff8b H Captain Tsubasa Vol. II - Club Plus & Fix Edition (Hack) NES +45a1cded0f8ab9763fe99476e6c7d7192ad92f37 H Captain Tsubasa Vol. II - Circle & Cross (Hack) NES +b915156298b2e589b7fa1711a19fb61d19f9ff8b H Captain Tsubasa Vol. II - Club Plus & Fix Edition (Hack) NES ca77e6d6d0f3762fb0e28ef8393a6dfb3a859720 B Captain Tsubasa Vol. II - Comback of Twins J Edition (Hack) [o1] NES a94d3768b57d1037b76cae5e559937cea1152f22 H Captain Tsubasa Vol. II - Comback of Twins J Edition (Hack) NES ad449f5d79a68b2b98b0ace2907dd58d36e13011 H Captain Tsubasa Vol. II - Comback of Twins K Edition (Hack) NES @@ -3257,7 +3257,7 @@ ed65670dcfadc367c4d141669654d27a29907aaa H Captain Tsubasa Vol. II - New Artists 497c6fe476abef31de7d1e692aa5fb9ad31ad7ec H Captain Tsubasa Vol. II - New Platinum Partner (Hack) NES 72b411a5e93105c1c02f16419513884b547c550b H Captain Tsubasa Vol. II - New Road of Emperor Plus (Hack) NES a02b202044bff2c06f9649e45adea5c10f88c764 H Captain Tsubasa Vol. II - New Road of Emperor Remake Run Wildly Edition (Hack) NES -4ae227e0d97577b4f1d0a4386a7f2833b70bbede H Captain Tsubasa Vol. II - Nippon no Ovari by sisqo & kral 89 (Hack) NES +4ae227e0d97577b4f1d0a4386a7f2833b70bbede H Captain Tsubasa Vol. II - Nippon no Ovari by sisqo & kral 89 (Hack) NES af9d5e442cac049bc6ee97bef21832c915f8fcbe H Captain Tsubasa Vol. II - OMG by Heroy (Hack) NES 1c7d72b8019bf8977f3694121c94de3a05707348 H Captain Tsubasa Vol. II - Onur Edition 2011 (Hack) NES c4947d4d58cffc8d80e6b3240e0f2e775d0e6a92 H Captain Tsubasa Vol. II - Orbit of Honor (Hack) NES @@ -3275,7 +3275,7 @@ ad0c06288f4ac3427524ee33f72c64e2026828ce H Captain Tsubasa Vol. II - Prince Nye 2025ce107819e051765845e15bdabbdcabb2450b H Captain Tsubasa Vol. II - Prince with Unlimited Allure (Hack) NES 6641d0f7166219e302b53a0391e78f2bdca0c942 H Captain Tsubasa Vol. II - Prologue of New Legend (Hack) NES 32f51d3c805b1594bca7a5128663fcbe377f9df9 H Captain Tsubasa Vol. II - Prologue of New Tanaru Legend (Hack) NES -1f229c31596e5dec91d410c72b616d519aea78d5 H Captain Tsubasa Vol. II - Raiju & Ocelot Edition (Hack) NES +1f229c31596e5dec91d410c72b616d519aea78d5 H Captain Tsubasa Vol. II - Raiju & Ocelot Edition (Hack) NES ce161826da7f3e46f3943bc05da23b5c866aaaae H Captain Tsubasa Vol. II - Raise of Western (Hack) NES adddaf33336b9721aa4dafb07eda260fd5229bdf H Captain Tsubasa Vol. II - Rampion Edition (Hack) NES a0759a83d16996fc6084eb95af2f0db1b2f345e9 H Captain Tsubasa Vol. II - Relin Edition v1.1 by mazong1123 (Hack) NES @@ -3313,7 +3313,7 @@ e8e48b44700c1efaf8c03e1752b03190febecc4f H Captain Tsubasa Vol. II - Sino-Korean e4d0b8f696fca5c834215e8f1c92ca7008687a46 H Captain Tsubasa Vol. II - Soccer Kiss (Hack) NES 9de5ffb7096c436ec5914d1d6dbbff508487638b H Captain Tsubasa Vol. II - Soccer Master in Argentina (Hack) NES 15a5fc93c408ca75e9c7af3ec20355b101566941 H Captain Tsubasa Vol. II - Sonunda Basardim Ilk Hackim (Hack) NES -dacfa7746cd9772000bf7a7797727bf69003b447 H Captain Tsubasa Vol. II - Speed of Ball Controlable & All Footballer (Hack) NES +dacfa7746cd9772000bf7a7797727bf69003b447 H Captain Tsubasa Vol. II - Speed of Ball Controlable & All Footballer (Hack) NES ae4dcc4971b095da02cdd15506a95a848ad0994e H Captain Tsubasa Vol. II - Speed of Ball Controlable (Hack) NES 90f3a515d7fc88faa4dcecc02544df6dcfb28fff H Captain Tsubasa Vol. II - Star 4 (Hack) NES 390b7a42c5a05cb85ef3758886aec39e0433be95 H Captain Tsubasa Vol. II - Story of Ryuji Amamiya (Hack) NES @@ -3359,7 +3359,7 @@ f1110e5206ebe7261caca6bf65dc8629ba3aa643 H Captain Tsubasa Vol. II - The New Joi 78d3750224ac99d57c8c549f49daf8bd4327f5e3 H Captain Tsubasa Vol. II - The Road to the King of World Cup of Romania (Hack) NES 08d80198896115199a243fd8989549eb824bf19f H Captain Tsubasa Vol. II - The World of King (Hack) NES fec3bd3b15e2c178ba6ccddf168321b86a5b4b90 H Captain Tsubasa Vol. II - The World of Master (Hack) NES -d638f9a142c98b9a295a303e5de3a9fb32731daf H Captain Tsubasa Vol. II - The World of Matsuyama & Emperor (Hack) NES +d638f9a142c98b9a295a303e5de3a9fb32731daf H Captain Tsubasa Vol. II - The World of Matsuyama & Emperor (Hack) NES db23d6e2e46a103a98ab28da85c9d8ca6ff46177 H Captain Tsubasa Vol. II - Three Musketeers of Uruguay (Hack) NES 9bc51e53dcb4a006d4548909b3d0d8046a1b80ab H Captain Tsubasa Vol. II - Tiger Arrive by hy1897 (Hack) NES 263445f5044a2ecda0da9bb742033c143d8111ae H Captain Tsubasa Vol. II - Tiger Arrive III (Hack) NES @@ -3369,9 +3369,9 @@ bea5f2dd7f36a90f796bfb4b5dbb8caec26cc8cf H Captain Tsubasa Vol. II - Tiger Threa dec1df219d5440f0dfd1bb89bf8c9cf112052187 H Captain Tsubasa Vol. II - Tiger Wake Up (Hack) NES abcc4f5e5956bd4b81907417f9c9449627cbb209 H Captain Tsubasa Vol. II - To Cleave a Path Toward the World (Hack) NES 4b938a7c140412a36d901ec34d4e6e3ab2316733 H Captain Tsubasa Vol. II - Tong's Final Perfect Edition (Hack) NES -1fbd50eac32baa20a3c691607e2b7dccabc5a988 H Captain Tsubasa Vol. II - True & False Poland (Hack) NES +1fbd50eac32baa20a3c691607e2b7dccabc5a988 H Captain Tsubasa Vol. II - True & False Poland (Hack) NES c56e2fc9b792d1d4955f09d9406645f4dda3b422 H Captain Tsubasa Vol. II - Two Brothers Edition (Hack) NES -909592b6fa254e85e6dfdd39450602ccd087d337 H Captain Tsubasa Vol. II - Two Dragons Among Sky & Land (Hack) NES +909592b6fa254e85e6dfdd39450602ccd087d337 H Captain Tsubasa Vol. II - Two Dragons Among Sky & Land (Hack) NES 3ce8b238c3112085e1c8fb7803c37dfeeb5121c0 H Captain Tsubasa Vol. II - Two Stars (Hack) NES 9dc7a0de94dc1533aa787cb326ae285b1cf3100c H Captain Tsubasa Vol. II - Ucuncu Edition (Hack) NES f12da591683afe725fbd7c31f6dcb96d943c1be1 H Captain Tsubasa Vol. II - United Team (Hack) NES @@ -3413,8 +3413,8 @@ d78d1b5a76ba5e791ed37678b0099bfb51c69e09 H Captain Tsubasa Vol. II by EricPonti fc72f4d7e9b57f86d30510db962162cee3d81ad7 H Captain Tsubasa Vol. II by Farouk (Hack) NES 5278e84254d596732eabccb63f59133f98cbc700 H Captain Tsubasa Vol. II by Greatsocrar (90807) (Hack) NES 84f25e8916f06b02034f0f2d1629f6a26c2f5db6 H Captain Tsubasa Vol. II by Hambg (Hack) NES -19fdc8c7b290cc0b4baa05217c4003a26caff94c H Captain Tsubasa Vol. II by Kral89 & Sisqo (101003) (Hack) NES -ece3a2266a8274efcae34d605821c526573418a8 H Captain Tsubasa Vol. II by Kral89 & Sisqo (90824) (Hack) NES +19fdc8c7b290cc0b4baa05217c4003a26caff94c H Captain Tsubasa Vol. II by Kral89 & Sisqo (101003) (Hack) NES +ece3a2266a8274efcae34d605821c526573418a8 H Captain Tsubasa Vol. II by Kral89 & Sisqo (90824) (Hack) NES 509f6256210049d730719f86852393dd51459352 H Captain Tsubasa Vol. II by RUI (V071103) (Hack) NES 5723575f7f28cac92ea1b620eec3f5e5c0769d37 H Captain Tsubasa Vol. II by Shinigami (120419) (Hack) NES f895c25e330122f9d848bc3c19dbec92c0fa6a9c H Captain Tsubasa Vol. II by Xiangfuxi (081104) (Hack) NES @@ -3828,12 +3828,12 @@ f53c5c4f9e6b3d0bdb9960157aef5deba002c8f7 U Chinese Character Demo (PD) NES 4f68fe97f00351696f83fb6a4b1ad868474316e9 G Chinese Checkers (Sachen-JAP) [U][!].unf NES 6662918d3ca6b789b71b7dffd0288d04edeb617a G Chinese Checkers (Sachen-USA) [!] NES a58b71b4b9ff14be13f3539405b23bccbca93b69 G Chinese Checkers (Sachen-USA) [U][!].unf NES -0db90c9ca321bb3accc6e376cab46018d934e149 G Chip & Dale 3 (Heavy Barrel) (Unl) [p1][!] NES -f874f6cceea1b5bfb950ae05e636238550c8b5f0 U Chip & Dale 3 (Heavy Barrel) (Unl) [p1][a1] NES -711ce9a3c6672fc26f5d3715fd6b240a1c2c2d42 U Chip & Dale 3 (Heavy Barrel) (Unl) [p1][a2] NES -9137af6f4a6da817eb5fd40ff4d5bdc9899151d5 B Chip & Dale 3 (Heavy Barrel) (Unl) [p1][o1] NES -9bc93a75bd86efa25173dc0190cb22f70f897890 T Chip & Dale 3 (Heavy Barrel) (Unl) [p1][T+Rus_Cool-Spot] NES -0b3ae3706a2038e6396cddd64c1a5f66f3db4634 T Chip & Dale 3 (Heavy Barrel) (Unl) [p1][T+Rus_Paha13] NES +0db90c9ca321bb3accc6e376cab46018d934e149 G Chip & Dale 3 (Heavy Barrel) (Unl) [p1][!] NES +f874f6cceea1b5bfb950ae05e636238550c8b5f0 U Chip & Dale 3 (Heavy Barrel) (Unl) [p1][a1] NES +711ce9a3c6672fc26f5d3715fd6b240a1c2c2d42 U Chip & Dale 3 (Heavy Barrel) (Unl) [p1][a2] NES +9137af6f4a6da817eb5fd40ff4d5bdc9899151d5 B Chip & Dale 3 (Heavy Barrel) (Unl) [p1][o1] NES +9bc93a75bd86efa25173dc0190cb22f70f897890 T Chip & Dale 3 (Heavy Barrel) (Unl) [p1][T+Rus_Cool-Spot] NES +0b3ae3706a2038e6396cddd64c1a5f66f3db4634 T Chip & Dale 3 (Heavy Barrel) (Unl) [p1][T+Rus_Paha13] NES 0752c8fa49ef9ca6828ba2e08b22f2a673e5469c G Chip 'n Dale Rescue Rangers (E) [!] NES 93140bf336c482ec8bbec50fcd586a2889830e6b T Chip 'n Dale Rescue Rangers (E) [T+Fre100%_Terminus] NES c16130b878cb7f4b799ba5eb373e066ac7e5b7d7 T Chip 'n Dale Rescue Rangers (E) [T+Ger_TischlDeckDich] NES @@ -4008,10 +4008,10 @@ df432e5bd5c9afa1c91e7c76ff5e5521d136643d U Chu Chu Rocket V.d by DWEdit (PD) NES d07c459890ae980bf2cd0ddfcb793ff9bdcbec74 U Chu Chu Rocket V.h by DWEdit (PD) NES 681f4869dbee15da0f71d1ea6aca743b1acc787e U Chu Chu Rocket V.xx by DWEdit (PD) NES 828b78d6b479566b2e58c8764fcc8a8b08a1292f U Chu Da D (Ch) NES -d4f3b7146af41e6e6914002569d0952a00dd9a7c U Chu Han Zheng Ba - The War Between Chu & Han (Ch) (Wxn) NES -cc5f73da064f2d9960a4992b23c188e84fae7577 B Chu Han Zheng Ba - The War Between Chu & Han (Ch) [b1] NES -1cf6a0e4337112405be96cad63a673d1193376dc H Chu Han Zheng Ba - The War Between Chu & Han (Ch) [f1] NES -3c7099746e8a9e63a6f2dcc86d1610944458a5fe U Chu Han Zheng Ba - The War Between Chu & Han (Ch) NES +d4f3b7146af41e6e6914002569d0952a00dd9a7c U Chu Han Zheng Ba - The War Between Chu & Han (Ch) (Wxn) NES +cc5f73da064f2d9960a4992b23c188e84fae7577 B Chu Han Zheng Ba - The War Between Chu & Han (Ch) [b1] NES +1cf6a0e4337112405be96cad63a673d1193376dc H Chu Han Zheng Ba - The War Between Chu & Han (Ch) [f1] NES +3c7099746e8a9e63a6f2dcc86d1610944458a5fe U Chu Han Zheng Ba - The War Between Chu & Han (Ch) NES 8aeac2380737ada73c4b6e87f751751785e416bf H Chu Liu Xiang (Ch) (Wxn) [f1] NES 2abe3e855bc7d3ee0c38fd16f8d4fc387d3a991e U Chu Liu Xiang (Ch) (Wxn) NES f69a7ff64f4f2c6f6ab89925b267e199152c00cd U Chu Liu Xiang (Ch) NES @@ -4517,7 +4517,7 @@ e283f529f23c1defcfdcf27b2eda4289f3c9d920 T Cosmo Genesis (J) [T-Eng1.0_Aeon Gene fd3d9f8a6c862773194c3e23b420aabe9453d2d6 T Cosmo Police Galivan (J) [T+Eng1.00_Jair] NES 6f38d0ada341f86f3055f689dd0f90c62556d91e U Cosmo Police Galivan (J) NES ec493cbab694b87477ff240d3b86bca0c4e62451 G Cosmos Cop (CN-08) (Unl) [!] NES -c4020f7aa09357974739e640673ef60af8386e21 H Counteroffensive of Mamoru Izawa & Kazuki Sorimachi (Captain Tsubasa II Hack) NES +c4020f7aa09357974739e640673ef60af8386e21 H Counteroffensive of Mamoru Izawa & Kazuki Sorimachi (Captain Tsubasa II Hack) NES 08c1a73e515cf5d3cc3573b6406a8ef351bc34f7 U Cow Boy (Unl) NES 3f12e2ac5e074e7970735d896331bb7e5ef5bb73 G Cowboy Kid (U) [!] NES 80eadde91d7172ef7694662aaaede874ecac7379 B Cowboy Kid (U) [o1] NES @@ -5047,8 +5047,8 @@ eb9b77ea091d80f61a612f3b0a04fdc68ba2a23f B Dian Shi Ma Li (Ch) [b2] NES fcfc928aecb25f3ee16dc42018b1c73d5283b5b4 B Dian Shi Ma Li (Ch) [b2][o1] NES 4eccc37c236b3f18c308631c68c7b2ce1614d28c B Dian Shi Ma Li (Ch) [b3] NES 050671f45712f65fec84dc490214a6942a8c53ff B Dian Shi Ma Li (Ch) [p1] NES -1c3b08f68ebe4981b84c074520b96a42d3b45d79 B Dick & Milk (Nuts & Milk Hack) [o1] NES -717328a839ca5aecc45cc1bdb48f5a0a87d913b9 H Dick & Milk (Nuts & Milk Hack) NES +1c3b08f68ebe4981b84c074520b96a42d3b45d79 B Dick & Milk (Nuts & Milk Hack) [o1] NES +717328a839ca5aecc45cc1bdb48f5a0a87d913b9 H Dick & Milk (Nuts & Milk Hack) NES 6ac01a581a1fd6b74ed6092943bd63066e14dbf0 H Dick Baseball (Baseball Hack) NES 29ecd49dc1a66ffc0a1abf9117a84a96a5f976a3 B Dick Dug (Dig Dug Hack) [o1] NES 1cff27dd1346d2a068e56c26d0282a7773738fb9 B Dick Dug (Dig Dug Hack) [o2] NES @@ -5257,11 +5257,11 @@ c26482ee39405d332aafcfff65fd378cbfd49cf6 T Donkey Kong (W) (PRG1) [T+Nor1.00_Jus e745fda35e90bcbbe470fa62f5dfd9b7cadefa5a T Donkey Kong (W) (PRG1) [T+Rus_Cool-Spot] NES 037b98dffd8203777ec37a8acd54945f4baae3ae T Donkey Kong (W) (PRG1) [T+Spa_PaladinKnights] NES 7156d06e0e1cea71c71005aad8160939fa12efdf H Donkey Kong - Dendyman's Revenge (Hack) NES -b2ba46743405fd399e86b34211310805a17986b6 H Donkey Kong 2 (Nuts & Milk Hack) [a1] NES -ea58fb27efbcc20f34ecb7781de299766b9ee76a T Donkey Kong 2 (Nuts & Milk Hack) [T+Rus_Cool-Spot] NES -800163f4b72901412b6a1899c2ba13123375abfb H Donkey Kong 2 (Nuts & Milk Hack) NES -f0e1d4d624573b4f7be5273947871417d87cfe5a T Donkey Kong 2 Demo Ver.5 (Nuts & Milk Hack) [T+Rus_Cool-Spot] NES -50b7580c05843cea716cf2624057df6bb9cfe061 H Donkey Kong 2 Demo Ver.5 (Nuts & Milk Hack) NES +b2ba46743405fd399e86b34211310805a17986b6 H Donkey Kong 2 (Nuts & Milk Hack) [a1] NES +ea58fb27efbcc20f34ecb7781de299766b9ee76a T Donkey Kong 2 (Nuts & Milk Hack) [T+Rus_Cool-Spot] NES +800163f4b72901412b6a1899c2ba13123375abfb H Donkey Kong 2 (Nuts & Milk Hack) NES +f0e1d4d624573b4f7be5273947871417d87cfe5a T Donkey Kong 2 Demo Ver.5 (Nuts & Milk Hack) [T+Rus_Cool-Spot] NES +50b7580c05843cea716cf2624057df6bb9cfe061 H Donkey Kong 2 Demo Ver.5 (Nuts & Milk Hack) NES c4e4062a91ea9fdbd575b77535bc7a4194e46694 U Donkey Kong 3 (U) (GBA e-Reader) NES 2fdc5f68313f0fb619fa1f741cd517cc0cb18c56 T Donkey Kong 3 (U) [T+Rus_Cool-Spot][a1] NES ec6fa944c672a2522c8bc270a25842281c65ff5d G Donkey Kong 3 (W) [!] NES @@ -5446,7 +5446,7 @@ dd3490d98b8ced80263db9d17721e34dbf12db85 T Double Dragon II - The Revenge (U) (P c46342b03cec7f9a895db964125760237340f116 H Double Dragon II - The Revenge - Classic Strengthened Edition (Hack) NES 35844839991c094e86ab59205d5c0c29dda490f3 H Double Dragon II - The Revenge - Clone of Bosses Edition (Hack) NES a3c419051711233cd192405f14986059805626a4 H Double Dragon II - The Revenge - Ultimate Strengthened Edition (Hack) NES -c19b034e5886c97da670b1381bb94dfa9873e96e H Double Dragon II - The Revenge by D.S.ghtMaster&KRIZAL (Hack) NES +c19b034e5886c97da670b1381bb94dfa9873e96e H Double Dragon II - The Revenge by D.S.ghtMaster&KRIZAL (Hack) NES 3a0fadff2b3beec2dc1f13b12eb7840af588aad7 H Double Dragon II - The Revenge by KRIZAL (Hack) NES dd37c6f3de1ceaed9a8bd1abcf9aafbf47b74059 H Double Dragon II - The Revenge Control Hack by Evgeny (Hack) NES 9fca8eb7eb3a635ad71afa3e719aa5cd1ba9a7c3 H Double Dragon III - Skip Level (Hack) [a1] NES @@ -5465,7 +5465,7 @@ f878cbd0d7065df4a4ca1733085f03955b64819f C Double Dragon III - The Rosetta Stone a0ccc44a8723ceb83a644c45fd6e724b4dadcb90 C Double Dragon III - The Rosetta Stone (J) [t3] NES 9ad84eeb300efaf15a69955ffbc6d65dfc50f99c H Double Dragon III - The Rosetta Stone - Additional Moves by shinwa (Hack) NES 88d2150bac12098680e23e92be8f5de8869cc421 H Double Dragon III - The Rosetta Stone - Bosses Usable Edition by shinwa (Hack) NES -f57e4ae9c12e05343b6dee3e4af21b2513971345 H Double Dragon III - The Rosetta Stone - Combined Skill & Enemies Changed Edition (Hack) NES +f57e4ae9c12e05343b6dee3e4af21b2513971345 H Double Dragon III - The Rosetta Stone - Combined Skill & Enemies Changed Edition (Hack) NES 2a88c78e830290d901a4010e5950f9149ab0db2d H Double Dragon III - The Rosetta Stone - Combined Skill Edition (Hack) NES f2fdc2ae7491dec5c9980678645dbd9b65160709 H Double Dragon III - The Rosetta Stone - Shuang Zai Long 3 by madcell (Hack) NES a1da64a21156c537b75162f0b64da651eee1a6b8 H Double Dragon III - The Rosetta Stone - Super Skill Edition (Hack) NES @@ -5995,7 +5995,7 @@ e81a4d42dd06ba171ef5e812623115b291f295b6 T Dream Master (J) [T+Eng] NES 5a71c261b50146962940fbbd840be8617b47e07b G DreamGEAR 75-in-1 (Unl) [U][!].unf NES 907564f256368d67d9ce6b361896e7d375ad7589 U Dreamworld Pogie (Prototype) NES 7525ca4bb891940d308164dee33c497d826c1960 H Dreamworld Pogie Revival (Dreamworld Pogie Hack) NES -882a3686982874112af0d20875e3f7e9496a7392 U Driar by Stefan Adolfsson & David Eriksson (PD) NES +882a3686982874112af0d20875e3f7e9496a7392 U Driar by Stefan Adolfsson & David Eriksson (PD) NES 0cc28dc56c8ee9bb5114708b98348a592da9aec4 U Dringle (Unl) NES af8febe0ef1011e5838bf3c38933ecea06721042 U Drip for NES Ported by quietust (2006-08-16) (PD) [U].unf NES 54261d0c387cd62161d5a0ad4cff9b0d3f48c3c7 U Drip for NES Ported by quietust (2006-10) (PD) [U].unf NES @@ -6089,9 +6089,9 @@ bfcf258c012d2369ec581038abae2021f147f531 U Duel, The by Bokudono (PD) NES d6c42a64492dd75bf31b07fd8f0dba421b30ba99 B Dumbass (PD) [b1] NES 19af20fc254fe8ff443f7db8d4461b7d71dee0cf U Dune War (Unl) (VT03) NES 26b782d3f6d080bb0fb0cbd236be3d0e7ad174b2 U Dung Dung No 1 (Ch) NES -04295f33c9555d4694c57aa6423dbe1466b98836 G Dungeon & Magic - Swords of Element (J) [!] NES -d8054f63f849e6b01497450d763867ba43423a26 B Dungeon & Magic - Swords of Element (J) [b1] NES -f4b42da49b97bf4d93fde1016602087fe5c5b0cb B Dungeon & Magic - Swords of Element (J) [o1] NES +04295f33c9555d4694c57aa6423dbe1466b98836 G Dungeon & Magic - Swords of Element (J) [!] NES +d8054f63f849e6b01497450d763867ba43423a26 B Dungeon & Magic - Swords of Element (J) [b1] NES +f4b42da49b97bf4d93fde1016602087fe5c5b0cb B Dungeon & Magic - Swords of Element (J) [o1] NES 427506826bf9cf2ef144100be2e3f98d9e979798 G Dungeon Kid (J) [!] NES 602ca2cada36025c04562dc174f7ceca284885b3 B Dungeon Kid (J) [b1] NES d8519092cf52b7a4f0fc94a9829ada12681c0279 C Dungeon Kid (J) [t1] NES @@ -6219,8 +6219,8 @@ c4085b7a4aabd8ac27fdc2b647715d451a2bc04a B Eliminator Boat Duel (U) [b1] NES d0ef1150ab6cdcb076a528cf2b18a780864d4bb3 B Eliminator Boat Duel (U) [o1] NES 00009ecaf75344e39cc9a94805f5113c10f270a2 B Eliminator Boat Duel (U) [o2] NES 02b277caef0970078dfb3f2dbb7ced731380ecfd G Elite (E) [!] NES -aa3b7bbb929efd9c2b364e63000ccb1cc107c2a0 B Elite (E) [f1] (NTSC by Ian Bell & David Braben) [o1] NES -17c4f91469931ea309bfff4faba3f3c34deed3c7 H Elite (E) [f1] (NTSC by Ian Bell & David Braben) NES +aa3b7bbb929efd9c2b364e63000ccb1cc107c2a0 B Elite (E) [f1] (NTSC by Ian Bell & David Braben) [o1] NES +17c4f91469931ea309bfff4faba3f3c34deed3c7 H Elite (E) [f1] (NTSC by Ian Bell & David Braben) NES 092849f8d75ac1206f63bb82e43c4f670fb8eed1 H Elite Tecmo League (Tecmo Super Bowl Hack) NES 4d4faac62a455dfa8ada73480e6c67906b3957e1 H Elite Tecmo League Clock (Tecmo Super Bowl Hack) NES 8bb770863ccded715de87dbccbf26e36c8363572 H Elite Tecmo League S1 Week 03 (Tecmo Super Bowl Hack) NES @@ -6261,7 +6261,7 @@ f59d7b0cf20d9abaf6a7b7f1b66744ea55f9d2fa G Erika to Satoru no Yume Bouken (J) [! c42a1191d0292f208873e0e1ab122d7354c7925e H Erika to Satoru no Yume Bouken (J) [f1] NES 222ac701664930f295da954393e8eb9376017f33 B Erika to Satoru no Yume Bouken (J) [f1][o1] NES bc59e706bc0cda456e496b2403a41df61eebfdbb B Erika to Satoru no Yume Bouken (J) [hM04][b1] NES -00222d1ea57c7ee4bb614536642d03f02cbca769 H Ernie & The Muppets Take It All Off (Sesame Street ABC Hack) NES +00222d1ea57c7ee4bb614536642d03f02cbca769 H Ernie & The Muppets Take It All Off (Sesame Street ABC Hack) NES 4f4355afcfde87e651c32eda7610d67c02396ff8 G Erunaaku no Zaihou (J) [!] NES aff3198813f2e25c9684b63354f1da6bdf2d7c6d B Erunaaku no Zaihou (J) [b1] NES 8d68935e94134eec22a4259080b3ce5590e4f7a3 B Erunaaku no Zaihou (J) [b2] NES @@ -6419,7 +6419,7 @@ a0375e7e0da9093417a9d081b7606ed9f5c71ac3 B F-15 Strike Eagle (U) [o1] NES 96ab957763051c6b8d952567450469c9af99e3d4 B F22 (Ch) [b1] NES 63c23c5bb78d256a0361e7a7a0ffb24d8c87cc11 T Facemaker (Dr. PC Jr.) (Ch) [T+Rus_Cool-Spot] NES dc8fde977a5a06d579f80d0861b235014b678a53 U Facemaker (Dr. PC Jr.) (Ch) NES -ea97d054a53c65428d1c1ee27c2fc5c945944843 U Fade to Black by Frederik Schultz & Morgan Johansson (PD) NES +ea97d054a53c65428d1c1ee27c2fc5c945944843 U Fade to Black by Frederik Schultz & Morgan Johansson (PD) NES 9f3d83c3b6e620d9e67cf5cd49428c3f88a71ca4 H Fall of the Moon v1.0 (Zelda Hack) NES 508dfa36b062dfd1a465301ada3a876acc402582 U Falldown by Sivak (2008) (PD) NES 45543a0aed48f5d0943a8ee33ea8a9709c3bfa3d H Falling Mario by WA (SMB1 Hack) NES @@ -6441,7 +6441,7 @@ f07d48f7355480f855a60d0e8c65621f4e4c643d H Famicom Jump II - Saikyou no 7 Nin (J 9c5381325383bf6c074b2c3cdcc825e138615a19 G Famicom Meijin Sen (J) [!] NES 44c1d079b75deeb3e858240a0d4a10d5d7add87c U Famicom Meijin Sen (J) [a1] NES aaf74b17bfe8c18fd672fcae18741956d1c3380e B Famicom Meijin Sen (J) [a1][o1] NES -6992f115820264ceaaff988cb4bfbe3c5e35ecc9 U Famicom Pro Action Rocky Encoder-Decoder by Chris Covell, ReaperSMS & Jamethiel (PD) NES +6992f115820264ceaaff988cb4bfbe3c5e35ecc9 U Famicom Pro Action Rocky Encoder-Decoder by Chris Covell, ReaperSMS & Jamethiel (PD) NES 21727912fe4ae683da2c7aadb029f355079964fd U Famicom Sequencer V0.5 (PD) NES 052e6915a4b6c15982d5b134fce7581210c7d8de U Famicom Shougi - Ryuuousen (J) (Prototype) NES e4cc5f8e013fae686d97f3901c261b5abfcc9d5b B Famicom Shougi - Ryuuousen (J) [o1] NES @@ -6580,10 +6580,10 @@ a3d852930db34bb76c1ac1531311dd5552b8e7be G Fantasy Zone (Tengen) [!] NES 96aca644fb0450542d35573e99afdd1534f8191f H Fantasy Zone 2 - The Teardrop of Opa-Opa (J) [hFFE] NES 7b7b333f5f4da08f523256518b5244006c994090 B Fantasy Zone 2 - The Teardrop of Opa-Opa (J) [o1] NES 808cc9050dcee35fa499d601e8567166bda4493a C Fantasy Zone 2 - The Teardrop of Opa-Opa (J) [t1] NES -2841d46704680033b183c7c07945dbbcb68427ed G Faria - A World of Mystery & Danger! (U) [!] NES -b9350d2ca19c4185b8cb32ffa5e51b114a5702fc B Faria - A World of Mystery & Danger! (U) [b1] NES -6129ba26219de2586562234e8f16a29ad6c586db B Faria - A World of Mystery & Danger! (U) [o1] NES -24027380173f2004a44870c8fee3eb9dd1027d76 C Faria - A World of Mystery & Danger! (U) [t1] NES +2841d46704680033b183c7c07945dbbcb68427ed G Faria - A World of Mystery & Danger! (U) [!] NES +b9350d2ca19c4185b8cb32ffa5e51b114a5702fc B Faria - A World of Mystery & Danger! (U) [b1] NES +6129ba26219de2586562234e8f16a29ad6c586db B Faria - A World of Mystery & Danger! (U) [o1] NES +24027380173f2004a44870c8fee3eb9dd1027d76 C Faria - A World of Mystery & Danger! (U) [t1] NES e7fdd7976a9c834f171b3ac39ab69259e05a0afa G Faria - Fuuin no Tsurugi (J) [!] NES d87116e7aee1b8fac894b30b4aaa50539aaedab9 B Faria - Fuuin no Tsurugi (J) [b1] NES 2235a01f54223dd2609cef3dc3dc82b7775b9bfb B Faria - Fuuin no Tsurugi (J) [b2] NES @@ -6631,7 +6631,7 @@ e86add4e0badb9396c18bbc2b786b08a044dd83d H Faxanadu Uncensored Edition by Safari 0db354cc152ff3413e401160d5f51871326628aa C FC Genjin - Freakthoropus Computerus (J) [t1] NES 99e513dba565f5b4f648bc0a1a0f52aff5a48946 U FC Genjin - Freakthoropus Computerus (J) NES 99d5f61fc8fda02db984308368277a326c123977 U FC Intro by emumax (PD) NES -416b236dd5babc127555185e15a22f70e718186e U FC WIN2000 (for Infrared Mouse & Keyboard) (Ch) NES +416b236dd5babc127555185e15a22f70e718186e U FC WIN2000 (for Infrared Mouse & Keyboard) (Ch) NES 07252ffa0df0f65d681e79ab2ba38250ec85c08b U FC-Subor V3.0 Music Demo (Unl) NES e0d0eaaf0523d3442072134667198ea5ee342934 H Fedsvd MLB (R.B.I. Baseball Hack) [a1] NES 6411512f09c63c6679c258b9c8cbd87791581f1f H Fedsvd MLB (R.B.I. Baseball Hack) NES @@ -6664,7 +6664,7 @@ c2add8e26655ba9b6774197dc1a6e730f0a92c0b U Feng Se Huan Xiang (ES-1138) (Ch) NES 083793f71533db327cbcbe0ae27d4a1483733777 U Feng Yun (Ch) (Decrypted) NES 1a0ced71e62f11bccb4b2de3fe0433240e75357b U Feng Yun (Ch) (Wxn) NES ea0d9f0df87a2c5b518642bb793d67b544ae5165 U Feng Yun (Ch) NES -8008cd3ff792a2c7e5e34c34543394d6ffbf48b5 U Fengli Dance 12-in-1 & 24-in-1 (Ch) NES +8008cd3ff792a2c7e5e34c34543394d6ffbf48b5 U Fengli Dance 12-in-1 & 24-in-1 (Ch) NES 1f3c590a05e3897f4266302f744dd65e70e501b0 G Ferrari - Grand Prix Challenge (E) [!] NES 146e39e962c6fff24724fe55d632ba4217cc3b67 G Ferrari - Grand Prix Challenge (J) [!] NES bee319db995fc25dd6ee88217e10420aab7310ca G Ferrari - Grand Prix Challenge (U) [!] NES @@ -6829,13 +6829,13 @@ b0f164556d8cb71b2c04bd7d9d306c0e7c026772 H Final Fantasy Epica V2.0 by Clomax Do edafdca67ae322a086386b219d67c526de592f73 H Final Fantasy Gaiden (FF1 Hack) NES 083294dfaa5238c750110ce0d95b57ebcd9c9ce6 H Final Fantasy Hard Type by Red Wizard (FF1 Hack) NES 5b46b541851eefc0954bd7f15ef860dc43bf1fac H Final Fantasy Hardtype V1.1 (FF1 Hack) NES -4b22c2c88fc71eacf270ea51ef218944bb4c536a G Final Fantasy I & II (J) [!] NES -b3c2be46b4118df618a90969aec3836c36213187 B Final Fantasy I & II (J) [b1] NES -f68f71e3475a0d2a3455eb4ea55aa7c6b4989329 B Final Fantasy I & II (J) [b2] NES -e0a971450a7907f8e5ac1749638d03800c371cce B Final Fantasy I & II (J) [o1] NES -5c86afaee19c4d564be583d19639af9e3308a6c6 B Final Fantasy I & II (J) [o1][T+Eng1.00_Demiforce] NES -704d46eb311a7d07268ea57de26cdacc3a83711a T Final Fantasy I & II (J) [T+Eng1.00_Demiforce,Grond] NES -ff5a216e3da57ee7133449a4ac6b0e8957a23595 T Final Fantasy I & II (J) [T+Eng1.00_Demiforce] NES +4b22c2c88fc71eacf270ea51ef218944bb4c536a G Final Fantasy I & II (J) [!] NES +b3c2be46b4118df618a90969aec3836c36213187 B Final Fantasy I & II (J) [b1] NES +f68f71e3475a0d2a3455eb4ea55aa7c6b4989329 B Final Fantasy I & II (J) [b2] NES +e0a971450a7907f8e5ac1749638d03800c371cce B Final Fantasy I & II (J) [o1] NES +5c86afaee19c4d564be583d19639af9e3308a6c6 B Final Fantasy I & II (J) [o1][T+Eng1.00_Demiforce] NES +704d46eb311a7d07268ea57de26cdacc3a83711a T Final Fantasy I & II (J) [T+Eng1.00_Demiforce,Grond] NES +ff5a216e3da57ee7133449a4ac6b0e8957a23595 T Final Fantasy I & II (J) [T+Eng1.00_Demiforce] NES ae373debd5a1d787eec28214c221fa4590c20844 U Final Fantasy II (J) (VC) NES 1a9e01a29472f1161bd16e1b4d76994346a505f6 G Final Fantasy II (J) [!] NES de129faa757050a925e5060f65bdc390d3978eb4 H Final Fantasy II (J) [hM02] NES @@ -6876,7 +6876,7 @@ ddc7b6b85ab0eaf26586d5a97aaa04c3620c2d1e H Final Fantasy II (J) [hM02][T-Eng1.0] 20079a629ff38fb2e76cf3a6e78c782588c890ef T Final Fantasy II (J) [T+Bra100%_Thirteen Traducoes] NES 90a5ccc3119aa91947f086c3c9fc069a7f80ef09 T Final Fantasy II (J) [T+Eng0.36_Toma,AlanMidas] NES 62ed16088e5293a9f238161c12fe59eaa196f1f8 T Final Fantasy II (J) [T+Eng1.03_Demiforce] NES -b7a849df213b59cd43066d15eeec4df983c0b5f5 T Final Fantasy II (J) [T+Eng1.03_Demiforce][f1] (Title & Weapon-Magic Exploit by Parasyte) NES +b7a849df213b59cd43066d15eeec4df983c0b5f5 T Final Fantasy II (J) [T+Eng1.03_Demiforce][f1] (Title & Weapon-Magic Exploit by Parasyte) NES de7fecb42947a24fbf632e2ccfccbdba69a857fb T Final Fantasy II (J) [T+Eng1.03_Demiforce][f1] (Title by Parasyte v1.0) NES 73f8436f78cec36f4d205a2dc5cc25fe949efc22 T Final Fantasy II (J) [T+Eng1.03PasoFami_Demiforce] NES 4e68ee5da3dbe2ed7348be072825364c87d2ab6a T Final Fantasy II (J) [T+Ita0.99a_Weapon Hunter] NES @@ -7085,7 +7085,7 @@ b7b3054034234ffaea975e4158f32f0f6bd12721 B Fire Emblem Gaiden (J) [T+Eng97b2_J2E de04536e3fa70d9dbccf62e0dc2e58bf02ac94f4 H Fire Emblem Gaiden by jibo818 (070502) (Hack) NES ead6701e3998cd7f81c8e8fccd1bb12a0bd90169 H Fire Emblem Gaiden by Lewis GT (070806) (Hack) NES d0c52c96c29dd6144215e63047b39972982894d1 H Fire Emblem Gaiden by scorpioywk v3.0a (Hack) NES -44b79228f44efc9acf9f878a08e8d8493c311ca7 H Fire Emblem Map & Enemy by One Talent (Hack) NES +44b79228f44efc9acf9f878a08e8d8493c311ca7 H Fire Emblem Map & Enemy by One Talent (Hack) NES 209f7ca3f4f9e179881aa9387dc6ad5dea4f4575 B Fire Emblem Two Dragon Edition (Hack) [b1] NES efa0e83b2bcb0f02fc81fc7b434ffe56209d3d67 H Fire Emblem Two Dragon Edition (Hack) NES 85438df235e84b38452282aa2f96624f31986b59 B Fire Flight Z (Formation Z Hack) [o1] NES @@ -7127,17 +7127,17 @@ c212375ac4a48de955e608af2ccc9cd36cc040fe T Fleet Commander (J) [T+Rus_Chief-Net] 18e4116d04aa688a8a8629f3b6770ec8436d2778 G Flight of the Intruder (U) [!] NES 425d371df518c142c9dfc9764e02ac53ada94d0e B Flight of the Intruder (U) [b1] NES b823ee04d31bdf6937ddfc3a1e81f2fa8ea3cf2f B Flight of the Intruder (U) [o1] NES -9695b227545fca9cd6c95abf348ff51b175634f6 G Flintstones, The - The Rescue of Dino & Hoppy (E) [!] NES -66b701bcf13ea261cf459058d141f078fc66652c C Flintstones, The - The Rescue of Dino & Hoppy (E) [t1] NES -9d1ba8a9cb5afe378bf4cdf94dee5eecd80ccf6b U Flintstones, The - The Rescue of Dino & Hoppy (J) NES -549de66388ff02e33a40bf7ef83e207f98a50888 G Flintstones, The - The Rescue of Dino & Hoppy (U) [!] NES -db9f7f37cac7a00752beffe5a14c295f1722823e B Flintstones, The - The Rescue of Dino & Hoppy (U) [b1] NES -c0a6a7cbf5de4451aed7f5f8fe6b67df97c4c11b B Flintstones, The - The Rescue of Dino & Hoppy (U) [b2] NES -18c335127d0338318ac04d43b6ee434623db761c B Flintstones, The - The Rescue of Dino & Hoppy (U) [o1] NES -805737b473814baeeaf98bdacd2de810dae5c8e5 G Flintstones, The - The Rescue of Dino & Hoppy (U) [p1][!] NES -ad651e65a9e7333a415f1071f0783a3f4ea53218 B Flintstones, The - The Rescue of Dino & Hoppy (U) [p2] NES -deb230107c87863a7226d4466470aa5b824d6d0c C Flintstones, The - The Rescue of Dino & Hoppy (U) [t1] NES -4c2199ab578faf2cb1f244e5a562ecc0918f27ca C Flintstones, The - The Rescue of Dino & Hoppy (U) [t2] NES +9695b227545fca9cd6c95abf348ff51b175634f6 G Flintstones, The - The Rescue of Dino & Hoppy (E) [!] NES +66b701bcf13ea261cf459058d141f078fc66652c C Flintstones, The - The Rescue of Dino & Hoppy (E) [t1] NES +9d1ba8a9cb5afe378bf4cdf94dee5eecd80ccf6b U Flintstones, The - The Rescue of Dino & Hoppy (J) NES +549de66388ff02e33a40bf7ef83e207f98a50888 G Flintstones, The - The Rescue of Dino & Hoppy (U) [!] NES +db9f7f37cac7a00752beffe5a14c295f1722823e B Flintstones, The - The Rescue of Dino & Hoppy (U) [b1] NES +c0a6a7cbf5de4451aed7f5f8fe6b67df97c4c11b B Flintstones, The - The Rescue of Dino & Hoppy (U) [b2] NES +18c335127d0338318ac04d43b6ee434623db761c B Flintstones, The - The Rescue of Dino & Hoppy (U) [o1] NES +805737b473814baeeaf98bdacd2de810dae5c8e5 G Flintstones, The - The Rescue of Dino & Hoppy (U) [p1][!] NES +ad651e65a9e7333a415f1071f0783a3f4ea53218 B Flintstones, The - The Rescue of Dino & Hoppy (U) [p2] NES +deb230107c87863a7226d4466470aa5b824d6d0c C Flintstones, The - The Rescue of Dino & Hoppy (U) [t1] NES +4c2199ab578faf2cb1f244e5a562ecc0918f27ca C Flintstones, The - The Rescue of Dino & Hoppy (U) [t2] NES 354415e5472c4cbf4978744c97a9a53c6b61cb49 G Flintstones, The - The Surprise at Dinosaur Peak! (E) [!] NES 5a6ae3e6897414758a8791783f3a482e5a2dd0fb G Flintstones, The - The Surprise at Dinosaur Peak! (U) [!] NES a3bdfaa4d67de0f1468d9fe701a8988e2e732744 B Flintstones, The - The Surprise at Dinosaur Peak! (U) [o1] NES @@ -7284,9 +7284,9 @@ ff9ba69080f51331a10df9c2f7531ab5a9a34e58 B Front Line (J) [T-Chi][b1] NES 2b257fa8049678600b4db8461b56bfceee1056aa H Front Line 2 Hardcore (Front Line Hack) NES a9966b9065b29defc48a2566136b634f74dd31e7 U FS Demo by KZ-S (PD) NES 3759f6d43be742defb5b52117e5378645332c816 H Fucked Up Bros 2 (SMB2 Hack) NES -0bc48f6ceee853de3535bb49227415e5d817ba0e H Fucked Up North & South (Hack) NES +0bc48f6ceee853de3535bb49227415e5d817ba0e H Fucked Up North & South (Hack) NES 794d30faa4ba81046405f3c6599b73c3a297b2ad H Fucker's Quest by Shitdic (Fester's Quest Hack) NES -b346af0a6ef44db9e251ed18a3925f8396868496 H Fudan Mario by DU-6&Hi (SMB1 Hack) NES +b346af0a6ef44db9e251ed18a3925f8396868496 H Fudan Mario by DU-6&Hi (SMB1 Hack) NES 1ae0646964ad522f78427d5f29401b197020a4df G Fudou Myouou Den (J) [!] NES 54f3061ca2ccc87342d44cec098a4c07d530d6ce B Fudou Myouou Den (J) [hFFE][b1] NES 056280af7a109617d1f0d21e228dcb9dbe394693 H Fudou Myouou Den (J) [hM80] NES @@ -7525,8 +7525,8 @@ c6954c8d5030bd3f446644e2a02b3135d3bbff93 B Garou Densetsu Special (Unl) [hM04][b fe0d1d3f7662bcba4c550440696d6fb24b3181a9 B Garou Densetsu Special (Unl) [hM04][b5] NES aec04b867e7de8dc7ace8563bd693b9199c4a33a H Garou Densetsu Special (Unl) [hM04][f1] NES de38a34367495ff5e899b574e15495f78a5e5678 U Garou Densetsu Special (Unl) NES -7f95489c35713f1befb5bfbfc6a51b523eaa1b50 T Gary's Nuts (J) (Nuts & Milk Hack) [T+Rus_Cool-Spot] NES -468e874670c5b8e7db979db02d5eb5d4bae256a4 H Gary's Nuts (J) (Nuts & Milk Hack) NES +7f95489c35713f1befb5bfbfc6a51b523eaa1b50 T Gary's Nuts (J) (Nuts & Milk Hack) [T+Rus_Cool-Spot] NES +468e874670c5b8e7db979db02d5eb5d4bae256a4 H Gary's Nuts (J) (Nuts & Milk Hack) NES b5a669ea96249a23ca3b868ac1c7555e611ee83b U Gauntlet (PC10) NES d3a2ad975e2e955e39fb3fd64e93ff983af81e0d G Gauntlet (Tengen) [!] NES debb19b46939a296bad008cffbb3bb0f8d6608d3 B Gauntlet (Tengen) [b1] NES @@ -7978,7 +7978,7 @@ bc39a2546b530fc84e90052d4077676da97ed679 T Grand Master (J) [T-Eng_Stardust Crus aa0fb9dd052ee687ff02ed2713ed92a3887e76f0 U Grand Master (J) NES 0f01b092ce5d02d5c6e3ea553290a06c8281ee24 U Grandia (Ch) (Wxn) NES 8bcdc14b93f52cd4a657c18fee21cdc4ed6298a1 H Graros (Seicross Hack) NES -f5d968639bb462819500cb33a3644487f177740b U Grave Digger by Tarnow, Hollis, Gillotti & Subramanian (PD) NES +f5d968639bb462819500cb33a3644487f177740b U Grave Digger by Tarnow, Hollis, Gillotti & Subramanian (PD) NES d0da677def74b64e1b2d25748e2bce691566c4b0 B Great Adventures of Weiny, The (Mario Bros Hack) [o1] NES b0b0a350e4360fb03cf536c961f2f4fa68f98dbf H Great Adventures of Weiny, The (Mario Bros Hack) NES a55e9323d89d855672dcb20dc29efd2f53ded972 G Great Battle Cyber (J) [!] NES @@ -8019,9 +8019,9 @@ e327e3e3814f0ea008d347eeee1b72e378abb857 B Gremlins 2 - The New Batch (U) [b1] N abc3dfd1cc1fab09eb5edb6223570a26f974c9e8 C Gremlins 2 - The New Batch (U) [t1] NES 34eea8840f666fca69d85f6dfa5fdf77a297b3b3 U Greys Demo by Chris Covell (PD) NES 3b3dea215ac51563b049f9f5a643bc1e5e88c8aa H Grond's Final Fantasy (FF1 Hack) NES -3d1098ccc2250e8e007170d2143112d61f348a31 H Grond's Final Fantasy Bugfix & Balancing (FF1 Hack) [a1] NES -076003fdac7b73059f8e45c9d9f8ae5a04af5c9c H Grond's Final Fantasy Bugfix & Balancing (FF1 Hack) NES -1e18667e99767f3ab6acf54b685986b230696722 H Grond's Final Fantasy Bugfix & Balancing (v1.1) (FF1 Hack) NES +3d1098ccc2250e8e007170d2143112d61f348a31 H Grond's Final Fantasy Bugfix & Balancing (FF1 Hack) [a1] NES +076003fdac7b73059f8e45c9d9f8ae5a04af5c9c H Grond's Final Fantasy Bugfix & Balancing (FF1 Hack) NES +1e18667e99767f3ab6acf54b685986b230696722 H Grond's Final Fantasy Bugfix & Balancing (v1.1) (FF1 Hack) NES 0828f94fedee148987ac3cfa4a270d26306bc6b0 U GSD Super Student Computer Cartridge (Ch) NES f8229677bfad4050a24bfb9a78521a6e36d3cac4 G Gu Ba Zhan Shi Xi Hua (Ch) [!] NES bd147f4eeafe37d73524a0d0a6735a422376e482 U Gu Ba Zhan Shi Xi Hua (Ch) [a1] NES @@ -8203,7 +8203,7 @@ e545041ff87271f56f975d73d7b772d37f06d2bb H Hanjuku Eiyuu (J) [hM02] NES 810a86d04016eeba01cdc826f80babb86619b8d7 H Hanjuku Eiyuu (J) [hM02][a1] NES e7305030fe0261de587b16c85a0acab9386bc858 B Hanjuku Eiyuu (J) [o1] NES 11777a01cdb2d242233742d4a302c1af51f759e4 H Hanjuku Eiyuu by fenglianxilin (070808) (Hack) NES -fbb406a103e79df26ac4ef208b7f9df16006ee44 H Hansel & Gretel (SMB1 Hack) NES +fbb406a103e79df26ac4ef208b7f9df16006ee44 H Hansel & Gretel (SMB1 Hack) NES 9be59e3c120046c2b9e68bb5f25d21f1b2dc8386 U Happy Angel Legend (Unl) NES 9a07441300f5f13898f777020fe8cb04361d3ca6 H Happy Birthday - BMF x 28 (SMB1 Hack) NES 65855650819327782bce279dbaea220090deeb6e G Happy Birthday Bugs (J) [!] NES @@ -9118,10 +9118,10 @@ af45f13c326ce6e8b5e29eb583faf5d9a74349b7 B Iron Tank - The Invasion of Normandy 3b4a5cb92fc0df0cb8e6fb4528a5414004005116 B Iron Tank - The Invasion of Normandy (U) [o2] NES f745f07efda10a0c685f693df47ed8b15b3aa458 C Iron Tank - The Invasion of Normandy (U) [t1] NES c8c011ab830e9aefd2c6335a40857fda48186356 C Iron Tank - The Invasion of Normandy (U) [t2] NES -bf7b26e28cecc6a46131971210bfb10123ab9dab G Ironsword - Wizards & Warriors II (E) [!] NES -97b79e432f62403fb9f877090850c41112a9a168 G Ironsword - Wizards & Warriors II (U) [!] NES -cdc3da09fdd4478b5c8f1640ea26604cdf096a62 B Ironsword - Wizards & Warriors II (U) [b1] NES -84f6af51c04d27e877480bc9136d4c0401bb2461 B Ironsword - Wizards & Warriors II (U) [o1] NES +bf7b26e28cecc6a46131971210bfb10123ab9dab G Ironsword - Wizards & Warriors II (E) [!] NES +97b79e432f62403fb9f877090850c41112a9a168 G Ironsword - Wizards & Warriors II (U) [!] NES +cdc3da09fdd4478b5c8f1640ea26604cdf096a62 B Ironsword - Wizards & Warriors II (U) [b1] NES +84f6af51c04d27e877480bc9136d4c0401bb2461 B Ironsword - Wizards & Warriors II (U) [o1] NES 5d9402702b33d226e822dd4a39b9004dcd90b787 U IRQ Flag Operation Test by Shay Green (30 Jun 2005) (PD) NES 7fbd5c094f63d8d0ad9cfb0730e809875bcdace6 U IRQ Flag Timing Test by Shay Green (30 Jun 2005) (PD) NES 5b87d2e908ae68348ccb306764ac7ec9067395e3 U IRQ Handler Test by Shay Green (30 Jun 2005) (PD) NES @@ -9390,15 +9390,15 @@ e54091563b9f39863a93f8c0260b3b5518628576 T JJ - Tobidase Daisakusen Part 2 (J) [ f19a702eefcb6467176916a6f612974dcba0fb19 T JJ - Tobidase Daisakusen Part 2 (J) [T+Rus] NES 6c2aee3bfe22bdbcab6f707720b3675c2d439c42 T JJ - Tobidase Daisakusen Part 2 (J) [T+Rus][t1] NES 90dd8e45ade16e684489d34343856b6a0b8dac26 C JJ - Tobidase Daisakusen Part 2 (J) [t1] NES -935a56567d1e8516c104ead5e9ecbc6d8e9b0a1f G Joe & Mac - Caveman Ninja (E) [!] NES -36bafdf6f8d531fecb3553c1923eeafac4a05c28 G Joe & Mac - Caveman Ninja (U) [!] NES -79a02ad09b776734e9e341d91137e989ea482f8e B Joe & Mac - Caveman Ninja (U) [b1] NES -6edbe6c00f8246a1f8c1a6fa543e9e2e83ea666e B Joe & Mac - Caveman Ninja (U) [o1] NES -e3b06ee583b47c55b5a1c9354482a27ad2cfbfde G Joe & Mac - Caveman Ninja (U) [p1][!] NES -bcf23b47befc698b9c8e1c2e1aa48529ac6ecf06 B Joe & Mac - Caveman Ninja (U) [p2] NES -ef454083c6720b6f0a541257eb9a41758f27746c B Joe & Mac - Caveman Ninja (U) [p3] NES -f8139f01b7c3ca2b14cefec784ae64781c8f956d C Joe & Mac - Caveman Ninja (U) [t1] (No Time) NES -9031b847c51320960655849c750f027b20d05a80 C Joe & Mac - Caveman Ninja (U) [t2] NES +935a56567d1e8516c104ead5e9ecbc6d8e9b0a1f G Joe & Mac - Caveman Ninja (E) [!] NES +36bafdf6f8d531fecb3553c1923eeafac4a05c28 G Joe & Mac - Caveman Ninja (U) [!] NES +79a02ad09b776734e9e341d91137e989ea482f8e B Joe & Mac - Caveman Ninja (U) [b1] NES +6edbe6c00f8246a1f8c1a6fa543e9e2e83ea666e B Joe & Mac - Caveman Ninja (U) [o1] NES +e3b06ee583b47c55b5a1c9354482a27ad2cfbfde G Joe & Mac - Caveman Ninja (U) [p1][!] NES +bcf23b47befc698b9c8e1c2e1aa48529ac6ecf06 B Joe & Mac - Caveman Ninja (U) [p2] NES +ef454083c6720b6f0a541257eb9a41758f27746c B Joe & Mac - Caveman Ninja (U) [p3] NES +f8139f01b7c3ca2b14cefec784ae64781c8f956d C Joe & Mac - Caveman Ninja (U) [t1] (No Time) NES +9031b847c51320960655849c750f027b20d05a80 C Joe & Mac - Caveman Ninja (U) [t2] NES 5e44cea620e33e3c7c04c67163b0a9c612939c47 G John Elway's Quarterback (U) [!] NES d0e8588498ff005c311492c221b3c67721b8d42d B John Elway's Quarterback (U) [o1] NES f67733b11991cc1c2301bf9d97df7c2b25a6bfdf B John Elway's Quarterback (U) [o2] NES @@ -9413,11 +9413,11 @@ e53a42ac93b757541e853695dd0c7ae50b437874 B Jongbou (J) [f1][o1] NES 1c07244a8b98dde1f4ecb176097ca6aacd8c785d B Jongbou (J) [f1][o3] NES ce8415b6a7585a752d1979ef87d4227591789e97 G Jordan Vs Bird - One On One (U) [!] NES 538668aaa59db38e072cd1f499dead9236bbe13f B Jordan Vs Bird - One On One (U) [o1] NES -011a7ce0c86929a5788a67ed49c5dc587c53f991 U Joshua & the Battle of Jericho (Wisdom Tree) (V5.0 CHR 6.0) NES -4d838a393823b2ab2fcca48b6cda6292f2992880 G Joshua & the Battle of Jericho (Wisdom Tree) (V6.0) [!] NES -4856a12ba4f01e0ca41bfa6c95039fc302a60724 B Joshua & the Battle of Jericho (Wisdom Tree) (V6.0) [b1] NES -e598d9753a823d39fda3cddc486a56ffb0ebee33 B Joshua & the Battle of Jericho (Wisdom Tree) (V6.0) [b2] NES -eb320ad334f8f26044eb1084b070003bafc4e7d1 B Joshua & the Battle of Jericho (Wisdom Tree) (V6.0) [o1] NES +011a7ce0c86929a5788a67ed49c5dc587c53f991 U Joshua & the Battle of Jericho (Wisdom Tree) (V5.0 CHR 6.0) NES +4d838a393823b2ab2fcca48b6cda6292f2992880 G Joshua & the Battle of Jericho (Wisdom Tree) (V6.0) [!] NES +4856a12ba4f01e0ca41bfa6c95039fc302a60724 B Joshua & the Battle of Jericho (Wisdom Tree) (V6.0) [b1] NES +e598d9753a823d39fda3cddc486a56ffb0ebee33 B Joshua & the Battle of Jericho (Wisdom Tree) (V6.0) [b2] NES +eb320ad334f8f26044eb1084b070003bafc4e7d1 B Joshua & the Battle of Jericho (Wisdom Tree) (V6.0) [o1] NES 85f64db051e8c173a18905066052d412a8eb1d6c G Journey to Silius (E) [!] NES 275244538589393b552b159ab1d380090c8e8996 G Journey to Silius (U) [!] NES 08c67ce185d2a4230d6c954bd90587192d2e34d2 B Journey to Silius (U) [b1] NES @@ -9990,10 +9990,10 @@ f324e7c8c3ad102ecdcca011ecc494f6f345d768 G Kirby's Adventure (U) (PRG1) [!] NES 455a81e5644317409d6047a7dccff56cb07cde89 H Kirby's Adventure 2 (SMB1 Hack) NES c6f778708182114b4f58093575cf51b5de9926b7 H Kirby's Adventure FUCKED (Hack) NES 15175dfe4b255b3ffc1003e7ffc3d87888fd3acc U Kirby's Dreamland 3 Title Screen Demake by Macbee v1.0 (PD) NES -c445072c3362fa3fb2cc481706d5b1b96b368798 B Kirby's Nuts (Nuts & Milk Hack) [o1] NES -67c1d833caa09444555711fdb32e7f16dfe61389 T Kirby's Nuts (Nuts & Milk Hack) [T+Rus_Cool-Spot] NES -d875bd8977d6486ac3c5c874d9d4f2cdcdc0841a T Kirby's Nuts by Kidwhatever (Nuts & Milk Hack) [T+Rus_Multisoft] NES -046d3a72942639a1a0c8a6eaa8c0a049051ea113 H Kirby's Nuts by Kidwhatever (Nuts & Milk Hack) NES +c445072c3362fa3fb2cc481706d5b1b96b368798 B Kirby's Nuts (Nuts & Milk Hack) [o1] NES +67c1d833caa09444555711fdb32e7f16dfe61389 T Kirby's Nuts (Nuts & Milk Hack) [T+Rus_Cool-Spot] NES +d875bd8977d6486ac3c5c874d9d4f2cdcdc0841a T Kirby's Nuts by Kidwhatever (Nuts & Milk Hack) [T+Rus_Multisoft] NES +046d3a72942639a1a0c8a6eaa8c0a049051ea113 H Kirby's Nuts by Kidwhatever (Nuts & Milk Hack) NES 576b13815dbcfdb621b2654ab14b30a8080a8a4a H Kiri5 Star (SMB1 Hack) [a1] NES 58f4d00498313f5179fd5749e9c15efeef0b5910 H Kiri5 Star (SMB1 Hack) NES 226da664994cee80f3af52fe98f77b92df291766 H Kiri7 (SMB1 Hack) NES @@ -10182,7 +10182,7 @@ b338354bf584e2abccb625d88f543d27d5d9e542 H Kunio-kun no Nekketsu Soccer League - 340c0dc4d29883152e31a79aa5477b851dbdfeb2 H Kunio-kun no Nekketsu Soccer League - Striker (Hack) NES d39199f9c1550add08c12d5a13bbb59fcb6b3b2c H Kunio-kun no Nekketsu Soccer League - Super Maltreatment Edition (Hack) NES 4f78b071b96bf1b2c5e8098bf1529b1b333e246d H Kunio-kun no Nekketsu Soccer League - Super Striker (Hack) NES -f407cdd3308b4dd5ab48c74db33a8879e880f588 H Kunio-kun no Nekketsu Soccer League - To Change Skill & Hit Keeper (Hack) NES +f407cdd3308b4dd5ab48c74db33a8879e880f588 H Kunio-kun no Nekketsu Soccer League - To Change Skill & Hit Keeper (Hack) NES 3ca8ef95f367374000aa14223b7c0fd746a7f584 H Kunio-kun no Nekketsu Soccer League - TT (Hack) NES d64b96f6171876119a5af8bf0ead7e879ed8770d H Kunio-kun no Nekketsu Soccer League - Twin Shot by altinfener38 (Hack) NES e45275579fd75471bd6c2f8ce8980c7bd6b907ab H Kunio-kun no Nekketsu Soccer League by oktucu (110806) (Hack) NES @@ -10272,7 +10272,7 @@ e6226a1bdf7c304438f4444df242f5ab5b4a1f67 B Lagrange Point (J) [b1][o1] NES ab6818c5e75516264d3a285ecbec5a4884683612 B Lagrange Point (J) [b1][t1] NES 65557407307ca0313775510120b9e8b09f08e860 C Lagrange Point (J) [t1] NES cc44c4f1b8f8075e428389cde3b2c3ee583942e2 U Lair's Secret (Unl) NES -bce119365efcbcab4bc03f7dc4f6dae5514ac172 H Lam by darkdata (Milk & Nuts Hack) NES +bce119365efcbcab4bc03f7dc4f6dae5514ac172 H Lam by darkdata (Milk & Nuts Hack) NES 6a0005e1bfd16f99cc79766e543dc624248d6cf8 U LAN Master bu shiru (PD) (2011-06-10) NES 81763892417f2b2a89bfbac83b240ef5da322369 U LAN Master by shiru (PD) NES 62fac07016d534852c9da61c060e8bd19ba5e6f0 G Laser Invasion (U) [!] NES @@ -10339,7 +10339,7 @@ a86fb55799df29a70132e35ba305dad820068022 T Legend of Kage, The (U) [T+Rus_Shedev f2755fe982e51a7f31a237aee03b91d364795629 H Legend of Prince Valiant, The (E) [hM04] NES 773fefddc1a15ab045bc0e23151bf5d157e98bc5 C Legend of Prince Valiant, The (E) [t1] NES 60bf4889b5b99b7441b91b4c9f4e8820bc4d0c7a U Legend of Robin Hood, The (U) (Prototype) NES -961e2890880a2185fd21ca25b6874c5d6ffcc6b8 H Legend of Sean, The (Master Chu & The Drunkard Hu Hack) NES +961e2890880a2185fd21ca25b6874c5d6ffcc6b8 H Legend of Sean, The (Master Chu & The Drunkard Hu Hack) NES ee3a7feabc22fa45256416681496626493b7a2e9 H Legend of Super Pikachu Bros 3 (SMB3 Hack) NES 2cc6cc45fa63f9354acd4f6b9d9deadfa88900c8 U Legend of the Black Shawarma Medley (Music Demo) by Snowbro (PD) NES 1d195beeb4b3edbf8d1d53df8f7b756ad77890cf H Legend of the Blob Bros. 2 V1.0 by BMF54123 (SMB2 Hack) NES @@ -10700,7 +10700,7 @@ e1308b338c2b75bb5674547312d445cadcafa40c U Luan Shi San Guo (Ch) NES 7ed2f88638929b7e81a93510e19560ce0f4decf5 H Luigi and the Christmas Quest (Final) (SMB1 Hack) NES f880b618845829fe41d313d7386bea4545a97246 H Luigi and the Christmas Quest (SMB1 Hack) [a1] NES fcd6b2a1d32aca07ff8a1caa4a7e7ab09f8f243d H Luigi and the Christmas Quest (SMB1 Hack) NES -8fc67b2f8613c711def655519a390b41f5614ce0 H Luigi and the New Quest (Level & Graphics Patch) (SMB1 Hack) NES +8fc67b2f8613c711def655519a390b41f5614ce0 H Luigi and the New Quest (Level & Graphics Patch) (SMB1 Hack) NES 76515328e14754247618e9aed6cac87a49a2e494 H Luigi and the New Quest (New Level Patch) (SMB1 Hack) NES 56bd3d597f4024ed558e34c5fa1e7dbee4c7f63d H Luigi and the New Quest (Partial Levels Patch) (SMB1 Hack) NES b38c3b1d8bddf46e382ebfc8b13248214ba081a8 H Luigi and the New Quest (SMB1 Hack) [a1] NES @@ -10751,10 +10751,10 @@ c8e128a54bf9aba9d9dd0f28a45f34e443ff0cdc T Lupin Sansei - Pandora no Isan (J) [T 1d1f04e0bed7113be71d78eedc4cbd2a92bad32e C Lupin Sansei - Pandora no Isan (J) [t1] NES 18d0afcb194f5a7eca06efac29473fa22a499014 C Lupin Sansei - Pandora no Isan (J) [t2] NES 96edd908d86043c856d189c3db7a95998771aae6 H M Mario (SMB1 Hack) NES -e0064546070f426da5fdc9d05a1affa74d955882 U M&M Heroes (Ch) (Wxn) NES -7bc4d849ea854df4ec39bc632d38ab888cfa30a0 H M&M Heroes (Unl) [f1] NES -f63e163ed15f5bd977c0132679cb5f5a7f23f45a T M&M Heroes (Unl) [T+Rus_FedX IV] NES -a7ab98cadb51b86837fc9a71e72619c0d27a9a9d U M&M Heroes (Unl) NES +e0064546070f426da5fdc9d05a1affa74d955882 U M&M Heroes (Ch) (Wxn) NES +7bc4d849ea854df4ec39bc632d38ab888cfa30a0 H M&M Heroes (Unl) [f1] NES +f63e163ed15f5bd977c0132679cb5f5a7f23f45a T M&M Heroes (Unl) [T+Rus_FedX IV] NES +a7ab98cadb51b86837fc9a71e72619c0d27a9a9d U M&M Heroes (Unl) NES 9f026896275121d4cfb8ac34bd9e0cba96372508 U M-Day (Ch) (Wxn) NES afac4a56c2cf511e3cf983e16890adbf2f896bfd G M.C Kids (U) (Prototype) [!] NES 0fabf7ee8ed5bdc855daa5b16c49efc4b94497ba G M.C Kids (U) [!] NES @@ -10778,7 +10778,7 @@ deade5ae2b4f0948763b7e77b6561dfed5fdc8ff B M.U.S.C.L.E. (U) [o3] NES 0579081f3d7c4b5b756351bff82fd42f9e1eb54e B M.U.S.C.L.E. (U) [o4] NES 0414719a4ad314926d8d9b9fc8461d7303501ba0 B M.U.S.C.L.E. (U) [o5] NES 4d7786106e6e550d993f20319428f27cae6ba998 U M82 Game Selectable Working Product Display (E) NES -a58de11d0f58995d642fc3d556b3b554c3cb6493 U Ma Bu Mi Zhen & Qu Wei Cheng Yu Wu (Ch) NES +a58de11d0f58995d642fc3d556b3b554c3cb6493 U Ma Bu Mi Zhen & Qu Wei Cheng Yu Wu (Ch) NES 6b1d4795428ca175d83abcf06b4d6def3d7b9e11 B Ma Li 12 (Yoshi no Cookie) [p1] NES 7c9daf77487a885367666c4f9dbc7714b0ce1439 B Ma Li 12 (Yoshi no Cookie) [p1][o1] NES 39fcdb90ab5fe745eeebef591127dae761b02e81 U Mac OS Demo (Large) by Chris Covell (PD) NES @@ -10994,9 +10994,9 @@ b8eabd4dfe1710ea8d74a990a2701ccda27d07d2 B Making Love (Battle City Hack) [o1] N 0792c8302caf2641f3644146500d669bd21ef0d1 T Making Love (Battle City Hack) [T+Rus_Cool-Spot][a1] NES 6efde8835d2f8c34875e24de8cdc353452d9f9b5 H Making Love (Battle City Hack) NES e5c0edeec0c4c45e4cfcf0ff0d48304ee90c215c H Male Lover Eon Man (Time Diver Eon Man Hack) NES -f76c5b3598b7869e57f438b861b6a198ef59a80e B Maluex (Nuts & Milk Hack) [o1] NES -544a5ed93d8ec8c34822f827126961377087e58d B Maluex (Nuts & Milk Hack) [o2] NES -4f26475c03365c125f9f9590bced09e3158f6a9a H Maluex (Nuts & Milk Hack) NES +f76c5b3598b7869e57f438b861b6a198ef59a80e B Maluex (Nuts & Milk Hack) [o1] NES +544a5ed93d8ec8c34822f827126961377087e58d B Maluex (Nuts & Milk Hack) [o2] NES +4f26475c03365c125f9f9590bced09e3158f6a9a H Maluex (Nuts & Milk Hack) NES 76edf6482110b1dcfebb2c57e00993ad80cc7878 U Mandelbrot (PD) NES 3764bbd627f1a6b5790712019e06efa3a011d4e4 U Manhole by KZ-S (PD) [a1] NES b01b5adc58b6b81cae093e3ad43ad6fc4065237a U Manhole by KZ-S (PD) NES @@ -11072,8 +11072,8 @@ fca0c2983073ae17f1034077b0769e64dc33e179 B Marble Madness (U) [o1] NES 14565b90be871acba746be154cdfc254c9c79193 H Maria's Golf (Golf Hack) NES 038103f080bd837c11b8e82d03a57909006e2d4f H Marilunker (Spelunker Hack) NES a86de28534e8d6b80a4e193a34073a6a58c30626 H Marilunker by Tsurumidou (Spelunker Hack) NES -9ca35258a3637b43c45ef7f17a75c7b32ea969a8 G Mario & Yoshi (E) [!] NES -5f69d6fe6299cd09e359f0db360495a40f8359fa H Mario + Toad (Nuts & Milk Hack) NES +9ca35258a3637b43c45ef7f17a75c7b32ea969a8 G Mario & Yoshi (E) [!] NES +5f69d6fe6299cd09e359f0db360495a40f8359fa H Mario + Toad (Nuts & Milk Hack) NES 0c2494b25620c81cf4a514ed9659429e59b4c6ef H Mario 1337 (SMB1 Hack) NES ff70fcbdf643b0c71cb2f8c170f315a4af755531 B Mario 16 (1993) (Unl) [b1] NES 3a6f026690bbf5f13b1066e5b100f783a6928c8b B Mario 16 (1993) (Unl) [o1] NES @@ -11096,8 +11096,8 @@ e972a5ee5b0f8f68a08106bce39ae1c82d34e1d2 H Mario a la Caza del Tesoro V1.0 Spani 69b006cd318393e610e77ee22fd29ee4f10f0fda H Mario Adventure Island (Takahashi Meijin no Bouken Shima Hack) NES 34edbd53301273a8a31f1fade92003bf197d2926 T Mario and Goombas by Cool-Spot (Mappy Hack) [T+Rus_Cool-Spot] NES bc2eafe7d8c3b63595ecb75f19760e4ab5634e56 H Mario and Goombas by Cool-Spot (Mappy Hack) NES -fdd6a65ea316ec531c0f96804bd02941add01b44 T Mario and Luigi (Nuts & Milk Hack) [T+Rus_Cool-Spot] NES -01b81f8e7ba17db3298822035435cd0c1ab87de6 H Mario and Luigi (Nuts & Milk Hack) NES +fdd6a65ea316ec531c0f96804bd02941add01b44 T Mario and Luigi (Nuts & Milk Hack) [T+Rus_Cool-Spot] NES +01b81f8e7ba17db3298822035435cd0c1ab87de6 H Mario and Luigi (Nuts & Milk Hack) NES e9bd0d304d265fa5a25c47cfed2d847605d3de76 H Mario Bomb Jack (Mighty Bomb Jack Hack) NES ef30e7d464a79dd4482b0da82c41504f46e477d2 H Mario Bros in the Clouds (SMB1 Hack) NES 1bf3152946f6b697dd80aa9ba5b16bddab8ac0c2 G Mario Bros. (E) (PRG1) [!] NES @@ -11235,7 +11235,7 @@ c90404b3c08265dfbc0677e7eb8a91eda8cf9a19 H Mario Runner by Y.Project (Championsh 441f1355cc8d159de0f82bd5471b5e25efac9448 H Mario Satanic Freak Bros 2 (SMB2 Hack) NES 35cc22c2861cb67e3feee8bb10bcc22bf1c611e3 H Mario Spy vs Spy (Spy vs Spy Hack) NES 38550a3ca3fc7f3263b26758ed37a9e3ba7e87fe B Mario Tails (SMB1 Hack) [b1] NES -fcd488c8f40e2956b1030d2b0e9ca4565694a5be H Mario Tank & Sub (SMB1 Hack) NES +fcd488c8f40e2956b1030d2b0e9ca4565694a5be H Mario Tank & Sub (SMB1 Hack) NES 764d9f6c2d2f9130c8de46fe9a0a408d3e96b13e H Mario Tokes A Doobie (SMB1 Hack) NES 2b5135b41e78505abf5489a2ab52faefee4a65fa H Mario Tower (SMB1 Hack) NES 48b8f691f3d73d8d2aa35c2f1e9c869c97d8b97b H Mario vs Monkey by Hax0r Kyo (Mario Bros Hack) NES @@ -11310,11 +11310,11 @@ a2b6008b8c2a65cd6e2312614505c463e1f4615f B Mashou (J) [hM02][b1] NES 1f1b2f43de9c29e41a9514a6019978529a9bfac8 C Mashou (J) [t1] NES 1d9757ab82c6e1095bc88765e3ff012d0ad7375a U Masmix v0.06, The by Wojciech Andralojc (PD) NES 2a493dcfeeb0d7f928cb8862b8e8be295ed3c685 U Master Chess (Ch) (Wxn) NES -62918362f30e4840ed4e7719339520cfefc92a2a G Master Chu & The Drunkard Hu (Color Dreams) [!] NES -569065844ea9f5c29fb80becef94190358dc9fe3 B Master Chu & The Drunkard Hu (Color Dreams) [o1] NES -de04b54e6bb4bcfc3cb8a40669cf52499c51ff89 U Master Chu & The Drunkard Hu (Joy Van) NES -9c98deede6eaa1c352d75c9cd8d1ca67ba16f77a G Master Chu & The Drunkard Hu (Sachen) [!] NES -08a2fbefe2e5543b9ef3e8342009456d67500884 G Master Chu & The Drunkard Hu (Sachen) [U][!].unf NES +62918362f30e4840ed4e7719339520cfefc92a2a G Master Chu & The Drunkard Hu (Color Dreams) [!] NES +569065844ea9f5c29fb80becef94190358dc9fe3 B Master Chu & The Drunkard Hu (Color Dreams) [o1] NES +de04b54e6bb4bcfc3cb8a40669cf52499c51ff89 U Master Chu & The Drunkard Hu (Joy Van) NES +9c98deede6eaa1c352d75c9cd8d1ca67ba16f77a G Master Chu & The Drunkard Hu (Sachen) [!] NES +08a2fbefe2e5543b9ef3e8342009456d67500884 G Master Chu & The Drunkard Hu (Sachen) [U][!].unf NES 00e58c05c1ddc011418b762e203283ba61510549 U Master Fighter 3 (Unl) [a1] NES 0aeb922bd4bfe12fde656729e0ee0058276b7a95 U Master Fighter 3 (Unl) NES 89ec66a8c33722a5bd1120bc69393b237e72de03 G Master Fighter II (Unl) (UT1374 PCB) [!] NES @@ -11785,11 +11785,11 @@ b64e5757c43c4270c7ec4656823b3dd7f506a31c U Metal Max (J) (VC) NES 9a9401b7e009d560978053035ba854484258453f H Metal Max - Shining Strengthened Edition (Hack) NES f0ded676241e773791a3209281b6290ca6c2a115 H Metal Max by ZTOUYIA (090214) (Hack) NES 7af64b80c8857dba498a520298ab438b92a27a0d H Metal Max Night Edition by MISAKA KEN (Hack) NES -491f6a151cb43c794f1e0984e3645e946b5f5600 G Metal Mech - Man & Machine (U) [!] NES -c46b547aaa2295d6e6daa978b971a47a1ea12906 B Metal Mech - Man & Machine (U) [b1] NES -b5806e8504f79d790fc67bc31e6d2ccca2990011 B Metal Mech - Man & Machine (U) [o1] NES -3e06e7b5db6da401ec312ab490b7069e8624a62f B Metal Mech - Man & Machine (U) [o2] NES -079f970b54f70e2144b5c9f197331f08a46b9aa2 B Metal Mech - Man & Machine (U) [o3] NES +491f6a151cb43c794f1e0984e3645e946b5f5600 G Metal Mech - Man & Machine (U) [!] NES +c46b547aaa2295d6e6daa978b971a47a1ea12906 B Metal Mech - Man & Machine (U) [b1] NES +b5806e8504f79d790fc67bc31e6d2ccca2990011 B Metal Mech - Man & Machine (U) [o1] NES +3e06e7b5db6da401ec312ab490b7069e8624a62f B Metal Mech - Man & Machine (U) [o2] NES +079f970b54f70e2144b5c9f197331f08a46b9aa2 B Metal Mech - Man & Machine (U) [o3] NES 5aa98fc076e38002f08bfb3130cca0fbbe03058f U Metal Slader Glory (J) (VC) NES a62908e4873cf88f4a3c571c2b06d3d7c51e7450 G Metal Slader Glory (J) [!] NES c62cc944e7cfac05ac9b99170dadfe1d8b5a3965 B Metal Slader Glory (J) [b1] NES @@ -11828,7 +11828,7 @@ b0e1e0cd36b40aab2f9fecf057098abdad718cd3 T Metroid (U) [T+Fre_Terminus] NES 6170e1db74b46a77ad701c0ec87bd129adccd037 T Metroid (U) [T+Spa050_PaladinKnights] NES 574117fa7c66279a1373e25d792a40f45286fce2 T Metroid (U) [T+Spa100b_ereza] NES 0d589c18ee0e59b7c7d17d7b6a698dcd968eb56e T Metroid (U) [T+Swe1.0_TheTranslator] NES -180d37be77a6bcbb5a572364ab214defe84ca0b8 H Metroid - Unused GFX Tiles & 99 Energy Units by Grond (Metroid Hack) NES +180d37be77a6bcbb5a572364ab214defe84ca0b8 H Metroid - Unused GFX Tiles & 99 Energy Units by Grond (Metroid Hack) NES e7980c189177ab863b254a2a7a9683440557e3c0 H Metroid - Wart's Invasion (Metroid Hack) NES fe72d83deeb11b4579f7b07fb2e231137af396f0 H Metroid - Zebian Illusion (Metroid Hack) NES 0be24e45e1ef766d67701aae299e1315c66e0979 H Metroid 2000 (Metroid Hack) NES @@ -11994,7 +11994,7 @@ b47d159f82fe0ec2b458ead44337255f387f5179 C Mighty Final Fight (U) [t1] NES 855f819f6745c64532be84cb771dcda43bed5abc C Mighty Final Fight (U) [t4] NES c54abb5f91ff22e164510adb94be037661ffe0ee C Mighty Final Fight (U) [t5] NES b63f9117a0d864ecf028c79cf0b759d02ca12dc7 H Mighty Final Fight - Rock (Hack) NES -da6b671f63e0884a06edc4ffab18e80ef3815e5c H Mighty Final Fight - Skill & Enemies Changed (Hack) NES +da6b671f63e0884a06edc4ffab18e80ef3815e5c H Mighty Final Fight - Skill & Enemies Changed (Hack) NES 706a4d92a6f892f50768216222deb0943cf1c8fb H Mikamari 1 (SMB1 Hack) NES 291ecdfa63678f47489874c3b68bdbfe47a8651c H Mikamari 2 (SMB1 Hack) NES 4eaa8f7c55b779ffd5310062d0f6012b77fcb0d2 H Mikamari 3 (SMB1 Hack) NES @@ -12469,7 +12469,7 @@ e9ebfd1a44a8b62ab774e421770f0caee34c34d4 U Mr Brownstone by Snowbro (PD) NES 363c095b7d6b0b035365d55bbcd822c911adecf2 H Mr. Happyface (Ms. Pac-Man Hack) [a1] NES 141991d10b5c2424d44bc2e8dfd62cd528e710ae H Mr. Happyface (Ms. Pac-Man Hack) NES b5bf9531fe5900dc946e92114f7983088bfe232f H Mr. Men (Dig Dug II Hack) NES -141f8ddc64afb5f28a51b7265268ef76c1f11f4a H Mr. Pac-Man by Dave Augusta & Googie (v1.0) (Ms. Pac-Man Hack) NES +141f8ddc64afb5f28a51b7265268ef76c1f11f4a H Mr. Pac-Man by Dave Augusta & Googie (v1.0) (Ms. Pac-Man Hack) NES 7893f168fd56adad3546b5db267b286ff659a349 H Mr. Sandman! by The Eadernator (SMB1 Hack) NES 697d523d2db7f1ebdcf91bf501422c6a033fbd44 B Mr. Saturn's Dragon Quest v1.21 (Dragon Warrior PRG0 Hack) [o1] NES 93c5f1cb016f46ba5e1033997a8cd8bfdfa43e89 H Mr. Saturn's Dragon Quest v1.21 (Dragon Warrior PRG0 Hack) NES @@ -12682,7 +12682,7 @@ cecd61c0a2321d44500bee546e04e382259b93f7 T Nekketsu! Street Basket - Ganbare Dun 13e673bd83bff5923729e259c42fed0995d989be T Nekketsu! Street Basket - Ganbare Dunk Heroes (J) [T-Eng.50] NES 7e129fa870424cbc23f274f373ae0e389c7d127f U Nekketsu! Street Basket - Ganbare Dunk Heroes (J) NES ffd1705e5919b87d5a26d49a8f48d35d57497796 H Nekketsu! Street Basket - Ganbare Dunk Heroes - Spirit Edition (Hack) NES -f5f295588ef93bb1ac44d16df184ac67ab678167 H Nekketsu! Street Basket - Ganbare Dunk Heroes by AXI&AHE (v0.9) (Hack) NES +f5f295588ef93bb1ac44d16df184ac67ab678167 H Nekketsu! Street Basket - Ganbare Dunk Heroes by AXI&AHE (v0.9) (Hack) NES 6a50ac4d84116cd39b57531a44f6509ef151829a H Nekketsu! Street Basket - Ganbare Dunk Heroes by D.S.ghtMaster+KRIZAL (Hack) NES fbfa57623728465fd3c2582c8fc5930430502da9 H Nekketsu! Street Basket - Ganbare Dunk Heroes by PU (100426) (Hack) NES fb0a992bc148de44d82277b5cf4e3aba40ad6e38 G Nemo - Pajama Hero (J) [!] NES @@ -13233,20 +13233,20 @@ ca1f630cfcf80e817e6e395b5bd52497f1604e63 B Nobunaga's Ambition 2 (U) [o1] NES a8fd3c5c20777b94d1204145104f72a93f83d225 U Nomolos - Storming the Catsle Demo (PD) NES 9c5d4c2654998e874b3eda5e3f0af8b5e353575e U Nong Chang Xiao Jing Ling (NJ025) (Ch) NES 4e48b65b60f94a054b865f9e1cb3fd47cf9b4949 H Normal (Lolo1 Hack) NES -766a602e239895343819c2980ecd296da14613e1 G North & South (E) [!] NES -3c1f1f3ba8ce62899c2153116c3bd73ae058e554 T North & South (E) [T+FreFinal_Generation IX] NES -023b6b9ac517453541324e3cca279588b94d5016 G North & South (J) [!] NES -2a7f6052219e8ed69f307b8eb3d724fdded74ae1 G North & South (U) [!] NES -da1d5fb3d856cee918a57e510a93d32e33af2843 B North & South (U) [b1] NES -f2f1257a99f9fe3788851e62577798b7cb400cfb B North & South (U) [b1][o1] NES -58346ef19200fce9be100cc21284f31b6a1dad61 B North & South (U) [b1][o2] NES -2342eec6311f597ea24bf418a9ff26030b5edd43 B North & South (U) [b2] NES -7df0cc39d279659e4df9319aa74e24152a4db884 B North & South (U) [b3] NES -2a08ba115a2ee1b6a7f07829bde5049dde11ec6c B North & South (U) [b4] NES -7dee9233fc66d18c92ac477965ba3f15892bda78 B North & South (U) [b5] NES -f7ab568fd4b65dfcc89aeba81e7b127740967700 B North & South (U) [b6] NES -1a38e957fc2953c987ea4f129f17edc6adc133f6 B North & South (U) [b7] NES -53cbaf5517f6aba9a5eeba311ddfa03680898ac0 T North & South (U) [T+Swe1.0_TheTranslator] NES +766a602e239895343819c2980ecd296da14613e1 G North & South (E) [!] NES +3c1f1f3ba8ce62899c2153116c3bd73ae058e554 T North & South (E) [T+FreFinal_Generation IX] NES +023b6b9ac517453541324e3cca279588b94d5016 G North & South (J) [!] NES +2a7f6052219e8ed69f307b8eb3d724fdded74ae1 G North & South (U) [!] NES +da1d5fb3d856cee918a57e510a93d32e33af2843 B North & South (U) [b1] NES +f2f1257a99f9fe3788851e62577798b7cb400cfb B North & South (U) [b1][o1] NES +58346ef19200fce9be100cc21284f31b6a1dad61 B North & South (U) [b1][o2] NES +2342eec6311f597ea24bf418a9ff26030b5edd43 B North & South (U) [b2] NES +7df0cc39d279659e4df9319aa74e24152a4db884 B North & South (U) [b3] NES +2a08ba115a2ee1b6a7f07829bde5049dde11ec6c B North & South (U) [b4] NES +7dee9233fc66d18c92ac477965ba3f15892bda78 B North & South (U) [b5] NES +f7ab568fd4b65dfcc89aeba81e7b127740967700 B North & South (U) [b6] NES +1a38e957fc2953c987ea4f129f17edc6adc133f6 B North & South (U) [b7] NES +53cbaf5517f6aba9a5eeba311ddfa03680898ac0 T North & South (U) [T+Swe1.0_TheTranslator] NES f25301c5586eaf0bd53f95cbf264a0e4207731e2 U Nothing Demo (PD) NES 7b3ff58b8684313b775fcffcdd24347060be5d38 G Novel Diamond 999999-in-1 [U][p1][!].unf NES 077c8e387d2c605e4a1fb3b7a3b8e743feaffc64 U NROM Template 0.01 by Damian Yerrick (2011) (PD) NES @@ -13278,28 +13278,28 @@ f67c0b6e6386ab3672759b7e1edbca7cfeecf4d5 H Nude Punch Out (Punch-Out!! Hack) NES 9072be68ee2eaa942c474a7eba228640d7693ba9 U Nuevo Tipo de Computadora (Game Star) NES 44b74d6a242b6446fa5a937884fb5a01da15a1cb U Nullsleep - Kuribos Requiem (PD) NES 15bb5ad31ef26025bb744e53e238f9880c90b9bd U NumberGuess by Vincent van der Leun (PD) NES -cca97fba72ca56809dd216618f5962eb6ea2f1aa G Nuts & Milk (J) [!] NES -38ad30d95aaa4376b282f98efd89df92846bb940 B Nuts & Milk (J) [o1] NES -50ce8cec6085dd639292ae274bb5e913c9e1fc24 B Nuts & Milk (J) [o2] NES -73b1aeb8c794ae7c1f662411c34d7ff11b362369 B Nuts & Milk (J) [p1] NES -c01df7f32a0724e2258786a114f948e5d5ec7963 B Nuts & Milk (J) [p1][o1] NES -e5a0ad38498935f360997c0925b539014618aa8a T Nuts & Milk (J) [T+Bra_JM-trad] NES -8a5022c666bab63216563f76ca202125af6cb0ba T Nuts & Milk (J) [T+Chi_MS emumax] NES -f8c39e1b575a1ff6775329bbca4b723059b42ed0 T Nuts & Milk (J) [T+FreFinal_ks151] NES -7b84df69272bc4e29327c037ffd2d3d129df39be T Nuts & Milk (J) [T+Rus_CARI] NES -4a7726cbad59730bf05715e6549ddd0616637a1b T Nuts & Milk (J) [T+Rus_Cool-Spot] NES -4929bc380983b6b5cd0602c45b1964381e8ac170 T Nuts & Milk (J) [T+Rus_Mario Soft] NES -bcff20a94a6d026ac3d061e90599a1c881ef0a1c T Nuts & Milk (J) [T+Rus_Multisoft] NES -5a93e79325dd52cceb312ad84ced5b0c055cd9b6 T Nuts & Milk (J) [T-Chi_MS emumax] NES -5cccfd9cd3b6ab918003e46c8faf210255d5736a T Nuts & Milk (J) [T-Chi_MS emumax][a1] NES -b3d5d4f11b7d68d82c8ca5240f8239f930b1c688 T Nuts & Milk (J) [T-Chi_MS emumax][a2] NES -e878b5c62b83cc13acf466480bc037c5d99b77e7 T Nuts & Milk (J) [t1][T+Rus_Cool-Spot] NES -9a229b126f0573659448bba903a13048dd21c99a C Nuts & Milk (J) [t2] (9 Lives) NES -d8289a152855628af82aafefe5e3e9ed765d6523 C Nuts & Milk (J) [t3] (50 Lives) NES -573df023388af04977b8ffd787987e66ea16efc6 C Nuts & Milk (J) [t4] (100 Lives) NES -0b00c2eef9ed256599f9584b0ba366f838065fec B Nuts & Milk by PE (Hack) [o1] NES -bcff4b0d1d7dfea58018434e6a9aca29568a7844 T Nuts & Milk by PE (Hack) [T+Rus_Cool-Spot] NES -8cdde663a326c50ab9d8cb434628dcd5490f3797 H Nuts & Milk by PE (Hack) NES +cca97fba72ca56809dd216618f5962eb6ea2f1aa G Nuts & Milk (J) [!] NES +38ad30d95aaa4376b282f98efd89df92846bb940 B Nuts & Milk (J) [o1] NES +50ce8cec6085dd639292ae274bb5e913c9e1fc24 B Nuts & Milk (J) [o2] NES +73b1aeb8c794ae7c1f662411c34d7ff11b362369 B Nuts & Milk (J) [p1] NES +c01df7f32a0724e2258786a114f948e5d5ec7963 B Nuts & Milk (J) [p1][o1] NES +e5a0ad38498935f360997c0925b539014618aa8a T Nuts & Milk (J) [T+Bra_JM-trad] NES +8a5022c666bab63216563f76ca202125af6cb0ba T Nuts & Milk (J) [T+Chi_MS emumax] NES +f8c39e1b575a1ff6775329bbca4b723059b42ed0 T Nuts & Milk (J) [T+FreFinal_ks151] NES +7b84df69272bc4e29327c037ffd2d3d129df39be T Nuts & Milk (J) [T+Rus_CARI] NES +4a7726cbad59730bf05715e6549ddd0616637a1b T Nuts & Milk (J) [T+Rus_Cool-Spot] NES +4929bc380983b6b5cd0602c45b1964381e8ac170 T Nuts & Milk (J) [T+Rus_Mario Soft] NES +bcff20a94a6d026ac3d061e90599a1c881ef0a1c T Nuts & Milk (J) [T+Rus_Multisoft] NES +5a93e79325dd52cceb312ad84ced5b0c055cd9b6 T Nuts & Milk (J) [T-Chi_MS emumax] NES +5cccfd9cd3b6ab918003e46c8faf210255d5736a T Nuts & Milk (J) [T-Chi_MS emumax][a1] NES +b3d5d4f11b7d68d82c8ca5240f8239f930b1c688 T Nuts & Milk (J) [T-Chi_MS emumax][a2] NES +e878b5c62b83cc13acf466480bc037c5d99b77e7 T Nuts & Milk (J) [t1][T+Rus_Cool-Spot] NES +9a229b126f0573659448bba903a13048dd21c99a C Nuts & Milk (J) [t2] (9 Lives) NES +d8289a152855628af82aafefe5e3e9ed765d6523 C Nuts & Milk (J) [t3] (50 Lives) NES +573df023388af04977b8ffd787987e66ea16efc6 C Nuts & Milk (J) [t4] (100 Lives) NES +0b00c2eef9ed256599f9584b0ba366f838065fec B Nuts & Milk by PE (Hack) [o1] NES +bcff4b0d1d7dfea58018434e6a9aca29568a7844 T Nuts & Milk by PE (Hack) [T+Rus_Cool-Spot] NES +8cdde663a326c50ab9d8cb434628dcd5490f3797 H Nuts & Milk by PE (Hack) NES 4381f42f7b69e00e4d44ba643331f0b8d4d6af12 U Nyancat V1 by DerekB (PD) NES 486b47656c93db07fae5a8749278414531efb6ce U Nyancat V2 by DerekB (PD) NES ab7e39224ff304c4619329c026cf9c079002921e H Oaty Invaders by Pope Hentai (Space Invaders Hack) NES @@ -14127,14 +14127,14 @@ fad06695ceb4520547470a3df1a7b5c561d056ca U Pattern Table Pixel-Flickering Demo F f052c4486726c3abac420bd6f411fbecd551d4ab H PCGC Tank Chinese (Battle City Hack) NES c1df3c306ed45974b45c4832f72e93382f38a0e8 U PCM Demo (PD) [a1] NES 72f4b89acfb66e7abeafc894507b8c8b8f3d4225 U PCM Demo (PD) NES -9d75e5dcaa20e302b0820331d0995d1cb9b4c50d H Peach & Daisy - The Royal Quest (Alpha) (SMB1 Hack) [a1] NES -83e35177b4c0cbcb92d6ab975a2d876964eba303 H Peach & Daisy - The Royal Quest (Alpha) (SMB1 Hack) NES -84701b4567b09170bdb5dd7eb0a0fd54afa64a50 H Peach & Daisy and The Royal Games (SMB1 Hack) NES -8559c0dc7d22d61b77306d0f270e0bb3e27ca620 H Peach & Daisy and The Royal Games with Hacked Music (SMB1 Hack) NES -2488999a27d64decba8545ad41b6884cf8b02fac H Peach & Daisy in The Ultimate Quest (SMB3 PRG0 Hack) NES -91ffa269fa5ffb549e9a12cc14bf7574b95b2226 H Peach & Daisy in The Ultimate Quest (SMB3 PRG1 Hack) [a1] NES -6ac4ce8f754326ce7d6e1bc33f90528eeebd82cd H Peach & Daisy in The Ultimate Quest (SMB3 PRG1 Hack) NES -1218041ff94ed80d91b5b83f760bd78645791233 H Peach & Daisy in The Ultimate Quest V2b (SMB3 PRG1 Hack) NES +9d75e5dcaa20e302b0820331d0995d1cb9b4c50d H Peach & Daisy - The Royal Quest (Alpha) (SMB1 Hack) [a1] NES +83e35177b4c0cbcb92d6ab975a2d876964eba303 H Peach & Daisy - The Royal Quest (Alpha) (SMB1 Hack) NES +84701b4567b09170bdb5dd7eb0a0fd54afa64a50 H Peach & Daisy and The Royal Games (SMB1 Hack) NES +8559c0dc7d22d61b77306d0f270e0bb3e27ca620 H Peach & Daisy and The Royal Games with Hacked Music (SMB1 Hack) NES +2488999a27d64decba8545ad41b6884cf8b02fac H Peach & Daisy in The Ultimate Quest (SMB3 PRG0 Hack) NES +91ffa269fa5ffb549e9a12cc14bf7574b95b2226 H Peach & Daisy in The Ultimate Quest (SMB3 PRG1 Hack) [a1] NES +6ac4ce8f754326ce7d6e1bc33f90528eeebd82cd H Peach & Daisy in The Ultimate Quest (SMB3 PRG1 Hack) NES +1218041ff94ed80d91b5b83f760bd78645791233 H Peach & Daisy in The Ultimate Quest V2b (SMB3 PRG1 Hack) NES a3714d4067896c3eafdc820fb75d72b2e9a44600 H Peach's Nightmare - No Mercy (Beta) (SMB1 Hack) NES 9485ea0fca9c569c50b12c1bbdaf58d188ebca3f H Peach's Nightmare - No Mercy (SMB1 Hack) NES c2f75c845b3ed54285153bf66cfa649ff9525931 H Peachy Mario by Mana (SMB1 Hack) NES @@ -14151,12 +14151,12 @@ f8d094394bb036ffb0d7f4c6572c876d481eaaec U Pegasus 5-in-1 (Golden Five) (Unl) NE 8bb6485cafa110f01e60da35ce5d537b886c5cc3 U Pegs by Sly Dog Studios (PD) NES 4d3d00d774ee6153d55878112c3aeeb48189b819 U Penalty Kick (Ch) (Wxn) NES cee202c3fbcc89608d6e333bdc290bd6224cc53e H Pencilvania (CV Hack) NES -f828bba945c4291586c9843a7bcff4400125cc88 U Penguin & Seal, The (Dung Dung No 1) (Sachen) (Ch) NES -eac74d9de2001baa8fa76e740f9866d612612e33 G Penguin & Seal, The (Sachen-HES) [!] NES -dab87920067b13c1252b47673ff078c882651ed0 B Penguin & Seal, The (Sachen-HES) [o1] NES -41994a3c8f15bfbba09fe48ce2f98b9691fbfd7b G Penguin & Seal, The (Sachen-HES) [U][!].unf NES +f828bba945c4291586c9843a7bcff4400125cc88 U Penguin & Seal, The (Dung Dung No 1) (Sachen) (Ch) NES +eac74d9de2001baa8fa76e740f9866d612612e33 G Penguin & Seal, The (Sachen-HES) [!] NES +dab87920067b13c1252b47673ff078c882651ed0 B Penguin & Seal, The (Sachen-HES) [o1] NES +41994a3c8f15bfbba09fe48ce2f98b9691fbfd7b G Penguin & Seal, The (Sachen-HES) [U][!].unf NES 74a1ae73ec743bc20f9959c3f4434b8c2a9b3cd5 U Penguin (Ch) (Wxn) NES -84e0889f31db8949d9e4281a6dc84350d5caef19 H Penguin (Nuts & Milk Hack) NES +84e0889f31db8949d9e4281a6dc84350d5caef19 H Penguin (Nuts & Milk Hack) NES 8226578f38034a45a2023d7340115149ed2d96bf H Penguin Shoot (Battle City Hack) NES 19f3aa482f2ed6f46d81fcb55960c9e56c039cf2 B Penguin-kun Wars (J) [b1] NES f04547d268c367e4bf42c47b2c15a7fa41a60ee7 B Penguin-kun Wars (J) [p1] NES @@ -14178,15 +14178,15 @@ ed96ab727ba734cda8f619ff171f5eeaf100c0f1 B Perfect Bowling (J) [o1] NES e2798f1b0f34fb4177b032ad37c6117632a2b8f7 G Pesterminator - The Western Exterminator (Color Dreams) [!] NES 6427975ec1a6c8eb2b44fbd23727ca4673dee6f1 B Pesterminator - The Western Exterminator (Color Dreams) [o1] NES ec5b7cea33ded1afa919a8e2d975ba25e7cb2d8e U Pet 4-in-1 (Unl) NES -faf1e63eaf03dba975d9f40cccbe446a71386ab2 G Peter Pan & The Pirates (U) [!] NES -bcf8aca930e0edfe72da7e836f121cce7ecfb0cd B Peter Pan & The Pirates (U) [b1] NES -0f71b02b1828d6fa3cf477b304e2e49c90333a40 B Peter Pan & The Pirates (U) [b2] NES -6f633431bcb0ec6a5d2883ea742c4281f6fe7351 B Peter Pan & The Pirates (U) [b3] NES -4596be40277f40d4c8c7546a25a08f912dbf7645 B Peter Pan & The Pirates (U) [o1] NES -acc8e6a5efee672e34b11ad2d699ba2adbe91770 B Peter Pan & The Pirates (U) [o2] NES -c51d1b51e599b5cf5743458ec7248c7653b461c2 B Peter Pan & The Pirates (U) [o3] NES -4eac15442ca9bc0ba7591e219e5d24176df1fa57 B Peter Pan & The Pirates (U) [o4] NES -93b0e1be6669692c19d51d35d4b8a31bdbf90573 C Peter Pan & The Pirates (U) [t1] NES +faf1e63eaf03dba975d9f40cccbe446a71386ab2 G Peter Pan & The Pirates (U) [!] NES +bcf8aca930e0edfe72da7e836f121cce7ecfb0cd B Peter Pan & The Pirates (U) [b1] NES +0f71b02b1828d6fa3cf477b304e2e49c90333a40 B Peter Pan & The Pirates (U) [b2] NES +6f633431bcb0ec6a5d2883ea742c4281f6fe7351 B Peter Pan & The Pirates (U) [b3] NES +4596be40277f40d4c8c7546a25a08f912dbf7645 B Peter Pan & The Pirates (U) [o1] NES +acc8e6a5efee672e34b11ad2d699ba2adbe91770 B Peter Pan & The Pirates (U) [o2] NES +c51d1b51e599b5cf5743458ec7248c7653b461c2 B Peter Pan & The Pirates (U) [o3] NES +4eac15442ca9bc0ba7591e219e5d24176df1fa57 B Peter Pan & The Pirates (U) [o4] NES +93b0e1be6669692c19d51d35d4b8a31bdbf90573 C Peter Pan & The Pirates (U) [t1] NES 1c6ebffde98f4afaba4032d68a6d2713d7ce6c01 H Phantasy Star The Hopeless (Air Fortress Hack) NES de763651d0d6ab670935b86f412e24d853f4a6d1 G Phantom Air Mission (E) [!] NES 373b6c4721e73142ea77be78439e741d6f86ad29 G Phantom Fighter (U) [!] NES @@ -14609,7 +14609,7 @@ e5c46255f9723358115d9a15142a1d2ed8e2123f U Powerpak Boot Loader V1.10 (PD) NES 99155590ec76d5541aff7e49ed3f998517130ac2 U Powerpak Boot Loader V1.11 (PD) NES 949f5a882611b0dd79333c5ba338e587d9fc986e U Powerpak NSF V1.20 (PD) NES 2e360a03a7b1e38dca4bf8d1153549b42a15bbf4 U Powerpak NSF V1.34 (PD) NES -9e470702ad1466d62245453dc8c6bb50b92c30c2 U PPU Palette RAM Access & Mirroring Test by Shay Green (15 Sep 2005) (PD) NES +9e470702ad1466d62245453dc8c6bb50b92c30c2 U PPU Palette RAM Access & Mirroring Test by Shay Green (15 Sep 2005) (PD) NES 4aad1a570833e0365592ac54ea13019dcd3d15e4 U PPU Timing V2 by Kevin Horton (PD) NES a376886d844d36e0a073d39fb343c3955fa908e5 U PR2_test (PD) NES 502923edd8e4efd7ff1b3c1eef302997ef3cff0b U PR8 NES Drum Synth v0.99 by Neil Baldwin (2011) (PD) NES @@ -14848,7 +14848,7 @@ d9492dd8f558b7db25e6fee6b95f008e9f7e6061 G Qix (U) [!] NES 84ef8209b0dc88bf9794e3373c35e64dd7bbf375 B Qix (U) [b2] NES 5411c6741a26912adcc0b5ec87813dca9cb77cce B Qix (U) [o1] NES 9440b56316739c25dd4a1470c36eb29fe41a7c11 H Quadruple Dragons (FF1 Hack) NES -05dbd91abd97b747b4470f1ea2109274714b6532 U Quadz by Michael Blain, Mark Schmit & Phil Yam (PD) NES +05dbd91abd97b747b4470f1ea2109274714b6532 U Quadz by Michael Blain, Mark Schmit & Phil Yam (PD) NES b053482f9ced7a1835fe961cc2373ff9521b74a2 U Quantum Disco Brothers by wAMMA (PD) (PAL) NES 93efdadedba42f4ec7a6cdf5634187ff38b66f91 G Quarter Back Scramble (J) [!] NES 10532a9c32080431fb5711ff42ef83187cf13639 G Quarth (J) [!] NES @@ -14941,7 +14941,7 @@ ecd19585722f8985b1e898dae23231aa2f75cdc5 H R.B.I. Baseball - Fantasy Baseball Le 949b63ad49546c59901f143d6331dcb0f290fdad H R.B.I. Baseball - Greats of College Baseball by fightonusc (Hack) NES 4599d3da7bf2968980000c6dc6ba9fc4a1bc67a0 H R.B.I. Baseball - Heaven Vs Hell by Britznoc (Hack) NES a9947effb0e21f56beb66b771dc8f62d06ac33ba H R.B.I. Baseball - Hunt for October '06 by Fryak (Hack) NES -da4bb9c9b18ff1e37c13852824b28ed5563dfb51 H R.B.I. Baseball - Japanese League & Negro League by DrNick (Hack) NES +da4bb9c9b18ff1e37c13852824b28ed5563dfb51 H R.B.I. Baseball - Japanese League & Negro League by DrNick (Hack) NES 2d94e410ca61c704bb319ea7e4fc8980765fe97e H R.B.I. Baseball - Mexican League 1979 - Northern Division by Cafetero (Hack) NES 79230b44c7a4429f96bba1bce5da3306d04cdbf0 H R.B.I. Baseball - Mexican League 1979 - Southern Division by Cafetero (Hack) NES cd415b9405d8ae4d52038ef086b017c498fdbc3d H R.B.I. Baseball - Same Team Fix (Hack) NES @@ -15037,7 +15037,7 @@ e875c71d507573f1c4559e7b8e797a5f05adc6d2 B Racket Attack (U) [b6] NES f55f2a192bc6d0927fedd445cb0515c5284467f2 B Racket Attack (U) [b8] NES 90716b3b6b4bb2bfb39f16248a257fe07557ba70 B Racket Attack (U) [o1] NES a2bc61169a2c21a68bc6d48441538e178bcb563b B Racket Attack (U) [o2] NES -b1197945728949126af2049e96d2433a7813a9da G Rackets & Rivals (E) [!] NES +b1197945728949126af2049e96d2433a7813a9da G Rackets & Rivals (E) [!] NES 66a0be81eb404220b2c519dcc3ca3432e883ac5a G Rad Racer (E) [!] NES cda80a93a5fa2622064056b5bc5e93eeb1c811de B Rad Racer (PC10) [b1] NES 7e0332479069fe729f44f61d8f337d228efc2a07 U Rad Racer (PC10) NES @@ -15202,12 +15202,12 @@ b00813ed6a0b4602b1384d6f7418052dc496dead G Reigen Doushi (J) [!] NES cb58b0109a4dc4c1f757035842da3b79744f4e9e B Remote Control (U) [o1] NES 068c2b2053974a7cad3e7a0637bc6354f32694e0 B Remote Control (U) [o2] NES 075b4a6af861726f45d0da61052769886a080e35 B Remote Control (U) [o3] NES -982f6bc24423ecc04199c8fa3f8d156c9af1a9b3 G Ren & Stimpy Show, The (U) [!] NES -07a8119abea8e83455f8aa45224418cc3af784a4 B Ren & Stimpy Show, The (U) [b1] NES -2476bf9fed478b6612c50be88448cd14cf694a17 B Ren & Stimpy Show, The (U) [b2] NES -ce765eceee5a44dbf2112f3e986c8cb0d11ac54d B Ren & Stimpy Show, The (U) [b3] NES -04b8201def7ae785ea69e592fa66f9a3f6838093 B Ren & Stimpy Show, The (U) [o1] NES -14c3f7970827f6f231f142396843966a0be4478f B Ren & Stimpy Show, The (U) [o2] NES +982f6bc24423ecc04199c8fa3f8d156c9af1a9b3 G Ren & Stimpy Show, The (U) [!] NES +07a8119abea8e83455f8aa45224418cc3af784a4 B Ren & Stimpy Show, The (U) [b1] NES +2476bf9fed478b6612c50be88448cd14cf694a17 B Ren & Stimpy Show, The (U) [b2] NES +ce765eceee5a44dbf2112f3e986c8cb0d11ac54d B Ren & Stimpy Show, The (U) [b3] NES +04b8201def7ae785ea69e592fa66f9a3f6838093 B Ren & Stimpy Show, The (U) [o1] NES +14c3f7970827f6f231f142396843966a0be4478f B Ren & Stimpy Show, The (U) [o2] NES c3e3e30408fda21ee2383e128b13e1b0f5650c32 U Renegade (U) (VC) NES bce48217b901a2bbd81fb89586661da6a442a179 G Renegade (U) [!] NES 3da61d5ef055b8fb8f0eb9605b7bb08f3cbbd21c B Renegade (U) [b1] NES @@ -15234,7 +15234,7 @@ ce9be360c843606897cba2878e8ad3bd57134369 H Retro Mario Bros 3 (Older) (SMB3 PRG1 47958c4b9b18116ffd4aafad43aeb4bfa3ec173d H Retro Mario Bros 3 (SMB3 PRG1 Hack) NES 85e5e4241d7fb3cb4bd03f2ec44c3439960e2f49 U Retrocoders' Demo for Y2Kode (PD) NES 5e4eb9f1a8b2a9dc60308c380659aa040d164545 U Retrocoders' Music ROMS - Years Behind (PD) NES -482360d347ba7c0deb945f93d43cc85377fc3654 H Return BC by Bishop & Multisoft (Battle City Hack) NES +482360d347ba7c0deb945f93d43cc85377fc3654 H Return BC by Bishop & Multisoft (Battle City Hack) NES 4be8bc2dfd966d52c3dc27042813eaaadf4217e3 H Return BC by Bishop (Battle City Hack) NES caa8da6dcf9d28028dfd6d2e6e86537fd0be3eb1 B Return of the Black Mage by Redrum (Warpman Hack) [o1] NES 717c53d094d0d7f01358568a92e938934a82960c H Return of the Black Mage by Redrum (Warpman Hack) NES @@ -16117,8 +16117,8 @@ c1332faaa9e40f1953a8f470b851f2a1f869715c H Sansuu 3 Nen - Keisan Game (J) [hM03] a9ce58ea73e0f63d264d0f79f23a077797fd52ff B Sansuu 3 Nen - Keisan Game (J) [hM03][o1] NES dafe0132cf7850ddbc50bc3a0f516d8a0b6049c6 G Sansuu 4 Nen - Keisan Game (J) (Prototype) [!] NES 7c5b6f8b54790e73d72088854253395360625d7f G Sansuu 4 Nen - Keisan Game (J) [!] NES -c6ac68e9dfaf87f774f8ff94a7a0eef3591e2d68 G Sansuu 5 & 6 Nen - Keisan Game (J) (Prototype) [!] NES -6020dc7df0e63dc00293d2fea63aef698f608942 U Sansuu 5 & 6 Nen - Keisan Game (J) NES +c6ac68e9dfaf87f774f8ff94a7a0eef3591e2d68 G Sansuu 5 & 6 Nen - Keisan Game (J) (Prototype) [!] NES +6020dc7df0e63dc00293d2fea63aef698f608942 U Sansuu 5 & 6 Nen - Keisan Game (J) NES 4631b718863e7e0819f8a5a20871df489667894f U Santa Claus (Ch) (Wxn) NES 4dd9861f9e77fd1d79058ec168d3659765f9b9a1 B SARS Kung Fu 2003 by Jeremiah Johnson (Kung Fu Hack) [o1] NES 5d2b88a9b421114ee9161a32a4a4be36e4d33c95 H SARS Kung Fu 2003 by Jeremiah Johnson (Kung Fu Hack) NES @@ -16151,8 +16151,8 @@ e0f27eda215acd60fd3333d971f353ade4022774 H Schneider (Captain Tsubasa II Hack) N e31b969724dc19ade8c2e82bd36b506653de7b58 U Screen Saver Demo by KZ-S (PD) NES 49735dfc8bcbb6a53b484832f6ee8a2b3379935e U Screen2NES Zelda Demo V2 by Afroman (PD) NES ac503144a0cf452f71a5ba3076f6c2ee130d58f0 U Scroll Demo by HollowOne11 (PD) NES -31f013891c2daa44cda80afc5fe9ed632823750a U ScrollNES 0.1 2010 by NO CARRIER & Batsly Adams (PD) [a1] NES -64a95d6b75ee8a90df670e3740980063289a81a5 U ScrollNES 0.1 2010 by NO CARRIER & Batsly Adams (PD) NES +31f013891c2daa44cda80afc5fe9ed632823750a U ScrollNES 0.1 2010 by NO CARRIER & Batsly Adams (PD) [a1] NES +64a95d6b75ee8a90df670e3740980063289a81a5 U ScrollNES 0.1 2010 by NO CARRIER & Batsly Adams (PD) NES 5ced0cb435fb8c3e28f3f3bbfe55b6ca196970ba G SD Battle Oozumou - Heisei Hero Basho (J) [!] NES 077c2d4b9ef42e915e13c40bf7e88fce098d0f14 G SD Gundam - Gachapon Senshi 2 - Capsule Senki (J) [!] NES 382496bc94169a2e13ddf946cdee66a8f15035f8 B SD Gundam - Gachapon Senshi 2 - Capsule Senki (J) [b1] NES @@ -16664,8 +16664,8 @@ dc06b62c59901190ad2f04f6a9b857c16c2400ec H Skinhead Fight (Nekketsu Kakutou Dens d25f42a6f677399c05e08b8c164dfd43cb6be2b5 H Skinhead on Ice (Nekketsu Hockey Hack) NES 1fd7896dfa2af88a0056fa712074b43f59c0e4da H Skinhead Racing (Downtown - Nekketsu Koushin Kyoku Hack) NES d383d346725ed66ea41d619daa311867c9dc5c58 G Sklad Nomer 18 (Unl) [!] NES -b191e5d30e31e1f8613c4b3fb40b770f97ae92ed G Skull & Crossbones (Tengen) [!] NES -6b05670da10c0ba5eb33c94fb931a5464741239e B Skull & Crossbones (Tengen) [o1] NES +b191e5d30e31e1f8613c4b3fb40b770f97ae92ed G Skull & Crossbones (Tengen) [!] NES +6b05670da10c0ba5eb33c94fb931a5464741239e B Skull & Crossbones (Tengen) [o1] NES 8427c83a22306c0ee376f782e948601985f49f5a B Skullanoid by Evan Lucore (Arkanoid Hack) [o1] NES 146cb857051c2fc6892e0a65b8246abf0bceabf3 H Skullanoid by Evan Lucore (Arkanoid Hack) NES 3fc678eae782f6337e6522285b9b78b0541067a9 G Sky Destroyer (J) [!] NES @@ -16974,11 +16974,11 @@ eb60b5015be750db9484d7f5a74fdd23ec22d150 G Solar Jetman - Hunt for the Golden Wa 65f10ecade7082e8cebd1e2cc9c18ba67746691c B Solar Jetman - Hunt for the Golden Warpship (U) [o1] NES 195959f8fc5daf5ed05dc8b7fd72a5e5a748a8bb T Solar Jetman - Hunt for the Golden Warpship (U) [T+Bra1.0_TraduROMS] NES a632ae12fec13637ee1824bad5e4f6e180add3d8 T Solar Jetman - Hunt for the Golden Warpship (U) [T+Rus_Chief-Net] NES -c05e8c0f26044ee2ed8873b9939f1a97e71fc29f U Solar Wars 2001 by Chris Covell, Joey Parsell & Michel Iwaniec (PD) NES -4d42ecc70c481f7fe68a8a2961ac27860fa97575 U Solar Wars by Chris Covell, Joey Parsell & Michel Iwaniec (PD) [a1] NES -da5ecfca8ee9f6a313039266fe0c705db84978d3 U Solar Wars by Chris Covell, Joey Parsell & Michel Iwaniec (PD) NES -ce8b4818719ecad6b35ce9ca4ef573467e160126 U Solar Wars Silent V.1 by Chris Covell, Joey Parsell & Michel Iwaniec (PD) NES -728e45acb68985ce8cc73c5f97ab226992ccfc09 U Solar Wars Silent V.2 by Chris Covell, Joey Parsell & Michel Iwaniec (PD) NES +c05e8c0f26044ee2ed8873b9939f1a97e71fc29f U Solar Wars 2001 by Chris Covell, Joey Parsell & Michel Iwaniec (PD) NES +4d42ecc70c481f7fe68a8a2961ac27860fa97575 U Solar Wars by Chris Covell, Joey Parsell & Michel Iwaniec (PD) [a1] NES +da5ecfca8ee9f6a313039266fe0c705db84978d3 U Solar Wars by Chris Covell, Joey Parsell & Michel Iwaniec (PD) NES +ce8b4818719ecad6b35ce9ca4ef573467e160126 U Solar Wars Silent V.1 by Chris Covell, Joey Parsell & Michel Iwaniec (PD) NES +728e45acb68985ce8cc73c5f97ab226992ccfc09 U Solar Wars Silent V.2 by Chris Covell, Joey Parsell & Michel Iwaniec (PD) NES dc50b0576187261030236687f37540cd429749ae H Soldier VS Mario (SMB1 Hack) NES 67bd42b43a2e0fc012569c02ab18bf7ec679443f T Solitair (from Nuevo Tipo de Computadora) (Unl) [T+Rus_Cool-Spot] NES b3fcfd458cb9ad4c69414b37b17b4c9cdd3d7abd T Solitair (from Nuevo Tipo de Computadora) (Unl) [T+Rus_Cool-Spot][a1] NES @@ -17245,7 +17245,7 @@ c9374202764fa52c749144b7ddcf26a9687a7d8a B Sqoon (U) [o3] NES 9bf0d67acdfde71eb391c7d35b6e45671c4fe35d U Square (Ch) (Wxn) NES 4072c52beeb14b128e0f1f497b4a72377fe59923 U Square Box by Quietust (PD) NES a864d3b913cefc885e01e0dacc53077ea7f5c727 U Square Box by Quietust [U] (PD).unf NES -7517bed4dbdc71c3184a9632e460f223b7a2191f U Square City by Mankeli, Zonzki & Bananmos (PD) NES +7517bed4dbdc71c3184a9632e460f223b7a2191f U Square City by Mankeli, Zonzki & Bananmos (PD) NES 90c1266a1bfc51c6a8fd5ae75a90bd9b6d491949 G Square Force (Unl) [!] NES f00d2feb353450bd6294bb431a54cee729e56689 G Square no Tom Sawyer (J) [!] NES af6443e035e95a7917b773fc2a32a9d7709caae5 B Square no Tom Sawyer (J) [b1] NES @@ -17566,11 +17566,11 @@ b3ed4ba03dba257229c68c4ea0173f8961bc00a2 B Strider (U) [o1] NES be18c598d75b1b8504952154938868723b045daa C Strider (U) [t1] NES a25bfd8f0cf77ee96f6b07deebe6313eb3787ea3 G Strike Wolf (MGC-014) (Unl) [!] NES 80cdb522e0d2adc41595c6dcec9fe330816b077e H Strip Aerobics (beta) by Golden Gun (Dance Aerobics Hack) NES -356fa145d802faa849c66b1c0e549de850cdffb1 U Stroke & Match Golf (Ladies) (VS) NES -53ed0cca26f766bbeb6d10bf90dd2891bda93ebe G Stroke & Match Golf (VS) [!] NES -c988eb9e17969812cd4d09896fd28da9ae3a6a13 U Stroke & Match Golf (VS) [a1] NES -6c756c8e4263a5b4dc8cc2502dc4e63fac6fab29 B Stroke & Match Golf (VS) [a1][b1] NES -7bbd19e207a78c833f8ae5ff535cbf974f299d73 B Stroke & Match Golf (VS) [a1][b2] NES +356fa145d802faa849c66b1c0e549de850cdffb1 U Stroke & Match Golf (Ladies) (VS) NES +53ed0cca26f766bbeb6d10bf90dd2891bda93ebe G Stroke & Match Golf (VS) [!] NES +c988eb9e17969812cd4d09896fd28da9ae3a6a13 U Stroke & Match Golf (VS) [a1] NES +6c756c8e4263a5b4dc8cc2502dc4e63fac6fab29 B Stroke & Match Golf (VS) [a1][b1] NES +7bbd19e207a78c833f8ae5ff535cbf974f299d73 B Stroke & Match Golf (VS) [a1][b2] NES 7bba18f6c4970a841fcca61cfa0c137fe4d79156 U Strong Pill (Ch) (Wxn) NES 8af29c451a88c37520a3ba67289b0ea984f1799a H Stronghold (SMB1 Hack) NES 0b1ff1e0010dfebe2e8a072df96ae1ce7af0595e H Stronghold, The (SMB1 Hack) NES @@ -17582,7 +17582,7 @@ b9a9a64cf606bba1fb70b3da70926ae2f22781f6 B Stunt Kids (Camerica) [o1] NES 75f1475b12ab45bd82aff0d46224dfec8b6ad663 H Subcon 2000 (Final) (SMB2 Hack) NES 13e7f2ca2c7ee1aea28245af364ce4fa6ac8b592 H Subcon 2000 (SMB2 Hack) NES 488d37154efc7611de0cded75aade267222777a6 U Submarine War (Ch) (Wxn) NES -8d24486170a3ffc5f36d89bae423a1d9fa173b60 U Subor Figure Ratiocination & IQ Puzzle (Ch) NES +8d24486170a3ffc5f36d89bae423a1d9fa173b60 U Subor Figure Ratiocination & IQ Puzzle (Ch) NES 88318d936361115b784f072ec7f1bddb0e6728ba U Subor V1.0 (R) [a1] NES 786f2da157861fd6db2aaf84fe95cc83244594fa U Subor V1.0 (R) NES 406a458af2f51a1b44ea18e1999781ca22b5b3c7 B Subor V3.0 (Ch) [b1] NES @@ -17649,8 +17649,8 @@ add98da0583a4a1cb6d5bfecf305fa64457d7b90 H SUP-Noid (Arkanoid Hack) NES 60081d0d62971348268c68f3c352c1da7cfc0d88 B Super 1997 4-in-1 [p1] NES 5e5ce5cbd73ea88ee012c88c0e7be30130f55ebd G Super 1998 3-in-1 (NT-008 PCB) [p1][!] NES fb947bf2f88e9cb8d33c0a7de8c243969bb54fdb G Super 1998 3-in-1 (VT-850, NT-008 PCB) [p1][!] NES -b103bd0b66e8ea798e64295e799fefe6b69cfd2b G Super 2-in-1 (Soccer Game & Crazy Dance) (Unl) [!] NES -3d580c1ce546b60664f2c6367d804a673478bc8d H Super 2-in-1 (Soccer Game & Crazy Dance) (Unl) [f1] NES +b103bd0b66e8ea798e64295e799fefe6b69cfd2b G Super 2-in-1 (Soccer Game & Crazy Dance) (Unl) [!] NES +3d580c1ce546b60664f2c6367d804a673478bc8d H Super 2-in-1 (Soccer Game & Crazy Dance) (Unl) [f1] NES a21a620a1eaed19ef52e8f184dec2872cee2005a U Super 2-in-1 (Unl) NES 997bbb9a3e52507fa488810ed90b613e5ba1f4cd B Super 22-in-1 [p1] NES 5830ff9449a0388450718d014a9034e32645bdec G Super 24-in-1 [U][p1][!].unf NES @@ -18009,7 +18009,7 @@ c48a6d63859327ffb4d7aac6ac4fb15f9d663c37 H Super Luigi - The Red Coin Quest Demo ea69228d23f05be1205ed891e558485069060736 H Super Mari 2 by Maikami (SMB1 Hack) NES 8301685fec5dc281b46b32acc1fadde588ca59bc H Super Mari by Maikami (SMB1 Hack) [a1] NES 749484a5d999730184edd0c5b1d234a841d08c63 H Super Mari by Maikami (SMB1 Hack) NES -9c2562be31541ef7df69e4133daaa3e2531cdedf U Super Mario & Sonic 2 (Ch) NES +9c2562be31541ef7df69e4133daaa3e2531cdedf U Super Mario & Sonic 2 (Ch) NES bf0ddfe1e564829c52d7aff0560721231994e786 U Super Mario 14 (Unl) NES 9f9f52fd92b660721b0ccccab1d99fc22729b289 H Super Mario 3 Challenge (SMB3 PAL Hack) NES 8a812f75451c88130424e39b4e38972dbbfa0b2a H Super Mario 4 (SMB1 Hack) [a1] NES @@ -18899,15 +18899,15 @@ fd7b1e21e33988714e0c6e5d881c40d11bc651cd B Swords and Serpents (U) [b1] NES a737d3984b88328a5d5f9709547b931f99e3f32d B Swords and Serpents (U) [b2] NES 297d50d7296544ab74ccf019aca1869424b99932 B Swords and Serpents (U) [o1] NES 77f4ea6ebcdd71a5dab45b014dd300458e625b19 B Swords and Serpents (U) [o2] NES -592c8b6be5816ba771b4fc18ec6a72cfee06d2c7 G T&C 2 - Thrilla's Surfari (U) [!] NES -55e8093bbbe53bd9d8d0d90952fcb6aeb9240b23 B T&C 2 - Thrilla's Surfari (U) [b1] NES -846b6b442ec5532c53d198da7c7d5909c97aff3c B T&C 2 - Thrilla's Surfari (U) [b2] NES -6a101fb054fbe93b6c6ca33245e3f8b8710e45a8 B T&C 2 - Thrilla's Surfari (U) [o1] NES -ec1ac46af157cbe49383402373ab04a483105980 B T&C 2 - Thrilla's Surfari (U) [p1] NES -7114bc8b0aad3094e59ccedba2845c1c032b15cc G T&C Surf Design (U) [!] NES -a8d63aa540cf74d966b465036f9a423136c8536b B T&C Surf Design (U) [b1] NES -006c8859d1ab3429daa1228cd6161af3cdabb236 B T&C Surf Design (U) [b2] NES -aff91bfb462c2aa10cc2d51ce93a04f050d7f84d B T&C Surf Design (U) [o1] NES +592c8b6be5816ba771b4fc18ec6a72cfee06d2c7 G T&C 2 - Thrilla's Surfari (U) [!] NES +55e8093bbbe53bd9d8d0d90952fcb6aeb9240b23 B T&C 2 - Thrilla's Surfari (U) [b1] NES +846b6b442ec5532c53d198da7c7d5909c97aff3c B T&C 2 - Thrilla's Surfari (U) [b2] NES +6a101fb054fbe93b6c6ca33245e3f8b8710e45a8 B T&C 2 - Thrilla's Surfari (U) [o1] NES +ec1ac46af157cbe49383402373ab04a483105980 B T&C 2 - Thrilla's Surfari (U) [p1] NES +7114bc8b0aad3094e59ccedba2845c1c032b15cc G T&C Surf Design (U) [!] NES +a8d63aa540cf74d966b465036f9a423136c8536b B T&C Surf Design (U) [b1] NES +006c8859d1ab3429daa1228cd6161af3cdabb236 B T&C Surf Design (U) [b2] NES +aff91bfb462c2aa10cc2d51ce93a04f050d7f84d B T&C Surf Design (U) [o1] NES fdbe721de58985fa9388e8dacaab2b9bbd2594bb G Taan Hak Fung Wan King Tank (Ch) [!] NES 07d463406d853ee92d196bedbf1c9d304fbfc442 T Taan Hak Fung Wan King Tank (Ch) [T+Rus_Cool-Spot] NES 09f2fc1c42469212c6867ae1a8049716f59e8773 U Table Tennis (Ch) (Wxn) NES @@ -19076,12 +19076,12 @@ cda500269bb162b0724f974b104cdc1573cd69dd C TaleSpin (U) [t4] NES ba0f38461b625da1b4d2d87ffe2d425e4300c7bc U Tall Pixel Demo by Damian Yerrick (PD) NES dab071f1829851c34483f02b1da737ee3ccd13b6 G Tamura Koushou Mahjong Seminar (J) [!] NES 21047b05fe5387b1c08834439f8fb153735da6ff B Tamura Koushou Mahjong Seminar (J) [b1] NES -4a6a524759ca64e2983cb188ff439178075e304c U Tanespot by Jonathan & Hans Knektar (PD) NES +4a6a524759ca64e2983cb188ff439178075e304c U Tanespot by Jonathan & Hans Knektar (PD) NES 74bb1012db87e69d6deb37de19446c668886049b U Tang Bo Hu Dian Qiu Xiang (NJ069) (Ch) NES 61c396d07aae17b391121f07cf9ba92bec0ca736 U Tang Mu Li Xian Ji (Ch) NES eac84b8189e3ec871f6974376e158737c2a376c7 G Tanigawa Kouji no Shougi Shinan II (J) [!] NES 9c3c6e0dd492ae7ea8f38224089a3f0b0b979880 G Tanigawa Kouji no Shougi Shinan III (J) [!] NES -d061ab6624edb4fdaf4d2a1df75499d1238eccf5 H Tank & Sub Mario (SMB1 Hack) NES +d061ab6624edb4fdaf4d2a1df75499d1238eccf5 H Tank & Sub Mario (SMB1 Hack) NES 459a8d83e8d0d992a2685ce6da135a2e691ed1a6 H Tank (Battle City Hack) NES 7f7888211e30b4dc296ee5addfbf8c62985bd9f9 U Tank (Ch) (Wxn) NES b5544d657fadef726ada69718407ab509dc69c47 U Tank 1990 (Ch) [a1] NES @@ -19112,8 +19112,8 @@ e30f43730fd9b74ebe5dc5c88e5bc0f72dc19fef H Tank Duel (Chi Title) (Battle City Ha e5f6c4aebfa1123554d4e3ef984f0a7e0bfdaef8 H Tank Duel 2 (Battle City Hack) NES 74ca37027c5e461fc88adc33fa428d832a5b225e B Tank Z by TOF (Battle City Hack) [o1] NES 007775f70b0726f7e20241484bf59e84cb35ce6f H Tank Z by TOF (Battle City Hack) NES -b5b01322bde1c061a76471fb544f90ecfbd0622b T Tanks & Milk (Nuts & Milk Hack) [T+Rus_Mitz] NES -832900808ad3add22e973fbb65408139abc0ed1a H Tanks & Milk (Nuts & Milk Hack) NES +b5b01322bde1c061a76471fb544f90ecfbd0622b T Tanks & Milk (Nuts & Milk Hack) [T+Rus_Mitz] NES +832900808ad3add22e973fbb65408139abc0ed1a H Tanks & Milk (Nuts & Milk Hack) NES b07bd06624f56133c87610a8bb722be10e495147 G Tantei Jinguuji Saburou - Toki no Sugiyuku Mama ni (J) [!] NES 2c0a885c049a4de54a31f51086cb20006e11beb8 U Tantei Jinguuji Saburou - Yokohamakou Renzoku Satsujin Jiken (J) (VC) NES be8ae507a738cc2059a598f2cfe68a0e848939c4 G Tantei Jinguuji Saburou - Yokohamakou Renzoku Satsujin Jiken (J) [!] NES @@ -19446,7 +19446,7 @@ f0a930d6451dd861698c153e2e4af341b506942a H Tecmo Rose Bowl 2002 1-AA College Foo b7d7e496ca9dfa023d79dcc973208c1c63477125 G Tecmo Super Bowl (U) [!] NES 09d7268535053f7ba16f94f4e4846a0d2705ee41 B Tecmo Super Bowl (U) [b1] NES 4f197e5d60df3bb0df051e46614b3de55edd0d7d B Tecmo Super Bowl (U) [o1] NES -ac3da734fa5eda62df44ecfb8912c18cb0f6623f H Tecmo Super Bowl 1962 Edit by Denny, Jstout & Elway7 (Hack) NES +ac3da734fa5eda62df44ecfb8912c18cb0f6623f H Tecmo Super Bowl 1962 Edit by Denny, Jstout & Elway7 (Hack) NES 761290f53aa1bfee1f9ddabbbdc70482dd415d1c H Tecmo Super Bowl 1968 by Carther (Hack) NES ea38b12e3cd3192d07637f32055ce1a3a82be32f H Tecmo Super Bowl 1968 Even Team - Online Tecmo Tourney Version (Hack) NES 6f4441535cc711207a204ee375bc7d0b535a9d19 H Tecmo Super Bowl 1983-1984 - BO FB Offtackle Left (Hack) NES @@ -19502,7 +19502,7 @@ cab90185c6f732f922f915cada0e9010a1330f6a H Tecmo Super Bowl 2006 - AFC Champions ce0e7ecec10a711a0e3afc31155ef920adc28cb9 H Tecmo Super Bowl 2006 by GRG (Hack) NES b75b315ca3c96ec8a2632a0373928979c4aefeab H Tecmo Super Bowl 2006 v.2 by RBPD5015 (Hack) NES 59783d5c20f9f046738532d7323f5c2dadaae333 H Tecmo Super Bowl 2006 v.final by mattjones18 (Hack) NES -9d2c88538919d6e1a2fc60215b721ff7d3e2b9b9 H Tecmo Super Bowl 2006 v.update - Title Screen by mattjones18&andrewmarsh13 (Hack) NES +9d2c88538919d6e1a2fc60215b721ff7d3e2b9b9 H Tecmo Super Bowl 2006 v.update - Title Screen by mattjones18&andrewmarsh13 (Hack) NES 40efbfe8bbb00f3db078fdcf522957653020fd4f H Tecmo Super Bowl 2006 v1 by drummer4god (Hack) NES bc25eaf09228d5a1c6a0f692898509b1de119534 H Tecmo Super Bowl 2006 v1 by mattjones18 (Hack) NES 95ddb60aaa75a8d2adb03c4f6d63dceca65dcadb H Tecmo Super Bowl 2006 v2 by drummer4god (Hack) NES @@ -19739,7 +19739,7 @@ bed34bf7c2bda653eda7a3eb1181c6a7c4cb0a65 H Tecmo Super Bowl X Globe Bowl (Hack) 10c4e09361a27a527dd4337ff62a49409670343c H Tecmo Super Bowl X IHSAA (Hack) NES 058e6dd332cc20282b87b001ee554f01666a939b H Tecmo Super Bowl X Mutant League (Hack) NES a2ddbeb71c07961cf875f0f01a3eca1b1dc7dd8f H Tecmo Super Bowl X Olympics (Hack) NES -3f5d28fe0591911ff8b60b59a80502572407af62 H Tecmo Super Bowl X World & USFL (Hack) NES +3f5d28fe0591911ff8b60b59a80502572407af62 H Tecmo Super Bowl X World & USFL (Hack) NES 07e33fb37a8ef1ef32582fc3ade1a1d42750c891 H Tecmo Super Bowl X World League (Hack) NES 1dccdc47be881eda06fc80bb6ee95b769177a814 H Tecmo Super Bowl X XFL (Hack) NES 30b6033e6ef01cbd8099beff41a10dfeda91436e H Tecmo Super Bowl XFL - Updated by GRG (Hack) NES @@ -20036,7 +20036,7 @@ d9e05cd3cb72d02352ce907f65137c161f000d51 H Tenchi wo Kurau II - Star and Rainbow 606b6c26886e37f674ba0b076825a0c18e51b838 H Tenchi wo Kurau II - Valiant General Edition by lmjny (Hack) NES 947659dcc3aa847b7abcd701e7328c13aff76941 H Tenchi wo Kurau II - Weiruwei's Final Edition (Hack) NES 7ce8f14c477da953cb66f7f0bfb89772de574e8f H Tenchi wo Kurau II - Woman Edition (Hack) NES -53bbb3a3def86ddf00d763c1ed171282d10dd29b H Tenchi wo Kurau II - Wu Jin & Guo Tai (Hack) NES +53bbb3a3def86ddf00d763c1ed171282d10dd29b H Tenchi wo Kurau II - Wu Jin & Guo Tai (Hack) NES 81be25d041c91f81e1b6df190b6baf886ee9a75c H Tenchi wo Kurau II - Yellow Turban Story (Hack) NES 17c71e03f6423c5f706e616182b1eea779913fd7 H Tenchi wo Kurau II - Yuan Luzhi Story (Hack) NES fa8396969fd18af4606f9a6d36cadc45eb747987 H Tenchi wo Kurau II - Yuan Shao Story (Hack) NES @@ -20252,16 +20252,16 @@ c697f7159f401fa736320a25a4f1b06233198f81 B Three Stooges (U) [o1] NES 2d2dd56f453715fc2fd8d0abf95bc2459f1d6082 B Three Stooges (U) [o2] NES 8c30cfc34cf89bae61591f599f6f24b3b255cb00 B Three Stooges (U) [o3] NES 1a618d99702421566c04e14096bf23ab25207f83 B Three Stooges (U) [o4] NES -5203dd2cbaafba9e5d4581a8252f2d47413902d8 G Thunder & Lightning (U) [!] NES -537819f97ddad1210614b59bffc81a6ef045a9ed B Thunder & Lightning (U) [b1] NES -cec96de01564f5bd14ace8668cd616f5f54094c8 B Thunder & Lightning (U) [b1][o1] NES -2eef9579430f9c00a59504715ebe3f4b3b4fbc4f B Thunder & Lightning (U) [b1][o2] NES -0a7c1edf9d2b26497de3aec1aa67a600795b72ca B Thunder & Lightning (U) [b2] NES -e6a90c84a3bd1e6c4e34d08df3ef4ff74c2206a3 B Thunder & Lightning (U) [b3] NES -2ea8b553bda94064f8142e8e2ea1d258db857da7 B Thunder & Lightning (U) [b4] NES -f04edfb835d9b14827f2e3359c81b7678b16b71b B Thunder & Lightning (U) [b5] NES -da657ecdd900b9b0d4ddc0473b9e9a92624d0659 B Thunder & Lightning (U) [b6] NES -468c6e236ddcab75bdc31e18f1731ffa52a62ade C Thunder & Lightning (U) [t1] NES +5203dd2cbaafba9e5d4581a8252f2d47413902d8 G Thunder & Lightning (U) [!] NES +537819f97ddad1210614b59bffc81a6ef045a9ed B Thunder & Lightning (U) [b1] NES +cec96de01564f5bd14ace8668cd616f5f54094c8 B Thunder & Lightning (U) [b1][o1] NES +2eef9579430f9c00a59504715ebe3f4b3b4fbc4f B Thunder & Lightning (U) [b1][o2] NES +0a7c1edf9d2b26497de3aec1aa67a600795b72ca B Thunder & Lightning (U) [b2] NES +e6a90c84a3bd1e6c4e34d08df3ef4ff74c2206a3 B Thunder & Lightning (U) [b3] NES +2ea8b553bda94064f8142e8e2ea1d258db857da7 B Thunder & Lightning (U) [b4] NES +f04edfb835d9b14827f2e3359c81b7678b16b71b B Thunder & Lightning (U) [b5] NES +da657ecdd900b9b0d4ddc0473b9e9a92624d0659 B Thunder & Lightning (U) [b6] NES +468c6e236ddcab75bdc31e18f1731ffa52a62ade C Thunder & Lightning (U) [t1] NES ff9a9dadbc051dba184bb2b75898d0b1e2003fa9 H Thunder Mario v0.1 (SMB1 Hack) [a1] NES ca34b25a91844a3553460f5c8a2c9c965aa2aa5c H Thunder Mario v0.1 (SMB1 Hack) NES e14b6ba27655313943a2bb440aa753bb6ca6fed5 U Thunder Warrior (Unl) NES @@ -20288,7 +20288,7 @@ cb0899ae2d9a0ad60edd0ada2b0a62c79be46893 U Thwaite V0.03 by Damian Yerrick (2011 276a18af8b307acd1edf98594e29710eeccf1c8c U Tian Long Ba Bu (NJ035) (Ch) NES cac9a7bb24890cc9cd7ab020581a5b609e1e1d0d U Tian Wang Xiang Mo Zhuan (Ch) (Decrypted) NES ab39d3fe1be075db59fe77abfb225249cfefcf90 U Tiao Wu Tan (Ch) NES -93e851e78f811175edb368d37dd7060c82fcfc3a T Tic & Tac 2 - Rangers du Risque (Chip 'n Dale 2 Hack) [T+Fre] NES +93e851e78f811175edb368d37dd7060c82fcfc3a T Tic & Tac 2 - Rangers du Risque (Chip 'n Dale 2 Hack) [T+Fre] NES 9bff3f91adf6fce47baae595be44fcd9c906884b U Tic-Tac by Sly Dog Studios (PD) NES 3bdb74f3a9f0620ca6581a7ad8a9864b810e3772 U Tic-Tac XO by Sly Dog Studios (PD) NES 15ac45742f1830dd6ba727cf41a4a9d9676a6d2a B Tie Fighter (Older) (SMB1 Hack) [b1] NES @@ -20430,7 +20430,7 @@ b4bc7b0867d9ecc88fe89bb6b4c564c495455363 H Toaster Bros (SMB1 Hack) NES 6e89817eb2531c4260120a609b89de354a5fd39d H Tobi (SMB1 Hack) NES b01ede8636ad9642476c09541b85ffb3d6bbb11a U Tobidase Daisakusen (FDS Conversion) NES c1307b51a96018211ef8105cbbbe90cd3e16a67b H Todos Contra TCHECO 2.0 by Macbee (Rockin' Kats Hack) NES -bf27c3c6ea6f06ff6d3071eb0e105608038e8052 U ToeJam & Earl Title Screen (PD) NES +bf27c3c6ea6f06ff6d3071eb0e105608038e8052 U ToeJam & Earl Title Screen (PD) NES 3d03d92a8f68a8d0619de48b710c9d514663b63e H Toilet Mario (SMB1 Hack) [a1] NES 8af0f78307042ecb8d938600b83daca6f76f004c H Toilet Mario (SMB1 Hack) NES f11c1240a664c5424a8c7eba7eeb42343c792350 U Toita Basketball (Unl) NES @@ -20464,30 +20464,30 @@ aef80dedb58085fc4b779e3747d69492f3b666bf G Tokoro San no Mamoru mo Semeru mo (J) b42120ffa11f8c809db4e6dd0ba11a8eebcd65bd H Tokoro San no Mamoru mo Semeru mo (Saitama Hack) NES ecf1fd4135beebe35c7ca8036e1a085dacdc4f5d U Tokumaru Raycaster 00 (PD) NES 2fca78b0d4a436579b3ed6c72dfe3888f3154644 U Tokumaru Raycaster 01 (PD) NES -d67f0beeb7603c224177264f13fc4b2d08ad679b G Tom & Jerry (E) [!] NES -7e1048cd8d868d1df56ed613f660b8513a6d71ea T Tom & Jerry (J) [T+Chi_MS emumax] NES -709016db8902eb4c6a99cd462fd1627babbbfbe4 U Tom & Jerry (J) NES -d6ebfe209995e8db14e82df952e8c5b10b025460 G Tom & Jerry (U) [!] NES -8620b79e4f0087a6a44ac3c31d2746292e573d49 B Tom & Jerry (U) [b1] NES -201867ffc992c4038021d8510fe8beea4f3e305a B Tom & Jerry (U) [b2] NES -936d84aafd680e4b52cfd006fd0f3ec8abfa2c24 B Tom & Jerry (U) [b3] NES -fe4ed3c8f29cbdb649a233b85e224f04f6a7f533 B Tom & Jerry (U) [o1] NES -6f8965f2e332e96a43de03ccca6a12b982f4a95a B Tom & Jerry (U) [p1] NES -7e984e9696e8d089ad870c68944ff2b95f053732 T Tom & Jerry (U) [p1][T+Rus_2R Team] NES -623f8b48b17e34653a0d9cd1db0b0facb8429b8f B Tom & Jerry (U) [p2] NES -8ecbe4a0a6b94542409c0990357de968e2e85f22 T Tom & Jerry (U) [T+Ara_Hisoka] NES -22c95df30f90c68b0d64b412029f9e905195bca1 T Tom & Jerry (U) [T+Pol] NES -28ceb78e1a2f2646bb47a8c5ed293605a7fa8a5f T Tom & Jerry (U) [T+Rus] NES -c3a972e3cd3f9832f7f46756d68744952e1585e9 C Tom & Jerry (U) [t1] NES -168e14e08574662823d6e4604540225205e29301 U Tom & Jerry 3 (Unl) NES +d67f0beeb7603c224177264f13fc4b2d08ad679b G Tom & Jerry (E) [!] NES +7e1048cd8d868d1df56ed613f660b8513a6d71ea T Tom & Jerry (J) [T+Chi_MS emumax] NES +709016db8902eb4c6a99cd462fd1627babbbfbe4 U Tom & Jerry (J) NES +d6ebfe209995e8db14e82df952e8c5b10b025460 G Tom & Jerry (U) [!] NES +8620b79e4f0087a6a44ac3c31d2746292e573d49 B Tom & Jerry (U) [b1] NES +201867ffc992c4038021d8510fe8beea4f3e305a B Tom & Jerry (U) [b2] NES +936d84aafd680e4b52cfd006fd0f3ec8abfa2c24 B Tom & Jerry (U) [b3] NES +fe4ed3c8f29cbdb649a233b85e224f04f6a7f533 B Tom & Jerry (U) [o1] NES +6f8965f2e332e96a43de03ccca6a12b982f4a95a B Tom & Jerry (U) [p1] NES +7e984e9696e8d089ad870c68944ff2b95f053732 T Tom & Jerry (U) [p1][T+Rus_2R Team] NES +623f8b48b17e34653a0d9cd1db0b0facb8429b8f B Tom & Jerry (U) [p2] NES +8ecbe4a0a6b94542409c0990357de968e2e85f22 T Tom & Jerry (U) [T+Ara_Hisoka] NES +22c95df30f90c68b0d64b412029f9e905195bca1 T Tom & Jerry (U) [T+Pol] NES +28ceb78e1a2f2646bb47a8c5ed293605a7fa8a5f T Tom & Jerry (U) [T+Rus] NES +c3a972e3cd3f9832f7f46756d68744952e1585e9 C Tom & Jerry (U) [t1] NES +168e14e08574662823d6e4604540225205e29301 U Tom & Jerry 3 (Unl) NES 67e2781b74c0771c377bfd11308662ab906e7a09 G Tom Sawyer no Bouken (J) [!] NES da0a506fda6aba44a56ac998b613176a7b8f8919 T Tom Sawyer no Bouken (J) [T+Rus_Guyver] NES a506f23a0f5905fe85051e14e9ad1e0e181163ed C Tom Sawyer no Bouken (J) [t1] NES 2ffc983e94e5ec9fc654052a442297c2b1ab24a1 H Tom Servo (Megaman III Hack) NES -9c1de5cd49641d025d75c4024ee303ed0135673e G Tombs & Treasure (U) [!] NES -582a21a4e41a0e844d66cd3c7e75bc75939c0cb5 B Tombs & Treasure (U) [o1] NES -2e819d9c061ab801c931ef547ce737de8f92403a B Tombs & Treasure (U) [o2] NES -6a1536f70666a52075e967ed24b1e48cbd7fa8a1 C Tombs & Treasure (U) [t1] NES +9c1de5cd49641d025d75c4024ee303ed0135673e G Tombs & Treasure (U) [!] NES +582a21a4e41a0e844d66cd3c7e75bc75939c0cb5 B Tombs & Treasure (U) [o1] NES +2e819d9c061ab801c931ef547ce737de8f92403a B Tombs & Treasure (U) [o2] NES +6a1536f70666a52075e967ed24b1e48cbd7fa8a1 C Tombs & Treasure (U) [t1] NES ea4f4ddf8d26245a0a16078f913d0074a080261c U Tommy T's Play Me Sound Editor (PD) NES 3b287cb938e58a77c6d5aefdfb47fe9027c17055 G Toobin' (Tengen) [!] NES df8f7e23d1cca410226951d89fd6d4cdbd8aaf4e B Toobin' (Tengen) [b1] NES @@ -20520,11 +20520,11 @@ ee7747f09f98e6fc1717652a7a485982f5b2d6d6 G Top Gun - The Second Mission (U) [!] 3dfdd953c496287d95c38a5e8653b6fdaadc0ede B Top Gun - The Second Mission (U) [o1] NES 9f92f4d56710b97b79525b7d055041a7ff302697 H Top Gun Altered (Hack) NES 334e4ff5070846b5db6f1f0d1eba80cb1a1141c8 U Top Gun III (Unl) NES -d3de04f554a5ae57750f12aedc810c0c3db3d2ea G Top Players' Tennis - Featuring Chris Evert & Ivan Lendl (U) [!] NES -1dc84f0db89649761867fb52711d31566ff26883 B Top Players' Tennis - Featuring Chris Evert & Ivan Lendl (U) [b1] NES -e42950f3b54f3368e3fdc54e03bfe9e728334561 B Top Players' Tennis - Featuring Chris Evert & Ivan Lendl (U) [b2] NES -ef32f202aa300422587ce967621b3a7afeb9065a B Top Players' Tennis - Featuring Chris Evert & Ivan Lendl (U) [b3] NES -50a9b1a803d4c5c55799657c340e942dc976e3f4 B Top Players' Tennis - Featuring Chris Evert & Ivan Lendl (U) [o1] NES +d3de04f554a5ae57750f12aedc810c0c3db3d2ea G Top Players' Tennis - Featuring Chris Evert & Ivan Lendl (U) [!] NES +1dc84f0db89649761867fb52711d31566ff26883 B Top Players' Tennis - Featuring Chris Evert & Ivan Lendl (U) [b1] NES +e42950f3b54f3368e3fdc54e03bfe9e728334561 B Top Players' Tennis - Featuring Chris Evert & Ivan Lendl (U) [b2] NES +ef32f202aa300422587ce967621b3a7afeb9065a B Top Players' Tennis - Featuring Chris Evert & Ivan Lendl (U) [b3] NES +50a9b1a803d4c5c55799657c340e942dc976e3f4 B Top Players' Tennis - Featuring Chris Evert & Ivan Lendl (U) [o1] NES d4d46dc4d99459c8dd57f30eeb16aa03358540f3 G Top Rider (J) [!] NES fd4d0f89989a257c35fc243eeb6f5c6d3f36b88a B Top Rider (J) [b1] NES cf633f8b8571bead545ed8d72da9b22771c1b255 H Top Rider (J) [hM04] NES @@ -20588,26 +20588,26 @@ d67238510c7f9b72eec13d5269a0158ffa975055 C Toxic Crusaders (U) [t1] NES aad697dda0e00fd508d0e9469660194701f25a2a H Toxic Crusaders Debug by dragon2snow (Hack) NES 7c748e5a83fb07905cadc427d1909a04af8c51ec H Toy Story (Unl) [hM219] NES e3a08bd0e03b4b395410ec1ccdd9c0f49400a410 U Toy Story (Unl) NES -f036a0ba914cac462525480fe583e2a7871d192c B Track & Field (PC10) [b1] NES -95f499762d567ca9c8373cff73253937529baeab U Track & Field (PC10) NES -df8425d96b3ac613eec604d66b32e91b001488d0 G Track & Field (U) [!] NES -ac29221519765ec4a10e5f6ef5549dd1393436c7 B Track & Field (U) [b1] NES -5a7c68d213dd96b2e4f4cedd3de4165c711ba945 B Track & Field (U) [o1] NES -c2d8a7573451d64681d2baa10b83e7d1e3c1c04a B Track & Field (U) [p1] NES -abee2b7e0513ba2e55a522a0105e461f2f5cb267 T Track & Field (U) [T+Bra100%_BRGames] NES -70b74fc1f7623f133a7f49f9e1b54418164f4056 G Track & Field II (E) [!] NES -29bd3871447df2ad02a5ab1ec2c9256e85a5c359 G Track & Field II (U) (PRG0) [!] NES -316a53f846cdbf55c021f8e9497f06e2b08245e4 B Track & Field II (U) (PRG0) [b1] NES -97e6822b57a61ed4f1f763582a1fb2f556f44632 B Track & Field II (U) (PRG0) [b2] NES -921d31753740408fe8b3cce41e36609ada225068 B Track & Field II (U) (PRG0) [b3] NES -817ca6d0d790458dfa248763170dd05b0408ab25 B Track & Field II (U) (PRG0) [b4] NES -16994d0c5085bc91e0768b39c462c8920fdfdb26 B Track & Field II (U) (PRG0) [o1] NES -dda552f0a6b95dbcc891cff98220fad2fd08eaad B Track & Field II (U) (PRG0) [o2] NES -62ce1b905f5bcf37d65c6126f962a8088c1ce171 T Track & Field II (U) (PRG0) [T+Bra1.0_ROMHackBR] NES -533cd4effd292961c38d5d3bec9bf4bab4acaa32 T Track & Field II (U) (PRG0) [T+Swe1.0_TheTranslator] NES -a3ca238ef9744175b1bdc70bcdb70aafe97239bc T Track & Field II (U) (PRG0) [T+Swe1.0_TheTranslator][a1] NES -768e8707b2af9167cfd2851c968988185d463f98 G Track & Field II (U) (REVA) [!] NES -830d9875c723a15fb322b4f12a750f618268e80b G Track & Field in Barcelona (E) [!] NES +f036a0ba914cac462525480fe583e2a7871d192c B Track & Field (PC10) [b1] NES +95f499762d567ca9c8373cff73253937529baeab U Track & Field (PC10) NES +df8425d96b3ac613eec604d66b32e91b001488d0 G Track & Field (U) [!] NES +ac29221519765ec4a10e5f6ef5549dd1393436c7 B Track & Field (U) [b1] NES +5a7c68d213dd96b2e4f4cedd3de4165c711ba945 B Track & Field (U) [o1] NES +c2d8a7573451d64681d2baa10b83e7d1e3c1c04a B Track & Field (U) [p1] NES +abee2b7e0513ba2e55a522a0105e461f2f5cb267 T Track & Field (U) [T+Bra100%_BRGames] NES +70b74fc1f7623f133a7f49f9e1b54418164f4056 G Track & Field II (E) [!] NES +29bd3871447df2ad02a5ab1ec2c9256e85a5c359 G Track & Field II (U) (PRG0) [!] NES +316a53f846cdbf55c021f8e9497f06e2b08245e4 B Track & Field II (U) (PRG0) [b1] NES +97e6822b57a61ed4f1f763582a1fb2f556f44632 B Track & Field II (U) (PRG0) [b2] NES +921d31753740408fe8b3cce41e36609ada225068 B Track & Field II (U) (PRG0) [b3] NES +817ca6d0d790458dfa248763170dd05b0408ab25 B Track & Field II (U) (PRG0) [b4] NES +16994d0c5085bc91e0768b39c462c8920fdfdb26 B Track & Field II (U) (PRG0) [o1] NES +dda552f0a6b95dbcc891cff98220fad2fd08eaad B Track & Field II (U) (PRG0) [o2] NES +62ce1b905f5bcf37d65c6126f962a8088c1ce171 T Track & Field II (U) (PRG0) [T+Bra1.0_ROMHackBR] NES +533cd4effd292961c38d5d3bec9bf4bab4acaa32 T Track & Field II (U) (PRG0) [T+Swe1.0_TheTranslator] NES +a3ca238ef9744175b1bdc70bcdb70aafe97239bc T Track & Field II (U) (PRG0) [T+Swe1.0_TheTranslator][a1] NES +768e8707b2af9167cfd2851c968988185d463f98 G Track & Field II (U) (REVA) [!] NES +830d9875c723a15fb322b4f12a750f618268e80b G Track & Field in Barcelona (E) [!] NES d974155c893375bdc5701e18b2feac774c4a59e5 B TradeMark Mario (SMB1 Hack) [o1] NES 1263a4459dfa4722581a46d94bf1429f1465f683 H TradeMark Mario (SMB1 Hack) NES c953cb58d25ed19b477779b81b1962bb25e06cdb H Tranny Tramps - The Family Jewels (Double Dragon III Hack) NES @@ -21002,7 +21002,7 @@ f6642a2ee4fd9cf1a8c4f991d9e427627fe5ea3b U Variable Width Font Demo v0.01 by Dam 8548c230871abaf39c965bc3f87488ec1ca13fff U Variable Width Font Demo v0.02 by Damian Yerrick+Blargg (PD) NES 582450682d233eb3b1279b1e11a0e0137602be6b U Variable Width Font Demo v0.03 by Damian Yerrick+Blargg (PD) NES afd24e18c113309cbc0917c73fdb2c7865511990 U VBL Flag Clearing Timing Test by Shay Green (6 Nov 2005) (PD) NES -6e1faa816c80462f5ee293c1847ee829683ea8a9 U VBL Flag Operation & PPU Timing Test by Shay Green (7 Nov 2005) (PD) NES +6e1faa816c80462f5ee293c1847ee829683ea8a9 U VBL Flag Operation & PPU Timing Test by Shay Green (7 Nov 2005) (PD) NES 3aef088d11ce1b6b8b2db07aba9aa79b6d8526e3 U VBL Timing Test by Shay Green (6 Nov 2005) (PD) NES 45585124fb0ba1b93995c4c15ec48382c90af165 U Vectest3 (PD) NES 2d55988a0e29604c90c844df15da34764688fbf0 U Vector Demo (PD) NES @@ -21094,7 +21094,7 @@ a99e0bc1b9087b3f2540c1b18425af6083e74f0e T Volleyball (UE) [T+FreBeta_ks151] NES 2b711242f71bdee2a9ec5045c4863b2b030bbbd8 T Volleyball (UE) [T+Ita1.0_ZombiKiller] NES 028bfd4d3228343a992cecf5fdd9d4805d8a3cc2 G Volshebnaya Palitra (R) [!] NES 58832f2ce7232a8e476b5376f533300eb6b702de U Vote for Oniken on Greenlight (PD) NES -c81a649f330e3de4784d94e5ea00b502a207716c U VRAM Access & Internal Read Buffer Operation Test by Shay Green (15 Sep 2005) (PD) NES +c81a649f330e3de4784d94e5ea00b502a207716c U VRAM Access & Internal Read Buffer Operation Test by Shay Green (15 Sep 2005) (PD) NES 475ec5c8f610793d2ec555021e18f9230b151d63 U VRC6 Sound Demo by Siudym (PD) (PAL) NES 3e6154c79f27c5c9b2d4eba11c78570c9c5425cb H VS. Airman (SMB1 Hack) NES f9db1a17425dcd34a7bc68c0f86d5c338e58e795 B VS. Blink (VS SMB1 Hack) [o1] NES @@ -21190,9 +21190,9 @@ abae2b3ed342bc069abee73137744e5b36b4b0ab B Wall Street Kid (U) [b1] NES 7aca04613ec4e14df9c954f3e08605b5d981fadc B Wall Street Kid (U) [o2] NES 3b07de583fdf353d0e78f46b161e1e0c955b45d1 B Wall Street Kid (U) [o3] NES 1f5b5b4552ad51bc07a8aa99345b25190527995e B Wall Street Kid (U) [o4] NES -7d60a48aa52afcdf64ea9b249ade7cc8e83301c6 U Wally Bear & the No Gang (AVE) (Prototype) NES -cd1ee26c0cef8c48b72cc4000ac7a577b8c4c0b5 G Wally Bear & the No Gang (AVE) [!] NES -6603d08ee41b39350184cdf03537eb36162e2f01 B Wally Bear & the No Gang (AVE) [o1] NES +7d60a48aa52afcdf64ea9b249ade7cc8e83301c6 U Wally Bear & the No Gang (AVE) (Prototype) NES +cd1ee26c0cef8c48b72cc4000ac7a577b8c4c0b5 G Wally Bear & the No Gang (AVE) [!] NES +6603d08ee41b39350184cdf03537eb36162e2f01 B Wally Bear & the No Gang (AVE) [o1] NES dd8c8a387158230df68e20bd90b6c729589a5116 H Waluigi's Adventure by Googie (SMB1 Hack) [a1] NES 0de42862be2fea4d569700db9a01ef7745e2d97a H Waluigi's Adventure by Googie (SMB1 Hack) [a2] NES a9c35c50a1a447728621fffbad42f32a521c09ed B Waluigi's Adventure by Googie (SMB1 Hack) [b1] NES @@ -21267,7 +21267,7 @@ ad680a185bed1fdb8f6f885deaad6ed3ae565ea1 H Waterboy, The (Harry's Legend Hack) N dc88673fb3defcf60fcbbc5b2968dab20a188ad8 U WAV2NES Sample (PD) NES 831595bf54bf5dc41031358b87c7a3f30b2da765 U Wavetable5 Demo by Blargg (PD) NES 0b8582204c535c3b9c7d1b89342f22efb455a757 U Wavetable6 4-Channel Music Demo by Blargg (PD) NES -f5391038938d1c8577e572f0480ebf600bfd6482 U Wavy & Stretch Demo V0.3 by Chris Covell (PD) NES +f5391038938d1c8577e572f0480ebf600bfd6482 U Wavy & Stretch Demo V0.3 by Chris Covell (PD) NES c3c8bc28a11c11e45d48bdb8dd6b03d9e1974c47 U Way Out (Ch) (Wxn) NES 2470ce28d144f6d1320a81e8f1faeabd07bed462 G Wayne Gretzky Hockey (U) [!] NES 2be91df36a683e1e09f3f897ba5170fff22f2ac7 B Wayne Gretzky Hockey (U) [b1] NES @@ -21385,14 +21385,14 @@ d3040b0e2e70f426236cf76e3dbc7bc23967eb28 T Willow (U) [T+Fre100] NES 5e108abf60f2f8467c5a7f962cf11f0702c370a5 T Willow (U) [T+Rus_arsen13,Tigran] NES c6639a7b826fc3c85167334d7e3902db896a4779 T Willow (U) [T-Fre010] NES 3352a0493d4d40de75b3036ee01133e2fbe8e602 C Willow (U) [t1] NES -d94557741ae526a0cc7b4a3be5aa4a825baf9a85 G Wily & Light no Rockboard - That's Paradise (J) [!] NES -be4507a270fb3406cd483f2fd4e34da74a22d7a7 B Wily & Light no Rockboard - That's Paradise (J) [b1] NES -f44c84c330d5d84ec5410ad81e4300e4be9578a9 B Wily & Light no Rockboard - That's Paradise (J) [b1][o1] NES -40bce9f07c099e021bc1a7c73e5cd81de026c630 T Wily & Light no Rockboard - That's Paradise (J) [T+Eng1.1(Megaman)_Interordi] NES -0cedcf804a8fce45e56ec7f4d8be454838589cc2 T Wily & Light no Rockboard - That's Paradise (J) [T+Eng1.1(Rockman)_Interordi] NES -8166ad98dc32344e803d662333bda1b2acc29035 T Wily & Light no Rockboard - That's Paradise (J) [T-Eng(Megaman)_Interordi] NES -479364d2a6bb8db8c3343ce813157a8024a2ab92 T Wily & Light no Rockboard - That's Paradise (J) [T-Eng(Rockman)_Interordi] NES -35993e347372d4496ccc387b5a29f71a1f0bdba2 T Wily & Light no Rockboard - That's Paradise (J) [T-Eng0.10_Interordi] NES +d94557741ae526a0cc7b4a3be5aa4a825baf9a85 G Wily & Light no Rockboard - That's Paradise (J) [!] NES +be4507a270fb3406cd483f2fd4e34da74a22d7a7 B Wily & Light no Rockboard - That's Paradise (J) [b1] NES +f44c84c330d5d84ec5410ad81e4300e4be9578a9 B Wily & Light no Rockboard - That's Paradise (J) [b1][o1] NES +40bce9f07c099e021bc1a7c73e5cd81de026c630 T Wily & Light no Rockboard - That's Paradise (J) [T+Eng1.1(Megaman)_Interordi] NES +0cedcf804a8fce45e56ec7f4d8be454838589cc2 T Wily & Light no Rockboard - That's Paradise (J) [T+Eng1.1(Rockman)_Interordi] NES +8166ad98dc32344e803d662333bda1b2acc29035 T Wily & Light no Rockboard - That's Paradise (J) [T-Eng(Megaman)_Interordi] NES +479364d2a6bb8db8c3343ce813157a8024a2ab92 T Wily & Light no Rockboard - That's Paradise (J) [T-Eng(Rockman)_Interordi] NES +35993e347372d4496ccc387b5a29f71a1f0bdba2 T Wily & Light no Rockboard - That's Paradise (J) [T-Eng0.10_Interordi] NES 49773466c4296d77f0697c073ed66d4fe3375459 G Win, Lose or Draw (U) [!] NES 8f37e6b4dbbfcbb1c9b4e1620f0dd459837e0e06 B Win, Lose or Draw (U) [b1] NES 8993dafeff608f9c2f9a4508ac9e334795ae87be B Win, Lose or Draw (U) [o1] NES @@ -21432,17 +21432,17 @@ f324f1977d4b7840c37821990247993c26fa46fc G Wizardry - Proving Grounds of the Mad 9a7adb06a54e7bccb74583a6217b47e5a9525520 B Wizardry II - Llylgamyn no Densetsu (J) [b1] NES 56fbae974686e83054fafe06e9d8a2b6bbb82ce9 B Wizardry II - Llylgamyn no Densetsu (J) [b2] NES 026ae09c426d6eb689270b384349f20890578a82 G Wizardry III - Diamond no Kishi (J) [!] NES -61ff5043afb71553b21f04378b0e9f3179b5ef81 G Wizards & Warriors (E) [!] NES -5c135a7971013cf6e3a2243bcdd6938cf5ba4b5b G Wizards & Warriors (U) (PRG0) [!] NES -5c8df2859ddc204537fd83cadcee540faacf175e B Wizards & Warriors (U) (PRG0) [o1] NES -59e36195a3fb2a3d5fd3db02cedb0e71b54bb3cd T Wizards & Warriors (U) (PRG0) [T+Rus_Guyver] NES -f1e061a739ed0a1963a357c8df3f19fffd9b77c3 G Wizards & Warriors (U) (PRG1) [!] NES -c6f1bed4cf59c155cd8e03109cefc0f451426450 G Wizards & Warriors III - Kuros - Visions of Power (E) [!] NES -9c04e7357e5b39cfd9d0a119c52102197b4a1be0 G Wizards & Warriors III - Kuros - Visions of Power (U) [!] NES -f4c54e865c9b76e7b96045d285a0b8a81a1e8095 B Wizards & Warriors III - Kuros - Visions of Power (U) [b1] NES -5a5063fa947b0755dfb5f8313e6b7cd0384bb424 B Wizards & Warriors III - Kuros - Visions of Power (U) [b2] NES -7f2093ea1e427e54b42ef0e607f64c0cc4bce2d7 B Wizards & Warriors III - Kuros - Visions of Power (U) [o1] NES -f12e91ee96a101aad014bda73933a053219a33c3 C Wizards & Warriors III - Kuros - Visions of Power (U) [t1] NES +61ff5043afb71553b21f04378b0e9f3179b5ef81 G Wizards & Warriors (E) [!] NES +5c135a7971013cf6e3a2243bcdd6938cf5ba4b5b G Wizards & Warriors (U) (PRG0) [!] NES +5c8df2859ddc204537fd83cadcee540faacf175e B Wizards & Warriors (U) (PRG0) [o1] NES +59e36195a3fb2a3d5fd3db02cedb0e71b54bb3cd T Wizards & Warriors (U) (PRG0) [T+Rus_Guyver] NES +f1e061a739ed0a1963a357c8df3f19fffd9b77c3 G Wizards & Warriors (U) (PRG1) [!] NES +c6f1bed4cf59c155cd8e03109cefc0f451426450 G Wizards & Warriors III - Kuros - Visions of Power (E) [!] NES +9c04e7357e5b39cfd9d0a119c52102197b4a1be0 G Wizards & Warriors III - Kuros - Visions of Power (U) [!] NES +f4c54e865c9b76e7b96045d285a0b8a81a1e8095 B Wizards & Warriors III - Kuros - Visions of Power (U) [b1] NES +5a5063fa947b0755dfb5f8313e6b7cd0384bb424 B Wizards & Warriors III - Kuros - Visions of Power (U) [b2] NES +7f2093ea1e427e54b42ef0e607f64c0cc4bce2d7 B Wizards & Warriors III - Kuros - Visions of Power (U) [o1] NES +f12e91ee96a101aad014bda73933a053219a33c3 C Wizards & Warriors III - Kuros - Visions of Power (U) [t1] NES 175b452b31adac390d5a36c654aaf4de49ec19c9 B Wizzy (Formation Z Hack) [o1] NES eae3e42bc9b02382207f39edfd71b77b5228c4d4 B Wizzy (Formation Z Hack) [o2] NES 2f416726d94f7541709b61a1f1e8a4ae8d2ef14d B Wizzy (Formation Z Hack) [o3] NES @@ -21993,7 +21993,7 @@ f52a4b77d37156db3d470b7a2acf1625d041520c U Zero Pong V3.0 by Zero-Soul (PD) NES 9119581a22ac8fe03a546f0088132eaa55692abd U Zhan Guo Qun Xiong Chuan (Ch) NES 349e2e47a59a14151c190fd687de973f82ea8c69 B Zhan Guo Qun Xiong Zhuan (Ch) [b1] NES 9680484cd6a1aba6164bb07a7b556c1a90b1d9d7 U Zhan Guo Qun Xiong Zhuan (Ch) NES -54b371871d45aad6219e6394ed379dd9db24b6b8 U Zhan Guo Si Chuan Sheng (C&E) (Unl) NES +54b371871d45aad6219e6394ed379dd9db24b6b8 U Zhan Guo Si Chuan Sheng (C&E) (Unl) NES be6140cc9fb99c7ab5388dfe5c7c13fa4cfe2a3f G Zhen Ben Xi You Ji (Asder) [!] NES 902dd1345e1440b4297b1046ce0c2db26fbbca5e C Zhen Jia Hou Wang (ES-1061) (Ch) (Decrypted) [t1] NES af9e06787f450260f9810c3d4a54674f24adea1b U Zhen Jia Hou Wang (ES-1061) (Ch) (Decrypted) NES diff --git a/Assets/gamedb/gamedb_n64.txt b/Assets/gamedb/gamedb_n64.txt index 511260f3b2..ecc5fc9b51 100644 --- a/Assets/gamedb/gamedb_n64.txt +++ b/Assets/gamedb/gamedb_n64.txt @@ -555,8 +555,8 @@ A5359E35839B40C414EAE498CA633B28176629AA G Olympic Hockey 98 (Japan) N64 Glide_ 7592F4C16B8E040539B5DCC201FAB2965A5E8C8D G Onegai Monsters (Japan) N64 133F17162B2734286F9E94F64ACB1538B11506B2 G Operation WinBack (Europe) (En,Fr,De,Es,It) N64 B8F29E8EFCF51EE9A6A16E2A1E60442B4F304950 G Pachinko 365 Nichi (Japan) N64 -2111D39265A317414D359E35A7D971C4DFA5F9E1 G Paper Mario (Europe) (En,Fr,De,Es) N64 Glide_enable_hacks_for_game=15;Glide_fb_hires_buf_clear=false;Glide_fb_optimize_texrect=false;Glide_swapmode=2;Glide_fb_smart=true;Glide_fb_read_alpha=true;Glide64mk2_enable_hacks_for_game=20;Glide64mk2_hires_buf_clear=false;Glide64mk2_optimize_texrect=false;Glide64mk2_filtering=1;Glide64mk2_swapmode=2;Glide64mk2_fb_smart=true;Glide64mk2_fb_read_alpha=true;Jabo_Clear_Frame=1;GLideN64_CopyColorToRDRAM=2 -3837F44CDA784B466C9A2D99DF70D77C322B97A0 G Paper Mario (USA) N64 RiceFrameBufferOption=3;RiceRenderToTextureOption=3;RiceScreenUpdateSettingHack=4;Glide_enable_hacks_for_game=15;Glide_fb_hires_buf_clear=false;Glide_fb_optimize_texrect=false;Glide_swapmode=2;Glide_fb_smart=true;Glide_fb_read_alpha=true;Glide64mk2_enable_hacks_for_game=20;Glide64mk2_hires_buf_clear=false;Glide64mk2_optimize_texrect=false;Glide64mk2_filtering=1;Glide64mk2_swapmode=2;Glide64mk2_fb_smart=true;Glide64mk2_fb_read_alpha=true;Jabo_Clear_Frame=1;GLideN64_CopyColorToRDRAM=2 +2111D39265A317414D359E35A7D971C4DFA5F9E1 G Paper Mario (Europe) (En,Fr,De,Es) N64 Glide_enable_hacks_for_game=15;Glide_fb_hires_buf_clear=false;Glide_fb_optimize_texrect=false;Glide_swapmode=2;Glide_fb_smart=true;Glide_fb_read_alpha=true;Glide64mk2_enable_hacks_for_game=20;Glide64mk2_hires_buf_clear=false;Glide64mk2_optimize_texrect=false;Glide64mk2_filtering=1;Glide64mk2_swapmode=2;Glide64mk2_fb_smart=true;Glide64mk2_fb_read_alpha=true;Jabo_Clear_Frame=1;GLideN64_CopyColorToRDRAM=1 +3837F44CDA784B466C9A2D99DF70D77C322B97A0 G Paper Mario (USA) N64 RiceFrameBufferOption=3;RiceRenderToTextureOption=3;RiceScreenUpdateSettingHack=4;Glide_enable_hacks_for_game=15;Glide_fb_hires_buf_clear=false;Glide_fb_optimize_texrect=false;Glide_swapmode=2;Glide_fb_smart=true;Glide_fb_read_alpha=true;Glide64mk2_enable_hacks_for_game=20;Glide64mk2_hires_buf_clear=false;Glide64mk2_optimize_texrect=false;Glide64mk2_filtering=1;Glide64mk2_swapmode=2;Glide64mk2_fb_smart=true;Glide64mk2_fb_read_alpha=true;Jabo_Clear_Frame=1;GLideN64_CopyColorToRDRAM=1 7DB4808042B9651B47592E814AC4C125B51D4D2F G Paperboy (Europe) N64 B043C47B9758FA6BB289CA7DBA2068BDA6CAFA3A G Paperboy (USA) N64 9887A0E4BFE3C5E85E31638853574069F6C41CD3 G Parlor! Pro 64 - Pachinko Jikki Simulation Game (Japan) N64 Glide_force_microcheck=true;Glide64mk2_force_microcheck=true;Glide64mk2_filtering=1 diff --git a/Assets/gamedb/gamedb_nes.txt b/Assets/gamedb/gamedb_nes.txt index b837ef1be5..ec808e4165 100644 --- a/Assets/gamedb/gamedb_nes.txt +++ b/Assets/gamedb/gamedb_nes.txt @@ -305,7 +305,6 @@ sha1:17473C223453D2D80FCB9DCFA317947287DC5C52 Xing He Zhan Shi (China) (Unl) NE sha1:B1C74236FD17FAB4AB9AA6AB28E38864C66D6255 Pocahontus (UNL) NES board=MAPPER182;PRG=256;CHR=256;WRAM=8;PAD_H=1 sha1:5FA23F88432006DCF6874EA36E9E7DA8934427BE Super Donkey Kong (Unl) NES board=MAPPER182;PRG=128;CHR=128;WRAM=8;PAD_H=1 sha1:8A7DAB8B78DA1C5EA159BA9EEC00FF97742245F1 B Super Donkey Kong (Unl) [b1] NES board=MAPPER182;PRG=128;CHR=128;WRAM=8;PAD_H=1 -sha1:8A7DAB8B78DA1C5EA159BA9EEC00FF97742245F1 O Super Donkey Kong (Unl) [o1] NES board=MAPPER182;PRG=128;CHR=128;WRAM=8;PAD_H=1 ;wrong vram info sha1:32D71DD6C5A8D78A918FE1B9D6D6C4A570D9652D Oeka Kids Anpanman no Hiragana Daisuki (J) NES board=MAPPER096;VRAM=32 diff --git a/BizHawk.Client.ApiHawk/BizHawk.Client.ApiHawk.csproj b/BizHawk.Client.ApiHawk/BizHawk.Client.ApiHawk.csproj index e80de5d5ae..f3aed78ae7 100644 --- a/BizHawk.Client.ApiHawk/BizHawk.Client.ApiHawk.csproj +++ b/BizHawk.Client.ApiHawk/BizHawk.Client.ApiHawk.csproj @@ -33,7 +33,9 @@ v4.6.1 512 - 1591 + 8.0 + 1591 + diff --git a/BizHawk.Client.ApiHawk/BizHawk.Client.ApiHawk.csproj.DotSettings b/BizHawk.Client.ApiHawk/BizHawk.Client.ApiHawk.csproj.DotSettings index 73e96563f9..b9fd6ee4f5 100644 --- a/BizHawk.Client.ApiHawk/BizHawk.Client.ApiHawk.csproj.DotSettings +++ b/BizHawk.Client.ApiHawk/BizHawk.Client.ApiHawk.csproj.DotSettings @@ -1,2 +1,2 @@  - CSharp60 \ No newline at end of file + CSharp80 \ No newline at end of file diff --git a/BizHawk.Client.ApiHawk/Classes/BizHawkSystemIdToCoreSystemEnumConverter.cs b/BizHawk.Client.ApiHawk/Classes/BizHawkSystemIdToCoreSystemEnumConverter.cs index dca4452785..16da2eddb0 100644 --- a/BizHawk.Client.ApiHawk/Classes/BizHawkSystemIdToCoreSystemEnumConverter.cs +++ b/BizHawk.Client.ApiHawk/Classes/BizHawkSystemIdToCoreSystemEnumConverter.cs @@ -117,6 +117,9 @@ namespace BizHawk.Client.ApiHawk case "GB4x": return CoreSystem.GB3x; + case "MAME": + return CoreSystem.MAME; + case "VB": case "NGP": case "DNGP": diff --git a/BizHawk.Client.Common/7z/LibraryManager.cs b/BizHawk.Client.Common/7z/LibraryManager.cs index 6f2f375862..1f93b0e8c1 100644 --- a/BizHawk.Client.Common/7z/LibraryManager.cs +++ b/BizHawk.Client.Common/7z/LibraryManager.cs @@ -134,54 +134,54 @@ namespace SevenZip /// Archive format public static void LoadLibrary(object user, Enum format) { - lock (_syncRoot) - { - if (_inArchives == null -#if COMPRESS - || _outArchives == null -#endif - ) + lock (_syncRoot) { - Init(); - } + if (_inArchives == null +#if COMPRESS + || _outArchives == null +#endif + ) + { + Init(); + } #if !WINCE && !MONO - if (_modulePtr == IntPtr.Zero) - { - //zero 29-oct-2012 - this check isnt useful since LoadLibrary can pretty much check for the same thing. and it wrecks our dll relocation scheme - //if (!File.Exists(_libraryFileName)) - //{ - // throw new SevenZipLibraryException("DLL file does not exist."); - //} - if ((_modulePtr = libLoader.LoadPlatformSpecific(_libraryFileName)) == IntPtr.Zero) + if (_modulePtr == IntPtr.Zero) { - //try a different directory - string alternateFilename = Path.Combine(Path.Combine(Path.GetDirectoryName(_libraryFileName),"dll"),"7z.dll"); - if ((_modulePtr = libLoader.LoadPlatformSpecific(alternateFilename)) == IntPtr.Zero) - throw new SevenZipLibraryException("failed to load library."); - } - if (libLoader.GetProcAddr(_modulePtr, "GetHandlerProperty") == IntPtr.Zero) - { - libLoader.FreePlatformSpecific(_modulePtr); - throw new SevenZipLibraryException("library is invalid."); - } - } -#endif - if (format is InArchiveFormat) - { - InitUserInFormat(user, (InArchiveFormat) format); - return; - } -#if COMPRESS - if (format is OutArchiveFormat) - { - InitUserOutFormat(user, (OutArchiveFormat) format); - return; - } -#endif - throw new ArgumentException( - "Enum " + format + " is not a valid archive format attribute!"); - } + //zero 29-oct-2012 - this check isnt useful since LoadOrNull can pretty much check for the same thing. and it wrecks our dll relocation scheme + //if (!File.Exists(_libraryFileName)) + //{ + // throw new SevenZipLibraryException("DLL file does not exist."); + //} + var newPtr = libLoader.LoadOrNull(_libraryFileName); + if (!newPtr.HasValue) + { + //try a different directory + newPtr = libLoader.LoadOrNull(Path.Combine(Path.Combine(Path.GetDirectoryName(_libraryFileName), "dll"), "7z.dll")); + if (!newPtr.HasValue) throw new SevenZipLibraryException("failed to load library."); + } + _modulePtr = newPtr.Value; + if (libLoader.GetProcAddr(_modulePtr, "GetHandlerProperty") == IntPtr.Zero) + { + libLoader.FreeByPtr(_modulePtr); + throw new SevenZipLibraryException("library is invalid."); + } + } +#endif + if (format is InArchiveFormat) + { + InitUserInFormat(user, (InArchiveFormat) format); + return; + } +#if COMPRESS + if (format is OutArchiveFormat) + { + InitUserOutFormat(user, (OutArchiveFormat) format); + return; + } +#endif + throw new ArgumentException("Enum " + format + " is not a valid archive format attribute!"); + } } /*/// @@ -435,7 +435,7 @@ namespace SevenZip if (_totalUsers == 0) { #if !WINCE && !MONO - libLoader.FreePlatformSpecific(_modulePtr); + libLoader.FreeByPtr(_modulePtr); #endif _modulePtr = IntPtr.Zero; diff --git a/BizHawk.Client.Common/Api/CoreSystem.cs b/BizHawk.Client.Common/Api/CoreSystem.cs index ae86c41564..3fad8c8563 100644 --- a/BizHawk.Client.Common/Api/CoreSystem.cs +++ b/BizHawk.Client.Common/Api/CoreSystem.cs @@ -34,8 +34,9 @@ ZXSpectrum, AmstradCPC, GGL, - ChannelF, GB3x, - GB4x + GB4x, + ChannelF, + MAME } } diff --git a/BizHawk.Client.Common/BizHawk.Client.Common.csproj b/BizHawk.Client.Common/BizHawk.Client.Common.csproj index ea09e5b1f0..66f156bd0e 100644 --- a/BizHawk.Client.Common/BizHawk.Client.Common.csproj +++ b/BizHawk.Client.Common/BizHawk.Client.Common.csproj @@ -13,6 +13,7 @@ v4.6.1 512 + 8.0 None @@ -127,6 +128,7 @@ + diff --git a/BizHawk.Client.Common/BizHawk.Client.Common.csproj.DotSettings b/BizHawk.Client.Common/BizHawk.Client.Common.csproj.DotSettings index 73e96563f9..b9fd6ee4f5 100644 --- a/BizHawk.Client.Common/BizHawk.Client.Common.csproj.DotSettings +++ b/BizHawk.Client.Common/BizHawk.Client.Common.csproj.DotSettings @@ -1,2 +1,2 @@  - CSharp60 \ No newline at end of file + CSharp80 \ No newline at end of file diff --git a/BizHawk.Client.Common/OpenAdvanced.cs b/BizHawk.Client.Common/OpenAdvanced.cs index 251d49d89e..88fbee6689 100644 --- a/BizHawk.Client.Common/OpenAdvanced.cs +++ b/BizHawk.Client.Common/OpenAdvanced.cs @@ -36,6 +36,7 @@ namespace BizHawk.Client.Common public const string OpenRom = "OpenRom"; public const string Libretro = "Libretro"; public const string LibretroNoGame = "LibretroNoGame"; + public const string MAME = "MAME"; } @@ -55,12 +56,33 @@ namespace BizHawk.Client.Common string type = text.Substring(0, idx); string token = text.Substring(idx + 1); IOpenAdvanced ioa; - if (type == OpenAdvancedTypes.OpenRom) ioa = new OpenAdvanced_OpenRom(); - else if (type == OpenAdvancedTypes.Libretro) ioa = new OpenAdvanced_Libretro(); - else if (type == OpenAdvancedTypes.LibretroNoGame) ioa = new OpenAdvanced_LibretroNoGame(); - else ioa = null; - if (ioa == null) - throw new InvalidOperationException($"{nameof(IOpenAdvanced)} deserialization error"); + + if (type == OpenAdvancedTypes.OpenRom) + { + ioa = new OpenAdvanced_OpenRom(); + } + else if (type == OpenAdvancedTypes.Libretro) + { + ioa = new OpenAdvanced_Libretro(); + } + else if (type == OpenAdvancedTypes.LibretroNoGame) + { + ioa = new OpenAdvanced_LibretroNoGame(); + } + else if (type == OpenAdvancedTypes.MAME) + { + ioa = new OpenAdvanced_MAME(); + } + else + { + ioa = null; + } + + if (ioa == null) + { + throw new InvalidOperationException($"{nameof(IOpenAdvanced)} deserialization error"); + } + ioa.Deserialize(token); return ioa; } @@ -161,4 +183,26 @@ namespace BizHawk.Client.Common tw.Write(Path); } } + + public class OpenAdvanced_MAME : IOpenAdvanced + { + public OpenAdvanced_MAME() + { } + + public string Path; + + public string TypeName { get { return "MAME"; } } + public string DisplayName { get { return Path; } } + public string SimplePath { get { return Path; } } + + public void Deserialize(string str) + { + Path = str; + } + + public void Serialize(TextWriter tw) + { + tw.Write(Path); + } + } } \ No newline at end of file diff --git a/BizHawk.Client.Common/RecentFiles.cs b/BizHawk.Client.Common/RecentFiles.cs index b3fa4b91c6..19ca7df854 100644 --- a/BizHawk.Client.Common/RecentFiles.cs +++ b/BizHawk.Client.Common/RecentFiles.cs @@ -89,17 +89,7 @@ namespace BizHawk.Client.Common { if (!Frozen) { - var removed = false; - foreach (var recent in recentlist.ToList()) - { - if (string.Compare(newFile, recent, StringComparison.CurrentCultureIgnoreCase) == 0) - { - recentlist.Remove(newFile); // intentionally keeps iterating after this to remove duplicate instances, though those should never exist in the first place - removed = true; - } - } - - return removed; + return recentlist.RemoveAll(recent => string.Compare(newFile, recent, StringComparison.CurrentCultureIgnoreCase) == 0) != 0; // none removed => return false } return false; diff --git a/BizHawk.Client.Common/RomLoader.cs b/BizHawk.Client.Common/RomLoader.cs index a8e820898f..58e417333a 100644 --- a/BizHawk.Client.Common/RomLoader.cs +++ b/BizHawk.Client.Common/RomLoader.cs @@ -24,6 +24,7 @@ using BizHawk.Emulation.Cores.Sega.Saturn; using BizHawk.Emulation.Cores.Sony.PSP; using BizHawk.Emulation.Cores.Sony.PSX; using BizHawk.Emulation.Cores.Computers.SinclairSpectrum; +using BizHawk.Emulation.Cores.Arcades.MAME; using BizHawk.Emulation.DiscSystem; using GPGX64 = BizHawk.Emulation.Cores.Consoles.Sega.gpgx; @@ -171,7 +172,7 @@ namespace BizHawk.Client.Common return false; } - public bool AsLibretro { get; set; } + public AdvancedRomLoaderType AdvancedLoader { get; set; } private bool HandleArchiveBinding(HawkFile file) { @@ -268,8 +269,13 @@ namespace BizHawk.Client.Common // only try mounting a file if a filename was given if (!string.IsNullOrEmpty(path)) { - // lets not use this unless we need to - // file.NonArchiveExtensions = romExtensions; + // MAME uses these extensions for arcade ROMs, but also accepts all sorts of variations of archives, folders, and files. if we let archive loader handle this, it won't know where to stop, since it'd require MAME's ROM database (which contains ROM names and blob hashes) to look things up, and even then it might be confused by archive/folder structure + // so assume the user provides the proper ROM directly, and handle possible errors later + if (AdvancedLoader == AdvancedRomLoaderType.MAMELaunchGame) + { + file.NonArchiveExtensions = new[] { ".zip", ".7z" }; + } + file.Open(path); // if the provided file doesnt even exist, give up! @@ -289,7 +295,7 @@ namespace BizHawk.Client.Common { string ext = null; - if (AsLibretro) + if (AdvancedLoader == AdvancedRomLoaderType.LibretroLaunchGame) { string codePathPart = Path.GetFileNameWithoutExtension(nextComm.LaunchLibretroCore); @@ -1152,6 +1158,9 @@ namespace BizHawk.Client.Common nextEmulator = new Octoshock(nextComm, null, null, rom.FileData, GetCoreSettings(), GetCoreSyncSettings()); nextEmulator.CoreComm.RomStatusDetails = "PSX etc."; break; + case "Arcade": + nextEmulator = new MAME(nextComm, file.Directory, file.CanonicalName); + break; case "GEN": if (Global.Config.CoreForcingViaGameDB && game.ForcedCore?.ToLower() == "pico") { diff --git a/BizHawk.Client.Common/SaveSlotManager.cs b/BizHawk.Client.Common/SaveSlotManager.cs index 8584312e7e..7ec9588a22 100644 --- a/BizHawk.Client.Common/SaveSlotManager.cs +++ b/BizHawk.Client.Common/SaveSlotManager.cs @@ -97,12 +97,6 @@ namespace BizHawk.Client.Common return _redo[slot]; } - public void Clear() - { - ClearRedoList(); - Update(); - } - public void SwapBackupSavestate(string path) { // Takes the .state and .bak files and swaps them diff --git a/BizHawk.Client.Common/SystemInfo.cs b/BizHawk.Client.Common/SystemInfo.cs index 29be9a4bc5..880074f08f 100644 --- a/BizHawk.Client.Common/SystemInfo.cs +++ b/BizHawk.Client.Common/SystemInfo.cs @@ -223,6 +223,11 @@ namespace BizHawk.Client.Common /// public static SystemInfo ChannelF { get; } = new SystemInfo("Channel F", CoreSystem.ChannelF, 2); + /// + /// Gets the instance for MAME + /// + public static SystemInfo MAME { get; } = new SystemInfo("MAME", CoreSystem.MAME, 4); + #endregion Get SystemInfo /// diff --git a/BizHawk.Client.Common/config/Binding.cs b/BizHawk.Client.Common/config/Binding.cs index c2ec1c1738..b2d9ad6d6a 100644 --- a/BizHawk.Client.Common/config/Binding.cs +++ b/BizHawk.Client.Common/config/Binding.cs @@ -96,13 +96,8 @@ namespace BizHawk.Client.Common } } - List entriesToRemove = (from entry in Bindings let binding = DefaultValues.FirstOrDefault(b => b.DisplayName == entry.DisplayName) where binding == null select entry).ToList(); - // Remove entries that no longer exist in defaults - foreach (Binding entry in entriesToRemove) - { - Bindings.Remove(entry); - } + Bindings.RemoveAll(entry => DefaultValues.All(b => b.DisplayName != entry.DisplayName)); } private static List _defaultValues; diff --git a/BizHawk.Client.Common/config/Config.cs b/BizHawk.Client.Common/config/Config.cs index 2603fd3329..b89ce28eb8 100644 --- a/BizHawk.Client.Common/config/Config.cs +++ b/BizHawk.Client.Common/config/Config.cs @@ -104,6 +104,8 @@ namespace BizHawk.Client.Common public int MainHeight = -1; public bool RunInBackground = true; public bool AcceptBackgroundInput = false; + public bool AcceptBackgroundInputControllerOnly = false; + public bool HandleAlternateKeyboardLayouts = false; public bool SingleInstanceMode = false; public bool AllowUD_LR = false; public bool ForbidUD_LR = false; diff --git a/BizHawk.Client.Common/config/PathEntry.cs b/BizHawk.Client.Common/config/PathEntry.cs index 8f8e6776a5..2c91df1807 100644 --- a/BizHawk.Client.Common/config/PathEntry.cs +++ b/BizHawk.Client.Common/config/PathEntry.cs @@ -119,7 +119,7 @@ namespace BizHawk.Client.Common } // Add missing displaynames - var missingDisplayPaths = Paths.Where(p => p.SystemDisplayName == null).ToList(); + var missingDisplayPaths = Paths.Where(p => p.SystemDisplayName == null); foreach (PathEntry path in missingDisplayPaths) { path.SystemDisplayName = DefaultValues.First(p => p.System == path.System).SystemDisplayName; diff --git a/BizHawk.Client.Common/config/RestoreDefaultsAttribute.cs b/BizHawk.Client.Common/config/RestoreDefaultsAttribute.cs new file mode 100644 index 0000000000..eb8584cd6e --- /dev/null +++ b/BizHawk.Client.Common/config/RestoreDefaultsAttribute.cs @@ -0,0 +1,12 @@ +using System; + +namespace BizHawk.Client.Common +{ + /// + /// Defines a method to be called when a tool dialog's Restore Defaults method is called + /// + [AttributeUsage(AttributeTargets.Method)] + public class RestoreDefaultsAttribute : Attribute + { + } +} diff --git a/BizHawk.Client.Common/lua/EmuLuaLibrary.Events.cs b/BizHawk.Client.Common/lua/EmuLuaLibrary.Events.cs index 1ec246820e..da03cbd7eb 100644 --- a/BizHawk.Client.Common/lua/EmuLuaLibrary.Events.cs +++ b/BizHawk.Client.Common/lua/EmuLuaLibrary.Events.cs @@ -50,78 +50,66 @@ namespace BizHawk.Client.Common public void CallSaveStateEvent(string name) { - var lfs = _luaFunctions.Where(l => l.Event == "OnSavestateSave").ToList(); - if (lfs.Any()) + var lfs = _luaFunctions.Where(l => l.Event == "OnSavestateSave"); + try { - try + foreach (var lf in lfs) { - foreach (var lf in lfs) - { - lf.Call(name); - } - } - catch (Exception e) - { - Log($"error running function attached by lua function event.onsavestate\nError message: {e.Message}"); + lf.Call(name); } } + catch (Exception e) + { + Log($"error running function attached by lua function event.onsavestate\nError message: {e.Message}"); + } } public void CallLoadStateEvent(string name) { - var lfs = _luaFunctions.Where(l => l.Event == "OnSavestateLoad").ToList(); - if (lfs.Any()) + var lfs = _luaFunctions.Where(l => l.Event == "OnSavestateLoad"); + try { - try + foreach (var lf in lfs) { - foreach (var lf in lfs) - { - lf.Call(name); - } - } - catch (Exception e) - { - Log($"error running function attached by lua function event.onloadstate\nError message: {e.Message}"); + lf.Call(name); } } + catch (Exception e) + { + Log($"error running function attached by lua function event.onloadstate\nError message: {e.Message}"); + } } public void CallFrameBeforeEvent() { - var lfs = _luaFunctions.Where(l => l.Event == "OnFrameStart").ToList(); - if (lfs.Any()) + var lfs = _luaFunctions.Where(l => l.Event == "OnFrameStart"); + try { - try + foreach (var lf in lfs) { - foreach (var lf in lfs) - { - lf.Call(); - } - } - catch (Exception e) - { - Log($"error running function attached by lua function event.onframestart\nError message: {e.Message}"); + lf.Call(); } } + catch (Exception e) + { + Log($"error running function attached by lua function event.onframestart\nError message: {e.Message}"); + } } public void CallFrameAfterEvent() { - var lfs = _luaFunctions.Where(l => l.Event == "OnFrameEnd").ToList(); - if (lfs.Any()) + var lfs = _luaFunctions.Where(l => l.Event == "OnFrameEnd"); + try { - try + foreach (var lf in lfs) { - foreach (var lf in lfs) - { - lf.Call(); - } - } - catch (Exception e) - { - Log($"error running function attached by lua function event.onframeend\nError message: {e.Message}"); + lf.Call(); } } + catch (Exception e) + { + Log($"error running function attached by lua function event.onframeend\nError message: {e.Message}"); + } } private bool N64CoreTypeDynarec() diff --git a/BizHawk.Client.Common/lua/LuaFile.cs b/BizHawk.Client.Common/lua/LuaFile.cs index 63ae59c75e..dddb59a85d 100644 --- a/BizHawk.Client.Common/lua/LuaFile.cs +++ b/BizHawk.Client.Common/lua/LuaFile.cs @@ -48,6 +48,11 @@ public void Stop() { + if (Thread == null) + { + return; + } + State = RunState.Disabled; //if(NLua.Lua.WhichLua == "NLua") Thread.GetTable("keepalives")[Thread] = null; diff --git a/BizHawk.Client.Common/lua/LuaFileList.cs b/BizHawk.Client.Common/lua/LuaFileList.cs index 678a4c7809..a8148df357 100644 --- a/BizHawk.Client.Common/lua/LuaFileList.cs +++ b/BizHawk.Client.Common/lua/LuaFileList.cs @@ -140,11 +140,19 @@ namespace BizHawk.Client.Common var sb = new StringBuilder(); foreach (var file in this) { - sb - .Append(file.Enabled ? "1" : "0") - .Append(' ') - .Append(PathManager.MakeRelativeTo(PathManager.MakeAbsolutePath(file.Path, ""), Path.GetDirectoryName(path))) - .AppendLine(); + if (file.IsSeparator) + { + sb.AppendLine("---"); + } + else + { + sb + .Append(file.Enabled ? "1" : "0") + .Append(' ') + .Append(PathManager.MakeRelativeTo(PathManager.MakeAbsolutePath(file.Path, "") + , Path.GetDirectoryName(path))) + .AppendLine(); + } } sw.Write(sb.ToString()); diff --git a/BizHawk.Client.Common/movie/bk2/Bk2ControllerAdapter.cs b/BizHawk.Client.Common/movie/bk2/Bk2ControllerAdapter.cs index 5c49ef6f5d..fbcd18319f 100644 --- a/BizHawk.Client.Common/movie/bk2/Bk2ControllerAdapter.cs +++ b/BizHawk.Client.Common/movie/bk2/Bk2ControllerAdapter.cs @@ -160,7 +160,7 @@ namespace BizHawk.Client.Common { var def = Global.Emulator.ControllerDefinition; var trimmed = mnemonic.Replace("|", ""); - var buttons = Definition.ControlsOrdered.SelectMany(c => c).ToList(); + var buttons = Definition.ControlsOrdered.SelectMany(c => c); var iterator = 0; foreach (var key in buttons) diff --git a/BizHawk.Client.Common/movie/conversions/MovieConversionExtensions.cs b/BizHawk.Client.Common/movie/conversions/MovieConversionExtensions.cs index a1450bf56a..6fe710524f 100644 --- a/BizHawk.Client.Common/movie/conversions/MovieConversionExtensions.cs +++ b/BizHawk.Client.Common/movie/conversions/MovieConversionExtensions.cs @@ -338,7 +338,7 @@ namespace BizHawk.Client.Common.MovieConversionExtensions if (Global.Emulator is SMS && (Global.Emulator as SMS).IsSG1000) { movie.HeaderEntries.Add("IsSGMode", "1"); - } + } if (Global.Emulator is SMS && (Global.Emulator as SMS).IsGameGear) { diff --git a/BizHawk.Client.Common/movie/import/IMovieImport.cs b/BizHawk.Client.Common/movie/import/IMovieImport.cs index 91191b7342..c35caddca8 100644 --- a/BizHawk.Client.Common/movie/import/IMovieImport.cs +++ b/BizHawk.Client.Common/movie/import/IMovieImport.cs @@ -68,14 +68,8 @@ namespace BizHawk.Client.Common public class ImportResult { - public ImportResult() - { - Warnings = new List(); - Errors = new List(); - } - - public IList Warnings { get; private set; } - public IList Errors { get; } + public IList Warnings { get; } = new List(); + public IList Errors { get; } = new List(); public Bk2Movie Movie { get; set; } } @@ -88,6 +82,6 @@ namespace BizHawk.Client.Common Extension = extension; } - public string Extension { get; private set; } + public string Extension { get; } } } diff --git a/BizHawk.Client.Common/movie/import/MovieImport.cs b/BizHawk.Client.Common/movie/import/MovieImport.cs index 6f16c63120..89152ab11d 100644 --- a/BizHawk.Client.Common/movie/import/MovieImport.cs +++ b/BizHawk.Client.Common/movie/import/MovieImport.cs @@ -42,23 +42,16 @@ namespace BizHawk.Client.Common public static void ProcessMovieImport(string fn, Action conversionErrorCallback, Action messageCallback) { var d = PathManager.MakeAbsolutePath(Global.Config.PathEntries.MoviesPathFragment, null); - string errorMsg; - string warningMsg; - var m = ImportFile(fn, out errorMsg, out warningMsg); + var m = ImportFile(fn, out var errorMsg, out var warningMsg); if (!string.IsNullOrWhiteSpace(errorMsg)) { conversionErrorCallback(errorMsg); } - if (!string.IsNullOrWhiteSpace(warningMsg)) - { - messageCallback(warningMsg); - } - else - { - messageCallback($"{Path.GetFileName(fn)} imported as {m.Filename}"); - } + messageCallback(!string.IsNullOrWhiteSpace(warningMsg) + ? warningMsg + : $"{Path.GetFileName(fn)} imported as {m.Filename}"); if (!Directory.Exists(d)) { @@ -67,7 +60,7 @@ namespace BizHawk.Client.Common } // Attempt to import another type of movie file into a movie object. - public static Bk2Movie ImportFile(string path, out string errorMsg, out string warningMsg) + public static IMovie ImportFile(string path, out string errorMsg, out string warningMsg) { errorMsg = ""; warningMsg = ""; @@ -118,25 +111,15 @@ namespace BizHawk.Client.Common private static IEnumerable ImportersForExtension(string ext) { - var info = typeof(MovieImport).Module; - var importers = from t in info.GetTypes() - where typeof(IMovieImport).IsAssignableFrom(t) - && TypeImportsExtension(t, ext) - select t; - - return importers; + return typeof(MovieImport).Module + .GetTypes() + .Where(t => typeof(IMovieImport).IsAssignableFrom(t)); } private static bool TypeImportsExtension(Type t, string ext) { var attrs = (ImportExtensionAttribute[])t.GetCustomAttributes(typeof(ImportExtensionAttribute), inherit: false); - - if (attrs.Any(a => a.Extension.ToUpper() == ext.ToUpper())) - { - return true; - } - - return false; + return attrs.Any(a => a.Extension.ToUpper() == ext.ToUpper()); } private static BkmMovie LegacyImportFile(string ext, string path, out string errorMsg, out string warningMsg) @@ -252,9 +235,12 @@ namespace BizHawk.Client.Common private static IController EmptyLmsvFrame(string line) { - var emptyController = new SimpleController { Definition = new ControllerDefinition { Name = "SNES Controller" } }; - emptyController["Reset"] = false; - emptyController["Power"] = false; + var emptyController = new SimpleController + { + Definition = new ControllerDefinition { Name = "SNES Controller" } + , ["Reset"] = false + , ["Power"] = false + }; string[] buttons = { "B", "Y", "Select", "Start", "Up", "Down", "Left", "Right", "A", "X", "L", "R" }; string[] sections = line.Split('|'); @@ -263,9 +249,9 @@ namespace BizHawk.Client.Common int player = section - 1; // We start with 1 string prefix = $"P{player} "; // "P1" - for (int button = 0; button < buttons.Length; button++) + foreach (var b in buttons) { - emptyController[prefix + buttons[button]] = false; + emptyController[prefix + b] = false; } } diff --git a/BizHawk.Client.Common/tools/CheatList.cs b/BizHawk.Client.Common/tools/CheatList.cs index 1ec255a96e..01702817df 100644 --- a/BizHawk.Client.Common/tools/CheatList.cs +++ b/BizHawk.Client.Common/tools/CheatList.cs @@ -222,7 +222,7 @@ namespace BizHawk.Client.Common public void RemoveRange(IEnumerable cheats) { - foreach (var cheat in cheats.ToList()) + foreach (var cheat in cheats.ToList()) // enumerate passed IEnumerable because it may depend on the value of _cheatList { _cheatList.Remove(cheat); } @@ -232,12 +232,7 @@ namespace BizHawk.Client.Common public void RemoveRange(IEnumerable watches) { - var removeList = _cheatList.Where(cheat => watches.Any(w => w == cheat)).ToList(); - foreach (var cheat in removeList) - { - _cheatList.Remove(cheat); - } - + _cheatList.RemoveAll(cheat => watches.Any(w => w == cheat)); Changes = true; } @@ -389,7 +384,9 @@ namespace BizHawk.Client.Common } else { - // Set to hex for saving + // Set to hex for saving + var temp_cheat_type = cheat.Type; + cheat.SetType(DisplayType.Hex); sb @@ -404,6 +401,9 @@ namespace BizHawk.Client.Common .Append((cheat.BigEndian ?? false) ? '1' : '0').Append('\t') .Append(cheat.ComparisonType).Append('\t') .AppendLine(); + + cheat.SetType(temp_cheat_type); + } } diff --git a/BizHawk.Client.Common/tools/RamSearchEngine.cs b/BizHawk.Client.Common/tools/RamSearchEngine.cs index 945312ff44..c65d589143 100644 --- a/BizHawk.Client.Common/tools/RamSearchEngine.cs +++ b/BizHawk.Client.Common/tools/RamSearchEngine.cs @@ -341,8 +341,7 @@ namespace BizHawk.Client.Common } var addresses = watches.Select(w => w.Address); - var removeList = _watchList.Where(w => addresses.Contains(w.Address)).ToList(); - _watchList = _watchList.Except(removeList).ToList(); + _watchList.RemoveAll(w => addresses.Contains(w.Address)); } public void RemoveRange(IEnumerable indices) diff --git a/BizHawk.Client.Common/tools/Watch/WatchList/WatchList.cs b/BizHawk.Client.Common/tools/Watch/WatchList/WatchList.cs index 833e3595e8..96999aa9b1 100644 --- a/BizHawk.Client.Common/tools/Watch/WatchList/WatchList.cs +++ b/BizHawk.Client.Common/tools/Watch/WatchList/WatchList.cs @@ -388,15 +388,8 @@ namespace BizHawk.Client.Common /// at the specified index public Watch this[int index] { - get - { - return _watchList[index]; - } - - set - { - _watchList[index] = value; - } + get => _watchList[index]; + set => _watchList[index] = value; } #endregion IList @@ -607,14 +600,7 @@ namespace BizHawk.Client.Common CurrentFileName = path; } - if (!append) - { - Changes = false; - } - else - { - Changes = true; - } + Changes = append; return true; } diff --git a/BizHawk.Client.DBMan/BizHawk.Client.DBMan.csproj b/BizHawk.Client.DBMan/BizHawk.Client.DBMan.csproj index e65442660a..6d14eca92e 100644 --- a/BizHawk.Client.DBMan/BizHawk.Client.DBMan.csproj +++ b/BizHawk.Client.DBMan/BizHawk.Client.DBMan.csproj @@ -39,6 +39,7 @@ 512 true + 8.0 diff --git a/BizHawk.Client.DBMan/BizHawk.Client.DBMan.csproj.DotSettings b/BizHawk.Client.DBMan/BizHawk.Client.DBMan.csproj.DotSettings index 73e96563f9..b9fd6ee4f5 100644 --- a/BizHawk.Client.DBMan/BizHawk.Client.DBMan.csproj.DotSettings +++ b/BizHawk.Client.DBMan/BizHawk.Client.DBMan.csproj.DotSettings @@ -1,2 +1,2 @@  - CSharp60 \ No newline at end of file + CSharp80 \ No newline at end of file diff --git a/BizHawk.Client.DBMan/DATTools/NOINTROParser.cs b/BizHawk.Client.DBMan/DATTools/NOINTROParser.cs index de710c70d2..b64be85b47 100644 --- a/BizHawk.Client.DBMan/DATTools/NOINTROParser.cs +++ b/BizHawk.Client.DBMan/DATTools/NOINTROParser.cs @@ -188,11 +188,11 @@ namespace BizHawk.Client.DBMan // process dump info flags and other info contained in [] if (nameString.Contains("[") && nameString.Contains("]")) { - List e = nameString.ToString().Split('[', ']').ToList(); - // remove first entry (this is the bit before the [] entries start - e.RemoveAt(0); - // remove empty entries - e = e.Where(s => !string.IsNullOrWhiteSpace(s)).Distinct().ToList(); + var e = nameString.Split('[', ']') + .Skip(1) // remove first entry (this is the bit before the [] entries start) + .Where(s => !string.IsNullOrWhiteSpace(s)) // remove empty entries + .Distinct() + .ToList(); if (e.Count > 0) { diff --git a/BizHawk.Client.DBMan/DATTools/TOSECParser.cs b/BizHawk.Client.DBMan/DATTools/TOSECParser.cs index 7ab55b2036..25f2834476 100644 --- a/BizHawk.Client.DBMan/DATTools/TOSECParser.cs +++ b/BizHawk.Client.DBMan/DATTools/TOSECParser.cs @@ -206,11 +206,11 @@ namespace BizHawk.Client.DBMan // process dump info flags and other info contained in [] if (nameString.Contains("[") && nameString.Contains("]")) { - List e = nameString.ToString().Split('[', ']').ToList(); - // remove first entry (this is the bit before the [] entries start - e.RemoveAt(0); - // remove empty entries - e = e.Where(s => !string.IsNullOrWhiteSpace(s)).Distinct().ToList(); + var e = nameString.Split('[', ']') + .Skip(1) // remove first entry (this is the bit before the [] entries start) + .Where(s => !string.IsNullOrWhiteSpace(s)) // remove empty entries + .Distinct() + .ToList(); if (e.Count > 0) { diff --git a/BizHawk.Client.DiscoHawk/BizHawk.Client.DiscoHawk.csproj b/BizHawk.Client.DiscoHawk/BizHawk.Client.DiscoHawk.csproj index 19809199c9..e45f56b5ce 100644 --- a/BizHawk.Client.DiscoHawk/BizHawk.Client.DiscoHawk.csproj +++ b/BizHawk.Client.DiscoHawk/BizHawk.Client.DiscoHawk.csproj @@ -32,6 +32,7 @@ false true + 8.0 true diff --git a/BizHawk.Client.DiscoHawk/BizHawk.Client.DiscoHawk.csproj.DotSettings b/BizHawk.Client.DiscoHawk/BizHawk.Client.DiscoHawk.csproj.DotSettings index 73e96563f9..b9fd6ee4f5 100644 --- a/BizHawk.Client.DiscoHawk/BizHawk.Client.DiscoHawk.csproj.DotSettings +++ b/BizHawk.Client.DiscoHawk/BizHawk.Client.DiscoHawk.csproj.DotSettings @@ -1,2 +1,2 @@  - CSharp60 \ No newline at end of file + CSharp80 \ No newline at end of file diff --git a/BizHawk.Client.EmuHawk/Api/ApiManager.cs b/BizHawk.Client.EmuHawk/Api/ApiManager.cs index 9dd5b71087..fdb3f836f7 100644 --- a/BizHawk.Client.EmuHawk/Api/ApiManager.cs +++ b/BizHawk.Client.EmuHawk/Api/ApiManager.cs @@ -23,15 +23,12 @@ namespace BizHawk.Client.EmuHawk .Where(t => typeof(IExternalApi).IsAssignableFrom(t)) .Where(t => t.IsSealed) .Where(t => ServiceInjector.IsAvailable(serviceProvider, t)) - .ToList(); - - apis.AddRange( - Assembly - .GetAssembly(typeof(ApiContainer)) - .GetTypes() - .Where(t => typeof(IExternalApi).IsAssignableFrom(t)) - .Where(t => t.IsSealed) - .Where(t => ServiceInjector.IsAvailable(serviceProvider, t))); + .Concat(Assembly + .GetAssembly(typeof(ApiContainer)) + .GetTypes() + .Where(t => typeof(IExternalApi).IsAssignableFrom(t)) + .Where(t => t.IsSealed) + .Where(t => ServiceInjector.IsAvailable(serviceProvider, t))); foreach (var api in apis) { diff --git a/BizHawk.Client.EmuHawk/BizBox.cs b/BizHawk.Client.EmuHawk/BizBox.cs index a233234d1d..9bff885393 100644 --- a/BizHawk.Client.EmuHawk/BizBox.cs +++ b/BizHawk.Client.EmuHawk/BizBox.cs @@ -48,8 +48,7 @@ namespace BizHawk.Client.EmuHawk .Select(t => t.GetCustomAttributes(false).OfType().FirstOrDefault()) .Where(a => a != null) .Where(a => a.Released) - .OrderByDescending(a => a.CoreName.ToLower()) - .ToList(); + .OrderByDescending(a => a.CoreName.ToLower()); foreach (var core in cores) { diff --git a/BizHawk.Client.EmuHawk/BizHawk.Client.EmuHawk.csproj b/BizHawk.Client.EmuHawk/BizHawk.Client.EmuHawk.csproj index d5e7b52341..a0bb67fd0b 100644 --- a/BizHawk.Client.EmuHawk/BizHawk.Client.EmuHawk.csproj +++ b/BizHawk.Client.EmuHawk/BizHawk.Client.EmuHawk.csproj @@ -38,6 +38,7 @@ true None true + 8.0 true @@ -84,7 +85,7 @@ ..\output\dll\nlua\NLua.dll False - + False ..\References\OpenTK.dll @@ -566,6 +567,8 @@ CoreFeatureAnalysis.cs + + Form @@ -575,7 +578,7 @@ Component - + Component @@ -585,21 +588,17 @@ Form - + + + Component - - InputRoll.cs - Component - - - InputRoll.cs - Component - - + InputRoll.cs Component + + Component @@ -612,30 +611,6 @@ MsgBox.cs - - PlatformAgnosticVirtualListView.cs - Component - - - PlatformAgnosticVirtualListView.cs - Component - - - PlatformAgnosticVirtualListView.cs - Component - - - PlatformAgnosticVirtualListView.cs - Component - - - PlatformAgnosticVirtualListView.cs - Component - - - PlatformAgnosticVirtualListView.cs - Component - Form @@ -660,9 +635,6 @@ Component - - Component - Component @@ -672,7 +644,6 @@ Component - @@ -685,9 +656,11 @@ + + Form @@ -704,6 +677,7 @@ + @@ -779,9 +753,6 @@ OpenAdvancedChooser.cs - - Component - Form @@ -814,12 +785,6 @@ - - Form - - - AutoHawk.cs - Form @@ -1553,9 +1518,6 @@ QuickProgressPopup.cs - - TasListView.cs - MainForm.cs Designer @@ -1584,9 +1546,6 @@ RomStatusPicker.cs - - AutoHawk.cs - BasicBot.cs @@ -1899,6 +1858,7 @@ + @@ -1926,6 +1886,8 @@ + + @@ -2255,6 +2217,7 @@ + diff --git a/BizHawk.Client.EmuHawk/BizHawk.Client.EmuHawk.csproj.DotSettings b/BizHawk.Client.EmuHawk/BizHawk.Client.EmuHawk.csproj.DotSettings index 73e96563f9..b9fd6ee4f5 100644 --- a/BizHawk.Client.EmuHawk/BizHawk.Client.EmuHawk.csproj.DotSettings +++ b/BizHawk.Client.EmuHawk/BizHawk.Client.EmuHawk.csproj.DotSettings @@ -1,2 +1,2 @@  - CSharp60 \ No newline at end of file + CSharp80 \ No newline at end of file diff --git a/BizHawk.Client.EmuHawk/CustomControls/ControlRenderer/GDIRenderer.cs b/BizHawk.Client.EmuHawk/CustomControls/ControlRenderer/GDIRenderer.cs new file mode 100644 index 0000000000..12e76de025 --- /dev/null +++ b/BizHawk.Client.EmuHawk/CustomControls/ControlRenderer/GDIRenderer.cs @@ -0,0 +1,505 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Runtime.InteropServices; + +namespace BizHawk.Client.EmuHawk.CustomControls +{ + /// + /// Wrapper for GDI rendering functions + /// This class is not thread-safe as GDI functions should be called from the UI thread + /// + public sealed class GdiRenderer : IControlRenderer + { + // Cache of all the Fonts used, rather than create them again and again + private readonly Dictionary _fontsCache = new Dictionary(); + + private class FontCacheEntry + { + public IntPtr HFont; + public IntPtr RotatedHFont; + } + + // Cache of all the brushes used, rather than create them again and again + private readonly Dictionary _brushCache = new Dictionary(); + + private Graphics _g; + private IntPtr _hdc; + private IntPtr _currentBrush = IntPtr.Zero; + + #region Construct and Destroy + + public void Dispose() + { + foreach (var brush in _brushCache) + { + if (brush.Value != IntPtr.Zero) + { + DeleteObject(brush.Value); + } + } + + foreach (var fc in _fontsCache) + { + DeleteObject(fc.Value.HFont); + DeleteObject(fc.Value.RotatedHFont); + } + + System.Diagnostics.Debug.Assert(_hdc == IntPtr.Zero, "Disposed a GDIRenderer while it held an HDC"); + System.Diagnostics.Debug.Assert(_g == null, "Disposed a GDIRenderer while it held a Graphics"); + } + + #endregion + + #region Api + + public void DrawBitmap(Bitmap bitmap, Point point) + { + IntPtr hBmp = bitmap.GetHbitmap(); + var bitHdc = CreateCompatibleDC(CurrentHdc); + IntPtr old = SelectObject(bitHdc, hBmp); + AlphaBlend(CurrentHdc, point.X, point.Y, bitmap.Width, bitmap.Height, bitHdc, 0, 0, bitmap.Width, bitmap.Height, new BLENDFUNCTION(AC_SRC_OVER, 0, 0xff, AC_SRC_ALPHA)); + SelectObject(bitHdc, old); + DeleteDC(bitHdc); + DeleteObject(hBmp); + } + + public IDisposable LockGraphics(Graphics g, int width, int height) + { + _g = g; + _hdc = g.GetHdc(); + SetBkMode(_hdc, BkModes.TRANSPARENT); + var l = new GdiGraphicsLock(this); + StartOffScreenBitmap(width, height); + return l; + } + + public Size MeasureString(string str, Font font) + { + SetFont(font); + + var size = new Size(); + GetTextExtentPoint32(CurrentHdc, str, str.Length, ref size); + return size; + } + + public void DrawString(string str, Point point) + { + TextOut(CurrentHdc, point.X, point.Y, str, str.Length); + } + + public static IntPtr CreateNormalHFont(Font font, int width) + { + var logFont = new LOGFONT(); + font.ToLogFont(logFont); + logFont.lfWidth = width; + logFont.lfOutPrecision = (byte)FontPrecision.OUT_TT_ONLY_PRECIS; + var ret = CreateFontIndirect(logFont); + return ret; + } + + //this returns an IntPtr font because .net's Font class will erase the relevant properties when using its Font.FromLogFont() + //note that whether this is rotated clockwise or CCW might affect how you have to position the text (right-aligned sometimes?, up or down by the height of the font?) + public static IntPtr CreateRotatedHFont(Font font, bool cw) + { + LOGFONT logF = new LOGFONT(); + font.ToLogFont(logF); + logF.lfEscapement = cw ? 2700 : 900; + logF.lfOrientation = logF.lfEscapement; + logF.lfOutPrecision = (byte)FontPrecision.OUT_TT_ONLY_PRECIS; + + var ret = CreateFontIndirect(logF); + return ret; + } + + // TODO: this should go away and be abstracted internally + public static void DestroyHFont(IntPtr hFont) + { + DeleteObject(hFont); + } + + public void PrepDrawString(Font font, Color color, bool rotate = false) + { + var fontEntry = GetCachedHFont(font); + SetGraphicsMode(CurrentHdc, 2); // shouldn't be necessary.. cant hurt + SelectObject(CurrentHdc, rotate ? fontEntry.RotatedHFont : fontEntry.HFont); + SetTextColor(color); + } + + // Set the text color of the device context + private void SetTextColor(Color color) + { + int rgb = (color.B & 0xFF) << 16 | (color.G & 0xFF) << 8 | color.R; + SetTextColor(CurrentHdc, rgb); + } + + public void DrawRectangle(int nLeftRect, int nTopRect, int nRightRect, int nBottomRect) + { + Rectangle(CurrentHdc, nLeftRect, nTopRect, nRightRect, nBottomRect); + } + + public void SetBrush(Color color) + { + if (_brushCache.ContainsKey(color)) + { + _currentBrush = _brushCache[color]; + } + else + { + int rgb = (color.B & 0xFF) << 16 | (color.G & 0xFF) << 8 | color.R; + var newBrush = CreateSolidBrush(rgb); + _brushCache.Add(color, newBrush); + _currentBrush = newBrush; + } + } + + public void FillRectangle(int x, int y, int w, int h) + { + var r = new GDIRect(new Rectangle(x, y, w, h)); + FillRect(CurrentHdc, ref r, _currentBrush); + } + + public void SetSolidPen(Color color) + { + int rgb = (color.B & 0xFF) << 16 | (color.G & 0xFF) << 8 | color.R; + SelectObject(CurrentHdc, GetStockObject((int)PaintObjects.DC_PEN)); + SetDCPenColor(CurrentHdc, rgb); + } + + public void Line(int x1, int y1, int x2, int y2) + { + MoveToEx(CurrentHdc, x1, y1, IntPtr.Zero); + LineTo(CurrentHdc, x2, y2); + } + + private IntPtr CurrentHdc => _bitHdc != IntPtr.Zero ? _bitHdc : _hdc; + + private IntPtr _bitMap = IntPtr.Zero; + private IntPtr _bitHdc = IntPtr.Zero; + private int _bitW; + private int _bitH; + + private void StartOffScreenBitmap(int width, int height) + { + _bitW = width; + _bitH = height; + + _bitHdc = CreateCompatibleDC(_hdc); + _bitMap = CreateCompatibleBitmap(_hdc, width, height); + SelectObject(_bitHdc, _bitMap); + SetBkMode(_bitHdc, BkModes.TRANSPARENT); + } + + private void EndOffScreenBitmap() + { + _bitW = 0; + _bitH = 0; + + DeleteObject(_bitMap); + DeleteObject(_bitHdc); + + _bitHdc = IntPtr.Zero; + _bitMap = IntPtr.Zero; + } + + private void CopyToScreen() + { + BitBlt(_hdc, 0, 0, _bitW, _bitH, _bitHdc, 0, 0, 0x00CC0020); + } + + #endregion + + #region Helpers + + // Set a resource (e.g. a font) for the current device context. + private void SetFont(Font font) + { + var blah = GetCachedHFont(font); + SelectObject(CurrentHdc, blah.HFont); + } + + private FontCacheEntry GetCachedHFont(Font font) + { + FontCacheEntry fontEntry; + var result = _fontsCache.TryGetValue(font, out fontEntry); + if (!result) + { + // Hack! The 6 is hardcoded to make tastudio look like taseditor, because taseditor is so perfect and wonderful + fontEntry = new FontCacheEntry + { + HFont = CreateNormalHFont(font, 6), + RotatedHFont = CreateRotatedHFont(font, true) + }; + _fontsCache.Add(font, fontEntry); + } + + return fontEntry; + } + + #endregion + + #region Imports + + // ReSharper disable IdentifierTypo + [DllImport("gdi32.dll", CharSet = CharSet.Auto)] + private static extern IntPtr CreateFontIndirect( + [In, MarshalAs(UnmanagedType.LPStruct)]LOGFONT lplf + ); + + [DllImport("gdi32.dll")] + private static extern int Rectangle(IntPtr hdc, int nLeftRect, int nTopRect, int nRightRect, int nBottomRect); + + [DllImport("user32.dll")] + private static extern int FillRect(IntPtr hdc, [In] ref GDIRect lprc, IntPtr hbr); + + [DllImport("gdi32.dll")] + private static extern int SetBkMode(IntPtr hdc, BkModes mode); + + [DllImport("gdi32.dll")] + + private static extern IntPtr SelectObject(IntPtr hdc, IntPtr hgdiObj); + + [DllImport("gdi32.dll")] + private static extern int SetTextColor(IntPtr hdc, int color); + + [DllImport("gdi32.dll", EntryPoint = "GetTextExtentPoint32W")] + private static extern int GetTextExtentPoint32(IntPtr hdc, [MarshalAs(UnmanagedType.LPWStr)] string str, int len, ref Size size); + + [DllImport("gdi32.dll", EntryPoint = "TextOutW")] + private static extern bool TextOut(IntPtr hdc, int x, int y, [MarshalAs(UnmanagedType.LPWStr)] string str, int len); + + [DllImport("gdi32.dll")] + public static extern int SetGraphicsMode(IntPtr hdc, int iMode); + + [DllImport("gdi32.dll")] + private static extern bool DeleteObject(IntPtr hObject); + + [DllImport("gdi32.dll")] + private static extern IntPtr CreateSolidBrush(int color); + + [DllImport("gdi32.dll")] + private static extern IntPtr MoveToEx(IntPtr hdc, int x, int y, IntPtr point); + + [DllImport("gdi32.dll")] + private static extern IntPtr LineTo(IntPtr hdc, int nXEnd, int nYEnd); + + [DllImport("gdi32.dll")] + private static extern IntPtr GetStockObject(int fnObject); + + [DllImport("gdi32.dll")] + private static extern IntPtr SetDCPenColor(IntPtr hdc, int crColor); + + [DllImport("gdi32.dll")] + private static extern IntPtr CreateCompatibleDC(IntPtr hdc); + + [DllImport("gdi32.dll", EntryPoint = "DeleteDC")] + public static extern bool DeleteDC([In] IntPtr hdc); + + [DllImport("gdi32.dll")] + private static extern IntPtr CreateCompatibleBitmap(IntPtr hdc, int width, int height); + + [DllImport("gdi32.dll", EntryPoint = "BitBlt", SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + static extern bool BitBlt([In] IntPtr hdc, int nXDest, int nYDest, int nWidth, int nHeight, [In] IntPtr hdcSrc, int nXSrc, int nYSrc, int dwRop); + + [DllImport("gdi32.dll", EntryPoint = "GdiAlphaBlend")] + static extern bool AlphaBlend(IntPtr hdcDest, int nXOriginDest, int nYOriginDest, int nWidthDest, int nHeightDest, IntPtr hdcSrc, int nXOriginSrc, int nYOriginSrc, int nWidthSrc, int nHeightSrc, BLENDFUNCTION blendFunction); + + // ReSharper disable InconsistentNaming + // ReSharper disable UnusedMember.Global + // ReSharper disable UnusedMember.Local + // ReSharper disable NotAccessedField.Local + // ReSharper disable ArrangeTypeMemberModifiers + public enum FontPrecision : byte + { + + OUT_DEFAULT_PRECIS = 0, + OUT_STRING_PRECIS = 1, + OUT_CHARACTER_PRECIS = 2, + OUT_STROKE_PRECIS = 3, + OUT_TT_PRECIS = 4, + OUT_DEVICE_PRECIS = 5, + OUT_RASTER_PRECIS = 6, + OUT_TT_ONLY_PRECIS = 7, + OUT_OUTLINE_PRECIS = 8, + OUT_SCREEN_OUTLINE_PRECIS = 9, + OUT_PS_ONLY_PRECIS = 10, + } + + // It is important for this to be the right declaration + // See more here http://www.tech-archive.net/Archive/DotNet/microsoft.public.dotnet.framework.drawing/2004-04/0319.html + // If it's wrong (I had a wrong one from pinvoke.net) then ToLogFont will fail mysteriously + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] + class LOGFONT + { + public int lfHeight = 0; + public int lfWidth = 0; + public int lfEscapement = 0; + public int lfOrientation = 0; + public int lfWeight = 0; + public byte lfItalic = 0; + public byte lfUnderline = 0; + public byte lfStrikeOut = 0; + public byte lfCharSet = 0; + public byte lfOutPrecision = 0; + public byte lfClipPrecision = 0; + public byte lfQuality = 0; + public byte lfPitchAndFamily = 0; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)] + public string lfFaceName = null; + } + + /// + /// The graphics mode that can be set by SetGraphicsMode. + /// + public enum GraphicsMode : int + { + /// + /// Sets the graphics mode that is compatible with 16-bit Windows. This is the default mode. If + /// this value is specified, the application can only modify the world-to-device transform by + /// calling functions that set window and viewport extents and origins, but not by using + /// SetWorldTransform or ModifyWorldTransform; calls to those functions will fail. + /// Examples of functions that set window and viewport extents and origins are SetViewportExtEx + /// and SetWindowExtEx. + /// + GM_COMPATIBLE = 1, + /// + /// Sets the advanced graphics mode that allows world transformations. This value must be + /// specified if the application will set or modify the world transformation for the specified + /// device context. In this mode all graphics, including text output, fully conform to the + /// world-to-device transformation specified in the device context. + /// + GM_ADVANCED = 2, + } + + /// + /// The XFORM structure specifies a world-space to page-space transformation. + /// + [StructLayout(LayoutKind.Sequential)] + public struct XFORM + { + public float eM11; + public float eM12; + public float eM21; + public float eM22; + public float eDx; + public float eDy; + + public XFORM(float eM11, float eM12, float eM21, float eM22, float eDx, float eDy) + { + this.eM11 = eM11; + this.eM12 = eM12; + this.eM21 = eM21; + this.eM22 = eM22; + this.eDx = eDx; + this.eDy = eDy; + } + + /// + /// Allows implicit conversion to a managed transformation matrix. + /// + public static implicit operator System.Drawing.Drawing2D.Matrix(XFORM xf) + { + return new System.Drawing.Drawing2D.Matrix(xf.eM11, xf.eM12, xf.eM21, xf.eM22, xf.eDx, xf.eDy); + } + + /// + /// Allows implicit conversion from a managed transformation matrix. + /// + public static implicit operator XFORM(System.Drawing.Drawing2D.Matrix m) + { + float[] elems = m.Elements; + return new XFORM(elems[0], elems[1], elems[2], elems[3], elems[4], elems[5]); + } + } + + [StructLayout(LayoutKind.Sequential)] + public struct BLENDFUNCTION + { + byte BlendOp; + byte BlendFlags; + byte SourceConstantAlpha; + byte AlphaFormat; + + public BLENDFUNCTION(byte op, byte flags, byte alpha, byte format) + { + BlendOp = op; + BlendFlags = flags; + SourceConstantAlpha = alpha; + AlphaFormat = format; + } + } + + const byte AC_SRC_OVER = 0x00; + const byte AC_SRC_ALPHA = 0x01; + + #endregion + + #region Classes, Structs, and Enums + + private class GdiGraphicsLock : IDisposable + { + private readonly GdiRenderer _gdi; + + public GdiGraphicsLock(GdiRenderer gdi) + { + _gdi = gdi; + } + + public void Dispose() + { + _gdi.CopyToScreen(); + _gdi.EndOffScreenBitmap(); + _gdi._g.ReleaseHdc(_gdi._hdc); + _gdi._hdc = IntPtr.Zero; + _gdi._g = null; + } + } + + private struct GDIRect + { + private int left; + private int top; + private int right; + private int bottom; + + public GDIRect(Rectangle r) + { + left = r.Left; + top = r.Top; + bottom = r.Bottom; + right = r.Right; + } + } + + private enum PaintObjects + { + WHITE_BRUSH = 0, + LTGRAY_BRUSH = 1, + GRAY_BRUSH = 2, + DKGRAY_BRUSH = 3, + BLACK_BRUSH = 4, + NULL_BRUSH = 5, + WHITE_PEN = 6, + BLACK_PEN = 7, + NULL_PEN = 8, + OEM_FIXED_FONT = 10, + ANSI_FIXED_FONT = 11, + ANSI_VAR_FONT = 12, + SYSTEM_FONT = 13, + DEVICE_DEFAULT_FONT = 14, + DEFAULT_PALETTE = 15, + SYSTEM_FIXED_FONT = 16, + DC_BRUSH = 18, + DC_PEN = 19, + } + + private enum BkModes : int + { + TRANSPARENT = 1, + OPAQUE = 2 + } + + #endregion + } +} diff --git a/BizHawk.Client.EmuHawk/CustomControls/ControlRenderer/GdiPlusRenderer.cs b/BizHawk.Client.EmuHawk/CustomControls/ControlRenderer/GdiPlusRenderer.cs new file mode 100644 index 0000000000..103f3fd916 --- /dev/null +++ b/BizHawk.Client.EmuHawk/CustomControls/ControlRenderer/GdiPlusRenderer.cs @@ -0,0 +1,108 @@ +using System; +using System.Drawing; + +namespace BizHawk.Client.EmuHawk.CustomControls +{ + public class GdiPlusRenderer : IControlRenderer + { + private Graphics _graphics; + + private readonly Pen _currentPen = new Pen(Color.Black); + private readonly SolidBrush _currentBrush = new SolidBrush(Color.Black); + private readonly SolidBrush _currentStringBrush = new SolidBrush(Color.Black); + private readonly Font _defaultFont = new Font("Arial", 8, FontStyle.Bold); + private Font _currentFont; + private bool _rotateString; + + public GdiPlusRenderer() + { + _currentFont = _defaultFont; + } + + private class GdiPlusGraphicsLock : IDisposable + { + public void Dispose() + { + // Nothing to do + // Other drawing methods need a way to dispose on demand, hence the need for + // this dummy class + } + } + + public void Dispose() + { + _currentPen.Dispose(); + _currentBrush.Dispose(); + _currentStringBrush.Dispose(); + _defaultFont.Dispose(); + } + + public void DrawBitmap(Bitmap bitmap, Point point) + { + _graphics.DrawImage(bitmap, point); + } + + public void DrawRectangle(int nLeftRect, int nTopRect, int nRightRect, int nBottomRect) + { + _graphics.DrawRectangle( + _currentPen, + new Rectangle(nLeftRect, nTopRect, nRightRect - nLeftRect, nBottomRect - nTopRect)); + } + + public void DrawString(string str, Point point) + { + if (_rotateString) + { + _graphics.TranslateTransform(point.X, point.Y); + _graphics.RotateTransform(90); + _graphics.DrawString(str, _currentFont, _currentStringBrush, Point.Empty); + _graphics.ResetTransform(); + } + else + { + _graphics.DrawString(str, _currentFont, _currentStringBrush, point); + } + } + + public void FillRectangle(int x, int y, int w, int h) + { + _graphics.FillRectangle( + _currentBrush, + new Rectangle(x, y, w, h)); + } + + public void Line(int x1, int y1, int x2, int y2) + { + _graphics.DrawLine(_currentPen, x1, y1, x2, y2); + } + + public IDisposable LockGraphics(Graphics g, int width, int height) + { + _graphics = g; + return new GdiPlusGraphicsLock(); + } + + public Size MeasureString(string str, Font font) + { + var size = _graphics.MeasureString(str, font); + return new Size((int)(size.Width + 0.5), (int)(size.Height + 0.5)); + } + + public void PrepDrawString(Font font, Color color, bool rotate = false) + { + _currentFont = font; + _currentStringBrush.Color = color; + _rotateString = rotate; + } + + public void SetBrush(Color color) + { + _currentBrush.Color = color; + } + + public void SetSolidPen(Color color) + { + _currentPen.Color = color; + } + } +} diff --git a/BizHawk.Client.EmuHawk/CustomControls/ControlRenderer/IControlRenderer.cs b/BizHawk.Client.EmuHawk/CustomControls/ControlRenderer/IControlRenderer.cs new file mode 100644 index 0000000000..9a5475cd9e --- /dev/null +++ b/BizHawk.Client.EmuHawk/CustomControls/ControlRenderer/IControlRenderer.cs @@ -0,0 +1,38 @@ +using System; +using System.Drawing; + +namespace BizHawk.Client.EmuHawk.CustomControls +{ + public interface IControlRenderer : IDisposable + { + /// + /// Required to use before calling drawing methods + /// + IDisposable LockGraphics(Graphics g, int width, int height); + + /// + /// Measure the width and height of string when drawn + /// using the given font + /// + Size MeasureString(string str, Font font); + + void SetBrush(Color color); + void SetSolidPen(Color color); + + void PrepDrawString(Font font, Color color, bool rotate = false); + + /// + /// Draw the given string using the given font and foreground color at given location + /// + void DrawString(string str, Point point); + + void DrawRectangle(int nLeftRect, int nTopRect, int nRightRect, int nBottomRect); + void FillRectangle(int x, int y, int w, int h); + + /// + /// Draw a bitmap object at the given position + /// + void DrawBitmap(Bitmap bitmap, Point point); + void Line(int x1, int y1, int x2, int y2); + } +} diff --git a/BizHawk.Client.EmuHawk/CustomControls/GDIRenderer.cs b/BizHawk.Client.EmuHawk/CustomControls/GDIRenderer.cs deleted file mode 100644 index 92ef9d86c0..0000000000 --- a/BizHawk.Client.EmuHawk/CustomControls/GDIRenderer.cs +++ /dev/null @@ -1,769 +0,0 @@ -using System; -using System.Text; -using System.Collections.Generic; -using System.Drawing; -using System.Runtime.InteropServices; - -namespace BizHawk.Client.EmuHawk.CustomControls -{ - /// - /// Wrapper for GDI rendering functions - /// This class is not thread-safe as GDI functions should be called from the UI thread - /// - public sealed class GDIRenderer : IDisposable - { - /// - /// used for calculation. - /// - private static readonly int[] CharFit = new int[1]; - - /// - /// used for calculation - /// - private static readonly int[] CharFitWidth = new int[1000]; - - /// - /// Cache of all the HFONTs used, rather than create them again and again - /// - private readonly Dictionary FontsCache = new Dictionary(); - - class FontCacheEntry - { - public IntPtr HFont; - } - - /// - /// Cache of all the brushes used, rather than create them again and again - /// - private readonly Dictionary BrushCache = new Dictionary(); - - private Graphics _g; - private IntPtr _hdc; - private IntPtr _currentBrush = IntPtr.Zero; - - #region Construct and Destroy - - public GDIRenderer() - { - //zero 04-16-2016 : this can't be legal, theres no HDC yet - //SetBkMode(_hdc, BkModes.OPAQUE); - } - - public void Dispose() - { - foreach (var brush in BrushCache) - { - if (brush.Value != IntPtr.Zero) - { - DeleteObject(brush.Value); - } - } - - foreach (var fc in FontsCache) - DeleteObject(fc.Value.HFont); - - EndOffScreenBitmap(); - - System.Diagnostics.Debug.Assert(_hdc == IntPtr.Zero, "Disposed a GDIRenderer while it held an HDC"); - System.Diagnostics.Debug.Assert(_g == null, "Disposed a GDIRenderer while it held a Graphics"); - } - - #endregion - - #region Api - - /// - /// Draw a bitmap object at the given position - /// - public void DrawBitmap(Bitmap bitmap, Point point, bool blend = false) - { - IntPtr hbmp = bitmap.GetHbitmap(); - var bitHDC = CreateCompatibleDC(CurrentHDC); - IntPtr old = SelectObject(bitHDC, hbmp); - if (blend) - { - AlphaBlend(CurrentHDC, point.X, point.Y, bitmap.Width, bitmap.Height, bitHDC, 0, 0, bitmap.Width, bitmap.Height, new BLENDFUNCTION(AC_SRC_OVER, 0, 0xff, AC_SRC_ALPHA)); - } - else - { - BitBlt(CurrentHDC, point.X, point.Y, bitmap.Width, bitmap.Height, bitHDC, 0, 0, 0xCC0020); - } - SelectObject(bitHDC, old); - DeleteDC(bitHDC); - DeleteObject(hbmp); - } - - /// - /// Required to use before calling drawing methods - /// - public GdiGraphicsLock LockGraphics(Graphics g) - { - _g = g; - _hdc = g.GetHdc(); - SetBkMode(_hdc, BkModes.TRANSPARENT); - return new GdiGraphicsLock(this); - } - - /// - /// Measure the width and height of string when drawn on device context HDC - /// using the given font - /// - public Size MeasureString(string str, Font font) - { - SetFont(font); - - var size = new Size(); - GetTextExtentPoint32(CurrentHDC, str, str.Length, ref size); - return size; - } - - /// - /// Measure the width and height of string when drawn on device context HDC - /// using the given font - /// Restrict the width of the string and get the number of characters able to fit in the restriction and - /// the width those characters take - /// - /// the max width to render the string in - /// the number of characters that will fit under restriction - public Size MeasureString(string str, Font font, float maxWidth, out int charFit, out int charFitWidth) - { - SetFont(font); - - var size = new Size(); - GetTextExtentExPoint(CurrentHDC, str, str.Length, (int)Math.Round(maxWidth), CharFit, CharFitWidth, ref size); - charFit = CharFit[0]; - charFitWidth = charFit > 0 ? CharFitWidth[charFit - 1] : 0; - return size; - } - - public void DrawString(string str, Point point) - { - TextOut(CurrentHDC, point.X, point.Y, str, str.Length); - } - - public static IntPtr CreateNormalHFont(Font font, int width) - { - LOGFONT logf = new LOGFONT(); - font.ToLogFont(logf); - logf.lfWidth = width; - logf.lfOutPrecision = (byte)FontPrecision.OUT_TT_ONLY_PRECIS; - var ret = CreateFontIndirect(logf); - return ret; - } - - //this returns an IntPtr HFONT because .net's Font class will erase the relevant properties when using its Font.FromLogFont() - //note that whether this is rotated clockwise or CCW might affect how you have to position the text (right-aligned sometimes?, up or down by the height of the font?) - public static IntPtr CreateRotatedHFont(Font font, bool CW) - { - LOGFONT logf = new LOGFONT(); - font.ToLogFont(logf); - logf.lfEscapement = CW ? 2700 : 900; - logf.lfOrientation = logf.lfEscapement; - logf.lfOutPrecision = (byte)FontPrecision.OUT_TT_ONLY_PRECIS; - - //this doesnt work! .net erases the relevant propreties.. it seems? - //return Font.FromLogFont(logf); - - var ret = CreateFontIndirect(logf); - return ret; - } - - public static void DestroyHFont(IntPtr hfont) - { - DeleteObject(hfont); - } - - public void PrepDrawString(IntPtr hfont, Color color) - { - SetGraphicsMode(CurrentHDC, 2); //shouldnt be necessary.. cant hurt - SelectObject(CurrentHDC, hfont); - SetTextColor(color); - } - - public void PrepDrawString(Font font, Color color) - { - SetFont(font); - SetTextColor(color); - } - - - /// - /// Draw the given string using the given font and foreground color at given location - /// See [http://msdn.microsoft.com/en-us/library/windows/desktop/dd162498(v=vs.85).aspx][15] - /// - public void DrawString(string str, Font font, Color color, Rectangle rect, TextFormatFlags flags) - { - SetFont(font); - SetTextColor(color); - - var rect2 = new Rect(rect); - DrawText(CurrentHDC, str, str.Length, ref rect2, (uint)flags); - } - - - /// - /// Set the text color of the device context - /// - public void SetTextColor(Color color) - { - int rgb = (color.B & 0xFF) << 16 | (color.G & 0xFF) << 8 | color.R; - SetTextColor(CurrentHDC, rgb); - } - - public void SetBackgroundColor(Color color) - { - int rgb = (color.B & 0xFF) << 16 | (color.G & 0xFF) << 8 | color.R; - SetBkColor(CurrentHDC, rgb); - } - - public void DrawRectangle(int nLeftRect, int nTopRect, int nRightRect, int nBottomRect) - { - Rectangle(CurrentHDC, nLeftRect, nTopRect, nRightRect, nBottomRect); - } - - public void SetBrush(Color color) - { - if (BrushCache.ContainsKey(color)) - { - _currentBrush = BrushCache[color]; - } - else - { - int rgb = (color.B & 0xFF) << 16 | (color.G & 0xFF) << 8 | color.R; - var newBrush = CreateSolidBrush(rgb); - BrushCache.Add(color, newBrush); - _currentBrush = newBrush; - } - } - - public void FillRectangle(int x, int y, int w, int h) - { - var r = new GDIRect(new Rectangle(x, y, w, h)); - FillRect(CurrentHDC, ref r, _currentBrush); - } - - public void SetPenPosition(int x, int y) - { - MoveToEx(CurrentHDC, x, y, IntPtr.Zero); - } - - public void SetSolidPen(Color color) - { - int rgb = (color.B & 0xFF) << 16 | (color.G & 0xFF) << 8 | color.R; - SelectObject(CurrentHDC, GetStockObject((int)PaintObjects.DC_PEN)); - SetDCPenColor(CurrentHDC, rgb); - } - - public void Line(int x1, int y1, int x2, int y2) - { - MoveToEx(CurrentHDC, x1, y1, IntPtr.Zero); - LineTo(CurrentHDC, x2, y2); - } - - private IntPtr CurrentHDC - { - get { return _bitHDC != IntPtr.Zero ? _bitHDC : _hdc; } - } - - private IntPtr _bitMap = IntPtr.Zero; - private IntPtr _bitHDC = IntPtr.Zero; - private int _bitW; - private int _bitH; - - public void StartOffScreenBitmap(int width, int height) - { - _bitW = width; - _bitH = height; - - _bitHDC = CreateCompatibleDC(_hdc); - _bitMap = CreateCompatibleBitmap(_hdc, width, height); - SelectObject(_bitHDC, _bitMap); - SetBkMode(_bitHDC, BkModes.TRANSPARENT); - } - - public void EndOffScreenBitmap() - { - _bitW = 0; - _bitH = 0; - - DeleteObject(_bitMap); - DeleteObject(_bitHDC); - - _bitHDC = IntPtr.Zero; - _bitMap = IntPtr.Zero; - } - - public void CopyToScreen() - { - BitBlt(_hdc, 0, 0, _bitW, _bitH, _bitHDC, 0, 0, 0x00CC0020); - } - - #endregion - - #region Helpers - - /// - /// Set a resource (e.g. a font) for the specified device context. - /// - private void SetFont(Font font) - { - SelectObject(CurrentHDC, GetCachedHFont(font)); - } - - private IntPtr GetCachedHFont(Font font) - { - //the original code struck me as bad. attempting to ID fonts by picking a subset of their fields is not gonna work. - //don't call this.Font in InputRoll.cs, it is probably slow. - //consider Fonts to be a jealously guarded resource (they need to be disposed, after all) and manage them carefully. - //this cache maintains the HFONTs only. - FontCacheEntry ce; - if (!FontsCache.TryGetValue(font, out ce)) - { - FontsCache[font] = ce = new FontCacheEntry(); - ce.HFont = font.ToHfont(); - } - return ce.HFont; - } - - #endregion - - #region Imports - - [DllImport("user32.dll")] - private static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC); - - [DllImport("user32.dll")] - private static extern IntPtr GetDC(IntPtr hWnd); - - [DllImport("user32.dll")] - private static extern IntPtr BeginPaint(IntPtr hWnd, ref IntPtr lpPaint); - - [DllImport("user32.dll")] - private static extern IntPtr EndPaint(IntPtr hWnd, IntPtr lpPaint); - - [DllImport("gdi32.dll", CharSet = CharSet.Auto)] - private static extern IntPtr CreateFontIndirect( - [In, MarshalAs(UnmanagedType.LPStruct)]LOGFONT lplf - ); - - [DllImport("gdi32.dll")] - private static extern int Rectangle(IntPtr hdc, int nLeftRect, int nTopRect, int nRightRect, int nBottomRect); - - [DllImport("user32.dll")] - private static extern int FillRect(IntPtr hdc, [In] ref GDIRect lprc, IntPtr hbr); - - [DllImport("gdi32.dll")] - private static extern int SetBkMode(IntPtr hdc, BkModes mode); - - [DllImport("gdi32.dll")] - private static extern IntPtr SelectObject(IntPtr hdc, IntPtr hgdiObj); - - [DllImport("gdi32.dll")] - private static extern int SetTextColor(IntPtr hdc, int color); - - [DllImport("gdi32.dll")] - private static extern int SetBkColor(IntPtr hdc, int color); - - [DllImport("gdi32.dll", EntryPoint = "GetTextExtentPoint32W")] - private static extern int GetTextExtentPoint32(IntPtr hdc, [MarshalAs(UnmanagedType.LPWStr)] string str, int len, ref Size size); - - [DllImport("gdi32.dll", EntryPoint = "GetTextExtentExPointW")] - private static extern bool GetTextExtentExPoint(IntPtr hDc, [MarshalAs(UnmanagedType.LPWStr)]string str, int nLength, int nMaxExtent, int[] lpnFit, int[] alpDx, ref Size size); - - [DllImport("gdi32.dll", EntryPoint = "TextOutW")] - private static extern bool TextOut(IntPtr hdc, int x, int y, [MarshalAs(UnmanagedType.LPWStr)] string str, int len); - - [DllImport("gdi32.dll")] - public static extern int SetGraphicsMode(IntPtr hdc, int iMode); - - [DllImport("user32.dll", EntryPoint = "DrawTextW")] - private static extern int DrawText(IntPtr hdc, [MarshalAs(UnmanagedType.LPWStr)] string str, int len, ref Rect rect, uint uFormat); - - [DllImport("gdi32.dll", EntryPoint = "ExtTextOutW")] - private static extern bool ExtTextOut(IntPtr hdc, int X, int Y, uint fuOptions, uint cbCount, [In] IntPtr lpDx); - - [DllImport("gdi32.dll")] - static extern bool SetWorldTransform(IntPtr hdc, [In] ref XFORM lpXform); - - [DllImport("gdi32.dll")] - private static extern int SelectClipRgn(IntPtr hdc, IntPtr hrgn); - - [DllImport("gdi32.dll")] - private static extern bool DeleteObject(IntPtr hObject); - - [DllImport("gdi32.dll")] - private static extern IntPtr CreateSolidBrush(int color); - - [DllImport("gdi32.dll")] - private static extern IntPtr CreatePen(int fnPenStyle, int nWidth, int color); - - [DllImport("gdi32.dll")] - private static extern IntPtr MoveToEx(IntPtr hdc, int x, int y, IntPtr point); - - [DllImport("gdi32.dll")] - private static extern IntPtr LineTo(IntPtr hdc, int nXEnd, int nYEnd); - - [DllImport("gdi32.dll")] - private static extern IntPtr GetStockObject(int fnObject); - - [DllImport("gdi32.dll")] - private static extern IntPtr SetDCPenColor(IntPtr hdc, int crColor); - - [DllImport("gdi32.dll")] - private static extern IntPtr CreateCompatibleDC(IntPtr hdc); - - [DllImport("gdi32.dll", EntryPoint = "DeleteDC")] - public static extern bool DeleteDC([In] IntPtr hdc); - - [DllImport("gdi32.dll")] - private static extern IntPtr CreateCompatibleBitmap(IntPtr hdc, int width, int height); - - [DllImport("gdi32.dll", EntryPoint = "BitBlt", SetLastError = true)] - [return: MarshalAs(UnmanagedType.Bool)] - static extern bool BitBlt([In] IntPtr hdc, int nXDest, int nYDest, int nWidth, int nHeight, [In] IntPtr hdcSrc, int nXSrc, int nYSrc, int dwRop); - - [DllImport("gdi32.dll", EntryPoint = "GdiAlphaBlend")] - static extern bool AlphaBlend(IntPtr hdcDest, int nXOriginDest, int nYOriginDest, int nWidthDest, int nHeightDest, IntPtr hdcSrc, int nXOriginSrc, int nYOriginSrc, int nWidthSrc, int nHeightSrc, BLENDFUNCTION blendFunction); - - public enum FontWeight : int - { - FW_DONTCARE = 0, - FW_THIN = 100, - FW_EXTRALIGHT = 200, - FW_LIGHT = 300, - FW_NORMAL = 400, - FW_MEDIUM = 500, - FW_SEMIBOLD = 600, - FW_BOLD = 700, - FW_EXTRABOLD = 800, - FW_HEAVY = 900, - } - public enum FontCharSet : byte - { - ANSI_CHARSET = 0, - DEFAULT_CHARSET = 1, - SYMBOL_CHARSET = 2, - SHIFTJIS_CHARSET = 128, - HANGEUL_CHARSET = 129, - HANGUL_CHARSET = 129, - GB2312_CHARSET = 134, - CHINESEBIG5_CHARSET = 136, - OEM_CHARSET = 255, - JOHAB_CHARSET = 130, - HEBREW_CHARSET = 177, - ARABIC_CHARSET = 178, - GREEK_CHARSET = 161, - TURKISH_CHARSET = 162, - VIETNAMESE_CHARSET = 163, - THAI_CHARSET = 222, - EASTEUROPE_CHARSET = 238, - RUSSIAN_CHARSET = 204, - MAC_CHARSET = 77, - BALTIC_CHARSET = 186, - } - public enum FontPrecision : byte - { - OUT_DEFAULT_PRECIS = 0, - OUT_STRING_PRECIS = 1, - OUT_CHARACTER_PRECIS = 2, - OUT_STROKE_PRECIS = 3, - OUT_TT_PRECIS = 4, - OUT_DEVICE_PRECIS = 5, - OUT_RASTER_PRECIS = 6, - OUT_TT_ONLY_PRECIS = 7, - OUT_OUTLINE_PRECIS = 8, - OUT_SCREEN_OUTLINE_PRECIS = 9, - OUT_PS_ONLY_PRECIS = 10, - } - public enum FontClipPrecision : byte - { - CLIP_DEFAULT_PRECIS = 0, - CLIP_CHARACTER_PRECIS = 1, - CLIP_STROKE_PRECIS = 2, - CLIP_MASK = 0xf, - CLIP_LH_ANGLES = (1 << 4), - CLIP_TT_ALWAYS = (2 << 4), - CLIP_DFA_DISABLE = (4 << 4), - CLIP_EMBEDDED = (8 << 4), - } - public enum FontQuality : byte - { - DEFAULT_QUALITY = 0, - DRAFT_QUALITY = 1, - PROOF_QUALITY = 2, - NONANTIALIASED_QUALITY = 3, - ANTIALIASED_QUALITY = 4, - CLEARTYPE_QUALITY = 5, - CLEARTYPE_NATURAL_QUALITY = 6, - } - [Flags] - public enum FontPitchAndFamily : byte - { - DEFAULT_PITCH = 0, - FIXED_PITCH = 1, - VARIABLE_PITCH = 2, - FF_DONTCARE = (0 << 4), - FF_ROMAN = (1 << 4), - FF_SWISS = (2 << 4), - FF_MODERN = (3 << 4), - FF_SCRIPT = (4 << 4), - FF_DECORATIVE = (5 << 4), - } - - //it is important for this to be the right declaration - //see more here http://www.tech-archive.net/Archive/DotNet/microsoft.public.dotnet.framework.drawing/2004-04/0319.html - //if it's wrong (I had a wrong one from pinvoke.net) then ToLogFont will fail mysteriously - [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] - class LOGFONT - { - public int lfHeight = 0; - public int lfWidth = 0; - public int lfEscapement = 0; - public int lfOrientation = 0; - public int lfWeight = 0; - public byte lfItalic = 0; - public byte lfUnderline = 0; - public byte lfStrikeOut = 0; - public byte lfCharSet = 0; - public byte lfOutPrecision = 0; - public byte lfClipPrecision = 0; - public byte lfQuality = 0; - public byte lfPitchAndFamily = 0; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)] - public string lfFaceName = null; - } - - /// - /// The graphics mode that can be set by SetGraphicsMode. - /// - public enum GraphicsMode : int - { - /// - /// Sets the graphics mode that is compatible with 16-bit Windows. This is the default mode. If - /// this value is specified, the application can only modify the world-to-device transform by - /// calling functions that set window and viewport extents and origins, but not by using - /// SetWorldTransform or ModifyWorldTransform; calls to those functions will fail. - /// Examples of functions that set window and viewport extents and origins are SetViewportExtEx - /// and SetWindowExtEx. - /// - GM_COMPATIBLE = 1, - /// - /// Sets the advanced graphics mode that allows world transformations. This value must be - /// specified if the application will set or modify the world transformation for the specified - /// device context. In this mode all graphics, including text output, fully conform to the - /// world-to-device transformation specified in the device context. - /// - GM_ADVANCED = 2, - } - - /// - /// The XFORM structure specifies a world-space to page-space transformation. - /// - [StructLayout(LayoutKind.Sequential)] - public struct XFORM - { - public float eM11; - public float eM12; - public float eM21; - public float eM22; - public float eDx; - public float eDy; - - public XFORM(float eM11, float eM12, float eM21, float eM22, float eDx, float eDy) - { - this.eM11 = eM11; - this.eM12 = eM12; - this.eM21 = eM21; - this.eM22 = eM22; - this.eDx = eDx; - this.eDy = eDy; - } - - /// - /// Allows implicit converstion to a managed transformation matrix. - /// - public static implicit operator System.Drawing.Drawing2D.Matrix(XFORM xf) - { - return new System.Drawing.Drawing2D.Matrix(xf.eM11, xf.eM12, xf.eM21, xf.eM22, xf.eDx, xf.eDy); - } - - /// - /// Allows implicit converstion from a managed transformation matrix. - /// - public static implicit operator XFORM(System.Drawing.Drawing2D.Matrix m) - { - float[] elems = m.Elements; - return new XFORM(elems[0], elems[1], elems[2], elems[3], elems[4], elems[5]); - } - } - - [StructLayout(LayoutKind.Sequential)] - public struct BLENDFUNCTION - { - byte BlendOp; - byte BlendFlags; - byte SourceConstantAlpha; - byte AlphaFormat; - - public BLENDFUNCTION(byte op, byte flags, byte alpha, byte format) - { - BlendOp = op; - BlendFlags = flags; - SourceConstantAlpha = alpha; - AlphaFormat = format; - } - } - - const byte AC_SRC_OVER = 0x00; - const byte AC_SRC_ALPHA = 0x01; - - [DllImport("gdi32.dll")] - static extern int SetBitmapBits(IntPtr hbmp, uint cBytes, byte[] lpBits); - - #endregion - - #region Classes, Structs, and Enums - - public class GdiGraphicsLock : IDisposable - { - private readonly GDIRenderer Gdi; - - public GdiGraphicsLock(GDIRenderer gdi) - { - this.Gdi = gdi; - } - - public void Dispose() - { - Gdi._g.ReleaseHdc(Gdi._hdc); - Gdi._hdc = IntPtr.Zero; - Gdi._g = null; - } - } - - private struct Rect - { - private int _left; - private int _top; - private int _right; - private int _bottom; - - public Rect(Rectangle r) - { - _left = r.Left; - _top = r.Top; - _bottom = r.Bottom; - _right = r.Right; - } - } - - private struct GDIRect - { - private int left; - private int top; - private int right; - private int bottom; - - public GDIRect(Rectangle r) - { - left = r.Left; - top = r.Top; - bottom = r.Bottom; - right = r.Right; - } - } - - private struct GDIPoint - { - private int x; - private int y; - - private GDIPoint(int x, int y) - { - this.x = x; - this.y = y; - } - } - - [Flags] - public enum ETOOptions : uint - { - CLIPPED = 0x4, - GLYPH_INDEX = 0x10, - IGNORELANGUAGE = 0x1000, - NUMERICSLATIN = 0x800, - NUMERICSLOCAL = 0x400, - OPAQUE = 0x2, - PDY = 0x2000, - RTLREADING = 0x800, - } - - /// - /// See [http://msdn.microsoft.com/en-us/library/windows/desktop/dd162498(v=vs.85).aspx][15] - /// - [Flags] - public enum TextFormatFlags : uint - { - Default = 0x00000000, - Center = 0x00000001, - Right = 0x00000002, - VCenter = 0x00000004, - Bottom = 0x00000008, - WordBreak = 0x00000010, - SingleLine = 0x00000020, - ExpandTabs = 0x00000040, - TabStop = 0x00000080, - NoClip = 0x00000100, - ExternalLeading = 0x00000200, - CalcRect = 0x00000400, - NoPrefix = 0x00000800, - Internal = 0x00001000, - EditControl = 0x00002000, - PathEllipsis = 0x00004000, - EndEllipsis = 0x00008000, - ModifyString = 0x00010000, - RtlReading = 0x00020000, - WordEllipsis = 0x00040000, - NoFullWidthCharBreak = 0x00080000, - HidePrefix = 0x00100000, - ProfixOnly = 0x00200000, - } - - [Flags] - public enum PenStyles - { - PS_SOLID = 0x00000000 - // TODO - } - - public enum PaintObjects - { - WHITE_BRUSH = 0, - LTGRAY_BRUSH = 1, - GRAY_BRUSH = 2, - DKGRAY_BRUSH = 3, - BLACK_BRUSH = 4, - NULL_BRUSH = 5, - WHITE_PEN = 6, - BLACK_PEN = 7, - NULL_PEN = 8, - OEM_FIXED_FONT = 10, - ANSI_FIXED_FONT = 11, - ANSI_VAR_FONT = 12, - SYSTEM_FONT = 13, - DEVICE_DEFAULT_FONT = 14, - DEFAULT_PALETTE = 15, - SYSTEM_FIXED_FONT = 16, - DC_BRUSH = 18, - DC_PEN = 19, - } - - public enum BkModes : int - { - TRANSPARENT = 1, - OPAQUE = 2 - } - - #endregion - } -} diff --git a/BizHawk.Client.EmuHawk/CustomControls/HexView.cs b/BizHawk.Client.EmuHawk/CustomControls/HexView.cs index 30faae953b..446c41950f 100644 --- a/BizHawk.Client.EmuHawk/CustomControls/HexView.cs +++ b/BizHawk.Client.EmuHawk/CustomControls/HexView.cs @@ -12,7 +12,7 @@ namespace BizHawk.Client.EmuHawk { public class HexView : Control { - private readonly GDIRenderer Gdi; + //private readonly IControlRenderer _renderer; private readonly Font NormalFont; private Size _charSize; @@ -27,18 +27,18 @@ namespace BizHawk.Client.EmuHawk SetStyle(ControlStyles.SupportsTransparentBackColor, true); SetStyle(ControlStyles.Opaque, true); - Gdi = new GDIRenderer(); + //_renderer = new GdiRenderer(); - using (var g = CreateGraphics()) - using (var LCK = Gdi.LockGraphics(g)) - { - _charSize = Gdi.MeasureString("A", NormalFont); // TODO make this a property so changing it updates other values. - } + //using (var g = CreateGraphics()) + //using (var LCK = _renderer.LockGraphics(g)) + //{ + // _charSize = _renderer.MeasureString("A", NormalFont); // TODO make this a property so changing it updates other values. + //} } protected override void Dispose(bool disposing) { - Gdi.Dispose(); + //_renderer.Dispose(); NormalFont.Dispose(); @@ -49,21 +49,21 @@ namespace BizHawk.Client.EmuHawk protected override void OnPaint(PaintEventArgs e) { - using (var LCK = Gdi.LockGraphics(e.Graphics)) - { - Gdi.StartOffScreenBitmap(Width, Height); + //using (var lck = _renderer.LockGraphics(e.Graphics)) + //{ + // _renderer.StartOffScreenBitmap(Width, Height); - // White Background - Gdi.SetBrush(Color.White); - Gdi.SetSolidPen(Color.White); - Gdi.FillRectangle(0, 0, Width, Height); + // // White Background + // _renderer.SetBrush(Color.White); + // _renderer.SetSolidPen(Color.White); + // _renderer.FillRectangle(0, 0, Width, Height); - Gdi.DrawString("Hello World", new Point(10, 10)); + // _renderer.DrawString("Hello World", new Point(10, 10)); - Gdi.CopyToScreen(); - Gdi.EndOffScreenBitmap(); - } + // _renderer.CopyToScreen(); + // _renderer.EndOffScreenBitmap(); + //} } #endregion diff --git a/BizHawk.Client.EmuHawk/CustomControls/InputRoll/Cell.cs b/BizHawk.Client.EmuHawk/CustomControls/InputRoll/Cell.cs new file mode 100644 index 0000000000..4ccc3e8e9e --- /dev/null +++ b/BizHawk.Client.EmuHawk/CustomControls/InputRoll/Cell.cs @@ -0,0 +1,96 @@ +using System.Collections.Generic; + +namespace BizHawk.Client.EmuHawk +{ + /// + /// Represents a single cell of the + /// + public class Cell + { + public RollColumn Column { get; internal set; } + public int? RowIndex { get; internal set; } + public string CurrentText { get; internal set; } + + public Cell() { } + + public Cell(Cell cell) + { + Column = cell.Column; + RowIndex = cell.RowIndex; + } + + public bool IsDataCell => Column != null && RowIndex.HasValue; + + public override bool Equals(object obj) + { + var cell = obj as Cell; + if (cell != null) + { + return Column == cell.Column && RowIndex == cell.RowIndex; + } + + return false; + } + + public override int GetHashCode() + { + return Column.GetHashCode() + RowIndex.GetHashCode(); + } + + public static bool operator ==(Cell a, Cell b) + { + if (ReferenceEquals(a, null)) + { + return ReferenceEquals(b, null); + } + + return a.Equals(b); + } + + public static bool operator !=(Cell a, Cell b) + { + return !(a == b); + } + } + + internal class SortCell : IComparer + { + int IComparer.Compare(Cell c1, Cell c2) + { + if (c1 == null && c2 == null) + { + return 0; + } + + if (c2 == null) + { + return 1; + } + + if (c1 == null) + { + return -1; + } + + if (c1.RowIndex.HasValue) + { + if (c2.RowIndex.HasValue) + { + int row = c1.RowIndex.Value.CompareTo(c2.RowIndex.Value); + return row == 0 + ? c1.Column.Name.CompareTo(c2.Column.Name) + : row; + } + + return 1; + } + + if (c2.RowIndex.HasValue) + { + return -1; + } + + return c1.Column.Name.CompareTo(c2.Column.Name); + } + } +} diff --git a/BizHawk.Client.EmuHawk/CustomControls/InputRoll/ColumnType.cs b/BizHawk.Client.EmuHawk/CustomControls/InputRoll/ColumnType.cs new file mode 100644 index 0000000000..b0fb0ce845 --- /dev/null +++ b/BizHawk.Client.EmuHawk/CustomControls/InputRoll/ColumnType.cs @@ -0,0 +1,10 @@ +namespace BizHawk.Client.EmuHawk +{ + /// + /// Specifies the type of column of a + /// + public enum ColumnType + { + Boolean, Float, Text, Image + } +} diff --git a/BizHawk.Client.EmuHawk/CustomControls/InputRoll/InputRoll.Drawing.cs b/BizHawk.Client.EmuHawk/CustomControls/InputRoll/InputRoll.Drawing.cs new file mode 100644 index 0000000000..db18513b43 --- /dev/null +++ b/BizHawk.Client.EmuHawk/CustomControls/InputRoll/InputRoll.Drawing.cs @@ -0,0 +1,697 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Linq; +using System.Windows.Forms; +using BizHawk.Client.EmuHawk.WinFormExtensions; + +namespace BizHawk.Client.EmuHawk +{ + public partial class InputRoll + { + protected override void OnPaint(PaintEventArgs e) + { + using (_renderer.LockGraphics(e.Graphics, Width, Height)) + { + // White Background + _renderer.SetBrush(Color.White); + _renderer.SetSolidPen(Color.White); + _renderer.FillRectangle(0, 0, Width, Height); + + // Lag frame calculations + SetLagFramesArray(); + + var visibleColumns = _columns.VisibleColumns.ToList(); + + CalculateHorizontalColumnPositions(visibleColumns); + + if (visibleColumns.Any()) + { + DrawColumnBg(visibleColumns); + DrawColumnText(visibleColumns); + } + + // Background + DrawBg(visibleColumns); + + // Foreground + DrawData(visibleColumns); + + DrawColumnDrag(visibleColumns); + DrawCellDrag(visibleColumns); + } + } + + private void DrawString(string text, int? width, Point point) + { + if (string.IsNullOrWhiteSpace(text)) + { + return; + } + + if (width.HasValue) + { + var max = (width.Value - CellWidthPadding) / _charSize.Width; + if (text.Length >= max) + { + text = text.Substring(0, max); + } + } + + _renderer.DrawString(text, point); + } + + protected override void OnPaintBackground(PaintEventArgs e) + { + // Do nothing, and this should never be called + } + + private void CalculateHorizontalColumnPositions(List visibleColumns) + { + if (!HorizontalOrientation) + { + _horizontalColumnHeights = null; + _horizontalColumnTops = null; + return; + } + + _horizontalColumnHeights = new int[visibleColumns.Count]; + _horizontalColumnTops = new int[visibleColumns.Count]; + + int top = 0; + int startRow = FirstVisibleRow; + for (int j = 0; j < visibleColumns.Count; j++) + { + RollColumn col = visibleColumns[j]; + int height = CellHeight; + if (col.Rotatable && col.RotatedHeight != null) + { + height = Math.Max(height, col.RotatedHeight.Value); + } + else if (col.Rotatable) + { + string text; + int strOffsetX = 0; + int strOffsetY = 0; + QueryItemText(startRow, col, out text, ref strOffsetX, ref strOffsetY); + int textWidth = _renderer.MeasureString(text, _font).Width; + height = Math.Max(height, textWidth + (CellWidthPadding * 2)); + } + _horizontalColumnHeights[j] = height; + _horizontalColumnTops[j] = top; + top += height; + } + } + + private void DrawColumnDrag(List visibleColumns) + { + if (_columnDown?.Width != null && _columnDownMoved && _currentX.HasValue && _currentY.HasValue && IsHoveringOnColumnCell) + { + int columnWidth = _columnDown.Width.Value; + int columnHeight = CellHeight; + if (HorizontalOrientation) + { + int columnIndex = visibleColumns.IndexOf(_columnDown); + columnWidth = ColumnWidth; + columnHeight = GetHColHeight(columnIndex); + } + int x1 = _currentX.Value - (columnWidth / 2); + int y1 = _currentY.Value - (columnHeight / 2); + int x2 = x1 + columnWidth; + int y2 = y1 + columnHeight; + int textOffsetY = CellHeightPadding; + if (HorizontalOrientation) + { + int textHeight = _renderer.MeasureString(_columnDown.Text, _font).Height; + textOffsetY = (columnHeight - textHeight) / 2; + } + + _renderer.SetSolidPen(_backColor); + _renderer.DrawRectangle(x1, y1, x2, y2); + _renderer.PrepDrawString(_font, _foreColor); + _renderer.DrawString(_columnDown.Text, new Point(x1 + CellWidthPadding, y1 + textOffsetY)); + } + } + + private void DrawCellDrag(List visibleColumns) + { + if (_draggingCell != null && _draggingCell.RowIndex.HasValue && _draggingCell.Column.Width.HasValue + && _currentX.HasValue && _currentY.HasValue) + { + var text = ""; + int offsetX = 0; + int offsetY = 0; + QueryItemText?.Invoke(_draggingCell.RowIndex.Value, _draggingCell.Column, out text, ref offsetX, ref offsetY); + + Color bgColor = _backColor; + QueryItemBkColor?.Invoke(_draggingCell.RowIndex.Value, _draggingCell.Column, ref bgColor); + + int columnHeight = CellHeight; + if (HorizontalOrientation) + { + int columnIndex = visibleColumns.IndexOf(_draggingCell.Column); + columnHeight = GetHColHeight(columnIndex); + } + int x1 = _currentX.Value - (_draggingCell.Column.Width.Value / 2); + int y1 = _currentY.Value - (columnHeight / 2); + int x2 = x1 + _draggingCell.Column.Width.Value; + int y2 = y1 + columnHeight; + + _renderer.SetBrush(bgColor); + _renderer.FillRectangle(x1, y1, x2 - x1, y2 - y1); + _renderer.PrepDrawString(_font, _foreColor); + _renderer.DrawString(text, new Point(x1 + CellWidthPadding + offsetX, y1 + CellHeightPadding + offsetY)); + } + } + + private void DrawColumnText(List visibleColumns) + { + if (HorizontalOrientation) + { + int y = -_vBar.Value; + + _renderer.PrepDrawString(_font, _foreColor); + + for(int j = 0; j < visibleColumns.Count; j++) + { + var column = visibleColumns[j]; + var columnHeight = GetHColHeight(j); + var textHeight = _renderer.MeasureString(column.Text, _font).Height; + var point = new Point(CellWidthPadding, y + ((columnHeight - textHeight) / 2)); + + if (IsHoveringOnColumnCell && column == CurrentCell.Column) + { + _renderer.PrepDrawString(_font, SystemColors.HighlightText); + DrawString(column.Text, column.Width, point); + _renderer.PrepDrawString(_font, _foreColor); + } + else + { + DrawString(column.Text, column.Width, point); + } + + y += columnHeight; + } + } + else + { + _renderer.PrepDrawString(_font, _foreColor); + + foreach (var column in visibleColumns) + { + var point = new Point(column.Left.Value + 2 * CellWidthPadding - _hBar.Value, CellHeightPadding); // TODO: fix this CellPadding issue (2 * CellPadding vs just CellPadding) + + if (IsHoveringOnColumnCell && column == CurrentCell.Column) + { + _renderer.PrepDrawString(_font, SystemColors.HighlightText); + DrawString(column.Text, column.Width, point); + _renderer.PrepDrawString(_font, _foreColor); + } + else + { + DrawString(column.Text, column.Width, point); + } + } + } + } + + private void DrawData(List visibleColumns) + { + // Prevent exceptions with small TAStudio windows + if (visibleColumns.Count == 0) + { + return; + } + + if (QueryItemText != null) + { + if (HorizontalOrientation) + { + int startRow = FirstVisibleRow; + int range = Math.Min(LastVisibleRow, RowCount - 1) - startRow + 1; + + _renderer.PrepDrawString(_font, _foreColor); + int lastVisible = LastVisibleColumnIndex; + for (int j = FirstVisibleColumn; j <= lastVisible; j++) + { + RollColumn col = visibleColumns[j]; + int colHeight = GetHColHeight(j); + + for (int i = 0, f = 0; f < range; i++, f++) + { + f += _lagFrames[i]; + + int baseX = RowsToPixels(i) + (col.Rotatable ? CellWidth : 0); + int baseY = GetHColTop(j) - _vBar.Value; + + if (!col.Rotatable) + { + Bitmap image = null; + int bitmapOffsetX = 0; + int bitmapOffsetY = 0; + + QueryItemIcon?.Invoke(f + startRow, col, ref image, ref bitmapOffsetX, ref bitmapOffsetY); + + if (image != null) + { + int x = baseX + CellWidthPadding + bitmapOffsetX; + int y = baseY + CellHeightPadding + bitmapOffsetY; + _renderer.DrawBitmap(image, new Point(x, y)); + } + } + + string text; + int strOffsetX = 0; + int strOffsetY = 0; + QueryItemText(f + startRow, col, out text, ref strOffsetX, ref strOffsetY); + + int textWidth = _renderer.MeasureString(text, _font).Width; + if (col.Rotatable) + { + // Center Text + int textX = Math.Max(((colHeight - textWidth) / 2), CellWidthPadding) + strOffsetX; + int textY = CellWidthPadding + strOffsetY; + var point = new Point(baseX - textY, baseY + textX); + + _renderer.PrepDrawString(_font, _foreColor, rotate: true); + DrawString(text, null, point); + _renderer.PrepDrawString(_font, _foreColor, rotate: false); + } + else + { + // Center Text + int textX = Math.Max(((CellWidth - textWidth) / 2), CellWidthPadding) + strOffsetX; + int textY = CellHeightPadding + strOffsetY; + var point = new Point(baseX + textX, baseY + textY); + + DrawString(text, ColumnWidth, point); + } + } + } + } + else + { + int startRow = FirstVisibleRow; + int range = Math.Min(LastVisibleRow, RowCount - 1) - startRow + 1; + + _renderer.PrepDrawString(_font, _foreColor); + int xPadding = CellWidthPadding + 1 - _hBar.Value; + for (int i = 0, f = 0; f < range; i++, f++) // Vertical + { + f += _lagFrames[i]; + int lastVisible = LastVisibleColumnIndex; + for (int j = FirstVisibleColumn; j <= lastVisible; j++) // Horizontal + { + RollColumn col = visibleColumns[j]; + + string text; + int strOffsetX = 0; + int strOffsetY = 0; + Point point = new Point(col.Left.Value + xPadding, RowsToPixels(i) + CellHeightPadding); + + Bitmap image = null; + int bitmapOffsetX = 0; + int bitmapOffsetY = 0; + + QueryItemIcon?.Invoke(f + startRow, visibleColumns[j], ref image, ref bitmapOffsetX, ref bitmapOffsetY); + + if (image != null) + { + _renderer.DrawBitmap(image, new Point(point.X + bitmapOffsetX, point.Y + bitmapOffsetY + CellHeightPadding)); + } + + QueryItemText(f + startRow, visibleColumns[j], out text, ref strOffsetX, ref strOffsetY); + + bool rePrep = false; + if (_selectedItems.Contains(new Cell { Column = visibleColumns[j], RowIndex = f + startRow })) + { + _renderer.PrepDrawString(_font, SystemColors.HighlightText); + rePrep = true; + } + + DrawString(text, col.Width, new Point(point.X + strOffsetX, point.Y + strOffsetY)); + + if (rePrep) + { + _renderer.PrepDrawString(_font, _foreColor); + } + } + } + } + } + } + + private void DrawColumnBg(List visibleColumns) + { + _renderer.SetBrush(SystemColors.ControlLight); + _renderer.SetSolidPen(Color.Black); + + if (HorizontalOrientation) + { + _renderer.FillRectangle(0, 0, ColumnWidth + 1, DrawHeight + 1); + + int y = -_vBar.Value; + for (int j = 0; j < visibleColumns.Count; j++) + { + _renderer.Line(1, y, ColumnWidth, y); + y += GetHColHeight(j); + } + + if (visibleColumns.Any()) + { + _renderer.Line(1, y, ColumnWidth, y); + } + + _renderer.Line(0, 0, 0, y + 1); + _renderer.Line(ColumnWidth, 0, ColumnWidth, y + 1); + } + else + { + int bottomEdge = RowsToPixels(0); + + // Gray column box and black line underneath + _renderer.FillRectangle(0, 0, Width + 1, bottomEdge + 1); + _renderer.Line(0, 0, TotalColWidth.Value + 1, 0); + _renderer.Line(0, bottomEdge, TotalColWidth.Value + 1, bottomEdge); + + // Vertical black separators + foreach (var column in visibleColumns) + { + int pos = column.Left.Value - _hBar.Value; + _renderer.Line(pos, 0, pos, bottomEdge); + } + + // Draw right most line + if (visibleColumns.Any()) + { + int right = TotalColWidth.Value - _hBar.Value; + _renderer.Line(right, 0, right, bottomEdge); + } + } + + // Emphasis + foreach (var column in visibleColumns.Where(c => c.Emphasis)) + { + _renderer.SetBrush(SystemColors.ActiveBorder); + if (HorizontalOrientation) + { + int columnIndex = visibleColumns.IndexOf(column); + _renderer.FillRectangle(1, GetHColTop(columnIndex) + 1, ColumnWidth - 1, GetHColHeight(columnIndex) - 1); + } + else + { + _renderer.FillRectangle(column.Left.Value + 1 - _hBar.Value, 1, column.Width.Value - 1, ColumnHeight - 1); + } + } + + // If the user is hovering over a column + if (IsHoveringOnColumnCell) + { + if (HorizontalOrientation) + { + for (int i = 0; i < visibleColumns.Count; i++) + { + if (visibleColumns[i] != CurrentCell.Column) + { + continue; + } + + int top = GetHColTop(i) - _vBar.Value; + int height = GetHColHeight(i); + + _renderer.SetBrush(CurrentCell.Column.Emphasis + ? SystemColors.Highlight.Add(0x00222222) + : SystemColors.Highlight); + + _renderer.FillRectangle(1, top + 1, ColumnWidth - 1, height - 1); + } + } + else + { + // TODO multiple selected columns + foreach (var column in visibleColumns) + { + if (column == CurrentCell.Column) + { + // Left of column is to the right of the viewable area or right of column is to the left of the viewable area + if (column.Left.Value - _hBar.Value > Width || column.Right.Value - _hBar.Value < 0) + { + continue; + } + + int left = column.Left.Value - _hBar.Value; + int width = column.Right.Value - _hBar.Value - left; + + _renderer.SetBrush(CurrentCell.Column.Emphasis + ? SystemColors.Highlight.Add(0x00550000) + : SystemColors.Highlight); + + _renderer.FillRectangle(left + 1, 1, width - 1, ColumnHeight - 1); + } + } + } + } + } + + // TODO refactor this and DoBackGroundCallback functions. + /// + /// Draw Gridlines and background colors using QueryItemBkColor. + /// + private void DrawBg(List visibleColumns) + { + if (UseCustomBackground && QueryItemBkColor != null) + { + DoBackGroundCallback(visibleColumns); + } + + if (GridLines) + { + _renderer.SetSolidPen(SystemColors.ControlLight); + if (HorizontalOrientation) + { + // Columns + for (int i = 1; i < VisibleRows + 1; i++) + { + int x = RowsToPixels(i); + _renderer.Line(x, 1, x, DrawHeight); + } + + // Rows + for (int i = 0; i < visibleColumns.Count + 1; i++) + { + int y = GetHColTop(i) - _vBar.Value; + _renderer.Line(RowsToPixels(0) + 1, y, DrawWidth, y); + } + } + else + { + // Columns + int y = ColumnHeight + 1; + foreach (var column in visibleColumns) + { + int x = (column.Left ?? 0) - _hBar.Value; + _renderer.Line(x, y, x, Height - 1); + } + + if (visibleColumns.Any()) + { + int x = (TotalColWidth ?? 0) - _hBar.Value; + _renderer.Line(x, y, x, Height - 1); + } + + // Rows + for (int i = 1; i < VisibleRows + 1; i++) + { + _renderer.Line(0, RowsToPixels(i), Width + 1, RowsToPixels(i)); + } + } + } + + if (_selectedItems.Any()) + { + DoSelectionBG(visibleColumns); + } + } + + private void DoSelectionBG(List visibleColumns) + { + Color rowColor = Color.White; + int lastVisibleRow = LastVisibleRow; + int lastRow = -1; + foreach (Cell cell in _selectedItems) + { + if (cell.RowIndex > lastVisibleRow || cell.RowIndex < FirstVisibleRow || !VisibleColumns.Contains(cell.Column)) + { + continue; + } + + Cell relativeCell = new Cell + { + RowIndex = cell.RowIndex - FirstVisibleRow, + Column = cell.Column, + }; + relativeCell.RowIndex -= CountLagFramesAbsolute(relativeCell.RowIndex.Value); + + if (QueryRowBkColor != null && lastRow != cell.RowIndex.Value) + { + QueryRowBkColor(cell.RowIndex.Value, ref rowColor); + lastRow = cell.RowIndex.Value; + } + + Color cellColor = rowColor; + QueryItemBkColor?.Invoke(cell.RowIndex.Value, cell.Column, ref cellColor); + + // Alpha layering for cell before selection + float alpha = (float)cellColor.A / 255; + if (cellColor.A != 255 && cellColor.A != 0) + { + cellColor = Color.FromArgb(rowColor.R - (int)((rowColor.R - cellColor.R) * alpha), + rowColor.G - (int)((rowColor.G - cellColor.G) * alpha), + rowColor.B - (int)((rowColor.B - cellColor.B) * alpha)); + } + + // Alpha layering for selection + alpha = 0.33f; + cellColor = Color.FromArgb(cellColor.R - (int)((cellColor.R - SystemColors.Highlight.R) * alpha), + cellColor.G - (int)((cellColor.G - SystemColors.Highlight.G) * alpha), + cellColor.B - (int)((cellColor.B - SystemColors.Highlight.B) * alpha)); + DrawCellBG(cellColor, relativeCell, visibleColumns); + } + } + + /// + /// Given a cell with RowIndex in between 0 and VisibleRows, it draws the background color specified. Do not call with absolute row indices. + /// + private void DrawCellBG(Color color, Cell cell, List visibleColumns) + { + int x, y, w, h; + + if (HorizontalOrientation) + { + x = RowsToPixels(cell.RowIndex.Value) + 1; + if (x < ColumnWidth) + { + return; + } + + int columnIndex = visibleColumns.IndexOf(cell.Column); + w = CellWidth - 1; + y = GetHColTop(columnIndex) - _vBar.Value + 1; // We can't draw without row and column, so assume they exist and fail catastrophically if they don't + h = GetHColHeight(columnIndex) - 1; + } + else + { + y = RowsToPixels(cell.RowIndex.Value) + 1; // We can't draw without row and column, so assume they exist and fail catastrophically if they don't + if (y < ColumnHeight) + { + return; + } + + x = cell.Column.Left.Value - _hBar.Value + 1; + w = cell.Column.Width.Value - 1; + h = CellHeight - 1; + } + + // Don't draw if off screen. + if (x > DrawWidth || y > DrawHeight) + { + return; + } + + _renderer.SetBrush(color); + _renderer.FillRectangle(x, y, w, h); + } + + /// + /// Calls QueryItemBkColor callback for all visible cells and fills in the background of those cells. + /// + private void DoBackGroundCallback(List visibleColumns) + { + int startIndex = FirstVisibleRow; + int range = Math.Min(LastVisibleRow, RowCount - 1) - startIndex + 1; + int lastVisibleColumn = LastVisibleColumnIndex; + int firstVisibleColumn = FirstVisibleColumn; + + // Prevent exceptions with small TAStudio windows + if (firstVisibleColumn < 0) + { + return; + } + + if (HorizontalOrientation) + { + for (int i = 0, f = 0; f < range; i++, f++) + { + f += _lagFrames[i]; + + Color rowColor = Color.White; + QueryRowBkColor?.Invoke(f + startIndex, ref rowColor); + + for (int j = firstVisibleColumn; j <= lastVisibleColumn; j++) + { + Color itemColor = Color.White; + QueryItemBkColor?.Invoke(f + startIndex, visibleColumns[j], ref itemColor); + if (itemColor == Color.White) + { + itemColor = rowColor; + } + else if (itemColor.A != 255 && itemColor.A != 0) + { + float alpha = (float)itemColor.A / 255; + itemColor = Color.FromArgb(rowColor.R - (int)((rowColor.R - itemColor.R) * alpha), + rowColor.G - (int)((rowColor.G - itemColor.G) * alpha), + rowColor.B - (int)((rowColor.B - itemColor.B) * alpha)); + } + + if (itemColor != Color.White) // An easy optimization, don't draw unless the user specified something other than the default + { + var cell = new Cell + { + Column = visibleColumns[j], + RowIndex = i + }; + DrawCellBG(itemColor, cell, visibleColumns); + } + } + } + } + else + { + for (int i = 0, f = 0; f < range; i++, f++) // Vertical + { + f += _lagFrames[i]; + + Color rowColor = Color.White; + QueryRowBkColor?.Invoke(f + startIndex, ref rowColor); + + for (int j = FirstVisibleColumn; j <= lastVisibleColumn; j++) // Horizontal + { + Color itemColor = Color.White; + QueryItemBkColor?.Invoke(f + startIndex, visibleColumns[j], ref itemColor); + if (itemColor == Color.White) + { + itemColor = rowColor; + } + else if (itemColor.A != 255 && itemColor.A != 0) + { + float alpha = (float)itemColor.A / 255; + itemColor = Color.FromArgb(rowColor.R - (int)((rowColor.R - itemColor.R) * alpha), + rowColor.G - (int)((rowColor.G - itemColor.G) * alpha), + rowColor.B - (int)((rowColor.B - itemColor.B) * alpha)); + } + + if (itemColor != Color.White) // An easy optimization, don't draw unless the user specified something other than the default + { + var cell = new Cell + { + Column = visibleColumns[j], + RowIndex = i + }; + DrawCellBG(itemColor, cell, visibleColumns); + } + } + } + } + } + } +} diff --git a/BizHawk.Client.EmuHawk/CustomControls/InputRoll.cs b/BizHawk.Client.EmuHawk/CustomControls/InputRoll/InputRoll.cs similarity index 76% rename from BizHawk.Client.EmuHawk/CustomControls/InputRoll.cs rename to BizHawk.Client.EmuHawk/CustomControls/InputRoll/InputRoll.cs index 98455379bd..701811e58b 100644 --- a/BizHawk.Client.EmuHawk/CustomControls/InputRoll.cs +++ b/BizHawk.Client.EmuHawk/CustomControls/InputRoll/InputRoll.cs @@ -1,2301 +1,2096 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Drawing; -using System.Linq; -using System.Windows.Forms; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Drawing; +using System.Linq; +using System.Windows.Forms; + +using BizHawk.Client.Common; +using BizHawk.Client.EmuHawk.CustomControls; +using BizHawk.Common; + +namespace BizHawk.Client.EmuHawk +{ + // Row width depends on font size and padding + // Column width is specified in column headers + // Row width is specified for horizontal orientation + public partial class InputRoll : Control + { + private readonly IControlRenderer _renderer; + private readonly SortedSet _selectedItems = new SortedSet(new SortCell()); + + // scrollbar location(s) are calculated later (e.g. on resize) + private readonly VScrollBar _vBar = new VScrollBar { Visible = false }; + private readonly HScrollBar _hBar = new HScrollBar { Visible = false }; + + private readonly Timer _hoverTimer = new Timer(); + private readonly byte[] _lagFrames = new byte[256]; // Large enough value that it shouldn't ever need resizing. // apparently not large enough for 4K + + private readonly Color _foreColor; + private readonly Color _backColor; + + private RollColumns _columns = new RollColumns(); + private bool _horizontalOrientation; + private bool _programmaticallyUpdatingScrollBarValues; + private int _maxCharactersInHorizontal = 1; + + private int _rowCount; + private Size _charSize; -using BizHawk.Client.Common; -using BizHawk.Client.EmuHawk.CustomControls; - -namespace BizHawk.Client.EmuHawk -{ - // Row width depends on font size and padding - // Column width is specified in column headers - // Row width is specified for horizontal orientation - public partial class InputRoll : Control - { - private RollRenderer Renderer = RollRenderer.GDIPlus; - - private Font _commonFont; - - private readonly SortedSet _selectedItems = new SortedSet(new SortCell()); - - private readonly VScrollBar _vBar; - private readonly HScrollBar _hBar; - - private readonly Timer _hoverTimer = new Timer(); - private readonly byte[] _lagFrames = new byte[256]; // Large enough value that it shouldn't ever need resizing. // apparently not large enough for 4K - - private readonly Color _foreColor; - private readonly Color _backColor; - - private RollColumns _columns = new RollColumns(); - private bool _horizontalOrientation; - private bool _programmaticallyUpdatingScrollBarValues; - private int _maxCharactersInHorizontal = 1; - - private int _rowCount; - - private RollColumn _columnDown; - - private int? _currentX; - private int? _currentY; - - // Hiding lag frames (Mainly intended for < 60fps play.) - public int LagFramesToHide { get; set; } - public bool HideWasLagFrames { get; set; } - - public bool AllowRightClickSelecton { get; set; } - public bool LetKeysModifySelection { get; set; } - public bool SuspendHotkeys { get; set; } - - public InputRoll() - { - // set renderer once at InputRoll instantiation - Renderer = (RollRenderer)TAStudio.InputRollRenderer; - - UseCustomBackground = true; - GridLines = true; - CellWidthPadding = 3; - CellHeightPadding = 0; - CurrentCell = null; - ScrollMethod = "near"; - - switch (Renderer) + // Updated on paint + private int[] _horizontalColumnHeights; + private int[] _horizontalColumnTops; + + private RollColumn _columnDown; + private RollColumn _columnResizing; + + private int? _currentX; + private int? _currentY; + + // Hiding lag frames (Mainly intended for < 60fps play.) + [Browsable(false)] + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public int LagFramesToHide { get; set; } + + [Browsable(false)] + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public bool HideWasLagFrames { get; set; } + + [Category("Behavior")] + public bool AllowRightClickSelection { get; set; } + + [Category("Behavior")] + public bool LetKeysModifySelection { get; set; } + + [Browsable(false)] + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public bool SuspendHotkeys { get; set; } + + private readonly Font _font = new Font("Arial", 8, FontStyle.Bold); + + public InputRoll() + { + UseCustomBackground = true; + GridLines = true; + CellWidthPadding = 3; + CellHeightPadding = 0; + CurrentCell = null; + ScrollMethod = "near"; + + SetStyle(ControlStyles.AllPaintingInWmPaint, true); + SetStyle(ControlStyles.UserPaint, true); + SetStyle(ControlStyles.SupportsTransparentBackColor, true); + SetStyle(ControlStyles.Opaque, true); + SetStyle(ControlStyles.OptimizedDoubleBuffer, true); + + if (OSTailoredCode.CurrentOS == OSTailoredCode.DistinctOS.Windows) + { + _renderer = new GdiRenderer(); + } + else + { + _renderer = new GdiPlusRenderer(); + } + + using (var g = CreateGraphics()) + using (_renderer.LockGraphics(g, Width, Height)) { - case RollRenderer.GDI: - _commonFont = new Font("Arial", 8, FontStyle.Bold); - _normalFont = GDIRenderer.CreateNormalHFont(_commonFont, 6); - - // PrepDrawString doesn't actually set the font, so this is rather useless. - // I'm leaving this stuff as-is so it will be a bit easier to fix up with another rendering method. - _rotatedFont = GDIRenderer.CreateRotatedHFont(_commonFont, true); - - SetStyle(ControlStyles.AllPaintingInWmPaint, true); - SetStyle(ControlStyles.UserPaint, true); - SetStyle(ControlStyles.SupportsTransparentBackColor, true); - SetStyle(ControlStyles.Opaque, true); - - _gdi = new GDIRenderer(); - GDIConstruction(); - break; - case RollRenderer.GDIPlus: -// _commonFont = new Font("Courier New", 8, FontStyle.Bold); - _commonFont = new Font("Arial", 8, FontStyle.Bold); - GDIPConstruction(); - break; - } - - UpdateCellSize(); - ColumnWidth = CellWidth; - ColumnHeight = CellHeight + 2; - - _vBar = new VScrollBar - { - // Location gets calculated later (e.g. on resize) - Visible = false, - SmallChange = CellHeight, - LargeChange = CellHeight * 20 - }; - - _hBar = new HScrollBar - { - // Location gets calculated later (e.g. on resize) - Visible = false, - SmallChange = CellWidth, - LargeChange = 20 - }; - - Controls.Add(_vBar); - Controls.Add(_hBar); - - _vBar.ValueChanged += VerticalBar_ValueChanged; - _hBar.ValueChanged += HorizontalBar_ValueChanged; - - HorizontalOrientation = false; - RecalculateScrollBars(); - _columns.ChangedCallback = ColumnChangedCallback; - - _hoverTimer.Interval = 750; - _hoverTimer.Tick += HoverTimerEventProcessor; - _hoverTimer.Stop(); - - _foreColor = ForeColor; - _backColor = BackColor; - } - - private void HoverTimerEventProcessor(object sender, EventArgs e) - { - _hoverTimer.Stop(); - - CellHovered?.Invoke(this, new CellEventArgs(LastCell, CurrentCell)); - } - - protected override void Dispose(bool disposing) - { - if (Renderer == RollRenderer.GDI) GDIDispose(); - base.Dispose(disposing); - } - - #region Properties - - /// - /// Gets or sets the amount of left and right padding on the text inside a cell - /// - [DefaultValue(3)] - [Category("Behavior")] - public int CellWidthPadding { get; set; } - - /// - /// Gets or sets the amount of top and bottom padding on the text inside a cell - /// - [DefaultValue(1)] - [Category("Behavior")] - public int CellHeightPadding { get; set; } - - /// - /// Gets or sets a value indicating whether grid lines are displayed around cells - /// - [Category("Appearance")] - [DefaultValue(true)] - public bool GridLines { get; set; } - - /// - /// Gets or sets a value indicating whether the control is horizontal or vertical - /// - [Category("Behavior")] - public bool HorizontalOrientation - { - get - { - return _horizontalOrientation; - } - set - { - if (_horizontalOrientation != value) - { - int temp = ScrollSpeed; - _horizontalOrientation = value; - OrientationChanged(); - _hBar.SmallChange = CellWidth; - _vBar.SmallChange = CellHeight; - ScrollSpeed = temp; - } - } - } - - /// - /// Gets or sets the scrolling speed - /// - [Category("Behavior")] - public int ScrollSpeed - { - get - { - if (HorizontalOrientation) - { - return _hBar.SmallChange / CellWidth; - } - if (CellHeight == 0) CellHeight++; - return _vBar.SmallChange / CellHeight; - } - - set - { - if (HorizontalOrientation) - { - _hBar.SmallChange = value * CellWidth; - } - else - { - _vBar.SmallChange = value * CellHeight; - } - } - } - - /// - /// Gets or sets the sets the virtual number of rows to be displayed. Does not include the column header row. - /// - [Category("Behavior")] - public int RowCount - { - get - { - return _rowCount; - } - - set - { - _rowCount = value; - RecalculateScrollBars(); - } - } - - /// - /// Gets or sets a value indicating whether columns can be resized - /// - [Category("Behavior")] - public bool AllowColumnResize { get; set; } - - /// - /// Gets or sets a value indicating whether columns can be reordered - /// - [Category("Behavior")] - public bool AllowColumnReorder { get; set; } - - /// - /// Gets or sets a value indicating whether the entire row will always be selected - /// - [Category("Appearance")] - [DefaultValue(false)] - public bool FullRowSelect { get; set; } - - /// - /// Gets or sets a value indicating whether multiple items can to be selected - /// - [Category("Behavior")] - [DefaultValue(true)] - public bool MultiSelect { get; set; } - - /// - /// Gets or sets a value indicating whether the control is in input painting mode - /// - [Category("Behavior")] - [DefaultValue(false)] - public bool InputPaintingMode { get; set; } - - /// - /// All visible columns - /// - [Category("Behavior")] - public IEnumerable VisibleColumns => _columns.VisibleColumns; - - /// - /// Gets or sets how the InputRoll scrolls when calling ScrollToIndex. - /// - [DefaultValue("near")] - [Category("Behavior")] - public string ScrollMethod { get; set; } - - /// - /// Gets or sets a value indicating how the Intever for the hover event - /// - [Category("Behavior")] - public bool AlwaysScroll { get; set; } - - /// - /// Gets or sets the lowest seek interval to activate the progress bar - /// - [Category("Behavior")] - public int SeekingCutoffInterval { get; set; } - - /// - /// Returns all columns including those that are not visible - /// - [Browsable(false)] - [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] - public RollColumns AllColumns => _columns; - - [DefaultValue(750)] - [Category("Behavior")] - public int HoverInterval - { - get { return _hoverTimer.Interval; } - set { _hoverTimer.Interval = value; } - } - - #endregion - - #region Event Handlers - - /// - /// Fire the event which requests the text for the passed cell - /// - [Category("Virtual")] - public event QueryItemTextHandler QueryItemText; - - /// - /// Fire the event which requests the background color for the passed cell - /// - [Category("Virtual")] - public event QueryItemBkColorHandler QueryItemBkColor; - - [Category("Virtual")] - public event QueryRowBkColorHandler QueryRowBkColor; - - /// - /// Fire the event which requests an icon for a given cell - /// - [Category("Virtual")] - public event QueryItemIconHandler QueryItemIcon; - - /// - /// Fire the QueryFrameLag event which checks if a given frame is a lag frame - /// - [Category("Virtual")] - public event QueryFrameLagHandler QueryFrameLag; - - /// - /// Fires when the mouse moves from one cell to another (including column header cells) - /// - [Category("Mouse")] - public event CellChangeEventHandler PointedCellChanged; - - /// - /// Fires when a cell is hovered on - /// - [Category("Mouse")] - public event HoverEventHandler CellHovered; - - /// - /// Occurs when a column header is clicked - /// - [Category("Action")] - public event ColumnClickEventHandler ColumnClick; - - /// - /// Occurs when a column header is right-clicked - /// - [Category("Action")] - public event ColumnClickEventHandler ColumnRightClick; - - /// - /// Occurs whenever the 'SelectedItems' property for this control changes - /// - [Category("Behavior")] - public event EventHandler SelectedIndexChanged; - - /// - /// Occurs whenever the mouse wheel is scrolled while the right mouse button is held - /// - [Category("Behavior")] - public event RightMouseScrollEventHandler RightMouseScrolled; - - [Category("Property Changed")] - [Description("Occurs when the column header has been reordered")] - public event ColumnReorderedEventHandler ColumnReordered; - - [Category("Action")] - [Description("Occurs when the scroll value of the visible rows change (in vertical orientation this is the vertical scroll bar change, and in horizontal it is the horizontal scroll bar)")] - public event RowScrollEvent RowScroll; - - [Category("Action")] - [Description("Occurs when the scroll value of the columns (in vertical orientation this is the horizontal scroll bar change, and in horizontal it is the vertical scroll bar)")] - public event ColumnScrollEvent ColumnScroll; - - [Category("Action")] - [Description("Occurs when a cell is dragged and then dropped into a new cell, old cell is the cell that was being dragged, new cell is its new destination")] - public event CellDroppedEvent CellDropped; - - /// - /// Retrieve the text for a cell - /// - public delegate void QueryItemTextHandler(int index, RollColumn column, out string text, ref int offsetX, ref int offsetY); - - /// - /// Retrieve the background color for a cell - /// - public delegate void QueryItemBkColorHandler(int index, RollColumn column, ref Color color); - public delegate void QueryRowBkColorHandler(int index, ref Color color); - - /// - /// Retrieve the image for a given cell - /// - public delegate void QueryItemIconHandler(int index, RollColumn column, ref Bitmap icon, ref int offsetX, ref int offsetY); - - /// - /// Check if a given frame is a lag frame - /// - public delegate bool QueryFrameLagHandler(int index, bool hideWasLag); - - public delegate void CellChangeEventHandler(object sender, CellEventArgs e); - - public delegate void HoverEventHandler(object sender, CellEventArgs e); - - public delegate void RightMouseScrollEventHandler(object sender, MouseEventArgs e); - - public delegate void ColumnClickEventHandler(object sender, ColumnClickEventArgs e); - - public delegate void ColumnReorderedEventHandler(object sender, ColumnReorderedEventArgs e); - - public delegate void RowScrollEvent(object sender, EventArgs e); - - public delegate void ColumnScrollEvent(object sender, EventArgs e); - - public delegate void CellDroppedEvent(object sender, CellEventArgs e); - - public class CellEventArgs - { - public CellEventArgs(Cell oldCell, Cell newCell) - { - OldCell = oldCell; - NewCell = newCell; - } - - public Cell OldCell { get; private set; } - public Cell NewCell { get; private set; } - } - - public class ColumnClickEventArgs - { - public ColumnClickEventArgs(RollColumn column) - { - Column = column; - } - - public RollColumn Column { get; private set; } - } - - public class ColumnReorderedEventArgs - { - public ColumnReorderedEventArgs(int oldDisplayIndex, int newDisplayIndex, RollColumn column) - { - Column = column; - OldDisplayIndex = oldDisplayIndex; - NewDisplayIndex = newDisplayIndex; - } - - public RollColumn Column { get; private set; } - public int OldDisplayIndex { get; private set; } - public int NewDisplayIndex { get; private set; } - } - - #endregion - - #region Api - - public void SelectRow(int index, bool val) - { - if (_columns.VisibleColumns.Any()) - { - if (val) - { - SelectCell(new Cell - { - RowIndex = index, - Column = _columns[0] - }); - } - else - { - IEnumerable items = _selectedItems.Where(cell => cell.RowIndex == index); - _selectedItems.RemoveWhere(items.Contains); - } - } - } - - public void SelectAll() - { - var oldFullRowVal = FullRowSelect; - FullRowSelect = true; - for (int i = 0; i < RowCount; i++) - { - SelectRow(i, true); - } - - FullRowSelect = oldFullRowVal; - } - - public void DeselectAll() - { - _selectedItems.Clear(); - } - - public void TruncateSelection(int index) - { - _selectedItems.RemoveWhere(cell => cell.RowIndex > index); - } - - [Browsable(false)] - [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] - public bool IsPointingAtColumnHeader => IsHoveringOnColumnCell; - - [Browsable(false)] - [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] - public int? FirstSelectedIndex - { - get - { - if (AnyRowsSelected) - { - return SelectedRows.Min(); - } - - return null; - } - } - - [Browsable(false)] - [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] - public int? LastSelectedIndex - { - get - { - if (AnyRowsSelected) - { - return SelectedRows.Max(); - } - - return null; - } - } - - /// - /// Gets or sets the current Cell that the mouse was in. - /// - [Browsable(false)] - [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] - public Cell CurrentCell { get; set; } - - [Browsable(false)] - [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] - public bool CurrentCellIsDataCell => CurrentCell?.RowIndex != null && CurrentCell.Column != null; - - /// - /// Gets or sets the previous Cell that the mouse was in. - /// - [Browsable(false)] - [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] - public Cell LastCell { get; private set; } - - [Browsable(false)] - [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] - public bool IsPaintDown { get; private set; } - - [Browsable(false)] - [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] - public bool UseCustomBackground { get; set; } - - [Browsable(false)] - [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] - public int DrawHeight { get; private set; } - - [Browsable(false)] - [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] - public int DrawWidth { get; private set; } - - /// - /// Gets or sets the width of data cells when in Horizontal orientation. - /// - public int MaxCharactersInHorizontal - { - get - { - return _maxCharactersInHorizontal; - } - - set - { - _maxCharactersInHorizontal = value; - UpdateCellSize(); - } - } - - [Browsable(false)] - [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] - public bool RightButtonHeld { get; private set; } - - public string UserSettingsSerialized() - { - var settings = ConfigService.SaveWithType(Settings); - return settings; - } - - public void LoadSettingsSerialized(string settingsJson) - { - var settings = ConfigService.LoadWithType(settingsJson); - - // TODO: don't silently fail, inform the user somehow - if (settings is InputRollSettings) - { - var rollSettings = settings as InputRollSettings; - _columns = rollSettings.Columns; - _columns.ChangedCallback = ColumnChangedCallback; - HorizontalOrientation = rollSettings.HorizontalOrientation; - LagFramesToHide = rollSettings.LagFramesToHide; - HideWasLagFrames = rollSettings.HideWasLagFrames; - } - } - - private InputRollSettings Settings => new InputRollSettings - { - Columns = _columns, - HorizontalOrientation = HorizontalOrientation, - LagFramesToHide = LagFramesToHide, - HideWasLagFrames = HideWasLagFrames - }; - - public class InputRollSettings - { - public RollColumns Columns { get; set; } - public bool HorizontalOrientation { get; set; } - public int LagFramesToHide { get; set; } - public bool HideWasLagFrames { get; set; } - } - - /// - /// Gets or sets the first visible row index, if scrolling is needed - /// - [Browsable(false)] - [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] - public int FirstVisibleRow - { - get // SuuperW: This was checking if the scroll bars were needed, which is useless because their Value is 0 if they aren't needed. - { - if (HorizontalOrientation) - { - return _hBar.Value / CellWidth; - } - if (CellHeight == 0) CellHeight++; - return _vBar.Value / CellHeight; - } - - set - { - if (HorizontalOrientation) - { - if (NeedsHScrollbar) - { - _programmaticallyUpdatingScrollBarValues = true; - if (value * CellWidth <= _hBar.Maximum) - { - _hBar.Value = value * CellWidth; - } - else - { - _hBar.Value = _hBar.Maximum; - } - - _programmaticallyUpdatingScrollBarValues = false; - } - } - else - { - if (NeedsVScrollbar) - { - _programmaticallyUpdatingScrollBarValues = true; - if (value * CellHeight <= _vBar.Maximum) - { - _vBar.Value = value * CellHeight; - } - else - { - _vBar.Value = _vBar.Maximum; - } - - _programmaticallyUpdatingScrollBarValues = false; - } - } - } - } - - [Browsable(false)] - [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] - private int LastFullyVisibleRow - { - get - { - int halfRow = 0; - if ((DrawHeight - ColumnHeight - 3) % CellHeight < CellHeight / 2) - { - halfRow = 1; - } - - return FirstVisibleRow + VisibleRows - halfRow + CountLagFramesDisplay(VisibleRows - halfRow); - } - } - - [Browsable(false)] - [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] - public int LastVisibleRow - { - get - { - return FirstVisibleRow + VisibleRows + CountLagFramesDisplay(VisibleRows); - } - - set - { - int halfRow = 0; - if ((DrawHeight - ColumnHeight - 3) % CellHeight < CellHeight / 2) - { - halfRow = 1; - } - - if (LagFramesToHide == 0) - { - FirstVisibleRow = Math.Max(value - (VisibleRows - halfRow), 0); - } - else - { - if (Math.Abs(LastFullyVisibleRow - value) > VisibleRows) // Big jump - { - FirstVisibleRow = Math.Max(value - (ExpectedDisplayRange() - halfRow), 0); - SetLagFramesArray(); - } - - // Small jump, more accurate - int lastVisible = LastFullyVisibleRow; - do - { - if ((lastVisible - value) / (LagFramesToHide + 1) != 0) - { - FirstVisibleRow = Math.Max(FirstVisibleRow - ((lastVisible - value) / (LagFramesToHide + 1)), 0); - } - else - { - FirstVisibleRow -= Math.Sign(lastVisible - value); - } - - SetLagFramesArray(); - lastVisible = LastFullyVisibleRow; - } - while ((lastVisible - value < 0 || lastVisible - value > _lagFrames[VisibleRows - halfRow]) && FirstVisibleRow != 0); - } - } - } - - public bool IsVisible(int index) - { - return (index >= FirstVisibleRow) && (index <= LastFullyVisibleRow); - } - - public bool IsPartiallyVisible(int index) - { - return index >= FirstVisibleRow && index <= LastVisibleRow; - } - - /// - /// Gets the number of rows currently visible including partially visible rows. - /// - [Browsable(false)] - [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] - public int VisibleRows - { - get - { - if (CellHeight == 0) CellHeight++; - if (HorizontalOrientation) - { - return (DrawWidth - ColumnWidth) / CellWidth; - } - - return (DrawHeight - ColumnHeight - 3) / CellHeight; // Minus three makes it work - } - } - - /// - /// Gets the first visible column index, if scrolling is needed - /// - [Browsable(false)] - [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] - public int FirstVisibleColumn - { - get - { - if (CellHeight == 0) CellHeight++; - if (HorizontalOrientation) - { - return _vBar.Value / CellHeight; - } - - var columnList = VisibleColumns.ToList(); - return columnList.FindIndex(c => c.Right > _hBar.Value); - } - } - - [Browsable(false)] - [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] - public int LastVisibleColumnIndex - { - get - { - if (CellHeight == 0) CellHeight++; - List columnList = VisibleColumns.ToList(); - int ret; - if (HorizontalOrientation) - { - ret = (_vBar.Value + DrawHeight) / CellHeight; - if (ret >= columnList.Count) - { - ret = columnList.Count - 1; - } - } - else - { - ret = columnList.FindLastIndex(c => c.Left <= DrawWidth + _hBar.Value); - } - - return ret; - } - } - - private Cell _draggingCell; - - public void DragCurrentCell() - { - _draggingCell = CurrentCell; - } - - public void ReleaseCurrentCell() - { - if (_draggingCell != null) - { - var draggedCell = _draggingCell; - _draggingCell = null; - - if (CurrentCell != draggedCell) - { - CellDropped?.Invoke(this, new CellEventArgs(draggedCell, CurrentCell)); - } - } - } - - /// - /// Scrolls to the given index, according to the scroll settings. - /// - public void ScrollToIndex(int index) - { - if (ScrollMethod == "near") - { - MakeIndexVisible(index); - } - - if (!IsVisible(index) || AlwaysScroll) - { - if (ScrollMethod == "top") - { - FirstVisibleRow = index; - } - else if (ScrollMethod == "bottom") - { - LastVisibleRow = index; - } - else if (ScrollMethod == "center") - { - if (LagFramesToHide == 0) - { - FirstVisibleRow = Math.Max(index - (VisibleRows / 2), 0); - } - else - { - if (Math.Abs(FirstVisibleRow + CountLagFramesDisplay(VisibleRows / 2) - index) > VisibleRows) // Big jump - { - FirstVisibleRow = Math.Max(index - (ExpectedDisplayRange() / 2), 0); - SetLagFramesArray(); - } - - // Small jump, more accurate - int lastVisible = FirstVisibleRow + CountLagFramesDisplay(VisibleRows / 2); - do - { - if ((lastVisible - index) / (LagFramesToHide + 1) != 0) - { - FirstVisibleRow = Math.Max(FirstVisibleRow - ((lastVisible - index) / (LagFramesToHide + 1)), 0); - } - else - { - FirstVisibleRow -= Math.Sign(lastVisible - index); - } - - SetLagFramesArray(); - lastVisible = FirstVisibleRow + CountLagFramesDisplay(VisibleRows / 2); - } - while ((lastVisible - index < 0 || lastVisible - index > _lagFrames[VisibleRows]) && FirstVisibleRow != 0); - } - } - } - } - - /// - /// Scrolls so that the given index is visible, if it isn't already; doesn't use scroll settings. - /// - public void MakeIndexVisible(int index) - { - if (!IsVisible(index)) - { - if (FirstVisibleRow > index) - { - FirstVisibleRow = index; - } - else - { - LastVisibleRow = index; - } - } - } - - [Browsable(false)] - [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] - public IEnumerable SelectedRows - { - get - { - return _selectedItems - .Where(cell => cell.RowIndex.HasValue) - .Select(cell => cell.RowIndex.Value) - .Distinct(); - } - } - - public bool AnyRowsSelected - { - get - { - return _selectedItems.Any(cell => cell.RowIndex.HasValue); - } - } - - public void ClearSelectedRows() - { - _selectedItems.Clear(); - } - - public IEnumerable GenerateContextMenuItems() - { - yield return new ToolStripSeparator(); - - var rotate = new ToolStripMenuItem - { - Name = "RotateMenuItem", - Text = "Rotate", - ShortcutKeyDisplayString = RotateHotkeyStr, - }; - - rotate.Click += (o, ev) => - { - HorizontalOrientation ^= true; - }; - - yield return rotate; - } - - public string RotateHotkeyStr => "Ctrl+Shift+F"; - - #endregion - - #region Mouse and Key Events - - private bool _columnDownMoved; - protected override void OnMouseMove(MouseEventArgs e) - { - _currentX = e.X; - _currentY = e.Y; - - if (_columnDown != null) - { - _columnDownMoved = true; - } - - Cell newCell = CalculatePointedCell(_currentX.Value, _currentY.Value); - - // SuuperW: Hide lag frames - if (QueryFrameLag != null && newCell.RowIndex.HasValue) - { - newCell.RowIndex += CountLagFramesDisplay(newCell.RowIndex.Value); - } - - newCell.RowIndex += FirstVisibleRow; - if (newCell.RowIndex < 0) - { - newCell.RowIndex = 0; - } - - if (!newCell.Equals(CurrentCell)) - { - CellChanged(newCell); - - if (IsHoveringOnColumnCell || - (WasHoveringOnColumnCell && !IsHoveringOnColumnCell)) - { - Refresh(); - } - else if (_columnDown != null) - { - Refresh(); - } - } - else if (_columnDown != null) // Kind of silly feeling to have this check twice, but the only alternative I can think of has it refreshing twice when pointed column changes with column down, and speed matters - { - Refresh(); - } - - base.OnMouseMove(e); - } - - protected override void OnMouseEnter(EventArgs e) - { - CurrentCell = new Cell - { - Column = null, - RowIndex = null - }; - - base.OnMouseEnter(e); - } - - protected override void OnMouseLeave(EventArgs e) - { - _currentX = null; - _currentY = null; - CurrentCell = null; - IsPaintDown = false; - _hoverTimer.Stop(); - Refresh(); - base.OnMouseLeave(e); - } - - // TODO add query callback of whether to select the cell or not - protected override void OnMouseDown(MouseEventArgs e) - { - if (!GlobalWin.MainForm.EmulatorPaused && _currentX.HasValue) - { - // copypaste from OnMouseMove() - Cell newCell = CalculatePointedCell(_currentX.Value, _currentY.Value); - if (QueryFrameLag != null && newCell.RowIndex.HasValue) - { - newCell.RowIndex += CountLagFramesDisplay(newCell.RowIndex.Value); - } - - newCell.RowIndex += FirstVisibleRow; - if (newCell.RowIndex < 0) - { - newCell.RowIndex = 0; - } - - if (!newCell.Equals(CurrentCell)) - { - CellChanged(newCell); - - if (IsHoveringOnColumnCell || - (WasHoveringOnColumnCell && !IsHoveringOnColumnCell)) - { - Refresh(); - } - else if (_columnDown != null) - { - Refresh(); - } - } - else if (_columnDown != null) - { - Refresh(); - } - } - - if (e.Button == MouseButtons.Left) - { - if (IsHoveringOnColumnCell) - { - _columnDown = CurrentCell.Column; - } - else if (InputPaintingMode) - { - IsPaintDown = true; - } - } - - if (e.Button == MouseButtons.Right) - { - if (!IsHoveringOnColumnCell) - { - RightButtonHeld = true; - } - } - - if (e.Button == MouseButtons.Left) - { - if (IsHoveringOnDataCell) - { - if (ModifierKeys == Keys.Alt) - { - // do marker drag here - } - else if (ModifierKeys == Keys.Shift && (CurrentCell.Column.Name == "FrameColumn" || CurrentCell.Column.Type == RollColumn.InputType.Text)) - { - if (_selectedItems.Any()) - { - if (FullRowSelect) - { - var selected = _selectedItems.Any(c => c.RowIndex.HasValue && CurrentCell.RowIndex.HasValue && c.RowIndex == CurrentCell.RowIndex); - - if (!selected) - { - var rowIndices = _selectedItems - .Where(c => c.RowIndex.HasValue) - .Select(c => c.RowIndex ?? -1) - .Where(c => c >= 0) // Hack to avoid possible Nullable exceptions - .Distinct() - .ToList(); - - var firstIndex = rowIndices.Min(); - var lastIndex = rowIndices.Max(); - - if (CurrentCell.RowIndex.Value < firstIndex) - { - for (int i = CurrentCell.RowIndex.Value; i < firstIndex; i++) - { - SelectCell(new Cell - { - RowIndex = i, - Column = CurrentCell.Column - }); - } - } - else if (CurrentCell.RowIndex.Value > lastIndex) - { - for (int i = lastIndex + 1; i <= CurrentCell.RowIndex.Value; i++) - { - SelectCell(new Cell - { - RowIndex = i, - Column = CurrentCell.Column - }); - } - } - else // Somewhere in between, a scenario that can happen with ctrl-clicking, find the previous and highlight from there - { - var nearest = rowIndices - .Where(x => x < CurrentCell.RowIndex.Value) - .Max(); - - for (int i = nearest + 1; i <= CurrentCell.RowIndex.Value; i++) - { - SelectCell(new Cell - { - RowIndex = i, - Column = CurrentCell.Column - }); - } - } - } - } - else - { - MessageBox.Show("Shift click logic for individual cells has not yet implemented"); - } - } - else - { - SelectCell(CurrentCell); - } - } - else if (ModifierKeys == Keys.Control && (CurrentCell.Column.Name == "FrameColumn" || CurrentCell.Column.Type == RollColumn.InputType.Text)) - { - SelectCell(CurrentCell, toggle: true); - } - else if (ModifierKeys != Keys.Shift) - { - var hadIndex = _selectedItems.Any(); - _selectedItems.Clear(); - SelectCell(CurrentCell); - } - - Refresh(); - - SelectedIndexChanged?.Invoke(this, new EventArgs()); - } - } - - base.OnMouseDown(e); - - if (AllowRightClickSelecton && e.Button == MouseButtons.Right) - { - if (!IsHoveringOnColumnCell && CurrentCell != null) - { - _currentX = e.X; - _currentY = e.Y; - Cell newCell = CalculatePointedCell(_currentX.Value, _currentY.Value); - newCell.RowIndex += FirstVisibleRow; - CellChanged(newCell); - SelectCell(CurrentCell); - } - } - } - - protected override void OnMouseUp(MouseEventArgs e) - { - if (IsHoveringOnColumnCell) - { - if (_columnDown != null && _columnDownMoved) - { - DoColumnReorder(); - _columnDown = null; - Refresh(); - } - else if (e.Button == MouseButtons.Left) - { - ColumnClickEvent(ColumnAtX(e.X)); - } - else if (e.Button == MouseButtons.Right) - { - ColumnRightClickEvent(ColumnAtX(e.X)); - } - } - - _columnDown = null; - _columnDownMoved = false; - RightButtonHeld = false; - IsPaintDown = false; - base.OnMouseUp(e); - } - - private void IncrementScrollBar(ScrollBar bar, bool increment) - { - int newVal; - if (increment) - { - newVal = bar.Value + bar.SmallChange; - if (newVal > bar.Maximum - bar.LargeChange) - { - newVal = bar.Maximum - bar.LargeChange; - } - } - else - { - newVal = bar.Value - bar.SmallChange; - if (newVal < 0) - { - newVal = 0; - } - } - - _programmaticallyUpdatingScrollBarValues = true; - bar.Value = newVal; - _programmaticallyUpdatingScrollBarValues = false; - } - - protected override void OnMouseWheel(MouseEventArgs e) - { - if (RightButtonHeld) - { - DoRightMouseScroll(this, e); - } - else - { - if (HorizontalOrientation) - { - do - { - IncrementScrollBar(_hBar, e.Delta < 0); - SetLagFramesFirst(); - } - while (_lagFrames[0] != 0 && _hBar.Value != 0 && _hBar.Value != _hBar.Maximum); - } - else - { - do - { - IncrementScrollBar(_vBar, e.Delta < 0); - SetLagFramesFirst(); - } - while (_lagFrames[0] != 0 && _vBar.Value != 0 && _vBar.Value != _vBar.Maximum); - } - - if (_currentX != null) - { - OnMouseMove(new MouseEventArgs(MouseButtons.None, 0, _currentX.Value, _currentY.Value, 0)); - } - - Refresh(); - } - } - - private void DoRightMouseScroll(object sender, MouseEventArgs e) - { - RightMouseScrolled?.Invoke(sender, e); - } - - private void ColumnClickEvent(RollColumn column) - { - ColumnClick?.Invoke(this, new ColumnClickEventArgs(column)); - } - - private void ColumnRightClickEvent(RollColumn column) - { - ColumnRightClick?.Invoke(this, new ColumnClickEventArgs(column)); - } - - protected override void OnKeyDown(KeyEventArgs e) - { - if (!SuspendHotkeys) - { - if (e.Control && !e.Alt && e.Shift && e.KeyCode == Keys.F) // Ctrl+Shift+F - { - HorizontalOrientation ^= true; - } - // Scroll - else if (!e.Control && !e.Alt && !e.Shift && e.KeyCode == Keys.PageUp) // Page Up - { - if (FirstVisibleRow > 0) - { - LastVisibleRow = FirstVisibleRow; - Refresh(); - } - } - else if (!e.Control && !e.Alt && !e.Shift && e.KeyCode == Keys.PageDown) // Page Down - { - var totalRows = LastVisibleRow - FirstVisibleRow; - if (totalRows <= RowCount) - { - var final = LastVisibleRow + totalRows; - if (final > RowCount) - { - final = RowCount; - } - - LastVisibleRow = final; - Refresh(); - } - } - else if (!e.Control && !e.Alt && !e.Shift && e.KeyCode == Keys.Home) // Home - { - FirstVisibleRow = 0; - Refresh(); - } - else if (!e.Control && !e.Alt && !e.Shift && e.KeyCode == Keys.End) // End - { - LastVisibleRow = RowCount; - Refresh(); - } - else if (!e.Control && !e.Shift && !e.Alt && e.KeyCode == Keys.Up) // Up - { - if (FirstVisibleRow > 0) - { - FirstVisibleRow--; - Refresh(); - } - } - else if (!e.Control && !e.Shift && !e.Alt && e.KeyCode == Keys.Down) // Down - { - if (FirstVisibleRow < RowCount - 1) - { - FirstVisibleRow++; - Refresh(); - } - } - // Selection courser - else if (e.Control && !e.Shift && !e.Alt && e.KeyCode == Keys.Up) // Ctrl + Up - { - if (SelectedRows.Any() && LetKeysModifySelection && SelectedRows.First() > 0) - { - foreach (var row in SelectedRows.ToList()) - { - SelectRow(row - 1, true); - SelectRow(row, false); - } - } - } - else if (e.Control && !e.Shift && !e.Alt && e.KeyCode == Keys.Down) // Ctrl + Down - { - if (SelectedRows.Any() && LetKeysModifySelection) - { - foreach (var row in SelectedRows.Reverse().ToList()) - { - SelectRow(row + 1, true); - SelectRow(row, false); - } - } - } - else if (e.Control && !e.Shift && !e.Alt && e.KeyCode == Keys.Left) // Ctrl + Left - { - if (SelectedRows.Any() && LetKeysModifySelection) - { - SelectRow(SelectedRows.Last(), false); - } - } - else if (e.Control && !e.Shift && !e.Alt && e.KeyCode == Keys.Right) // Ctrl + Right - { - if (SelectedRows.Any() && LetKeysModifySelection && SelectedRows.Last() < _rowCount - 1) - { - SelectRow(SelectedRows.Last() + 1, true); - } - } - else if (e.Control && e.Shift && !e.Alt && e.KeyCode == Keys.Left) // Ctrl + Shift + Left - { - if (SelectedRows.Any() && LetKeysModifySelection && SelectedRows.First() > 0) - { - SelectRow(SelectedRows.First() - 1, true); - } - } - else if (e.Control && e.Shift && !e.Alt && e.KeyCode == Keys.Right) // Ctrl + Shift + Right - { - if (SelectedRows.Any() && LetKeysModifySelection) - { - SelectRow(SelectedRows.First(), false); - } - } - else if (e.Control && !e.Shift && !e.Alt && e.KeyCode == Keys.PageUp) // Ctrl + Page Up - { - //jump to above marker with selection courser - if (LetKeysModifySelection) - { - - } - } - else if (e.Control && !e.Shift && !e.Alt && e.KeyCode == Keys.PageDown) // Ctrl + Page Down - { - //jump to below marker with selection courser - if (LetKeysModifySelection) - { - - } - - } - else if (e.Control && !e.Shift && !e.Alt && e.KeyCode == Keys.Home) // Ctrl + Home - { - //move selection courser to frame 0 - if (LetKeysModifySelection) - { - DeselectAll(); - SelectRow(0, true); - } - } - else if (e.Control && !e.Shift && !e.Alt && e.KeyCode == Keys.End) // Ctrl + End - { - //move selection courser to end of movie - if (LetKeysModifySelection) - { - DeselectAll(); - SelectRow(RowCount-1, true); - } - } - - } - - base.OnKeyDown(e); - } - - #endregion - - #region Change Events - - protected override void OnResize(EventArgs e) - { - RecalculateScrollBars(); - base.OnResize(e); - Refresh(); - } - - private void OrientationChanged() - { - RecalculateScrollBars(); - - // TODO scroll to correct positions - ColumnChangedCallback(); - RecalculateScrollBars(); - - Refresh(); - } - - /// - /// Call this function to change the CurrentCell to newCell - /// - private void CellChanged(Cell newCell) - { - LastCell = CurrentCell; - CurrentCell = newCell; - - if (PointedCellChanged != null && - (LastCell.Column != CurrentCell.Column || LastCell.RowIndex != CurrentCell.RowIndex)) - { - PointedCellChanged(this, new CellEventArgs(LastCell, CurrentCell)); - } - - if (CurrentCell?.Column != null && CurrentCell.RowIndex.HasValue) - { - _hoverTimer.Start(); - } - else - { - _hoverTimer.Stop(); - } - } - - private void VerticalBar_ValueChanged(object sender, EventArgs e) - { - if (!_programmaticallyUpdatingScrollBarValues) - { - Refresh(); - } - - if (_horizontalOrientation) - { - ColumnScroll?.Invoke(this, e); - } - else - { - RowScroll?.Invoke(this, e); - } - } - - private void HorizontalBar_ValueChanged(object sender, EventArgs e) - { - if (!_programmaticallyUpdatingScrollBarValues) - { - Refresh(); - } - - if (_horizontalOrientation) - { - RowScroll?.Invoke(this, e); - } - else - { - ColumnScroll?.Invoke(this, e); - } - } - - private void ColumnChangedCallback() - { - RecalculateScrollBars(); - if (_columns.VisibleColumns.Any()) - { - ColumnWidth = _columns.VisibleColumns.Max(c => c.Width.Value) + CellWidthPadding * 4; - } - } - - #endregion - - #region Helpers - - // TODO: Make into an extension method - private static Color Add(Color color, int val) - { - var col = color.ToArgb(); - col += val; - return Color.FromArgb(col); - } - - private void DoColumnReorder() - { - if (_columnDown != CurrentCell.Column) - { - var oldIndex = _columns.IndexOf(_columnDown); - var newIndex = _columns.IndexOf(CurrentCell.Column); - - ColumnReordered?.Invoke(this, new ColumnReorderedEventArgs(oldIndex, newIndex, _columnDown)); - - _columns.Remove(_columnDown); - _columns.Insert(newIndex, _columnDown); - } - } - - // ScrollBar.Maximum = DesiredValue + ScrollBar.LargeChange - 1 - // See MSDN Page for more information on the dumb ScrollBar.Maximum Property - private void RecalculateScrollBars() - { - if (_vBar == null || _hBar == null) return; - - UpdateDrawSize(); - + // Measure width change to ignore extra padding at start/end + var size1 = _renderer.MeasureString("A", _font); + var size2 = _renderer.MeasureString("AA", _font); + _charSize = new Size(size2.Width - size1.Width, size1.Height); // TODO make this a property so changing it updates other values. + } + + UpdateCellSize(); + ColumnWidth = CellWidth; + ColumnHeight = CellHeight + 2; + + _vBar.SmallChange = CellHeight; + _vBar.LargeChange = CellHeight * 20; + + _hBar.SmallChange = CellWidth; + _hBar.LargeChange = 20; + + Controls.Add(_vBar); + Controls.Add(_hBar); + + _vBar.ValueChanged += VerticalBar_ValueChanged; + _hBar.ValueChanged += HorizontalBar_ValueChanged; + + RecalculateScrollBars(); + _columns.ChangedCallback = ColumnChangedCallback; + + _hoverTimer.Interval = 750; + _hoverTimer.Tick += HoverTimerEventProcessor; + _hoverTimer.Stop(); + + _foreColor = ForeColor; + _backColor = BackColor; + } + + private void HoverTimerEventProcessor(object sender, EventArgs e) + { + _hoverTimer.Stop(); + + CellHovered?.Invoke(this, new CellEventArgs(LastCell, CurrentCell)); + } + + protected override void Dispose(bool disposing) + { + _renderer.Dispose(); + base.Dispose(disposing); + } + + protected override void OnDoubleClick(EventArgs e) + { + if (IsHoveringOnColumnEdge) + { + if (HorizontalOrientation) + { + // TODO + } + else + { + var maxLength = CurrentCell.Column.Text?.Length ?? 0; + + for (int i = 0; i < RowCount; i++) + { + string text = ""; + int offSetX = 0, offSetY = 0; + QueryItemText?.Invoke(i, CurrentCell.Column, out text, ref offSetX, ref offSetY); + if (text.Length > maxLength) + { + maxLength = text.Length; + } + } + + var newWidth = (maxLength * _charSize.Width) + (CellWidthPadding * 2); + CurrentCell.Column.Width = newWidth; + _columns.ColumnsChanged(); + Refresh(); + } + + } + + base.OnDoubleClick(e); + } + + #region Properties + + /// + /// Gets or sets the amount of left and right padding on the text inside a cell + /// + [DefaultValue(3)] + [Category("Behavior")] + public int CellWidthPadding { get; set; } + + /// + /// Gets or sets the amount of top and bottom padding on the text inside a cell + /// + [DefaultValue(1)] + [Category("Behavior")] + public int CellHeightPadding { get; set; } + + /// + /// Gets or sets a value indicating whether grid lines are displayed around cells + /// + [Category("Appearance")] + [DefaultValue(true)] + public bool GridLines { get; set; } + + /// + /// Gets or sets a value indicating whether the control is horizontal or vertical + /// + [Category("Behavior")] + public bool HorizontalOrientation + { + get + { + return _horizontalOrientation; + } + set + { + if (_horizontalOrientation != value) + { + int temp = ScrollSpeed; + _horizontalOrientation = value; + OrientationChanged(); + _hBar.SmallChange = CellWidth; + _vBar.SmallChange = CellHeight; + ScrollSpeed = temp; + } + } + } + + /// + /// Gets or sets the scrolling speed + /// + [Category("Behavior")] + public int ScrollSpeed + { + get + { + if (HorizontalOrientation) + { + return _hBar.SmallChange / CellWidth; + } + + return _vBar.SmallChange / CellHeight; + } + + set + { + if (HorizontalOrientation) + { + _hBar.SmallChange = value * CellWidth; + } + else + { + _vBar.SmallChange = value * CellHeight; + } + } + } + + /// + /// Gets or sets the sets the virtual number of rows to be displayed. Does not include the column header row. + /// + [Category("Behavior")] + public int RowCount + { + get + { + return _rowCount; + } + + set + { + _rowCount = value; + RecalculateScrollBars(); + } + } + + /// + /// Gets or sets a value indicating whether columns can be resized + /// + [Category("Behavior")] + public bool AllowColumnResize { get; set; } + + /// + /// Gets or sets a value indicating whether columns can be reordered + /// + [Category("Behavior")] + public bool AllowColumnReorder { get; set; } + + /// + /// Gets or sets a value indicating whether the entire row will always be selected + /// + [Category("Appearance")] + [DefaultValue(false)] + public bool FullRowSelect { get; set; } + + /// + /// Gets or sets a value indicating whether multiple items can to be selected + /// + [Category("Behavior")] + [DefaultValue(true)] + public bool MultiSelect { get; set; } + + /// + /// Gets or sets a value indicating whether the control is in input painting mode + /// + [Category("Behavior")] + [DefaultValue(false)] + public bool InputPaintingMode { get; set; } + + /// + /// All visible columns + /// + [Category("Behavior")] + public IEnumerable VisibleColumns => _columns.VisibleColumns; + + /// + /// Gets or sets how the InputRoll scrolls when calling ScrollToIndex. + /// + [DefaultValue("near")] + [Category("Behavior")] + public string ScrollMethod { get; set; } + + /// + /// Gets or sets a value indicating how the scrolling behavior for the hover event + /// + [Category("Behavior")] + public bool AlwaysScroll { get; set; } + + /// + /// Gets or sets the lowest seek interval to activate the progress bar + /// + [Category("Behavior")] + public int SeekingCutoffInterval { get; set; } + + /// + /// Returns all columns including those that are not visible + /// + [Browsable(false)] + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public RollColumns AllColumns => _columns; + + [DefaultValue(750)] + [Category("Behavior")] + public int HoverInterval + { + get { return _hoverTimer.Interval; } + set { _hoverTimer.Interval = value; } + } + + #endregion + + #region Event Handlers + + /// + /// Fire the event which requests the text for the passed cell + /// + [Category("Virtual")] + public event QueryItemTextHandler QueryItemText; + + /// + /// Fire the event which requests the background color for the passed cell + /// + [Category("Virtual")] + public event QueryItemBkColorHandler QueryItemBkColor; + + [Category("Virtual")] + public event QueryRowBkColorHandler QueryRowBkColor; + + /// + /// Fire the event which requests an icon for a given cell + /// + [Category("Virtual")] + public event QueryItemIconHandler QueryItemIcon; + + /// + /// Fire the QueryFrameLag event which checks if a given frame is a lag frame + /// + [Category("Virtual")] + public event QueryFrameLagHandler QueryFrameLag; + + /// + /// Fires when the mouse moves from one cell to another (including column header cells) + /// + [Category("Mouse")] + public event CellChangeEventHandler PointedCellChanged; + + /// + /// Fires when a cell is hovered on + /// + [Category("Mouse")] + public event HoverEventHandler CellHovered; + + /// + /// Occurs when a column header is clicked + /// + [Category("Action")] + public event ColumnClickEventHandler ColumnClick; + + /// + /// Occurs when a column header is right-clicked + /// + [Category("Action")] + public event ColumnClickEventHandler ColumnRightClick; + + /// + /// Occurs whenever the 'SelectedItems' property for this control changes + /// + [Category("Behavior")] + public event EventHandler SelectedIndexChanged; + + /// + /// Occurs whenever the mouse wheel is scrolled while the right mouse button is held + /// + [Category("Behavior")] + public event RightMouseScrollEventHandler RightMouseScrolled; + + [Category("Property Changed")] + [Description("Occurs when the column header has been reordered")] + public event ColumnReorderedEventHandler ColumnReordered; + + [Category("Action")] + [Description("Occurs when the scroll value of the visible rows change (in vertical orientation this is the vertical scroll bar change, and in horizontal it is the horizontal scroll bar)")] + public event RowScrollEvent RowScroll; + + [Category("Action")] + [Description("Occurs when the scroll value of the columns (in vertical orientation this is the horizontal scroll bar change, and in horizontal it is the vertical scroll bar)")] + public event ColumnScrollEvent ColumnScroll; + + [Category("Action")] + [Description("Occurs when a cell is dragged and then dropped into a new cell, old cell is the cell that was being dragged, new cell is its new destination")] + public event CellDroppedEvent CellDropped; + + /// + /// Retrieve the text for a cell + /// + public delegate void QueryItemTextHandler(int index, RollColumn column, out string text, ref int offsetX, ref int offsetY); + + /// + /// Retrieve the background color for a cell + /// + public delegate void QueryItemBkColorHandler(int index, RollColumn column, ref Color color); + public delegate void QueryRowBkColorHandler(int index, ref Color color); + + /// + /// Retrieve the image for a given cell + /// + public delegate void QueryItemIconHandler(int index, RollColumn column, ref Bitmap icon, ref int offsetX, ref int offsetY); + + /// + /// Check if a given frame is a lag frame + /// + public delegate bool QueryFrameLagHandler(int index, bool hideWasLag); + + public delegate void CellChangeEventHandler(object sender, CellEventArgs e); + + public delegate void HoverEventHandler(object sender, CellEventArgs e); + + public delegate void RightMouseScrollEventHandler(object sender, MouseEventArgs e); + + public delegate void ColumnClickEventHandler(object sender, ColumnClickEventArgs e); + + public delegate void ColumnReorderedEventHandler(object sender, ColumnReorderedEventArgs e); + + public delegate void RowScrollEvent(object sender, EventArgs e); + + public delegate void ColumnScrollEvent(object sender, EventArgs e); + + public delegate void CellDroppedEvent(object sender, CellEventArgs e); + + public class CellEventArgs + { + public CellEventArgs(Cell oldCell, Cell newCell) + { + OldCell = oldCell; + NewCell = newCell; + } + + public Cell OldCell { get; } + public Cell NewCell { get; } + } + + public class ColumnClickEventArgs + { + public ColumnClickEventArgs(RollColumn column) + { + Column = column; + } + + public RollColumn Column { get; } + } + + public class ColumnReorderedEventArgs + { + public ColumnReorderedEventArgs(int oldDisplayIndex, int newDisplayIndex, RollColumn column) + { + Column = column; + OldDisplayIndex = oldDisplayIndex; + NewDisplayIndex = newDisplayIndex; + } + + public RollColumn Column { get; } + public int OldDisplayIndex { get; } + public int NewDisplayIndex { get; } + } + + #endregion + + #region Api + + public void SelectRow(int index, bool val) + { + if (_columns.VisibleColumns.Any()) + { + if (val) + { + SelectCell(new Cell + { + RowIndex = index, + Column = _columns[0] + }); + } + else + { + IEnumerable items = _selectedItems.Where(cell => cell.RowIndex == index); + _selectedItems.RemoveWhere(items.Contains); + } + } + } + + public void SelectAll() + { + var oldFullRowVal = FullRowSelect; + FullRowSelect = true; + for (int i = 0; i < RowCount; i++) + { + SelectRow(i, true); + } + + FullRowSelect = oldFullRowVal; + } + + public void DeselectAll() + { + _selectedItems.Clear(); + } + + public void TruncateSelection(int index) + { + _selectedItems.RemoveWhere(cell => cell.RowIndex > index); + } + + [Browsable(false)] + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public bool IsPointingAtColumnHeader => IsHoveringOnColumnCell; + + [Browsable(false)] + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public int? FirstSelectedIndex + { + get + { + if (AnyRowsSelected) + { + return SelectedRows.Min(); + } + + return null; + } + } + + [Browsable(false)] + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public int? LastSelectedIndex + { + get + { + if (AnyRowsSelected) + { + return SelectedRows.Max(); + } + + return null; + } + } + + /// + /// Gets or sets the current Cell that the mouse was in. + /// + [Browsable(false)] + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public Cell CurrentCell { get; set; } + + [Browsable(false)] + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public bool CurrentCellIsDataCell => CurrentCell?.RowIndex != null && CurrentCell.Column != null; + + /// + /// Gets or sets the previous Cell that the mouse was in. + /// + [Browsable(false)] + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public Cell LastCell { get; private set; } + + [Browsable(false)] + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public bool IsPaintDown { get; private set; } + + [Browsable(false)] + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public bool UseCustomBackground { get; set; } + + [Browsable(false)] + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public int DrawHeight { get; private set; } + + [Browsable(false)] + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public int DrawWidth { get; private set; } + + /// + /// Gets or sets the width of data cells when in Horizontal orientation. + /// + [Browsable(false)] + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public int MaxCharactersInHorizontal + { + get + { + return _maxCharactersInHorizontal; + } + + set + { + _maxCharactersInHorizontal = value; + UpdateCellSize(); + } + } + + [Browsable(false)] + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public bool RightButtonHeld { get; private set; } + + public string UserSettingsSerialized() + { + var settings = ConfigService.SaveWithType(Settings); + return settings; + } + + public void LoadSettingsSerialized(string settingsJson) + { + var settings = ConfigService.LoadWithType(settingsJson); + + // TODO: don't silently fail, inform the user somehow + if (settings is InputRollSettings) + { + var rollSettings = settings as InputRollSettings; + _columns = rollSettings.Columns; + _columns.ChangedCallback = ColumnChangedCallback; + HorizontalOrientation = rollSettings.HorizontalOrientation; + LagFramesToHide = rollSettings.LagFramesToHide; + HideWasLagFrames = rollSettings.HideWasLagFrames; + } + } + + private InputRollSettings Settings => new InputRollSettings + { + Columns = _columns, + HorizontalOrientation = HorizontalOrientation, + LagFramesToHide = LagFramesToHide, + HideWasLagFrames = HideWasLagFrames + }; + + public class InputRollSettings + { + public RollColumns Columns { get; set; } + public bool HorizontalOrientation { get; set; } + public int LagFramesToHide { get; set; } + public bool HideWasLagFrames { get; set; } + } + + /// + /// Gets or sets the first visible row index, if scrolling is needed + /// + [Browsable(false)] + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public int FirstVisibleRow + { + get + { + if (HorizontalOrientation) + { + return _hBar.Value / CellWidth; + } + + return _vBar.Value / CellHeight; + } + + set + { + if (HorizontalOrientation) + { + if (NeedsHScrollbar) + { + _programmaticallyUpdatingScrollBarValues = true; + if (value * CellWidth <= _hBar.Maximum) + { + _hBar.Value = value * CellWidth; + } + else + { + _hBar.Value = _hBar.Maximum; + } + + _programmaticallyUpdatingScrollBarValues = false; + } + } + else + { + if (NeedsVScrollbar) + { + _programmaticallyUpdatingScrollBarValues = true; + if (value * CellHeight <= _vBar.Maximum) + { + _vBar.Value = value * CellHeight; + } + else + { + _vBar.Value = _vBar.Maximum; + } + + _programmaticallyUpdatingScrollBarValues = false; + } + } + } + } + + [Browsable(false)] + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + private int LastFullyVisibleRow + { + get + { + int halfRow = 0; + if ((DrawHeight - ColumnHeight - 3) % CellHeight < CellHeight / 2) + { + halfRow = 1; + } + + return FirstVisibleRow + VisibleRows - halfRow + CountLagFramesDisplay(VisibleRows - halfRow); + } + } + + [Browsable(false)] + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public int LastVisibleRow + { + get + { + return FirstVisibleRow + VisibleRows + CountLagFramesDisplay(VisibleRows); + } + + set + { + int halfRow = 0; + if ((DrawHeight - ColumnHeight - 3) % CellHeight < CellHeight / 2) + { + halfRow = 1; + } + + if (LagFramesToHide == 0) + { + FirstVisibleRow = Math.Max(value - (VisibleRows - halfRow), 0); + } + else + { + if (Math.Abs(LastFullyVisibleRow - value) > VisibleRows) // Big jump + { + FirstVisibleRow = Math.Max(value - (ExpectedDisplayRange() - halfRow), 0); + SetLagFramesArray(); + } + + // Small jump, more accurate + int lastVisible = LastFullyVisibleRow; + do + { + if ((lastVisible - value) / (LagFramesToHide + 1) != 0) + { + FirstVisibleRow = Math.Max(FirstVisibleRow - ((lastVisible - value) / (LagFramesToHide + 1)), 0); + } + else + { + FirstVisibleRow -= Math.Sign(lastVisible - value); + } + + SetLagFramesArray(); + lastVisible = LastFullyVisibleRow; + } + while ((lastVisible - value < 0 || lastVisible - value > _lagFrames[VisibleRows - halfRow]) && FirstVisibleRow != 0); + } + } + } + + public bool IsVisible(int index) + { + return (index >= FirstVisibleRow) && (index <= LastFullyVisibleRow); + } + + public bool IsPartiallyVisible(int index) + { + return index >= FirstVisibleRow && index <= LastVisibleRow; + } + + /// + /// Gets the number of rows currently visible including partially visible rows. + /// + [Browsable(false)] + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public int VisibleRows + { + get + { + if (HorizontalOrientation) + { + return (DrawWidth - ColumnWidth) / CellWidth; + } + + return (DrawHeight - ColumnHeight - 3) / CellHeight; // Minus three makes it work + } + } + + /// + /// Gets the first visible column index, if scrolling is needed + /// + [Browsable(false)] + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public int FirstVisibleColumn + { + get + { + var columnList = VisibleColumns.ToList(); + + if (HorizontalOrientation) + { + return Enumerable.Range(0, columnList.Count).First(i => GetHColBottom(i) > _vBar.Value); + } + + return columnList.FindIndex(c => c.Right > _hBar.Value); + } + } + + [Browsable(false)] + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public int LastVisibleColumnIndex + { + get + { + List columnList = VisibleColumns.ToList(); + + if (HorizontalOrientation) + { + int count = columnList.Count; + return Enumerable.Range(0, count).Select(i => count - 1 - i).First(i => GetHColTop(i) <= DrawWidth + _hBar.Value); + } + + return columnList.FindLastIndex(c => c.Left <= DrawWidth + _hBar.Value); + } + } + + private Cell _draggingCell; + + public void DragCurrentCell() + { + _draggingCell = CurrentCell; + } + + public void ReleaseCurrentCell() + { + if (_draggingCell != null) + { + var draggedCell = _draggingCell; + _draggingCell = null; + + if (CurrentCell != draggedCell) + { + CellDropped?.Invoke(this, new CellEventArgs(draggedCell, CurrentCell)); + } + } + } + + /// + /// Scrolls to the given index, according to the scroll settings. + /// + public void ScrollToIndex(int index) + { + if (ScrollMethod == "near") + { + MakeIndexVisible(index); + } + + if (!IsVisible(index) || AlwaysScroll) + { + if (ScrollMethod == "top") + { + FirstVisibleRow = index; + } + else if (ScrollMethod == "bottom") + { + LastVisibleRow = index; + } + else if (ScrollMethod == "center") + { + if (LagFramesToHide == 0) + { + FirstVisibleRow = Math.Max(index - (VisibleRows / 2), 0); + } + else + { + if (Math.Abs(FirstVisibleRow + CountLagFramesDisplay(VisibleRows / 2) - index) > VisibleRows) // Big jump + { + FirstVisibleRow = Math.Max(index - (ExpectedDisplayRange() / 2), 0); + SetLagFramesArray(); + } + + // Small jump, more accurate + int lastVisible = FirstVisibleRow + CountLagFramesDisplay(VisibleRows / 2); + do + { + if ((lastVisible - index) / (LagFramesToHide + 1) != 0) + { + FirstVisibleRow = Math.Max(FirstVisibleRow - ((lastVisible - index) / (LagFramesToHide + 1)), 0); + } + else + { + FirstVisibleRow -= Math.Sign(lastVisible - index); + } + + SetLagFramesArray(); + lastVisible = FirstVisibleRow + CountLagFramesDisplay(VisibleRows / 2); + } + while ((lastVisible - index < 0 || lastVisible - index > _lagFrames[VisibleRows]) && FirstVisibleRow != 0); + } + } + } + } + + /// + /// Scrolls so that the given index is visible, if it isn't already; doesn't use scroll settings. + /// + public void MakeIndexVisible(int index) + { + if (!IsVisible(index)) + { + if (FirstVisibleRow > index) + { + FirstVisibleRow = index; + } + else + { + LastVisibleRow = index; + } + } + } + + [Browsable(false)] + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public IEnumerable SelectedRows + { + get + { + return _selectedItems + .Where(cell => cell.RowIndex.HasValue) + .Select(cell => cell.RowIndex.Value) + .Distinct(); + } + } + + public bool AnyRowsSelected + { + get + { + return _selectedItems.Any(cell => cell.RowIndex.HasValue); + } + } + + public void ClearSelectedRows() + { + _selectedItems.Clear(); + } + + public IEnumerable GenerateContextMenuItems() + { + yield return new ToolStripSeparator(); + + var rotate = new ToolStripMenuItem + { + Name = "RotateMenuItem", + Text = "Rotate", + ShortcutKeyDisplayString = RotateHotkeyStr, + }; + + rotate.Click += (o, ev) => + { + HorizontalOrientation ^= true; + }; + + yield return rotate; + } + + public string RotateHotkeyStr => "Ctrl+Shift+F"; + + #endregion + + #region Mouse and Key Events + + private bool _columnDownMoved; + private int _previousX; // TODO: move me + + protected override void OnMouseMove(MouseEventArgs e) + { + _previousX = _currentX ?? 0; + _currentX = e.X; + _currentY = e.Y; + + if (_columnResizing != null) + { + if (_currentX != _previousX) + { + _columnResizing.Width += _currentX - _previousX; + _columns.ColumnsChanged(); + Refresh(); + } + } + else if (_columnDown != null) + { + _columnDownMoved = true; + } + + Cell newCell = CalculatePointedCell(_currentX.Value, _currentY.Value); + + // SuuperW: Hide lag frames + if (QueryFrameLag != null && newCell.RowIndex.HasValue) + { + newCell.RowIndex += CountLagFramesDisplay(newCell.RowIndex.Value); + } + + newCell.RowIndex += FirstVisibleRow; + if (newCell.RowIndex < 0) + { + newCell.RowIndex = 0; + } + + if (!newCell.Equals(CurrentCell)) + { + CellChanged(newCell); + + if (IsHoveringOnColumnCell || + (WasHoveringOnColumnCell && !IsHoveringOnColumnCell)) + { + Refresh(); + } + else if (_columnDown != null) + { + Refresh(); + } + } + else if (_columnDown != null) // Kind of silly feeling to have this check twice, but the only alternative I can think of has it refreshing twice when pointed column changes with column down, and speed matters + { + Refresh(); + } + + Cursor = IsHoveringOnColumnEdge || _columnResizing != null + ? Cursors.VSplit + : Cursors.Default; + + base.OnMouseMove(e); + } + + protected override void OnMouseEnter(EventArgs e) + { + CurrentCell = new Cell + { + Column = null, + RowIndex = null + }; + + base.OnMouseEnter(e); + } + + protected override void OnMouseLeave(EventArgs e) + { + _currentX = null; + _currentY = null; + CurrentCell = null; + IsPaintDown = false; + _columnResizing = null; + _hoverTimer.Stop(); + Refresh(); + base.OnMouseLeave(e); + } + + // TODO add query callback of whether to select the cell or not + protected override void OnMouseDown(MouseEventArgs e) + { + if (!GlobalWin.MainForm.EmulatorPaused && _currentX.HasValue) + { + // TODO: this is copy pasta from OnMouseMove() + Cell newCell = CalculatePointedCell(_currentX.Value, _currentY.Value); + if (QueryFrameLag != null && newCell.RowIndex.HasValue) + { + newCell.RowIndex += CountLagFramesDisplay(newCell.RowIndex.Value); + } + + newCell.RowIndex += FirstVisibleRow; + if (newCell.RowIndex < 0) + { + newCell.RowIndex = 0; + } + + if (!newCell.Equals(CurrentCell)) + { + CellChanged(newCell); + + if (IsHoveringOnColumnCell || + (WasHoveringOnColumnCell && !IsHoveringOnColumnCell)) + { + Refresh(); + } + else if (_columnDown != null) + { + Refresh(); + } + } + else if (_columnDown != null) + { + Refresh(); + } + } + + if (e.Button == MouseButtons.Left) + { + if (IsHoveringOnColumnEdge) + { + _columnResizing = CurrentCell.Column; + } + if (IsHoveringOnColumnCell) + { + _columnDown = CurrentCell.Column; + } + else if (InputPaintingMode) + { + IsPaintDown = true; + } + } + + if (e.Button == MouseButtons.Right) + { + if (!IsHoveringOnColumnCell) + { + RightButtonHeld = true; + } + } + + if (e.Button == MouseButtons.Left) + { + if (IsHoveringOnDataCell) + { + if (ModifierKeys == Keys.Alt) + { + // do marker drag here + } + else if (ModifierKeys == Keys.Shift && CurrentCell.Column.Type == ColumnType.Text) + { + if (_selectedItems.Any()) + { + if (FullRowSelect) + { + var selected = _selectedItems.Any(c => c.RowIndex.HasValue && CurrentCell.RowIndex.HasValue && c.RowIndex == CurrentCell.RowIndex); + + if (!selected) + { + var rowIndices = _selectedItems + .Where(c => c.RowIndex.HasValue) + .Select(c => c.RowIndex ?? -1) + .Where(c => c >= 0) // Hack to avoid possible Nullable exceptions + .Distinct() + .ToList(); + + var firstIndex = rowIndices.Min(); + var lastIndex = rowIndices.Max(); + + if (CurrentCell.RowIndex.Value < firstIndex) + { + for (int i = CurrentCell.RowIndex.Value; i < firstIndex; i++) + { + SelectCell(new Cell + { + RowIndex = i, + Column = CurrentCell.Column + }); + } + } + else if (CurrentCell.RowIndex.Value > lastIndex) + { + for (int i = lastIndex + 1; i <= CurrentCell.RowIndex.Value; i++) + { + SelectCell(new Cell + { + RowIndex = i, + Column = CurrentCell.Column + }); + } + } + else // Somewhere in between, a scenario that can happen with ctrl-clicking, find the previous and highlight from there + { + var nearest = rowIndices + .Where(x => x < CurrentCell.RowIndex.Value) + .Max(); + + for (int i = nearest + 1; i <= CurrentCell.RowIndex.Value; i++) + { + SelectCell(new Cell + { + RowIndex = i, + Column = CurrentCell.Column + }); + } + } + } + } + else + { + MessageBox.Show("Shift click logic for individual cells has not yet implemented"); + } + } + else + { + SelectCell(CurrentCell); + } + } + else if (ModifierKeys == Keys.Control && CurrentCell.Column.Type == ColumnType.Text) + { + SelectCell(CurrentCell, toggle: true); + } + else if (ModifierKeys != Keys.Shift) + { + _selectedItems.Clear(); + SelectCell(CurrentCell); + } + + Refresh(); + + SelectedIndexChanged?.Invoke(this, new EventArgs()); + } + } + + base.OnMouseDown(e); + + if (AllowRightClickSelection && e.Button == MouseButtons.Right) + { + if (!IsHoveringOnColumnCell && CurrentCell != null) + { + _currentX = e.X; + _currentY = e.Y; + Cell newCell = CalculatePointedCell(_currentX.Value, _currentY.Value); + newCell.RowIndex += FirstVisibleRow; + CellChanged(newCell); + SelectCell(CurrentCell); + } + } + } + + protected override void OnMouseUp(MouseEventArgs e) + { + if (_columnResizing == null && IsHoveringOnColumnCell) + { + if (_columnDown != null && _columnDownMoved) + { + DoColumnReorder(); + _columnDown = null; + Refresh(); + } + else if (e.Button == MouseButtons.Left) + { + ColumnClickEvent(ColumnAtPixel(e.X)); + } + else if (e.Button == MouseButtons.Right) + { + ColumnRightClickEvent(ColumnAtPixel(e.X)); + } + } + + _columnResizing = null; + _columnDown = null; + _columnDownMoved = false; + RightButtonHeld = false; + IsPaintDown = false; + base.OnMouseUp(e); + } + + private void IncrementScrollBar(ScrollBar bar, bool increment) + { + int newVal; + if (increment) + { + newVal = bar.Value + bar.SmallChange; + if (newVal > bar.Maximum - bar.LargeChange) + { + newVal = bar.Maximum - bar.LargeChange; + } + } + else + { + newVal = bar.Value - bar.SmallChange; + if (newVal < 0) + { + newVal = 0; + } + } + + _programmaticallyUpdatingScrollBarValues = true; + bar.Value = newVal; + _programmaticallyUpdatingScrollBarValues = false; + } + + protected override void OnMouseWheel(MouseEventArgs e) + { + if (RightButtonHeld) + { + DoRightMouseScroll(this, e); + } + else + { + if (HorizontalOrientation) + { + do + { + IncrementScrollBar(_hBar, e.Delta < 0); + SetLagFramesFirst(); + } + while (_lagFrames[0] != 0 && _hBar.Value != 0 && _hBar.Value != _hBar.Maximum); + } + else + { + do + { + IncrementScrollBar(_vBar, e.Delta < 0); + SetLagFramesFirst(); + } + while (_lagFrames[0] != 0 && _vBar.Value != 0 && _vBar.Value != _vBar.Maximum); + } + + if (_currentX != null) + { + OnMouseMove(new MouseEventArgs(MouseButtons.None, 0, _currentX.Value, _currentY.Value, 0)); + } + + Refresh(); + } + } + + private void DoRightMouseScroll(object sender, MouseEventArgs e) + { + RightMouseScrolled?.Invoke(sender, e); + } + + private void ColumnClickEvent(RollColumn column) + { + ColumnClick?.Invoke(this, new ColumnClickEventArgs(column)); + } + + private void ColumnRightClickEvent(RollColumn column) + { + ColumnRightClick?.Invoke(this, new ColumnClickEventArgs(column)); + } + + protected override void OnKeyDown(KeyEventArgs e) + { + if (!SuspendHotkeys) + { + if (e.Control && !e.Alt && e.Shift && e.KeyCode == Keys.F) // Ctrl+Shift+F + { + HorizontalOrientation ^= true; + } + // Scroll + else if (!e.Control && !e.Alt && !e.Shift && e.KeyCode == Keys.PageUp) // Page Up + { + if (FirstVisibleRow > 0) + { + LastVisibleRow = FirstVisibleRow; + Refresh(); + } + } + else if (!e.Control && !e.Alt && !e.Shift && e.KeyCode == Keys.PageDown) // Page Down + { + var totalRows = LastVisibleRow - FirstVisibleRow; + if (totalRows <= RowCount) + { + var final = LastVisibleRow + totalRows; + if (final > RowCount) + { + final = RowCount; + } + + LastVisibleRow = final; + Refresh(); + } + } + else if (!e.Control && !e.Alt && !e.Shift && e.KeyCode == Keys.Home) // Home + { + FirstVisibleRow = 0; + Refresh(); + } + else if (!e.Control && !e.Alt && !e.Shift && e.KeyCode == Keys.End) // End + { + LastVisibleRow = RowCount; + Refresh(); + } + else if (!e.Control && !e.Shift && !e.Alt && e.KeyCode == Keys.Up) // Up + { + if (FirstVisibleRow > 0) + { + FirstVisibleRow--; + Refresh(); + } + } + else if (!e.Control && !e.Shift && !e.Alt && e.KeyCode == Keys.Down) // Down + { + if (FirstVisibleRow < RowCount - 1) + { + FirstVisibleRow++; + Refresh(); + } + } + // Selection courser + else if (e.Control && !e.Shift && !e.Alt && e.KeyCode == Keys.Up) // Ctrl + Up + { + if (SelectedRows.Any() && LetKeysModifySelection && SelectedRows.First() > 0) + { + foreach (var row in SelectedRows.ToList()) // clones SelectedRows + { + SelectRow(row - 1, true); + SelectRow(row, false); + } + } + } + else if (e.Control && !e.Shift && !e.Alt && e.KeyCode == Keys.Down) // Ctrl + Down + { + if (SelectedRows.Any() && LetKeysModifySelection) + { + foreach (var row in SelectedRows.Reverse()) // clones SelectedRows + { + SelectRow(row + 1, true); + SelectRow(row, false); + } + } + } + else if (e.Control && !e.Shift && !e.Alt && e.KeyCode == Keys.Left) // Ctrl + Left + { + if (SelectedRows.Any() && LetKeysModifySelection) + { + SelectRow(SelectedRows.Last(), false); + } + } + else if (e.Control && !e.Shift && !e.Alt && e.KeyCode == Keys.Right) // Ctrl + Right + { + if (SelectedRows.Any() && LetKeysModifySelection && SelectedRows.Last() < _rowCount - 1) + { + SelectRow(SelectedRows.Last() + 1, true); + } + } + else if (e.Control && e.Shift && !e.Alt && e.KeyCode == Keys.Left) // Ctrl + Shift + Left + { + if (SelectedRows.Any() && LetKeysModifySelection && SelectedRows.First() > 0) + { + SelectRow(SelectedRows.First() - 1, true); + } + } + else if (e.Control && e.Shift && !e.Alt && e.KeyCode == Keys.Right) // Ctrl + Shift + Right + { + if (SelectedRows.Any() && LetKeysModifySelection) + { + SelectRow(SelectedRows.First(), false); + } + } + else if (e.Control && !e.Shift && !e.Alt && e.KeyCode == Keys.PageUp) // Ctrl + Page Up + { + //jump to above marker with selection courser + if (LetKeysModifySelection) + { + + } + } + else if (e.Control && !e.Shift && !e.Alt && e.KeyCode == Keys.PageDown) // Ctrl + Page Down + { + //jump to below marker with selection courser + if (LetKeysModifySelection) + { + + } + + } + else if (e.Control && !e.Shift && !e.Alt && e.KeyCode == Keys.Home) // Ctrl + Home + { + //move selection courser to frame 0 + if (LetKeysModifySelection) + { + DeselectAll(); + SelectRow(0, true); + } + } + else if (e.Control && !e.Shift && !e.Alt && e.KeyCode == Keys.End) // Ctrl + End + { + //move selection courser to end of movie + if (LetKeysModifySelection) + { + DeselectAll(); + SelectRow(RowCount-1, true); + } + } + + } + + base.OnKeyDown(e); + } + + #endregion + + #region Change Events + + protected override void OnResize(EventArgs e) + { + RecalculateScrollBars(); + base.OnResize(e); + Refresh(); + } + + private void OrientationChanged() + { + RecalculateScrollBars(); + + // TODO scroll to correct positions + ColumnChangedCallback(); + RecalculateScrollBars(); + + Refresh(); + } + + /// + /// Call this function to change the CurrentCell to newCell + /// + private void CellChanged(Cell newCell) + { + LastCell = CurrentCell; + CurrentCell = newCell; + + if (PointedCellChanged != null && + (LastCell.Column != CurrentCell.Column || LastCell.RowIndex != CurrentCell.RowIndex)) + { + PointedCellChanged(this, new CellEventArgs(LastCell, CurrentCell)); + } + + if (CurrentCell?.Column != null && CurrentCell.RowIndex.HasValue) + { + _hoverTimer.Start(); + } + else + { + _hoverTimer.Stop(); + } + } + + private void VerticalBar_ValueChanged(object sender, EventArgs e) + { + if (!_programmaticallyUpdatingScrollBarValues) + { + Refresh(); + } + + if (_horizontalOrientation) + { + ColumnScroll?.Invoke(_vBar, e); + } + else + { + RowScroll?.Invoke(_vBar, e); + } + } + + private void HorizontalBar_ValueChanged(object sender, EventArgs e) + { + if (!_programmaticallyUpdatingScrollBarValues) + { + Refresh(); + } + + if (_horizontalOrientation) + { + RowScroll?.Invoke(_hBar, e); + } + else + { + ColumnScroll?.Invoke(_vBar, e); + } + } + + private void ColumnChangedCallback() + { + RecalculateScrollBars(); + if (_columns.VisibleColumns.Any()) + { + ColumnWidth = _columns.VisibleColumns.Max(c => c.Width.Value) + CellWidthPadding * 4; + } + } + + #endregion + + #region Helpers + + private void DoColumnReorder() + { + if (_columnDown != CurrentCell.Column) + { + var oldIndex = _columns.IndexOf(_columnDown); + var newIndex = _columns.IndexOf(CurrentCell.Column); + + ColumnReordered?.Invoke(this, new ColumnReorderedEventArgs(oldIndex, newIndex, _columnDown)); + + _columns.Remove(_columnDown); + _columns.Insert(newIndex, _columnDown); + } + } + + // ScrollBar.Maximum = DesiredValue + ScrollBar.LargeChange - 1 + // See MSDN Page for more information on the dumb ScrollBar.Maximum Property + private void RecalculateScrollBars() + { + UpdateDrawSize(); + var columns = _columns.VisibleColumns.ToList(); - - if (CellHeight == 0) CellHeight++; - if (HorizontalOrientation) + int iLastColumn = columns.Count - 1; + + if (HorizontalOrientation) + { + NeedsVScrollbar = GetHColBottom(iLastColumn) > DrawHeight; + NeedsHScrollbar = RowCount > 1; + } + else + { + NeedsVScrollbar = ColumnHeight + (RowCount * RowHeight) > Height; + NeedsHScrollbar = TotalColWidth.HasValue && TotalColWidth.Value - DrawWidth + 1 > 0; + } + + UpdateDrawSize(); + if (VisibleRows > 0) + { + if (HorizontalOrientation) + { + _hBar.Maximum = Math.Max((VisibleRows - 1) * CellWidth, _hBar.Maximum); + _hBar.LargeChange = (VisibleRows - 1) * CellWidth; + _vBar.LargeChange = Math.Max(0, DrawHeight / 2); + } + else + { + _vBar.Maximum = Math.Max((VisibleRows - 1) * CellHeight, _vBar.Maximum); // ScrollBar.Maximum is dumb + _vBar.LargeChange = (VisibleRows - 1) * CellHeight; + // DrawWidth can be negative if the TAStudio window is small enough + // Clamp LargeChange to 0 here to prevent exceptions + _hBar.LargeChange = Math.Max(0, DrawWidth / 2); + } + } + + // Update VBar + if (NeedsVScrollbar) + { + if (HorizontalOrientation) + { + _vBar.Maximum = GetHColBottom(iLastColumn) - DrawHeight + _vBar.LargeChange; + if (_vBar.Maximum < 0) + { + _vBar.Maximum = 0; + } + } + else + { + _vBar.Maximum = RowsToPixels(RowCount + 1) - (CellHeight * 3) + _vBar.LargeChange - 1; + if (_vBar.Maximum < 0) + { + _vBar.Maximum = 0; + } + } + + _vBar.Location = new Point(Width - _vBar.Width, 0); + _vBar.Height = Height; + _vBar.Visible = true; + } + else + { + _vBar.Visible = false; + _vBar.Value = 0; + } + + // Update HBar + if (NeedsHScrollbar) + { + if (HorizontalOrientation) + { + _hBar.Maximum = RowsToPixels(RowCount + 1) - (CellHeight * 3) + _hBar.LargeChange - 1; + } + else + { + _hBar.Maximum = TotalColWidth.Value - DrawWidth + _hBar.LargeChange; + } + + _hBar.Location = new Point(0, Height - _hBar.Height); + _hBar.Width = Width - (NeedsVScrollbar ? (_vBar.Width + 1) : 0); + _hBar.Visible = true; + } + else + { + _hBar.Visible = false; + _hBar.Value = 0; + } + } + + private void UpdateDrawSize() + { + if (NeedsVScrollbar) + { + DrawWidth = Width - _vBar.Width; + } + else + { + DrawWidth = Width; + } + if (NeedsHScrollbar) + { + DrawHeight = Height - _hBar.Height; + } + else + { + DrawHeight = Height; + } + } + + /// + /// If FullRowSelect is enabled, selects all cells in the row that contains the given cell. Otherwise only given cell is added. + /// + /// The cell to select. + /// Specifies whether or not to toggle the current state, rather than force the value to true + private void SelectCell(Cell cell, bool toggle = false) + { + if (cell.RowIndex.HasValue && cell.RowIndex < RowCount) + { + if (!MultiSelect) + { + _selectedItems.Clear(); + } + + if (FullRowSelect) + { + if (toggle && _selectedItems.Any(x => x.RowIndex.HasValue && x.RowIndex == cell.RowIndex)) + { + _selectedItems.RemoveWhere(x => x.RowIndex.HasValue && x.RowIndex == cell.RowIndex); + } + else + { + foreach (var column in _columns) + { + _selectedItems.Add(new Cell + { + RowIndex = cell.RowIndex, + Column = column + }); + } + } + } + else + { + if (toggle && _selectedItems.Any(x => x.RowIndex.HasValue && x.RowIndex == cell.RowIndex)) + { + var item = _selectedItems + .FirstOrDefault(x => x.Equals(cell)); + + if (item != null) + { + _selectedItems.Remove(item); + } + } + else + { + _selectedItems.Add(CurrentCell); + } + } + } + } + + private bool IsHoveringOnColumnCell => CurrentCell?.Column != null && !CurrentCell.RowIndex.HasValue; + + private bool IsHoveringOnColumnEdge => AllowColumnResize && IsHoveringOnColumnCell && IsPointingOnCellEdge(_currentX); + + private bool IsHoveringOnDataCell => CurrentCell?.Column != null && CurrentCell.RowIndex.HasValue; + + private bool WasHoveringOnColumnCell => LastCell?.Column != null && !LastCell.RowIndex.HasValue; + + private bool WasHoveringOnDataCell => LastCell?.Column != null && LastCell.RowIndex.HasValue; + + private bool IsPointingOnCellEdge(int? x) + { + if (x.HasValue) + { + if (HorizontalOrientation) + { + return false; // TODO: support column resize in horizontal orientation + } + + foreach (RollColumn column in _columns.VisibleColumns) + { + if (column.Left - _hBar.Value + (column.Width - column.Width / 6) <= x.Value && column.Right - _hBar.Value >= x.Value) + { + return true; + } + } + } + + return false; + } + + /// + /// Finds the specific cell that contains the (x, y) coordinate. + /// + /// The row number that it returns will be between 0 and VisibleRows, NOT the absolute row number. + /// X coordinate point. + /// Y coordinate point. + /// The cell with row number and RollColumn reference, both of which can be null. + private Cell CalculatePointedCell(int x, int y) + { + var newCell = new Cell(); + var columns = _columns.VisibleColumns.ToList(); + + // If pointing to a column header + if (columns.Any()) + { + if (HorizontalOrientation) + { + newCell.RowIndex = PixelsToRows(x); + newCell.Column = ColumnAtPixel(y); + } + else + { + newCell.RowIndex = PixelsToRows(y); + newCell.Column = ColumnAtPixel(x); + } + } + + if (!(IsPaintDown || RightButtonHeld) && newCell.RowIndex <= -1) // -2 if we're entering from the top + { + newCell.RowIndex = null; + } + + return newCell; + } + + // A boolean that indicates if the InputRoll is too large vertically and requires a vertical scrollbar. + private bool NeedsVScrollbar { get; set; } + + // A boolean that indicates if the InputRoll is too large horizontally and requires a horizontal scrollbar. + private bool NeedsHScrollbar { get; set; } + + /// + /// Gets the total width of all the columns by using the last column's Right property. + /// + /// A nullable Int representing total width. + private int? TotalColWidth + { + get + { + if (_columns.VisibleColumns.Any()) + { + return _columns.VisibleColumns.Last().Right; + } + + return null; + } + } + + /// + /// Returns the RollColumn object at the specified visible pixel coordinate. + /// + /// The pixel coordinate. + /// RollColumn object that contains the pixel coordinate or null if none exists. + private RollColumn ColumnAtPixel(int pixel) + { + if (_horizontalOrientation) + { + foreach (var item in _columns.VisibleColumns.Select((n, i) => new { Column = n, Index = i })) + { + if (GetHColTop(item.Index) - _vBar.Value <= pixel && GetHColBottom(item.Index) - _vBar.Value >= pixel) + { + return item.Column; + } + } + } + else { - NeedsVScrollbar = columns.Count > DrawHeight / CellHeight; - NeedsHScrollbar = RowCount > 1; - } - else - { - NeedsVScrollbar = RowCount > 1; - NeedsHScrollbar = TotalColWidth.HasValue && TotalColWidth.Value - DrawWidth + 1 > 0; - } - - UpdateDrawSize(); - if (VisibleRows > 0) - { - if (HorizontalOrientation) + foreach (RollColumn column in _columns.VisibleColumns) { - _vBar.LargeChange = DrawHeight / 2; - _hBar.Maximum = Math.Max((VisibleRows - 1) * CellHeight, _hBar.Maximum); - _hBar.LargeChange = (VisibleRows - 1) * CellHeight; - } - else - { - _vBar.Maximum = Math.Max((VisibleRows - 1) * CellHeight, _vBar.Maximum); // ScrollBar.Maximum is dumb - _vBar.LargeChange = (VisibleRows - 1) * CellHeight; - // DrawWidth can be negative if the TAStudio window is small enough - // Clamp LargeChange to 0 here to prevent exceptions - _hBar.LargeChange = Math.Max(0, DrawWidth / 2); - } - } - - // Update VBar - if (NeedsVScrollbar) - { - if (HorizontalOrientation) - { - _vBar.Maximum = ((columns.Count() * CellHeight) - DrawHeight) + _vBar.LargeChange; - } - else - { - _vBar.Maximum = RowsToPixels(RowCount + 1) - (CellHeight * 3) + _vBar.LargeChange - 1; - } - - _vBar.Location = new Point(Width - _vBar.Width, 0); - _vBar.Height = Height; - _vBar.Visible = true; - } - else - { - _vBar.Visible = false; - _vBar.Value = 0; - } - - // Update HBar - if (NeedsHScrollbar) - { - if (HorizontalOrientation) - { - _hBar.Maximum = RowsToPixels(RowCount + 1) - (CellHeight * 3) + _hBar.LargeChange - 1; - } - else - { - _hBar.Maximum = TotalColWidth.Value - DrawWidth + _hBar.LargeChange; - } - - _hBar.Location = new Point(0, Height - _hBar.Height); - _hBar.Width = Width - (NeedsVScrollbar ? (_vBar.Width + 1) : 0); - _hBar.Visible = true; - } - else - { - _hBar.Visible = false; - _hBar.Value = 0; - } - } - - private void UpdateDrawSize() - { - if (NeedsVScrollbar) - { - DrawWidth = Width - _vBar.Width; - } - else - { - DrawWidth = Width; - } - if (NeedsHScrollbar) - { - DrawHeight = Height - _hBar.Height; - } - else - { - DrawHeight = Height; - } - } - - /// - /// If FullRowSelect is enabled, selects all cells in the row that contains the given cell. Otherwise only given cell is added. - /// - /// The cell to select. - private void SelectCell(Cell cell, bool toggle = false) - { - if (cell.RowIndex.HasValue && cell.RowIndex < RowCount) - { - if (!MultiSelect) - { - _selectedItems.Clear(); - } - - if (FullRowSelect) - { - if (toggle && _selectedItems.Any(x => x.RowIndex.HasValue && x.RowIndex == cell.RowIndex)) + if (column.Left.Value - _hBar.Value <= pixel && column.Right.Value - _hBar.Value >= pixel) { - var items = _selectedItems - .Where(x => x.RowIndex.HasValue && x.RowIndex == cell.RowIndex) - .ToList(); - - foreach (var item in items) - { - _selectedItems.Remove(item); - } + return column; } - else - { - foreach (var column in _columns) - { - _selectedItems.Add(new Cell - { - RowIndex = cell.RowIndex, - Column = column - }); - } - } - } - else - { - if (toggle && _selectedItems.Any(x => x.RowIndex.HasValue && x.RowIndex == cell.RowIndex)) - { - var item = _selectedItems - .FirstOrDefault(x => x.Equals(cell)); + } + } + return null; + } + + /// + /// Converts a row number to a horizontal or vertical coordinate. + /// + /// A vertical coordinate if Vertical Oriented, otherwise a horizontal coordinate. + private int RowsToPixels(int index) + { + if (_horizontalOrientation) + { + return (index * CellWidth) + ColumnWidth; + } + + return (index * CellHeight) + ColumnHeight; + } + + /// + /// Converts a horizontal or vertical coordinate to a row number. + /// + /// A vertical coordinate if Vertical Oriented, otherwise a horizontal coordinate. + /// A row number between 0 and VisibleRows if it is a data row, otherwise a negative number if above all Datarows. + private int PixelsToRows(int pixels) + { + // Using Math.Floor and float because integer division rounds towards 0 but we want to round down. + if (_horizontalOrientation) + { + return (int)Math.Floor((float)(pixels - ColumnWidth) / CellWidth); + } + return (int)Math.Floor((float)(pixels - ColumnHeight) / CellHeight); + } + + private int GetHColHeight(int index) => + _horizontalColumnHeights != null && index < _horizontalColumnHeights.Length ? _horizontalColumnHeights[index] : CellHeight; + + private int GetHColTop(int index) => + _horizontalColumnTops != null && index < _horizontalColumnTops.Length ? _horizontalColumnTops[index] : (index * CellHeight); - if (item != null) - { - _selectedItems.Remove(item); - } - } - else - { - _selectedItems.Add(CurrentCell); - } - } - } - } - - private bool IsHoveringOnColumnCell => CurrentCell?.Column != null && !CurrentCell.RowIndex.HasValue; - - private bool IsHoveringOnDataCell => CurrentCell?.Column != null && CurrentCell.RowIndex.HasValue; - - private bool WasHoveringOnColumnCell => LastCell?.Column != null && !LastCell.RowIndex.HasValue; - - private bool WasHoveringOnDataCell => LastCell?.Column != null && LastCell.RowIndex.HasValue; - - /// - /// Finds the specific cell that contains the (x, y) coordinate. - /// - /// The row number that it returns will be between 0 and VisibleRows, NOT the absolute row number. - /// X coordinate point. - /// Y coordinate point. - /// The cell with row number and RollColumn reference, both of which can be null. - private Cell CalculatePointedCell(int x, int y) - { - var newCell = new Cell(); - var columns = _columns.VisibleColumns.ToList(); - - // If pointing to a column header - if (columns.Any()) - { - if (HorizontalOrientation) - { - newCell.RowIndex = PixelsToRows(x); - - if (CellHeight == 0) CellHeight++; - - int colIndex = (y + _vBar.Value) / CellHeight; - if (colIndex >= 0 && colIndex < columns.Count) - { - newCell.Column = columns[colIndex]; - } - } - else - { - newCell.RowIndex = PixelsToRows(y); - newCell.Column = ColumnAtX(x); - } - } - - if (!(IsPaintDown || RightButtonHeld) && newCell.RowIndex <= -1) // -2 if we're entering from the top - { - newCell.RowIndex = null; - } - - return newCell; - } - - // A boolean that indicates if the InputRoll is too large vertically and requires a vertical scrollbar. - private bool NeedsVScrollbar { get; set; } - - // A boolean that indicates if the InputRoll is too large horizontally and requires a horizontal scrollbar. - private bool NeedsHScrollbar { get; set; } - - /// - /// Updates the width of the supplied column. - /// Call when changing the ColumnCell text, CellPadding, or text font. - /// - /// The RollColumn object to update. - /// The new width of the RollColumn object. - private int UpdateWidth(RollColumn col) - { - switch (Renderer) - { - case RollRenderer.GDI: - col.Width = (col.Text.Length * _charSize.Width) + (CellWidthPadding * 4); - break; - case RollRenderer.GDIPlus: - col.Width = (int)Math.Round((col.Text.Length * _charSizeF.Width) + (CellWidthPadding * 4)); - break; - } - return col.Width.Value; - } - - /// - /// Gets the total width of all the columns by using the last column's Right property. - /// - /// A nullable Int representing total width. - private int? TotalColWidth - { - get - { - if (_columns.VisibleColumns.Any()) - { - return _columns.VisibleColumns.Last().Right; - } - - return null; - } - } - - /// - /// Returns the RollColumn object at the specified visible x coordinate. Coordinate should be between 0 and Width of the InputRoll Control. - /// - /// The x coordinate. - /// RollColumn object that contains the x coordinate or null if none exists. - private RollColumn ColumnAtX(int x) - { - foreach (RollColumn column in _columns.VisibleColumns) - { - if (column.Left.Value - _hBar.Value <= x && column.Right.Value - _hBar.Value >= x) - { - return column; - } - } - - return null; - } - - /// - /// Converts a row number to a horizontal or vertical coordinate. - /// - /// A vertical coordinate if Vertical Oriented, otherwise a horizontal coordinate. - private int RowsToPixels(int index) - { - if (_horizontalOrientation) - { - return (index * CellWidth) + ColumnWidth; - } - - return (index * CellHeight) + ColumnHeight; - } - - /// - /// Converts a horizontal or vertical coordinate to a row number. - /// - /// A vertical coordinate if Vertical Oriented, otherwise a horizontal coordinate. - /// A row number between 0 and VisibleRows if it is a Datarow, otherwise a negative number if above all Datarows. - private int PixelsToRows(int pixels) - { - // Using Math.Floor and float because integer division rounds towards 0 but we want to round down. - if (_horizontalOrientation) - { - return (int)Math.Floor((float)(pixels - ColumnWidth) / CellWidth); - } - if (CellHeight == 0) CellHeight++; - return (int)Math.Floor((float)(pixels - ColumnHeight) / CellHeight); - } + private int GetHColBottom(int index) => + GetHColTop(index) + GetHColHeight(index); // The width of the largest column cell in Horizontal Orientation - - private int ColumnWidth { get; set; } - - // The height of a column cell in Vertical Orientation. - private int ColumnHeight { get; set; } - - // The width of a cell in Horizontal Orientation. Only can be changed by changing the Font or CellPadding. - private int CellWidth { get; set; } - - [Browsable(false)] - public int RowHeight => CellHeight; - - /// - /// Gets or sets a value indicating the height of a cell in Vertical Orientation. Only can be changed by changing the Font or CellPadding. - /// - private int CellHeight { get; set; } - - /// - /// Call when _charSize, MaxCharactersInHorizontal, or CellPadding is changed. - /// - private void UpdateCellSize() - { - switch (Renderer) - { - case RollRenderer.GDI: - CellHeight = _charSize.Height + (CellHeightPadding * 2); - CellWidth = (_charSize.Width * MaxCharactersInHorizontal) + (CellWidthPadding * 4); // Double the padding for horizontal because it looks better - break; - case RollRenderer.GDIPlus: - CellHeight = (int)Math.Round(_charSizeF.Height + (CellHeightPadding * 2) + 1); // needed for GDI+ to match GDI cell height - CellWidth = (int)Math.Round((_charSizeF.Width * MaxCharactersInHorizontal) + (CellWidthPadding * 4)); // Double the padding for horizontal because it looks better - break; - } - } - - // SuuperW: Count lag frames between FirstDisplayed and given display position - private int CountLagFramesDisplay(int relativeIndex) - { - if (QueryFrameLag != null && LagFramesToHide != 0) - { - int count = 0; - for (int i = 0; i <= relativeIndex; i++) - { - count += _lagFrames[i]; - } - - return count; - } - - return 0; - } - - // Count lag frames between FirstDisplayed and given relative frame index - private int CountLagFramesAbsolute(int relativeIndex) - { - if (QueryFrameLag != null && LagFramesToHide != 0) - { - int count = 0; - for (int i = 0; i + count <= relativeIndex; i++) - { - count += _lagFrames[i]; - } - - return count; - } - - return 0; - } - - private void SetLagFramesArray() - { - if (QueryFrameLag != null && LagFramesToHide != 0) - { - bool showNext = false; - - // First one needs to check BACKWARDS for lag frame count. - SetLagFramesFirst(); - int f = _lagFrames[0]; - if (QueryFrameLag(FirstVisibleRow + f, HideWasLagFrames)) - { - showNext = true; - } - - for (int i = 1; i <= VisibleRows; i++) - { - _lagFrames[i] = 0; - if (!showNext) - { - for (; _lagFrames[i] < LagFramesToHide; _lagFrames[i]++) - { - if (!QueryFrameLag(FirstVisibleRow + i + f, HideWasLagFrames)) - { - break; - } - - f++; - } - } - else - { - if (!QueryFrameLag(FirstVisibleRow + i + f, HideWasLagFrames)) - { - showNext = false; - } - } - - if (_lagFrames[i] == LagFramesToHide && QueryFrameLag(FirstVisibleRow + i + f, HideWasLagFrames)) - { - showNext = true; - } - } - } - else - { - for (int i = 0; i <= VisibleRows; i++) - { - _lagFrames[i] = 0; - } - } - } - private void SetLagFramesFirst() - { - if (QueryFrameLag != null && LagFramesToHide != 0) - { - // Count how many lag frames are above displayed area. - int count = 0; - do - { - count++; - } - while (QueryFrameLag(FirstVisibleRow - count, HideWasLagFrames) && count <= LagFramesToHide); - count--; - - // Count forward - int fCount = -1; - do - { - fCount++; - } - while (QueryFrameLag(FirstVisibleRow + fCount, HideWasLagFrames) && count + fCount < LagFramesToHide); - _lagFrames[0] = (byte)fCount; - } - else - { - _lagFrames[0] = 0; - } - } - - // Number of displayed + hidden frames, if fps is as expected - private int ExpectedDisplayRange() - { - return (VisibleRows + 1) * LagFramesToHide; - } - - #endregion - - #region Classes - - public class RollColumns : List - { - public RollColumn this[string name] - { - get - { - return this.SingleOrDefault(column => column.Name == name); - } - } - - public IEnumerable VisibleColumns - { - get - { - return this.Where(c => c.Visible); - } - } - - public Action ChangedCallback { get; set; } - - private void DoChangeCallback() - { - // no check will make it crash for user too, not sure which way of alarm we prefer. no alarm at all will cause all sorts of subtle bugs - if (ChangedCallback == null) - { - System.Diagnostics.Debug.Fail($"{nameof(ColumnChangedCallback)} has died!"); - } - else - { - ChangedCallback(); - } - } - - // TODO: this shouldn't be exposed. But in order to not expose it, each RollColumn must have a change callback, and all property changes must call it, it is quicker and easier to just call this when needed - public void ColumnsChanged() - { - int pos = 0; - - var columns = VisibleColumns.ToList(); - - for (int i = 0; i < columns.Count; i++) - { - columns[i].Left = pos; - pos += columns[i].Width.Value; - columns[i].Right = pos; - } - - DoChangeCallback(); - } - - public new void Add(RollColumn column) - { - if (this.Any(c => c.Name == column.Name)) - { - // The designer sucks, doing nothing for now - return; - //throw new InvalidOperationException("A column with this name already exists."); - } - - base.Add(column); - ColumnsChanged(); - } - - public new void AddRange(IEnumerable collection) - { - foreach (var column in collection) - { - if (this.Any(c => c.Name == column.Name)) - { - // The designer sucks, doing nothing for now - return; - - throw new InvalidOperationException("A column with this name already exists."); - } - } - - base.AddRange(collection); - ColumnsChanged(); - } - - public new void Insert(int index, RollColumn column) - { - if (this.Any(c => c.Name == column.Name)) - { - throw new InvalidOperationException("A column with this name already exists."); - } - - base.Insert(index, column); - ColumnsChanged(); - } - - public new void InsertRange(int index, IEnumerable collection) - { - foreach (var column in collection) - { - if (this.Any(c => c.Name == column.Name)) - { - throw new InvalidOperationException("A column with this name already exists."); - } - } - - base.InsertRange(index, collection); - ColumnsChanged(); - } - - public new bool Remove(RollColumn column) - { - var result = base.Remove(column); - ColumnsChanged(); - return result; - } - - public new int RemoveAll(Predicate match) - { - var result = base.RemoveAll(match); - ColumnsChanged(); - return result; - } - - public new void RemoveAt(int index) - { - base.RemoveAt(index); - ColumnsChanged(); - } - - public new void RemoveRange(int index, int count) - { - base.RemoveRange(index, count); - ColumnsChanged(); - } - - public new void Clear() - { - base.Clear(); - ColumnsChanged(); - } - - public IEnumerable Groups - { - get - { - return this - .Select(x => x.Group) - .Distinct(); - } - } - } - - public class RollColumn - { - public enum InputType { Boolean, Float, Text, Image } - - public string Group { get; set; } - public int? Width { get; set; } - public int? Left { get; set; } - public int? Right { get; set; } - public string Name { get; set; } - public string Text { get; set; } - public InputType Type { get; set; } - public bool Visible { get; set; } - - /// - /// Column will be drawn with an emphasized look, if true - /// - private bool _emphasis; - public bool Emphasis - { - get { return _emphasis; } - set { _emphasis = value; } - } - - public RollColumn() - { - Visible = true; - } - } - - /// - /// Represents a single cell of the - /// - public class Cell - { - public RollColumn Column { get; internal set; } - public int? RowIndex { get; internal set; } - public string CurrentText { get; internal set; } - - public Cell() { } - - public Cell(Cell cell) - { - Column = cell.Column; - RowIndex = cell.RowIndex; - } - - public bool IsDataCell => Column != null && RowIndex.HasValue; - - public override bool Equals(object obj) - { - if (obj is Cell) - { - var cell = obj as Cell; - return this.Column == cell.Column && this.RowIndex == cell.RowIndex; - } - - return base.Equals(obj); - } - - public override int GetHashCode() - { - return Column.GetHashCode() + RowIndex.GetHashCode(); - } - } - - private class SortCell : IComparer - { - int IComparer.Compare(Cell a, Cell b) - { - Cell c1 = a as Cell; - Cell c2 = b as Cell; - if (c1.RowIndex.HasValue) - { - if (c2.RowIndex.HasValue) - { - int row = c1.RowIndex.Value.CompareTo(c2.RowIndex.Value); - if (row == 0) - { - return c1.Column.Name.CompareTo(c2.Column.Name); - } - - return row; - } - - return 1; - } - - if (c2.RowIndex.HasValue) - { - return -1; - } - - return c1.Column.Name.CompareTo(c2.Column.Name); - } - } - - public enum RollRenderer - { - GDI = 0, - GDIPlus = 1 - } - - #endregion - } -} + private int ColumnWidth { get; set; } + + // The height of a column cell in Vertical Orientation. + private int ColumnHeight { get; set; } + + // The width of a cell in Horizontal Orientation. Only can be changed by changing the Font or CellPadding. + private int CellWidth { get; set; } + + [Browsable(false)] + public int RowHeight => CellHeight; + + /// + /// Gets or sets a value indicating the height of a cell in Vertical Orientation. Only can be changed by changing the Font or CellPadding. + /// + private int CellHeight { get; set; } = 8; + + /// + /// Call when _charSize, MaxCharactersInHorizontal, or CellPadding is changed. + /// + private void UpdateCellSize() + { + CellHeight = _charSize.Height + (CellHeightPadding * 2); + CellWidth = (_charSize.Width * MaxCharactersInHorizontal) + (CellWidthPadding * 4); // Double the padding for horizontal because it looks better + } + + // SuuperW: Count lag frames between FirstDisplayed and given display position + private int CountLagFramesDisplay(int relativeIndex) + { + if (QueryFrameLag != null && LagFramesToHide != 0) + { + int count = 0; + for (int i = 0; i <= relativeIndex; i++) + { + count += _lagFrames[i]; + } + + return count; + } + + return 0; + } + + // Count lag frames between FirstDisplayed and given relative frame index + private int CountLagFramesAbsolute(int relativeIndex) + { + if (QueryFrameLag != null && LagFramesToHide != 0) + { + int count = 0; + for (int i = 0; i + count <= relativeIndex; i++) + { + count += _lagFrames[i]; + } + + return count; + } + + return 0; + } + + private void SetLagFramesArray() + { + if (QueryFrameLag != null && LagFramesToHide != 0) + { + bool showNext = false; + + // First one needs to check BACKWARDS for lag frame count. + SetLagFramesFirst(); + int f = _lagFrames[0]; + if (QueryFrameLag(FirstVisibleRow + f, HideWasLagFrames)) + { + showNext = true; + } + + for (int i = 1; i <= VisibleRows; i++) + { + _lagFrames[i] = 0; + if (!showNext) + { + for (; _lagFrames[i] < LagFramesToHide; _lagFrames[i]++) + { + if (!QueryFrameLag(FirstVisibleRow + i + f, HideWasLagFrames)) + { + break; + } + + f++; + } + } + else + { + if (!QueryFrameLag(FirstVisibleRow + i + f, HideWasLagFrames)) + { + showNext = false; + } + } + + if (_lagFrames[i] == LagFramesToHide && QueryFrameLag(FirstVisibleRow + i + f, HideWasLagFrames)) + { + showNext = true; + } + } + } + else + { + for (int i = 0; i <= VisibleRows; i++) + { + _lagFrames[i] = 0; + } + } + } + private void SetLagFramesFirst() + { + if (QueryFrameLag != null && LagFramesToHide != 0) + { + // Count how many lag frames are above displayed area. + int count = 0; + do + { + count++; + } + while (QueryFrameLag(FirstVisibleRow - count, HideWasLagFrames) && count <= LagFramesToHide); + count--; + + // Count forward + int fCount = -1; + do + { + fCount++; + } + while (QueryFrameLag(FirstVisibleRow + fCount, HideWasLagFrames) && count + fCount < LagFramesToHide); + _lagFrames[0] = (byte)fCount; + } + else + { + _lagFrames[0] = 0; + } + } + + // Number of displayed + hidden frames, if fps is as expected + private int ExpectedDisplayRange() + { + return (VisibleRows + 1) * LagFramesToHide; + } + + #endregion + } +} diff --git a/BizHawk.Client.EmuHawk/CustomControls/InputRoll/RollColumn.cs b/BizHawk.Client.EmuHawk/CustomControls/InputRoll/RollColumn.cs new file mode 100644 index 0000000000..0999e9ebe6 --- /dev/null +++ b/BizHawk.Client.EmuHawk/CustomControls/InputRoll/RollColumn.cs @@ -0,0 +1,31 @@ +using System; + +namespace BizHawk.Client.EmuHawk +{ + public class RollColumn + { + public string Group { get; set; } + public int? Width { get; set; } + public int? Left { get; set; } + public int? Right { get; set; } + public string Name { get; set; } + public string Text { get; set; } + public ColumnType Type { get; set; } + public bool Visible { get; set; } = true; + + /// + /// Column will be drawn with an emphasized look, if true + /// + public bool Emphasis { get; set; } + + /// + /// Column header text will be drawn rotated, if true + /// + public bool Rotatable { get; set; } + + /// + /// If drawn rotated, specifies the desired height, or null to auto-size + /// + public int? RotatedHeight { get; set; } + } +} diff --git a/BizHawk.Client.EmuHawk/CustomControls/InputRoll/RollColumns.cs b/BizHawk.Client.EmuHawk/CustomControls/InputRoll/RollColumns.cs new file mode 100644 index 0000000000..96ee91ea59 --- /dev/null +++ b/BizHawk.Client.EmuHawk/CustomControls/InputRoll/RollColumns.cs @@ -0,0 +1,126 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace BizHawk.Client.EmuHawk +{ + public class RollColumns : List + { + public RollColumn this[string name] => this.SingleOrDefault(column => column.Name == name); + + public IEnumerable VisibleColumns => this.Where(c => c.Visible); + + public Action ChangedCallback { get; set; } + + // TODO: this shouldn't be exposed. But in order to not expose it, each RollColumn must have a change callback, and all property changes must call it, it is quicker and easier to just call this when needed + public void ColumnsChanged() + { + int pos = 0; + + foreach (var col in VisibleColumns) + { + col.Left = pos; + pos += col.Width ?? 0; + col.Right = pos; + } + + ChangedCallback?.Invoke(); + } + + public new void Add(RollColumn column) + { + if (this.Any(c => c.Name == column.Name)) + { + // The designer sucks, doing nothing for now + return; + //throw new InvalidOperationException("A column with this name already exists."); + } + + base.Add(column); + ColumnsChanged(); + } + + public new void AddRange(IEnumerable collection) + { + var items = collection.ToList(); + foreach (var column in items) + { + if (this.Any(c => c.Name == column.Name)) + { + // The designer sucks, doing nothing for now + return; + + throw new InvalidOperationException("A column with this name already exists."); + } + } + + base.AddRange(items); + ColumnsChanged(); + } + + public new void Insert(int index, RollColumn column) + { + if (this.Any(c => c.Name == column.Name)) + { + // The designer sucks, doing nothing for now + return; + + throw new InvalidOperationException("A column with this name already exists."); + } + + base.Insert(index, column); + ColumnsChanged(); + } + + public new void InsertRange(int index, IEnumerable collection) + { + var items = collection.ToList(); + foreach (var column in items) + { + if (this.Any(c => c.Name == column.Name)) + { + throw new InvalidOperationException("A column with this name already exists."); + } + } + + base.InsertRange(index, items); + ColumnsChanged(); + } + + public new bool Remove(RollColumn column) + { + var result = base.Remove(column); + ColumnsChanged(); + return result; + } + + public new int RemoveAll(Predicate match) + { + var result = base.RemoveAll(match); + ColumnsChanged(); + return result; + } + + public new void RemoveAt(int index) + { + base.RemoveAt(index); + ColumnsChanged(); + } + + public new void RemoveRange(int index, int count) + { + base.RemoveRange(index, count); + ColumnsChanged(); + } + + public new void Clear() + { + base.Clear(); + ColumnsChanged(); + } + + public IEnumerable Groups => this + .Select(x => x.Group) + .Distinct(); + } +} diff --git a/BizHawk.Client.EmuHawk/CustomControls/MsgBox.cs b/BizHawk.Client.EmuHawk/CustomControls/MsgBox.cs index 278fc0c73d..7dabe03020 100644 --- a/BizHawk.Client.EmuHawk/CustomControls/MsgBox.cs +++ b/BizHawk.Client.EmuHawk/CustomControls/MsgBox.cs @@ -47,6 +47,7 @@ namespace BizHawk.Client.EmuHawk.CustomControls { InitializeComponent(); + this.ControlBox = false; // Do not set in designer (causes problems with auto scaling) this.messageLbl.Text = message; this.Text = title; this.m_sysIcon = icon; @@ -58,7 +59,7 @@ namespace BizHawk.Client.EmuHawk.CustomControls public void SetMessageToAutoSize() { this.messageLbl.AutoSize = true; - this.messageLbl.MaximumSize = new Size(this.MaximumSize.Width - this.m_sysIcon.Width - 25, this.MaximumSize.Height); + this.messageLbl.MaximumSize = new Size(this.MaximumSize.Width - this.m_sysIcon.Width - UIHelper.ScaleX(25), this.MaximumSize.Height); } /// @@ -220,11 +221,11 @@ namespace BizHawk.Client.EmuHawk.CustomControls } - const int FORM_Y_MARGIN = 10; - const int FORM_X_MARGIN = 16; - const int BUTTON_SPACE = 5; - const int CHECKBOX_SPACE = 15; - const int TEXT_Y_MARGIN = 30; + private static readonly int FORM_Y_MARGIN = UIHelper.ScaleY(10); + private static readonly int FORM_X_MARGIN = UIHelper.ScaleX(16); + private static readonly int BUTTON_SPACE = UIHelper.ScaleX(5); + private static readonly int CHECKBOX_SPACE = UIHelper.ScaleX(15); + private static readonly int TEXT_Y_MARGIN = UIHelper.ScaleY(30); /// /// Auto fits the dialog box to fit the text and the buttons. diff --git a/BizHawk.Client.EmuHawk/CustomControls/MsgBox.designer.cs b/BizHawk.Client.EmuHawk/CustomControls/MsgBox.designer.cs index 3c58b8066b..ccdd5ea1dd 100644 --- a/BizHawk.Client.EmuHawk/CustomControls/MsgBox.designer.cs +++ b/BizHawk.Client.EmuHawk/CustomControls/MsgBox.designer.cs @@ -105,7 +105,6 @@ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.CancelButton = this.btn1; this.ClientSize = new System.Drawing.Size(485, 149); - this.ControlBox = false; this.Controls.Add(this.btn3); this.Controls.Add(this.chkBx); this.Controls.Add(this.btn1); diff --git a/BizHawk.Client.EmuHawk/CustomControls/TasListView.cs b/BizHawk.Client.EmuHawk/CustomControls/TasListView.cs deleted file mode 100644 index 2fd17e6f68..0000000000 --- a/BizHawk.Client.EmuHawk/CustomControls/TasListView.cs +++ /dev/null @@ -1,181 +0,0 @@ -using System; -using System.Linq; -using System.Windows.Forms; - -namespace BizHawk.Client.EmuHawk -{ - public class TasListView : VirtualListView - { - public class Cell - { - public int? RowIndex; - public string Column; - - // Convenience hack - public override string ToString() - { - return string.IsNullOrEmpty(Column) ? "?" : $"{Column} - {(RowIndex.HasValue ? RowIndex.ToString() : "?")}"; - } - } - - public bool RightButtonHeld { get; set; } - - public int? LastSelectedIndex - { - get - { - if (SelectedIndices.Count > 0) - { - return SelectedIndices - .OfType() - .OrderBy(x => x) - .Last(); - } - - return null; - } - } - - private Cell _currentPointedCell = new Cell(); - public Cell CurrentCell - { - get { return _currentPointedCell; } - } - - private Cell _lastPointedCell = new Cell(); - public Cell LastCell - { - get { return _lastPointedCell; } - } - - public bool InputPaintingMode { get; set; } - public bool IsPaintDown { get; private set; } - - /// - /// Calculates the column name and row number that the point (x, y) lies in. - /// - /// X coordinate - /// Y coordinate - private void CalculatePointedCell(int x, int y) - { - int? newRow; - string newColumn = ""; - - var accumulator = 0; - foreach (ColumnHeader column in Columns) - { - accumulator += column.Width; - if (accumulator < x) - { - continue; - } - - newColumn = column.Name; - break; - } - - var rowHeight = this.LineHeight;// 5 (in VirtualListView) and 6 work here for me, but are they always dependable, how can I get the padding? - var headerHeight = rowHeight + 6; - - newRow = ((y - headerHeight) / rowHeight) + this.VScrollPos; - if (newRow >= ItemCount) - { - newRow = null; - } - - if (newColumn != CurrentCell.Column || newRow != CurrentCell.RowIndex) - { - LastCell.Column = CurrentCell.Column; - LastCell.RowIndex = CurrentCell.RowIndex; - - CurrentCell.Column = newColumn; - CurrentCell.RowIndex = newRow; - - CellChanged(LastCell, CurrentCell); - } - } - - public class CellEventArgs - { - public CellEventArgs(Cell oldCell, Cell newCell) - { - OldCell = oldCell; - NewCell = newCell; - } - - public Cell OldCell { get; private set; } - public Cell NewCell { get; private set; } - } - - public delegate void CellChangeEventHandler(object sender, CellEventArgs e); - public event CellChangeEventHandler PointedCellChanged; - - private void CellChanged(Cell oldCell, Cell newCell) - { - if (PointedCellChanged != null) - { - PointedCellChanged(this, new CellEventArgs(oldCell, newCell)); - } - } - - protected override void OnMouseLeave(EventArgs e) - { - _currentPointedCell.Column = ""; - _currentPointedCell.RowIndex = null; - IsPaintDown = false; - base.OnMouseLeave(e); - } - - protected override void OnMouseMove(MouseEventArgs e) - { - CalculatePointedCell(e.X, e.Y); - base.OnMouseMove(e); - } - - protected override void OnMouseDown(MouseEventArgs e) - { - if (e.Button == MouseButtons.Left && InputPaintingMode) - { - IsPaintDown = true; - } - - if (e.Button == MouseButtons.Right) - { - RightButtonHeld = true; - } - - base.OnMouseDown(e); - } - - protected override void OnMouseUp(MouseEventArgs e) - { - IsPaintDown = false; - RightButtonHeld = false; - - base.OnMouseUp(e); - } - - protected override void OnMouseWheel(MouseEventArgs e) - { - if (RightButtonHeld) - { - DoRightMouseScroll(this, e); - } - else - { - base.OnMouseWheel(e); - } - } - - public delegate void RightMouseScrollEventHandler(object sender, MouseEventArgs e); - public event RightMouseScrollEventHandler RightMouseScrolled; - - private void DoRightMouseScroll(object sender, MouseEventArgs e) - { - if (RightMouseScrolled != null) - { - RightMouseScrolled(sender, e); - } - } - } -} diff --git a/BizHawk.Client.EmuHawk/CustomControls/TasListView.resx b/BizHawk.Client.EmuHawk/CustomControls/TasListView.resx deleted file mode 100644 index 43b04417e2..0000000000 --- a/BizHawk.Client.EmuHawk/CustomControls/TasListView.resx +++ /dev/null @@ -1,126 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 17, 17 - - - False - - \ No newline at end of file diff --git a/BizHawk.Client.EmuHawk/CustomControls/VirtualListView.cs b/BizHawk.Client.EmuHawk/CustomControls/VirtualListView.cs deleted file mode 100644 index 6f800dc407..0000000000 --- a/BizHawk.Client.EmuHawk/CustomControls/VirtualListView.cs +++ /dev/null @@ -1,854 +0,0 @@ -using System; -using System.ComponentModel; -using System.Diagnostics; -using System.Drawing; -using System.Runtime.InteropServices; -using System.Windows.Forms; - -namespace BizHawk.Client.EmuHawk -{ - #region win32interop - - [StructLayout(LayoutKind.Sequential)] - internal struct LvDispInfo - { - public NmHdr Hdr; - public LvItem Item; - } - - [StructLayout(LayoutKind.Sequential)] - internal struct NmHdr - { - public IntPtr HwndFrom; - public IntPtr IdFrom; - public int Code; - } - - [StructLayout(LayoutKind.Sequential)] - internal struct NmItemActivate - { - public NmHdr Hdr; - public int Item; - public int SubItem; - public uint NewState; - public uint OldState; - public uint uChanged; - public POINT Action; - public uint lParam; - public uint KeyFlags; - } - - [StructLayout(LayoutKind.Sequential)] - internal struct RECT - { - public int Top; - public int Left; - public int Bottom; - public int Right; - } - - [StructLayout(LayoutKind.Sequential)] - internal struct NmCustomDrawInfo - { - public NmHdr Hdr; - public uint dwDrawStage; - public IntPtr Hdc; - public RECT Rect; - public IntPtr dwItemSpec; - public uint ItemState; - private int _pad64bits; - public IntPtr lItemlParam; - } - - [StructLayout(LayoutKind.Sequential)] - internal struct NmLvCustomDraw - { - public NmCustomDrawInfo Nmcd; - public int ClearText; - public int ClearTextBackground; - public int SubItem; - } - - - - [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] - internal struct LvItem - { - public uint Mask; - public int Item; - public int SubItem; - public uint State; - public uint StateMask; - public IntPtr PszText; - public int cchTextMax; - public int Image; - public IntPtr lParam; - public int Indent; - } - - [FlagsAttribute] - internal enum CustomDrawReturnFlags - { - CDRF_DODEFAULT = 0x00000000, - CDRF_NEWFONT = 0x00000002, - CDRF_SKIPDEFAULT = 0x00000004, - CDRF_NOTIFYPOSTPAINT = 0x00000010, - CDRF_NOTIFYITEMDRAW = 0x00000020, - CDRF_NOTIFYSUBITEMDRAW = 0x00000020, - CDRF_NOTIFYPOSTERASE = 0x00000040, - } - - [FlagsAttribute] - internal enum CustomDrawDrawStageFlags - { - CDDS_PREPAINT = 0x00000001, - CDDS_POSTPAINT = 0x00000002, - CDDS_PREERASE = 0x00000003, - CDDS_POSTERASE = 0x00000004, - - // the 0x000010000 bit means it's individual item specific - CDDS_ITEM = 0x00010000, - CDDS_ITEMPREPAINT = (CDDS_ITEM | CDDS_PREPAINT), - CDDS_ITEMPOSTPAINT = (CDDS_ITEM | CDDS_POSTPAINT), - CDDS_ITEMPREERASE = (CDDS_ITEM | CDDS_PREERASE), - CDDS_ITEMPOSTERASE = (CDDS_ITEM | CDDS_POSTERASE), - CDDS_SUBITEM = 0x00020000, - CDDS_SUBITEMPREPAINT = (CDDS_SUBITEM | CDDS_ITEMPREPAINT), - CDDS_SUBITEMPOSTPAINT = (CDDS_SUBITEM | CDDS_ITEMPOSTPAINT), - CDDS_SUBITEMPREERASE = (CDDS_SUBITEM | CDDS_ITEMPREERASE), - CDDS_SUBITEMPOSTERASE = (CDDS_SUBITEM | CDDS_ITEMPOSTERASE), - } - - [FlagsAttribute] - internal enum LvHitTestFlags - { - LVHT_NOWHERE = 0x0001, - LVHT_ONITEMICON = 0x0002, - LVHT_ONITEMLABEL = 0x0004, - LVHT_ONITEMSTATEICON = 0x0008, - LVHT_ONITEM = (LVHT_ONITEMICON | LVHT_ONITEMLABEL | LVHT_ONITEMSTATEICON), - - LVHT_ABOVE = 0x0008, - LVHT_BELOW = 0x0010, - LVHT_TORIGHT = 0x0020, - LVHT_TOLEFT = 0x0040 - } - - [StructLayout(LayoutKind.Sequential)] - internal struct POINT - { - public int X; - public int Y; - } - - [StructLayout(LayoutKind.Sequential)] - internal class LvHitTestInfo - { - public POINT Point; - public uint Flags; - public int Item; - public int SubItem; - } - - [StructLayout(LayoutKind.Sequential)] - internal struct NMLISTVIEW - { - public NmHdr hdr; - public int iItem; - public int iSubItem; - public uint uNewState; - public uint uOldState; - public uint uChanged; - public POINT ptAction; - public IntPtr lParam; - } - - - internal enum ListViewItemMask : short - { - LVIF_TEXT = 0x0001, - LVIF_IMAGE = 0x0002, - LVIF_PARAM = 0x0004, - LVIF_STATE = 0x0008, - - LVIF_INDENT = 0x0010, - LVIF_NORECOMPUTE = 0x0800, - LVIF_GROUPID = 0x0100, - LVIF_COLUMNS = 0x0200 - } - - internal enum LvNi - { - ALL = 0x0000, - FOCUSED = 0x0001, - SELECTED = 0x0002, - CUT = 0x0004, - DROPHILITED = 0x0008, - - ABOVE = 0x0100, - BELOW = 0x0200, - TOLEFT = 0x0400, - TORIGHT = 0x0800 - } - - internal enum ListViewMessages - { - LVM_FIRST = 0x1000, - LVM_GETITEMCOUNT = (LVM_FIRST + 4), - LVM_SETCALLBACKMASK = (LVM_FIRST + 11), - LVM_GETNEXTITEM = (LVM_FIRST + 12), - LVM_HITTEST = (LVM_FIRST + 18), - LVM_ENSUREVISIBLE = (LVM_FIRST + 19), - LVM_SETITEMSTATE = (LVM_FIRST + 43), - LVM_GETITEMSTATE = (LVM_FIRST + 44), - LVM_SETITEMCOUNT = (LVM_FIRST + 47), - LVM_GETSUBITEMRECT = (LVM_FIRST + 56) - } - - internal enum ListViewStyles : short - { - LVS_OWNERDATA = 0x1000, - LVS_SORTASCENDING = 0x0010, - LVS_SORTDESCENDING = 0x0020, - LVS_SHAREIMAGELISTS = 0x0040, - LVS_NOLABELWRAP = 0x0080, - LVS_AUTOARRANGE = 0x0100 - } - - internal enum ListViewStylesICF : uint - { - LVSICF_NOINVALIDATEALL = 0x00000001, - LVSICF_NOSCROLL = 0x00000002 - } - - internal enum WindowsMessage : uint - { - WM_ERASEBKGND = 0x0014, - WM_SCROLL = 0x115, - WM_LBUTTONDOWN = 0x0201, - WM_LBUTTONUP = 0x0202, - WM_LBUTTONDBLCLK = 0x0203, - WM_RBUTTONDOWN = 0x0204, - WM_RBUTTONUP = 0x0205, - WM_RBUTTONDBLCLK = 0x0206, - WM_SETFOCUS = 0x0007, - WM_NOTIFY = 0x004E, - WM_USER = 0x0400, - WM_REFLECT = WM_USER + 0x1c00 - } - - internal enum Notices - { - NM_FIRST = 0, - NM_CUSTOMDRAW = NM_FIRST - 12, - NM_CLICK = NM_FIRST - 2, - NM_DBLCLICK = NM_FIRST - 3, - } - - internal enum ListViewNotices - { - LVN_FIRST = (0 - 100), - LVN_LAST = (0 - 199), - LVN_BEGINDRAG = LVN_FIRST - 9, - LVN_BEGINRDRAG = LVN_FIRST - 11, - LVN_GETDISPINFOA = LVN_FIRST - 50, - LVN_GETDISPINFOW = LVN_FIRST - 77, - LVN_SETDISPINFOA = LVN_FIRST - 51, - LVN_SETDISPINFOW = LVN_FIRST - 78, - LVN_ODCACHEHINT = LVN_FIRST - 13, - LVN_ODFINDITEMW = LVN_FIRST - 79 - } - - [Flags] - internal enum ListViewCallBackMask : uint - { - LVIS_FOCUSED = 0x0001, - LVIS_SELECTED = 0x0002, - LVIS_CUT = 0x0004, - LVIS_DROPHILITED = 0x0008, - LVIS_GLOW = 0x0010, - LVIS_ACTIVATING = 0x0020, - - LVIS_OVERLAYMASK = 0x0F00, - LVIS_STATEIMAGEMASK = 0xF000, - } - - #endregion - - #region VirtualListView Delegates - - /// - /// Retrieve the background color for a Listview cell (item and subitem). - /// - /// Listview item (row). - /// Listview subitem (column). - /// Background color to use - public delegate void QueryItemBkColorHandler(int item, int subItem, ref Color color); - - /// - /// Retrieve the text for a Listview cell (item and subitem). - /// - /// Listview item (row). - /// Listview subitem (column). - /// Text to display. - public delegate void QueryItemTextHandler(int item, int subItem, out string text); - - /// - /// Retrieve the image index for a Listview item. - /// - /// Listview item (row). - /// Listview subitem (column) - should always be zero. - /// Index of associated ImageList. - public delegate void QueryItemImageHandler(int item, int subItem, out int imageIndex); - - /// - /// Retrieve the indent for a Listview item. The indent is always width of an image. - /// For example, 1 indents the Listview item one image width. - /// - /// Listview item (row). - /// The amount to indent the Listview item. - public delegate void QueryItemIndentHandler(int item, out int itemIndent); - - public delegate void QueryItemHandler(int idx, out ListViewItem item); - - #endregion - - /// - /// VirtualListView is a virtual Listview which allows for a large number of items(rows) - /// to be displayed. The virtual Listview contains very little actual information - - /// mainly item selection and focus information. - /// - public class VirtualListView : ListView - { - // store the item count to prevent the call to SendMessage(LVM_GETITEMCOUNT) - private int _itemCount; - - #region Display query callbacks - - /// - /// Fire the QueryItemBkColor event which requests the background color for the passed Listview cell - /// - public event QueryItemBkColorHandler QueryItemBkColor; - - /// - /// Fire the QueryItemText event which requests the text for the passed Listview cell. - /// - [Category("Data")] - public event QueryItemTextHandler QueryItemText; - - /// - /// Fire the QueryItemImage event which requests the ImageIndex for the passed Listview item. - /// - [Category("Data")] - public event QueryItemImageHandler QueryItemImage; - - /// - /// Fire the QueryItemIndent event which requests the indent for the passed Listview item. - /// - [Category("Data")] - public event QueryItemIndentHandler QueryItemIndent; - - [Category("Data")] - public event QueryItemHandler QueryItem; - - #endregion - - #region Properties - - /// - /// Gets or sets the sets the virtual number of items to be displayed. - /// - [Category("Behavior")] - public int ItemCount - { - get - { - return _itemCount; - } - - set - { - _itemCount = value; - - // If the virtual item count is set before the handle is created - // then the image lists don't get loaded properly - if (!IsHandleCreated) - { - return; - } - - SetVirtualItemCount(); - } - } - - /// - /// Gets or sets how list items are to be displayed. - /// Hide the ListView.View property. - /// Virtual Listviews only allow Details or List. - /// - public new View View - { - get - { - return base.View; - } - - set - { - if (value == View.LargeIcon || - value == View.SmallIcon) - { - throw new ArgumentException($"Icon views are invalid for virtual {nameof(ListView)}s", nameof(View)); - } - - base.View = value; - } - } - - /// - /// Gets the required creation parameters when the control handle is created. - /// Use LVS_OWNERDATA to set this as a virtual Listview. - /// - protected override CreateParams CreateParams - { - get - { - var cp = base.CreateParams; - - // LVS_OWNERDATA style must be set when the control is created - cp.Style |= (int)ListViewStyles.LVS_OWNERDATA; - return cp; - } - } - - #endregion - - [Browsable(false)] - [DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden)] - public int LineHeight { get; private set; } - - [Browsable(false)] - [DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden)] - public int NumberOfVisibleRows - { - get - { - return Height / LineHeight; - } - } - - #region Constructors - - /// - /// Initializes a new instance of the class. - /// Create a new instance of this control. - /// - public VirtualListView() - { - // virtual listviews must be Details or List view with no sorting - View = View.Details; - Sorting = SortOrder.None; - - UseCustomBackground = true; - - ptrlvhti = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(LvHitTestInfo))); - - SetStyle(ControlStyles.OptimizedDoubleBuffer, true); - SetStyle(ControlStyles.Opaque, true); - SetStyle(ControlStyles.AllPaintingInWmPaint, true); - - LineHeight = this.Font.Height + 5; - } - - ~VirtualListView() - { - Marshal.FreeHGlobal(ptrlvhti); - } - - #endregion - - #region Methods - /// - /// Set the state of the passed Listview item's index. - /// - /// Listview item's index. - /// Select the passed item? - public void SelectItem(int index, bool selected) - { - var ptrItem = IntPtr.Zero; - - try - { - // Determine whether selecting or unselecting. - uint select = selected ? (uint)ListViewCallBackMask.LVIS_SELECTED : 0; - - // Fill in the LVITEM structure with state fields. - var stateItem = new LvItem - { - Mask = (uint)ListViewItemMask.LVIF_STATE, - Item = index, - SubItem = 0, - State = @select, - StateMask = (uint)ListViewCallBackMask.LVIS_SELECTED - }; - - // Copy the structure to unmanaged memory. - ptrItem = Marshal.AllocHGlobal(Marshal.SizeOf(stateItem.GetType())); - Marshal.StructureToPtr(stateItem, ptrItem, true); - - // Send the message to the control window. - Win32.SendMessage( - this.Handle, - (int)ListViewMessages.LVM_SETITEMSTATE, - (IntPtr)index, - ptrItem); - } - catch (Exception ex) - { - System.Diagnostics.Trace.WriteLine($"VirtualListView.SetItemState error={ex.Message}"); - - // TODO: should this eat any exceptions? - throw; - } - finally - { - // Always release the unmanaged memory. - if (ptrItem != IntPtr.Zero) - { - Marshal.FreeHGlobal(ptrItem); - } - } - } - - private void SetVirtualItemCount() - { - Win32.SendMessage( - this.Handle, - (int)ListViewMessages.LVM_SETITEMCOUNT, - (IntPtr)this._itemCount, - IntPtr.Zero); - } - - protected void OnDispInfoNotice(ref Message m, bool useAnsi) - { - var info = (LvDispInfo)m.GetLParam(typeof(LvDispInfo)); - - if ((info.Item.Mask & (uint)ListViewItemMask.LVIF_TEXT) > 0) - { - if (QueryItemText != null) - { - string lvtext; - QueryItemText(info.Item.Item, info.Item.SubItem, out lvtext); - if (lvtext != null) - { - try - { - int maxIndex = Math.Min(info.Item.cchTextMax - 1, lvtext.Length); - var data = new char[maxIndex + 1]; - lvtext.CopyTo(0, data, 0, lvtext.Length); - data[maxIndex] = '\0'; - Marshal.Copy(data, 0, info.Item.PszText, data.Length); - } - catch (Exception e) - { - Debug.WriteLine($"Failed to copy text name from client: {e}", $"{nameof(VirtualListView)}.{nameof(OnDispInfoNotice)}"); - } - } - } - } - - if ((info.Item.Mask & (uint)ListViewItemMask.LVIF_IMAGE) > 0) - { - int imageIndex = 0; - if (QueryItemImage != null) - { - QueryItemImage(info.Item.Item, info.Item.SubItem, out imageIndex); - } - - info.Item.Image = imageIndex; - Marshal.StructureToPtr(info, m.LParam, false); - } - - if ((info.Item.Mask & (uint)ListViewItemMask.LVIF_INDENT) > 0) - { - int itemIndent = 0; - if (QueryItemIndent != null) - { - QueryItemIndent(info.Item.Item, out itemIndent); - } - - info.Item.Indent = itemIndent; - Marshal.StructureToPtr(info, m.LParam, false); - } - - m.Result = new IntPtr(0); - } - - protected void OnCustomDrawNotice(ref Message m) - { - var cd = (NmLvCustomDraw)m.GetLParam(typeof(NmLvCustomDraw)); - switch (cd.Nmcd.dwDrawStage) - { - case (int)CustomDrawDrawStageFlags.CDDS_ITEMPREPAINT: - case (int)CustomDrawDrawStageFlags.CDDS_PREPAINT: - m.Result = new IntPtr((int)CustomDrawReturnFlags.CDRF_NOTIFYSUBITEMDRAW); - break; - case (int)CustomDrawDrawStageFlags.CDDS_SUBITEMPREPAINT: - if (QueryItemBkColor != null) - { - var color = Color.FromArgb(cd.ClearTextBackground & 0xFF, (cd.ClearTextBackground >> 8) & 0xFF, (cd.ClearTextBackground >> 16) & 0xFF); - QueryItemBkColor(cd.Nmcd.dwItemSpec.ToInt32(), cd.SubItem, ref color); - cd.ClearTextBackground = (color.B << 16) | (color.G << 8) | color.R; - Marshal.StructureToPtr(cd, m.LParam, false); - } - - m.Result = new IntPtr((int)CustomDrawReturnFlags.CDRF_DODEFAULT); - break; - } - } - - /// - /// Event to be fired whenever the control scrolls - /// - public event ScrollEventHandler Scroll; - protected virtual void OnScroll(ScrollEventArgs e) - { - var handler = this.Scroll; - if (handler != null) - { - handler(this, e); - } - } - - [DllImport("user32.dll", CharSet = CharSet.Auto)] - public static extern int GetScrollPos(IntPtr hWnd, Orientation nBar); - - /// - /// Gets the Vertical Scroll position of the control. - /// - public int VScrollPos - { - get { return GetScrollPos(this.Handle, Orientation.Vertical); } - } - - protected override void WndProc(ref Message m) - { - var messageProcessed = false; - switch (m.Msg) - { - case (int)WindowsMessage.WM_REFLECT + (int)WindowsMessage.WM_NOTIFY: - var nm1 = (NmHdr)m.GetLParam(typeof(NmHdr)); - switch (nm1.Code) - { - case (int)Notices.NM_CUSTOMDRAW: - OnCustomDrawNotice(ref m); - messageProcessed = true; - - if (QueryItemBkColor == null || !UseCustomBackground) - { - m.Result = (IntPtr)0; - } - - break; - case (int)ListViewNotices.LVN_GETDISPINFOW: - OnDispInfoNotice(ref m, false); - messageProcessed = true; - break; - case (int)ListViewNotices.LVN_BEGINDRAG: - OnBeginItemDrag(MouseButtons.Left, ref m); - messageProcessed = true; - break; - case (int)ListViewNotices.LVN_BEGINRDRAG: - OnBeginItemDrag(MouseButtons.Right, ref m); - messageProcessed = true; - break; - } - - break; - case (int)WindowsMessage.WM_SCROLL: - // http://stackoverflow.com/questions/1851620/handling-scroll-event-on-listview-in-c-sharp - OnScroll(new ScrollEventArgs((ScrollEventType)(m.WParam.ToInt32() & 0xffff), m.WParam.ToInt32())); - break; - case (int)WindowsMessage.WM_ERASEBKGND: - if (BlazingFast) - { - messageProcessed = true; - m.Result = new IntPtr(1); - } - - break; - } - - if (!messageProcessed) - { - try - { - base.WndProc(ref m); - } - catch (Exception ex) - { - Trace.WriteLine($"Message {m} caused an exception: {ex.Message}"); - } - } - } - - public bool BlazingFast { get; set; } - public bool UseCustomBackground { get; set; } - - protected ListViewItem GetItem(int idx) - { - ListViewItem item = null; - if (QueryItem != null) - { - QueryItem(idx, out item); - } - - if (item == null) - { - throw new ArgumentException($"cannot find item {idx} via {nameof(QueryItem)} event"); - } - - return item; - } - - protected void OnBeginItemDrag(MouseButtons mouseButton, ref Message m) - { - var info = (NMLISTVIEW)m.GetLParam(typeof(NMLISTVIEW)); - ListViewItem item = null; - if (QueryItem != null) - { - QueryItem(info.iItem, out item); - } - - OnItemDrag(new ItemDragEventArgs(mouseButton, item)); - } - - protected override void OnHandleCreated(EventArgs e) - { - base.OnHandleCreated(e); - - // ensure the value for ItemCount is sent to the control properly if the user set it - // before the handle was created - SetVirtualItemCount(); - } - - protected override void OnHandleDestroyed(EventArgs e) - { - // the ListView OnHandleDestroyed accesses the Items list for all selected items - ItemCount = 0; - base.OnHandleDestroyed(e); - } - - #endregion - - LvHitTestInfo lvhti = new LvHitTestInfo(); - IntPtr ptrlvhti; - int selection = -1; - - public int hitTest(int x, int y) - { - lvhti.Point.X = x; - lvhti.Point.Y = y; - Marshal.StructureToPtr(lvhti, ptrlvhti, true); - int z = (int)Win32.SendMessage(this.Handle, (int)ListViewMessages.LVM_HITTEST, (IntPtr)0, ptrlvhti); - Marshal.PtrToStructure(ptrlvhti, lvhti); - return z; - } - - public void ensureVisible(int index) - { - Win32.SendMessage(Handle, (int)ListViewMessages.LVM_ENSUREVISIBLE, (IntPtr)index, (IntPtr)1); - } - - public void ensureVisible() - { - ensureVisible(selectedItem); - } - - public void setSelection(int index) - { - clearSelection(); - selection = index; - SelectItem(selection, true); - } - - public int selectedItem - { - get - { - if (SelectedIndices.Count == 0) - { - return -1; - } - else - { - return SelectedIndices[0]; - } - } - - set - { - setSelection(value); - } - } - - public void clearSelection() - { - if (selection != -1) - { - SelectItem(selection, false); - } - - selection = -1; - } - - // Informs user that a select all event is in place, can be used in change events to wait until this is false - public bool SelectAllInProgress { get; set; } - - public void SelectAll() - { - this.BeginUpdate(); - SelectAllInProgress = true; - - for (var i = 0; i < _itemCount; i++) - { - if (i == _itemCount - 1) - { - SelectAllInProgress = false; - } - - this.SelectItem(i, true); - } - - this.EndUpdate(); - } - - public void DeselectAll() - { - this.BeginUpdate(); - SelectAllInProgress = true; - - for (var i = 0; i < _itemCount; i++) - { - if (i == _itemCount - 1) - { - SelectAllInProgress = false; - } - - this.SelectItem(i, false); - } - - this.EndUpdate(); - } - - protected override void OnKeyDown(KeyEventArgs e) - { - if (e.KeyCode == Keys.A && e.Control && !e.Alt && !e.Shift) // Select All - { - SelectAll(); - } - - base.OnKeyDown(e); - } - } -} diff --git a/BizHawk.Client.EmuHawk/EmuHawkUtil.cs b/BizHawk.Client.EmuHawk/EmuHawkUtil.cs new file mode 100644 index 0000000000..ca0879fd32 --- /dev/null +++ b/BizHawk.Client.EmuHawk/EmuHawkUtil.cs @@ -0,0 +1,53 @@ +using System; +using System.Drawing; +using System.Windows.Forms; +using BizHawk.Client.Common; +using BizHawk.Client.EmuHawk.CustomControls; +using BizHawk.Emulation.Common; +using Cores = BizHawk.Emulation.Cores; + +namespace BizHawk.Client.EmuHawk +{ + public static class EmuHawkUtil + { + public static bool EnsureCoreIsAccurate(IEmulator emulator) + { + static bool PromptToSwitchCore(string currentCore, string recommendedCore, Action disableCurrentCore) + { + using var box = new MsgBox( + $"While the {currentCore} core is faster, it is not nearly as accurate as {recommendedCore}.{Environment.NewLine}It is recommended that you switch to the {recommendedCore} core for movie recording.{Environment.NewLine}Switch to {recommendedCore}?", + "Accuracy Warning", + MessageBoxIcon.Warning); + + box.SetButtons( + new[] { "Switch", "Continue" }, + new[] { DialogResult.Yes, DialogResult.Cancel }); + + box.MaximumSize = UIHelper.Scale(new Size(575, 175)); + box.SetMessageToAutoSize(); + + var result = box.ShowDialog(); + + if (result != DialogResult.Yes) + { + return false; + } + + disableCurrentCore(); + GlobalWin.MainForm.RebootCore(); + return true; + } + + if (emulator is Cores.Nintendo.SNES9X.Snes9x) + { + return PromptToSwitchCore("Snes9x", "bsnes", () => Global.Config.SNES_InSnes9x = false); + } + if (emulator is Cores.Consoles.Nintendo.QuickNES.QuickNES) + { + return PromptToSwitchCore("QuickNes", "NesHawk", () => Global.Config.NES_InQuickNES = false); + } + + return true; + } + } +} diff --git a/BizHawk.Client.EmuHawk/Extensions/ControlExtensions.cs b/BizHawk.Client.EmuHawk/Extensions/ControlExtensions.cs index 756dcfca33..b37ca52fa2 100644 --- a/BizHawk.Client.EmuHawk/Extensions/ControlExtensions.cs +++ b/BizHawk.Client.EmuHawk/Extensions/ControlExtensions.cs @@ -7,10 +7,7 @@ using System.Runtime.InteropServices; using System.Text; using System.Windows.Forms; -using BizHawk.Common; using BizHawk.Common.ReflectionExtensions; -using BizHawk.Client.Common; - namespace BizHawk.Client.EmuHawk.WinFormExtensions { @@ -43,44 +40,7 @@ namespace BizHawk.Client.EmuHawk.WinFormExtensions return control.BeginInvoke(action); } - public static void AddColumn(this ListView listView, string columnName, bool enabled, int columnWidth) - { - if (enabled) - { - if (listView.Columns[columnName] == null) - { - var column = new ColumnHeader - { - Name = columnName, - Text = columnName.Replace("Column", ""), - Width = columnWidth, - }; - - listView.Columns.Add(column); - } - } - } - - public static void AddColumn(this ListView listView, ToolDialogSettings.Column column) - { - if (column.Visible) - { - if (listView.Columns[column.Name] == null) - { - var lsstViewColumn = new ColumnHeader - { - Name = column.Name, - Text = column.Name.Replace("Column", ""), - Width = column.Width, - DisplayIndex = column.Index - }; - - listView.Columns.Add(lsstViewColumn); - } - } - } - - public static ToolStripMenuItem GenerateColumnsMenu(this ToolDialogSettings.ColumnList list, Action changeCallback) + public static ToolStripMenuItem ToColumnsMenu(this InputRoll inputRoll, Action changeCallback) { var menu = new ToolStripMenuItem { @@ -88,33 +48,31 @@ namespace BizHawk.Client.EmuHawk.WinFormExtensions Text = "Columns" }; - var dummyList = list; + var columns = inputRoll.AllColumns; - foreach (var column in dummyList) + foreach (var column in columns) { var menuItem = new ToolStripMenuItem { Name = column.Name, - Text = column.Name.Replace("Column", "") + Text = $"{column.Text} ({column.Name})", + Checked = column.Visible, + CheckOnClick = true, + Tag = column.Name }; - menuItem.Click += (o, ev) => + menuItem.CheckedChanged += (o, ev) => { - dummyList[menuItem.Name].Visible ^= true; + var sender = (ToolStripMenuItem)o; + columns.Find(c => c.Name == (string)sender.Tag).Visible = sender.Checked; + columns.ColumnsChanged(); changeCallback(); + inputRoll.Refresh(); }; menu.DropDownItems.Add(menuItem); } - menu.DropDownOpened += (o, e) => - { - foreach (var column in dummyList) - { - (menu.DropDownItems[column.Name] as ToolStripMenuItem).Checked = column.Visible; - } - }; - return menu; } @@ -123,6 +81,13 @@ namespace BizHawk.Client.EmuHawk.WinFormExtensions return control.PointToScreen(new Point(child.Location.X, child.Location.Y)); } + public static Color Add(this Color color, int val) + { + var col = color.ToArgb(); + col += val; + return Color.FromArgb(col); + } + #region Enumerable to Enumerable /// @@ -139,16 +104,6 @@ namespace BizHawk.Client.EmuHawk.WinFormExtensions return tabControl.TabPages.Cast(); } - public static IEnumerable SelectedIndices(this ListView listView) - { - return listView.SelectedIndices.Cast(); - } - - public static IEnumerable ColumnHeaders(this ListView listView) - { - return listView.Columns.OfType(); - } - #endregion } @@ -251,7 +206,7 @@ namespace BizHawk.Client.EmuHawk.WinFormExtensions { foreach (ListViewItem.ListViewSubItem item in listViewControl.Items[index].SubItems) { - if (!String.IsNullOrWhiteSpace(item.Text)) + if (!string.IsNullOrWhiteSpace(item.Text)) { sb.Append(item.Text).Append('\t'); } diff --git a/BizHawk.Client.EmuHawk/Extensions/CoreExtensions.cs b/BizHawk.Client.EmuHawk/Extensions/CoreExtensions.cs index 613d465979..07590da894 100644 --- a/BizHawk.Client.EmuHawk/Extensions/CoreExtensions.cs +++ b/BizHawk.Client.EmuHawk/Extensions/CoreExtensions.cs @@ -11,6 +11,7 @@ using BizHawk.Emulation.Cores.Nintendo.SNES9X; using BizHawk.Emulation.Cores.Sega.Saturn; using BizHawk.Emulation.Cores.Consoles.Sega.gpgx; using BizHawk.Emulation.Cores.Sony.PSP; +using BizHawk.Emulation.Cores.Arcades.MAME; using BizHawk.Client.Common; @@ -51,6 +52,10 @@ namespace BizHawk.Client.EmuHawk.CoreExtensions { return Properties.Resources.snes9x; } + else if (core is MAME) + { + return Properties.Resources.mame; + } else { return null; diff --git a/BizHawk.Client.EmuHawk/Extensions/ToolExtensions.cs b/BizHawk.Client.EmuHawk/Extensions/ToolExtensions.cs index c125b2286d..3e71f5ff11 100644 --- a/BizHawk.Client.EmuHawk/Extensions/ToolExtensions.cs +++ b/BizHawk.Client.EmuHawk/Extensions/ToolExtensions.cs @@ -50,7 +50,7 @@ namespace BizHawk.Client.EmuHawk.ToolExtensions } //TODO - do TSMI and TSDD need disposing? yuck - var item = new ToolStripMenuItem { Text = caption }; + var item = new ToolStripMenuItem { Text = caption.Replace("&", "&&") }; items.Add(item); item.Click += (o, ev) => diff --git a/BizHawk.Client.EmuHawk/FileFilterEntry.cs b/BizHawk.Client.EmuHawk/FileFilterEntry.cs new file mode 100644 index 0000000000..9465b9b940 --- /dev/null +++ b/BizHawk.Client.EmuHawk/FileFilterEntry.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace BizHawk.Client.EmuHawk +{ + public class FileFilterEntry + { + public string Description { get; } + public string[] Filters { get; } + public string[] DeveloperFilters { get; } + + public FileFilterEntry(string description, string filters, string developerFilters = null) + { + Description = description; + Filters = filters?.Split(';') ?? Array.Empty(); + DeveloperFilters = developerFilters?.Split(';') ?? Array.Empty(); + } + + public IEnumerable EffectiveFilters + { + get + { + IEnumerable effectiveFilters = Filters; + if (VersionInfo.DeveloperBuild) + { + effectiveFilters = effectiveFilters.Concat(DeveloperFilters); + } + return effectiveFilters; + } + } + } +} diff --git a/BizHawk.Client.EmuHawk/FileLoader.cs b/BizHawk.Client.EmuHawk/FileLoader.cs index 3d49dd87a1..d08f5c693d 100644 --- a/BizHawk.Client.EmuHawk/FileLoader.cs +++ b/BizHawk.Client.EmuHawk/FileLoader.cs @@ -6,7 +6,6 @@ using System.Collections.Generic; using BizHawk.Common; using BizHawk.Emulation.Common.IEmulatorExtensions; -using BizHawk.Emulation.Cores.PCEngine; using BizHawk.Client.Common; namespace BizHawk.Client.EmuHawk @@ -40,31 +39,8 @@ namespace BizHawk.Client.EmuHawk } } - // This is the list from MainForm->RomFilter()'s non-developer build. It needs to be kept up-to-date when new cores are added. - // adelikat: This is annoying and bad. Maybe we could generate RomFilter from this property? - private string[] KnownRomExtensions - { - get - { - if (VersionInfo.DeveloperBuild) - { - return new[] - { - ".NES", ".FDS", ".UNF", ".SMS", ".GG", ".SG", ".GB", ".GBC", ".GBA", ".PCE", ".SGX", ".BIN", ".SMD", ".GEN", ".MD", ".SMC", - ".SFC", ".A26", ".A78", ".LNX", ".COL", ".ROM", ".M3U", ".CUE", ".CCD", ".SGB", ".Z64", ".V64", ".N64", ".WS", ".WSC", ".XML", - ".DSK", ".DO", ".PO", ".PSF", ".MINIPSF", ".NSF", ".EXE", ".PRG", ".D64", ".G64", ".CRT", ".TAP", ".32X", ".MDS", ".TZX", - ".PZX", ".CSW", ".WAV", ".CDT" - }; - } - - return new[] - { - ".NES", ".FDS", ".UNF", ".SMS", ".GG", ".SG", ".GB", ".GBC", ".GBA", ".PCE", ".SGX", ".BIN", ".SMD", ".GEN", ".MD", ".SMC", - ".SFC", ".A26", ".A78", ".LNX", ".COL", ".ROM", ".M3U", ".CUE", ".CCD", ".SGB", ".Z64", ".V64", ".N64", ".WS", ".WSC", ".XML", - ".DSK", ".DO", ".PO", ".PSF", ".MINIPSF", ".NSF", ".PRG", ".D64", ".G64", ".CRT", ".TAP", ".32X", ".MDS", ".TZX", ".PZX", ".CSW", ".WAV" - }; - } - } + private IEnumerable KnownRomExtensions => + RomFilterEntries.SelectMany(f => f.EffectiveFilters.Where(s => s.StartsWith("*.", StringComparison.Ordinal)).Select(s => s.Substring(1).ToUpperInvariant())); private readonly string[] _nonArchive = { ".ISO", ".CUE", ".CCD" }; @@ -173,7 +149,7 @@ namespace BizHawk.Client.EmuHawk { foreach (string file in fileList) { - var ext = Path.GetExtension(file).ToUpper() ?? ""; + var ext = Path.GetExtension(file).ToUpperInvariant() ?? ""; FileInformation fileInformation = new FileInformation(Path.GetDirectoryName(file), Path.GetFileName(file), archive); switch (ext) diff --git a/BizHawk.Client.EmuHawk/Input/Input.cs b/BizHawk.Client.EmuHawk/Input/Input.cs index c1d873ad76..9facff47c6 100644 --- a/BizHawk.Client.EmuHawk/Input/Input.cs +++ b/BizHawk.Client.EmuHawk/Input/Input.cs @@ -3,8 +3,6 @@ using System.Linq; using System.Collections.Generic; using System.Threading; -using SlimDX.DirectInput; - using BizHawk.Common; using BizHawk.Client.Common; @@ -70,6 +68,13 @@ namespace BizHawk.Client.EmuHawk Pad = 4 } + public enum AllowInput + { + None = 0, + All = 1, + OnlyController = 2 + } + /// /// If your form needs this kind of input focus, be sure to say so. /// Really, this only makes sense for mouse, but I've started building it out for other things @@ -196,71 +201,53 @@ namespace BizHawk.Client.EmuHawk { public LogicalButton LogicalButton; public InputEventType EventType; + public InputFocus Source; public override string ToString() { return $"{EventType.ToString()}:{LogicalButton.ToString()}"; } } - private readonly WorkingDictionary ModifierState = new WorkingDictionary(); + private readonly Dictionary ModifierState = new Dictionary(); private readonly WorkingDictionary LastState = new WorkingDictionary(); - private readonly WorkingDictionary UnpressState = new WorkingDictionary(); - private readonly HashSet IgnoreKeys = new HashSet(new[] { "LeftShift", "RightShift", "LeftControl", "RightControl", "LeftAlt", "RightAlt" }); private readonly WorkingDictionary FloatValues = new WorkingDictionary(); private readonly WorkingDictionary FloatDeltas = new WorkingDictionary(); private bool trackdeltas = false; + private bool IgnoreEventsNextPoll = false; - void HandleButton(string button, bool newState) + void HandleButton(string button, bool newState, InputFocus source) { - bool isModifier = IgnoreKeys.Contains(button); - if (EnableIgnoreModifiers && isModifier) return; - if (LastState[button] && newState) return; - if (!LastState[button] && !newState) return; + ModifierKey currentModifier = ButtonToModifierKey(button); + if (EnableIgnoreModifiers && currentModifier != ModifierKey.None) return; + if (LastState[button] == newState) return; //apply //NOTE: this is not quite right. if someone held leftshift+rightshift it would be broken. seems unlikely, though. - if (button == "LeftShift") + if (currentModifier != ModifierKey.None) { - _Modifiers &= ~ModifierKey.Shift; if (newState) - _Modifiers |= ModifierKey.Shift; + _Modifiers |= currentModifier; + else + _Modifiers &= ~currentModifier; } - if (button == "RightShift") { _Modifiers &= ~ModifierKey.Shift; if (newState) _Modifiers |= ModifierKey.Shift; } - if (button == "LeftControl") { _Modifiers &= ~ModifierKey.Control; if (newState) _Modifiers |= ModifierKey.Control; } - if (button == "RightControl") { _Modifiers &= ~ModifierKey.Control; if (newState) _Modifiers |= ModifierKey.Control; } - if (button == "LeftAlt") { _Modifiers &= ~ModifierKey.Alt; if (newState) _Modifiers |= ModifierKey.Alt; } - if (button == "RightAlt") { _Modifiers &= ~ModifierKey.Alt; if (newState) _Modifiers |= ModifierKey.Alt; } - - if (UnpressState.ContainsKey(button)) - { - if (newState) return; - Console.WriteLine($"Removing Unpress {button} with {nameof(newState)} {newState}"); - UnpressState.Remove(button); - LastState[button] = false; - return; - } - //dont generate events for things like Ctrl+LeftControl ModifierKey mods = _Modifiers; - if (button == "LeftShift") mods &= ~ModifierKey.Shift; - if (button == "RightShift") mods &= ~ModifierKey.Shift; - if (button == "LeftControl") mods &= ~ModifierKey.Control; - if (button == "RightControl") mods &= ~ModifierKey.Control; - if (button == "LeftAlt") mods &= ~ModifierKey.Alt; - if (button == "RightAlt") mods &= ~ModifierKey.Alt; + if (currentModifier != ModifierKey.None) + mods &= ~currentModifier; var ie = new InputEvent { EventType = newState ? InputEventType.Press : InputEventType.Release, - LogicalButton = new LogicalButton(button, mods) + LogicalButton = new LogicalButton(button, mods), + Source = source }; LastState[button] = newState; //track the pressed events with modifiers that we send so that we can send corresponding unpresses with modifiers //this is an interesting idea, which we may need later, but not yet. //for example, you may see this series of events: press:ctrl+c, release:ctrl, release:c - //but you might would rather have press:ctr+c, release:ctrl+c + //but you might would rather have press:ctrl+c, release:ctrl+c //this code relates the releases to the original presses. //UPDATE - this is necessary for the frame advance key, which has a special meaning when it gets stuck down //so, i am adding it as of 11-sep-2011 @@ -270,32 +257,53 @@ namespace BizHawk.Client.EmuHawk } else { - if (ModifierState[button] != null) + LogicalButton buttonModifierState; + if (ModifierState.TryGetValue(button, out buttonModifierState)) { - LogicalButton alreadyReleased = ie.LogicalButton; - var ieModified = new InputEvent - { - LogicalButton = (LogicalButton)ModifierState[button], - EventType = InputEventType.Release - }; - if (ieModified.LogicalButton != alreadyReleased) - _NewEvents.Add(ieModified); + if (buttonModifierState != ie.LogicalButton && !IgnoreEventsNextPoll) + { + _NewEvents.Add( + new InputEvent + { + LogicalButton = buttonModifierState, + EventType = InputEventType.Release, + Source = source + }); + } + ModifierState.Remove(button); } - ModifierState[button] = null; } - _NewEvents.Add(ie); + if (!IgnoreEventsNextPoll) + { + _NewEvents.Add(ie); + } } - ModifierKey _Modifiers; + private static ModifierKey ButtonToModifierKey(string button) + { + switch (button) + { + case "LeftShift": return ModifierKey.Shift; + case "RightShift": return ModifierKey.Shift; + case "LeftControl": return ModifierKey.Control; + case "RightControl": return ModifierKey.Control; + case "LeftAlt": return ModifierKey.Alt; + case "RightAlt": return ModifierKey.Alt; + } + return ModifierKey.None; + } + + private ModifierKey _Modifiers; private readonly List _NewEvents = new List(); - //do we need this? public void ClearEvents() { lock (this) { InputEvents.Clear(); + // To "clear" anything currently in the input device buffers + IgnoreEventsNextPoll = true; } } @@ -351,7 +359,7 @@ namespace BizHawk.Client.EmuHawk //analyze keys foreach (var ke in keyEvents) - HandleButton(ke.Key.ToString(), ke.Pressed); + HandleButton(ke.Key.ToString(), ke.Pressed, InputFocus.Keyboard); lock (FloatValues) { @@ -378,7 +386,7 @@ namespace BizHawk.Client.EmuHawk { string xname = $"X{pad.PlayerNumber} "; for (int b = 0; b < pad.NumButtons; b++) - HandleButton(xname + pad.ButtonName(b), pad.Pressed(b)); + HandleButton(xname + pad.ButtonName(b), pad.Pressed(b), InputFocus.Pad); foreach (var sv in pad.GetFloats()) { string n = xname + sv.Item1; @@ -394,7 +402,7 @@ namespace BizHawk.Client.EmuHawk { string jname = $"J{pad.PlayerNumber} "; for (int b = 0; b < pad.NumButtons; b++) - HandleButton(jname + pad.ButtonName(b), pad.Pressed(b)); + HandleButton(jname + pad.ButtonName(b), pad.Pressed(b), InputFocus.Pad); foreach (var sv in pad.GetFloats()) { string n = jname + sv.Item1; @@ -423,11 +431,11 @@ namespace BizHawk.Client.EmuHawk FloatValues["WMouse Y"] = P.Y; var B = System.Windows.Forms.Control.MouseButtons; - HandleButton("WMouse L", (B & System.Windows.Forms.MouseButtons.Left) != 0); - HandleButton("WMouse C", (B & System.Windows.Forms.MouseButtons.Middle) != 0); - HandleButton("WMouse R", (B & System.Windows.Forms.MouseButtons.Right) != 0); - HandleButton("WMouse 1", (B & System.Windows.Forms.MouseButtons.XButton1) != 0); - HandleButton("WMouse 2", (B & System.Windows.Forms.MouseButtons.XButton2) != 0); + HandleButton("WMouse L", (B & System.Windows.Forms.MouseButtons.Left) != 0, InputFocus.Mouse); + HandleButton("WMouse C", (B & System.Windows.Forms.MouseButtons.Middle) != 0, InputFocus.Mouse); + HandleButton("WMouse R", (B & System.Windows.Forms.MouseButtons.Right) != 0, InputFocus.Mouse); + HandleButton("WMouse 1", (B & System.Windows.Forms.MouseButtons.XButton1) != 0, InputFocus.Mouse); + HandleButton("WMouse 2", (B & System.Windows.Forms.MouseButtons.XButton2) != 0, InputFocus.Mouse); } else { @@ -439,22 +447,26 @@ namespace BizHawk.Client.EmuHawk //HandleButton("WMouse 1", false); //HandleButton("WMouse 2", false); } - } - //WHAT!? WE SHOULD NOT BE SO NAIVELY TOUCHING MAINFORM FROM THE INPUTTHREAD. ITS BUSY RUNNING. - bool swallow = !GlobalWin.MainForm.AllowInput(false); - - foreach (var ie in _NewEvents) + if (_NewEvents.Count != 0) { - //events are swallowed in some cases: - if (ie.LogicalButton.Alt && !GlobalWin.MainForm.AllowInput(true)) - { } - else if (ie.EventType == InputEventType.Press && swallow) - { } - else + //WHAT!? WE SHOULD NOT BE SO NAIVELY TOUCHING MAINFORM FROM THE INPUTTHREAD. ITS BUSY RUNNING. + AllowInput allowInput = GlobalWin.MainForm.AllowInput(false); + + foreach (var ie in _NewEvents) + { + //events are swallowed in some cases: + if (ie.LogicalButton.Alt && ShouldSwallow(GlobalWin.MainForm.AllowInput(true), ie)) + continue; + if (ie.EventType == InputEventType.Press && ShouldSwallow(allowInput, ie)) + continue; + EnqueueEvent(ie); + } } + + IgnoreEventsNextPoll = false; } //lock(this) //arbitrary selection of polling frequency: @@ -462,6 +474,11 @@ namespace BizHawk.Client.EmuHawk } } + private static bool ShouldSwallow(AllowInput allowInput, InputEvent inputEvent) + { + return allowInput == AllowInput.None || (allowInput == AllowInput.OnlyController && inputEvent.Source != InputFocus.Pad); + } + public void StartListeningForFloatEvents() { lock (FloatValues) @@ -500,42 +517,39 @@ namespace BizHawk.Client.EmuHawk } //returns the next Press event, if available. should be useful - public string GetNextBindEvent() + public string GetNextBindEvent(ref InputEvent lastPress) { //this whole process is intimately involved with the data structures, which can conflict with the input thread. lock (this) { if (InputEvents.Count == 0) return null; - if (!GlobalWin.MainForm.AllowInput(false)) return null; + AllowInput allowInput = GlobalWin.MainForm.AllowInput(false); - //we only listen to releases for input binding, because we need to distinguish releases of pure modifierkeys from modified keys + //wait for the first release after a press to complete input binding, because we need to distinguish pure modifierkeys from modified keys //if you just pressed ctrl, wanting to bind ctrl, we'd see: pressed:ctrl, unpressed:ctrl //if you just pressed ctrl+c, wanting to bind ctrl+c, we'd see: pressed:ctrl, pressed:ctrl+c, unpressed:ctrl+c, unpressed:ctrl - //so its the first unpress we need to listen for + //but in the 2nd example the unpresses will be swapped if ctrl is released first, so we'll take the last press before the release while (InputEvents.Count != 0) { - var ie = DequeueEvent(); + InputEvent ie = DequeueEvent(); - //as a special perk, we'll accept escape immediately - if (ie.EventType == InputEventType.Press && ie.LogicalButton.Button == "Escape") - goto ACCEPT; + if (ShouldSwallow(allowInput, ie)) continue; - if (ie.EventType == InputEventType.Press) continue; + if (ie.EventType == InputEventType.Press) + { + lastPress = ie; + //don't allow presses to directly complete binding except escape which we'll accept as a special perk + if (ie.LogicalButton.Button != "Escape") + continue; + } + else if (lastPress == null) continue; - ACCEPT: - Console.WriteLine("Bind Event: {0} ", ie); - - foreach (var kvp in LastState) - if (kvp.Value) - { - Console.WriteLine($"Unpressing {kvp.Key}"); - UnpressState[kvp.Key] = true; - } + Console.WriteLine("Bind Event: {0} ", lastPress); InputEvents.Clear(); - return ie.LogicalButton.ToString(); + return lastPress.LogicalButton.ToString(); } return null; @@ -545,16 +559,6 @@ namespace BizHawk.Client.EmuHawk //controls whether modifier keys will be ignored as key press events //this should be used by hotkey binders, but we may want modifier key events //to get triggered in the main form - public bool EnableIgnoreModifiers = false; - - //sets a key as unpressed for the binding system - public void BindUnpress(System.Windows.Forms.Keys key) - { - //only validated for Return - string keystr = key.ToString(); - UnpressState[keystr] = true; - LastState[keystr] = true; - } - + public volatile bool EnableIgnoreModifiers = false; } } diff --git a/BizHawk.Client.EmuHawk/Input/Keyboard.cs b/BizHawk.Client.EmuHawk/Input/Keyboard.cs index d42f5e6b6a..b7cda338cf 100644 --- a/BizHawk.Client.EmuHawk/Input/Keyboard.cs +++ b/BizHawk.Client.EmuHawk/Input/Keyboard.cs @@ -60,9 +60,9 @@ namespace BizHawk.Client.EmuHawk foreach (var e in events) { foreach (var k in e.PressedKeys) - _eventList.Add(new KeyEvent { Key = k, Pressed = true }); + _eventList.Add(new KeyEvent { Key = KeyboardMapping.Handle(k), Pressed = true }); foreach (var k in e.ReleasedKeys) - _eventList.Add(new KeyEvent { Key = k, Pressed = false }); + _eventList.Add(new KeyEvent { Key = KeyboardMapping.Handle(k), Pressed = false }); } } diff --git a/BizHawk.Client.EmuHawk/Input/KeyboardMapping.cs b/BizHawk.Client.EmuHawk/Input/KeyboardMapping.cs new file mode 100644 index 0000000000..4e73b5450f --- /dev/null +++ b/BizHawk.Client.EmuHawk/Input/KeyboardMapping.cs @@ -0,0 +1,416 @@ +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Windows.Forms; +using BizHawk.Client.Common; +using SlimDX.DirectInput; + +namespace BizHawk.Client.EmuHawk +{ + internal static class KeyboardMapping + { + [DllImport("user32.dll", CharSet = CharSet.Auto)] + private static extern uint MapVirtualKey(uint uCode, uint uMapType); + + private const uint MAPVK_VSC_TO_VK_EX = 0x03; + + public static Key Handle(Key key) + { + if (!Global.Config.HandleAlternateKeyboardLayouts) return key; + ScanCode inputScanCode = SlimDXScanCodeMap[(int)key]; + Keys virtualKey = (Keys)MapVirtualKey((uint)inputScanCode, MAPVK_VSC_TO_VK_EX); + ScanCode standardScanCode = GetStandardScanCode(virtualKey); + if (standardScanCode == 0) + standardScanCode = inputScanCode; + return ScanCodeToSlimDXKey[standardScanCode]; + } + + private static ScanCode GetStandardScanCode(Keys virtualKey) + { + switch (virtualKey) + { + case Keys.Escape: return ScanCode.Escape; + case Keys.D1: return ScanCode.D1; + case Keys.D2: return ScanCode.D2; + case Keys.D3: return ScanCode.D3; + case Keys.D4: return ScanCode.D4; + case Keys.D5: return ScanCode.D5; + case Keys.D6: return ScanCode.D6; + case Keys.D7: return ScanCode.D7; + case Keys.D8: return ScanCode.D8; + case Keys.D9: return ScanCode.D9; + case Keys.D0: return ScanCode.D0; + case Keys.OemMinus: return ScanCode.Minus; + case Keys.Oemplus: return ScanCode.Equals; + case Keys.Back: return ScanCode.Back; + case Keys.Tab: return ScanCode.Tab; + case Keys.Q: return ScanCode.Q; + case Keys.W: return ScanCode.W; + case Keys.E: return ScanCode.E; + case Keys.R: return ScanCode.R; + case Keys.T: return ScanCode.T; + case Keys.Y: return ScanCode.Y; + case Keys.U: return ScanCode.U; + case Keys.I: return ScanCode.I; + case Keys.O: return ScanCode.O; + case Keys.P: return ScanCode.P; + case Keys.OemOpenBrackets: return ScanCode.LBracket; + case Keys.OemCloseBrackets: return ScanCode.RBracket; + case Keys.Return: return ScanCode.Return; + case Keys.LControlKey: return ScanCode.LControl; + case Keys.A: return ScanCode.A; + case Keys.S: return ScanCode.S; + case Keys.D: return ScanCode.D; + case Keys.F: return ScanCode.F; + case Keys.G: return ScanCode.G; + case Keys.H: return ScanCode.H; + case Keys.J: return ScanCode.J; + case Keys.K: return ScanCode.K; + case Keys.L: return ScanCode.L; + case Keys.OemSemicolon: return ScanCode.Semicolon; + case Keys.OemQuotes: return ScanCode.Apostrophe; + case Keys.Oemtilde: return ScanCode.Grave; + case Keys.LShiftKey: return ScanCode.LShift; + case Keys.OemPipe: return ScanCode.Backslash; + case Keys.Z: return ScanCode.Z; + case Keys.X: return ScanCode.X; + case Keys.C: return ScanCode.C; + case Keys.V: return ScanCode.V; + case Keys.B: return ScanCode.B; + case Keys.N: return ScanCode.N; + case Keys.M: return ScanCode.M; + case Keys.Oemcomma: return ScanCode.Comma; + case Keys.OemPeriod: return ScanCode.Period; + case Keys.OemQuestion: return ScanCode.Slash; + case Keys.RShiftKey: return ScanCode.RShift; + case Keys.Multiply: return ScanCode.Multiply; + case Keys.LMenu: return ScanCode.LMenu; + case Keys.Space: return ScanCode.Space; + case Keys.Capital: return ScanCode.Capital; + case Keys.F1: return ScanCode.F1; + case Keys.F2: return ScanCode.F2; + case Keys.F3: return ScanCode.F3; + case Keys.F4: return ScanCode.F4; + case Keys.F5: return ScanCode.F5; + case Keys.F6: return ScanCode.F6; + case Keys.F7: return ScanCode.F7; + case Keys.F8: return ScanCode.F8; + case Keys.F9: return ScanCode.F9; + case Keys.F10: return ScanCode.F10; + case Keys.NumLock: return ScanCode.NumLock; + case Keys.Scroll: return ScanCode.Scroll; + case Keys.Subtract: return ScanCode.Subtract; + case Keys.Add: return ScanCode.Add; + case Keys.OemBackslash: return ScanCode.Oem_102; + case Keys.F11: return ScanCode.F11; + case Keys.F12: return ScanCode.F12; + case Keys.F13: return ScanCode.F13; + case Keys.F14: return ScanCode.F14; + case Keys.F15: return ScanCode.F15; + } + return 0; + } + + private enum ScanCode + { + Escape = 0x01, + D1 = 0x02, + D2 = 0x03, + D3 = 0x04, + D4 = 0x05, + D5 = 0x06, + D6 = 0x07, + D7 = 0x08, + D8 = 0x09, + D9 = 0x0A, + D0 = 0x0B, + Minus = 0x0C, + Equals = 0x0D, + Back = 0x0E, + Tab = 0x0F, + Q = 0x10, + W = 0x11, + E = 0x12, + R = 0x13, + T = 0x14, + Y = 0x15, + U = 0x16, + I = 0x17, + O = 0x18, + P = 0x19, + LBracket = 0x1A, + RBracket = 0x1B, + Return = 0x1C, + LControl = 0x1D, + A = 0x1E, + S = 0x1F, + D = 0x20, + F = 0x21, + G = 0x22, + H = 0x23, + J = 0x24, + K = 0x25, + L = 0x26, + Semicolon = 0x27, + Apostrophe = 0x28, + Grave = 0x29, + LShift = 0x2A, + Backslash = 0x2B, + Z = 0x2C, + X = 0x2D, + C = 0x2E, + V = 0x2F, + B = 0x30, + N = 0x31, + M = 0x32, + Comma = 0x33, + Period = 0x34, + Slash = 0x35, + RShift = 0x36, + Multiply = 0x37, + LMenu = 0x38, + Space = 0x39, + Capital = 0x3A, + F1 = 0x3B, + F2 = 0x3C, + F3 = 0x3D, + F4 = 0x3E, + F5 = 0x3F, + F6 = 0x40, + F7 = 0x41, + F8 = 0x42, + F9 = 0x43, + F10 = 0x44, + NumLock = 0x45, + Scroll = 0x46, + NumPad7 = 0x47, + NumPad8 = 0x48, + NumPad9 = 0x49, + Subtract = 0x4A, + NumPad4 = 0x4B, + NumPad5 = 0x4C, + NumPad6 = 0x4D, + Add = 0x4E, + NumPad1 = 0x4F, + NumPad2 = 0x50, + NumPad3 = 0x51, + NumPad0 = 0x52, + Decimal = 0x53, + Oem_102 = 0x56, + F11 = 0x57, + F12 = 0x58, + F13 = 0x64, + F14 = 0x65, + F15 = 0x66, + Kana = 0x70, + Abnt_C1 = 0x73, + Convert = 0x79, + NoConvert = 0x7B, + Yen = 0x7D, + Abnt_C2 = 0x7E, + NumPadEquals = 0x8D, + PrevTrack = 0x90, + AT = 0x91, + Colon = 0x92, + Underline = 0x93, + Kanji = 0x94, + Stop = 0x95, + AX = 0x96, + Unlabeled = 0x97, + NextTrack = 0x99, + NumPadEnter = 0x9C, + RControl = 0x9D, + Mute = 0xA0, + Calculator = 0xA1, + PlayPause = 0xA2, + MediaStop = 0xA4, + VolumeDown = 0xAE, + VolumeUp = 0xB0, + WebHome = 0xB2, + NumPadComma = 0xB3, + Divide = 0xB5, + SysRq = 0xB7, + RMenu = 0xB8, + Pause = 0xC5, + Home = 0xC7, + Up = 0xC8, + Prior = 0xC9, + Left = 0xCB, + Right = 0xCD, + End = 0xCF, + Down = 0xD0, + Next = 0xD1, + Insert = 0xD2, + Delete = 0xD3, + LWin = 0xDB, + RWin = 0xDC, + Apps = 0xDD, + Power = 0xDE, + Sleep = 0xDF, + Wake = 0xE3, + WebSearch = 0xE5, + WebFavorites = 0xE6, + WebRefresh = 0xE7, + WebStop = 0xE8, + WebForward = 0xE9, + WebBack = 0xEA, + MyComputer = 0xEB, + Mail = 0xEC, + MediaSelect = 0xED + } + + private static readonly ScanCode[] SlimDXScanCodeMap = new ScanCode[] + { + ScanCode.D0, // 0 + ScanCode.D1, // 1 + ScanCode.D2, // 2 + ScanCode.D3, // 3 + ScanCode.D4, // 4 + ScanCode.D5, // 5 + ScanCode.D6, // 6 + ScanCode.D7, // 7 + ScanCode.D8, // 8 + ScanCode.D9, // 9 + ScanCode.A, // 10 + ScanCode.B, // 11 + ScanCode.C, // 12 + ScanCode.D, // 13 + ScanCode.E, // 14 + ScanCode.F, // 15 + ScanCode.G, // 16 + ScanCode.H, // 17 + ScanCode.I, // 18 + ScanCode.J, // 19 + ScanCode.K, // 20 + ScanCode.L, // 21 + ScanCode.M, // 22 + ScanCode.N, // 23 + ScanCode.O, // 24 + ScanCode.P, // 25 + ScanCode.Q, // 26 + ScanCode.R, // 27 + ScanCode.S, // 28 + ScanCode.T, // 29 + ScanCode.U, // 30 + ScanCode.V, // 31 + ScanCode.W, // 32 + ScanCode.X, // 33 + ScanCode.Y, // 34 + ScanCode.Z, // 35 + ScanCode.Abnt_C1, // 36 + ScanCode.Abnt_C2, // 37 + ScanCode.Apostrophe, // 38 + ScanCode.Apps, // 39 + ScanCode.AT, // 40 + ScanCode.AX, // 41 + ScanCode.Back, // 42 + ScanCode.Backslash, // 43 + ScanCode.Calculator, // 44 + ScanCode.Capital, // 45 + ScanCode.Colon, // 46 + ScanCode.Comma, // 47 + ScanCode.Convert, // 48 + ScanCode.Delete, // 49 + ScanCode.Down, // 50 + ScanCode.End, // 51 + ScanCode.Equals, // 52 + ScanCode.Escape, // 53 + ScanCode.F1, // 54 + ScanCode.F2, // 55 + ScanCode.F3, // 56 + ScanCode.F4, // 57 + ScanCode.F5, // 58 + ScanCode.F6, // 59 + ScanCode.F7, // 60 + ScanCode.F8, // 61 + ScanCode.F9, // 62 + ScanCode.F10, // 63 + ScanCode.F11, // 64 + ScanCode.F12, // 65 + ScanCode.F13, // 66 + ScanCode.F14, // 67 + ScanCode.F15, // 68 + ScanCode.Grave, // 69 + ScanCode.Home, // 70 + ScanCode.Insert, // 71 + ScanCode.Kana, // 72 + ScanCode.Kanji, // 73 + ScanCode.LBracket, // 74 + ScanCode.LControl, // 75 + ScanCode.Left, // 76 + ScanCode.LMenu, // 77 + ScanCode.LShift, // 78 + ScanCode.LWin, // 79 + ScanCode.Mail, // 80 + ScanCode.MediaSelect, // 81 + ScanCode.MediaStop, // 82 + ScanCode.Minus, // 83 + ScanCode.Mute, // 84 + ScanCode.MyComputer, // 85 + ScanCode.NextTrack, // 86 + ScanCode.NoConvert, // 87 + ScanCode.NumLock, // 88 + ScanCode.NumPad0, // 89 + ScanCode.NumPad1, // 90 + ScanCode.NumPad2, // 91 + ScanCode.NumPad3, // 92 + ScanCode.NumPad4, // 93 + ScanCode.NumPad5, // 94 + ScanCode.NumPad6, // 95 + ScanCode.NumPad7, // 96 + ScanCode.NumPad8, // 97 + ScanCode.NumPad9, // 98 + ScanCode.NumPadComma, // 99 + ScanCode.NumPadEnter, // 100 + ScanCode.NumPadEquals, // 101 + ScanCode.Subtract, // 102 + ScanCode.Decimal, // 103 + ScanCode.Add, // 104 + ScanCode.Divide, // 105 + ScanCode.Multiply, // 106 + ScanCode.Oem_102, // 107 + ScanCode.Next, // 108 + ScanCode.Prior, // 109 + ScanCode.Pause, // 110 + ScanCode.Period, // 111 + ScanCode.PlayPause, // 112 + ScanCode.Power, // 113 + ScanCode.PrevTrack, // 114 + ScanCode.RBracket, // 115 + ScanCode.RControl, // 116 + ScanCode.Return, // 117 + ScanCode.Right, // 118 + ScanCode.RMenu, // 119 + ScanCode.RShift, // 120 + ScanCode.RWin, // 121 + ScanCode.Scroll, // 122 + ScanCode.Semicolon, // 123 + ScanCode.Slash, // 124 + ScanCode.Sleep, // 125 + ScanCode.Space, // 126 + ScanCode.Stop, // 127 + ScanCode.SysRq, // 128 + ScanCode.Tab, // 129 + ScanCode.Underline, // 130 + ScanCode.Unlabeled, // 131 + ScanCode.Up, // 132 + ScanCode.VolumeDown, // 133 + ScanCode.VolumeUp, // 134 + ScanCode.Wake, // 135 + ScanCode.WebBack, // 136 + ScanCode.WebFavorites, // 137 + ScanCode.WebForward, // 138 + ScanCode.WebHome, // 139 + ScanCode.WebRefresh, // 140 + ScanCode.WebSearch, // 141 + ScanCode.WebStop, // 142 + ScanCode.Yen, // 143 + 0 // 144 + }; + + private static readonly Dictionary ScanCodeToSlimDXKey = + SlimDXScanCodeMap + .Select((n, i) => new { Value = n, Index = i }) + .ToDictionary(n => n.Value, n => (Key)n.Index); + } +} diff --git a/BizHawk.Client.EmuHawk/LogWindow.Designer.cs b/BizHawk.Client.EmuHawk/LogWindow.Designer.cs index fe03b76c7a..1b681d0bf9 100644 --- a/BizHawk.Client.EmuHawk/LogWindow.Designer.cs +++ b/BizHawk.Client.EmuHawk/LogWindow.Designer.cs @@ -1,4 +1,6 @@ -namespace BizHawk.Client.EmuHawk +using System.Windows.Forms; + +namespace BizHawk.Client.EmuHawk { partial class LogWindow { @@ -34,7 +36,7 @@ this.buttonCopy = new System.Windows.Forms.Button(); this.buttonCopyAll = new System.Windows.Forms.Button(); this.AddToGameDbBtn = new System.Windows.Forms.Button(); - this.virtualListView1 = new BizHawk.Client.EmuHawk.VirtualListView(); + this.virtualListView1 = new System.Windows.Forms.ListView(); this.columnHeader1 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); this.tableLayoutPanel1.SuspendLayout(); this.SuspendLayout(); @@ -118,23 +120,20 @@ // // virtualListView1 // - this.virtualListView1.BlazingFast = false; this.virtualListView1.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { this.columnHeader1}); this.virtualListView1.Dock = System.Windows.Forms.DockStyle.Fill; this.virtualListView1.Font = new System.Drawing.Font("Courier New", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.virtualListView1.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.None; - this.virtualListView1.ItemCount = 0; + this.virtualListView1.VirtualListSize = 0; this.virtualListView1.Location = new System.Drawing.Point(0, 0); this.virtualListView1.Name = "virtualListView1"; - this.virtualListView1.SelectAllInProgress = false; - this.virtualListView1.selectedItem = -1; this.virtualListView1.Size = new System.Drawing.Size(675, 367); this.virtualListView1.TabIndex = 8; this.virtualListView1.UseCompatibleStateImageBehavior = false; this.virtualListView1.View = System.Windows.Forms.View.Details; this.virtualListView1.VirtualMode = true; - this.virtualListView1.QueryItemText += new BizHawk.Client.EmuHawk.QueryItemTextHandler(this.virtualListView1_QueryItemText); + this.virtualListView1.RetrieveVirtualItem += new RetrieveVirtualItemEventHandler(this.virtualListView1_QueryItemText); this.virtualListView1.ClientSizeChanged += new System.EventHandler(this.virtualListView1_ClientSizeChanged); this.virtualListView1.KeyDown += new System.Windows.Forms.KeyEventHandler(this.virtualListView1_KeyDown); // @@ -163,7 +162,7 @@ private System.Windows.Forms.Button btnClose; private System.Windows.Forms.Button btnClear; private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1; - private VirtualListView virtualListView1; + private System.Windows.Forms.ListView virtualListView1; private System.Windows.Forms.ColumnHeader columnHeader1; private System.Windows.Forms.Button buttonCopy; private System.Windows.Forms.Button buttonCopyAll; diff --git a/BizHawk.Client.EmuHawk/LogWindow.cs b/BizHawk.Client.EmuHawk/LogWindow.cs index af5d0d8968..212ec849d2 100644 --- a/BizHawk.Client.EmuHawk/LogWindow.cs +++ b/BizHawk.Client.EmuHawk/LogWindow.cs @@ -5,7 +5,6 @@ using System.IO; using System.Text; using System.Windows.Forms; -using BizHawk.Common.ReflectionExtensions; using BizHawk.Emulation.Common; using BizHawk.Emulation.Common.IEmulatorExtensions; using BizHawk.Client.Common; @@ -40,7 +39,7 @@ namespace BizHawk.Client.EmuHawk var ss = report.Split('\n'); foreach (var s in ss) dlg.Lines.Add(s.TrimEnd('\r')); - dlg.virtualListView1.ItemCount = ss.Length; + dlg.virtualListView1.VirtualListSize = ss.Length; dlg.Text = title; dlg.btnClear.Visible = false; dlg.ShowDialog(parent); @@ -55,7 +54,7 @@ namespace BizHawk.Client.EmuHawk if (!string.IsNullOrWhiteSpace(s)) { Lines.Add(s.TrimEnd('\r')); - virtualListView1.ItemCount++; + virtualListView1.VirtualListSize++; } } } @@ -63,7 +62,7 @@ namespace BizHawk.Client.EmuHawk private void btnClear_Click(object sender, EventArgs e) { Lines.Clear(); - virtualListView1.ItemCount = 0; + virtualListView1.VirtualListSize = 0; virtualListView1.SelectedIndices.Clear(); } @@ -99,9 +98,9 @@ namespace BizHawk.Client.EmuHawk } } - private void virtualListView1_QueryItemText(int item, int subItem, out string text) + private void virtualListView1_QueryItemText(object sender, RetrieveVirtualItemEventArgs e) { - text = Lines[item]; + e.Item = new ListViewItem(Lines[e.ItemIndex]); } private void virtualListView1_ClientSizeChanged(object sender, EventArgs e) diff --git a/BizHawk.Client.EmuHawk/MainForm.Designer.cs b/BizHawk.Client.EmuHawk/MainForm.Designer.cs index 83c8c0544a..af23e02304 100644 --- a/BizHawk.Client.EmuHawk/MainForm.Designer.cs +++ b/BizHawk.Client.EmuHawk/MainForm.Designer.cs @@ -234,7 +234,6 @@ this.dummyExternalTool = new System.Windows.Forms.ToolStripMenuItem(); this.batchRunnerToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.ExperimentalToolsSubMenu = new System.Windows.Forms.ToolStripMenuItem(); - this.AutoHawkMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.NewHexEditorMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.NESSubMenu = new System.Windows.Forms.ToolStripMenuItem(); this.coreToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); @@ -496,42 +495,42 @@ // this.MainformMenu.ClickThrough = true; this.MainformMenu.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.FileSubMenu, - this.EmulationSubMenu, - this.ViewSubMenu, - this.ConfigSubMenu, - this.ToolsSubMenu, - this.NESSubMenu, - this.PCESubMenu, - this.SMSSubMenu, - this.TI83SubMenu, - this.AtariSubMenu, - this.A7800SubMenu, - this.GBSubMenu, - this.GBASubMenu, - this.PSXSubMenu, - this.SNESSubMenu, - this.ColecoSubMenu, - this.N64SubMenu, - this.SaturnSubMenu, - this.DGBSubMenu, - this.DGBHawkSubMenu, + this.FileSubMenu, + this.EmulationSubMenu, + this.ViewSubMenu, + this.ConfigSubMenu, + this.ToolsSubMenu, + this.NESSubMenu, + this.PCESubMenu, + this.SMSSubMenu, + this.TI83SubMenu, + this.AtariSubMenu, + this.A7800SubMenu, + this.GBSubMenu, + this.GBASubMenu, + this.PSXSubMenu, + this.SNESSubMenu, + this.ColecoSubMenu, + this.N64SubMenu, + this.SaturnSubMenu, + this.DGBSubMenu, + this.DGBHawkSubMenu, this.GB3xSubMenu, this.GB4xSubMenu, this.GGLSubMenu, - this.GenesisSubMenu, - this.wonderSwanToolStripMenuItem, - this.AppleSubMenu, - this.C64SubMenu, - this.IntvSubMenu, - this.sNESToolStripMenuItem, - this.pCFXToolStripMenuItem, - this.virtualBoyToolStripMenuItem, - this.neoGeoPocketToolStripMenuItem, - this.zXSpectrumToolStripMenuItem, + this.GenesisSubMenu, + this.wonderSwanToolStripMenuItem, + this.AppleSubMenu, + this.C64SubMenu, + this.IntvSubMenu, + this.sNESToolStripMenuItem, + this.pCFXToolStripMenuItem, + this.virtualBoyToolStripMenuItem, + this.neoGeoPocketToolStripMenuItem, + this.zXSpectrumToolStripMenuItem, this.VectrexSubMenu, - this.HelpSubMenu, - this.amstradCPCToolStripMenuItem}); + this.HelpSubMenu, + this.amstradCPCToolStripMenuItem}); this.MainformMenu.LayoutStyle = System.Windows.Forms.ToolStripLayoutStyle.Flow; this.MainformMenu.Location = new System.Drawing.Point(0, 0); this.MainformMenu.Name = "MainformMenu"; @@ -545,21 +544,21 @@ // FileSubMenu // this.FileSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.OpenRomMenuItem, - this.RecentRomSubMenu, - this.OpenAdvancedMenuItem, - this.CloseRomMenuItem, - this.toolStripMenuItem1, - this.SaveStateSubMenu, - this.LoadStateSubMenu, - this.SaveSlotSubMenu, - this.SaveRAMSubMenu, - this.toolStripMenuItem2, - this.MovieSubMenu, - this.AVSubMenu, - this.ScreenshotSubMenu, - this.toolStripSeparator4, - this.ExitMenuItem}); + this.OpenRomMenuItem, + this.RecentRomSubMenu, + this.OpenAdvancedMenuItem, + this.CloseRomMenuItem, + this.toolStripMenuItem1, + this.SaveStateSubMenu, + this.LoadStateSubMenu, + this.SaveSlotSubMenu, + this.SaveRAMSubMenu, + this.toolStripMenuItem2, + this.MovieSubMenu, + this.AVSubMenu, + this.ScreenshotSubMenu, + this.toolStripSeparator4, + this.ExitMenuItem}); this.FileSubMenu.Name = "FileSubMenu"; this.FileSubMenu.Size = new System.Drawing.Size(37, 19); this.FileSubMenu.Text = "&File"; @@ -576,7 +575,7 @@ // RecentRomSubMenu // this.RecentRomSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.toolStripSeparator3}); + this.toolStripSeparator3}); this.RecentRomSubMenu.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.Recent; this.RecentRomSubMenu.Name = "RecentRomSubMenu"; this.RecentRomSubMenu.Size = new System.Drawing.Size(159, 22); @@ -611,18 +610,18 @@ // SaveStateSubMenu // this.SaveStateSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.SaveState1MenuItem, - this.SaveState2MenuItem, - this.SaveState3MenuItem, - this.SaveState4MenuItem, - this.SaveState5MenuItem, - this.SaveState6MenuItem, - this.SaveState7MenuItem, - this.SaveState8MenuItem, - this.SaveState9MenuItem, - this.SaveState0MenuItem, - this.toolStripSeparator6, - this.SaveNamedStateMenuItem}); + this.SaveState1MenuItem, + this.SaveState2MenuItem, + this.SaveState3MenuItem, + this.SaveState4MenuItem, + this.SaveState5MenuItem, + this.SaveState6MenuItem, + this.SaveState7MenuItem, + this.SaveState8MenuItem, + this.SaveState9MenuItem, + this.SaveState0MenuItem, + this.toolStripSeparator6, + this.SaveNamedStateMenuItem}); this.SaveStateSubMenu.Name = "SaveStateSubMenu"; this.SaveStateSubMenu.Size = new System.Drawing.Size(159, 22); this.SaveStateSubMenu.Text = "&Save State"; @@ -713,20 +712,20 @@ // LoadStateSubMenu // this.LoadStateSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.LoadState1MenuItem, - this.LoadState2MenuItem, - this.LoadState3MenuItem, - this.LoadState4MenuItem, - this.LoadState5MenuItem, - this.LoadState6MenuItem, - this.LoadState7MenuItem, - this.LoadState8MenuItem, - this.LoadState9MenuItem, - this.LoadState0MenuItem, - this.toolStripSeparator7, - this.LoadNamedStateMenuItem, - this.toolStripSeparator21, - this.AutoloadLastSlotMenuItem}); + this.LoadState1MenuItem, + this.LoadState2MenuItem, + this.LoadState3MenuItem, + this.LoadState4MenuItem, + this.LoadState5MenuItem, + this.LoadState6MenuItem, + this.LoadState7MenuItem, + this.LoadState8MenuItem, + this.LoadState9MenuItem, + this.LoadState0MenuItem, + this.toolStripSeparator7, + this.LoadNamedStateMenuItem, + this.toolStripSeparator21, + this.AutoloadLastSlotMenuItem}); this.LoadStateSubMenu.Name = "LoadStateSubMenu"; this.LoadStateSubMenu.Size = new System.Drawing.Size(159, 22); this.LoadStateSubMenu.Text = "&Load State"; @@ -829,21 +828,21 @@ // SaveSlotSubMenu // this.SaveSlotSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.SelectSlot0MenuItem, - this.SelectSlot1MenuItem, - this.SelectSlot2MenuItem, - this.SelectSlot3MenuItem, - this.SelectSlot4MenuItem, - this.SelectSlot5MenuItem, - this.SelectSlot6MenuItem, - this.SelectSlot7MenuItem, - this.SelectSlot8MenuItem, - this.SelectSlot9MenuItem, - this.PreviousSlotMenuItem, - this.NextSlotMenuItem, - this.toolStripSeparator5, - this.SaveToCurrentSlotMenuItem, - this.LoadCurrentSlotMenuItem}); + this.SelectSlot0MenuItem, + this.SelectSlot1MenuItem, + this.SelectSlot2MenuItem, + this.SelectSlot3MenuItem, + this.SelectSlot4MenuItem, + this.SelectSlot5MenuItem, + this.SelectSlot6MenuItem, + this.SelectSlot7MenuItem, + this.SelectSlot8MenuItem, + this.SelectSlot9MenuItem, + this.PreviousSlotMenuItem, + this.NextSlotMenuItem, + this.toolStripSeparator5, + this.SaveToCurrentSlotMenuItem, + this.LoadCurrentSlotMenuItem}); this.SaveSlotSubMenu.Name = "SaveSlotSubMenu"; this.SaveSlotSubMenu.Size = new System.Drawing.Size(159, 22); this.SaveSlotSubMenu.Text = "Save S&lot"; @@ -957,7 +956,7 @@ // SaveRAMSubMenu // this.SaveRAMSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.FlushSaveRAMMenuItem}); + this.FlushSaveRAMMenuItem}); this.SaveRAMSubMenu.Name = "SaveRAMSubMenu"; this.SaveRAMSubMenu.Size = new System.Drawing.Size(159, 22); this.SaveRAMSubMenu.Text = "Save &RAM"; @@ -978,21 +977,21 @@ // MovieSubMenu // this.MovieSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.ReadonlyMenuItem, - this.toolStripSeparator15, - this.RecentMovieSubMenu, - this.RecordMovieMenuItem, - this.PlayMovieMenuItem, - this.StopMovieMenuItem, - this.PlayFromBeginningMenuItem, - this.ImportMoviesMenuItem, - this.SaveMovieMenuItem, - this.SaveMovieAsMenuItem, - this.StopMovieWithoutSavingMenuItem, - this.toolStripSeparator14, - this.AutomaticallyBackupMoviesMenuItem, - this.FullMovieLoadstatesMenuItem, - this.MovieEndSubMenu}); + this.ReadonlyMenuItem, + this.toolStripSeparator15, + this.RecentMovieSubMenu, + this.RecordMovieMenuItem, + this.PlayMovieMenuItem, + this.StopMovieMenuItem, + this.PlayFromBeginningMenuItem, + this.ImportMoviesMenuItem, + this.SaveMovieMenuItem, + this.SaveMovieAsMenuItem, + this.StopMovieWithoutSavingMenuItem, + this.toolStripSeparator14, + this.AutomaticallyBackupMoviesMenuItem, + this.FullMovieLoadstatesMenuItem, + this.MovieEndSubMenu}); this.MovieSubMenu.Name = "MovieSubMenu"; this.MovieSubMenu.Size = new System.Drawing.Size(159, 22); this.MovieSubMenu.Text = "&Movie"; @@ -1014,7 +1013,7 @@ // RecentMovieSubMenu // this.RecentMovieSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.toolStripSeparator16}); + this.toolStripSeparator16}); this.RecentMovieSubMenu.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.Recent; this.RecentMovieSubMenu.Name = "RecentMovieSubMenu"; this.RecentMovieSubMenu.Size = new System.Drawing.Size(231, 22); @@ -1112,10 +1111,10 @@ // MovieEndSubMenu // this.MovieEndSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.MovieEndFinishMenuItem, - this.MovieEndRecordMenuItem, - this.MovieEndStopMenuItem, - this.MovieEndPauseMenuItem}); + this.MovieEndFinishMenuItem, + this.MovieEndRecordMenuItem, + this.MovieEndStopMenuItem, + this.MovieEndPauseMenuItem}); this.MovieEndSubMenu.Name = "MovieEndSubMenu"; this.MovieEndSubMenu.Size = new System.Drawing.Size(231, 22); this.MovieEndSubMenu.Text = "On Movie End"; @@ -1152,12 +1151,12 @@ // AVSubMenu // this.AVSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.RecordAVMenuItem, - this.ConfigAndRecordAVMenuItem, - this.StopAVIMenuItem, - this.toolStripSeparator19, - this.CaptureOSDMenuItem, - this.SynclessRecordingMenuItem}); + this.RecordAVMenuItem, + this.ConfigAndRecordAVMenuItem, + this.StopAVIMenuItem, + this.toolStripSeparator19, + this.CaptureOSDMenuItem, + this.SynclessRecordingMenuItem}); this.AVSubMenu.Name = "AVSubMenu"; this.AVSubMenu.Size = new System.Drawing.Size(159, 22); this.AVSubMenu.Text = "&AVI/WAV"; @@ -1209,12 +1208,12 @@ // ScreenshotSubMenu // this.ScreenshotSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.ScreenshotMenuItem, - this.ScreenshotAsMenuItem, - this.ScreenshotClipboardMenuItem, - this.ScreenshotClientClipboardMenuItem, - this.toolStripSeparator20, - this.ScreenshotCaptureOSDMenuItem1}); + this.ScreenshotMenuItem, + this.ScreenshotAsMenuItem, + this.ScreenshotClipboardMenuItem, + this.ScreenshotClientClipboardMenuItem, + this.toolStripSeparator20, + this.ScreenshotCaptureOSDMenuItem1}); this.ScreenshotSubMenu.Name = "ScreenshotSubMenu"; this.ScreenshotSubMenu.Size = new System.Drawing.Size(159, 22); this.ScreenshotSubMenu.Text = "Scree&nshot"; @@ -1277,11 +1276,11 @@ // EmulationSubMenu // this.EmulationSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.PauseMenuItem, - this.RebootCoreMenuItem, - this.toolStripSeparator1, - this.SoftResetMenuItem, - this.HardResetMenuItem}); + this.PauseMenuItem, + this.RebootCoreMenuItem, + this.toolStripSeparator1, + this.SoftResetMenuItem, + this.HardResetMenuItem}); this.EmulationSubMenu.Name = "EmulationSubMenu"; this.EmulationSubMenu.Size = new System.Drawing.Size(73, 19); this.EmulationSubMenu.Text = "&Emulation"; @@ -1325,19 +1324,19 @@ // ViewSubMenu // this.ViewSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.WindowSizeSubMenu, - this.SwitchToFullscreenMenuItem, - this.toolStripSeparator2, - this.DisplayFPSMenuItem, - this.DisplayFrameCounterMenuItem, - this.DisplayLagCounterMenuItem, - this.DisplayInputMenuItem, - this.DisplayRerecordCountMenuItem, - this.DisplaySubtitlesMenuItem, - this.toolStripMenuItem4, - this.DisplayStatusBarMenuItem, - this.DisplayMessagesMenuItem, - this.DisplayLogWindowMenuItem}); + this.WindowSizeSubMenu, + this.SwitchToFullscreenMenuItem, + this.toolStripSeparator2, + this.DisplayFPSMenuItem, + this.DisplayFrameCounterMenuItem, + this.DisplayLagCounterMenuItem, + this.DisplayInputMenuItem, + this.DisplayRerecordCountMenuItem, + this.DisplaySubtitlesMenuItem, + this.toolStripMenuItem4, + this.DisplayStatusBarMenuItem, + this.DisplayMessagesMenuItem, + this.DisplayLogWindowMenuItem}); this.ViewSubMenu.Name = "ViewSubMenu"; this.ViewSubMenu.Size = new System.Drawing.Size(44, 19); this.ViewSubMenu.Text = "&View"; @@ -1346,12 +1345,12 @@ // WindowSizeSubMenu // this.WindowSizeSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.x1MenuItem, - this.x2MenuItem, - this.x3MenuItem, - this.x4MenuItem, - this.x5MenuItem, - this.mzMenuItem}); + this.x1MenuItem, + this.x2MenuItem, + this.x3MenuItem, + this.x4MenuItem, + this.x5MenuItem, + this.mzMenuItem}); this.WindowSizeSubMenu.Name = "WindowSizeSubMenu"; this.WindowSizeSubMenu.Size = new System.Drawing.Size(198, 22); this.WindowSizeSubMenu.Text = "&Window Size"; @@ -1483,27 +1482,27 @@ // ConfigSubMenu // this.ConfigSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.ControllersMenuItem, - this.HotkeysMenuItem, - this.DisplayConfigMenuItem, - this.SoundMenuItem, - this.PathsMenuItem, - this.FirmwaresMenuItem, - this.MessagesMenuItem, - this.AutofireMenuItem, - this.RewindOptionsMenuItem, - this.extensionsToolStripMenuItem, - this.ClientOptionsMenuItem, - this.ProfilesMenuItem, - this.toolStripSeparator9, - this.SpeedSkipSubMenu, - this.KeyPrioritySubMenu, - this.CoresSubMenu, - this.toolStripSeparator10, - this.SaveConfigMenuItem, - this.SaveConfigAsMenuItem, - this.LoadConfigMenuItem, - this.LoadConfigFromMenuItem}); + this.ControllersMenuItem, + this.HotkeysMenuItem, + this.DisplayConfigMenuItem, + this.SoundMenuItem, + this.PathsMenuItem, + this.FirmwaresMenuItem, + this.MessagesMenuItem, + this.AutofireMenuItem, + this.RewindOptionsMenuItem, + this.extensionsToolStripMenuItem, + this.ClientOptionsMenuItem, + this.ProfilesMenuItem, + this.toolStripSeparator9, + this.SpeedSkipSubMenu, + this.KeyPrioritySubMenu, + this.CoresSubMenu, + this.toolStripSeparator10, + this.SaveConfigMenuItem, + this.SaveConfigAsMenuItem, + this.LoadConfigMenuItem, + this.LoadConfigFromMenuItem}); this.ConfigSubMenu.Name = "ConfigSubMenu"; this.ConfigSubMenu.Size = new System.Drawing.Size(55, 19); this.ConfigSubMenu.Text = "&Config"; @@ -1611,23 +1610,23 @@ // SpeedSkipSubMenu // this.SpeedSkipSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.ClockThrottleMenuItem, - this.AudioThrottleMenuItem, - this.VsyncThrottleMenuItem, - this.toolStripSeparator27, - this.VsyncEnabledMenuItem, - this.toolStripMenuItem3, - this.miUnthrottled, - this.MinimizeSkippingMenuItem, - this.NeverSkipMenuItem, - this.toolStripMenuItem17, - this.toolStripMenuItem5, - this.Speed50MenuItem, - this.Speed75MenuItem, - this.Speed100MenuItem, - this.Speed150MenuItem, - this.Speed200MenuItem, - this.Speed400MenuItem}); + this.ClockThrottleMenuItem, + this.AudioThrottleMenuItem, + this.VsyncThrottleMenuItem, + this.toolStripSeparator27, + this.VsyncEnabledMenuItem, + this.toolStripMenuItem3, + this.miUnthrottled, + this.MinimizeSkippingMenuItem, + this.NeverSkipMenuItem, + this.toolStripMenuItem17, + this.toolStripMenuItem5, + this.Speed50MenuItem, + this.Speed75MenuItem, + this.Speed100MenuItem, + this.Speed150MenuItem, + this.Speed200MenuItem, + this.Speed400MenuItem}); this.SpeedSkipSubMenu.Name = "SpeedSkipSubMenu"; this.SpeedSkipSubMenu.Size = new System.Drawing.Size(180, 22); this.SpeedSkipSubMenu.Text = "Speed/Skip"; @@ -1695,15 +1694,15 @@ // toolStripMenuItem17 // this.toolStripMenuItem17.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.Frameskip1MenuItem, - this.Frameskip2MenuItem, - this.Frameskip3MenuItem, - this.Frameskip4MenuItem, - this.Frameskip5MenuItem, - this.Frameskip6MenuItem, - this.Frameskip7MenuItem, - this.Frameskip8MenuItem, - this.Frameskip9MenuItem}); + this.Frameskip1MenuItem, + this.Frameskip2MenuItem, + this.Frameskip3MenuItem, + this.Frameskip4MenuItem, + this.Frameskip5MenuItem, + this.Frameskip6MenuItem, + this.Frameskip7MenuItem, + this.Frameskip8MenuItem, + this.Frameskip9MenuItem}); this.toolStripMenuItem17.Name = "toolStripMenuItem17"; this.toolStripMenuItem17.Size = new System.Drawing.Size(202, 22); this.toolStripMenuItem17.Text = "Skip 1..9"; @@ -1821,9 +1820,9 @@ // KeyPrioritySubMenu // this.KeyPrioritySubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.BothHkAndControllerMenuItem, - this.InputOverHkMenuItem, - this.HkOverInputMenuItem}); + this.BothHkAndControllerMenuItem, + this.InputOverHkMenuItem, + this.HkOverInputMenuItem}); this.KeyPrioritySubMenu.Name = "KeyPrioritySubMenu"; this.KeyPrioritySubMenu.Size = new System.Drawing.Size(180, 22); this.KeyPrioritySubMenu.Text = "Key Priority"; @@ -1853,17 +1852,17 @@ // CoresSubMenu // this.CoresSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.NesCoreSubMenu, - this.CoreSNESSubMenu, - this.GbaCoreSubMenu, - this.SGBCoreSubmenu, - this.GBCoreSubmenu, - this.GBInSGBMenuItem, - this.toolStripMenuItem16, - this.allowGameDBCoreOverridesToolStripMenuItem, - this.toolStripSeparator8, - this.N64VideoPluginSettingsMenuItem, - this.setLibretroCoreToolStripMenuItem}); + this.NesCoreSubMenu, + this.CoreSNESSubMenu, + this.GbaCoreSubMenu, + this.SGBCoreSubmenu, + this.GBCoreSubmenu, + this.GBInSGBMenuItem, + this.toolStripMenuItem16, + this.allowGameDBCoreOverridesToolStripMenuItem, + this.toolStripSeparator8, + this.N64VideoPluginSettingsMenuItem, + this.setLibretroCoreToolStripMenuItem}); this.CoresSubMenu.Name = "CoresSubMenu"; this.CoresSubMenu.Size = new System.Drawing.Size(180, 22); this.CoresSubMenu.Text = "Cores"; @@ -1872,10 +1871,10 @@ // NesCoreSubMenu // this.NesCoreSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.QuicknesCoreMenuItem, - this.NesCoreMenuItem, - this.toolStripSeparator38, - this.SubNesHawkMenuItem}); + this.QuicknesCoreMenuItem, + this.NesCoreMenuItem, + this.toolStripSeparator38, + this.SubNesHawkMenuItem}); this.NesCoreSubMenu.Name = "NesCoreSubMenu"; this.NesCoreSubMenu.Size = new System.Drawing.Size(239, 22); this.NesCoreSubMenu.Text = "NES"; @@ -1910,8 +1909,8 @@ // CoreSNESSubMenu // this.CoreSNESSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.Coresnes9xMenuItem, - this.CorebsnesMenuItem}); + this.Coresnes9xMenuItem, + this.CorebsnesMenuItem}); this.CoreSNESSubMenu.Name = "CoreSNESSubMenu"; this.CoreSNESSubMenu.Size = new System.Drawing.Size(239, 22); this.CoreSNESSubMenu.Text = "SNES"; @@ -1934,8 +1933,8 @@ // GbaCoreSubMenu // this.GbaCoreSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.VbaNextCoreMenuItem, - this.MgbaCoreMenuItem}); + this.VbaNextCoreMenuItem, + this.MgbaCoreMenuItem}); this.GbaCoreSubMenu.Name = "GbaCoreSubMenu"; this.GbaCoreSubMenu.Size = new System.Drawing.Size(239, 22); this.GbaCoreSubMenu.Text = "GBA"; @@ -1958,8 +1957,8 @@ // SGBCoreSubmenu // this.SGBCoreSubmenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.SgbBsnesMenuItem, - this.SgbSameBoyMenuItem}); + this.SgbBsnesMenuItem, + this.SgbSameBoyMenuItem}); this.SGBCoreSubmenu.Name = "SGBCoreSubmenu"; this.SGBCoreSubmenu.Size = new System.Drawing.Size(239, 22); this.SGBCoreSubmenu.Text = "SGB"; @@ -1982,8 +1981,8 @@ // GBCoreSubmenu // this.GBCoreSubmenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.GBGambatteMenuItem, - this.GBGBHawkMenuItem}); + this.GBGambatteMenuItem, + this.GBGBHawkMenuItem}); this.GBCoreSubmenu.Name = "GBCoreSubmenu"; this.GBCoreSubmenu.Size = new System.Drawing.Size(239, 22); this.GBCoreSubmenu.Text = "GB"; @@ -2080,27 +2079,27 @@ // ToolsSubMenu // this.ToolsSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.ToolBoxMenuItem, - this.toolStripSeparator12, - this.RamWatchMenuItem, - this.RamSearchMenuItem, - this.LuaConsoleMenuItem, - this.TAStudioMenuItem, - this.HexEditorMenuItem, - this.TraceLoggerMenuItem, - this.DebuggerMenuItem, - this.CodeDataLoggerMenuItem, - this.MacroToolMenuItem, - this.VirtualPadMenuItem, - this.BasicBotMenuItem, - this.toolStripSeparator11, - this.CheatsMenuItem, - this.gameSharkConverterToolStripMenuItem, - this.toolStripSeparator29, - this.MultiDiskBundlerFileMenuItem, - this.externalToolToolStripMenuItem, - this.batchRunnerToolStripMenuItem, - this.ExperimentalToolsSubMenu}); + this.ToolBoxMenuItem, + this.toolStripSeparator12, + this.RamWatchMenuItem, + this.RamSearchMenuItem, + this.LuaConsoleMenuItem, + this.TAStudioMenuItem, + this.HexEditorMenuItem, + this.TraceLoggerMenuItem, + this.DebuggerMenuItem, + this.CodeDataLoggerMenuItem, + this.MacroToolMenuItem, + this.VirtualPadMenuItem, + this.BasicBotMenuItem, + this.toolStripSeparator11, + this.CheatsMenuItem, + this.gameSharkConverterToolStripMenuItem, + this.toolStripSeparator29, + this.MultiDiskBundlerFileMenuItem, + this.externalToolToolStripMenuItem, + this.batchRunnerToolStripMenuItem, + this.ExperimentalToolsSubMenu}); this.ToolsSubMenu.Name = "ToolsSubMenu"; this.ToolsSubMenu.Size = new System.Drawing.Size(47, 19); this.ToolsSubMenu.Text = "&Tools"; @@ -2242,7 +2241,7 @@ // externalToolToolStripMenuItem // this.externalToolToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.dummyExternalTool}); + this.dummyExternalTool}); this.externalToolToolStripMenuItem.Name = "externalToolToolStripMenuItem"; this.externalToolToolStripMenuItem.Size = new System.Drawing.Size(191, 22); this.externalToolToolStripMenuItem.Text = "External Tool"; @@ -2265,20 +2264,12 @@ // ExperimentalToolsSubMenu // this.ExperimentalToolsSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.AutoHawkMenuItem, - this.NewHexEditorMenuItem}); + this.NewHexEditorMenuItem}); this.ExperimentalToolsSubMenu.Name = "ExperimentalToolsSubMenu"; this.ExperimentalToolsSubMenu.Size = new System.Drawing.Size(191, 22); this.ExperimentalToolsSubMenu.Text = "Experimental Tools"; this.ExperimentalToolsSubMenu.DropDownOpened += new System.EventHandler(this.ExperimentalToolsSubMenu_DropDownOpened); // - // AutoHawkMenuItem - // - this.AutoHawkMenuItem.Name = "AutoHawkMenuItem"; - this.AutoHawkMenuItem.Size = new System.Drawing.Size(155, 22); - this.AutoHawkMenuItem.Text = "AutoHawk"; - this.AutoHawkMenuItem.Click += new System.EventHandler(this.AutoHawkMenuItem_Click); - // // NewHexEditorMenuItem // this.NewHexEditorMenuItem.Name = "NewHexEditorMenuItem"; @@ -2289,22 +2280,22 @@ // NESSubMenu // this.NESSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.coreToolStripMenuItem, - this.toolStripSeparator34, - this.NESPPUViewerMenuItem, - this.NESNametableViewerMenuItem, - this.NESGameGenieCodesMenuItem, - this.musicRipperToolStripMenuItem, - this.toolStripSeparator17, - this.NesControllerSettingsMenuItem, - this.NESGraphicSettingsMenuItem, - this.NESSoundChannelsMenuItem, - this.VSSettingsMenuItem, - this.MovieSettingsMenuItem, - this.toolStripSeparator22, - this.FDSControlsMenuItem, - this.VSControlsMenuItem, - this.barcodeReaderToolStripMenuItem}); + this.coreToolStripMenuItem, + this.toolStripSeparator34, + this.NESPPUViewerMenuItem, + this.NESNametableViewerMenuItem, + this.NESGameGenieCodesMenuItem, + this.musicRipperToolStripMenuItem, + this.toolStripSeparator17, + this.NesControllerSettingsMenuItem, + this.NESGraphicSettingsMenuItem, + this.NESSoundChannelsMenuItem, + this.VSSettingsMenuItem, + this.MovieSettingsMenuItem, + this.toolStripSeparator22, + this.FDSControlsMenuItem, + this.VSControlsMenuItem, + this.barcodeReaderToolStripMenuItem}); this.NESSubMenu.Name = "NESSubMenu"; this.NESSubMenu.Size = new System.Drawing.Size(40, 19); this.NESSubMenu.Text = "&NES"; @@ -2313,8 +2304,8 @@ // coreToolStripMenuItem // this.coreToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.quickNESToolStripMenuItem, - this.nesHawkToolStripMenuItem}); + this.quickNESToolStripMenuItem, + this.nesHawkToolStripMenuItem}); this.coreToolStripMenuItem.Name = "coreToolStripMenuItem"; this.coreToolStripMenuItem.Size = new System.Drawing.Size(233, 22); this.coreToolStripMenuItem.Text = "&Core"; @@ -2418,7 +2409,7 @@ // FDSControlsMenuItem // this.FDSControlsMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.FdsEjectDiskMenuItem}); + this.FdsEjectDiskMenuItem}); this.FDSControlsMenuItem.Name = "FDSControlsMenuItem"; this.FDSControlsMenuItem.Size = new System.Drawing.Size(233, 22); this.FDSControlsMenuItem.Text = "FDS Controls"; @@ -2434,9 +2425,9 @@ // VSControlsMenuItem // this.VSControlsMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.VSInsertCoinP1MenuItem, - this.VSInsertCoinP2MenuItem, - this.VSServiceSwitchMenuItem}); + this.VSInsertCoinP1MenuItem, + this.VSInsertCoinP2MenuItem, + this.VSServiceSwitchMenuItem}); this.VSControlsMenuItem.Name = "VSControlsMenuItem"; this.VSControlsMenuItem.Size = new System.Drawing.Size(233, 22); this.VSControlsMenuItem.Text = "VS Controls"; @@ -2472,16 +2463,16 @@ // PCESubMenu // this.PCESubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.PceControllerSettingsMenuItem, - this.PCEGraphicsSettingsMenuItem, - this.toolStripSeparator32, - this.PCEBGViewerMenuItem, - this.PCEtileViewerToolStripMenuItem, - this.PceSoundDebuggerToolStripMenuItem, - this.toolStripSeparator25, - this.PCEAlwaysPerformSpriteLimitMenuItem, - this.PCEAlwaysEqualizeVolumesMenuItem, - this.PCEArcadeCardRewindEnableMenuItem}); + this.PceControllerSettingsMenuItem, + this.PCEGraphicsSettingsMenuItem, + this.toolStripSeparator32, + this.PCEBGViewerMenuItem, + this.PCEtileViewerToolStripMenuItem, + this.PceSoundDebuggerToolStripMenuItem, + this.toolStripSeparator25, + this.PCEAlwaysPerformSpriteLimitMenuItem, + this.PCEAlwaysEqualizeVolumesMenuItem, + this.PCEArcadeCardRewindEnableMenuItem}); this.PCESubMenu.Name = "PCESubMenu"; this.PCESubMenu.Size = new System.Drawing.Size(40, 19); this.PCESubMenu.Text = "&PCE"; @@ -2558,23 +2549,23 @@ // SMSSubMenu // this.SMSSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.SMSregionToolStripMenuItem, - this.SMSdisplayToolStripMenuItem, - this.SMSControllerToolStripMenuItem, - this.SMStoolStripMenuItem2, - this.SMSenableBIOSToolStripMenuItem, - this.SMSEnableFMChipMenuItem, - this.SMSOverclockMenuItem, - this.SMSForceStereoMenuItem, - this.SMSSpriteLimitMenuItem, - this.SMSDisplayOverscanMenuItem, - this.SMSFix3DGameDisplayToolStripMenuItem, - this.ShowClippedRegionsMenuItem, - this.HighlightActiveDisplayRegionMenuItem, - this.SMSGraphicsSettingsMenuItem, - this.toolStripSeparator24, - this.SMSVDPViewerToolStripMenuItem, - this.GGGameGenieMenuItem}); + this.SMSregionToolStripMenuItem, + this.SMSdisplayToolStripMenuItem, + this.SMSControllerToolStripMenuItem, + this.SMStoolStripMenuItem2, + this.SMSenableBIOSToolStripMenuItem, + this.SMSEnableFMChipMenuItem, + this.SMSOverclockMenuItem, + this.SMSForceStereoMenuItem, + this.SMSSpriteLimitMenuItem, + this.SMSDisplayOverscanMenuItem, + this.SMSFix3DGameDisplayToolStripMenuItem, + this.ShowClippedRegionsMenuItem, + this.HighlightActiveDisplayRegionMenuItem, + this.SMSGraphicsSettingsMenuItem, + this.toolStripSeparator24, + this.SMSVDPViewerToolStripMenuItem, + this.GGGameGenieMenuItem}); this.SMSSubMenu.Name = "SMSSubMenu"; this.SMSSubMenu.Size = new System.Drawing.Size(42, 19); this.SMSSubMenu.Text = "&SMS"; @@ -2583,10 +2574,10 @@ // SMSregionToolStripMenuItem // this.SMSregionToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.SMSregionExportToolStripMenuItem, - this.SMSregionJapanToolStripMenuItem, - this.SMSregionKoreaToolStripMenuItem, - this.SMSregionAutoToolStripMenuItem}); + this.SMSregionExportToolStripMenuItem, + this.SMSregionJapanToolStripMenuItem, + this.SMSregionKoreaToolStripMenuItem, + this.SMSregionAutoToolStripMenuItem}); this.SMSregionToolStripMenuItem.Name = "SMSregionToolStripMenuItem"; this.SMSregionToolStripMenuItem.Size = new System.Drawing.Size(277, 22); this.SMSregionToolStripMenuItem.Text = "Region"; @@ -2622,9 +2613,9 @@ // SMSdisplayToolStripMenuItem // this.SMSdisplayToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.SMSdisplayNtscToolStripMenuItem, - this.SMSdisplayPalToolStripMenuItem, - this.SMSdisplayAutoToolStripMenuItem}); + this.SMSdisplayNtscToolStripMenuItem, + this.SMSdisplayPalToolStripMenuItem, + this.SMSdisplayAutoToolStripMenuItem}); this.SMSdisplayToolStripMenuItem.Name = "SMSdisplayToolStripMenuItem"; this.SMSdisplayToolStripMenuItem.Size = new System.Drawing.Size(277, 22); this.SMSdisplayToolStripMenuItem.Text = "Display Type"; @@ -2653,11 +2644,11 @@ // SMSControllerToolStripMenuItem // this.SMSControllerToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.SMSControllerStandardToolStripMenuItem, - this.SMSControllerPaddleToolStripMenuItem, - this.SMSControllerLightPhaserToolStripMenuItem, - this.SMSControllerSportsPadToolStripMenuItem, - this.SMSControllerKeyboardToolStripMenuItem}); + this.SMSControllerStandardToolStripMenuItem, + this.SMSControllerPaddleToolStripMenuItem, + this.SMSControllerLightPhaserToolStripMenuItem, + this.SMSControllerSportsPadToolStripMenuItem, + this.SMSControllerKeyboardToolStripMenuItem}); this.SMSControllerToolStripMenuItem.Name = "SMSControllerToolStripMenuItem"; this.SMSControllerToolStripMenuItem.Size = new System.Drawing.Size(277, 22); this.SMSControllerToolStripMenuItem.Text = "&Controller Type"; @@ -2794,11 +2785,11 @@ // TI83SubMenu // this.TI83SubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.KeypadMenuItem, - this.LoadTIFileMenuItem, - this.toolStripSeparator13, - this.AutoloadKeypadMenuItem, - this.paletteToolStripMenuItem}); + this.KeypadMenuItem, + this.LoadTIFileMenuItem, + this.toolStripSeparator13, + this.AutoloadKeypadMenuItem, + this.paletteToolStripMenuItem}); this.TI83SubMenu.Name = "TI83SubMenu"; this.TI83SubMenu.Size = new System.Drawing.Size(41, 19); this.TI83SubMenu.Text = "TI83"; @@ -2843,7 +2834,7 @@ // AtariSubMenu // this.AtariSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.AtariSettingsToolStripMenuItem}); + this.AtariSettingsToolStripMenuItem}); this.AtariSubMenu.Name = "AtariSubMenu"; this.AtariSubMenu.Size = new System.Drawing.Size(44, 19); this.AtariSubMenu.Text = "&Atari"; @@ -2858,8 +2849,8 @@ // A7800SubMenu // this.A7800SubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.A7800ControllerSettingsMenuItem, - this.A7800FilterSettingsMenuItem}); + this.A7800ControllerSettingsMenuItem, + this.A7800FilterSettingsMenuItem}); this.A7800SubMenu.Name = "A7800SubMenu"; this.A7800SubMenu.Size = new System.Drawing.Size(51, 19); this.A7800SubMenu.Text = "&A7800"; @@ -2882,12 +2873,12 @@ // GBSubMenu // this.GBSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.GBcoreSettingsToolStripMenuItem, - this.LoadGBInSGBMenuItem, - this.toolStripSeparator28, - this.GBGPUViewerMenuItem, - this.GBGameGenieMenuItem, - this.GBPrinterViewerMenuItem}); + this.GBcoreSettingsToolStripMenuItem, + this.LoadGBInSGBMenuItem, + this.toolStripSeparator28, + this.GBGPUViewerMenuItem, + this.GBGameGenieMenuItem, + this.GBPrinterViewerMenuItem}); this.GBSubMenu.Name = "GBSubMenu"; this.GBSubMenu.Size = new System.Drawing.Size(34, 19); this.GBSubMenu.Text = "&GB"; @@ -2936,10 +2927,10 @@ // GBASubMenu // this.GBASubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.GBACoreSelectionSubMenu, - this.GBAcoresettingsToolStripMenuItem1, - this.toolStripSeparator33, - this.GbaGpuViewerMenuItem}); + this.GBACoreSelectionSubMenu, + this.GBAcoresettingsToolStripMenuItem1, + this.toolStripSeparator33, + this.GbaGpuViewerMenuItem}); this.GBASubMenu.Name = "GBASubMenu"; this.GBASubMenu.Size = new System.Drawing.Size(42, 19); this.GBASubMenu.Text = "GBA"; @@ -2947,8 +2938,8 @@ // GBACoreSelectionSubMenu // this.GBACoreSelectionSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.GBAmGBAMenuItem, - this.GBAVBANextMenuItem}); + this.GBAmGBAMenuItem, + this.GBAVBANextMenuItem}); this.GBACoreSelectionSubMenu.Name = "GBACoreSelectionSubMenu"; this.GBACoreSelectionSubMenu.Size = new System.Drawing.Size(135, 22); this.GBACoreSelectionSubMenu.Text = "&Core"; @@ -2973,7 +2964,7 @@ this.GBAcoresettingsToolStripMenuItem1.Name = "GBAcoresettingsToolStripMenuItem1"; this.GBAcoresettingsToolStripMenuItem1.Size = new System.Drawing.Size(135, 22); this.GBAcoresettingsToolStripMenuItem1.Text = "&Settings..."; - this.GBAcoresettingsToolStripMenuItem1.Click += new System.EventHandler(this.GBAcoresettingsToolStripMenuItem1_Click); + this.GBAcoresettingsToolStripMenuItem1.Click += new System.EventHandler(this.GBACoreSettingsToolStripMenuItem_Click); // // toolStripSeparator33 // @@ -2990,10 +2981,10 @@ // PSXSubMenu // this.PSXSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.PSXControllerSettingsMenuItem, - this.PSXOptionsMenuItem, - this.PSXDiscControlsMenuItem, - this.PSXHashDiscsToolStripMenuItem}); + this.PSXControllerSettingsMenuItem, + this.PSXOptionsMenuItem, + this.PSXDiscControlsMenuItem, + this.PSXHashDiscsToolStripMenuItem}); this.PSXSubMenu.Name = "PSXSubMenu"; this.PSXSubMenu.Size = new System.Drawing.Size(39, 19); this.PSXSubMenu.Text = "PSX"; @@ -3031,12 +3022,12 @@ // SNESSubMenu // this.SNESSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.SNESControllerConfigurationMenuItem, - this.toolStripSeparator18, - this.SnesGfxDebuggerMenuItem, - this.SnesGBInSGBMenuItem, - this.SnesGameGenieMenuItem, - this.SnesOptionsMenuItem}); + this.SNESControllerConfigurationMenuItem, + this.toolStripSeparator18, + this.SnesGfxDebuggerMenuItem, + this.SnesGBInSGBMenuItem, + this.SnesGameGenieMenuItem, + this.SnesOptionsMenuItem}); this.SNESSubMenu.Name = "SNESSubMenu"; this.SNESSubMenu.Size = new System.Drawing.Size(46, 19); this.SNESSubMenu.Text = "&SNES"; @@ -3087,10 +3078,10 @@ // ColecoSubMenu // this.ColecoSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.ColecoControllerSettingsMenuItem, - this.toolStripSeparator35, - this.ColecoSkipBiosMenuItem, - this.ColecoUseSGMMenuItem}); + this.ColecoControllerSettingsMenuItem, + this.toolStripSeparator35, + this.ColecoSkipBiosMenuItem, + this.ColecoUseSGMMenuItem}); this.ColecoSubMenu.Name = "ColecoSubMenu"; this.ColecoSubMenu.Size = new System.Drawing.Size(56, 19); this.ColecoSubMenu.Text = "&Coleco"; @@ -3126,12 +3117,12 @@ // N64SubMenu // this.N64SubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.N64PluginSettingsMenuItem, - this.N64ControllerSettingsMenuItem, - this.toolStripSeparator23, - this.N64CircularAnalogRangeMenuItem, - this.MupenStyleLagMenuItem, - this.N64ExpansionSlotMenuItem}); + this.N64PluginSettingsMenuItem, + this.N64ControllerSettingsMenuItem, + this.toolStripSeparator23, + this.N64CircularAnalogRangeMenuItem, + this.MupenStyleLagMenuItem, + this.N64ExpansionSlotMenuItem}); this.N64SubMenu.Name = "N64SubMenu"; this.N64SubMenu.Size = new System.Drawing.Size(40, 19); this.N64SubMenu.Text = "N64"; @@ -3182,7 +3173,7 @@ // SaturnSubMenu // this.SaturnSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.SaturnPreferencesMenuItem}); + this.SaturnPreferencesMenuItem}); this.SaturnSubMenu.Name = "SaturnSubMenu"; this.SaturnSubMenu.Size = new System.Drawing.Size(53, 19); this.SaturnSubMenu.Text = "&Saturn"; @@ -3197,7 +3188,7 @@ // DGBSubMenu // this.DGBSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.DGBsettingsToolStripMenuItem}); + this.DGBsettingsToolStripMenuItem}); this.DGBSubMenu.Name = "DGBSubMenu"; this.DGBSubMenu.Size = new System.Drawing.Size(59, 19); this.DGBSubMenu.Text = "&GB Link"; @@ -3212,7 +3203,7 @@ // DGBHawkSubMenu // this.DGBHawkSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.DGBHawksettingsToolStripMenuItem}); + this.DGBHawksettingsToolStripMenuItem}); this.DGBHawkSubMenu.Name = "DGBHawkSubMenu"; this.DGBHawkSubMenu.Size = new System.Drawing.Size(59, 19); this.DGBHawkSubMenu.Text = "&GB Link"; @@ -3257,7 +3248,7 @@ // GGLSubMenu // this.GGLSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.GGLsettingsToolStripMenuItem}); + this.GGLsettingsToolStripMenuItem}); this.GGLSubMenu.Name = "GGLSubMenu"; this.GGLSubMenu.Size = new System.Drawing.Size(60, 19); this.GGLSubMenu.Text = "&GG Link"; @@ -3287,10 +3278,10 @@ // GenesisSubMenu // this.GenesisSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.vDPViewerToolStripMenuItem, - this.GenesisGameGenieECDC, - this.toolStripSeparator26, - this.GenesisSettingsToolStripMenuItem}); + this.vDPViewerToolStripMenuItem, + this.GenesisGameGenieECDC, + this.toolStripSeparator26, + this.GenesisSettingsToolStripMenuItem}); this.GenesisSubMenu.Name = "GenesisSubMenu"; this.GenesisSubMenu.Size = new System.Drawing.Size(59, 19); this.GenesisSubMenu.Text = "&Genesis"; @@ -3324,7 +3315,7 @@ // wonderSwanToolStripMenuItem // this.wonderSwanToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.settingsToolStripMenuItem}); + this.settingsToolStripMenuItem}); this.wonderSwanToolStripMenuItem.Name = "wonderSwanToolStripMenuItem"; this.wonderSwanToolStripMenuItem.Size = new System.Drawing.Size(89, 19); this.wonderSwanToolStripMenuItem.Text = "&WonderSwan"; @@ -3334,13 +3325,13 @@ this.settingsToolStripMenuItem.Name = "settingsToolStripMenuItem"; this.settingsToolStripMenuItem.Size = new System.Drawing.Size(125, 22); this.settingsToolStripMenuItem.Text = "&Settings..."; - this.settingsToolStripMenuItem.Click += new System.EventHandler(this.WondersawnSettingsMenuItem_Click); + this.settingsToolStripMenuItem.Click += new System.EventHandler(this.WonderSwanSettingsMenuItem_Click); // // AppleSubMenu // this.AppleSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.AppleDisksSubMenu, - this.settingsToolStripMenuItem1}); + this.AppleDisksSubMenu, + this.settingsToolStripMenuItem1}); this.AppleSubMenu.Name = "AppleSubMenu"; this.AppleSubMenu.Size = new System.Drawing.Size(50, 19); this.AppleSubMenu.Text = "Apple"; @@ -3349,7 +3340,7 @@ // AppleDisksSubMenu // this.AppleDisksSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.toolStripSeparator31}); + this.toolStripSeparator31}); this.AppleDisksSubMenu.Name = "AppleDisksSubMenu"; this.AppleDisksSubMenu.Size = new System.Drawing.Size(125, 22); this.AppleDisksSubMenu.Text = "Disks"; @@ -3370,8 +3361,8 @@ // C64SubMenu // this.C64SubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.C64DisksSubMenu, - this.C64SettingsMenuItem}); + this.C64DisksSubMenu, + this.C64SettingsMenuItem}); this.C64SubMenu.Name = "C64SubMenu"; this.C64SubMenu.Size = new System.Drawing.Size(39, 19); this.C64SubMenu.Text = "&C64"; @@ -3380,7 +3371,7 @@ // C64DisksSubMenu // this.C64DisksSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.toolStripSeparator36}); + this.toolStripSeparator36}); this.C64DisksSubMenu.Name = "C64DisksSubMenu"; this.C64DisksSubMenu.Size = new System.Drawing.Size(125, 22); this.C64DisksSubMenu.Text = "Disks"; @@ -3401,11 +3392,11 @@ // IntvSubMenu // this.IntvSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.IntVControllerSettingsMenuItem}); + this.IntVControllerSettingsMenuItem}); this.IntvSubMenu.Name = "IntvSubMenu"; this.IntvSubMenu.Size = new System.Drawing.Size(39, 19); this.IntvSubMenu.Text = "&Intv"; - this.IntvSubMenu.DropDownOpened += new System.EventHandler(this.IntvSubMenu_DropDownOpened); + this.IntvSubMenu.DropDownOpened += new System.EventHandler(this.IntVSubMenu_DropDownOpened); // // IntVControllerSettingsMenuItem // @@ -3418,7 +3409,7 @@ // sNESToolStripMenuItem // this.sNESToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.preferencesToolStripMenuItem}); + this.preferencesToolStripMenuItem}); this.sNESToolStripMenuItem.Name = "sNESToolStripMenuItem"; this.sNESToolStripMenuItem.Size = new System.Drawing.Size(46, 19); this.sNESToolStripMenuItem.Text = "&SNES"; @@ -3428,12 +3419,12 @@ this.preferencesToolStripMenuItem.Name = "preferencesToolStripMenuItem"; this.preferencesToolStripMenuItem.Size = new System.Drawing.Size(144, 22); this.preferencesToolStripMenuItem.Text = "Preferences..."; - this.preferencesToolStripMenuItem.Click += new System.EventHandler(this.preferencesToolStripMenuItem_Click); + this.preferencesToolStripMenuItem.Click += new System.EventHandler(this.Snes9xSettingsMenuItem_Click); // // pCFXToolStripMenuItem // this.pCFXToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.preferencesToolStripMenuItem3}); + this.preferencesToolStripMenuItem3}); this.pCFXToolStripMenuItem.Name = "pCFXToolStripMenuItem"; this.pCFXToolStripMenuItem.Size = new System.Drawing.Size(52, 19); this.pCFXToolStripMenuItem.Text = "&PC-FX"; @@ -3443,12 +3434,12 @@ this.preferencesToolStripMenuItem3.Name = "preferencesToolStripMenuItem3"; this.preferencesToolStripMenuItem3.Size = new System.Drawing.Size(144, 22); this.preferencesToolStripMenuItem3.Text = "Preferences..."; - this.preferencesToolStripMenuItem3.Click += new System.EventHandler(this.preferencesToolStripMenuItem3_Click); + this.preferencesToolStripMenuItem3.Click += new System.EventHandler(this.PCFXSettingsMenuItem_Click); // // virtualBoyToolStripMenuItem // this.virtualBoyToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.preferencesToolStripMenuItem1}); + this.preferencesToolStripMenuItem1}); this.virtualBoyToolStripMenuItem.Name = "virtualBoyToolStripMenuItem"; this.virtualBoyToolStripMenuItem.Size = new System.Drawing.Size(73, 19); this.virtualBoyToolStripMenuItem.Text = "&VirtualBoy"; @@ -3458,12 +3449,12 @@ this.preferencesToolStripMenuItem1.Name = "preferencesToolStripMenuItem1"; this.preferencesToolStripMenuItem1.Size = new System.Drawing.Size(144, 22); this.preferencesToolStripMenuItem1.Text = "Preferences..."; - this.preferencesToolStripMenuItem1.Click += new System.EventHandler(this.preferencesToolStripMenuItem1_Click); + this.preferencesToolStripMenuItem1.Click += new System.EventHandler(this.VirtualBoySettingsMenuItem_Click); // // neoGeoPocketToolStripMenuItem // this.neoGeoPocketToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.preferencesToolStripMenuItem2}); + this.preferencesToolStripMenuItem2}); this.neoGeoPocketToolStripMenuItem.Name = "neoGeoPocketToolStripMenuItem"; this.neoGeoPocketToolStripMenuItem.Size = new System.Drawing.Size(101, 19); this.neoGeoPocketToolStripMenuItem.Text = "&NeoGeo Pocket"; @@ -3473,21 +3464,20 @@ this.preferencesToolStripMenuItem2.Name = "preferencesToolStripMenuItem2"; this.preferencesToolStripMenuItem2.Size = new System.Drawing.Size(144, 22); this.preferencesToolStripMenuItem2.Text = "Preferences..."; - this.preferencesToolStripMenuItem2.Click += new System.EventHandler(this.preferencesToolStripMenuItem2_Click); + this.preferencesToolStripMenuItem2.Click += new System.EventHandler(this.NeoGeoSettingsMenuItem_Click); // // zXSpectrumToolStripMenuItem // this.zXSpectrumToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.ZXSpectrumCoreEmulationSettingsMenuItem, - this.ZXSpectrumControllerConfigurationMenuItem, - this.ZXSpectrumAudioSettingsMenuItem, - this.ZXSpectrumNonSyncSettingsMenuItem, - this.ZXSpectrumPokeMemoryMenuItem, - this.ZXSpectrumMediaMenuItem}); + this.ZXSpectrumCoreEmulationSettingsMenuItem, + this.ZXSpectrumControllerConfigurationMenuItem, + this.ZXSpectrumAudioSettingsMenuItem, + this.ZXSpectrumNonSyncSettingsMenuItem, + this.ZXSpectrumPokeMemoryMenuItem, + this.ZXSpectrumMediaMenuItem}); this.zXSpectrumToolStripMenuItem.Name = "zXSpectrumToolStripMenuItem"; this.zXSpectrumToolStripMenuItem.Size = new System.Drawing.Size(87, 19); this.zXSpectrumToolStripMenuItem.Text = "ZX Spectrum"; - this.zXSpectrumToolStripMenuItem.DropDownOpened += new System.EventHandler(this.zXSpectrumToolStripMenuItem_DropDownOpened); // // ZXSpectrumCoreEmulationSettingsMenuItem // @@ -3527,9 +3517,9 @@ // ZXSpectrumMediaMenuItem // this.ZXSpectrumMediaMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.ZXSpectrumTapesSubMenu, - this.ZXSpectrumDisksSubMenu, - this.ZXSpectrumExportSnapshotMenuItemMenuItem}); + this.ZXSpectrumTapesSubMenu, + this.ZXSpectrumDisksSubMenu, + this.ZXSpectrumExportSnapshotMenuItemMenuItem}); this.ZXSpectrumMediaMenuItem.Name = "ZXSpectrumMediaMenuItem"; this.ZXSpectrumMediaMenuItem.Size = new System.Drawing.Size(201, 22); this.ZXSpectrumMediaMenuItem.Text = "Media"; @@ -3538,7 +3528,7 @@ // ZXSpectrumTapesSubMenu // this.ZXSpectrumTapesSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.zxt1ToolStripMenuItem}); + this.zxt1ToolStripMenuItem}); this.ZXSpectrumTapesSubMenu.Name = "ZXSpectrumTapesSubMenu"; this.ZXSpectrumTapesSubMenu.Size = new System.Drawing.Size(159, 22); this.ZXSpectrumTapesSubMenu.Text = "Tapes"; @@ -3553,7 +3543,7 @@ // ZXSpectrumDisksSubMenu // this.ZXSpectrumDisksSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.zxt2ToolStripMenuItem}); + this.zxt2ToolStripMenuItem}); this.ZXSpectrumDisksSubMenu.Name = "ZXSpectrumDisksSubMenu"; this.ZXSpectrumDisksSubMenu.Size = new System.Drawing.Size(159, 22); this.ZXSpectrumDisksSubMenu.Text = "Disks"; @@ -3575,10 +3565,10 @@ // HelpSubMenu // this.HelpSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.OnlineHelpMenuItem, - this.ForumsMenuItem, - this.FeaturesMenuItem, - this.AboutMenuItem}); + this.OnlineHelpMenuItem, + this.ForumsMenuItem, + this.FeaturesMenuItem, + this.AboutMenuItem}); this.HelpSubMenu.Name = "HelpSubMenu"; this.HelpSubMenu.Size = new System.Drawing.Size(44, 19); this.HelpSubMenu.Text = "&Help"; @@ -3619,11 +3609,11 @@ // amstradCPCToolStripMenuItem // this.amstradCPCToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.amstradCPCCoreEmulationSettingsToolStripMenuItem, - this.AmstradCPCAudioSettingsToolStripMenuItem, - this.AmstradCPCNonSyncSettingsToolStripMenuItem, - this.AmstradCPCPokeMemoryToolStripMenuItem, - this.AmstradCPCMediaToolStripMenuItem}); + this.amstradCPCCoreEmulationSettingsToolStripMenuItem, + this.AmstradCPCAudioSettingsToolStripMenuItem, + this.AmstradCPCNonSyncSettingsToolStripMenuItem, + this.AmstradCPCPokeMemoryToolStripMenuItem, + this.AmstradCPCMediaToolStripMenuItem}); this.amstradCPCToolStripMenuItem.Name = "amstradCPCToolStripMenuItem"; this.amstradCPCToolStripMenuItem.Size = new System.Drawing.Size(90, 19); this.amstradCPCToolStripMenuItem.Text = "Amstrad CPC"; @@ -3659,8 +3649,8 @@ // AmstradCPCMediaToolStripMenuItem // this.AmstradCPCMediaToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.AmstradCPCTapesSubMenu, - this.AmstradCPCDisksSubMenu}); + this.AmstradCPCTapesSubMenu, + this.AmstradCPCDisksSubMenu}); this.AmstradCPCMediaToolStripMenuItem.Name = "AmstradCPCMediaToolStripMenuItem"; this.AmstradCPCMediaToolStripMenuItem.Size = new System.Drawing.Size(201, 22); this.AmstradCPCMediaToolStripMenuItem.Text = "Media"; @@ -3669,7 +3659,7 @@ // AmstradCPCTapesSubMenu // this.AmstradCPCTapesSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.cpct1ToolStripMenuItem}); + this.cpct1ToolStripMenuItem}); this.AmstradCPCTapesSubMenu.Name = "AmstradCPCTapesSubMenu"; this.AmstradCPCTapesSubMenu.Size = new System.Drawing.Size(104, 22); this.AmstradCPCTapesSubMenu.Text = "Tapes"; @@ -3684,7 +3674,7 @@ // AmstradCPCDisksSubMenu // this.AmstradCPCDisksSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.cpcd1ToolStripMenuItem}); + this.cpcd1ToolStripMenuItem}); this.AmstradCPCDisksSubMenu.Name = "AmstradCPCDisksSubMenu"; this.AmstradCPCDisksSubMenu.Size = new System.Drawing.Size(104, 22); this.AmstradCPCDisksSubMenu.Text = "Disks"; @@ -3706,30 +3696,30 @@ // this.MainStatusBar.ClickThrough = true; this.MainStatusBar.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.DumpStatusButton, - this.EmuStatus, - this.PlayRecordStatusButton, - this.PauseStatusButton, - this.RebootStatusBarIcon, - this.AVIStatusLabel, - this.LedLightStatusLabel, - this.SaveSlotsStatusLabel, - this.Slot1StatusButton, - this.Slot2StatusButton, - this.Slot3StatusButton, - this.Slot4StatusButton, - this.Slot5StatusButton, - this.Slot6StatusButton, - this.Slot7StatusButton, - this.Slot8StatusButton, - this.Slot9StatusButton, - this.Slot0StatusButton, - this.CheatStatusButton, - this.KeyPriorityStatusLabel, - this.CoreNameStatusBarButton, - this.ProfileFirstBootLabel, - this.LinkConnectStatusBarButton, - this.UpdateNotification}); + this.DumpStatusButton, + this.EmuStatus, + this.PlayRecordStatusButton, + this.PauseStatusButton, + this.RebootStatusBarIcon, + this.AVIStatusLabel, + this.LedLightStatusLabel, + this.SaveSlotsStatusLabel, + this.Slot1StatusButton, + this.Slot2StatusButton, + this.Slot3StatusButton, + this.Slot4StatusButton, + this.Slot5StatusButton, + this.Slot6StatusButton, + this.Slot7StatusButton, + this.Slot8StatusButton, + this.Slot9StatusButton, + this.Slot0StatusButton, + this.CheatStatusButton, + this.KeyPriorityStatusLabel, + this.CoreNameStatusBarButton, + this.ProfileFirstBootLabel, + this.LinkConnectStatusBarButton, + this.UpdateNotification}); this.MainStatusBar.Location = new System.Drawing.Point(0, 386); this.MainStatusBar.Name = "MainStatusBar"; this.MainStatusBar.ShowItemToolTips = true; @@ -3949,31 +3939,31 @@ // MainFormContextMenu // this.MainFormContextMenu.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.OpenRomContextMenuItem, - this.LoadLastRomContextMenuItem, - this.StopAVContextMenuItem, - this.ContextSeparator_AfterROM, - this.RecordMovieContextMenuItem, - this.PlayMovieContextMenuItem, - this.RestartMovieContextMenuItem, - this.StopMovieContextMenuItem, - this.LoadLastMovieContextMenuItem, - this.BackupMovieContextMenuItem, - this.StopNoSaveContextMenuItem, - this.ViewSubtitlesContextMenuItem, - this.AddSubtitleContextMenuItem, - this.ViewCommentsContextMenuItem, - this.SaveMovieContextMenuItem, - this.SaveMovieAsContextMenuItem, - this.ContextSeparator_AfterMovie, - this.UndoSavestateContextMenuItem, - this.ContextSeparator_AfterUndo, - this.ConfigContextMenuItem, - this.ScreenshotContextMenuItem, - this.CloseRomContextMenuItem, - this.ClearSRAMContextMenuItem, - this.ShowMenuContextMenuSeparator, - this.ShowMenuContextMenuItem}); + this.OpenRomContextMenuItem, + this.LoadLastRomContextMenuItem, + this.StopAVContextMenuItem, + this.ContextSeparator_AfterROM, + this.RecordMovieContextMenuItem, + this.PlayMovieContextMenuItem, + this.RestartMovieContextMenuItem, + this.StopMovieContextMenuItem, + this.LoadLastMovieContextMenuItem, + this.BackupMovieContextMenuItem, + this.StopNoSaveContextMenuItem, + this.ViewSubtitlesContextMenuItem, + this.AddSubtitleContextMenuItem, + this.ViewCommentsContextMenuItem, + this.SaveMovieContextMenuItem, + this.SaveMovieAsContextMenuItem, + this.ContextSeparator_AfterMovie, + this.UndoSavestateContextMenuItem, + this.ContextSeparator_AfterUndo, + this.ConfigContextMenuItem, + this.ScreenshotContextMenuItem, + this.CloseRomContextMenuItem, + this.ClearSRAMContextMenuItem, + this.ShowMenuContextMenuSeparator, + this.ShowMenuContextMenuItem}); this.MainFormContextMenu.Name = "contextMenuStrip1"; this.MainFormContextMenu.Size = new System.Drawing.Size(217, 490); this.MainFormContextMenu.Closing += new System.Windows.Forms.ToolStripDropDownClosingEventHandler(this.MainFormContextMenu_Closing); @@ -4121,22 +4111,22 @@ // ConfigContextMenuItem // this.ConfigContextMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.toolStripMenuItem6, - this.toolStripMenuItem7, - this.toolStripMenuItem8, - this.toolStripMenuItem9, - this.toolStripMenuItem10, - this.toolStripMenuItem11, - this.toolStripMenuItem12, - this.toolStripMenuItem13, - this.toolStripMenuItem14, - this.toolStripMenuItem15, - this.customizeToolStripMenuItem, - this.toolStripSeparator30, - this.SavestateTypeContextSubMenu, - this.toolStripSeparator37, - this.toolStripMenuItem66, - this.toolStripMenuItem67}); + this.toolStripMenuItem6, + this.toolStripMenuItem7, + this.toolStripMenuItem8, + this.toolStripMenuItem9, + this.toolStripMenuItem10, + this.toolStripMenuItem11, + this.toolStripMenuItem12, + this.toolStripMenuItem13, + this.toolStripMenuItem14, + this.toolStripMenuItem15, + this.customizeToolStripMenuItem, + this.toolStripSeparator30, + this.SavestateTypeContextSubMenu, + this.toolStripSeparator37, + this.toolStripMenuItem66, + this.toolStripMenuItem67}); this.ConfigContextMenuItem.Name = "ConfigContextMenuItem"; this.ConfigContextMenuItem.Size = new System.Drawing.Size(216, 22); this.ConfigContextMenuItem.Text = "Config"; @@ -4235,9 +4225,9 @@ // SavestateTypeContextSubMenu // this.SavestateTypeContextSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.SavestateTypeDefaultContextMenuItem, - this.SavestateBinaryContextMenuItem, - this.SavestateTextContextMenuItem}); + this.SavestateTypeDefaultContextMenuItem, + this.SavestateBinaryContextMenuItem, + this.SavestateTextContextMenuItem}); this.SavestateTypeContextSubMenu.Name = "SavestateTypeContextSubMenu"; this.SavestateTypeContextSubMenu.Size = new System.Drawing.Size(159, 22); this.SavestateTypeContextSubMenu.Text = "Savestate Type"; @@ -4749,7 +4739,6 @@ private System.Windows.Forms.ToolStripMenuItem dummyExternalTool; private System.Windows.Forms.ToolStripMenuItem RecordAVMenuItem; private System.Windows.Forms.ToolStripMenuItem ExperimentalToolsSubMenu; - private System.Windows.Forms.ToolStripMenuItem AutoHawkMenuItem; private System.Windows.Forms.ToolStripMenuItem NewHexEditorMenuItem; private System.Windows.Forms.ToolStripMenuItem SaveConfigAsMenuItem; private System.Windows.Forms.ToolStripMenuItem LoadConfigFromMenuItem; @@ -4797,28 +4786,28 @@ private System.Windows.Forms.ToolStripMenuItem SMSControllerLightPhaserToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem SMSControllerSportsPadToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem SMSControllerKeyboardToolStripMenuItem; - private System.Windows.Forms.ToolStripMenuItem zXSpectrumToolStripMenuItem; - private System.Windows.Forms.ToolStripMenuItem ZXSpectrumControllerConfigurationMenuItem; - private System.Windows.Forms.ToolStripMenuItem ZXSpectrumCoreEmulationSettingsMenuItem; - private System.Windows.Forms.ToolStripMenuItem ZXSpectrumNonSyncSettingsMenuItem; - private System.Windows.Forms.ToolStripMenuItem ZXSpectrumAudioSettingsMenuItem; - private System.Windows.Forms.ToolStripMenuItem ZXSpectrumPokeMemoryMenuItem; - private System.Windows.Forms.ToolStripMenuItem ZXSpectrumMediaMenuItem; - private System.Windows.Forms.ToolStripMenuItem ZXSpectrumTapesSubMenu; - private System.Windows.Forms.ToolStripMenuItem ZXSpectrumDisksSubMenu; - private System.Windows.Forms.ToolStripMenuItem zxt1ToolStripMenuItem; - private System.Windows.Forms.ToolStripMenuItem zxt2ToolStripMenuItem; - private System.Windows.Forms.ToolStripMenuItem ZXSpectrumExportSnapshotMenuItemMenuItem; - private System.Windows.Forms.ToolStripMenuItem amstradCPCToolStripMenuItem; - private System.Windows.Forms.ToolStripMenuItem amstradCPCCoreEmulationSettingsToolStripMenuItem; - private System.Windows.Forms.ToolStripMenuItem AmstradCPCAudioSettingsToolStripMenuItem; - private System.Windows.Forms.ToolStripMenuItem AmstradCPCPokeMemoryToolStripMenuItem; - private System.Windows.Forms.ToolStripMenuItem AmstradCPCMediaToolStripMenuItem; - private System.Windows.Forms.ToolStripMenuItem AmstradCPCTapesSubMenu; - private System.Windows.Forms.ToolStripMenuItem cpct1ToolStripMenuItem; - private System.Windows.Forms.ToolStripMenuItem AmstradCPCDisksSubMenu; - private System.Windows.Forms.ToolStripMenuItem cpcd1ToolStripMenuItem; - private System.Windows.Forms.ToolStripMenuItem AmstradCPCNonSyncSettingsToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem zXSpectrumToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem ZXSpectrumControllerConfigurationMenuItem; + private System.Windows.Forms.ToolStripMenuItem ZXSpectrumCoreEmulationSettingsMenuItem; + private System.Windows.Forms.ToolStripMenuItem ZXSpectrumNonSyncSettingsMenuItem; + private System.Windows.Forms.ToolStripMenuItem ZXSpectrumAudioSettingsMenuItem; + private System.Windows.Forms.ToolStripMenuItem ZXSpectrumPokeMemoryMenuItem; + private System.Windows.Forms.ToolStripMenuItem ZXSpectrumMediaMenuItem; + private System.Windows.Forms.ToolStripMenuItem ZXSpectrumTapesSubMenu; + private System.Windows.Forms.ToolStripMenuItem ZXSpectrumDisksSubMenu; + private System.Windows.Forms.ToolStripMenuItem zxt1ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem zxt2ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem ZXSpectrumExportSnapshotMenuItemMenuItem; + private System.Windows.Forms.ToolStripMenuItem amstradCPCToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem amstradCPCCoreEmulationSettingsToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem AmstradCPCAudioSettingsToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem AmstradCPCPokeMemoryToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem AmstradCPCMediaToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem AmstradCPCTapesSubMenu; + private System.Windows.Forms.ToolStripMenuItem cpct1ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem AmstradCPCDisksSubMenu; + private System.Windows.Forms.ToolStripMenuItem cpcd1ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem AmstradCPCNonSyncSettingsToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem SubNesHawkMenuItem; private System.Windows.Forms.ToolStripSeparator toolStripSeparator38; } diff --git a/BizHawk.Client.EmuHawk/MainForm.Events.cs b/BizHawk.Client.EmuHawk/MainForm.Events.cs index 362f9ee24f..6ac855a1ee 100644 --- a/BizHawk.Client.EmuHawk/MainForm.Events.cs +++ b/BizHawk.Client.EmuHawk/MainForm.Events.cs @@ -6,21 +6,18 @@ using System.Collections.Generic; using BizHawk.Emulation.Common; using BizHawk.Emulation.Common.IEmulatorExtensions; -using BizHawk.Emulation.Cores.Atari.A7800Hawk; using BizHawk.Emulation.Cores.Calculators; using BizHawk.Emulation.Cores.ColecoVision; using BizHawk.Emulation.Cores.Nintendo.NES; using BizHawk.Emulation.Cores.Nintendo.SubNESHawk; using BizHawk.Emulation.Cores.Nintendo.N64; using BizHawk.Emulation.Cores.Nintendo.SNES; -using BizHawk.Emulation.Cores.Nintendo.SNES9X; using BizHawk.Emulation.Cores.PCEngine; using BizHawk.Emulation.Cores.Sega.MasterSystem; using BizHawk.Emulation.Cores.Consoles.Nintendo.QuickNES; using BizHawk.Client.Common; -using BizHawk.Client.EmuHawk.CustomControls; using BizHawk.Client.EmuHawk.WinFormExtensions; using BizHawk.Client.EmuHawk.ToolExtensions; using BizHawk.Emulation.Cores.Computers.AppleII; @@ -309,6 +306,7 @@ namespace BizHawk.Client.EmuHawk private void OpenRomMenuItem_Click(object sender, EventArgs e) { + AdvancedLoader = AdvancedRomLoaderType.None; OpenRom(); } @@ -320,7 +318,9 @@ namespace BizHawk.Client.EmuHawk return; } - if (oac.Result == OpenAdvancedChooser.Command.RetroLaunchNoGame) + AdvancedLoader = oac.Result; + + if (AdvancedLoader == AdvancedRomLoaderType.LibretroLaunchNoGame) { var argsNoGame = new LoadRomArgs { @@ -334,15 +334,20 @@ namespace BizHawk.Client.EmuHawk var filter = RomFilter; - if (oac.Result == OpenAdvancedChooser.Command.RetroLaunchGame) + if (AdvancedLoader == AdvancedRomLoaderType.LibretroLaunchGame) { args.OpenAdvanced = new OpenAdvanced_Libretro(); filter = oac.SuggestedExtensionFilter; } - else if (oac.Result == OpenAdvancedChooser.Command.ClassicLaunchGame) + else if (AdvancedLoader == AdvancedRomLoaderType.ClassicLaunchGame) { args.OpenAdvanced = new OpenAdvanced_OpenRom(); } + else if (AdvancedLoader == AdvancedRomLoaderType.MAMELaunchGame) + { + args.OpenAdvanced = new OpenAdvanced_MAME(); + filter = "MAME Arcade ROMs (*.zip)|*.zip"; + } else { throw new InvalidOperationException("Automatic Alpha Sanitizer"); @@ -468,8 +473,8 @@ namespace BizHawk.Client.EmuHawk { var result = MessageBox.Show( this, - "Thanks for using Bizhawk! The emulation core you have selected " + - "is currently BETA-status. We appreciate your help in testing Bizhawk. " + + "Thanks for using BizHawk! The emulation core you have selected " + + "is currently BETA-status. We appreciate your help in testing BizHawk. " + "You can record a movie on this core if you'd like to, but expect to " + "encounter bugs and sync problems. Continue?", "BizHawk", MessageBoxButtons.YesNo); @@ -478,55 +483,10 @@ namespace BizHawk.Client.EmuHawk return; } } - else if (Emulator is Snes9x) + + if (!EmuHawkUtil.EnsureCoreIsAccurate(Emulator)) { - var box = new MsgBox( - "While the Snes9x core is faster, it is not nearly as accurate as bsnes. \nIt is recommended that you switch to the bsnes core for movie recording\nSwitch to bsnes?", - "Accuracy Warning", - MessageBoxIcon.Warning); - - box.SetButtons( - new[] { "Switch", "Continue" }, - new[] { DialogResult.Yes, DialogResult.Cancel }); - - box.MaximumSize = new Size(475, 350); - box.SetMessageToAutoSize(); - var result = box.ShowDialog(); - - if (result == DialogResult.Yes) - { - Global.Config.SNES_InSnes9x = false; - RebootCore(); - } - else if (result == DialogResult.Cancel) - { - // Do nothing and allow the user to continue to record the movie - } - } - else if (Emulator is QuickNES) // This is unsustainable :( But mixing the logic together is even worse, this needs to be rethought - { - var box = new MsgBox( - "While the QuickNes core is faster, it is not nearly as accurate as NesHawk. \nIt is recommended that you switch to the NesHawk core for movie recording\nSwitch to NesHawk?", - "Accuracy Warning", - MessageBoxIcon.Warning); - - box.SetButtons( - new[] { "Switch", "Continue" }, - new[] { DialogResult.Yes, DialogResult.Cancel }); - - box.MaximumSize = new Size(475, 350); - box.SetMessageToAutoSize(); - var result = box.ShowDialog(); - - if (result == DialogResult.Yes) - { - Global.Config.NES_InQuickNES = false; - RebootCore(); - } - else if (result == DialogResult.Cancel) - { - // Do nothing and allow the user to continue to record the movie - } + // Inaccurate core but allow the user to continue anyway } new RecordMovie(Emulator).ShowDialog(); @@ -659,7 +619,7 @@ namespace BizHawk.Client.EmuHawk private void RecordAVMenuItem_Click(object sender, EventArgs e) { - RecordAv(null, null); // force unattended, but allow tradtional setup + RecordAv(null, null); // force unattended, but allow traditional setup } private void StopAVMenuItem_Click(object sender, EventArgs e) @@ -1024,9 +984,8 @@ namespace BizHawk.Client.EmuHawk private void FirmwaresMenuItem_Click(object sender, EventArgs e) { - if (e is RomLoader.RomErrorArgs) + if (e is RomLoader.RomErrorArgs args) { - var args = (RomLoader.RomErrorArgs)e; var result = new FirmwaresConfig(true, args.RomPath).ShowDialog(); args.Retry = result == DialogResult.Retry; } @@ -1446,7 +1405,7 @@ namespace BizHawk.Client.EmuHawk externalToolToolStripMenuItem.DropDownItems.Add(item); } - + if (externalToolToolStripMenuItem.DropDownItems.Count == 0) { externalToolToolStripMenuItem.DropDownItems.Add("None"); @@ -1455,7 +1414,6 @@ namespace BizHawk.Client.EmuHawk private void ExperimentalToolsSubMenu_DropDownOpened(object sender, EventArgs e) { - AutoHawkMenuItem.Enabled = GlobalWin.Tools.IsAvailable(); NewHexEditorMenuItem.Enabled = GlobalWin.Tools.IsAvailable(); } @@ -1475,7 +1433,7 @@ namespace BizHawk.Client.EmuHawk if (OSTailoredCode.CurrentOS != OSTailoredCode.DistinctOS.Windows) { // this is apparently needed for weird mono-forms-on-different-thread issues - // dont do .Show() within Load() for RamSearch - instead put an instance of it here on MainForm, then show here + // don't do .Show() within Load() for RamSearch - instead put an instance of it here on MainForm, then show here // the mono winforms implementation is.... weird and buggy ramSearch.Show(); } @@ -1552,11 +1510,6 @@ namespace BizHawk.Client.EmuHawk new BatchRun().ShowDialog(); } - private void AutoHawkMenuItem_Click(object sender, EventArgs e) - { - GlobalWin.Tools.Load(); - } - private void NewHexEditorMenuItem_Click(object sender, EventArgs e) { GlobalWin.Tools.Load(); @@ -1585,7 +1538,7 @@ namespace BizHawk.Client.EmuHawk VSControlsMenuItem.Enabled = VSSettingsMenuItem.Enabled = - Emulator is NES && ((NES)Emulator).IsVS; + Emulator is NES nes && nes.IsVS; NESSoundChannelsMenuItem.Enabled = GlobalWin.Tools.IsAvailable(); MovieSettingsMenuItem.Enabled = Emulator is NES && !Global.MovieSession.Movie.IsActive; @@ -1661,7 +1614,7 @@ namespace BizHawk.Client.EmuHawk private void VsSettingsMenuItem_Click(object sender, EventArgs e) { - if (Emulator is NES && ((NES)Emulator).IsVS) + if (Emulator is NES nes && nes.IsVS) { new NesVsSettings().ShowHawkDialog(); } @@ -1678,7 +1631,7 @@ namespace BizHawk.Client.EmuHawk private void VsInsertCoinP1MenuItem_Click(object sender, EventArgs e) { - if (Emulator is NES && ((NES)Emulator).IsVS) + if (Emulator is NES nes && nes.IsVS) { if (!Global.MovieSession.Movie.IsPlaying || Global.MovieSession.Movie.IsFinished) { @@ -1690,7 +1643,7 @@ namespace BizHawk.Client.EmuHawk private void VsInsertCoinP2MenuItem_Click(object sender, EventArgs e) { - if (Emulator is NES && ((NES)Emulator).IsVS) + if (Emulator is NES nes && nes.IsVS) { if (!Global.MovieSession.Movie.IsPlaying || Global.MovieSession.Movie.IsFinished) { @@ -1702,7 +1655,7 @@ namespace BizHawk.Client.EmuHawk private void VsServiceSwitchMenuItem_Click(object sender, EventArgs e) { - if (Emulator is NES && ((NES)Emulator).IsVS) + if (Emulator is NES nes && nes.IsVS) { if (!Global.MovieSession.Movie.IsPlaying || Global.MovieSession.Movie.IsFinished) { @@ -1842,7 +1795,7 @@ namespace BizHawk.Client.EmuHawk SMSDisplayOverscanMenuItem.Visible = Global.Game.System == "SMS" || Global.Game.System == "SG"; - + SMSOverclockMenuItem.Visible = SMSForceStereoMenuItem.Visible = SMSdisplayToolStripMenuItem.Visible = @@ -2013,7 +1966,7 @@ namespace BizHawk.Client.EmuHawk s.ControllerType = "Sports Pad"; PutCoreSyncSettings(s); } - + private void SMSControllerKeyboardToolStripMenuItem_Click(object sender, EventArgs e) { var s = ((SMS)Emulator).GetSyncSettings(); @@ -2119,7 +2072,7 @@ namespace BizHawk.Client.EmuHawk { GBPrefs.DoGBPrefsDialog(this); } - else // sameboy + else // SameBoy { GenericCoreConfig.DoDialog(this, "Gameboy Settings"); } @@ -2149,6 +2102,11 @@ namespace BizHawk.Client.EmuHawk #region GBA + private void GBACoreSettingsToolStripMenuItem_Click(object sender, EventArgs e) + { + GenericCoreConfig.DoDialog(this, "Gameboy Advance Settings"); + } + private void GbaGpuViewerMenuItem_Click(object sender, EventArgs e) { GlobalWin.Tools.Load(); @@ -2168,14 +2126,8 @@ namespace BizHawk.Client.EmuHawk private void GBACoreSelectionSubMenu_DropDownOpened(object sender, EventArgs e) { - GBAmGBAMenuItem.Checked = Global.Config.GBA_UsemGBA == true; - GBAVBANextMenuItem.Checked = Global.Config.GBA_UsemGBA == false; - } - - private void GbaWithmGBAMenuItem_Click(object sender, EventArgs e) - { - Global.Config.GBA_UsemGBA ^= true; - FlagNeedsReboot(); + GBAmGBAMenuItem.Checked = Global.Config.GBA_UsemGBA; + GBAVBANextMenuItem.Checked = !Global.Config.GBA_UsemGBA; } #endregion @@ -2256,6 +2208,11 @@ namespace BizHawk.Client.EmuHawk SNESOptions.DoSettingsDialog(this); } + private void Snes9xSettingsMenuItem_Click(object sender, EventArgs e) + { + GenericCoreConfig.DoDialog(this, "Snes9x Settings"); + } + #endregion #region Coleco @@ -2317,7 +2274,7 @@ namespace BizHawk.Client.EmuHawk } else { - // Do nothing, Reboot is being flagged already if they chaned anything + // Do nothing, Reboot is being flagged already if they changed anything } } else @@ -2443,7 +2400,7 @@ namespace BizHawk.Client.EmuHawk #region Wondersawn - private void WondersawnSettingsMenuItem_Click(object sender, EventArgs e) + private void WonderSwanSettingsMenuItem_Click(object sender, EventArgs e) { GenericCoreConfig.DoDialog(this, "WonderSwan Settings"); } @@ -2469,9 +2426,8 @@ namespace BizHawk.Client.EmuHawk { AppleDisksSubMenu.DropDownItems.Clear(); - if (Emulator is AppleII) + if (Emulator is AppleII appleII) { - var appleII = (AppleII)Emulator; for (int i = 0; i < appleII.DiskCount; i++) { var menuItem = new ToolStripMenuItem @@ -2508,9 +2464,8 @@ namespace BizHawk.Client.EmuHawk { C64DisksSubMenu.DropDownItems.Clear(); - if (Emulator is C64) + if (Emulator is C64 c64) { - var c64 = (C64)Emulator; for (int i = 0; i < c64.DiskCount; i++) { var menuItem = new ToolStripMenuItem @@ -2540,7 +2495,7 @@ namespace BizHawk.Client.EmuHawk #region Intv - private void IntvSubMenu_DropDownOpened(object sender, EventArgs e) + private void IntVSubMenu_DropDownOpened(object sender, EventArgs e) { IntVControllerSettingsMenuItem.Enabled = !Global.MovieSession.Movie.IsActive; } @@ -2550,260 +2505,271 @@ namespace BizHawk.Client.EmuHawk new IntvControllerSettings().ShowDialog(); } - #endregion + #endregion - #region ZXSpectrum + #region VirtualBoy + private void VirtualBoySettingsMenuItem_Click(object sender, EventArgs e) + { + GenericCoreConfig.DoDialog(this, "VirtualBoy Settings"); + } - private void zXSpectrumToolStripMenuItem_DropDownOpened(object sender, EventArgs e) - { + #endregion - } + #region NeoGeoPocket - - private void preferencesToolStripMenuItem4_Click(object sender, EventArgs e) - { - GenericCoreConfig.DoDialog(this, "ZXSpectrum Settings"); - } - + private void NeoGeoSettingsMenuItem_Click(object sender, EventArgs e) + { + GenericCoreConfig.DoDialog(this, "NeoPop Settings"); + } - private void ZXSpectrumControllerConfigurationMenuItem_Click(object sender, EventArgs e) - { - new ZXSpectrumJoystickSettings().ShowDialog(); - } + #endregion - private void ZXSpectrumCoreEmulationSettingsMenuItem_Click(object sender, EventArgs e) - { - new ZXSpectrumCoreEmulationSettings().ShowDialog(); - } + #region PC-FX - private void ZXSpectrumNonSyncSettingsMenuItem_Click(object sender, EventArgs e) - { - new ZXSpectrumNonSyncSettings().ShowDialog(); - } + private void PCFXSettingsMenuItem_Click(object sender, EventArgs e) + { + GenericCoreConfig.DoDialog(this, "PC-FX Settings"); + } - private void ZXSpectrumAudioSettingsMenuItem_Click(object sender, EventArgs e) - { - new ZXSpectrumAudioSettings().ShowDialog(); - } + #endregion - private void ZXSpectrumPokeMemoryMenuItem_Click(object sender, EventArgs e) - { - new ZXSpectrumPokeMemory().ShowDialog(); - } + #region ZXSpectrum - private void ZXSpectrumMediaMenuItem_DropDownOpened(object sender, EventArgs e) - { - if (Emulator is ZXSpectrum) - { - ZXSpectrumTapesSubMenu.Enabled = ((ZXSpectrum)Emulator)._tapeInfo.Count > 0; - ZXSpectrumDisksSubMenu.Enabled = ((ZXSpectrum)Emulator)._diskInfo.Count > 0; - } - } + private void ZXSpectrumControllerConfigurationMenuItem_Click(object sender, EventArgs e) + { + new ZXSpectrumJoystickSettings().ShowDialog(); + } - private void ZXSpectrumTapesSubMenu_DropDownOpened(object sender, EventArgs e) - { - ZXSpectrumTapesSubMenu.DropDownItems.Clear(); + private void ZXSpectrumCoreEmulationSettingsMenuItem_Click(object sender, EventArgs e) + { + new ZXSpectrumCoreEmulationSettings().ShowDialog(); + } - List items = new List(); + private void ZXSpectrumNonSyncSettingsMenuItem_Click(object sender, EventArgs e) + { + new ZXSpectrumNonSyncSettings().ShowDialog(); + } - if (Emulator is ZXSpectrum) - { - var speccy = (ZXSpectrum)Emulator; - var currSel = speccy._machine.TapeMediaIndex; + private void ZXSpectrumAudioSettingsMenuItem_Click(object sender, EventArgs e) + { + new ZXSpectrumAudioSettings().ShowDialog(); + } - for (int i = 0; i < speccy._tapeInfo.Count; i++) - { - string name = speccy._tapeInfo[i].Name; + private void ZXSpectrumPokeMemoryMenuItem_Click(object sender, EventArgs e) + { + new ZXSpectrumPokeMemory().ShowDialog(); + } - var menuItem = new ToolStripMenuItem - { - Name = $"{i}_{name}", - Text = $"{i}: {name}", - Checked = currSel == i - }; + private void ZXSpectrumMediaMenuItem_DropDownOpened(object sender, EventArgs e) + { + if (Emulator is ZXSpectrum) + { + ZXSpectrumTapesSubMenu.Enabled = ((ZXSpectrum)Emulator)._tapeInfo.Count > 0; + ZXSpectrumDisksSubMenu.Enabled = ((ZXSpectrum)Emulator)._diskInfo.Count > 0; + } + } - int dummy = i; - menuItem.Click += (o, ev) => - { - speccy._machine.TapeMediaIndex = dummy; - }; - - items.Add(menuItem); - } - } - - ZXSpectrumTapesSubMenu.DropDownItems.AddRange(items.ToArray()); - } - - private void ZXSpectrumDisksSubMenu_DropDownOpened(object sender, EventArgs e) - { - ZXSpectrumDisksSubMenu.DropDownItems.Clear(); - - List items = new List(); - - if (Emulator is ZXSpectrum) - { - var speccy = (ZXSpectrum)Emulator; - var currSel = speccy._machine.DiskMediaIndex; - - for (int i = 0; i < speccy._diskInfo.Count; i++) - { - string name = speccy._diskInfo[i].Name; - - var menuItem = new ToolStripMenuItem - { - Name = $"{i}_{name}", - Text = $"{i}: {name}", - Checked = currSel == i - }; - - int dummy = i; - menuItem.Click += (o, ev) => - { - speccy._machine.DiskMediaIndex = dummy; - }; - - items.Add(menuItem); - } - } - - ZXSpectrumDisksSubMenu.DropDownItems.AddRange(items.ToArray()); - } - - private void ZXSpectrumExportSnapshotMenuItemMenuItem_Click(object sender, EventArgs e) - { - SaveFileDialog zxSnapExpDialog = new SaveFileDialog(); - zxSnapExpDialog.RestoreDirectory = true; - zxSnapExpDialog.Title = "EXPERIMENTAL - Export 3rd party snapshot formats"; - zxSnapExpDialog.DefaultExt = "szx"; - zxSnapExpDialog.Filter = "ZX-State files (*.szx)|*.szx"; - zxSnapExpDialog.SupportMultiDottedExtensions = true; - - try - { - var res = zxSnapExpDialog.ShowDialog(); - if (res == DialogResult.OK) - { - var speccy = (ZXSpectrum)Emulator; - var snap = speccy.GetSZXSnapshot(); - File.WriteAllBytes(zxSnapExpDialog.FileName, snap); - //File.WriteAllText(zxSnapExpDialog.FileName, snap); - } - } - catch (Exception ex) - { - var ee = ex; - } - } - - #endregion - - #region AmstradCPC - - private void amstradCPCCoreEmulationSettingsToolStripMenuItem_Click(object sender, EventArgs e) - { - new AmstradCPCCoreEmulationSettings().ShowDialog(); - } - - private void AmstradCPCAudioSettingsToolStripMenuItem_Click(object sender, EventArgs e) - { - new AmstradCPCAudioSettings().ShowDialog(); - } - - private void AmstradCPCPokeMemoryToolStripMenuItem_Click(object sender, EventArgs e) - { - new AmstradCPCPokeMemory().ShowDialog(); - } - - private void AmstradCPCMediaToolStripMenuItem_DropDownOpened(object sender, EventArgs e) - { - if (Emulator is AmstradCPC) - { - AmstradCPCTapesSubMenu.Enabled = ((AmstradCPC)Emulator)._tapeInfo.Count > 0; - AmstradCPCDisksSubMenu.Enabled = ((AmstradCPC)Emulator)._diskInfo.Count > 0; - } - } - - private void AmstradCPCTapesSubMenu_DropDownOpened(object sender, EventArgs e) - { - AmstradCPCTapesSubMenu.DropDownItems.Clear(); + private void ZXSpectrumTapesSubMenu_DropDownOpened(object sender, EventArgs e) + { + ZXSpectrumTapesSubMenu.DropDownItems.Clear(); List items = new List(); - if (Emulator is AmstradCPC) - { - var ams = (AmstradCPC)Emulator; - var currSel = ams._machine.TapeMediaIndex; + if (Emulator is ZXSpectrum speccy) + { + var tapeMediaIndex = speccy._machine.TapeMediaIndex; - for (int i = 0; i < ams._tapeInfo.Count; i++) - { - string name = ams._tapeInfo[i].Name; + for (int i = 0; i < speccy._tapeInfo.Count; i++) + { + string name = speccy._tapeInfo[i].Name; - var menuItem = new ToolStripMenuItem - { - Name = $"{i}_{name}", - Text = $"{i}: {name}", - Checked = currSel == i - }; + var menuItem = new ToolStripMenuItem + { + Name = $"{i}_{name}", + Text = $"{i}: {name}", + Checked = tapeMediaIndex == i + }; - int dummy = i; - menuItem.Click += (o, ev) => - { - ams._machine.TapeMediaIndex = dummy; - }; + int dummy = i; + menuItem.Click += (o, ev) => + { + speccy._machine.TapeMediaIndex = dummy; + }; items.Add(menuItem); } - } + } + + ZXSpectrumTapesSubMenu.DropDownItems.AddRange(items.ToArray()); + } + + private void ZXSpectrumDisksSubMenu_DropDownOpened(object sender, EventArgs e) + { + ZXSpectrumDisksSubMenu.DropDownItems.Clear(); + + var items = new List(); + + if (Emulator is ZXSpectrum speccy) + { + var diskMediaIndex = speccy._machine.DiskMediaIndex; + + for (int i = 0; i < speccy._diskInfo.Count; i++) + { + string name = speccy._diskInfo[i].Name; + + var menuItem = new ToolStripMenuItem + { + Name = $"{i}_{name}", + Text = $"{i}: {name}", + Checked = diskMediaIndex == i + }; + + int dummy = i; + menuItem.Click += (o, ev) => + { + speccy._machine.DiskMediaIndex = dummy; + }; + + items.Add(menuItem); + } + } + + ZXSpectrumDisksSubMenu.DropDownItems.AddRange(items.ToArray()); + } + + private void ZXSpectrumExportSnapshotMenuItemMenuItem_Click(object sender, EventArgs e) + { + var zxSnapExpDialog = new SaveFileDialog + { + RestoreDirectory = true + , Title = "EXPERIMENTAL - Export 3rd party snapshot formats" + , DefaultExt = "szx" + , Filter = "ZX-State files (*.szx)|*.szx" + , SupportMultiDottedExtensions = true + }; + + try + { + var res = zxSnapExpDialog.ShowDialog(); + if (res == DialogResult.OK) + { + var speccy = (ZXSpectrum)Emulator; + var snap = speccy.GetSZXSnapshot(); + File.WriteAllBytes(zxSnapExpDialog.FileName, snap); + } + } + catch (Exception ex) + { + var ee = ex; + } + } + + #endregion + + #region AmstradCPC + + private void amstradCPCCoreEmulationSettingsToolStripMenuItem_Click(object sender, EventArgs e) + { + new AmstradCPCCoreEmulationSettings().ShowDialog(); + } + + private void AmstradCPCAudioSettingsToolStripMenuItem_Click(object sender, EventArgs e) + { + new AmstradCPCAudioSettings().ShowDialog(); + } + + private void AmstradCPCPokeMemoryToolStripMenuItem_Click(object sender, EventArgs e) + { + new AmstradCPCPokeMemory().ShowDialog(); + } + + private void AmstradCPCMediaToolStripMenuItem_DropDownOpened(object sender, EventArgs e) + { + if (Emulator is AmstradCPC) + { + AmstradCPCTapesSubMenu.Enabled = ((AmstradCPC)Emulator)._tapeInfo.Count > 0; + AmstradCPCDisksSubMenu.Enabled = ((AmstradCPC)Emulator)._diskInfo.Count > 0; + } + } + + private void AmstradCPCTapesSubMenu_DropDownOpened(object sender, EventArgs e) + { + AmstradCPCTapesSubMenu.DropDownItems.Clear(); + + var items = new List(); + + if (Emulator is AmstradCPC ams) + { + var tapeMediaIndex = ams._machine.TapeMediaIndex; + + for (int i = 0; i < ams._tapeInfo.Count; i++) + { + string name = ams._tapeInfo[i].Name; + + var menuItem = new ToolStripMenuItem + { + Name = $"{i}_{name}", + Text = $"{i}: {name}", + Checked = tapeMediaIndex == i + }; + + int dummy = i; + menuItem.Click += (o, ev) => + { + ams._machine.TapeMediaIndex = dummy; + }; + + items.Add(menuItem); + } + } AmstradCPCTapesSubMenu.DropDownItems.AddRange(items.ToArray()); } - private void AmstradCPCDisksSubMenu_DropDownOpened(object sender, EventArgs e) - { + private void AmstradCPCDisksSubMenu_DropDownOpened(object sender, EventArgs e) + { AmstradCPCDisksSubMenu.DropDownItems.Clear(); - List items = new List(); + var items = new List(); - if (Emulator is AmstradCPC) - { - var ams = (AmstradCPC)Emulator; - var currSel = ams._machine.DiskMediaIndex; + if (Emulator is AmstradCPC ams) + { + var diskMediaIndex = ams._machine.DiskMediaIndex; - for (int i = 0; i < ams._diskInfo.Count; i++) - { - string name = ams._diskInfo[i].Name; + for (int i = 0; i < ams._diskInfo.Count; i++) + { + string name = ams._diskInfo[i].Name; - var menuItem = new ToolStripMenuItem - { - Name = $"{i}_{name}", - Text = $"{i}: {name}", - Checked = currSel == i - }; + var menuItem = new ToolStripMenuItem + { + Name = $"{i}_{name}", + Text = $"{i}: {name}", + Checked = diskMediaIndex == i + }; - int dummy = i; - menuItem.Click += (o, ev) => - { - ams._machine.DiskMediaIndex = dummy; - }; + int dummy = i; + menuItem.Click += (o, ev) => + { + ams._machine.DiskMediaIndex = dummy; + }; items.Add(menuItem); } - } + } AmstradCPCDisksSubMenu.DropDownItems.AddRange(items.ToArray()); } - private void AmstradCPCNonSyncSettingsToolStripMenuItem_Click(object sender, EventArgs e) - { - new AmstradCPCNonSyncSettings().ShowDialog(); - } + private void AmstradCPCNonSyncSettingsToolStripMenuItem_Click(object sender, EventArgs e) + { + new AmstradCPCNonSyncSettings().ShowDialog(); + } - #endregion + #endregion - #region Help + #region Help - private void HelpSubMenu_DropDownOpened(object sender, EventArgs e) + private void HelpSubMenu_DropDownOpened(object sender, EventArgs e) { FeaturesMenuItem.Visible = VersionInfo.DeveloperBuild; } @@ -2853,9 +2819,9 @@ namespace BizHawk.Client.EmuHawk showMenuVisible = true; // need to always be able to restore this as an emergency measure } - if (argParser._chromeless) + if (_argParser._chromeless) { - showMenuVisible = true; // I decided this was always possible in chromeless mode, we'll see what they think + showMenuVisible = true; // I decided this was always possible in chrome-less mode, we'll see what they think } ShowMenuContextMenuItem.Visible = @@ -3297,7 +3263,7 @@ namespace BizHawk.Client.EmuHawk { try { - FormDragDrop_Internal(sender, e); + _FormDragDrop_internal(sender, e); } catch (Exception ex) { @@ -3305,113 +3271,6 @@ namespace BizHawk.Client.EmuHawk } } - private void FormDragDrop_Internal(object sender, DragEventArgs e) - { - _FormDragDrop_internal(sender, e); -/* - var filePaths = (string[])e.Data.GetData(DataFormats.FileDrop); - var isLua = false; - foreach (var path in filePaths) - { - var extension = Path.GetExtension(path); - if (extension != null && extension.ToUpper() == ".LUA") - { - OpenLuaConsole(); - if (GlobalWin.Tools.Has()) - { - GlobalWin.Tools.LuaConsole.LoadLuaFile(path); - } - isLua = true; - } - } - if (isLua) - { - return; - } - - var ext = Path.GetExtension(filePaths[0]) ?? ""; - if (ext.ToUpper() == ".LUASES") - { - OpenLuaConsole(); - if (GlobalWin.Tools.Has()) - { - GlobalWin.Tools.LuaConsole.LoadLuaSession(filePaths[0]); - } - } - else if (MovieService.IsValidMovieExtension(ext)) - { - if (Emulator.IsNull()) - { - OpenRom(); - } - - if (Emulator.IsNull()) - { - return; - } - - StartNewMovie(MovieService.Get(filePaths[0]), false); - } - else if (ext.ToUpper() == ".STATE") - { - LoadState(filePaths[0], Path.GetFileName(filePaths[0])); - } - else if (ext.ToUpper() == ".CHT") - { - Global.CheatList.Load(filePaths[0], false); - GlobalWin.Tools.Load(); - } - else if (ext.ToUpper() == ".WCH") - { - GlobalWin.Tools.LoadRamWatch(true); - (GlobalWin.Tools.Get() as RamWatch).LoadWatchFile(new FileInfo(filePaths[0]), false); - } - - else if (ext.ToUpper() == ".CDL" && Emulator is PCEngine) - { - GlobalWin.Tools.Load(); - (GlobalWin.Tools.Get() as CDL).LoadFile(filePaths[0]); - } - - else if (MovieImport.IsValidMovieExtension(Path.GetExtension(filePaths[0]))) - { - if (Emulator.IsNull()) - { - OpenRom(); - } - - if (Emulator.IsNull()) - { - return; - } - - // tries to open a legacy movie format by importing it - string errorMsg; - string warningMsg; - var movie = MovieImport.ImportFile(filePaths[0], out errorMsg, out warningMsg); - if (!string.IsNullOrEmpty(errorMsg)) - { - MessageBox.Show(errorMsg, "Conversion error", MessageBoxButtons.OK, MessageBoxIcon.Error); - } - else - { - // fix movie extension to something palatable for these purposes. - // for instance, something which doesnt clobber movies you already may have had. - // i'm evenly torn between this, and a file in %TEMP%, but since we dont really have a way to clean up this tempfile, i choose this: - StartNewMovie(movie, false); - } - - GlobalWin.OSD.AddMessage(warningMsg); - } - else - { - var args = new LoadRomArgs(); - args.OpenAdvanced = new OpenAdvanced_OpenRom { Path = filePaths[0] }; - LoadRom(filePaths[0], args); - } - */ - } - #endregion } } diff --git a/BizHawk.Client.EmuHawk/MainForm.Hotkey.cs b/BizHawk.Client.EmuHawk/MainForm.Hotkey.cs index 130d640a0f..464ea13f66 100644 --- a/BizHawk.Client.EmuHawk/MainForm.Hotkey.cs +++ b/BizHawk.Client.EmuHawk/MainForm.Hotkey.cs @@ -347,7 +347,10 @@ namespace BizHawk.Client.EmuHawk type = " (on)"; } - Global.CheatList.ToList().ForEach(x => x.Toggle()); + foreach (var x in Global.CheatList) + { + x.Toggle(); + } GlobalWin.OSD.AddMessage($"Cheats toggled{type}"); } diff --git a/BizHawk.Client.EmuHawk/MainForm.cs b/BizHawk.Client.EmuHawk/MainForm.cs index 444e73cc3d..1661e2eca6 100644 --- a/BizHawk.Client.EmuHawk/MainForm.cs +++ b/BizHawk.Client.EmuHawk/MainForm.cs @@ -25,7 +25,6 @@ using BizHawk.Emulation.Cores.Nintendo.NES; using BizHawk.Emulation.Cores.Nintendo.SNES; using BizHawk.Emulation.Cores.Nintendo.N64; using BizHawk.Emulation.Cores.Nintendo.GBHawkLink; -using BizHawk.Emulation.Cores.Sega.GGHawkLink; using BizHawk.Client.EmuHawk.WinFormExtensions; using BizHawk.Client.EmuHawk.ToolExtensions; @@ -34,7 +33,6 @@ using BizHawk.Client.ApiHawk; using BizHawk.Emulation.Common.Base_Implementations; using BizHawk.Emulation.Cores.Nintendo.SNES9X; using BizHawk.Emulation.Cores.Consoles.SNK; -using BizHawk.Emulation.Cores.Consoles.Sega.PicoDrive; using BizHawk.Emulation.Cores.Consoles.Nintendo.Gameboy; namespace BizHawk.Client.EmuHawk @@ -47,11 +45,11 @@ namespace BizHawk.Client.EmuHawk { SetWindowText(); - // Hide Status bar icons and general statusbar prep + // Hide Status bar icons and general StatusBar prep MainStatusBar.Padding = new Padding(MainStatusBar.Padding.Left, MainStatusBar.Padding.Top, MainStatusBar.Padding.Left, MainStatusBar.Padding.Bottom); // Workaround to remove extra padding on right PlayRecordStatusButton.Visible = false; AVIStatusLabel.Visible = false; - SetPauseStatusbarIcon(); + SetPauseStatusBarIcon(); ToolFormBase.UpdateCheatRelatedTools(null, null); RebootStatusBarIcon.Visible = false; UpdateNotification.Visible = false; @@ -83,20 +81,19 @@ namespace BizHawk.Client.EmuHawk static MainForm() { - // If this isnt here, then our assemblyresolving hacks wont work due to the check for MainForm.INTERIM - // its.. weird. dont ask. + // If this isn't here, then our assembly resolving hacks wont work due to the check for MainForm.INTERIM + // its.. weird. don't ask. } private CoreComm CreateCoreComm() { - CoreComm ret = new CoreComm(ShowMessageCoreComm, NotifyCoreComm) + return new CoreComm(ShowMessageCoreComm, NotifyCoreComm) { ReleaseGLContext = o => GlobalWin.GLManager.ReleaseGLContext(o), RequestGLContext = (major, minor, forward) => GlobalWin.GLManager.CreateGLContext(major, minor, forward), ActivateGLContext = gl => GlobalWin.GLManager.Activate((GLManager.ContextRef)gl), DeactivateGLContext = () => GlobalWin.GLManager.Deactivate() }; - return ret; } public MainForm(string[] args) @@ -157,13 +154,13 @@ namespace BizHawk.Client.EmuHawk }; try { - argParser.ParseArguments(args); + _argParser.ParseArguments(args); } catch (ArgParserException e) { MessageBox.Show(e.Message); } - + Database.LoadDatabase(Path.Combine(PathManager.GetExeDirectoryAbsolute(), "gamedb", "gamedb.txt")); @@ -281,14 +278,14 @@ namespace BizHawk.Client.EmuHawk Location = new Point(Global.Config.MainWndx, Global.Config.MainWndy); } - if (argParser.cmdRom != null) + if (_argParser.cmdRom != null) { // Commandline should always override auto-load - var ioa = OpenAdvancedSerializer.ParseWithLegacy(argParser.cmdRom); - LoadRom(argParser.cmdRom, new LoadRomArgs { OpenAdvanced = ioa }); + var ioa = OpenAdvancedSerializer.ParseWithLegacy(_argParser.cmdRom); + LoadRom(_argParser.cmdRom, new LoadRomArgs { OpenAdvanced = ioa }); if (Global.Game == null) { - MessageBox.Show($"Failed to load {argParser.cmdRom} specified on commandline"); + MessageBox.Show($"Failed to load {_argParser.cmdRom} specified on commandline"); } } else if (Global.Config.RecentRoms.AutoLoad && !Global.Config.RecentRoms.Empty) @@ -296,14 +293,14 @@ namespace BizHawk.Client.EmuHawk LoadRomFromRecent(Global.Config.RecentRoms.MostRecent); } - if (argParser.audiosync.HasValue) + if (_argParser.audiosync.HasValue) { - Global.Config.VideoWriterAudioSync = argParser.audiosync.Value; + Global.Config.VideoWriterAudioSync = _argParser.audiosync.Value; } - if (argParser.cmdMovie != null) + if (_argParser.cmdMovie != null) { - _supressSyncSettingsWarning = true; // We dont' want to be nagged if we are attempting to automate + _suppressSyncSettingsWarning = true; // We don't want to be nagged if we are attempting to automate if (Global.Game == null) { OpenRom(); @@ -312,21 +309,19 @@ namespace BizHawk.Client.EmuHawk // If user picked a game, then do the commandline logic if (!Global.Game.IsNullInstance) { - var movie = MovieService.Get(argParser.cmdMovie); + var movie = MovieService.Get(_argParser.cmdMovie); Global.MovieSession.ReadOnly = true; - // if user is dumping and didnt supply dump length, make it as long as the loaded movie - if (argParser._autoDumpLength == 0) + // if user is dumping and didn't supply dump length, make it as long as the loaded movie + if (_argParser._autoDumpLength == 0) { - argParser._autoDumpLength = movie.InputLogLength; + _argParser._autoDumpLength = movie.InputLogLength; } // Copy pasta from drag & drop - if (MovieImport.IsValidMovieExtension(Path.GetExtension(argParser.cmdMovie))) + if (MovieImport.IsValidMovieExtension(Path.GetExtension(_argParser.cmdMovie))) { - string errorMsg; - string warningMsg; - var imported = MovieImport.ImportFile(argParser.cmdMovie, out errorMsg, out warningMsg); + var imported = MovieImport.ImportFile(_argParser.cmdMovie, out var errorMsg, out var warningMsg); if (!string.IsNullOrEmpty(errorMsg)) { MessageBox.Show(errorMsg, "Conversion error", MessageBoxButtons.OK, MessageBoxIcon.Error); @@ -344,10 +339,10 @@ namespace BizHawk.Client.EmuHawk else { StartNewMovie(movie, false); - Global.Config.RecentMovies.Add(argParser.cmdMovie); + Global.Config.RecentMovies.Add(_argParser.cmdMovie); } - _supressSyncSettingsWarning = false; + _suppressSyncSettingsWarning = false; } } else if (Global.Config.RecentMovies.AutoLoad && !Global.Config.RecentMovies.Empty) @@ -371,20 +366,20 @@ namespace BizHawk.Client.EmuHawk } } - if (argParser.startFullscreen || Global.Config.StartFullscreen) + if (_argParser.startFullscreen || Global.Config.StartFullscreen) { _needsFullscreenOnLoad = true; } if (!Global.Game.IsNullInstance) { - if (argParser.cmdLoadState != null) + if (_argParser.cmdLoadState != null) { - LoadState(argParser.cmdLoadState, Path.GetFileName(argParser.cmdLoadState)); + LoadState(_argParser.cmdLoadState, Path.GetFileName(_argParser.cmdLoadState)); } - else if (argParser.cmdLoadSlot != null) + else if (_argParser.cmdLoadSlot != null) { - LoadQuickSave($"QuickSave{argParser.cmdLoadSlot}"); + LoadQuickSave($"QuickSave{_argParser.cmdLoadSlot}"); } else if (Global.Config.AutoLoadLastSaveSlot) { @@ -393,14 +388,14 @@ namespace BizHawk.Client.EmuHawk } //start Lua Console if requested in the command line arguments - if (argParser.luaConsole) + if (_argParser.luaConsole) { GlobalWin.Tools.Load(); } //load Lua Script if requested in the command line arguments - if (argParser.luaScript != null) + if (_argParser.luaScript != null) { - GlobalWin.Tools.LuaConsole.LoadLuaFile(argParser.luaScript); + GlobalWin.Tools.LuaConsole.LoadLuaFile(_argParser.luaScript); } GlobalWin.Tools.AutoLoad(); @@ -421,11 +416,11 @@ namespace BizHawk.Client.EmuHawk { PauseEmulator(); } - + // start dumping, if appropriate - if (argParser.cmdDumpType != null && argParser.cmdDumpName != null) + if (_argParser.cmdDumpType != null && _argParser.cmdDumpName != null) { - RecordAv(argParser.cmdDumpType, argParser.cmdDumpName); + RecordAv(_argParser.cmdDumpType, _argParser.cmdDumpName); } SetMainformMovieInfo(); @@ -438,7 +433,7 @@ namespace BizHawk.Client.EmuHawk }; } - private readonly bool _supressSyncSettingsWarning; + private readonly bool _suppressSyncSettingsWarning; public int ProgramRunLoop() { @@ -461,7 +456,7 @@ namespace BizHawk.Client.EmuHawk InitializeFpsData(); - for (;;) + for (; ; ) { Input.Instance.Update(); @@ -551,10 +546,7 @@ namespace BizHawk.Client.EmuHawk private bool _emulatorPaused; public bool EmulatorPaused { - get - { - return _emulatorPaused; - } + get => _emulatorPaused; private set { @@ -578,7 +570,7 @@ namespace BizHawk.Client.EmuHawk Paused = paused; } - public bool Paused { get; private set; } + public bool Paused { get; } } #endregion @@ -596,20 +588,19 @@ namespace BizHawk.Client.EmuHawk // runloop won't exec lua public bool SuppressLua { get; set; } + public AdvancedRomLoaderType AdvancedLoader { get; set; } + public long MouseWheelTracker { get; private set; } private int? _pauseOnFrame; public int? PauseOnFrame // If set, upon completion of this frame, the client wil pause { - get - { - return _pauseOnFrame; - } + get => _pauseOnFrame; set { _pauseOnFrame = value; - SetPauseStatusbarIcon(); + SetPauseStatusBarIcon(); if (value == null) // TODO: make an Event handler instead, but the logic here is that after turbo seeking, tools will want to do a real update when the emulator finally pauses { @@ -621,9 +612,7 @@ namespace BizHawk.Client.EmuHawk } public bool IsSeeking => PauseOnFrame.HasValue; - private bool IsTurboSeeking => PauseOnFrame.HasValue && Global.Config.TurboSeek; - public bool IsTurboing => Global.ClientControls["Turbo"] || IsTurboSeeking; #endregion @@ -650,27 +639,21 @@ namespace BizHawk.Client.EmuHawk /// /// Controls whether the app generates input events. should be turned off for most modal dialogs /// - public bool AllowInput(bool yieldAlt) + public Input.AllowInput AllowInput(bool yieldAlt) { // the main form gets input if (ActiveForm == this) { - return true; + return Input.AllowInput.All; } // even more special logic for TAStudio: // TODO - implement by event filter in TAStudio - var maybeTAStudio = ActiveForm as TAStudio; - if (maybeTAStudio != null) + if (ActiveForm is TAStudio maybeTAStudio) { - if (yieldAlt) + if (yieldAlt || maybeTAStudio.IsInMenuLoop) { - return false; - } - - if (maybeTAStudio.IsInMenuLoop) - { - return false; + return Input.AllowInput.None; } } @@ -680,26 +663,23 @@ namespace BizHawk.Client.EmuHawk || ActiveForm is TAStudio || ActiveForm is VirtualpadTool) { - return true; + return Input.AllowInput.All; } // if no form is active on this process, then the background input setting applies if (ActiveForm == null && Global.Config.AcceptBackgroundInput) { - return true; + return Global.Config.AcceptBackgroundInputControllerOnly ? Input.AllowInput.OnlyController : Input.AllowInput.All; } - return false; + return Input.AllowInput.None; } // TODO: make this an actual property, set it when loading a Rom, and pass it dialogs, etc // This is a quick hack to reduce the dependency on Global.Emulator private IEmulator Emulator { - get - { - return Global.Emulator; - } + get => Global.Emulator; set { @@ -727,9 +707,9 @@ namespace BizHawk.Client.EmuHawk private void ProcessInput() { - ControllerInputCoalescer conInput = (ControllerInputCoalescer)Global.ControllerInputCoalescer; + var conInput = (ControllerInputCoalescer)Global.ControllerInputCoalescer; - for (;;) + for (; ; ) { // loop through all available events var ie = Input.Instance.DequeueEvent(); @@ -765,11 +745,11 @@ namespace BizHawk.Client.EmuHawk } } - // ordinarily, an alt release with nothing else would move focus to the menubar. but that is sort of useless, and hard to implement exactly right. + // ordinarily, an alt release with nothing else would move focus to the MenuBar. but that is sort of useless, and hard to implement exactly right. } // zero 09-sep-2012 - all input is eligible for controller input. not sure why the above was done. - // maybe because it doesnt make sense to me to bind hotkeys and controller inputs to the same keystrokes + // maybe because it doesn't make sense to me to bind hotkeys and controller inputs to the same keystrokes // adelikat 02-dec-2012 - implemented options for how to handle controller vs hotkey conflicts. This is primarily motivated by computer emulation and thus controller being nearly the entire keyboard bool handled; @@ -785,14 +765,14 @@ namespace BizHawk.Client.EmuHawk handled = triggers.Aggregate(handled, (current, trigger) => current | CheckHotkey(trigger)); } - // hotkeys which arent handled as actions get coalesced as pollable virtual client buttons + // hotkeys which aren't handled as actions get coalesced as pollable virtual client buttons if (!handled) { _hotkeyCoalescer.Receive(ie); } break; - case 1: // Input overrides Hokeys + case 1: // Input overrides Hotkeys conInput.Receive(ie); if (!Global.ActiveController.HasBinding(ie.LogicalButton.ToString())) { @@ -802,7 +782,7 @@ namespace BizHawk.Client.EmuHawk handled = triggers.Aggregate(handled, (current, trigger) => current | CheckHotkey(trigger)); } - // hotkeys which arent handled as actions get coalesced as pollable virtual client buttons + // hotkeys which aren't handled as actions get coalesced as pollable virtual client buttons if (!handled) { _hotkeyCoalescer.Receive(ie); @@ -817,12 +797,12 @@ namespace BizHawk.Client.EmuHawk handled = triggers.Aggregate(handled, (current, trigger) => current | CheckHotkey(trigger)); } - // hotkeys which arent handled as actions get coalesced as pollable virtual client buttons + // hotkeys which aren't handled as actions get coalesced as pollable virtual client buttons if (!handled) { _hotkeyCoalescer.Receive(ie); - // Check for hotkeys that may not be handled through Checkhotkey() method, reject controller input mapped to these + // Check for hotkeys that may not be handled through CheckHotkey() method, reject controller input mapped to these if (!triggers.Any(IsInternalHotkey)) { conInput.Receive(ie); @@ -857,33 +837,26 @@ namespace BizHawk.Client.EmuHawk public void RebootCore() { - var ioa = OpenAdvancedSerializer.ParseWithLegacy(_currentlyOpenRomPoopForAdvancedLoaderPleaseRefactorMe); - if (ioa is OpenAdvanced_LibretroNoGame) - { - LoadRom("", CurrentlyOpenRomArgs); - } - else - { - LoadRom(ioa.SimplePath, CurrentlyOpenRomArgs); - } + if (CurrentlyOpenRomArgs == null) return; + LoadRom(CurrentlyOpenRomArgs.OpenAdvanced.SimplePath, CurrentlyOpenRomArgs); } public void PauseEmulator() { EmulatorPaused = true; - SetPauseStatusbarIcon(); + SetPauseStatusBarIcon(); } public void UnpauseEmulator() { EmulatorPaused = false; - SetPauseStatusbarIcon(); + SetPauseStatusBarIcon(); } public void TogglePause() { EmulatorPaused ^= true; - SetPauseStatusbarIcon(); + SetPauseStatusBarIcon(); // TODO: have tastudio set a pause status change callback, or take control over pause if (GlobalWin.Tools.Has()) @@ -1027,15 +1000,15 @@ namespace BizHawk.Client.EmuHawk { // TODO - maybe apply a hack tracked during fullscreen here to override it FormBorderStyle = FormBorderStyle.None; - MainMenuStrip.Visible = Global.Config.DispChrome_MenuFullscreen && !argParser._chromeless; - MainStatusBar.Visible = Global.Config.DispChrome_StatusBarFullscreen && !argParser._chromeless; + MainMenuStrip.Visible = Global.Config.DispChrome_MenuFullscreen && !_argParser._chromeless; + MainStatusBar.Visible = Global.Config.DispChrome_StatusBarFullscreen && !_argParser._chromeless; } else { - MainStatusBar.Visible = Global.Config.DispChrome_StatusBarWindowed && !argParser._chromeless; - MainMenuStrip.Visible = Global.Config.DispChrome_MenuWindowed && !argParser._chromeless; - MaximizeBox = MinimizeBox = Global.Config.DispChrome_CaptionWindowed && !argParser._chromeless; - if (Global.Config.DispChrome_FrameWindowed == 0 || argParser._chromeless) + MainStatusBar.Visible = Global.Config.DispChrome_StatusBarWindowed && !_argParser._chromeless; + MainMenuStrip.Visible = Global.Config.DispChrome_MenuWindowed && !_argParser._chromeless; + MaximizeBox = MinimizeBox = Global.Config.DispChrome_CaptionWindowed && !_argParser._chromeless; + if (Global.Config.DispChrome_FrameWindowed == 0 || _argParser._chromeless) { FormBorderStyle = FormBorderStyle.None; } @@ -1070,17 +1043,17 @@ namespace BizHawk.Client.EmuHawk // Work around an AMD driver bug in >= vista: // It seems windows will activate opengl fullscreen mode when a GL control is occupying the exact space of a screen (0,0 and dimensions=screensize) // AMD cards manifest a problem under these circumstances, flickering other monitors. - // It isnt clear whether nvidia cards are failing to employ this optimization, or just not flickering. - // (this could be determined with more work; other side affects of the fullscreen mode include: corrupted taskbar, no modal boxes on top of GL control, no screenshots) + // It isn't clear whether nvidia cards are failing to employ this optimization, or just not flickering. + // (this could be determined with more work; other side affects of the fullscreen mode include: corrupted TaskBar, no modal boxes on top of GL control, no screenshots) // At any rate, we can solve this by adding a 1px black border around the GL control // Please note: It is important to do this before resizing things, otherwise momentarily a GL control without WS_BORDER will be at the magic dimensions and cause the flakeout if (OSTailoredCode.CurrentOS == OSTailoredCode.DistinctOS.Windows && Global.Config.DispFullscreenHacks && Global.Config.DispMethod == Config.EDispMethod.OpenGL) { - //ATTENTION: this causes the statusbar to not work well, since the backcolor is now set to black instead of SystemColors.Control. - //It seems that some statusbar elements composite with the backcolor. - //Maybe we could add another control under the statusbar. with a different backcolor + // ATTENTION: this causes the StatusBar to not work well, since the backcolor is now set to black instead of SystemColors.Control. + // It seems that some StatusBar elements composite with the backcolor. + // Maybe we could add another control under the StatusBar. with a different backcolor Padding = new Padding(1); BackColor = Color.Black; @@ -1105,11 +1078,11 @@ namespace BizHawk.Client.EmuHawk if (OSTailoredCode.CurrentOS == OSTailoredCode.DistinctOS.Windows) { - // do this even if DispFullscreenHacks arent enabled, to restore it in case it changed underneath us or something + // do this even if DispFullscreenHacks aren't enabled, to restore it in case it changed underneath us or something Padding = new Padding(0); - // it's important that we set the form color back to this, because the statusbar icons blend onto the mainform, not onto the statusbar-- - // so we need the statusbar and mainform backdrop color to match + // it's important that we set the form color back to this, because the StatusBar icons blend onto the mainform, not onto the StatusBar-- + // so we need the StatusBar and mainform backdrop color to match BackColor = SystemColors.Control; } @@ -1200,8 +1173,6 @@ namespace BizHawk.Client.EmuHawk } } - private LibsnesCore AsSNES => Emulator as LibsnesCore; - private void SNES_ToggleBg(int layer) { if (!(Emulator is LibsnesCore) && !(Emulator is Snes9x)) @@ -1363,7 +1334,7 @@ namespace BizHawk.Client.EmuHawk private AutofireController _autofireNullControls; - // Sound refator TODO: we can enforce async mode here with a property that gets/sets this but does an async check + // Sound refactor TODO: we can enforce async mode here with a property that gets/sets this but does an async check private ISoundProvider _aviSoundInputAsync; // Note: This sound provider must be in async mode! private SimpleSyncSoundProvider _dumpProxy; // an audio proxy used for dumping @@ -1404,7 +1375,7 @@ namespace BizHawk.Client.EmuHawk private int _lastOpenRomFilter; - private ArgParser argParser = new ArgParser(); + private readonly ArgParser _argParser = new ArgParser(); // Resources private Bitmap _statusBarDiskLightOnImage; @@ -1419,7 +1390,7 @@ namespace BizHawk.Client.EmuHawk public PresentationPanel PresentationPanel { get; } - //countdown for saveram autoflushing + // countdown for saveram autoflushing public int AutoFlushSaveRamIn { get; set; } #endregion @@ -1474,7 +1445,7 @@ namespace BizHawk.Client.EmuHawk } } - if (!Global.Config.DispChrome_CaptionWindowed || argParser._chromeless) + if (!Global.Config.DispChrome_CaptionWindowed || _argParser._chromeless) { str = ""; } @@ -1507,11 +1478,7 @@ namespace BizHawk.Client.EmuHawk DumpStatusButton.Image = Properties.Resources.Blank; DumpStatusButton.ToolTipText = ""; - if (Emulator.IsNull()) - { - return; - } - else if (Global.Game == null) + if (Emulator.IsNull() || Global.Game == null) { return; } @@ -1563,10 +1530,10 @@ namespace BizHawk.Client.EmuHawk { annotation = Emulator.CoreComm.RomStatusAnnotation; - if (annotation == "Multi-disk bundler") - { - DumpStatusButton.Image = Properties.Resources.RetroQuestion; - } + if (annotation == "Multi-disk bundler") + { + DumpStatusButton.Image = Properties.Resources.RetroQuestion; + } } DumpStatusButton.ToolTipText = annotation; @@ -1598,8 +1565,8 @@ namespace BizHawk.Client.EmuHawk } else { - var oldram = Emulator.AsSaveRam().CloneSaveRam(); - if (oldram == null) + var oldRam = Emulator.AsSaveRam().CloneSaveRam(); + if (oldRam == null) { // we're eating this one now. The possible negative consequence is that a user could lose // their saveram and not know why @@ -1608,7 +1575,7 @@ namespace BizHawk.Client.EmuHawk } // why do we silently truncate\pad here instead of warning\erroring? - sram = new byte[oldram.Length]; + sram = new byte[oldRam.Length]; using (var reader = new BinaryReader( new FileStream(PathManager.SaveRamPath(Global.Game), FileMode.Open, FileAccess.Read))) { @@ -1624,7 +1591,7 @@ namespace BizHawk.Client.EmuHawk GlobalWin.OSD.AddMessage("An error occurred while loading Sram"); } } - } + } public bool FlushSaveRAM(bool autosave = false) { @@ -1647,15 +1614,15 @@ namespace BizHawk.Client.EmuHawk var backupFile = new FileInfo(backupPath); if (file.Directory != null && !file.Directory.Exists) { - try - { - file.Directory.Create(); - } - catch - { - GlobalWin.OSD.AddMessage($"Unable to flush SaveRAM to: {newFile.Directory}"); - return false; - } + try + { + file.Directory.Create(); + } + catch + { + GlobalWin.OSD.AddMessage($"Unable to flush SaveRAM to: {newFile.Directory}"); + return false; + } } var writer = new BinaryWriter(new FileStream(newPath, FileMode.Create, FileAccess.Write)); @@ -1687,7 +1654,7 @@ namespace BizHawk.Client.EmuHawk newFile.MoveTo(path); } - return true; + return true; } private void RewireSound() @@ -1741,8 +1708,8 @@ namespace BizHawk.Client.EmuHawk sNESToolStripMenuItem.Visible = false; neoGeoPocketToolStripMenuItem.Visible = false; pCFXToolStripMenuItem.Visible = false; - zXSpectrumToolStripMenuItem.Visible = false; - amstradCPCToolStripMenuItem.Visible = false; + zXSpectrumToolStripMenuItem.Visible = false; + amstradCPCToolStripMenuItem.Visible = false; VectrexSubMenu.Visible = false; switch (system) @@ -1822,7 +1789,7 @@ namespace BizHawk.Client.EmuHawk else { DGBSubMenu.Visible = true; - } + } break; case "WSWAN": wonderSwanToolStripMenuItem.Visible = true; @@ -1845,17 +1812,17 @@ namespace BizHawk.Client.EmuHawk case "PCFX": pCFXToolStripMenuItem.Visible = true; break; - case "ZXSpectrum": - zXSpectrumToolStripMenuItem.Visible = true; + case "ZXSpectrum": + zXSpectrumToolStripMenuItem.Visible = true; #if DEBUG - ZXSpectrumExportSnapshotMenuItemMenuItem.Visible = true; + ZXSpectrumExportSnapshotMenuItemMenuItem.Visible = true; #else - ZXSpectrumExportSnapshotMenuItemMenuItem.Visible = false; + ZXSpectrumExportSnapshotMenuItemMenuItem.Visible = false; #endif - break; - case "AmstradCPC": - amstradCPCToolStripMenuItem.Visible = true; - break; + break; + case "AmstradCPC": + amstradCPCToolStripMenuItem.Visible = true; + break; case "GGL": GGLSubMenu.Visible = true; break; @@ -1921,7 +1888,7 @@ namespace BizHawk.Client.EmuHawk } } - private void SetPauseStatusbarIcon() + private void SetPauseStatusBarIcon() { if (EmulatorPaused) { @@ -2043,8 +2010,8 @@ namespace BizHawk.Client.EmuHawk private void SaveSlotSelectedMessage() { int slot = Global.Config.SaveSlot; - string emptypart = _stateSlots.HasSlot(slot) ? "" : " (empty)"; - string message = $"Slot {slot}{emptypart} selected."; + string emptyPart = _stateSlots.HasSlot(slot) ? "" : " (empty)"; + string message = $"Slot {slot}{emptyPart} selected."; GlobalWin.OSD.AddMessage(message); } @@ -2059,19 +2026,18 @@ namespace BizHawk.Client.EmuHawk Size currVideoSize = new Size(video.BufferWidth, video.BufferHeight); Size currVirtualSize = new Size(video.VirtualWidth, video.VirtualHeight); - bool resizeFramebuffer = false; - if (currVideoSize != _lastVideoSize || currVirtualSize != _lastVirtualSize) - resizeFramebuffer = true; - bool isZero = false; - if (currVideoSize.Width == 0 || currVideoSize.Height == 0 || currVirtualSize.Width == 0 || currVirtualSize.Height == 0) - isZero = true; - + bool resizeFramebuffer = currVideoSize != _lastVideoSize || currVirtualSize != _lastVirtualSize; + + bool isZero = currVideoSize.Width == 0 || currVideoSize.Height == 0 || currVirtualSize.Width == 0 || currVirtualSize.Height == 0; + //don't resize if the new size is 0 somehow; we'll wait until we have a sensible size - if(isZero) + if (isZero) + { resizeFramebuffer = false; + } - if(resizeFramebuffer) + if (resizeFramebuffer) { _lastVideoSize = currVideoSize; _lastVirtualSize = currVirtualSize; @@ -2080,7 +2046,7 @@ namespace BizHawk.Client.EmuHawk //rendering flakes out egregiously if we have a zero size //can we fix it later not to? - if(isZero) + if (isZero) GlobalWin.DisplayManager.Blank(); else GlobalWin.DisplayManager.UpdateSource(video); @@ -2132,79 +2098,67 @@ namespace BizHawk.Client.EmuHawk } } - var str = sb.ToString().Replace("%ARCH%", "*.zip;*.rar;*.7z;*.gz"); + var str = sb.ToString().Replace("%ARCH%", ArchiveFilters); str = str.Replace(";", "; "); return str; } + public static FileFilterEntry[] RomFilterEntries { get; } = + { + new FileFilterEntry("Music Files", null, developerFilters: "*.psf;*.minipsf;*.sid;*.nsf"), + new FileFilterEntry("Disc Images", "*.cue;*.ccd;*.mds;*.m3u"), + new FileFilterEntry("NES", "*.nes;*.fds;*.unf;*.nsf;%ARCH%"), + new FileFilterEntry("Super NES", "*.smc;*.sfc;*.xml;%ARCH%"), + new FileFilterEntry("PlayStation", "*.cue;*.ccd;*.mds;*.m3u"), + new FileFilterEntry("PSX Executables (experimental)", null, developerFilters: "*.exe"), + new FileFilterEntry("PSF Playstation Sound File", "*.psf;*.minipsf"), + new FileFilterEntry("Nintendo 64", "*.z64;*.v64;*.n64"), + new FileFilterEntry("Gameboy", "*.gb;*.gbc;*.sgb;%ARCH%"), + new FileFilterEntry("Gameboy Advance", "*.gba;%ARCH%"), + new FileFilterEntry("Master System", "*.sms;*.gg;*.sg;%ARCH%"), + new FileFilterEntry("PC Engine", "*.pce;*.sgx;*.cue;*.ccd;*.mds;%ARCH%"), + new FileFilterEntry("Atari 2600", "*.a26;%ARCH%", developerFilters: "*.bin"), + new FileFilterEntry("Atari 7800", "*.a78;%ARCH%", developerFilters: "*.bin"), + new FileFilterEntry("Atari Lynx", "*.lnx;%ARCH%"), + new FileFilterEntry("ColecoVision", "*.col;%ARCH%"), + new FileFilterEntry("IntelliVision", "*.int;*.bin;*.rom;%ARCH%"), + new FileFilterEntry("TI-83", "*.rom;%ARCH%"), + new FileFilterEntry("Archive Files", "%ARCH%"), + new FileFilterEntry("Genesis", "*.gen;*.md;*.smd;*.32x;*.bin;*.cue;*.ccd;%ARCH%"), + new FileFilterEntry("SID Commodore 64 Music File", null, developerFilters: "*.sid;%ARCH%"), + new FileFilterEntry("WonderSwan", "*.ws;*.wsc;%ARCH%"), + new FileFilterEntry("Apple II", "*.dsk;*.do;*.po;%ARCH%"), + new FileFilterEntry("Virtual Boy", "*.vb;%ARCH%"), + new FileFilterEntry("Neo Geo Pocket", "*.ngp;*.ngc;%ARCH%"), + new FileFilterEntry("Commodore 64", "*.prg;*.d64;*.g64;*.crt;*.tap;%ARCH%"), + new FileFilterEntry("Amstrad CPC", null, developerFilters: "*.cdt;*.dsk;%ARCH%"), + new FileFilterEntry("Sinclair ZX Spectrum", "*.tzx;*.tap;*.dsk;*.pzx;*.csw;*.wav;%ARCH%") + }; + + public const string ArchiveFilters = "*.zip;*.rar;*.7z;*.gz"; + public static string RomFilter { get { - if (VersionInfo.DeveloperBuild) + string GetRomFilterStrings() { - return FormatFilter( - "Rom Files", "*.nes;*.fds;*.unf;*.sms;*.gg;*.sg;*.pce;*.sgx;*.bin;*.smd;*.rom;*.a26;*.a78;*.lnx;*.m3u;*.cue;*.ccd;*.mds;*.exe;*.gb;*.gbc;*.gba;*.gen;*.md;*.32x;*.col;*.int;*.smc;*.sfc;*.prg;*.d64;*.g64;*.crt;*.tap;*.sgb;*.xml;*.z64;*.v64;*.n64;*.ws;*.wsc;*.dsk;*.do;*.po;*.vb;*.ngp;*.ngc;*.psf;*.minipsf;*.nsf;*.tzx;*.pzx;*.csw;*.wav;*.cdt;%ARCH%", - "Music Files", "*.psf;*.minipsf;*.sid;*.nsf", - "Disc Images", "*.cue;*.ccd;*.mds;*.m3u", - "NES", "*.nes;*.fds;*.unf;*.nsf;%ARCH%", - "Super NES", "*.smc;*.sfc;*.xml;%ARCH%", - "Master System", "*.sms;*.gg;*.sg;%ARCH%", - "PC Engine", "*.pce;*.sgx;*.cue;*.ccd;*.mds;%ARCH%", - "TI-83", "*.rom;%ARCH%", - "Archive Files", "%ARCH%", - "Savestate", "*.state", - "Atari 2600", "*.a26;*.bin;%ARCH%", - "Atari 7800", "*.a78;*.bin;%ARCH%", - "Atari Lynx", "*.lnx;%ARCH%", - "Genesis", "*.gen;*.smd;*.bin;*.md;*.32x;*.cue;*.ccd;%ARCH%", - "Gameboy", "*.gb;*.gbc;*.sgb;%ARCH%", - "Gameboy Advance", "*.gba;%ARCH%", - "Colecovision", "*.col;%ARCH%", - "Intellivision", "*.int;*.bin;*.rom;%ARCH%", - "PlayStation", "*.cue;*.ccd;*.mds;*.m3u", - "PSX Executables (experimental)", "*.exe", - "PSF Playstation Sound File", "*.psf;*.minipsf", - "Commodore 64", "*.prg;*.d64;*.g64;*.crt;*.tap;%ARCH%", - "SID Commodore 64 Music File", "*.sid;%ARCH%", - "Nintendo 64", "*.z64;*.v64;*.n64", - "WonderSwan", "*.ws;*.wsc;%ARCH%", - "Apple II", "*.dsk;*.do;*.po;%ARCH%", - "Virtual Boy", "*.vb;%ARCH%", - "Neo Geo Pocket", "*.ngp;*.ngc;%ARCH%", - "Sinclair ZX Spectrum", "*.tzx;*.tap;*.dsk;*.pzx;*.csw;*.wav;%ARCH%", - "Amstrad CPC", "*.cdt;*.dsk;%ARCH%", - "All Files", "*.*"); + var values = new HashSet(RomFilterEntries.SelectMany(f => f.EffectiveFilters)); + if (values.Remove("%ARCH%")) + { + values.UnionWith(ArchiveFilters.Split(';')); + } + return string.Join(";", values.OrderBy(n => n)); } - return FormatFilter( - "Rom Files", "*.nes;*.fds;*.unf;*.sms;*.gg;*.sg;*.gb;*.gbc;*.gba;*.pce;*.sgx;*.bin;*.smd;*.gen;*.md;*.32x;*.smc;*.sfc;*.a26;*.a78;*.lnx;*.col;*.int;*.rom;*.m3u;*.cue;*.ccd;*.mds;*.sgb;*.z64;*.v64;*.n64;*.ws;*.wsc;*.xml;*.dsk;*.do;*.po;*.psf;*.ngp;*.ngc;*.prg;*.d64;*.g64;*.minipsf;*.nsf;*.tzx;*.pzx;*.csw;*.wav;%ARCH%", - "Disc Images", "*.cue;*.ccd;*.mds;*.m3u", - "NES", "*.nes;*.fds;*.unf;*.nsf;%ARCH%", - "Super NES", "*.smc;*.sfc;*.xml;%ARCH%", - "PlayStation", "*.cue;*.ccd;*.mds;*.m3u", - "PSF Playstation Sound File", "*.psf;*.minipsf", - "Nintendo 64", "*.z64;*.v64;*.n64", - "Gameboy", "*.gb;*.gbc;*.sgb;%ARCH%", - "Gameboy Advance", "*.gba;%ARCH%", - "Master System", "*.sms;*.gg;*.sg;%ARCH%", - "PC Engine", "*.pce;*.sgx;*.cue;*.ccd;*.mds;%ARCH%", - "Atari 2600", "*.a26;%ARCH%", - "Atari 7800", "*.a78;%ARCH%", - "Atari Lynx", "*.lnx;%ARCH%", - "Colecovision", "*.col;%ARCH%", - "Intellivision", "*.int;*.bin;*.rom;%ARCH%", - "TI-83", "*.rom;%ARCH%", - "Archive Files", "%ARCH%", - "Savestate", "*.state", - "Genesis", "*.gen;*.md;*.smd;*.32x;*.bin;*.cue;*.ccd;%ARCH%", - "WonderSwan", "*.ws;*.wsc;%ARCH%", - "Apple II", "*.dsk;*.do;*.po;%ARCH%", - "Virtual Boy", "*.vb;%ARCH%", - "Neo Geo Pocket", "*.ngp;*.ngc;%ARCH%", - "Commodore 64", "*.prg;*.d64;*.g64;*.crt;*.tap;%ARCH%", - "Sinclair ZX Spectrum", "*.tzx;*.tap;*.dsk;*.pzx;*.csw;*.wav;%ARCH%", - "All Files", "*.*"); + var allFilters = new List(); + + allFilters.Add(new FileFilterEntry("Rom Files", GetRomFilterStrings())); + allFilters.AddRange(RomFilterEntries.Where(f => f.EffectiveFilters.Any())); + allFilters.Add(new FileFilterEntry("Savestate", "*.state")); + allFilters.Add(new FileFilterEntry("All Files", "*.*")); + + return FormatFilter(allFilters.SelectMany(f => new[] { f.Description, string.Join(";", f.EffectiveFilters) }).ToArray()); } } @@ -2243,8 +2197,8 @@ namespace BizHawk.Client.EmuHawk { e.Settings = Global.Config.GetCoreSyncSettings(e.Core); - // adelikat: only show this nag if the core actually has sync settings, not all cores do - if (e.Settings != null && !_supressSyncSettingsWarning) + // Only show this nag if the core actually has sync settings, not all cores do + if (e.Settings != null && !_suppressSyncSettingsWarning) { MessageBox.Show( "No sync settings found, using currently configured settings for this core.", @@ -2502,6 +2456,8 @@ namespace BizHawk.Client.EmuHawk FrameBufferResized(); } + private static readonly int[] _speedPercents = { 1, 3, 6, 12, 25, 50, 75, 100, 150, 200, 300, 400, 800, 1600, 3200, 6400 }; + private void IncreaseSpeed() { if (!Global.Config.ClockThrottle) @@ -2513,66 +2469,13 @@ namespace BizHawk.Client.EmuHawk var oldp = Global.Config.SpeedPercent; int newp; - if (oldp < 3) + int i = 0; + do { - newp = 3; - } - else if (oldp < 6) - { - newp = 6; - } - else if (oldp < 12) - { - newp = 12; - } - else if (oldp < 25) - { - newp = 25; - } - else if (oldp < 50) - { - newp = 50; - } - else if (oldp < 75) - { - newp = 75; - } - else if (oldp < 100) - { - newp = 100; - } - else if (oldp < 150) - { - newp = 150; - } - else if (oldp < 200) - { - newp = 200; - } - else if (oldp < 300) - { - newp = 300; - } - else if (oldp < 400) - { - newp = 400; - } - else if (oldp < 800) - { - newp = 800; - } - else if (oldp < 1600) - { - newp = 1600; - } - else if (oldp < 3200) - { - newp = 3200; - } - else - { - newp = 6400; + i++; + newp = _speedPercents[i]; } + while (newp <= oldp && i < _speedPercents.Length - 1); SetSpeedPercent(newp); } @@ -2588,66 +2491,13 @@ namespace BizHawk.Client.EmuHawk var oldp = Global.Config.SpeedPercent; int newp; - if (oldp > 3200) + int i = _speedPercents.Length - 1; + do { - newp = 3200; - } - else if (oldp > 1600) - { - newp = 1600; - } - else if (oldp > 800) - { - newp = 800; - } - else if (oldp > 400) - { - newp = 400; - } - else if (oldp > 300) - { - newp = 300; - } - else if (oldp > 200) - { - newp = 200; - } - else if (oldp > 150) - { - newp = 150; - } - else if (oldp > 100) - { - newp = 100; - } - else if (oldp > 75) - { - newp = 75; - } - else if (oldp > 50) - { - newp = 50; - } - else if (oldp > 25) - { - newp = 25; - } - else if (oldp > 12) - { - newp = 12; - } - else if (oldp > 6) - { - newp = 6; - } - else if (oldp > 3) - { - newp = 3; - } - else - { - newp = 1; + i--; + newp = _speedPercents[i]; } + while (newp >= oldp && i > 0); SetSpeedPercent(newp); } @@ -2815,22 +2665,22 @@ namespace BizHawk.Client.EmuHawk var attributes = Emulator.Attributes(); CoreNameStatusBarButton.Text = Emulator.DisplayName(); - CoreNameStatusBarButton.Image = Emulator.Icon(); - CoreNameStatusBarButton.ToolTipText = attributes.Ported ? "(ported) " : ""; + CoreNameStatusBarButton.Image = Emulator.Icon(); + CoreNameStatusBarButton.ToolTipText = attributes.Ported ? "(ported) " : ""; - if (Emulator.SystemId == "ZXSpectrum") - { - var core = (Emulation.Cores.Computers.SinclairSpectrum.ZXSpectrum)Emulator as Emulation.Cores.Computers.SinclairSpectrum.ZXSpectrum; - CoreNameStatusBarButton.ToolTipText = core.GetMachineType(); - } + if (Emulator.SystemId == "ZXSpectrum") + { + var core = (Emulation.Cores.Computers.SinclairSpectrum.ZXSpectrum)Emulator; + CoreNameStatusBarButton.ToolTipText = core.GetMachineType(); + } - if (Emulator.SystemId == "AmstradCPC") - { - var core = (Emulation.Cores.Computers.AmstradCPC.AmstradCPC)Emulator as Emulation.Cores.Computers.AmstradCPC.AmstradCPC; - CoreNameStatusBarButton.ToolTipText = core.GetMachineType(); - } - } + if (Emulator.SystemId == "AmstradCPC") + { + var core = (Emulation.Cores.Computers.AmstradCPC.AmstradCPC)Emulator; + CoreNameStatusBarButton.ToolTipText = core.GetMachineType(); + } + } private void ToggleKeyPriority() { @@ -2947,8 +2797,7 @@ namespace BizHawk.Client.EmuHawk runFrame = true; } - bool returnToRecording; - bool isRewinding = Rewind(ref runFrame, currentTimestamp, out returnToRecording); + bool isRewinding = Rewind(ref runFrame, currentTimestamp, out var returnToRecording); float atten = 0; @@ -3022,7 +2871,7 @@ namespace BizHawk.Client.EmuHawk FlushSaveRAM(true); } } - // why not skip audio if the user doesnt want sound + // why not skip audio if the user doesn't want sound bool renderSound = (Global.Config.SoundEnabled && !IsTurboing) || (_currAviWriter?.UsesAudio ?? false); if (!renderSound) { @@ -3174,11 +3023,11 @@ namespace BizHawk.Client.EmuHawk /// /// start AVI recording, unattended /// - /// match the short name of an + /// match the short name of an /// filename to save to - private void RecordAv(string videowritername, string filename) + private void RecordAv(string videoWriterName, string filename) { - RecordAvBase(videowritername, filename, true); + RecordAvBase(videoWriterName, filename, true); } /// @@ -3192,7 +3041,7 @@ namespace BizHawk.Client.EmuHawk /// /// start AV recording /// - private void RecordAvBase(string videowritername, string filename, bool unattended) + private void RecordAvBase(string videoWriterName, string filename, bool unattended) { if (_currAviWriter != null) { @@ -3202,15 +3051,15 @@ namespace BizHawk.Client.EmuHawk // select IVideoWriter to use IVideoWriter aw; - if (string.IsNullOrEmpty(videowritername) && !string.IsNullOrEmpty(Global.Config.VideoWriter)) + if (string.IsNullOrEmpty(videoWriterName) && !string.IsNullOrEmpty(Global.Config.VideoWriter)) { - videowritername = Global.Config.VideoWriter; + videoWriterName = Global.Config.VideoWriter; } _dumpaudiosync = Global.Config.VideoWriterAudioSync; - if (unattended && !string.IsNullOrEmpty(videowritername)) + if (unattended && !string.IsNullOrEmpty(videoWriterName)) { - aw = VideoWriterInventory.GetVideoWriter(videowritername); + aw = VideoWriterInventory.GetVideoWriter(videoWriterName); } else { @@ -3221,7 +3070,7 @@ namespace BizHawk.Client.EmuHawk if (aw == null) { GlobalWin.OSD.AddMessage( - unattended ? $"Couldn't start video writer \"{videowritername}\"" : "A/V capture canceled."); + unattended ? $"Couldn't start video writer \"{videoWriterName}\"" : "A/V capture canceled."); return; } @@ -3304,7 +3153,7 @@ namespace BizHawk.Client.EmuHawk var sfd = new SaveFileDialog(); if (Global.Game != null) { - sfd.FileName = $"{PathManager.FilesystemSafeName(Global.Game)}.{ext}"; // dont use Path.ChangeExtension, it might wreck game names with dots in them + sfd.FileName = $"{PathManager.FilesystemSafeName(Global.Game)}.{ext}"; // don't use Path.ChangeExtension, it might wreck game names with dots in them sfd.InitialDirectory = PathManager.MakeAbsolutePath(Global.Config.PathEntries.AvPathFragment, null); } else @@ -3413,9 +3262,9 @@ namespace BizHawk.Client.EmuHawk try { // is this the best time to handle this? or deeper inside? - if (argParser._currAviWriterFrameList != null) + if (_argParser._currAviWriterFrameList != null) { - if (!argParser._currAviWriterFrameList.Contains(Emulator.Frame)) + if (!_argParser._currAviWriterFrameList.Contains(Emulator.Frame)) { goto HANDLE_AUTODUMP; } @@ -3497,14 +3346,14 @@ namespace BizHawk.Client.EmuHawk AbortAv(); } - HANDLE_AUTODUMP: - if (argParser._autoDumpLength > 0) + HANDLE_AUTODUMP: + if (_argParser._autoDumpLength > 0) { - argParser._autoDumpLength--; - if (argParser._autoDumpLength == 0) // finish + _argParser._autoDumpLength--; + if (_argParser._autoDumpLength == 0) // finish { StopAv(); - if (argParser._autoCloseOnDump) + if (_argParser._autoCloseOnDump) { _exitRequestPending = true; } @@ -3513,7 +3362,7 @@ namespace BizHawk.Client.EmuHawk } } - private int? LoadArhiveChooser(HawkFile file) + private int? LoadArchiveChooser(HawkFile file) { var ac = new ArchiveChooser(file); if (ac.ShowDialog(this) == DialogResult.OK) @@ -3592,29 +3441,28 @@ namespace BizHawk.Client.EmuHawk public bool LoadRom(string path, LoadRomArgs args) { - bool ret = _LoadRom(path, args); - if(!ret) return false; + if (!LoadRomInternal(path, args)) + return false; - //what's the meaning of the last rom path when opening an archive? based on the archive file location + // what's the meaning of the last rom path when opening an archive? based on the archive file location if (args.OpenAdvanced is OpenAdvanced_OpenRom) { - var leftpart = path.Split('|')[0]; - Global.Config.LastRomPath = Path.GetFullPath(Path.GetDirectoryName(leftpart)); + var leftPart = path.Split('|')[0]; + Global.Config.LastRomPath = Path.GetFullPath(Path.GetDirectoryName(leftPart)); } return true; } // Still needs a good bit of refactoring - public bool _LoadRom(string path, LoadRomArgs args) + private bool LoadRomInternal(string path, LoadRomArgs args) { - path = HawkFile.Util_ResolveLink(path); - - // default args + if (path == null) + throw new ArgumentNullException(nameof(path)); if (args == null) - { - args = new LoadRomArgs(); - } + throw new ArgumentNullException(nameof(args)); + + path = HawkFile.Util_ResolveLink(path); // if this is the first call to LoadRom (they will come in recursively) then stash the args bool firstCall = false; @@ -3634,21 +3482,19 @@ namespace BizHawk.Client.EmuHawk // if the core is managing its own DE through SyncSettings a 'deterministic' bool can be passed into the core's constructor // it is then up to the core itself to override its own local DeterministicEmulation setting bool deterministic = args.Deterministic ?? Global.MovieSession.QueuedMovie != null; - + if (!GlobalWin.Tools.AskSave()) { return false; } - bool asLibretro = args.OpenAdvanced is OpenAdvanced_Libretro || args.OpenAdvanced is OpenAdvanced_LibretroNoGame; - var loader = new RomLoader { - ChooseArchive = LoadArhiveChooser, + ChooseArchive = LoadArchiveChooser, ChoosePlatform = ChoosePlatformForRom, Deterministic = deterministic, MessageCallback = GlobalWin.OSD.AddMessage, - AsLibretro = asLibretro + AdvancedLoader = AdvancedLoader }; Global.FirmwareManager.RecentlyServed.Clear(); @@ -3664,31 +3510,32 @@ namespace BizHawk.Client.EmuHawk var nextComm = CreateCoreComm(); - // we need to inform LoadRom which Libretro core to use... IOpenAdvanced ioa = args.OpenAdvanced; - if (ioa is IOpenAdvancedLibretro) - { - var ioaretro = (IOpenAdvancedLibretro)ioa; + var oa_openrom = ioa as OpenAdvanced_OpenRom; + var oa_retro = ioa as OpenAdvanced_Libretro; + var ioa_retro = ioa as IOpenAdvancedLibretro; + // we need to inform LoadRom which Libretro core to use... + if (ioa_retro != null) + { // prepare a core specification - // if it wasnt already specified, use the current default - if (ioaretro.CorePath == null) + // if it wasn't already specified, use the current default + if (ioa_retro.CorePath == null) { - ioaretro.CorePath = Global.Config.LibretroCore; + ioa_retro.CorePath = Global.Config.LibretroCore; } - nextComm.LaunchLibretroCore = ioaretro.CorePath; + nextComm.LaunchLibretroCore = ioa_retro.CorePath; if (nextComm.LaunchLibretroCore == null) { throw new InvalidOperationException("Can't load a file via Libretro until a core is specified"); } } - if (ioa is OpenAdvanced_OpenRom) + if (oa_openrom != null) { - var ioa_openrom = (OpenAdvanced_OpenRom)ioa; // path already has the right value, while ioa.Path is null (interestingly, these are swapped below) - // I doubt null is meant to be assigned here, and it just prevents gameload + // I doubt null is meant to be assigned here, and it just prevents game load //path = ioa_openrom.Path; } @@ -3696,63 +3543,56 @@ namespace BizHawk.Client.EmuHawk var result = loader.LoadRom(path, nextComm); // we need to replace the path in the OpenAdvanced with the canonical one the user chose. - // It can't be done until loder.LoadRom happens (for CanonicalFullPath) + // It can't be done until loader.LoadRom happens (for CanonicalFullPath) // i'm not sure this needs to be more abstractly engineered yet until we have more OpenAdvanced examples - if (ioa is OpenAdvanced_Libretro) + if (oa_retro != null) { - var oaretro = ioa as OpenAdvanced_Libretro; - oaretro.token.Path = loader.CanonicalFullPath; + oa_retro.token.Path = loader.CanonicalFullPath; } - if (ioa is OpenAdvanced_OpenRom) + if (oa_openrom != null) { - ((OpenAdvanced_OpenRom)ioa).Path = loader.CanonicalFullPath; + oa_openrom.Path = loader.CanonicalFullPath; } if (result) { - - string loaderName = $"*{OpenAdvancedSerializer.Serialize(ioa)}"; + string openAdvancedArgs = $"*{OpenAdvancedSerializer.Serialize(ioa)}"; Emulator = loader.LoadedEmulator; Global.Game = loader.Game; CoreFileProvider.SyncCoreCommInputSignals(nextComm); InputManager.SyncControls(); - if (ioa is OpenAdvanced_OpenRom) + if (oa_openrom != null && Path.GetExtension(oa_openrom.Path.Replace("|", "")).ToLowerInvariant() == ".xml" && !(Emulator is LibsnesCore)) { - OpenAdvanced_OpenRom ioa_openRom = ioa as OpenAdvanced_OpenRom; + // this is a multi-disk bundler file + // determine the xml assets and create RomStatusDetails for all of them + var xmlGame = XmlGame.Create(new HawkFile(oa_openrom.Path)); - if (Path.GetExtension(ioa_openRom.Path.Replace("|","")).ToLower() == ".xml") + StringWriter xSw = new StringWriter(); + + for (int xg = 0; xg < xmlGame.Assets.Count; xg++) { - // this is a multi-disk bundler file - // determine the xml assets and create RomStatusDetails for all of them - var xmlGame = XmlGame.Create(new HawkFile(ioa_openRom.Path)); + var ext = Path.GetExtension(xmlGame.AssetFullPaths[xg]).ToLowerInvariant(); - StringWriter xSw = new StringWriter(); - - for (int xg = 0; xg < xmlGame.Assets.Count; xg++) + if (ext == ".cue" || ext == ".ccd" || ext == ".toc" || ext == ".mds") { - var ext = Path.GetExtension(xmlGame.AssetFullPaths[xg]).ToLower(); - - if (ext == ".cue" || ext == ".ccd" || ext == ".toc" || ext == ".mds") - { - xSw.WriteLine(Path.GetFileNameWithoutExtension(xmlGame.Assets[xg].Key)); - xSw.WriteLine("SHA1:N/A"); - xSw.WriteLine("MD5:N/A"); - xSw.WriteLine(); - } - else - { - xSw.WriteLine(xmlGame.Assets[xg].Key); - xSw.WriteLine($"SHA1:{xmlGame.Assets[xg].Value.HashSHA1()}"); - xSw.WriteLine($"MD5:{xmlGame.Assets[xg].Value.HashMD5()}"); - xSw.WriteLine(); - } + xSw.WriteLine(Path.GetFileNameWithoutExtension(xmlGame.Assets[xg].Key)); + xSw.WriteLine("SHA1:N/A"); + xSw.WriteLine("MD5:N/A"); + xSw.WriteLine(); + } + else + { + xSw.WriteLine(xmlGame.Assets[xg].Key); + xSw.WriteLine($"SHA1:{xmlGame.Assets[xg].Value.HashSHA1()}"); + xSw.WriteLine($"MD5:{xmlGame.Assets[xg].Value.HashMD5()}"); + xSw.WriteLine(); } - - Emulator.CoreComm.RomStatusDetails = xSw.ToString(); - Emulator.CoreComm.RomStatusAnnotation = "Multi-disk bundler"; } + + Emulator.CoreComm.RomStatusDetails = xSw.ToString(); + Emulator.CoreComm.RomStatusAnnotation = "Multi-disk bundler"; } if (Emulator is TI83 && Global.Config.TI83autoloadKeyPad) @@ -3760,9 +3600,8 @@ namespace BizHawk.Client.EmuHawk GlobalWin.Tools.Load(); } - if (loader.LoadedEmulator is NES) + if (loader.LoadedEmulator is NES nes) { - var nes = (NES)loader.LoadedEmulator; if (!string.IsNullOrWhiteSpace(nes.GameName)) { Global.Game.Name = nes.GameName; @@ -3770,9 +3609,8 @@ namespace BizHawk.Client.EmuHawk Global.Game.Status = nes.RomStatus; } - else if (loader.LoadedEmulator is QuickNES) + else if (loader.LoadedEmulator is QuickNES qns) { - var qns = (QuickNES)loader.LoadedEmulator; if (!string.IsNullOrWhiteSpace(qns.BootGodName)) { Global.Game.Name = qns.BootGodName; @@ -3801,13 +3639,13 @@ namespace BizHawk.Client.EmuHawk // restarts the lua console if a different rom is loaded. // im not really a fan of how this is done.. - if (Global.Config.RecentRoms.Empty || Global.Config.RecentRoms.MostRecent != loaderName) + if (Global.Config.RecentRoms.Empty || Global.Config.RecentRoms.MostRecent != openAdvancedArgs) { GlobalWin.Tools.Restart(); } - Global.Config.RecentRoms.Add(loaderName); - JumpLists.AddRecentItem(loaderName, ioa.DisplayName); + Global.Config.RecentRoms.Add(openAdvancedArgs); + JumpLists.AddRecentItem(openAdvancedArgs, ioa.DisplayName); // Don't load Save Ram if a movie is being loaded if (!Global.MovieSession.MovieIsQueued) @@ -3838,15 +3676,9 @@ namespace BizHawk.Client.EmuHawk } } - SetWindowText(); - _currentlyOpenRomPoopForAdvancedLoaderPleaseRefactorMe = loaderName; - CurrentlyOpenRom = loaderName.Replace("*OpenRom*", ""); // POOP - HandlePlatformMenus(); - _stateSlots.Clear(); - UpdateCoreStatusBarButton(); - UpdateDumpIcon(); - SetMainformMovieInfo(); + CurrentlyOpenRom = oa_openrom?.Path ?? openAdvancedArgs; CurrentlyOpenRomArgs = args; + OnRomChanged(); GlobalWin.DisplayManager.Blank(); Global.Rewinder.Initialize(); @@ -3874,26 +3706,17 @@ namespace BizHawk.Client.EmuHawk ClientApi.OnRomLoaded(Emulator); return true; } + else if (!(Emulator is NullEmulator)) + { + // The ROM has been loaded by a recursive invocation of the LoadROM method. + ClientApi.OnRomLoaded(Emulator); + return true; + } else { // This shows up if there's a problem - // TODO: put all these in a single method or something - - // The ROM has been loaded by a recursive invocation of the LoadROM method. - if (!(Emulator is NullEmulator)) - { - ClientApi.OnRomLoaded(Emulator); - return true; - } - ClientApi.UpdateEmulatorAndVP(Emulator); - HandlePlatformMenus(); - _stateSlots.Clear(); - UpdateStatusSlots(); - UpdateCoreStatusBarButton(); - UpdateDumpIcon(); - SetMainformMovieInfo(); - SetWindowText(); + OnRomChanged(); return false; } } @@ -3906,7 +3729,16 @@ namespace BizHawk.Client.EmuHawk } } - private string _currentlyOpenRomPoopForAdvancedLoaderPleaseRefactorMe = ""; + private void OnRomChanged() + { + SetWindowText(); + HandlePlatformMenus(); + _stateSlots.ClearRedoList(); + UpdateStatusSlots(); + UpdateCoreStatusBarButton(); + UpdateDumpIcon(); + SetMainformMovieInfo(); + } private void CommitCoreSettingsToConfig() { @@ -3945,15 +3777,15 @@ namespace BizHawk.Client.EmuHawk else if (Emulator.HasSaveRam() && Emulator.AsSaveRam().SaveRamModified) { if (!FlushSaveRAM()) - { - var msgRes = MessageBox.Show("Failed flushing the game's Save RAM to your disk.\nClose without flushing Save RAM?", - "Directory IO Error", MessageBoxButtons.YesNo, MessageBoxIcon.Error); + { + var msgRes = MessageBox.Show("Failed flushing the game's Save RAM to your disk.\nClose without flushing Save RAM?", + "Directory IO Error", MessageBoxButtons.YesNo, MessageBoxIcon.Error); - if (msgRes != DialogResult.Yes) - { - return; - } - } + if (msgRes != DialogResult.Yes) + { + return; + } + } } StopAv(); @@ -4001,18 +3833,12 @@ namespace BizHawk.Client.EmuHawk GlobalWin.Tools.Restart(); ApiManager.Restart(Emulator.ServiceProvider); RewireSound(); - Text = $"BizHawk{(VersionInfo.DeveloperBuild ? " (interim) " : "")}"; - HandlePlatformMenus(); - _stateSlots.Clear(); - UpdateDumpIcon(); - UpdateCoreStatusBarButton(); ClearHolds(); - PauseOnFrame = null; ToolFormBase.UpdateCheatRelatedTools(null, null); - UpdateStatusSlots(); + PauseOnFrame = null; CurrentlyOpenRom = null; CurrentlyOpenRomArgs = null; - _currentlyOpenRomPoopForAdvancedLoaderPleaseRefactorMe = ""; + OnRomChanged(); } } @@ -4065,7 +3891,7 @@ namespace BizHawk.Client.EmuHawk return int.Parse(slot.Substring(slot.Length - 1, 1)); } - public void LoadState(string path, string userFriendlyStateName, bool fromLua = false, bool supressOSD = false) // Move to client.common + public void LoadState(string path, string userFriendlyStateName, bool fromLua = false, bool suppressOSD = false) // Move to client.common { if (!Emulator.HasSavestates()) { @@ -4107,7 +3933,7 @@ namespace BizHawk.Client.EmuHawk ClearRewindData(); } - if (!supressOSD) + if (!suppressOSD) { GlobalWin.OSD.AddMessage($"Loaded state: {userFriendlyStateName}"); } @@ -4120,15 +3946,14 @@ namespace BizHawk.Client.EmuHawk Global.MovieSession.Movie.IsCountingRerecords = wasCountingRerecords; } - public void LoadQuickSave(string quickSlotName, bool fromLua = false, bool supressOSD = false) + public void LoadQuickSave(string quickSlotName, bool fromLua = false, bool suppressOSD = false) { if (!Emulator.HasSavestates()) { return; } - bool handled; - ClientApi.OnBeforeQuickLoad(this, quickSlotName, out handled); + ClientApi.OnBeforeQuickLoad(this, quickSlotName, out var handled); if (handled) { return; @@ -4148,7 +3973,7 @@ namespace BizHawk.Client.EmuHawk return; } - LoadState(path, quickSlotName, fromLua, supressOSD); + LoadState(path, quickSlotName, fromLua, suppressOSD); } public void SaveState(string path, string userFriendlyStateName, bool fromLua) @@ -4415,11 +4240,6 @@ namespace BizHawk.Client.EmuHawk } } - private void GBAcoresettingsToolStripMenuItem1_Click(object sender, EventArgs e) - { - GenericCoreConfig.DoDialog(this, "Gameboy Advance Settings"); - } - private void CaptureRewind(bool suppressCaptureRewind) { if (IsRewindSlave) @@ -4432,26 +4252,6 @@ namespace BizHawk.Client.EmuHawk } } - private void preferencesToolStripMenuItem1_Click(object sender, EventArgs e) - { - GenericCoreConfig.DoDialog(this, "VirtualBoy Settings"); - } - - private void preferencesToolStripMenuItem_Click(object sender, EventArgs e) - { - GenericCoreConfig.DoDialog(this, "Snes9x Settings"); - } - - private void preferencesToolStripMenuItem2_Click(object sender, EventArgs e) - { - GenericCoreConfig.DoDialog(this, "NeoPop Settings"); - } - - private void preferencesToolStripMenuItem3_Click(object sender, EventArgs e) - { - GenericCoreConfig.DoDialog(this, "PC-FX Settings"); - } - private bool Rewind(ref bool runFrame, long currentTimestamp, out bool returnToRecording) { var isRewinding = false; @@ -4479,7 +4279,7 @@ namespace BizHawk.Client.EmuHawk _frameRewindWasPaused = false; } - // if we're freely running, there's no need for reverse frame progress semantics (that may be debateable though) + // if we're freely running, there's no need for reverse frame progress semantics (that may be debatable though) if (!EmulatorPaused) { isRewinding = true; diff --git a/BizHawk.Client.EmuHawk/OpenAdvancedChooser.Designer.cs b/BizHawk.Client.EmuHawk/OpenAdvancedChooser.Designer.cs index af6c2fcc75..360c49fcd4 100644 --- a/BizHawk.Client.EmuHawk/OpenAdvancedChooser.Designer.cs +++ b/BizHawk.Client.EmuHawk/OpenAdvancedChooser.Designer.cs @@ -28,147 +28,184 @@ /// private void InitializeComponent() { - this.label3 = new System.Windows.Forms.Label(); - this.label2 = new System.Windows.Forms.Label(); - this.btnLibretroLaunchNoGame = new System.Windows.Forms.Button(); - this.btnCancel = new System.Windows.Forms.Button(); - this.groupBox2 = new System.Windows.Forms.GroupBox(); - this.txtLibretroCore = new System.Windows.Forms.TextBox(); - this.btnLibretroLaunchGame = new System.Windows.Forms.Button(); - this.btnSetLibretroCore = new System.Windows.Forms.Button(); - this.groupBox3 = new System.Windows.Forms.GroupBox(); - this.btnClassicLaunchGame = new System.Windows.Forms.Button(); - this.groupBox2.SuspendLayout(); - this.groupBox3.SuspendLayout(); - this.SuspendLayout(); - // - // label3 - // - this.label3.Location = new System.Drawing.Point(6, 25); - this.label3.Name = "label3"; - this.label3.Size = new System.Drawing.Size(250, 29); - this.label3.TabIndex = 5; - this.label3.Text = "Load a rom with the classic BizHawk autodetection method. But why not just use Op" + - "en Rom?"; - // - // label2 - // - this.label2.AutoSize = true; - this.label2.Location = new System.Drawing.Point(6, 26); - this.label2.Name = "label2"; - this.label2.Size = new System.Drawing.Size(69, 13); - this.label2.TabIndex = 3; - this.label2.Text = "Current Core:"; - // - // btnLibretroLaunchNoGame - // - this.btnLibretroLaunchNoGame.Location = new System.Drawing.Point(217, 50); - this.btnLibretroLaunchNoGame.Name = "btnLibretroLaunchNoGame"; - this.btnLibretroLaunchNoGame.Size = new System.Drawing.Size(102, 23); - this.btnLibretroLaunchNoGame.TabIndex = 1; - this.btnLibretroLaunchNoGame.Text = "Launch No Game"; - this.btnLibretroLaunchNoGame.UseVisualStyleBackColor = true; - this.btnLibretroLaunchNoGame.Click += new System.EventHandler(this.btnLibretroLaunchNoGame_Click); - // - // btnCancel - // - this.btnCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; - this.btnCancel.Location = new System.Drawing.Point(370, 176); - this.btnCancel.Name = "btnCancel"; - this.btnCancel.Size = new System.Drawing.Size(75, 23); - this.btnCancel.TabIndex = 2; - this.btnCancel.Text = "Cancel"; - this.btnCancel.UseVisualStyleBackColor = true; - this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click); - // - // groupBox2 - // - this.groupBox2.Controls.Add(this.txtLibretroCore); - this.groupBox2.Controls.Add(this.btnLibretroLaunchGame); - this.groupBox2.Controls.Add(this.btnSetLibretroCore); - this.groupBox2.Controls.Add(this.label2); - this.groupBox2.Controls.Add(this.btnLibretroLaunchNoGame); - this.groupBox2.Location = new System.Drawing.Point(12, 12); - this.groupBox2.Name = "groupBox2"; - this.groupBox2.Size = new System.Drawing.Size(433, 81); - this.groupBox2.TabIndex = 3; - this.groupBox2.TabStop = false; - this.groupBox2.Text = "Libretro"; - // - // txtLibretroCore - // - this.txtLibretroCore.AllowDrop = true; - this.txtLibretroCore.Location = new System.Drawing.Point(81, 23); - this.txtLibretroCore.Name = "txtLibretroCore"; - this.txtLibretroCore.ReadOnly = true; - this.txtLibretroCore.Size = new System.Drawing.Size(314, 20); - this.txtLibretroCore.TabIndex = 6; - this.txtLibretroCore.DragDrop += new System.Windows.Forms.DragEventHandler(this.txtLibretroCore_DragDrop); - this.txtLibretroCore.DragEnter += new System.Windows.Forms.DragEventHandler(this.txtLibretroCore_DragEnter); - // - // btnLibretroLaunchGame - // - this.btnLibretroLaunchGame.Location = new System.Drawing.Point(325, 50); - this.btnLibretroLaunchGame.Name = "btnLibretroLaunchGame"; - this.btnLibretroLaunchGame.Size = new System.Drawing.Size(102, 23); - this.btnLibretroLaunchGame.TabIndex = 5; - this.btnLibretroLaunchGame.Text = "Launch Game"; - this.btnLibretroLaunchGame.UseVisualStyleBackColor = true; - this.btnLibretroLaunchGame.Click += new System.EventHandler(this.btnLibretroLaunchGame_Click); - // - // btnSetLibretroCore - // - this.btnSetLibretroCore.AutoSize = true; - this.btnSetLibretroCore.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; - this.btnSetLibretroCore.Location = new System.Drawing.Point(401, 21); - this.btnSetLibretroCore.Name = "btnSetLibretroCore"; - this.btnSetLibretroCore.Size = new System.Drawing.Size(26, 23); - this.btnSetLibretroCore.TabIndex = 4; - this.btnSetLibretroCore.Text = "..."; - this.btnSetLibretroCore.UseVisualStyleBackColor = true; - this.btnSetLibretroCore.Click += new System.EventHandler(this.btnSetLibretroCore_Click); - // - // groupBox3 - // - this.groupBox3.Controls.Add(this.btnClassicLaunchGame); - this.groupBox3.Controls.Add(this.label3); - this.groupBox3.Location = new System.Drawing.Point(12, 99); - this.groupBox3.Name = "groupBox3"; - this.groupBox3.Size = new System.Drawing.Size(277, 100); - this.groupBox3.TabIndex = 6; - this.groupBox3.TabStop = false; - this.groupBox3.Text = "BizHawk Classic"; - // - // btnClassicLaunchGame - // - this.btnClassicLaunchGame.Location = new System.Drawing.Point(169, 71); - this.btnClassicLaunchGame.Name = "btnClassicLaunchGame"; - this.btnClassicLaunchGame.Size = new System.Drawing.Size(102, 23); - this.btnClassicLaunchGame.TabIndex = 6; - this.btnClassicLaunchGame.Text = "Launch Game"; - this.btnClassicLaunchGame.UseVisualStyleBackColor = true; - this.btnClassicLaunchGame.Click += new System.EventHandler(this.btnClassicLaunchGame_Click); - // - // OpenAdvancedChooser - // - this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.CancelButton = this.btnCancel; - this.ClientSize = new System.Drawing.Size(457, 208); - this.Controls.Add(this.groupBox3); - this.Controls.Add(this.groupBox2); - this.Controls.Add(this.btnCancel); - this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; - this.MaximizeBox = false; - this.MinimizeBox = false; - this.Name = "OpenAdvancedChooser"; - this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; - this.Text = "Open Advanced"; - this.groupBox2.ResumeLayout(false); - this.groupBox2.PerformLayout(); - this.groupBox3.ResumeLayout(false); - this.ResumeLayout(false); - + this.label3 = new System.Windows.Forms.Label(); + this.label2 = new System.Windows.Forms.Label(); + this.btnLibretroLaunchNoGame = new System.Windows.Forms.Button(); + this.btnCancel = new System.Windows.Forms.Button(); + this.groupBox2 = new System.Windows.Forms.GroupBox(); + this.txtLibretroCore = new System.Windows.Forms.TextBox(); + this.btnLibretroLaunchGame = new System.Windows.Forms.Button(); + this.btnSetLibretroCore = new System.Windows.Forms.Button(); + this.groupBox3 = new System.Windows.Forms.GroupBox(); + this.btnClassicLaunchGame = new System.Windows.Forms.Button(); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.label1 = new System.Windows.Forms.Label(); + this.btnMAMELaunchGame = new System.Windows.Forms.Button(); + this.groupBox2.SuspendLayout(); + this.groupBox3.SuspendLayout(); + this.groupBox1.SuspendLayout(); + this.SuspendLayout(); + // + // label3 + // + this.label3.Location = new System.Drawing.Point(6, 25); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(198, 45); + this.label3.TabIndex = 5; + this.label3.Text = "Load a ROM with the classic BizHawk autodetection method. But why not just use Op" + + "en Rom?"; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(6, 26); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(69, 13); + this.label2.TabIndex = 3; + this.label2.Text = "Current Core:"; + // + // btnLibretroLaunchNoGame + // + this.btnLibretroLaunchNoGame.Location = new System.Drawing.Point(217, 50); + this.btnLibretroLaunchNoGame.Name = "btnLibretroLaunchNoGame"; + this.btnLibretroLaunchNoGame.Size = new System.Drawing.Size(102, 23); + this.btnLibretroLaunchNoGame.TabIndex = 1; + this.btnLibretroLaunchNoGame.Text = "Launch No Game"; + this.btnLibretroLaunchNoGame.UseVisualStyleBackColor = true; + this.btnLibretroLaunchNoGame.Click += new System.EventHandler(this.btnLibretroLaunchNoGame_Click); + // + // btnCancel + // + this.btnCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.btnCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.btnCancel.Location = new System.Drawing.Point(370, 221); + this.btnCancel.Name = "btnCancel"; + this.btnCancel.Size = new System.Drawing.Size(75, 23); + this.btnCancel.TabIndex = 2; + this.btnCancel.Text = "Cancel"; + this.btnCancel.UseVisualStyleBackColor = true; + this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click); + // + // groupBox2 + // + this.groupBox2.Controls.Add(this.txtLibretroCore); + this.groupBox2.Controls.Add(this.btnLibretroLaunchGame); + this.groupBox2.Controls.Add(this.btnSetLibretroCore); + this.groupBox2.Controls.Add(this.label2); + this.groupBox2.Controls.Add(this.btnLibretroLaunchNoGame); + this.groupBox2.Location = new System.Drawing.Point(12, 12); + this.groupBox2.Name = "groupBox2"; + this.groupBox2.Size = new System.Drawing.Size(433, 81); + this.groupBox2.TabIndex = 3; + this.groupBox2.TabStop = false; + this.groupBox2.Text = "Libretro"; + // + // txtLibretroCore + // + this.txtLibretroCore.AllowDrop = true; + this.txtLibretroCore.Location = new System.Drawing.Point(81, 23); + this.txtLibretroCore.Name = "txtLibretroCore"; + this.txtLibretroCore.ReadOnly = true; + this.txtLibretroCore.Size = new System.Drawing.Size(314, 20); + this.txtLibretroCore.TabIndex = 6; + this.txtLibretroCore.DragDrop += new System.Windows.Forms.DragEventHandler(this.txtLibretroCore_DragDrop); + this.txtLibretroCore.DragEnter += new System.Windows.Forms.DragEventHandler(this.txtLibretroCore_DragEnter); + // + // btnLibretroLaunchGame + // + this.btnLibretroLaunchGame.Location = new System.Drawing.Point(325, 50); + this.btnLibretroLaunchGame.Name = "btnLibretroLaunchGame"; + this.btnLibretroLaunchGame.Size = new System.Drawing.Size(102, 23); + this.btnLibretroLaunchGame.TabIndex = 5; + this.btnLibretroLaunchGame.Text = "Launch Game"; + this.btnLibretroLaunchGame.UseVisualStyleBackColor = true; + this.btnLibretroLaunchGame.Click += new System.EventHandler(this.btnLibretroLaunchGame_Click); + // + // btnSetLibretroCore + // + this.btnSetLibretroCore.AutoSize = true; + this.btnSetLibretroCore.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; + this.btnSetLibretroCore.Location = new System.Drawing.Point(401, 21); + this.btnSetLibretroCore.Name = "btnSetLibretroCore"; + this.btnSetLibretroCore.Size = new System.Drawing.Size(26, 23); + this.btnSetLibretroCore.TabIndex = 4; + this.btnSetLibretroCore.Text = "..."; + this.btnSetLibretroCore.UseVisualStyleBackColor = true; + this.btnSetLibretroCore.Click += new System.EventHandler(this.btnSetLibretroCore_Click); + // + // groupBox3 + // + this.groupBox3.Controls.Add(this.btnClassicLaunchGame); + this.groupBox3.Controls.Add(this.label3); + this.groupBox3.Location = new System.Drawing.Point(235, 99); + this.groupBox3.Name = "groupBox3"; + this.groupBox3.Size = new System.Drawing.Size(210, 100); + this.groupBox3.TabIndex = 6; + this.groupBox3.TabStop = false; + this.groupBox3.Text = "BizHawk Classic"; + // + // btnClassicLaunchGame + // + this.btnClassicLaunchGame.Location = new System.Drawing.Point(102, 71); + this.btnClassicLaunchGame.Name = "btnClassicLaunchGame"; + this.btnClassicLaunchGame.Size = new System.Drawing.Size(102, 23); + this.btnClassicLaunchGame.TabIndex = 6; + this.btnClassicLaunchGame.Text = "Launch Game"; + this.btnClassicLaunchGame.UseVisualStyleBackColor = true; + this.btnClassicLaunchGame.Click += new System.EventHandler(this.btnClassicLaunchGame_Click); + // + // groupBox1 + // + this.groupBox1.Controls.Add(this.label1); + this.groupBox1.Controls.Add(this.btnMAMELaunchGame); + this.groupBox1.Location = new System.Drawing.Point(13, 99); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(216, 100); + this.groupBox1.TabIndex = 7; + this.groupBox1.TabStop = false; + this.groupBox1.Text = "MAME Arcade"; + // + // label1 + // + this.label1.Location = new System.Drawing.Point(6, 25); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(204, 42); + this.label1.TabIndex = 1; + this.label1.Text = "Load .zip archive as MAME Arcade ROM (do not unzip)"; + this.label1.Click += new System.EventHandler(this.btnMAMELaunchGame_Click); + // + // btnMAMELaunchGame + // + this.btnMAMELaunchGame.Location = new System.Drawing.Point(108, 71); + this.btnMAMELaunchGame.Name = "btnMAMELaunchGame"; + this.btnMAMELaunchGame.Size = new System.Drawing.Size(102, 23); + this.btnMAMELaunchGame.TabIndex = 0; + this.btnMAMELaunchGame.Text = "Launch Game"; + this.btnMAMELaunchGame.UseVisualStyleBackColor = true; + this.btnMAMELaunchGame.Click += new System.EventHandler(this.btnMAMELaunchGame_Click); + // + // OpenAdvancedChooser + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.CancelButton = this.btnCancel; + this.ClientSize = new System.Drawing.Size(457, 256); + this.Controls.Add(this.groupBox1); + this.Controls.Add(this.groupBox3); + this.Controls.Add(this.groupBox2); + this.Controls.Add(this.btnCancel); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "OpenAdvancedChooser"; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "Open Advanced"; + this.groupBox2.ResumeLayout(false); + this.groupBox2.PerformLayout(); + this.groupBox3.ResumeLayout(false); + this.groupBox1.ResumeLayout(false); + this.ResumeLayout(false); + } #endregion @@ -182,6 +219,9 @@ private System.Windows.Forms.TextBox txtLibretroCore; private System.Windows.Forms.Button btnLibretroLaunchGame; private System.Windows.Forms.GroupBox groupBox3; - private System.Windows.Forms.Button btnClassicLaunchGame; + private System.Windows.Forms.Button btnClassicLaunchGame; + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Button btnMAMELaunchGame; } } \ No newline at end of file diff --git a/BizHawk.Client.EmuHawk/OpenAdvancedChooser.cs b/BizHawk.Client.EmuHawk/OpenAdvancedChooser.cs index 8eff5a7e6e..f68d411837 100644 --- a/BizHawk.Client.EmuHawk/OpenAdvancedChooser.cs +++ b/BizHawk.Client.EmuHawk/OpenAdvancedChooser.cs @@ -7,7 +7,8 @@ using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; - + +using BizHawk.Emulation.Common; using BizHawk.Emulation.Cores; using BizHawk.Emulation.Cores.Libretro; using BizHawk.Client.Common; @@ -20,13 +21,7 @@ namespace BizHawk.Client.EmuHawk { MainForm mainForm; - public enum Command - { - RetroLaunchNoGame, RetroLaunchGame, - ClassicLaunchGame - } - - public Command Result; + public AdvancedRomLoaderType Result; public string SuggestedExtensionFilter; public OpenAdvancedChooser(MainForm mainForm) @@ -131,21 +126,28 @@ namespace BizHawk.Client.EmuHawk filter = MainForm.FormatFilter(args.ToArray()); SuggestedExtensionFilter = filter; - Result = Command.RetroLaunchGame; + Result = AdvancedRomLoaderType.LibretroLaunchGame; DialogResult = DialogResult.OK; Close(); + } + + private void btnMAMELaunchGame_Click(object sender, EventArgs e) + { + Result = AdvancedRomLoaderType.MAMELaunchGame; + DialogResult = DialogResult.OK; + Close(); } private void btnClassicLaunchGame_Click(object sender, EventArgs e) { - Result = Command.ClassicLaunchGame; + Result = AdvancedRomLoaderType.ClassicLaunchGame; DialogResult = DialogResult.OK; Close(); } private void btnLibretroLaunchNoGame_Click(object sender, EventArgs e) { - Result = Command.RetroLaunchNoGame; + Result = AdvancedRomLoaderType.LibretroLaunchNoGame; DialogResult = DialogResult.OK; Close(); } @@ -170,6 +172,6 @@ namespace BizHawk.Client.EmuHawk var filePaths = (string[])e.Data.GetData(DataFormats.FileDrop); Global.Config.LibretroCore = filePaths[0]; RefreshLibretroCore(false); - } + } } } diff --git a/BizHawk.Client.EmuHawk/Program.cs b/BizHawk.Client.EmuHawk/Program.cs index 10fb48b196..f05542abb8 100644 --- a/BizHawk.Client.EmuHawk/Program.cs +++ b/BizHawk.Client.EmuHawk/Program.cs @@ -30,36 +30,33 @@ namespace BizHawk.Client.EmuHawk //try loading libraries we know we'll need //something in the winforms, etc. code below will cause .net to popup a missing msvcr100.dll in case that one's missing //but oddly it lets us proceed and we'll then catch it here - var d3dx9 = libLoader.LoadPlatformSpecific("d3dx9_43.dll"); - var vc2015 = libLoader.LoadPlatformSpecific("vcruntime140.dll"); - var vc2012 = libLoader.LoadPlatformSpecific("msvcr120.dll"); //TODO - check version? - var vc2010 = libLoader.LoadPlatformSpecific("msvcr100.dll"); //TODO - check version? - var vc2010p = libLoader.LoadPlatformSpecific("msvcp100.dll"); - var fail = vc2015 == IntPtr.Zero || vc2010 == IntPtr.Zero || vc2012 == IntPtr.Zero || vc2010p == IntPtr.Zero; - var warn = d3dx9 == IntPtr.Zero; - if (fail || warn) + var d3dx9 = libLoader.LoadOrNull("d3dx9_43.dll"); + var vc2015 = libLoader.LoadOrNull("vcruntime140.dll"); + var vc2012 = libLoader.LoadOrNull("msvcr120.dll"); //TODO - check version? + var vc2010 = libLoader.LoadOrNull("msvcr100.dll"); //TODO - check version? + var vc2010p = libLoader.LoadOrNull("msvcp100.dll"); + var reqPresent = vc2015.HasValue && vc2010.HasValue && vc2012.HasValue && vc2010p.HasValue; + var optPresent = d3dx9.HasValue; + if (!reqPresent || !optPresent) { var alertLines = new[] { "[ OK ] .NET CLR (You wouldn't even get here without it)", - $"[{(d3dx9 == IntPtr.Zero ? "WARN" : " OK ")}] Direct3d 9", - $"[{(vc2010 == IntPtr.Zero || vc2010p == IntPtr.Zero ? "FAIL" : " OK ")}] Visual C++ 2010 SP1 Runtime", - $"[{(vc2012 == IntPtr.Zero ? "FAIL" : " OK ")}] Visual C++ 2012 Runtime", - $"[{(vc2015 == IntPtr.Zero ? "FAIL" : " OK ")}] Visual C++ 2015 Runtime" + $"[{(d3dx9.HasValue ? " OK " : "WARN")}] Direct3d 9", + $"[{(vc2010.HasValue && vc2010p.HasValue ? " OK " : "FAIL")}] Visual C++ 2010 SP1 Runtime", + $"[{(vc2012.HasValue ? " OK " : "FAIL")}] Visual C++ 2012 Runtime", + $"[{(vc2015.HasValue ? " OK " : "FAIL")}] Visual C++ 2015 Runtime" }; - var box = new BizHawk.Client.EmuHawk.CustomControls.PrereqsAlert(!fail) + var box = new CustomControls.PrereqsAlert(reqPresent) { - textBox1 = { Text = string.Concat("\n", alertLines) } + textBox1 = { Text = string.Join(Environment.NewLine, alertLines) } }; box.ShowDialog(); - if (fail) System.Diagnostics.Process.GetCurrentProcess().Kill(); + if (!reqPresent) Process.GetCurrentProcess().Kill(); } - libLoader.FreePlatformSpecific(d3dx9); - libLoader.FreePlatformSpecific(vc2015); - libLoader.FreePlatformSpecific(vc2012); - libLoader.FreePlatformSpecific(vc2010); - libLoader.FreePlatformSpecific(vc2010p); + foreach (var p in new[] { d3dx9, vc2015, vc2012, vc2010, vc2010p }) + if (p.HasValue) libLoader.FreeByPtr(p.Value); // this will look in subdirectory "dll" to load pinvoked stuff var dllDir = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "dll"); @@ -115,7 +112,7 @@ namespace BizHawk.Client.EmuHawk } } - BizHawk.Common.TempFileManager.Start(); + TempFileManager.Start(); #if true // switch to if false for system-agnostic glory! switch (EXE_PROJECT.OSTailoredCode.CurrentOS) @@ -147,8 +144,8 @@ namespace BizHawk.Client.EmuHawk Global.Config.ResolveDefaults(); - BizHawk.Client.Common.StringLogUtil.DefaultToDisk = Global.Config.MoviesOnDisk; - BizHawk.Client.Common.StringLogUtil.DefaultToAWE = Global.Config.MoviesInAWE; + StringLogUtil.DefaultToDisk = Global.Config.MoviesOnDisk; + StringLogUtil.DefaultToAWE = Global.Config.MoviesInAWE; // super hacky! this needs to be done first. still not worth the trouble to make this system fully proper if (Array.Exists(args, arg => arg.StartsWith("--gdi", StringComparison.InvariantCultureIgnoreCase))) diff --git a/BizHawk.Client.EmuHawk/Properties/Resources.Designer.cs b/BizHawk.Client.EmuHawk/Properties/Resources.Designer.cs index d9e97b6eff..0ca90c2902 100644 --- a/BizHawk.Client.EmuHawk/Properties/Resources.Designer.cs +++ b/BizHawk.Client.EmuHawk/Properties/Resources.Designer.cs @@ -19,7 +19,7 @@ namespace BizHawk.Client.EmuHawk.Properties { // class via a tool like ResGen or Visual Studio. // To add or remove a member, edit your .ResX file then rerun ResGen // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] internal class Resources { @@ -120,6 +120,16 @@ namespace BizHawk.Client.EmuHawk.Properties { } } + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap ArcadeController { + get { + object obj = ResourceManager.GetObject("ArcadeController", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// @@ -870,6 +880,16 @@ namespace BizHawk.Client.EmuHawk.Properties { } } + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap mame { + get { + object obj = ResourceManager.GetObject("mame", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// @@ -1479,6 +1499,16 @@ namespace BizHawk.Client.EmuHawk.Properties { } } + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap StopButton { + get { + object obj = ResourceManager.GetObject("StopButton", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// diff --git a/BizHawk.Client.EmuHawk/Properties/Resources.resx b/BizHawk.Client.EmuHawk/Properties/Resources.resx index 1876bfb3b7..ac426a1592 100644 --- a/BizHawk.Client.EmuHawk/Properties/Resources.resx +++ b/BizHawk.Client.EmuHawk/Properties/Resources.resx @@ -1563,4 +1563,13 @@ ..\Resources\MoveTop.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\images\StopButton.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\images\ControllerImages\ArcadeController.jpg;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\images\mame.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + \ No newline at end of file diff --git a/BizHawk.Client.EmuHawk/Sound/Interfaces/ISoundOutput.cs b/BizHawk.Client.EmuHawk/Sound/Interfaces/ISoundOutput.cs index f6dce3be8d..061c93d7ff 100644 --- a/BizHawk.Client.EmuHawk/Sound/Interfaces/ISoundOutput.cs +++ b/BizHawk.Client.EmuHawk/Sound/Interfaces/ISoundOutput.cs @@ -9,6 +9,6 @@ namespace BizHawk.Client.EmuHawk void ApplyVolumeSettings(double volume); int MaxSamplesDeficit { get; } int CalculateSamplesNeeded(); - void WriteSamples(short[] samples, int sampleCount); + void WriteSamples(short[] samples, int sampleOffset, int sampleCount); } } diff --git a/BizHawk.Client.EmuHawk/Sound/Output/DirectSoundSoundOutput.cs b/BizHawk.Client.EmuHawk/Sound/Output/DirectSoundSoundOutput.cs index 21ca8bd90f..20d0959cad 100644 --- a/BizHawk.Client.EmuHawk/Sound/Output/DirectSoundSoundOutput.cs +++ b/BizHawk.Client.EmuHawk/Sound/Output/DirectSoundSoundOutput.cs @@ -42,7 +42,7 @@ namespace BizHawk.Client.EmuHawk public static IEnumerable GetDeviceNames() { - return DirectSound.GetDevices().Select(d => d.Description).ToList(); + return DirectSound.GetDevices().Select(d => d.Description); } private int BufferSizeSamples { get; set; } @@ -152,12 +152,10 @@ namespace BizHawk.Client.EmuHawk return (end - start + size) % size; } - public void WriteSamples(short[] samples, int sampleCount) + public void WriteSamples(short[] samples, int sampleOffset, int sampleCount) { if (sampleCount == 0) return; - int total = sampleCount * Sound.ChannelCount; - if (total > samples.Length) { total = samples.Length; } - _deviceBuffer.Write(samples, 0, total, _actualWriteOffsetBytes, LockFlags.None); + _deviceBuffer.Write(samples, sampleOffset * Sound.ChannelCount, sampleCount * Sound.ChannelCount, _actualWriteOffsetBytes, LockFlags.None); _actualWriteOffsetBytes = (_actualWriteOffsetBytes + (sampleCount * Sound.BlockAlign)) % BufferSizeBytes; _filledBufferSizeBytes += sampleCount * Sound.BlockAlign; } diff --git a/BizHawk.Client.EmuHawk/Sound/Output/DummySoundOutput.cs b/BizHawk.Client.EmuHawk/Sound/Output/DummySoundOutput.cs index d1632ced87..31aebb6fa1 100644 --- a/BizHawk.Client.EmuHawk/Sound/Output/DummySoundOutput.cs +++ b/BizHawk.Client.EmuHawk/Sound/Output/DummySoundOutput.cs @@ -73,7 +73,7 @@ namespace BizHawk.Client.EmuHawk return samplesNeeded; } - public void WriteSamples(short[] samples, int sampleCount) + public void WriteSamples(short[] samples, int sampleOffset, int sampleCount) { if (sampleCount == 0) return; _remainingSamples += sampleCount; diff --git a/BizHawk.Client.EmuHawk/Sound/Output/OpenALSoundOutput.cs b/BizHawk.Client.EmuHawk/Sound/Output/OpenALSoundOutput.cs index 263a18c5be..37d3d277ea 100644 --- a/BizHawk.Client.EmuHawk/Sound/Output/OpenALSoundOutput.cs +++ b/BizHawk.Client.EmuHawk/Sound/Output/OpenALSoundOutput.cs @@ -17,6 +17,7 @@ namespace BizHawk.Client.EmuHawk private int _sourceID; private BufferPool _bufferPool; private int _currentSamplesQueued; + private short[] _tempSampleBuffer; public OpenALSoundOutput(Sound sound) { @@ -94,11 +95,17 @@ namespace BizHawk.Client.EmuHawk return samplesNeeded; } - public void WriteSamples(short[] samples, int sampleCount) + public void WriteSamples(short[] samples, int sampleOffset, int sampleCount) { if (sampleCount == 0) return; UnqueueProcessedBuffers(); int byteCount = sampleCount * Sound.BlockAlign; + if (sampleOffset != 0) + { + AllocateTempSampleBuffer(sampleCount); + Buffer.BlockCopy(samples, sampleOffset * Sound.BlockAlign, _tempSampleBuffer, 0, byteCount); + samples = _tempSampleBuffer; + } var buffer = _bufferPool.Obtain(byteCount); AL.BufferData(buffer.BufferID, ALFormat.Stereo16, samples, byteCount, Sound.SampleRate); AL.SourceQueueBuffer(_sourceID, buffer.BufferID); @@ -127,6 +134,15 @@ namespace BizHawk.Client.EmuHawk return value; } + private void AllocateTempSampleBuffer(int sampleCount) + { + int length = sampleCount * Sound.ChannelCount; + if (_tempSampleBuffer == null || _tempSampleBuffer.Length < length) + { + _tempSampleBuffer = new short[length]; + } + } + private class BufferPool : IDisposable { private Stack _availableItems = new Stack(); diff --git a/BizHawk.Client.EmuHawk/Sound/Output/XAudio2SoundOutput.cs b/BizHawk.Client.EmuHawk/Sound/Output/XAudio2SoundOutput.cs index e5bf4f8dc0..80fb913f06 100644 --- a/BizHawk.Client.EmuHawk/Sound/Output/XAudio2SoundOutput.cs +++ b/BizHawk.Client.EmuHawk/Sound/Output/XAudio2SoundOutput.cs @@ -49,7 +49,9 @@ namespace BizHawk.Client.EmuHawk { using (XAudio2 device = new XAudio2()) { - return Enumerable.Range(0, device.DeviceCount).Select(n => device.GetDeviceDetails(n).DisplayName).ToList(); + return Enumerable.Range(0, device.DeviceCount) + .Select(n => device.GetDeviceDetails(n).DisplayName) + .ToList(); // enumerate before local var device is disposed } } @@ -110,14 +112,13 @@ namespace BizHawk.Client.EmuHawk return samplesNeeded; } - public void WriteSamples(short[] samples, int sampleCount) + public void WriteSamples(short[] samples, int sampleOffset, int sampleCount) { if (sampleCount == 0) return; _bufferPool.Release(_sourceVoice.State.BuffersQueued); int byteCount = sampleCount * Sound.BlockAlign; var buffer = _bufferPool.Obtain(byteCount); - if (byteCount > (samples.Length * 2)) { byteCount = samples.Length * 2; } - Buffer.BlockCopy(samples, 0, buffer.Bytes, 0, byteCount); + Buffer.BlockCopy(samples, sampleOffset * Sound.BlockAlign, buffer.Bytes, 0, byteCount); _sourceVoice.SubmitSourceBuffer(new AudioBuffer { AudioBytes = byteCount, diff --git a/BizHawk.Client.EmuHawk/Sound/Sound.cs b/BizHawk.Client.EmuHawk/Sound/Sound.cs index 85aaa2502d..6156b3cfc4 100644 --- a/BizHawk.Client.EmuHawk/Sound/Sound.cs +++ b/BizHawk.Client.EmuHawk/Sound/Sound.cs @@ -16,8 +16,6 @@ namespace BizHawk.Client.EmuHawk public const int BlockAlign = BytesPerSample * ChannelCount; private bool _disposed; - private bool _unjamSoundThrottle; - private readonly ISoundOutput _outputDevice; private readonly SoundOutputProvider _outputProvider = new SoundOutputProvider(); // Buffer for Sync sources private readonly BufferedAsync _bufferedAsync = new BufferedAsync(); // Buffer for Async sources @@ -118,9 +116,8 @@ namespace BizHawk.Client.EmuHawk // Fill device buffer with silence but leave enough room for one frame int samplesPerFrame = (int)Math.Round(SampleRate / (double)Global.Emulator.VsyncRate()); int silenceSamples = Math.Max(samplesNeeded - samplesPerFrame, 0); - _outputDevice.WriteSamples(new short[silenceSamples * 2], silenceSamples); + _outputDevice.WriteSamples(new short[silenceSamples * 2], 0, silenceSamples); samplesNeeded -= silenceSamples; - _unjamSoundThrottle = isUnderrun; if (isUnderrun) { @@ -141,14 +138,16 @@ namespace BizHawk.Client.EmuHawk if (atten > 1) atten = 1; _outputDevice.ApplyVolumeSettings(atten); - short[] samples; int samplesNeeded = _outputDevice.CalculateSamplesNeeded(); - int samplesProvided; + short[] samples; + int sampleOffset; + int sampleCount; if (atten == 0) { samples = new short[samplesNeeded * ChannelCount]; - samplesProvided = samplesNeeded; + sampleOffset = 0; + sampleCount = samplesNeeded; _bufferedProvider.DiscardSamples(); } @@ -156,25 +155,34 @@ namespace BizHawk.Client.EmuHawk { if (Global.Config.SoundThrottle) { - _outputProvider.BaseSoundProvider.GetSamplesSync(out samples, out samplesProvided); + _outputProvider.BaseSoundProvider.GetSamplesSync(out samples, out sampleCount); + sampleOffset = 0; - if (Global.DisableSecondaryThrottling && samplesProvided > samplesNeeded) + if (Global.DisableSecondaryThrottling && sampleCount > samplesNeeded) { return; } - while (samplesProvided > samplesNeeded) + int samplesPerMs = SampleRate / 1000; + int outputThresholdMs = 20; + while (sampleCount > samplesNeeded) { - Thread.Sleep((samplesProvided - samplesNeeded) / (SampleRate / 1000)); // Let the audio clock control sleep time - samplesNeeded = _outputDevice.CalculateSamplesNeeded(); - if (_unjamSoundThrottle) + if (samplesNeeded >= outputThresholdMs * samplesPerMs) { - //may be garbage, but what can we do? - samplesProvided = samplesNeeded; - break; + // If we were given a large enough number of samples (e.g. larger than the device's + // buffer), the device will never need that many samples no matter how long we + // wait, so we have to start splitting up the output + _outputDevice.WriteSamples(samples, sampleOffset, samplesNeeded); + sampleOffset += samplesNeeded; + sampleCount -= samplesNeeded; } + else + { + // Let the audio clock control sleep time + Thread.Sleep(Math.Min((sampleCount - samplesNeeded) / samplesPerMs, outputThresholdMs)); + } + samplesNeeded = _outputDevice.CalculateSamplesNeeded(); } - _unjamSoundThrottle = false; } else { @@ -182,7 +190,8 @@ namespace BizHawk.Client.EmuHawk { _outputProvider.OnVolatility(); } - _outputProvider.GetSamples(samplesNeeded, out samples, out samplesProvided); + _outputProvider.GetSamples(samplesNeeded, out samples, out sampleCount); + sampleOffset = 0; } } else if (_bufferedProvider == _bufferedAsync) @@ -191,14 +200,15 @@ namespace BizHawk.Client.EmuHawk _bufferedAsync.GetSamplesAsync(samples); - samplesProvided = samplesNeeded; + sampleOffset = 0; + sampleCount = samplesNeeded; } else { return; } - _outputDevice.WriteSamples(samples, samplesProvided); + _outputDevice.WriteSamples(samples, sampleOffset, sampleCount); } public static int MillisecondsToSamples(int milliseconds) diff --git a/BizHawk.Client.EmuHawk/ToolAttribute.cs b/BizHawk.Client.EmuHawk/ToolAttribute.cs index 721fa0cf48..53a2f837da 100644 --- a/BizHawk.Client.EmuHawk/ToolAttribute.cs +++ b/BizHawk.Client.EmuHawk/ToolAttribute.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; namespace BizHawk.Client.EmuHawk { @@ -9,14 +10,14 @@ namespace BizHawk.Client.EmuHawk public ToolAttribute(bool released, string[] supportedSystems, string[] unsupportedCores = null) { Released = released; - SupportedSystems = supportedSystems; - UnsupportedCores = unsupportedCores; + SupportedSystems = supportedSystems ?? Enumerable.Empty(); + UnsupportedCores = unsupportedCores ?? Enumerable.Empty(); } - public bool Released { get; private set; } + public bool Released { get; } - public IEnumerable SupportedSystems { get; private set; } + public IEnumerable SupportedSystems { get; } - public IEnumerable UnsupportedCores { get; private set; } + public IEnumerable UnsupportedCores { get; } } } diff --git a/BizHawk.Client.EmuHawk/UIHelper.cs b/BizHawk.Client.EmuHawk/UIHelper.cs index 27fffa4448..cc74296676 100644 --- a/BizHawk.Client.EmuHawk/UIHelper.cs +++ b/BizHawk.Client.EmuHawk/UIHelper.cs @@ -2,42 +2,21 @@ using System.Drawing; using System.Windows.Forms; -namespace BizHawk.Client.Common +namespace BizHawk.Client.EmuHawk { public static class UIHelper { - private static readonly AutoScaleMode _autoScaleMode = AutoScaleMode.Font; - private static readonly SizeF _autoScaleBaseSize = new SizeF(6F, 13F); - private static readonly SizeF _autoScaleCurrentSize = GetCurrentAutoScaleSize(_autoScaleMode); + public static AutoScaleMode AutoScaleMode { get; } = AutoScaleMode.Font; - private static SizeF GetCurrentAutoScaleSize(AutoScaleMode autoScaleMode) - { - using (Form form = new Form()) - { - form.AutoScaleMode = autoScaleMode; - return form.CurrentAutoScaleDimensions; - } - } + public static SizeF AutoScaleBaseSize { get; } = new SizeF(6F, 13F); - public static AutoScaleMode AutoScaleMode - { - get { return _autoScaleMode; } - } + public static SizeF AutoScaleCurrentSize { get; } = GetCurrentAutoScaleSize(AutoScaleMode); - public static SizeF AutoScaleBaseSize - { - get { return _autoScaleBaseSize; } - } + public static float AutoScaleFactorX { get; } = AutoScaleCurrentSize.Width / AutoScaleBaseSize.Width; - public static float AutoScaleFactorX - { - get { return _autoScaleCurrentSize.Width / _autoScaleBaseSize.Width; } - } + public static float AutoScaleFactorY { get; } = AutoScaleCurrentSize.Height / AutoScaleBaseSize.Height; - public static float AutoScaleFactorY - { - get { return _autoScaleCurrentSize.Height / _autoScaleBaseSize.Height; } - } + public static SizeF AutoScaleFactor { get; } = new SizeF(AutoScaleFactorX, AutoScaleFactorY); public static int ScaleX(int size) { @@ -58,5 +37,13 @@ namespace BizHawk.Client.Common { return new Size(ScaleX(s.Width), ScaleY(s.Height)); } + + private static SizeF GetCurrentAutoScaleSize(AutoScaleMode autoScaleMode) + { + using (var form = new Form { AutoScaleMode = autoScaleMode }) + { + return form.CurrentAutoScaleDimensions; + } + } } } diff --git a/BizHawk.Client.EmuHawk/app.config b/BizHawk.Client.EmuHawk/app.config index 9b69721c46..9d91d3673b 100644 --- a/BizHawk.Client.EmuHawk/app.config +++ b/BizHawk.Client.EmuHawk/app.config @@ -3,7 +3,10 @@ - - - + + + + + + diff --git a/BizHawk.Client.EmuHawk/app.manifest b/BizHawk.Client.EmuHawk/app.manifest new file mode 100644 index 0000000000..c86efcb5ad --- /dev/null +++ b/BizHawk.Client.EmuHawk/app.manifest @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + + + diff --git a/BizHawk.Client.EmuHawk/config/ControllerConfig.Designer.cs b/BizHawk.Client.EmuHawk/config/ControllerConfig.Designer.cs index 20d7076fdf..cc024b4a27 100644 --- a/BizHawk.Client.EmuHawk/config/ControllerConfig.Designer.cs +++ b/BizHawk.Client.EmuHawk/config/ControllerConfig.Designer.cs @@ -302,7 +302,8 @@ this.Name = "ControllerConfig"; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; this.Text = "Controller Config"; - this.Load += new System.EventHandler(this.NewControllerConfig_Load); + this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.ControllerConfig_FormClosed); + this.Load += new System.EventHandler(this.ControllerConfig_Load); this.tabControl1.ResumeLayout(false); this.tableLayoutPanel1.ResumeLayout(false); ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit(); diff --git a/BizHawk.Client.EmuHawk/config/ControllerConfig.cs b/BizHawk.Client.EmuHawk/config/ControllerConfig.cs index 25b246d55f..01408593e5 100644 --- a/BizHawk.Client.EmuHawk/config/ControllerConfig.cs +++ b/BizHawk.Client.EmuHawk/config/ControllerConfig.cs @@ -49,7 +49,12 @@ namespace BizHawk.Client.EmuHawk ControllerImages.Add("Apple IIe Keyboard", Properties.Resources.AppleIIKeyboard); ControllerImages.Add("VirtualBoy Controller", Properties.Resources.VBoyController); ControllerImages.Add("NeoGeo Portable Controller", Properties.Resources.NGPController); - + ControllerImages.Add("MAME Controller", Properties.Resources.ArcadeController); + } + + private ControllerConfig() + { + InitializeComponent(); } protected override void OnActivated(EventArgs e) @@ -64,13 +69,14 @@ namespace BizHawk.Client.EmuHawk Input.Instance.ControlInputFocus(this, Input.InputFocus.Mouse, false); } - private ControllerConfig() + private void ControllerConfig_Load(object sender, EventArgs e) { - InitializeComponent(); - Closing += (o, e) => - { - buttonOK.Focus(); // A very dirty hack to avoid https://code.google.com/p/bizhawk/issues/detail?id=161 - }; + Text = $"{_theDefinition.Name} Configuration"; + } + + private void ControllerConfig_FormClosed(object sender, FormClosedEventArgs e) + { + Input.Instance.ClearEvents(); } private delegate Control PanelCreator(Dictionary settings, List buttons, Size size); @@ -187,7 +193,10 @@ namespace BizHawk.Client.EmuHawk if (Global.Emulator.SystemId == "ZXSpectrum" || Global.Emulator.SystemId == "AmstradCPC" || Global.Emulator.SystemId == "ChannelF") return; - string tabname = (Global.Emulator.SystemId == "C64") ? "Keyboard" : "Console"; // hack + string tabname = + (Global.Emulator.SystemId == "C64") ? "Keyboard" : + (Global.Emulator.SystemId == "MAME") ? "Misc" : + "Console"; // hack tt.TabPages.Add(tabname); tt.TabPages[pageidx].Controls.Add(createpanel(settings, buckets[0], tt.Size)); } @@ -365,11 +374,6 @@ namespace BizHawk.Client.EmuHawk Close(); } - private void NewControllerConfig_Load(object sender, EventArgs e) - { - Text = $"{_theDefinition.Name} Configuration"; - } - private static TabControl GetTabControl(IEnumerable controls) { if (controls != null) diff --git a/BizHawk.Client.EmuHawk/config/GuiOptions.Designer.cs b/BizHawk.Client.EmuHawk/config/GuiOptions.Designer.cs index 70e35459eb..038f9c74bf 100644 --- a/BizHawk.Client.EmuHawk/config/GuiOptions.Designer.cs +++ b/BizHawk.Client.EmuHawk/config/GuiOptions.Designer.cs @@ -42,6 +42,7 @@ this.NeverAskSaveCheckbox = new System.Windows.Forms.CheckBox(); this.label2 = new System.Windows.Forms.Label(); this.AcceptBackgroundInputCheckbox = new System.Windows.Forms.CheckBox(); + this.AcceptBackgroundInputControllerOnlyCheckBox = new System.Windows.Forms.CheckBox(); this.label1 = new System.Windows.Forms.Label(); this.RunInBackgroundCheckbox = new System.Windows.Forms.CheckBox(); this.SaveWindowPositionCheckbox = new System.Windows.Forms.CheckBox(); @@ -73,6 +74,7 @@ this.toolTip1 = new System.Windows.Forms.ToolTip(this.components); this.label9 = new System.Windows.Forms.Label(); this.label10 = new System.Windows.Forms.Label(); + this.HandleAlternateKeyboardLayoutsCheckBox = new System.Windows.Forms.CheckBox(); this.tabControl1.SuspendLayout(); this.tabPage1.SuspendLayout(); this.groupBox1.SuspendLayout(); @@ -120,10 +122,12 @@ // // tabPage1 // + this.tabPage1.Controls.Add(this.HandleAlternateKeyboardLayoutsCheckBox); this.tabPage1.Controls.Add(this.groupBox1); this.tabPage1.Controls.Add(this.NeverAskSaveCheckbox); this.tabPage1.Controls.Add(this.label2); this.tabPage1.Controls.Add(this.AcceptBackgroundInputCheckbox); + this.tabPage1.Controls.Add(this.AcceptBackgroundInputControllerOnlyCheckBox); this.tabPage1.Controls.Add(this.label1); this.tabPage1.Controls.Add(this.RunInBackgroundCheckbox); this.tabPage1.Controls.Add(this.SaveWindowPositionCheckbox); @@ -144,7 +148,7 @@ this.groupBox1.Controls.Add(this.StartFullScreenCheckbox); this.groupBox1.Controls.Add(this.label3); this.groupBox1.Controls.Add(this.SingleInstanceModeCheckbox); - this.groupBox1.Location = new System.Drawing.Point(6, 182); + this.groupBox1.Location = new System.Drawing.Point(6, 205); this.groupBox1.Name = "groupBox1"; this.groupBox1.Size = new System.Drawing.Size(369, 140); this.groupBox1.TabIndex = 13; @@ -215,7 +219,7 @@ this.label2.Location = new System.Drawing.Point(26, 155); this.label2.Name = "label2"; this.label2.Size = new System.Drawing.Size(349, 13); - this.label2.TabIndex = 9; + this.label2.TabIndex = 10; this.label2.Text = "When this is set, the client will receive user input even when focus is lost"; // // AcceptBackgroundInputCheckbox @@ -227,6 +231,18 @@ this.AcceptBackgroundInputCheckbox.TabIndex = 8; this.AcceptBackgroundInputCheckbox.Text = "Accept background input"; this.AcceptBackgroundInputCheckbox.UseVisualStyleBackColor = true; + this.AcceptBackgroundInputCheckbox.CheckedChanged += new System.EventHandler(this.AcceptBackgroundInputCheckbox_CheckedChanged); + // + // AcceptBackgroundInputControllerOnlyCheckBox + // + this.AcceptBackgroundInputControllerOnlyCheckBox.AutoSize = true; + this.AcceptBackgroundInputControllerOnlyCheckBox.Enabled = false; + this.AcceptBackgroundInputControllerOnlyCheckBox.Location = new System.Drawing.Point(156, 135); + this.AcceptBackgroundInputControllerOnlyCheckBox.Name = "AcceptBackgroundInputControllerOnlyCheckBox"; + this.AcceptBackgroundInputControllerOnlyCheckBox.Size = new System.Drawing.Size(117, 17); + this.AcceptBackgroundInputControllerOnlyCheckBox.TabIndex = 9; + this.AcceptBackgroundInputControllerOnlyCheckBox.Text = "From controller only"; + this.AcceptBackgroundInputControllerOnlyCheckBox.UseVisualStyleBackColor = true; // // label1 // @@ -313,7 +329,7 @@ this.groupBox2.Margin = new System.Windows.Forms.Padding(0); this.groupBox2.Name = "groupBox2"; this.groupBox2.Size = new System.Drawing.Size(265, 60); - this.groupBox2.TabIndex = 27; + this.groupBox2.TabIndex = 5; this.groupBox2.TabStop = false; this.groupBox2.Text = "AutoSaveRAM"; // @@ -327,7 +343,7 @@ 0}); this.AutosaveSRAMtextBox.Name = "AutosaveSRAMtextBox"; this.AutosaveSRAMtextBox.Size = new System.Drawing.Size(50, 20); - this.AutosaveSRAMtextBox.TabIndex = 27; + this.AutosaveSRAMtextBox.TabIndex = 5; // // AutosaveSRAMradioButton1 // @@ -335,7 +351,7 @@ this.AutosaveSRAMradioButton1.Location = new System.Drawing.Point(48, 33); this.AutosaveSRAMradioButton1.Name = "AutosaveSRAMradioButton1"; this.AutosaveSRAMradioButton1.Size = new System.Drawing.Size(36, 17); - this.AutosaveSRAMradioButton1.TabIndex = 22; + this.AutosaveSRAMradioButton1.TabIndex = 2; this.AutosaveSRAMradioButton1.TabStop = true; this.AutosaveSRAMradioButton1.Text = "5s"; this.AutosaveSRAMradioButton1.UseVisualStyleBackColor = true; @@ -346,7 +362,7 @@ this.label8.Location = new System.Drawing.Point(202, 35); this.label8.Name = "label8"; this.label8.Size = new System.Drawing.Size(12, 13); - this.label8.TabIndex = 26; + this.label8.TabIndex = 6; this.label8.Text = "s"; // // AutosaveSRAMradioButton2 @@ -355,7 +371,7 @@ this.AutosaveSRAMradioButton2.Location = new System.Drawing.Point(90, 34); this.AutosaveSRAMradioButton2.Name = "AutosaveSRAMradioButton2"; this.AutosaveSRAMradioButton2.Size = new System.Drawing.Size(39, 17); - this.AutosaveSRAMradioButton2.TabIndex = 23; + this.AutosaveSRAMradioButton2.TabIndex = 3; this.AutosaveSRAMradioButton2.TabStop = true; this.AutosaveSRAMradioButton2.Text = "5m"; this.AutosaveSRAMradioButton2.UseVisualStyleBackColor = true; @@ -366,7 +382,7 @@ this.AutosaveSRAMradioButton3.Location = new System.Drawing.Point(131, 35); this.AutosaveSRAMradioButton3.Name = "AutosaveSRAMradioButton3"; this.AutosaveSRAMradioButton3.Size = new System.Drawing.Size(14, 13); - this.AutosaveSRAMradioButton3.TabIndex = 24; + this.AutosaveSRAMradioButton3.TabIndex = 4; this.AutosaveSRAMradioButton3.TabStop = true; this.AutosaveSRAMradioButton3.UseVisualStyleBackColor = true; this.AutosaveSRAMradioButton3.CheckedChanged += new System.EventHandler(this.AutosaveSRAMradioButton3_CheckedChanged); @@ -377,7 +393,7 @@ this.AutosaveSRAMCheckbox.Location = new System.Drawing.Point(6, 62); this.AutosaveSRAMCheckbox.Name = "AutosaveSRAMCheckbox"; this.AutosaveSRAMCheckbox.Size = new System.Drawing.Size(15, 14); - this.AutosaveSRAMCheckbox.TabIndex = 21; + this.AutosaveSRAMCheckbox.TabIndex = 4; this.AutosaveSRAMCheckbox.UseVisualStyleBackColor = true; this.AutosaveSRAMCheckbox.CheckedChanged += new System.EventHandler(this.AutosaveSRAMCheckbox_CheckedChanged); // @@ -397,7 +413,7 @@ this.label7.Location = new System.Drawing.Point(3, 1); this.label7.Name = "label7"; this.label7.Size = new System.Drawing.Size(50, 13); - this.label7.TabIndex = 2; + this.label7.TabIndex = 0; this.label7.Text = "Lua Core"; // // LuaInterfaceRadio @@ -406,7 +422,7 @@ this.LuaInterfaceRadio.Location = new System.Drawing.Point(4, 36); this.LuaInterfaceRadio.Name = "LuaInterfaceRadio"; this.LuaInterfaceRadio.Size = new System.Drawing.Size(338, 17); - this.LuaInterfaceRadio.TabIndex = 1; + this.LuaInterfaceRadio.TabIndex = 2; this.LuaInterfaceRadio.TabStop = true; this.LuaInterfaceRadio.Text = "Lua+LuaInterface - Faster but memory leaks, use at your own risk!"; this.LuaInterfaceRadio.UseVisualStyleBackColor = true; @@ -417,7 +433,7 @@ this.NLuaRadio.Location = new System.Drawing.Point(4, 17); this.NLuaRadio.Name = "NLuaRadio"; this.NLuaRadio.Size = new System.Drawing.Size(194, 17); - this.NLuaRadio.TabIndex = 0; + this.NLuaRadio.TabIndex = 1; this.NLuaRadio.TabStop = true; this.NLuaRadio.Text = "NLua+KopiLua - Reliable but slower"; this.NLuaRadio.UseVisualStyleBackColor = true; @@ -507,7 +523,7 @@ this.BackupSRamCheckbox.Location = new System.Drawing.Point(6, 39); this.BackupSRamCheckbox.Name = "BackupSRamCheckbox"; this.BackupSRamCheckbox.Size = new System.Drawing.Size(203, 17); - this.BackupSRamCheckbox.TabIndex = 9; + this.BackupSRamCheckbox.TabIndex = 3; this.BackupSRamCheckbox.Text = "Backup SaveRAM to .SaveRAM.bak"; this.BackupSRamCheckbox.UseVisualStyleBackColor = true; // @@ -536,7 +552,7 @@ this.label9.Location = new System.Drawing.Point(6, 16); this.label9.Name = "label9"; this.label9.Size = new System.Drawing.Size(225, 13); - this.label9.TabIndex = 28; + this.label9.TabIndex = 0; this.label9.Text = "Save SaveRAM to .AutoSaveRAM.SaveRAM"; // // label10 @@ -545,9 +561,19 @@ this.label10.Location = new System.Drawing.Point(9, 34); this.label10.Name = "label10"; this.label10.Size = new System.Drawing.Size(33, 13); - this.label10.TabIndex = 29; + this.label10.TabIndex = 1; this.label10.Text = "every"; // + // HandleAlternateKeyboardLayoutsCheckBox + // + this.HandleAlternateKeyboardLayoutsCheckBox.AutoSize = true; + this.HandleAlternateKeyboardLayoutsCheckBox.Location = new System.Drawing.Point(6, 175); + this.HandleAlternateKeyboardLayoutsCheckBox.Name = "HandleAlternateKeyboardLayoutsCheckBox"; + this.HandleAlternateKeyboardLayoutsCheckBox.Size = new System.Drawing.Size(255, 17); + this.HandleAlternateKeyboardLayoutsCheckBox.TabIndex = 11; + this.HandleAlternateKeyboardLayoutsCheckBox.Text = "Handle alternate keyboard layouts (e.g. Dvorak) [experimental]"; + this.HandleAlternateKeyboardLayoutsCheckBox.UseVisualStyleBackColor = true; + // // EmuHawkOptions // this.AcceptButton = this.OkBtn; @@ -593,6 +619,7 @@ private System.Windows.Forms.Label label1; private System.Windows.Forms.Label label2; private System.Windows.Forms.CheckBox AcceptBackgroundInputCheckbox; + private System.Windows.Forms.CheckBox AcceptBackgroundInputControllerOnlyCheckBox; private System.Windows.Forms.CheckBox NeverAskSaveCheckbox; private System.Windows.Forms.Label label3; private System.Windows.Forms.CheckBox SingleInstanceModeCheckbox; @@ -625,5 +652,6 @@ private System.Windows.Forms.NumericUpDown AutosaveSRAMtextBox; private System.Windows.Forms.Label label10; private System.Windows.Forms.Label label9; + private System.Windows.Forms.CheckBox HandleAlternateKeyboardLayoutsCheckBox; } } \ No newline at end of file diff --git a/BizHawk.Client.EmuHawk/config/GuiOptions.cs b/BizHawk.Client.EmuHawk/config/GuiOptions.cs index d5106c9d24..f05e73be46 100644 --- a/BizHawk.Client.EmuHawk/config/GuiOptions.cs +++ b/BizHawk.Client.EmuHawk/config/GuiOptions.cs @@ -49,6 +49,8 @@ namespace BizHawk.Client.EmuHawk SaveWindowPositionCheckbox.Checked = Global.Config.SaveWindowPosition; RunInBackgroundCheckbox.Checked = Global.Config.RunInBackground; AcceptBackgroundInputCheckbox.Checked = Global.Config.AcceptBackgroundInput; + AcceptBackgroundInputControllerOnlyCheckBox.Checked = Global.Config.AcceptBackgroundInputControllerOnly; + HandleAlternateKeyboardLayoutsCheckBox.Checked = Global.Config.HandleAlternateKeyboardLayouts; NeverAskSaveCheckbox.Checked = Global.Config.SupressAskSave; SingleInstanceModeCheckbox.Checked = Global.Config.SingleInstanceMode; @@ -83,6 +85,8 @@ namespace BizHawk.Client.EmuHawk Global.Config.SaveWindowPosition = SaveWindowPositionCheckbox.Checked; Global.Config.RunInBackground = RunInBackgroundCheckbox.Checked; Global.Config.AcceptBackgroundInput = AcceptBackgroundInputCheckbox.Checked; + Global.Config.AcceptBackgroundInputControllerOnly = AcceptBackgroundInputControllerOnlyCheckBox.Checked; + Global.Config.HandleAlternateKeyboardLayouts = HandleAlternateKeyboardLayoutsCheckBox.Checked; Global.Config.SupressAskSave = NeverAskSaveCheckbox.Checked; Global.Config.SingleInstanceMode = SingleInstanceModeCheckbox.Checked; @@ -113,6 +117,11 @@ namespace BizHawk.Client.EmuHawk GlobalWin.OSD.AddMessage("Customizing aborted."); } + private void AcceptBackgroundInputCheckbox_CheckedChanged(object sender, EventArgs e) + { + AcceptBackgroundInputControllerOnlyCheckBox.Enabled = AcceptBackgroundInputCheckbox.Checked; + } + private void AutosaveSRAMCheckbox_CheckedChanged(object sender, EventArgs e) { groupBox2.Enabled = AutosaveSRAMCheckbox.Checked; diff --git a/BizHawk.Client.EmuHawk/config/HotkeyConfig.Designer.cs b/BizHawk.Client.EmuHawk/config/HotkeyConfig.Designer.cs index 7047ff8b90..d37183c230 100644 --- a/BizHawk.Client.EmuHawk/config/HotkeyConfig.Designer.cs +++ b/BizHawk.Client.EmuHawk/config/HotkeyConfig.Designer.cs @@ -228,7 +228,8 @@ this.Name = "HotkeyConfig"; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; this.Text = "Configure Hotkeys"; - this.Load += new System.EventHandler(this.NewHotkeyWindow_Load); + this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.HotkeyConfig_FormClosed); + this.Load += new System.EventHandler(this.HotkeyConfig_Load); this.HotkeyTabControl.ResumeLayout(false); this.clearBtnContextMenu.ResumeLayout(false); this.ResumeLayout(false); diff --git a/BizHawk.Client.EmuHawk/config/HotkeyConfig.cs b/BizHawk.Client.EmuHawk/config/HotkeyConfig.cs index 24adc44d21..79ee9abc29 100644 --- a/BizHawk.Client.EmuHawk/config/HotkeyConfig.cs +++ b/BizHawk.Client.EmuHawk/config/HotkeyConfig.cs @@ -14,11 +14,6 @@ namespace BizHawk.Client.EmuHawk { InitializeComponent(); - Closing += (o, e) => - { - IDB_SAVE.Focus(); // A very dirty hack to avoid https://code.google.com/p/bizhawk/issues/detail?id=161 - }; - tabPage1.Focus(); } @@ -34,7 +29,7 @@ namespace BizHawk.Client.EmuHawk Input.Instance.ControlInputFocus(this, Input.InputFocus.Mouse, false); } - private void NewHotkeyWindow_Load(object sender, EventArgs e) + private void HotkeyConfig_Load(object sender, EventArgs e) { var source = new AutoCompleteStringCollection(); source.AddRange(Global.Config.HotkeyBindings.Select(x => x.DisplayName).ToArray()); @@ -47,6 +42,11 @@ namespace BizHawk.Client.EmuHawk DoFocus(); } + private void HotkeyConfig_FormClosed(object sender, FormClosedEventArgs e) + { + Input.Instance.ClearEvents(); + } + private void IDB_CANCEL_Click(object sender, EventArgs e) { GlobalWin.OSD.AddMessage("Hotkey config aborted"); @@ -72,64 +72,49 @@ namespace BizHawk.Client.EmuHawk foreach (var w in InputWidgets) { - var b = Global.Config.HotkeyBindings.FirstOrDefault(x => x.DisplayName == w.WidgetName); + var b = Global.Config.HotkeyBindings.First(x => x.DisplayName == w.WidgetName); b.Bindings = w.Bindings; } } - private IEnumerable InputWidgets - { - get - { - var widgets = new List(); - for (var x = 0; x < HotkeyTabControl.TabPages.Count; x++) - { - for (var y = 0; y < HotkeyTabControl.TabPages[x].Controls.Count; y++) - { - if (HotkeyTabControl.TabPages[x].Controls[y] is InputCompositeWidget) - { - widgets.Add(HotkeyTabControl.TabPages[x].Controls[y] as InputCompositeWidget); - } - } - } - return widgets; - } - } + private IEnumerable InputWidgets => + HotkeyTabControl.TabPages.Cast().SelectMany(tp => tp.Controls.OfType()); private void DoTabs() { + HotkeyTabControl.SuspendLayout(); HotkeyTabControl.TabPages.Clear(); // Buckets - var tabs = Global.Config.HotkeyBindings.Select(x => x.TabGroup).Distinct().ToList(); + var tabs = Global.Config.HotkeyBindings.Select(x => x.TabGroup).Distinct(); foreach (var tab in tabs) { - var _y = UIHelper.ScaleY(14); - var _x = UIHelper.ScaleX(6); - - var tb = new TabPage {Name = tab, Text = tab}; - - var bindings = Global.Config.HotkeyBindings.Where(x => x.TabGroup == tab).OrderBy(x => x.Ordinal).ThenBy(x => x.DisplayName).ToList(); - + var tb = new TabPage { Name = tab, Text = tab }; + var bindings = Global.Config.HotkeyBindings.Where(n => n.TabGroup == tab).OrderBy(n => n.Ordinal).ThenBy(n => n.DisplayName); + int x = UIHelper.ScaleX(6); + int y = UIHelper.ScaleY(14); int iwOffsetX = UIHelper.ScaleX(110); int iwOffsetY = UIHelper.ScaleY(-4); int iwWidth = UIHelper.ScaleX(120); + + tb.SuspendLayout(); + foreach (var b in bindings) { var l = new Label { Text = b.DisplayName, - Location = new Point(_x, _y), - Size = new Size(iwOffsetX - UIHelper.ScaleX(2), UIHelper.ScaleY(15)), + Location = new Point(x, y), + Size = new Size(iwOffsetX - UIHelper.ScaleX(2), UIHelper.ScaleY(15)) }; var w = new InputCompositeWidget { - Location = new Point(_x + iwOffsetX, _y + iwOffsetY), + Location = new Point(x + iwOffsetX, y + iwOffsetY), AutoTab = AutoTabCheckBox.Checked, Width = iwWidth, - WidgetName = b.DisplayName, + WidgetName = b.DisplayName }; w.SetupTooltip(toolTip1, b.ToolTip); @@ -140,11 +125,11 @@ namespace BizHawk.Client.EmuHawk tb.Controls.Add(l); tb.Controls.Add(w); - _y += UIHelper.ScaleY(24); - if (_y > HotkeyTabControl.Height - UIHelper.ScaleY(35)) + y += UIHelper.ScaleY(24); + if (y > HotkeyTabControl.Height - UIHelper.ScaleY(35)) { - _x += iwOffsetX + iwWidth + UIHelper.ScaleX(10); - _y = UIHelper.ScaleY(14); + x += iwOffsetX + iwWidth + UIHelper.ScaleX(10); + y = UIHelper.ScaleY(14); } } @@ -153,13 +138,16 @@ namespace BizHawk.Client.EmuHawk tb.Controls.Add(new Label { Text = "Save States hotkeys operate with branches when TAStudio is engaged.", - Location = new Point(_x, _y), - Size = new Size(iwWidth + iwOffsetX, HotkeyTabControl.Height - _y), + Location = new Point(x, y), + Size = new Size(iwWidth + iwOffsetX, HotkeyTabControl.Height - y) }); } HotkeyTabControl.TabPages.Add(tb); + tb.ResumeLayout(); } + + HotkeyTabControl.ResumeLayout(); } private void Defaults() @@ -232,7 +220,6 @@ namespace BizHawk.Client.EmuHawk if (w != null) { HotkeyTabControl.SelectTab((TabPage)w.Parent); - Input.Instance.BindUnpress(e.KeyCode); w.Focus(); } } diff --git a/BizHawk.Client.EmuHawk/config/InputWidget.cs b/BizHawk.Client.EmuHawk/config/InputWidget.cs index 7026051674..c34c500d5f 100644 --- a/BizHawk.Client.EmuHawk/config/InputWidget.cs +++ b/BizHawk.Client.EmuHawk/config/InputWidget.cs @@ -14,8 +14,8 @@ namespace BizHawk.Client.EmuHawk // TODO: when binding, make sure that the new key combo is not in one of the other bindings private readonly Timer _timer = new Timer(); private readonly List _bindings = new List(); - - private string _wasPressed = ""; + + private Input.InputEvent _lastPress; public InputCompositeWidget CompositeWidget { get; set; } @@ -88,9 +88,9 @@ namespace BizHawk.Client.EmuHawk protected override void OnEnter(EventArgs e) { + Input.Instance.ClearEvents(); + _lastPress = null; _timer.Start(); - - _wasPressed = Input.Instance.GetNextBindEvent(); BackColor = Color.FromArgb(unchecked((int)0xFFC0FFFF)); // Color.LightCyan is too light on Windows 8, this is a bit darker } @@ -102,6 +102,12 @@ namespace BizHawk.Client.EmuHawk base.OnLeave(e); } + protected override void OnHandleDestroyed(EventArgs e) + { + _timer.Stop(); + base.OnHandleDestroyed(e); + } + private void Timer_Tick(object sender, EventArgs e) { ReadKeys(); @@ -129,11 +135,7 @@ namespace BizHawk.Client.EmuHawk private void ReadKeys() { Input.Instance.Update(); - var bindingStr = Input.Instance.GetNextBindEvent(); - if (!string.IsNullOrEmpty(_wasPressed) && bindingStr == _wasPressed) - { - return; - } + var bindingStr = Input.Instance.GetNextBindEvent(ref _lastPress); if (bindingStr != null) { @@ -171,7 +173,6 @@ namespace BizHawk.Client.EmuHawk _bindings.Add(bindingStr); } - _wasPressed = bindingStr; UpdateLabel(); Increment(); } @@ -188,8 +189,6 @@ namespace BizHawk.Client.EmuHawk { base.OnKeyUp(e); } - - _wasPressed = ""; } protected override void OnKeyDown(KeyEventArgs e) diff --git a/BizHawk.Client.EmuHawk/config/NES/NESSyncSettingsForm.cs b/BizHawk.Client.EmuHawk/config/NES/NESSyncSettingsForm.cs index b343fe4355..3debf50624 100644 --- a/BizHawk.Client.EmuHawk/config/NES/NESSyncSettingsForm.cs +++ b/BizHawk.Client.EmuHawk/config/NES/NESSyncSettingsForm.cs @@ -64,7 +64,7 @@ namespace BizHawk.Client.EmuHawk typeof(NES.NESSyncSettings.Region), (string)RegionComboBox.SelectedItem); - List oldRam = _syncSettings.InitialWRamStatePattern?.ToList() ?? new List(); + var oldRam = _syncSettings.InitialWRamStatePattern ?? new List(); if (!string.IsNullOrWhiteSpace(RamPatternOverrideBox.Text)) { diff --git a/BizHawk.Client.EmuHawk/config/PathConfig.cs b/BizHawk.Client.EmuHawk/config/PathConfig.cs index 04b5886de9..71942ae196 100644 --- a/BizHawk.Client.EmuHawk/config/PathConfig.cs +++ b/BizHawk.Client.EmuHawk/config/PathConfig.cs @@ -115,8 +115,7 @@ namespace BizHawk.Client.EmuHawk var paths = pathCollection .Where(p => p.System == systemId) .OrderBy(p => p.Ordinal) - .ThenBy(p => p.Type) - .ToList(); + .ThenBy(p => p.Type); var y = UIHelper.ScaleY(14); foreach (var path in paths) @@ -261,10 +260,10 @@ namespace BizHawk.Client.EmuHawk private void DoRomToggle() { - AllPathControls - .Where(c => c.Name == "ROM") - .ToList() - .ForEach(control => control.Enabled = !RecentForROMs.Checked); + foreach (var control in AllPathControls.Where(c => c.Name == "ROM")) + { + control.Enabled = !RecentForROMs.Checked; + } } private IEnumerable AllPathBoxes diff --git a/BizHawk.Client.EmuHawk/config/RewindConfig.Designer.cs b/BizHawk.Client.EmuHawk/config/RewindConfig.Designer.cs index 144227ae21..0c2c1db224 100644 --- a/BizHawk.Client.EmuHawk/config/RewindConfig.Designer.cs +++ b/BizHawk.Client.EmuHawk/config/RewindConfig.Designer.cs @@ -186,7 +186,7 @@ this.label10.Location = new System.Drawing.Point(6, 20); this.label10.Name = "label10"; this.label10.Size = new System.Drawing.Size(40, 13); - this.label10.TabIndex = 17; + this.label10.TabIndex = 0; this.label10.Text = "Enable"; // // LargeStateEnabledBox @@ -195,7 +195,7 @@ this.LargeStateEnabledBox.Location = new System.Drawing.Point(9, 87); this.LargeStateEnabledBox.Name = "LargeStateEnabledBox"; this.LargeStateEnabledBox.Size = new System.Drawing.Size(15, 14); - this.LargeStateEnabledBox.TabIndex = 16; + this.LargeStateEnabledBox.TabIndex = 11; this.LargeStateEnabledBox.UseVisualStyleBackColor = true; this.LargeStateEnabledBox.CheckStateChanged += new System.EventHandler(this.LargeStateEnabledBox_CheckStateChanged); // @@ -205,7 +205,7 @@ this.MediumStateEnabledBox.Location = new System.Drawing.Point(9, 63); this.MediumStateEnabledBox.Name = "MediumStateEnabledBox"; this.MediumStateEnabledBox.Size = new System.Drawing.Size(15, 14); - this.MediumStateEnabledBox.TabIndex = 15; + this.MediumStateEnabledBox.TabIndex = 6; this.MediumStateEnabledBox.UseVisualStyleBackColor = true; this.MediumStateEnabledBox.CheckStateChanged += new System.EventHandler(this.MediumStateEnabledBox_CheckStateChanged); // @@ -215,7 +215,7 @@ this.SmallStateEnabledBox.Location = new System.Drawing.Point(9, 39); this.SmallStateEnabledBox.Name = "SmallStateEnabledBox"; this.SmallStateEnabledBox.Size = new System.Drawing.Size(15, 14); - this.SmallStateEnabledBox.TabIndex = 14; + this.SmallStateEnabledBox.TabIndex = 1; this.SmallStateEnabledBox.UseVisualStyleBackColor = true; this.SmallStateEnabledBox.CheckStateChanged += new System.EventHandler(this.SmallStateEnabledBox_CheckStateChanged); // @@ -234,7 +234,7 @@ this.LargeLabel3.Location = new System.Drawing.Point(307, 88); this.LargeLabel3.Name = "LargeLabel3"; this.LargeLabel3.Size = new System.Drawing.Size(38, 13); - this.LargeLabel3.TabIndex = 12; + this.LargeLabel3.TabIndex = 15; this.LargeLabel3.Text = "frames"; // // LargeSavestateNumeric @@ -252,7 +252,7 @@ 0}); this.LargeSavestateNumeric.Name = "LargeSavestateNumeric"; this.LargeSavestateNumeric.Size = new System.Drawing.Size(38, 20); - this.LargeSavestateNumeric.TabIndex = 11; + this.LargeSavestateNumeric.TabIndex = 14; this.LargeSavestateNumeric.Value = new decimal(new int[] { 1, 0, @@ -266,7 +266,7 @@ this.LargeLabel1.Location = new System.Drawing.Point(40, 88); this.LargeLabel1.Name = "LargeLabel1"; this.LargeLabel1.Size = new System.Drawing.Size(179, 13); - this.LargeLabel1.TabIndex = 10; + this.LargeLabel1.TabIndex = 12; this.LargeLabel1.Text = "Large savestates (more than 100KB)"; this.LargeLabel1.Click += new System.EventHandler(this.LargeLabel1_Click); // @@ -276,7 +276,7 @@ this.MediumLabel2.Location = new System.Drawing.Point(227, 64); this.MediumLabel2.Name = "MediumLabel2"; this.MediumLabel2.Size = new System.Drawing.Size(33, 13); - this.MediumLabel2.TabIndex = 9; + this.MediumLabel2.TabIndex = 8; this.MediumLabel2.Text = "every"; // // MediumLabel3 @@ -285,7 +285,7 @@ this.MediumLabel3.Location = new System.Drawing.Point(307, 64); this.MediumLabel3.Name = "MediumLabel3"; this.MediumLabel3.Size = new System.Drawing.Size(38, 13); - this.MediumLabel3.TabIndex = 8; + this.MediumLabel3.TabIndex = 10; this.MediumLabel3.Text = "frames"; // // MediumSavestateNumeric @@ -303,7 +303,7 @@ 0}); this.MediumSavestateNumeric.Name = "MediumSavestateNumeric"; this.MediumSavestateNumeric.Size = new System.Drawing.Size(38, 20); - this.MediumSavestateNumeric.TabIndex = 7; + this.MediumSavestateNumeric.TabIndex = 9; this.MediumSavestateNumeric.Value = new decimal(new int[] { 1, 0, @@ -317,7 +317,7 @@ this.MediumLabel1.Location = new System.Drawing.Point(40, 64); this.MediumLabel1.Name = "MediumLabel1"; this.MediumLabel1.Size = new System.Drawing.Size(160, 13); - this.MediumLabel1.TabIndex = 6; + this.MediumLabel1.TabIndex = 7; this.MediumLabel1.Text = "Medium savestates (32 - 100KB)"; this.MediumLabel1.Click += new System.EventHandler(this.MediumLabel1_Click); // @@ -327,7 +327,7 @@ this.SmallLabel2.Location = new System.Drawing.Point(227, 40); this.SmallLabel2.Name = "SmallLabel2"; this.SmallLabel2.Size = new System.Drawing.Size(33, 13); - this.SmallLabel2.TabIndex = 5; + this.SmallLabel2.TabIndex = 3; this.SmallLabel2.Text = "every"; // // SmallLabel3 @@ -336,7 +336,7 @@ this.SmallLabel3.Location = new System.Drawing.Point(307, 40); this.SmallLabel3.Name = "SmallLabel3"; this.SmallLabel3.Size = new System.Drawing.Size(38, 13); - this.SmallLabel3.TabIndex = 4; + this.SmallLabel3.TabIndex = 5; this.SmallLabel3.Text = "frames"; // // SmallSavestateNumeric @@ -354,7 +354,7 @@ 0}); this.SmallSavestateNumeric.Name = "SmallSavestateNumeric"; this.SmallSavestateNumeric.Size = new System.Drawing.Size(38, 20); - this.SmallSavestateNumeric.TabIndex = 3; + this.SmallSavestateNumeric.TabIndex = 4; this.SmallSavestateNumeric.Value = new decimal(new int[] { 1, 0, @@ -399,7 +399,7 @@ this.MediumStateTrackbar.Minimum = 1; this.MediumStateTrackbar.Name = "MediumStateTrackbar"; this.MediumStateTrackbar.Size = new System.Drawing.Size(186, 45); - this.MediumStateTrackbar.TabIndex = 7; + this.MediumStateTrackbar.TabIndex = 1; this.MediumStateTrackbar.TickFrequency = 256; this.MediumStateTrackbar.Value = 1; this.MediumStateTrackbar.ValueChanged += new System.EventHandler(this.MediumStateTrackbar_ValueChanged); @@ -417,7 +417,7 @@ this.groupBox2.Location = new System.Drawing.Point(12, 387); this.groupBox2.Name = "groupBox2"; this.groupBox2.Size = new System.Drawing.Size(371, 105); - this.groupBox2.TabIndex = 8; + this.groupBox2.TabIndex = 5; this.groupBox2.TabStop = false; this.groupBox2.Text = "State Size Definition"; // @@ -436,7 +436,7 @@ 0}); this.LargeStateUpDown.Name = "LargeStateUpDown"; this.LargeStateUpDown.Size = new System.Drawing.Size(52, 20); - this.LargeStateUpDown.TabIndex = 14; + this.LargeStateUpDown.TabIndex = 6; this.LargeStateUpDown.Value = new decimal(new int[] { 256, 0, @@ -459,7 +459,7 @@ 0}); this.MediumStateUpDown.Name = "MediumStateUpDown"; this.MediumStateUpDown.Size = new System.Drawing.Size(52, 20); - this.MediumStateUpDown.TabIndex = 13; + this.MediumStateUpDown.TabIndex = 2; this.MediumStateUpDown.Value = new decimal(new int[] { 1, 0, @@ -473,7 +473,7 @@ this.LargeStateSizeLabel.Location = new System.Drawing.Point(312, 71); this.LargeStateSizeLabel.Name = "LargeStateSizeLabel"; this.LargeStateSizeLabel.Size = new System.Drawing.Size(21, 13); - this.LargeStateSizeLabel.TabIndex = 12; + this.LargeStateSizeLabel.TabIndex = 7; this.LargeStateSizeLabel.Text = "KB"; // // label5 @@ -482,7 +482,7 @@ this.label5.Location = new System.Drawing.Point(27, 63); this.label5.Name = "label5"; this.label5.Size = new System.Drawing.Size(34, 13); - this.label5.TabIndex = 11; + this.label5.TabIndex = 4; this.label5.Text = "Large"; // // LargeStateTrackbar @@ -493,7 +493,7 @@ this.LargeStateTrackbar.Minimum = 256; this.LargeStateTrackbar.Name = "LargeStateTrackbar"; this.LargeStateTrackbar.Size = new System.Drawing.Size(186, 45); - this.LargeStateTrackbar.TabIndex = 10; + this.LargeStateTrackbar.TabIndex = 5; this.LargeStateTrackbar.TickFrequency = 1024; this.LargeStateTrackbar.Value = 256; this.LargeStateTrackbar.ValueChanged += new System.EventHandler(this.LargeStateTrackbar_ValueChanged); @@ -504,7 +504,7 @@ this.MediumStateSizeLabel.Location = new System.Drawing.Point(313, 35); this.MediumStateSizeLabel.Name = "MediumStateSizeLabel"; this.MediumStateSizeLabel.Size = new System.Drawing.Size(21, 13); - this.MediumStateSizeLabel.TabIndex = 9; + this.MediumStateSizeLabel.TabIndex = 3; this.MediumStateSizeLabel.Text = "KB"; // // label2 @@ -513,7 +513,7 @@ this.label2.Location = new System.Drawing.Point(18, 31); this.label2.Name = "label2"; this.label2.Size = new System.Drawing.Size(44, 13); - this.label2.TabIndex = 8; + this.label2.TabIndex = 0; this.label2.Text = "Medium"; // // groupBox3 @@ -531,7 +531,7 @@ this.groupBox3.Location = new System.Drawing.Point(12, 214); this.groupBox3.Name = "groupBox3"; this.groupBox3.Size = new System.Drawing.Size(371, 167); - this.groupBox3.TabIndex = 9; + this.groupBox3.TabIndex = 4; this.groupBox3.TabStop = false; this.groupBox3.Text = "Rewind Options"; // @@ -683,7 +683,7 @@ this.groupBox4.Location = new System.Drawing.Point(12, 12); this.groupBox4.Name = "groupBox4"; this.groupBox4.Size = new System.Drawing.Size(371, 72); - this.groupBox4.TabIndex = 12; + this.groupBox4.TabIndex = 2; this.groupBox4.TabStop = false; this.groupBox4.Text = "Current Statistics"; // @@ -767,7 +767,7 @@ this.groupBox6.Location = new System.Drawing.Point(22, 78); this.groupBox6.Name = "groupBox6"; this.groupBox6.Size = new System.Drawing.Size(215, 48); - this.groupBox6.TabIndex = 0; + this.groupBox6.TabIndex = 4; this.groupBox6.TabStop = false; this.groupBox6.Text = "Type"; // @@ -811,7 +811,7 @@ this.btnResetCompression.Location = new System.Drawing.Point(243, 34); this.btnResetCompression.Name = "btnResetCompression"; this.btnResetCompression.Size = new System.Drawing.Size(27, 27); - this.btnResetCompression.TabIndex = 23; + this.btnResetCompression.TabIndex = 3; this.toolTip1.SetToolTip(this.btnResetCompression, "Reset to default"); this.btnResetCompression.UseVisualStyleBackColor = true; this.btnResetCompression.Click += new System.EventHandler(this.BtnResetCompression_Click); @@ -823,7 +823,7 @@ this.trackBarCompression.Maximum = 9; this.trackBarCompression.Name = "trackBarCompression"; this.trackBarCompression.Size = new System.Drawing.Size(157, 45); - this.trackBarCompression.TabIndex = 20; + this.trackBarCompression.TabIndex = 1; this.toolTip1.SetToolTip(this.trackBarCompression, "0 = None; 9 = Maximum"); this.trackBarCompression.Value = 1; this.trackBarCompression.ValueChanged += new System.EventHandler(this.TrackBarCompression_ValueChanged); @@ -838,7 +838,7 @@ 0}); this.nudCompression.Name = "nudCompression"; this.nudCompression.Size = new System.Drawing.Size(52, 20); - this.nudCompression.TabIndex = 22; + this.nudCompression.TabIndex = 2; this.nudCompression.Value = new decimal(new int[] { 1, 0, @@ -866,7 +866,7 @@ this.groupBox7.Location = new System.Drawing.Point(389, 12); this.groupBox7.Name = "groupBox7"; this.groupBox7.Size = new System.Drawing.Size(342, 408); - this.groupBox7.TabIndex = 2; + this.groupBox7.TabIndex = 6; this.groupBox7.TabStop = false; this.groupBox7.Text = "Savestate Options"; // @@ -983,7 +983,7 @@ this.label12.Location = new System.Drawing.Point(19, 21); this.label12.Name = "label12"; this.label12.Size = new System.Drawing.Size(96, 13); - this.label12.TabIndex = 24; + this.label12.TabIndex = 0; this.label12.Text = "Compression Level"; // // RewindConfig diff --git a/BizHawk.Client.EmuHawk/config/SoundConfig.Designer.cs b/BizHawk.Client.EmuHawk/config/SoundConfig.Designer.cs index 29732a87ea..6c53cb8612 100644 --- a/BizHawk.Client.EmuHawk/config/SoundConfig.Designer.cs +++ b/BizHawk.Client.EmuHawk/config/SoundConfig.Designer.cs @@ -89,7 +89,7 @@ this.cbEnableNormal.Location = new System.Drawing.Point(6, 20); this.cbEnableNormal.Name = "cbEnableNormal"; this.cbEnableNormal.Size = new System.Drawing.Size(48, 17); - this.cbEnableNormal.TabIndex = 3; + this.cbEnableNormal.TabIndex = 0; this.cbEnableNormal.Text = "Ena."; this.cbEnableNormal.UseVisualStyleBackColor = true; this.cbEnableNormal.CheckedChanged += new System.EventHandler(this.UpdateSoundDialog); @@ -116,7 +116,7 @@ this.nudRWFF.Location = new System.Drawing.Point(58, 223); this.nudRWFF.Name = "nudRWFF"; this.nudRWFF.Size = new System.Drawing.Size(45, 20); - this.nudRWFF.TabIndex = 15; + this.nudRWFF.TabIndex = 7; this.nudRWFF.Value = new decimal(new int[] { 100, 0, @@ -129,7 +129,7 @@ this.cbEnableRWFF.Location = new System.Drawing.Point(58, 20); this.cbEnableRWFF.Name = "cbEnableRWFF"; this.cbEnableRWFF.Size = new System.Drawing.Size(48, 17); - this.cbEnableRWFF.TabIndex = 14; + this.cbEnableRWFF.TabIndex = 4; this.cbEnableRWFF.Text = "Ena."; this.cbEnableRWFF.UseVisualStyleBackColor = true; // @@ -141,7 +141,7 @@ this.tbRWFF.Name = "tbRWFF"; this.tbRWFF.Orientation = System.Windows.Forms.Orientation.Vertical; this.tbRWFF.Size = new System.Drawing.Size(42, 164); - this.tbRWFF.TabIndex = 13; + this.tbRWFF.TabIndex = 6; this.tbRWFF.TickFrequency = 10; this.tbRWFF.Scroll += new System.EventHandler(this.TbRwff_Scroll); // @@ -152,7 +152,7 @@ this.label2.Location = new System.Drawing.Point(56, 42); this.label2.Name = "label2"; this.label2.Size = new System.Drawing.Size(50, 13); - this.label2.TabIndex = 12; + this.label2.TabIndex = 5; this.label2.Text = "RW && FF"; // // label1 @@ -162,7 +162,7 @@ this.label1.Location = new System.Drawing.Point(6, 42); this.label1.Name = "label1"; this.label1.Size = new System.Drawing.Size(40, 13); - this.label1.TabIndex = 11; + this.label1.TabIndex = 1; this.label1.Text = "Normal"; // // tbNormal @@ -173,7 +173,7 @@ this.tbNormal.Name = "tbNormal"; this.tbNormal.Orientation = System.Windows.Forms.Orientation.Vertical; this.tbNormal.Size = new System.Drawing.Size(42, 164); - this.tbNormal.TabIndex = 0; + this.tbNormal.TabIndex = 2; this.tbNormal.TickFrequency = 10; this.tbNormal.Scroll += new System.EventHandler(this.TrackBar1_Scroll); // @@ -182,7 +182,7 @@ this.nudNormal.Location = new System.Drawing.Point(5, 223); this.nudNormal.Name = "nudNormal"; this.nudNormal.Size = new System.Drawing.Size(45, 20); - this.nudNormal.TabIndex = 1; + this.nudNormal.TabIndex = 3; this.nudNormal.Value = new decimal(new int[] { 100, 0, @@ -199,7 +199,7 @@ this.listBoxSoundDevices.Location = new System.Drawing.Point(138, 110); this.listBoxSoundDevices.Name = "listBoxSoundDevices"; this.listBoxSoundDevices.Size = new System.Drawing.Size(254, 95); - this.listBoxSoundDevices.TabIndex = 7; + this.listBoxSoundDevices.TabIndex = 8; // // SoundDeviceLabel // @@ -207,7 +207,7 @@ this.SoundDeviceLabel.Location = new System.Drawing.Point(135, 89); this.SoundDeviceLabel.Name = "SoundDeviceLabel"; this.SoundDeviceLabel.Size = new System.Drawing.Size(78, 13); - this.SoundDeviceLabel.TabIndex = 6; + this.SoundDeviceLabel.TabIndex = 7; this.SoundDeviceLabel.Text = "Sound Device:"; // // BufferSizeLabel @@ -217,7 +217,7 @@ this.BufferSizeLabel.Location = new System.Drawing.Point(135, 210); this.BufferSizeLabel.Name = "BufferSizeLabel"; this.BufferSizeLabel.Size = new System.Drawing.Size(61, 13); - this.BufferSizeLabel.TabIndex = 8; + this.BufferSizeLabel.TabIndex = 9; this.BufferSizeLabel.Text = "Buffer Size:"; // // BufferSizeNumeric @@ -236,7 +236,7 @@ 0}); this.BufferSizeNumeric.Name = "BufferSizeNumeric"; this.BufferSizeNumeric.Size = new System.Drawing.Size(59, 20); - this.BufferSizeNumeric.TabIndex = 9; + this.BufferSizeNumeric.TabIndex = 10; this.BufferSizeNumeric.Value = new decimal(new int[] { 100, 0, @@ -250,7 +250,7 @@ this.BufferSizeUnitsLabel.Location = new System.Drawing.Point(267, 210); this.BufferSizeUnitsLabel.Name = "BufferSizeUnitsLabel"; this.BufferSizeUnitsLabel.Size = new System.Drawing.Size(63, 13); - this.BufferSizeUnitsLabel.TabIndex = 10; + this.BufferSizeUnitsLabel.TabIndex = 11; this.BufferSizeUnitsLabel.Text = "milliseconds"; // // grpOutputMethod @@ -261,7 +261,7 @@ this.grpOutputMethod.Location = new System.Drawing.Point(292, 12); this.grpOutputMethod.Name = "grpOutputMethod"; this.grpOutputMethod.Size = new System.Drawing.Size(100, 90); - this.grpOutputMethod.TabIndex = 5; + this.grpOutputMethod.TabIndex = 12; this.grpOutputMethod.TabStop = false; this.grpOutputMethod.Text = "Output Method"; // @@ -307,7 +307,7 @@ this.cbMuteFrameAdvance.Location = new System.Drawing.Point(139, 68); this.cbMuteFrameAdvance.Name = "cbMuteFrameAdvance"; this.cbMuteFrameAdvance.Size = new System.Drawing.Size(128, 17); - this.cbMuteFrameAdvance.TabIndex = 17; + this.cbMuteFrameAdvance.TabIndex = 6; this.cbMuteFrameAdvance.Text = "Mute Frame Advance"; this.cbMuteFrameAdvance.UseVisualStyleBackColor = true; // @@ -317,7 +317,7 @@ this.cbEnableMaster.Location = new System.Drawing.Point(139, 16); this.cbEnableMaster.Name = "cbEnableMaster"; this.cbEnableMaster.Size = new System.Drawing.Size(128, 17); - this.cbEnableMaster.TabIndex = 18; + this.cbEnableMaster.TabIndex = 4; this.cbEnableMaster.Text = "Sound Master Enable"; this.cbEnableMaster.UseVisualStyleBackColor = true; this.cbEnableMaster.CheckedChanged += new System.EventHandler(this.UpdateSoundDialog); @@ -328,7 +328,7 @@ this.label3.Location = new System.Drawing.Point(161, 35); this.label3.Name = "label3"; this.label3.Size = new System.Drawing.Size(126, 26); - this.label3.TabIndex = 19; + this.label3.TabIndex = 5; this.label3.Text = "Controls whether cores even generate audio."; // // SoundConfig diff --git a/BizHawk.Client.EmuHawk/images/ControllerImages/ArcadeController.jpg b/BizHawk.Client.EmuHawk/images/ControllerImages/ArcadeController.jpg new file mode 100644 index 0000000000..d243bc8471 Binary files /dev/null and b/BizHawk.Client.EmuHawk/images/ControllerImages/ArcadeController.jpg differ diff --git a/BizHawk.Client.EmuHawk/images/mame.png b/BizHawk.Client.EmuHawk/images/mame.png new file mode 100644 index 0000000000..18f5678efd Binary files /dev/null and b/BizHawk.Client.EmuHawk/images/mame.png differ diff --git a/BizHawk.Client.EmuHawk/movie/PlayMovie.Designer.cs b/BizHawk.Client.EmuHawk/movie/PlayMovie.Designer.cs index 8afcc7d618..3ccf267f64 100644 --- a/BizHawk.Client.EmuHawk/movie/PlayMovie.Designer.cs +++ b/BizHawk.Client.EmuHawk/movie/PlayMovie.Designer.cs @@ -49,7 +49,7 @@ this.editToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.StopOnFrameCheckbox = new System.Windows.Forms.CheckBox(); this.StopOnFrameTextBox = new BizHawk.Client.EmuHawk.WatchValueBox(); - this.MovieView = new BizHawk.Client.EmuHawk.VirtualListView(); + this.MovieView = new System.Windows.Forms.ListView(); this.columnHeader1 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); this.columnHeader2 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); this.columnHeader3 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); @@ -269,7 +269,6 @@ this.MovieView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); - this.MovieView.BlazingFast = false; this.MovieView.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { this.columnHeader1, this.columnHeader2, @@ -279,16 +278,13 @@ this.MovieView.FullRowSelect = true; this.MovieView.GridLines = true; this.MovieView.HideSelection = false; - this.MovieView.ItemCount = 0; + this.MovieView.VirtualListSize = 0; this.MovieView.Location = new System.Drawing.Point(12, 28); this.MovieView.MultiSelect = false; this.MovieView.Name = "MovieView"; - this.MovieView.SelectAllInProgress = false; - this.MovieView.selectedItem = -1; this.MovieView.Size = new System.Drawing.Size(480, 322); this.MovieView.TabIndex = 5; this.MovieView.UseCompatibleStateImageBehavior = false; - this.MovieView.UseCustomBackground = true; this.MovieView.View = System.Windows.Forms.View.Details; this.MovieView.ColumnClick += new System.Windows.Forms.ColumnClickEventHandler(this.MovieView_ColumnClick); this.MovieView.SelectedIndexChanged += new System.EventHandler(this.MovieView_SelectedIndexChanged); @@ -381,7 +377,7 @@ private System.Windows.Forms.Button Cancel; private System.Windows.Forms.Button OK; private System.Windows.Forms.Button BrowseMovies; - private VirtualListView MovieView; + private System.Windows.Forms.ListView MovieView; private System.Windows.Forms.ColumnHeader columnHeader1; private System.Windows.Forms.ColumnHeader columnHeader2; private System.Windows.Forms.ColumnHeader columnHeader3; diff --git a/BizHawk.Client.EmuHawk/movie/PlayMovie.cs b/BizHawk.Client.EmuHawk/movie/PlayMovie.cs index 6365304e9f..7a3169b96f 100644 --- a/BizHawk.Client.EmuHawk/movie/PlayMovie.cs +++ b/BizHawk.Client.EmuHawk/movie/PlayMovie.cs @@ -27,7 +27,7 @@ namespace BizHawk.Client.EmuHawk public PlayMovie() { InitializeComponent(); - MovieView.QueryItemText += MovieView_QueryItemText; + MovieView.RetrieveVirtualItem += MovieView_QueryItemText; MovieView.VirtualMode = true; _sortReverse = false; _sortedCol = ""; @@ -45,28 +45,13 @@ namespace BizHawk.Client.EmuHawk TurboCheckbox.Checked = Global.Config.TurboSeek; } - private void MovieView_QueryItemText(int index, int column, out string text) + private void MovieView_QueryItemText(object sender, RetrieveVirtualItemEventArgs e) { - text = ""; - if (column == 0) // File - { - text = Path.GetFileName(_movieList[index].Filename); - } - - if (column == 1) // System - { - text = _movieList[index].SystemID; - } - - if (column == 2) // Game - { - text = _movieList[index].GameName; - } - - if (column == 3) // Time - { - text = PlatformFrameRates.MovieTime(_movieList[index]).ToString(@"hh\:mm\:ss\.fff"); - } + var entry = _movieList[e.ItemIndex]; + e.Item = new ListViewItem(entry.Filename); + e.Item.SubItems.Add(entry.SystemID); + e.Item.SubItems.Add(entry.GameName); + e.Item.SubItems.Add(PlatformFrameRates.MovieTime(entry).ToString(@"hh\:mm\:ss\.fff")); } private void Run() @@ -230,14 +215,13 @@ namespace BizHawk.Client.EmuHawk private void HighlightMovie(int index) { MovieView.SelectedIndices.Clear(); - MovieView.setSelection(index); - MovieView.SelectItem(index, true); + MovieView.Items[index].Selected = true; } private void ScanFiles() { _movieList.Clear(); - MovieView.ItemCount = 0; + MovieView.VirtualListSize = 0; MovieView.Update(); var directory = PathManager.MakeAbsolutePath(Global.Config.PathEntries.MoviesPathFragment, null); @@ -293,7 +277,7 @@ namespace BizHawk.Client.EmuHawk void RefreshMovieList() { - MovieView.ItemCount = _movieList.Count; + MovieView.VirtualListSize = _movieList.Count; UpdateList(); } @@ -306,10 +290,10 @@ namespace BizHawk.Client.EmuHawk { var filePaths = (string[])e.Data.GetData(DataFormats.FileDrop); - filePaths - .Where(path => MovieService.MovieExtensions.Contains(Path.GetExtension(path).Replace(".", ""))) - .ToList() - .ForEach(path => AddMovieToList(path, force: true)); + foreach (var path in filePaths.Where(path => MovieService.MovieExtensions.Contains(Path.GetExtension(path).Replace(".", "")))) + { + AddMovieToList(path, force: true); + } RefreshMovieList(); } @@ -403,7 +387,7 @@ namespace BizHawk.Client.EmuHawk OK.Enabled = true; var firstIndex = MovieView.SelectedIndices[0]; - MovieView.ensureVisible(firstIndex); + MovieView.EnsureVisible(firstIndex); foreach (var kvp in _movieList[firstIndex].HeaderEntries) { @@ -468,11 +452,11 @@ namespace BizHawk.Client.EmuHawk private void EditMenuItem_Click(object sender, EventArgs e) { - MovieView.SelectedIndices - .Cast() - .Select(index => _movieList[index]) - .ToList() - .ForEach(movie => System.Diagnostics.Process.Start(movie.Filename)); + foreach (var movie in MovieView.SelectedIndices.Cast() + .Select(index => _movieList[index])) + { + System.Diagnostics.Process.Start(movie.Filename); + } } #endregion @@ -593,8 +577,7 @@ namespace BizHawk.Client.EmuHawk if (index.HasValue) { MovieView.SelectedIndices.Clear(); - MovieView.setSelection(index.Value); - MovieView.SelectItem(index.Value, true); + MovieView.Items[index.Value].Selected = true; } } } diff --git a/BizHawk.Client.EmuHawk/tools/AutoHawk.Designer.cs b/BizHawk.Client.EmuHawk/tools/AutoHawk.Designer.cs deleted file mode 100644 index 5054e0208c..0000000000 --- a/BizHawk.Client.EmuHawk/tools/AutoHawk.Designer.cs +++ /dev/null @@ -1,86 +0,0 @@ -namespace BizHawk.Client.EmuHawk -{ - partial class AutoHawk - { - /// - /// Required designer variable. - /// - private System.ComponentModel.IContainer components = null; - - /// - /// Clean up any resources being used. - /// - /// true if managed resources should be disposed; otherwise, false. - protected override void Dispose(bool disposing) - { - if (disposing && (components != null)) - { - components.Dispose(); - } - base.Dispose(disposing); - } - - #region Windows Form Designer generated code - - /// - /// Required method for Designer support - do not modify - /// the contents of this method with the code editor. - /// - private void InitializeComponent() - { - this.AutoMenu = new System.Windows.Forms.MenuStrip(); - this.FileSubMenu = new System.Windows.Forms.ToolStripMenuItem(); - this.ExitMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.AutoMenu.SuspendLayout(); - this.SuspendLayout(); - // - // AutoMenu - // - this.AutoMenu.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.FileSubMenu}); - this.AutoMenu.Location = new System.Drawing.Point(0, 0); - this.AutoMenu.Name = "AutoMenu"; - this.AutoMenu.Size = new System.Drawing.Size(508, 24); - this.AutoMenu.TabIndex = 2; - this.AutoMenu.Text = "menuStrip1"; - // - // FileSubMenu - // - this.FileSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.ExitMenuItem}); - this.FileSubMenu.Name = "FileSubMenu"; - this.FileSubMenu.Size = new System.Drawing.Size(37, 20); - this.FileSubMenu.Text = "&File"; - // - // ExitMenuItem - // - this.ExitMenuItem.Name = "ExitMenuItem"; - this.ExitMenuItem.Size = new System.Drawing.Size(152, 22); - this.ExitMenuItem.Text = "E&xit"; - this.ExitMenuItem.Click += new System.EventHandler(this.ExitMenuItem_Click); - // - // AutoHawk - // - this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(508, 444); - this.Controls.Add(this.AutoMenu); - this.MainMenuStrip = this.AutoMenu; - this.Name = "AutoHawk"; - this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; - this.Text = "AutoHawk"; - this.Load += new System.EventHandler(this.AutoHawk_Load); - this.AutoMenu.ResumeLayout(false); - this.AutoMenu.PerformLayout(); - this.ResumeLayout(false); - this.PerformLayout(); - - } - - #endregion - - private System.Windows.Forms.MenuStrip AutoMenu; - private System.Windows.Forms.ToolStripMenuItem FileSubMenu; - private System.Windows.Forms.ToolStripMenuItem ExitMenuItem; - } -} \ No newline at end of file diff --git a/BizHawk.Client.EmuHawk/tools/AutoHawk.cs b/BizHawk.Client.EmuHawk/tools/AutoHawk.cs deleted file mode 100644 index c1674db0ee..0000000000 --- a/BizHawk.Client.EmuHawk/tools/AutoHawk.cs +++ /dev/null @@ -1,74 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Data; -using System.Drawing; -using System.Linq; -using System.Text; -using System.Windows.Forms; - -using BizHawk.Emulation.Common; - -namespace BizHawk.Client.EmuHawk -{ - [Tool(released: false, supportedSystems: null)] - public partial class AutoHawk : Form, IToolFormAutoConfig - { - public AutoHawk() - { - InitializeComponent(); - } - - private void AutoHawk_Load(object sender, EventArgs e) - { - - } - - [RequiredService] - public IMemoryDomains MemoryDomains { get; set; } - - [RequiredService] - public IStatable StatableCore { get; set; } - - [ConfigPersist] - public ConfigVariables Config { get; set; } - - public class ConfigVariables - { - // anything that needs to be saved in config.ini should go here - } - - #region IToolForm Implementation - - public void NewUpdate(ToolFormUpdateType type) { } - - public void UpdateValues() - { - // TODO: per frame stuff goes here - } - - public void FastUpdate() - { - // TODO: when the user is turboing this will be called, slow things like updating graphics should be avoided, but critical operations must still be done here - } - - public void Restart() - { - // When the user changes to a new ROM, closes a ROM, starts a movie, etc, this will be called - } - - public bool UpdateBefore { get { return true; } } - - public bool AskSaveChanges() - { - return true; - } - - #endregion - - private void ExitMenuItem_Click(object sender, EventArgs e) - { - Close(); - } - } -} diff --git a/BizHawk.Client.EmuHawk/tools/AutoHawk.resx b/BizHawk.Client.EmuHawk/tools/AutoHawk.resx deleted file mode 100644 index 435c368278..0000000000 --- a/BizHawk.Client.EmuHawk/tools/AutoHawk.resx +++ /dev/null @@ -1,123 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 17, 17 - - \ No newline at end of file diff --git a/BizHawk.Client.EmuHawk/tools/BasicBot/BasicBot.cs b/BizHawk.Client.EmuHawk/tools/BasicBot/BasicBot.cs index 5f32d9ecc4..e4a1d99ca2 100644 --- a/BizHawk.Client.EmuHawk/tools/BasicBot/BasicBot.cs +++ b/BizHawk.Client.EmuHawk/tools/BasicBot/BasicBot.cs @@ -449,10 +449,10 @@ namespace BizHawk.Client.EmuHawk CurrentFileName = ""; _bestBotAttempt = null; - ControlProbabilityPanel.Controls - .OfType() - .ToList() - .ForEach(cp => cp.Probability = 0); + foreach (var cp in ControlProbabilityPanel.Controls.OfType()) + { + cp.Probability = 0; + } FrameLength = 0; MaximizeAddress = 0; @@ -845,14 +845,14 @@ namespace BizHawk.Client.EmuHawk StartFromSlotBox.SelectedIndex = 0; - int starty = 0; + const int starty = 0; + const int lineHeight = 30; + const int marginLeft = 15; int accumulatedy = 0; - int lineHeight = 30; - int marginLeft = 15; int count = 0; + ControlProbabilityPanel.SuspendLayout(); ControlProbabilityPanel.Controls.Clear(); - foreach (var button in Emulator.ControllerDefinition.BoolButtons) { var control = new BotControlsRow @@ -863,11 +863,13 @@ namespace BizHawk.Client.EmuHawk TabIndex = count + 1, ProbabilityChangedCallback = AssessRunButtonStatus }; + control.Scale(UIHelper.AutoScaleFactor); ControlProbabilityPanel.Controls.Add(control); accumulatedy += lineHeight; count++; } + ControlProbabilityPanel.ResumeLayout(); if (Settings.RecentBotFiles.AutoLoad) { diff --git a/BizHawk.Client.EmuHawk/tools/BasicBot/BotControlsRow.Designer.cs b/BizHawk.Client.EmuHawk/tools/BasicBot/BotControlsRow.Designer.cs index 0ddb924cff..9ee550ffe8 100644 --- a/BizHawk.Client.EmuHawk/tools/BasicBot/BotControlsRow.Designer.cs +++ b/BizHawk.Client.EmuHawk/tools/BasicBot/BotControlsRow.Designer.cs @@ -72,8 +72,7 @@ // // BotControlsRow // - this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Inherit; this.Controls.Add(this.ProbabilitySlider); this.Controls.Add(this.ProbabilityUpDown); this.Controls.Add(this.ButtonNameLabel); diff --git a/BizHawk.Client.EmuHawk/tools/CDL.cs b/BizHawk.Client.EmuHawk/tools/CDL.cs index fa9e45556e..af444b8e08 100644 --- a/BizHawk.Client.EmuHawk/tools/CDL.cs +++ b/BizHawk.Client.EmuHawk/tools/CDL.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.IO; +using System.Linq; using System.Windows.Forms; using BizHawk.Emulation.Common; @@ -59,6 +60,24 @@ namespace BizHawk.Client.EmuHawk InitializeComponent(); tsbViewStyle.SelectedIndex = 0; + + lvCDL.AllColumns.Clear(); + lvCDL.AllColumns.AddRange(new [] + { + new RollColumn { Name = "CDLFile", Text = "CDL File @", Width = 107, Type = ColumnType.Text }, + new RollColumn { Name = "Domain", Text = "Domain", Width = 126, Type = ColumnType.Text }, + new RollColumn { Name = "Percent", Text = "%", Width = 58, Type = ColumnType.Text }, + new RollColumn { Name = "Mapped", Text = "Mapped", Width = 64, Type = ColumnType.Text }, + new RollColumn { Name = "Size", Text = "Size", Width = 112, Type = ColumnType.Text }, + new RollColumn { Name = "0x01", Text = "0x01", Width = 56, Type = ColumnType.Text }, + new RollColumn { Name = "0x02", Text = "0x02", Width = 56, Type = ColumnType.Text }, + new RollColumn { Name = "0x04", Text = "0x04", Width = 56, Type = ColumnType.Text }, + new RollColumn { Name = "0x08", Text = "0x08", Width = 56, Type = ColumnType.Text }, + new RollColumn { Name = "0x10", Text = "0x10", Width = 56, Type = ColumnType.Text }, + new RollColumn { Name = "0x20", Text = "0x20", Width = 56, Type = ColumnType.Text }, + new RollColumn { Name = "0x40", Text = "0x40", Width = 56, Type = ColumnType.Text }, + new RollColumn { Name = "0x80", Text = "0x80", Width = 56, Type = ColumnType.Text } + }); } public void NewUpdate(ToolFormUpdateType type) { } @@ -98,23 +117,10 @@ namespace BizHawk.Client.EmuHawk if (_cdl == null) { - lvCDL.BeginUpdate(); - if (OSTailoredCode.CurrentOS == OSTailoredCode.DistinctOS.Windows) - { - lvCDL.Items.Clear(); - } - else - { - // this is a winforms implementation problem for mono - // see https://github.com/mono/mono/issues/11070 - // until this is resolved in mono we should just skip this call - } - lvCDL.EndUpdate(); + lvCDL.DeselectAll(); return; } - lvCDL.BeginUpdate(); - listContents = new string[_cdl.Count][]; int idx = 0; @@ -183,8 +189,7 @@ namespace BizHawk.Client.EmuHawk } } - lvCDL.VirtualListSize = _cdl.Count; - lvCDL.EndUpdate(); + lvCDL.RowCount = _cdl.Count; } public bool AskSaveChanges() @@ -571,9 +576,10 @@ namespace BizHawk.Client.EmuHawk CodeDataLogger.SetCDL(null); } - private void lvCDL_QueryItemText(int item, int subItem, out string text) + private void lvCDL_QueryItemText(int index, RollColumn column, out string text, ref int offsetX, ref int offsetY) { - text = listContents[item][subItem]; + var subItem = lvCDL.AllColumns.IndexOf(column); + text = listContents[index][subItem]; } private void tsbExportText_Click(object sender, EventArgs e) diff --git a/BizHawk.Client.EmuHawk/tools/CDL.designer.cs b/BizHawk.Client.EmuHawk/tools/CDL.designer.cs index a43f020105..5b24949487 100644 --- a/BizHawk.Client.EmuHawk/tools/CDL.designer.cs +++ b/BizHawk.Client.EmuHawk/tools/CDL.designer.cs @@ -52,20 +52,7 @@ this.tsbViewStyle = new System.Windows.Forms.ToolStripComboBox(); this.toolStripSeparator4 = new System.Windows.Forms.ToolStripSeparator(); this.tsbExportText = new System.Windows.Forms.ToolStripButton(); - this.lvCDL = new BizHawk.Client.EmuHawk.VirtualListView(); - this.colAddress = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); - this.colDomain = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); - this.colPct = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); - this.colMapped = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); - this.colSize = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); - this.colFlag01 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); - this.colFlag02 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); - this.colFlag04 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); - this.colFlag08 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); - this.colFlag10 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); - this.colFlag20 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); - this.colFlag40 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); - this.colFlag80 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.lvCDL = new InputRoll(); this.miAutoResume = new System.Windows.Forms.ToolStripMenuItem(); this.menuStrip1.SuspendLayout(); this.toolStrip1.SuspendLayout(); @@ -280,93 +267,18 @@ // // lvCDL // - this.lvCDL.BlazingFast = false; - this.lvCDL.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { - this.colAddress, - this.colDomain, - this.colPct, - this.colMapped, - this.colSize, - this.colFlag01, - this.colFlag02, - this.colFlag04, - this.colFlag08, - this.colFlag10, - this.colFlag20, - this.colFlag40, - this.colFlag80}); this.lvCDL.Dock = System.Windows.Forms.DockStyle.Fill; this.lvCDL.FullRowSelect = true; this.lvCDL.GridLines = true; - this.lvCDL.ItemCount = 0; + this.lvCDL.RowCount = 0; this.lvCDL.Location = new System.Drawing.Point(0, 49); this.lvCDL.Name = "lvCDL"; - this.lvCDL.SelectAllInProgress = false; - this.lvCDL.selectedItem = -1; this.lvCDL.Size = new System.Drawing.Size(992, 323); this.lvCDL.TabIndex = 9; - this.lvCDL.UseCompatibleStateImageBehavior = false; this.lvCDL.UseCustomBackground = true; - this.lvCDL.View = System.Windows.Forms.View.Details; - this.lvCDL.VirtualMode = true; - this.lvCDL.QueryItemText += new BizHawk.Client.EmuHawk.QueryItemTextHandler(this.lvCDL_QueryItemText); - // - // colAddress - // - this.colAddress.Text = "CDL File @"; - this.colAddress.Width = 107; - // - // colDomain - // - this.colDomain.Text = "Domain"; - this.colDomain.Width = 126; - // - // colPct - // - this.colPct.Text = "%"; - this.colPct.Width = 58; - // - // colMapped - // - this.colMapped.Text = "Mapped"; - this.colMapped.Width = 64; - // - // colSize - // - this.colSize.Text = "Size"; - this.colSize.Width = 102; - // - // colFlag01 - // - this.colFlag01.Text = "0x01"; - // - // colFlag02 - // - this.colFlag02.Text = "0x02"; - // - // colFlag04 - // - this.colFlag04.Text = "0x04"; - // - // colFlag08 - // - this.colFlag08.Text = "0x08"; - // - // colFlag10 - // - this.colFlag10.Text = "0x10"; - // - // colFlag20 - // - this.colFlag20.Text = "0x20"; - // - // colFlag40 - // - this.colFlag40.Text = "0x40"; - // - // colFlag80 - // - this.colFlag80.Text = "0x80"; + this.lvCDL.AllowColumnReorder = false; + this.lvCDL.AllowColumnResize = true; + this.lvCDL.QueryItemText += new InputRoll.QueryItemTextHandler(this.lvCDL_QueryItemText); // // miAutoResume // @@ -422,20 +334,7 @@ private System.Windows.Forms.ToolStripSeparator toolStripSeparator3; private System.Windows.Forms.ToolStripButton tsbViewUpdate; private System.Windows.Forms.ToolStripComboBox tsbViewStyle; - private VirtualListView lvCDL; - private System.Windows.Forms.ColumnHeader colAddress; - private System.Windows.Forms.ColumnHeader colDomain; - private System.Windows.Forms.ColumnHeader colPct; - private System.Windows.Forms.ColumnHeader colMapped; - private System.Windows.Forms.ColumnHeader colSize; - private System.Windows.Forms.ColumnHeader colFlag01; - private System.Windows.Forms.ColumnHeader colFlag02; - private System.Windows.Forms.ColumnHeader colFlag04; - private System.Windows.Forms.ColumnHeader colFlag08; - private System.Windows.Forms.ColumnHeader colFlag10; - private System.Windows.Forms.ColumnHeader colFlag20; - private System.Windows.Forms.ColumnHeader colFlag40; - private System.Windows.Forms.ColumnHeader colFlag80; + private InputRoll lvCDL; private System.Windows.Forms.ToolStripSeparator toolStripSeparator4; private System.Windows.Forms.ToolStripButton tsbExportText; private System.Windows.Forms.ToolStripMenuItem miAutoStart; diff --git a/BizHawk.Client.EmuHawk/tools/Cheats/CheatEdit.Designer.cs b/BizHawk.Client.EmuHawk/tools/Cheats/CheatEdit.Designer.cs index 1e115271d4..9707bb5bb5 100644 --- a/BizHawk.Client.EmuHawk/tools/Cheats/CheatEdit.Designer.cs +++ b/BizHawk.Client.EmuHawk/tools/Cheats/CheatEdit.Designer.cs @@ -41,7 +41,7 @@ this.DomainDropDown = new System.Windows.Forms.ComboBox(); this.SizeLabel = new System.Windows.Forms.Label(); this.SizeDropDown = new System.Windows.Forms.ComboBox(); - this.DisplayTypeLael = new System.Windows.Forms.Label(); + this.DisplayTypeLabel = new System.Windows.Forms.Label(); this.DisplayTypeDropDown = new System.Windows.Forms.ComboBox(); this.BigEndianCheckBox = new System.Windows.Forms.CheckBox(); this.AddButton = new System.Windows.Forms.Button(); @@ -174,14 +174,14 @@ this.SizeDropDown.TabIndex = 19; this.SizeDropDown.SelectedIndexChanged += new System.EventHandler(this.SizeDropDown_SelectedIndexChanged); // - // DisplayTypeLael + // DisplayTypeLabel // - this.DisplayTypeLael.AutoSize = true; - this.DisplayTypeLael.Location = new System.Drawing.Point(11, 219); - this.DisplayTypeLael.Name = "DisplayTypeLael"; - this.DisplayTypeLael.Size = new System.Drawing.Size(114, 25); - this.DisplayTypeLael.TabIndex = 20; - this.DisplayTypeLael.Text = "Display As"; + this.DisplayTypeLabel.AutoSize = true; + this.DisplayTypeLabel.Location = new System.Drawing.Point(11, 219); + this.DisplayTypeLabel.Name = "DisplayTypeLabel"; + this.DisplayTypeLabel.Size = new System.Drawing.Size(114, 25); + this.DisplayTypeLabel.TabIndex = 20; + this.DisplayTypeLabel.Text = "Display As"; // // DisplayTypeDropDown // @@ -289,7 +289,7 @@ this.Controls.Add(this.AddButton); this.Controls.Add(this.BigEndianCheckBox); this.Controls.Add(this.DisplayTypeDropDown); - this.Controls.Add(this.DisplayTypeLael); + this.Controls.Add(this.DisplayTypeLabel); this.Controls.Add(this.SizeDropDown); this.Controls.Add(this.SizeLabel); this.Controls.Add(this.DomainDropDown); @@ -330,7 +330,7 @@ private System.Windows.Forms.ComboBox DomainDropDown; private System.Windows.Forms.Label SizeLabel; private System.Windows.Forms.ComboBox SizeDropDown; - private System.Windows.Forms.Label DisplayTypeLael; + private System.Windows.Forms.Label DisplayTypeLabel; private System.Windows.Forms.ComboBox DisplayTypeDropDown; private System.Windows.Forms.CheckBox BigEndianCheckBox; private System.Windows.Forms.Button AddButton; diff --git a/BizHawk.Client.EmuHawk/tools/Cheats/Cheats.Designer.cs b/BizHawk.Client.EmuHawk/tools/Cheats/Cheats.Designer.cs index 63fce6be5a..10fa9bdabe 100644 --- a/BizHawk.Client.EmuHawk/tools/Cheats/Cheats.Designer.cs +++ b/BizHawk.Client.EmuHawk/tools/Cheats/Cheats.Designer.cs @@ -30,14 +30,7 @@ { this.components = new System.ComponentModel.Container(); System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Cheats)); - this.CheatListView = new BizHawk.Client.EmuHawk.VirtualListView(); - this.CheatName = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); - this.Address = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); - this.Value = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); - this.Compare = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); - this.ComparisonType = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); - this.On = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); - this.Domain = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.CheatListView = new InputRoll(); this.CheatsContextMenu = new System.Windows.Forms.ContextMenuStrip(this.components); this.ToggleContextMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.RemoveContextMenuItem = new System.Windows.Forms.ToolStripMenuItem(); @@ -102,35 +95,22 @@ // CheatListView // this.CheatListView.AllowColumnReorder = true; + this.CheatListView.AllowColumnResize = true; + this.CheatListView.MultiSelect = true; this.CheatListView.AllowDrop = true; this.CheatListView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); - this.CheatListView.AutoArrange = false; - this.CheatListView.BlazingFast = false; - this.CheatListView.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { - this.CheatName, - this.Address, - this.Value, - this.Compare, - this.ComparisonType, - this.On, - this.Domain}); this.CheatListView.ContextMenuStrip = this.CheatsContextMenu; this.CheatListView.FullRowSelect = true; this.CheatListView.GridLines = true; - this.CheatListView.HideSelection = false; - this.CheatListView.ItemCount = 0; + this.CheatListView.RowCount = 0; this.CheatListView.Location = new System.Drawing.Point(12, 72); this.CheatListView.Name = "CheatListView"; - this.CheatListView.SelectAllInProgress = false; - this.CheatListView.selectedItem = -1; this.CheatListView.Size = new System.Drawing.Size(414, 321); this.CheatListView.TabIndex = 1; - this.CheatListView.UseCompatibleStateImageBehavior = false; this.CheatListView.UseCustomBackground = true; - this.CheatListView.View = System.Windows.Forms.View.Details; - this.CheatListView.ColumnClick += new System.Windows.Forms.ColumnClickEventHandler(this.CheatListView_ColumnClick); + this.CheatListView.ColumnClick += new BizHawk.Client.EmuHawk.InputRoll.ColumnClickEventHandler(this.CheatListView_ColumnClick); this.CheatListView.SelectedIndexChanged += new System.EventHandler(this.CheatListView_SelectedIndexChanged); this.CheatListView.Click += new System.EventHandler(this.CheatListView_Click); this.CheatListView.DragDrop += new System.Windows.Forms.DragEventHandler(this.NewCheatForm_DragDrop); @@ -138,41 +118,6 @@ this.CheatListView.DoubleClick += new System.EventHandler(this.CheatListView_DoubleClick); this.CheatListView.KeyDown += new System.Windows.Forms.KeyEventHandler(this.CheatListView_KeyDown); // - // CheatName - // - this.CheatName.Text = "Name"; - this.CheatName.Width = 104; - // - // Address - // - this.Address.Text = "Address"; - this.Address.Width = 52; - // - // Value - // - this.Value.Text = "Value"; - this.Value.Width = 40; - // - // Compare - // - this.Compare.Text = "Compare"; - // - // ComparisonType - // - this.ComparisonType.Text = "Comparison Type"; - this.ComparisonType.Width = 194; - // - // On - // - this.On.Text = "On"; - this.On.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; - this.On.Width = 40; - // - // Domain - // - this.Domain.Text = "Domain"; - this.Domain.Width = 75; - // // CheatsContextMenu // this.CheatsContextMenu.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { @@ -403,6 +348,8 @@ // this.DisableAllCheatsMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.Stop; this.DisableAllCheatsMenuItem.Name = "DisableAllCheatsMenuItem"; + this.DisableAllCheatsMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Back))); + this.DisableAllCheatsMenuItem.ShortcutKeyDisplayString = "Ctrl + Backspace"; this.DisableAllCheatsMenuItem.Size = new System.Drawing.Size(233, 22); this.DisableAllCheatsMenuItem.Text = "Disable all"; this.DisableAllCheatsMenuItem.Click += new System.EventHandler(this.DisableAllCheatsMenuItem_Click); @@ -693,14 +640,7 @@ #endregion - private VirtualListView CheatListView; - private System.Windows.Forms.ColumnHeader CheatName; - private System.Windows.Forms.ColumnHeader Address; - private System.Windows.Forms.ColumnHeader Value; - private System.Windows.Forms.ColumnHeader ComparisonType; - private System.Windows.Forms.ColumnHeader Compare; - private System.Windows.Forms.ColumnHeader On; - private System.Windows.Forms.ColumnHeader Domain; + private InputRoll CheatListView; private MenuStripEx CheatsMenu; private System.Windows.Forms.ToolStripMenuItem FileSubMenu; private System.Windows.Forms.ToolStripMenuItem NewMenuItem; diff --git a/BizHawk.Client.EmuHawk/tools/Cheats/Cheats.cs b/BizHawk.Client.EmuHawk/tools/Cheats/Cheats.cs index cbc8cd2efe..9fff2eadc5 100644 --- a/BizHawk.Client.EmuHawk/tools/Cheats/Cheats.cs +++ b/BizHawk.Client.EmuHawk/tools/Cheats/Cheats.cs @@ -43,7 +43,6 @@ namespace BizHawk.Client.EmuHawk CheatListView.QueryItemText += CheatListView_QueryItemText; CheatListView.QueryItemBkColor += CheatListView_QueryItemBkColor; - CheatListView.VirtualMode = true; _sortedColumn = ""; _sortReverse = false; @@ -80,7 +79,7 @@ namespace BizHawk.Client.EmuHawk /// public void UpdateDialog() { - CheatListView.ItemCount = Global.CheatList.Count; + CheatListView.RowCount = Global.CheatList.Count; TotalLabel.Text = $"{Global.CheatList.CheatCount} {(Global.CheatList.CheatCount == 1 ? "cheat" : "cheats")} {Global.CheatList.ActiveCount} active"; } @@ -150,21 +149,36 @@ namespace BizHawk.Client.EmuHawk private void Cheats_Load(object sender, EventArgs e) { + // Hack for previous config settings + if (Settings.Columns.Any(c => string.IsNullOrWhiteSpace(c.Text))) + { + Settings = new CheatsSettings(); + } + TopMost = Settings.TopMost; CheatEditor.MemoryDomains = Core; LoadConfigSettings(); + CheatsMenu.Items.Add(CheatListView.ToColumnsMenu(ColumnToggleCallback)); ToggleGameGenieButton(); CheatEditor.SetAddEvent(AddCheat); CheatEditor.SetEditEvent(EditCheat); UpdateDialog(); + } - CheatsMenu.Items.Add(Settings.Columns.GenerateColumnsMenu(ColumnToggleCallback)); + private void SetColumns() + { + foreach (var column in Settings.Columns) + { + if (CheatListView.AllColumns[column.Name] == null) + { + CheatListView.AllColumns.Add(column); + } + } } private void ColumnToggleCallback() { - SaveColumnInfo(CheatListView, Settings.Columns); - LoadColumnInfo(CheatListView, Settings.Columns); + Settings.Columns = CheatListView.AllColumns; } private void ToggleGameGenieButton() @@ -195,7 +209,7 @@ namespace BizHawk.Client.EmuHawk private void SaveConfigSettings() { - SaveColumnInfo(CheatListView, Settings.Columns); + Settings.Columns =CheatListView.AllColumns; if (WindowState == FormWindowState.Normal) { @@ -221,10 +235,11 @@ namespace BizHawk.Client.EmuHawk Size = Settings.WindowSize; } - LoadColumnInfo(CheatListView, Settings.Columns); + CheatListView.AllColumns.Clear(); + SetColumns(); } - private void CheatListView_QueryItemText(int index, int column, out string text) + private void CheatListView_QueryItemText(int index, RollColumn column, out string text, ref int offsetX, ref int offsetY) { text = ""; if (index >= Global.CheatList.Count || Global.CheatList[index].IsSeparator) @@ -232,7 +247,7 @@ namespace BizHawk.Client.EmuHawk return; } - var columnName = CheatListView.Columns[column].Name; + var columnName = column.Name; switch (columnName) { @@ -296,7 +311,7 @@ namespace BizHawk.Client.EmuHawk } } - private void CheatListView_QueryItemBkColor(int index, int column, ref Color color) + private void CheatListView_QueryItemBkColor(int index, RollColumn column, ref Color color) { if (index < Global.CheatList.Count) { @@ -311,7 +326,7 @@ namespace BizHawk.Client.EmuHawk } } - private IEnumerable SelectedIndices => CheatListView.SelectedIndices.Cast(); + private IEnumerable SelectedIndices => CheatListView.SelectedRows; private IEnumerable SelectedItems { @@ -325,19 +340,16 @@ namespace BizHawk.Client.EmuHawk private void DoSelectedIndexChange() { - if (!CheatListView.SelectAllInProgress) + if (SelectedCheats.Any()) { - if (SelectedCheats.Any()) - { - var cheat = SelectedCheats.First(); - CheatEditor.SetCheat(cheat); - CheatGroupBox.Text = $"Editing Cheat {cheat.Name} - {cheat.AddressStr}"; - } - else - { - CheatEditor.ClearForm(); - CheatGroupBox.Text = "New Cheat"; - } + var cheat = SelectedCheats.First(); + CheatEditor.SetCheat(cheat); + CheatGroupBox.Text = $"Editing Cheat {cheat.Name} - {cheat.AddressStr}"; + } + else + { + CheatEditor.ClearForm(); + CheatGroupBox.Text = "New Cheat"; } } @@ -434,7 +446,8 @@ namespace BizHawk.Client.EmuHawk ToggleMenuItem.Enabled = SelectedIndices.Any(); - DisableAllCheatsMenuItem.Enabled = Global.CheatList.ActiveCount > 0; + // Always leave enabled even if no cheats enabled. This way the hotkey will always work however a new cheat is enabled + // DisableAllCheatsMenuItem.Enabled = Global.CheatList.ActiveCount > 0; GameGenieSeparator.Visible = OpenGameGenieEncoderDecoderMenuItem.Visible = @@ -451,7 +464,7 @@ namespace BizHawk.Client.EmuHawk Global.CheatList.Remove(item); } - CheatListView.SelectedIndices.Clear(); + CheatListView.DeselectAll(); UpdateDialog(); } } @@ -486,12 +499,12 @@ namespace BizHawk.Client.EmuHawk Global.CheatList.Insert(index - 1, cheat); } - var newindices = indices.Select(t => t - 1).ToList(); + var newIndices = indices.Select(t => t - 1); - CheatListView.SelectedIndices.Clear(); - foreach (var newi in newindices) + CheatListView.DeselectAll(); + foreach (var index in newIndices) { - CheatListView.SelectItem(newi, true); + CheatListView.SelectRow(index, true); } UpdateMessageLabel(); @@ -515,12 +528,12 @@ namespace BizHawk.Client.EmuHawk UpdateMessageLabel(); - var newindices = indices.Select(t => t + 1).ToList(); + var newIndices = indices.Select(t => t + 1); - CheatListView.SelectedIndices.Clear(); - foreach (var newi in newindices) + CheatListView.DeselectAll(); + foreach (var index in newIndices) { - CheatListView.SelectItem(newi, true); + CheatListView.SelectRow(index, true); } UpdateDialog(); @@ -533,12 +546,15 @@ namespace BizHawk.Client.EmuHawk private void ToggleMenuItem_Click(object sender, EventArgs e) { - SelectedCheats.ToList().ForEach(x => x.Toggle()); + foreach (var x in SelectedCheats) + { + x.Toggle(); + } CheatListView.Refresh(); } private void DisableAllCheatsMenuItem_Click(object sender, EventArgs e) - { + { Global.CheatList.DisableAll(); } @@ -608,14 +624,15 @@ namespace BizHawk.Client.EmuHawk .OfType() .First(x => x.Name == "GeneratedColumnsSubMenu")); - CheatsMenu.Items.Add(Settings.Columns.GenerateColumnsMenu(ColumnToggleCallback)); + CheatsMenu.Items.Add(CheatListView.ToColumnsMenu(ColumnToggleCallback)); Global.Config.DisableCheatsOnLoad = false; Global.Config.LoadCheatFileByGame = true; Global.Config.CheatsAutoSaveOnClose = true; RefreshFloatingWindowControl(Settings.FloatingWindow); - LoadColumnInfo(CheatListView, Settings.Columns); + CheatListView.AllColumns.Clear(); + SetColumns(); } #endregion @@ -648,9 +665,9 @@ namespace BizHawk.Client.EmuHawk DoSelectedIndexChange(); } - private void CheatListView_ColumnClick(object sender, ColumnClickEventArgs e) + private void CheatListView_ColumnClick(object sender, InputRoll.ColumnClickEventArgs e) { - var column = CheatListView.Columns[e.Column]; + var column = e.Column; if (column.Name != _sortedColumn) { _sortReverse = false; @@ -720,22 +737,21 @@ namespace BizHawk.Client.EmuHawk { public CheatsSettings() { - Columns = new ColumnList + Columns = new List { - new Column { Name = NameColumn, Visible = true, Index = 0, Width = 128 }, - new Column { Name = AddressColumn, Visible = true, Index = 1, Width = 60 }, - new Column { Name = ValueColumn, Visible = true, Index = 2, Width = 59 }, - new Column { Name = CompareColumn, Visible = true, Index = 3, Width = 59 }, - new Column { Name = ComparisonTypeColumn, Visible = true, Index = 4, Width = 60 }, - new Column { Name = OnColumn, Visible = false, Index = 5, Width = 28 }, - new Column { Name = DomainColumn, Visible = true, Index = 6, Width = 55 }, - new Column { Name = SizeColumn, Visible = true, Index = 7, Width = 55 }, - new Column { Name = EndianColumn, Visible = false, Index = 8, Width = 55 }, - new Column { Name = TypeColumn, Visible = false, Index = 9, Width = 55 } + new RollColumn { Text = "Names", Name = NameColumn, Visible = true, Width = 128, Type = ColumnType.Text }, + new RollColumn { Text = "Address", Name = AddressColumn, Visible = true, Width = 60, Type = ColumnType.Text }, + new RollColumn { Text = "Value", Name = ValueColumn, Visible = true, Width = 59, Type = ColumnType.Text }, + new RollColumn { Text = "Compare", Name = CompareColumn, Visible = true, Width = 63, Type = ColumnType.Text }, + new RollColumn { Text = "Compare Type", Name = ComparisonTypeColumn, Visible = true, Width = 98, Type = ColumnType.Text }, + new RollColumn { Text = "On", Name = OnColumn, Visible = false, Width = 28, Type = ColumnType.Text }, + new RollColumn { Text = "Size", Name = SizeColumn, Visible = true, Width = 55, Type = ColumnType.Text }, + new RollColumn { Text = "Endian", Name = EndianColumn, Visible = false, Width = 55, Type = ColumnType.Text }, + new RollColumn { Text = "Display Type", Name = TypeColumn, Visible = false, Width = 88, Type = ColumnType.Text } }; } - public ColumnList Columns { get; set; } + public List Columns { get; set; } } } } diff --git a/BizHawk.Client.EmuHawk/tools/Debugger/BreakpointControl.Designer.cs b/BizHawk.Client.EmuHawk/tools/Debugger/BreakpointControl.Designer.cs index a30300fc04..7ea0308c42 100644 --- a/BizHawk.Client.EmuHawk/tools/Debugger/BreakpointControl.Designer.cs +++ b/BizHawk.Client.EmuHawk/tools/Debugger/BreakpointControl.Designer.cs @@ -36,7 +36,7 @@ this.RemoveBreakpointButton = new System.Windows.Forms.Button(); this.DuplicateBreakpointButton = new System.Windows.Forms.Button(); this.EditBreakpointButton = new System.Windows.Forms.Button(); - this.BreakpointView = new BizHawk.Client.EmuHawk.VirtualListView(); + this.BreakpointView = new System.Windows.Forms.ListView(); this.columnHeader1 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); this.columnHeader2 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); this.columnHeader3 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); @@ -118,7 +118,6 @@ this.BreakpointView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); - this.BreakpointView.BlazingFast = false; this.BreakpointView.CheckBoxes = true; this.BreakpointView.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { this.columnHeader1, @@ -129,16 +128,13 @@ this.BreakpointView.FullRowSelect = true; this.BreakpointView.GridLines = true; this.BreakpointView.HideSelection = false; - this.BreakpointView.ItemCount = 0; + this.BreakpointView.VirtualListSize = 0; this.BreakpointView.Location = new System.Drawing.Point(0, 19); this.BreakpointView.Name = "BreakpointView"; - this.BreakpointView.SelectAllInProgress = false; - this.BreakpointView.selectedItem = -1; this.BreakpointView.Size = new System.Drawing.Size(366, 365); this.BreakpointView.TabIndex = 5; this.BreakpointView.TabStop = false; this.BreakpointView.UseCompatibleStateImageBehavior = false; - this.BreakpointView.UseCustomBackground = true; this.BreakpointView.View = System.Windows.Forms.View.Details; this.BreakpointView.ItemActivate += new System.EventHandler(this.BreakpointView_ItemActivate); this.BreakpointView.SelectedIndexChanged += new System.EventHandler(this.BreakpointView_SelectedIndexChanged); @@ -184,7 +180,7 @@ #endregion - private VirtualListView BreakpointView; + private System.Windows.Forms.ListView BreakpointView; public System.Windows.Forms.ColumnHeader columnHeader1; private System.Windows.Forms.ColumnHeader columnHeader2; private System.Windows.Forms.Button AddBreakpointButton; diff --git a/BizHawk.Client.EmuHawk/tools/Debugger/BreakpointControl.cs b/BizHawk.Client.EmuHawk/tools/Debugger/BreakpointControl.cs index 5d8dfc5bc9..9594007e9d 100644 --- a/BizHawk.Client.EmuHawk/tools/Debugger/BreakpointControl.cs +++ b/BizHawk.Client.EmuHawk/tools/Debugger/BreakpointControl.cs @@ -22,8 +22,7 @@ namespace BizHawk.Client.EmuHawk public BreakpointControl() { InitializeComponent(); - BreakpointView.QueryItemText += BreakPointView_QueryItemText; - BreakpointView.QueryItemBkColor += BreakPointView_QueryItemBkColor; + BreakpointView.RetrieveVirtualItem += BreakPointView_QueryItemText; BreakpointView.VirtualMode = true; _breakpoints.Callback = BreakpointCallback; } @@ -33,30 +32,16 @@ namespace BizHawk.Client.EmuHawk UpdateStatsLabel(); } - private void BreakPointView_QueryItemText(int index, int column, out string text) + private void BreakPointView_QueryItemText(object sender, RetrieveVirtualItemEventArgs e) { - text = ""; - switch (column) - { - case 0: - text = $"{_breakpoints[index].Address:X}"; - break; - case 1: - text = $"{_breakpoints[index].AddressMask:X}"; - break; - case 2: - text = _breakpoints[index].Type.ToString(); - break; - case 3: - text = _breakpoints[index].Name; - break; - } - } + var entry = _breakpoints[e.ItemIndex]; + e.Item = new ListViewItem($"{entry.Address:X}"); + e.Item.SubItems.Add($"{entry.AddressMask:X}"); + e.Item.SubItems.Add(entry.Type.ToString()); + e.Item.SubItems.Add(entry.Name); - private void BreakPointView_QueryItemBkColor(int index, int column, ref Color color) - { - color = _breakpoints[index].ReadOnly ? SystemColors.Control - : _breakpoints[index].Active ? Color.LightCyan + e.Item.BackColor = entry.ReadOnly ? SystemColors.Control + : entry.Active ? Color.LightCyan : Color.White; } @@ -90,7 +75,7 @@ namespace BizHawk.Client.EmuHawk { CheckForNewBreakpoints(); - BreakpointView.ItemCount = _breakpoints.Count; + BreakpointView.VirtualListSize = _breakpoints.Count; UpdateStatsLabel(); } } @@ -124,7 +109,7 @@ namespace BizHawk.Client.EmuHawk _breakpoints.Add(new Breakpoint(Core, callback)); } - BreakpointView.ItemCount = _breakpoints.Count; + BreakpointView.VirtualListSize = _breakpoints.Count; BreakpointView.Refresh(); UpdateBreakpointRemoveButton(); UpdateStatsLabel(); @@ -146,7 +131,7 @@ namespace BizHawk.Client.EmuHawk { _breakpoints.Add(Core, MemoryDomains.SystemBus.Name, address, mask, type); - BreakpointView.ItemCount = _breakpoints.Count; + BreakpointView.VirtualListSize = _breakpoints.Count; UpdateBreakpointRemoveButton(); UpdateStatsLabel(); } @@ -160,7 +145,7 @@ namespace BizHawk.Client.EmuHawk _breakpoints.Add(Core, MemoryDomains.SystemBus.Name, b.Address, b.AddressMask, b.BreakType); } - BreakpointView.ItemCount = _breakpoints.Count; + BreakpointView.VirtualListSize = _breakpoints.Count; UpdateBreakpointRemoveButton(); UpdateStatsLabel(); } @@ -208,7 +193,7 @@ namespace BizHawk.Client.EmuHawk _breakpoints.Remove(item); } - BreakpointView.ItemCount = _breakpoints.Count; + BreakpointView.VirtualListSize = _breakpoints.Count; UpdateBreakpointRemoveButton(); UpdateStatsLabel(); } @@ -243,7 +228,7 @@ namespace BizHawk.Client.EmuHawk item.Active ^= true; } - BreakpointView.ItemCount = _breakpoints.Count; + BreakpointView.VirtualListSize = _breakpoints.Count; UpdateBreakpointRemoveButton(); UpdateStatsLabel(); } @@ -270,7 +255,7 @@ namespace BizHawk.Client.EmuHawk item.Active ^= true; } - BreakpointView.ItemCount = _breakpoints.Count; + BreakpointView.VirtualListSize = _breakpoints.Count; UpdateStatsLabel(); } @@ -288,7 +273,7 @@ namespace BizHawk.Client.EmuHawk } } - BreakpointView.ItemCount = _breakpoints.Count; + BreakpointView.VirtualListSize = _breakpoints.Count; UpdateBreakpointRemoveButton(); UpdateStatsLabel(); } @@ -310,7 +295,7 @@ namespace BizHawk.Client.EmuHawk } } - BreakpointView.ItemCount = _breakpoints.Count; + BreakpointView.VirtualListSize = _breakpoints.Count; UpdateBreakpointRemoveButton(); UpdateStatsLabel(); } diff --git a/BizHawk.Client.EmuHawk/tools/Debugger/GenericDebugger.Designer.cs b/BizHawk.Client.EmuHawk/tools/Debugger/GenericDebugger.Designer.cs index ff6dc13a11..2eaa8ea454 100644 --- a/BizHawk.Client.EmuHawk/tools/Debugger/GenericDebugger.Designer.cs +++ b/BizHawk.Client.EmuHawk/tools/Debugger/GenericDebugger.Designer.cs @@ -46,9 +46,7 @@ this.DisassemblerBox = new System.Windows.Forms.GroupBox(); this.ToPCBtn = new System.Windows.Forms.Button(); this.label1 = new System.Windows.Forms.Label(); - this.DisassemblerView = new BizHawk.Client.EmuHawk.VirtualListView(); - this.Address = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); - this.Instruction = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.DisassemblerView = new InputRoll(); this.DisassemblerContextMenu = new System.Windows.Forms.ContextMenuStrip(this.components); this.AddBreakpointContextMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.StepOutBtn = new System.Windows.Forms.Button(); @@ -239,39 +237,21 @@ this.DisassemblerView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); - this.DisassemblerView.BlazingFast = false; - this.DisassemblerView.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { - this.Address, - this.Instruction}); + this.DisassemblerView.AllowColumnReorder = false; + this.DisassemblerView.AllowColumnResize = true; this.DisassemblerView.ContextMenuStrip = this.DisassemblerContextMenu; this.DisassemblerView.Font = new System.Drawing.Font("Courier New", 8F); this.DisassemblerView.FullRowSelect = true; this.DisassemblerView.GridLines = true; - this.DisassemblerView.HideSelection = false; - this.DisassemblerView.ItemCount = 0; + this.DisassemblerView.RowCount = 0; this.DisassemblerView.Location = new System.Drawing.Point(6, 39); this.DisassemblerView.Name = "DisassemblerView"; - this.DisassemblerView.SelectAllInProgress = false; - this.DisassemblerView.selectedItem = -1; this.DisassemblerView.Size = new System.Drawing.Size(395, 476); this.DisassemblerView.TabIndex = 1; - this.DisassemblerView.UseCompatibleStateImageBehavior = false; this.DisassemblerView.UseCustomBackground = true; - this.DisassemblerView.View = System.Windows.Forms.View.Details; - this.DisassemblerView.Scroll += new System.Windows.Forms.ScrollEventHandler(this.DisassemblerView_Scroll); + this.DisassemblerView.RowScroll += new InputRoll.RowScrollEvent(this.DisassemblerView_Scroll); this.DisassemblerView.SizeChanged += new System.EventHandler(this.DisassemblerView_SizeChanged); this.DisassemblerView.KeyDown += new System.Windows.Forms.KeyEventHandler(this.DisassemblerView_KeyDown); - this.DisassemblerView.MouseWheel += new System.Windows.Forms.MouseEventHandler(this.DisassemblerView_Wheel); - // - // Address - // - this.Address.Text = "Address"; - this.Address.Width = 94; - // - // Instruction - // - this.Instruction.Text = "Instruction"; - this.Instruction.Width = 291; // // DisassemblerContextMenu // @@ -412,9 +392,7 @@ private System.Windows.Forms.GroupBox BreakpointsGroupBox; private BreakpointControl BreakPointControl1; private System.Windows.Forms.GroupBox DisassemblerBox; - private VirtualListView DisassemblerView; - private System.Windows.Forms.ColumnHeader Address; - private System.Windows.Forms.ColumnHeader Instruction; + private InputRoll DisassemblerView; private System.Windows.Forms.Label label1; private System.Windows.Forms.Button StepOutBtn; private System.Windows.Forms.Button StepIntoBtn; diff --git a/BizHawk.Client.EmuHawk/tools/Debugger/GenericDebugger.Disassembler.cs b/BizHawk.Client.EmuHawk/tools/Debugger/GenericDebugger.Disassembler.cs index df9b7328aa..c86f93f188 100644 --- a/BizHawk.Client.EmuHawk/tools/Debugger/GenericDebugger.Disassembler.cs +++ b/BizHawk.Client.EmuHawk/tools/Debugger/GenericDebugger.Disassembler.cs @@ -43,16 +43,14 @@ namespace BizHawk.Client.EmuHawk { if (CanDisassemble) { - DisassemblerView.BlazingFast = true; Disassemble(); SetDisassemblerItemCount(); - DisassemblerView.BlazingFast = false; } } private void Disassemble() { - int lineCount = DisassemblerView.NumberOfVisibleRows; + int lineCount = DisassemblerView.RowCount + 2; _disassemblyLines.Clear(); uint a = _currentDisassemblerAddress; @@ -69,24 +67,24 @@ namespace BizHawk.Client.EmuHawk } } - private void DisassemblerView_QueryItemText(int index, int column, out string text) + private void DisassemblerView_QueryItemText(int index, RollColumn column, out string text, ref int offsetX, ref int offsetY) { text = ""; if (index < _disassemblyLines.Count) { - if (column == 0) + if (column.Name == AddressColumnName) { text = _disassemblyLines[index].Address.ToHexString(_pcRegisterSize); } - else if (column == 1) + else if (column.Name == InstructionColumnName) { text = _disassemblyLines[index].Mnemonic; } } } - private void DisassemblerView_QueryItemBkColor(int index, int column, ref Color color) + private void DisassemblerView_QueryItemBkColor(int index, RollColumn column, ref Color color) { if (_disassemblyLines.Any() && index < _disassemblyLines.Count) { @@ -97,9 +95,16 @@ namespace BizHawk.Client.EmuHawk } } + private void DecrementCurrentAddress() { + if (_currentDisassemblerAddress == 0) + { + return; + } + uint newaddress = _currentDisassemblerAddress; + while (true) { int bytestoadvance; @@ -137,51 +142,44 @@ namespace BizHawk.Client.EmuHawk } } - private void DisassemblerView_Scroll(object sender, ScrollEventArgs e) + + private bool _blockScroll; + private void DisassemblerView_Scroll(object sender, EventArgs e) { - if (e.Type == ScrollEventType.SmallIncrement) + // This is really really gross, but it works + if (_blockScroll) { - SmallIncrement(); + return; } - if (e.Type == ScrollEventType.SmallDecrement) + var scrollBar = sender as ScrollBar; + if (scrollBar != null) { - SmallDecrement(); - } - } + if (scrollBar.Value > 0) + { + SmallIncrement(); - private void DisassemblerView_Wheel(object sender, MouseEventArgs e) - { - if (e.Delta > 0) - { - SmallDecrement(); - } - if (e.Delta > 120) - { - SmallDecrement(); - } - if (e.Delta > 240) - { - SmallDecrement(); - } + _blockScroll = true; + scrollBar.Value = 14; + _blockScroll = false; + } + else + { + SmallDecrement(); - if (e.Delta < 0) - { - SmallIncrement(); - } - if (e.Delta < -120) - { - SmallIncrement(); - } - if (e.Delta < -240) - { - SmallIncrement(); + if (_currentDisassemblerAddress != 0) + { + _blockScroll = true; + scrollBar.Value = 14; + _blockScroll = false; + } + } } } private void SetDisassemblerItemCount() { - DisassemblerView.ItemCount = DisassemblerView.NumberOfVisibleRows + 1; + DisassemblerView.RowCount = DisassemblerView.VisibleRows + 2; } private void DisassemblerView_SizeChanged(object sender, EventArgs e) @@ -225,7 +223,7 @@ namespace BizHawk.Client.EmuHawk private void CopySelectedDisassembler() { - var indices = DisassemblerView.SelectedIndices; + var indices = DisassemblerView.SelectedRows.ToList(); if (indices.Count > 0) { @@ -256,12 +254,12 @@ namespace BizHawk.Client.EmuHawk private void DisassemblerContextMenu_Opening(object sender, EventArgs e) { - AddBreakpointContextMenuItem.Enabled = DisassemblerView.SelectedIndices.Count > 0; + AddBreakpointContextMenuItem.Enabled = DisassemblerView.SelectedRows.Any(); } private void AddBreakpointContextMenuItem_Click(object sender, EventArgs e) { - var indices = DisassemblerView.SelectedIndices; + var indices = DisassemblerView.SelectedRows.ToList(); if (indices.Count > 0) { diff --git a/BizHawk.Client.EmuHawk/tools/Debugger/GenericDebugger.cs b/BizHawk.Client.EmuHawk/tools/Debugger/GenericDebugger.cs index e15f973653..4f180134ff 100644 --- a/BizHawk.Client.EmuHawk/tools/Debugger/GenericDebugger.cs +++ b/BizHawk.Client.EmuHawk/tools/Debugger/GenericDebugger.cs @@ -10,6 +10,9 @@ namespace BizHawk.Client.EmuHawk { public partial class GenericDebugger : Form, IToolFormAutoConfig, IControlMainform { + private const string AddressColumnName = "Address"; + private const string InstructionColumnName = "Instruction"; + public GenericDebugger() { InitializeComponent(); @@ -17,7 +20,24 @@ namespace BizHawk.Client.EmuHawk DisassemblerView.QueryItemText += DisassemblerView_QueryItemText; DisassemblerView.QueryItemBkColor += DisassemblerView_QueryItemBkColor; - DisassemblerView.VirtualMode = true; + DisassemblerView.AllColumns.Clear(); + DisassemblerView.AllColumns.AddRange(new[] + { + new RollColumn + { + Name = AddressColumnName, + Text = AddressColumnName, + Width = 94, + Type = ColumnType.Text + }, + new RollColumn + { + Name = InstructionColumnName, + Text = InstructionColumnName, + Width = 291, + Type = ColumnType.Text + } + }); } private void GenericDebugger_Load(object sender, EventArgs e) @@ -75,7 +95,7 @@ namespace BizHawk.Client.EmuHawk else { DisassemblerBox.Enabled = false; - DisassemblerView.ItemCount = 0; + DisassemblerView.RowCount = 0; DisassemblerBox.Controls.Add(new Label { Location = new Point(UIHelper.ScaleX(35), UIHelper.ScaleY(23)), diff --git a/BizHawk.Client.EmuHawk/tools/Debugger/RegisterBoxControl.cs b/BizHawk.Client.EmuHawk/tools/Debugger/RegisterBoxControl.cs index 9f6d273e8f..83dba6a59b 100644 --- a/BizHawk.Client.EmuHawk/tools/Debugger/RegisterBoxControl.cs +++ b/BizHawk.Client.EmuHawk/tools/Debugger/RegisterBoxControl.cs @@ -41,46 +41,37 @@ namespace BizHawk.Client.EmuHawk { if (Controls.OfType().Any(p => p.Name == "FlagPanel")) { - Controls - .OfType() + foreach (var checkbox in Controls.OfType() .First(p => p.Name == "FlagPanel") .Controls - .OfType() - .ToList() - .ForEach(checkbox => + .OfType()) + { + if (checkbox.Name == register.Key) { - if (checkbox.Name == register.Key) - { - checkbox.Checked = register.Value.Value == 1; - } - }); + checkbox.Checked = register.Value.Value == 1; + } + } } if (_canSetCpuRegisters) { - Controls - .OfType() - .ToList() - .ForEach(textbox => + foreach (var textbox in Controls.OfType()) + { + if (textbox.Name == register.Key) { - if (textbox.Name == register.Key) - { - textbox.Text = register.Value.Value.ToHexString(register.Value.BitSize / 4); - } - }); + textbox.Text = register.Value.Value.ToHexString(register.Value.BitSize / 4); + } + } } else { - Controls - .OfType