diff --git a/Assets/gamedb/gamedb_a7800.txt b/Assets/gamedb/gamedb_a7800.txt index 5515b75bdc..19214c873a 100644 --- a/Assets/gamedb/gamedb_a7800.txt +++ b/Assets/gamedb/gamedb_a7800.txt @@ -1,39 +1,49 @@ ;;NOTE: These hashes were generated using trimmed ROM headers +;0 = normal cart (no banking or pokey or RAM) +;1 = Super Game mapper (standard mapper) +;2 = Super Game with extra ROM +;3 = F-18 Hornet Mapper +;4 = Double Dragon and Rampage + +md5:91041AADD1700A7A4076F4005F2C362F Diagnostics A78 NTSC=true;board=0 +md5:89E7B20E7E0C629D00C6CA68949A216F Test Rom A78 NTSC=true;board=0 md5:4332c24e4f3bc72e7fe1b77adf66c2b7 3D Asteroids A78 NTSC=true;board=0 -md5:0be996d25144966d5541c9eb4919b289 Ace of Aces A78 NTSC=true;board=A78SG -md5:aadde920b3aaba03bc10b40bd0619c94 Ace of Aces A78 PAL=true;board=A78SG -md5:877dcc97a775ed55081864b2dbf5f1e2 Alien Brigade A78 NTSC=true;board=A78S9 -md5:de3e9496cb7341f865f27e5a72c7f2f5 Alien Brigade A78 PAL=true;board=A78S9 -md5:0a9e58ef5eb9ff93246e0fff684dc7f1 Arkanoid (0911) A78 NTSC=true;board=A7832P +md5:A0285769753B18C407CB6E818B7DCAD2 3D Asteroids A78 NTSC=true;board=0 +md5:0be996d25144966d5541c9eb4919b289 Ace of Aces A78 NTSC=true;board=1 +md5:aadde920b3aaba03bc10b40bd0619c94 Ace of Aces A78 PAL=true;board=1 +md5:877dcc97a775ed55081864b2dbf5f1e2 Alien Brigade A78 NTSC=true;board=2 +md5:de3e9496cb7341f865f27e5a72c7f2f5 Alien Brigade A78 PAL=true;board=2 +md5:0a9e58ef5eb9ff93246e0fff684dc7f1 Arkanoid (0911) A78 NTSC=true;board=0;Pokey=true md5:f9fb84658c5586df159a0c75cc46b54c Asteroids Deluxe A78 NTSC=true;board=0 -md5:a65f79ad4a0bbdecd59d5f7eb3623fd7 Asteroids Deluxe A78 NTSC=true;board=A7832 -md5:1baf41de200f26ec643625021290bec2 Asteroids Deluxe A78 PAL=true;board=A7832 +md5:a65f79ad4a0bbdecd59d5f7eb3623fd7 Asteroids Deluxe A78 NTSC=true;board=0 +md5:1baf41de200f26ec643625021290bec2 Asteroids Deluxe A78 PAL=true;board=0 md5:07342c78619ba6ffcc61c10e907e3b50 Asteroids A78 NTSC=true;board=0 -md5:8fc3a695eaea3984912d98ed4a543376 Ballblazer A78 NTSC=true;board=A7832P -md5:b558814d54904ce0582e2f6a801d03af Ballblazer A78 PAL=true;board=A7832P -md5:42682415906c21c6af80e4198403ffda Barnyard Blaster A78 NTSC=true;board=A78SG -md5:babe2bc2976688bafb8b23c192658126 Barnyard Blaster A78 PAL=true;board=A78SG -md5:f5f6b69c5eb4b55fc163158d1a6b423e Basketbrawl A78 NTSC=true;board=A78SG -md5:fba002089fcfa176454ab507e0eb76cb Basketbrawl A78 PAL=true;board=A78SG +md5:8fc3a695eaea3984912d98ed4a543376 Ballblazer A78 NTSC=true;board=0;Pokey=true +md5:b558814d54904ce0582e2f6a801d03af Ballblazer A78 PAL=true;board=0;Pokey=true +md5:42682415906c21c6af80e4198403ffda Barnyard Blaster A78 NTSC=true;board=1 +md5:babe2bc2976688bafb8b23c192658126 Barnyard Blaster A78 PAL=true;board=1 +md5:f5f6b69c5eb4b55fc163158d1a6b423e Basketbrawl A78 NTSC=true;board=1 +md5:fba002089fcfa176454ab507e0eb76cb Basketbrawl A78 PAL=true;board=1 md5:6010a398070dfacb4c0173d75d73c50a Beef Drop A78 NTSC=true;board=0 md5:c534db0a062225b17cfb8ecce0fb9090 Beef Drop A78 NTSC=true;board=0 -md5:6da5b1b9fa0001e3517f6084ff651b07 Bentley Bear - Crystal Quest A78 NTSC=true;board=A78S9 +md5:CE25D34071B2C798ACE4C8792EAE8E84 Beef Drop A78 NTSC=true;board=0 +md5:6da5b1b9fa0001e3517f6084ff651b07 Bentley Bear - Crystal Quest A78 NTSC=true;board=2 md5:5a09946e57dbe30408a8f253a28d07db Centipede A78 NTSC=true;board=0 md5:38c056a48472d9a9e16ebda5ed91dae7 Centipede A78 PAL=true;board=0 md5:93e4387864b014c155d7c17877990d1e Choplifter! A78 NTSC=true;board=0 md5:59d4edb0230b5acc918b94f6bc94779f Choplifter! A78 PAL=true;board=0 md5:441ac404cdc7bcbd4d787f911df7bf0d Color Test A78 NTSC=true;board=0 -md5:2e8e28f6ad8b9b9267d518d880c73ebb Commando A78 NTSC=true;board=A78SGP -md5:55da6c6c3974d013f517e725aa60f48e Commando A78 PAL=true;board=A78SGP -md5:db691469128d9a4217ec7e315930b646 Crack'ed A78 NTSC=true;board=A78SG -md5:7cbe78fa06f47ba6516a67a4b003c9ee Crack'ed A78 PAL=true;board=A78SG -md5:0c9b124355d5328697a3b9e0011353f2 Crazy Brix A78 NTSC=true;board=A7816 -md5:45e1d527becc96d1715e810d1c07ac27 Crazy Brix A78 NTSC=true;board=A7816 -md5:fc7db1a9243ce2140f716762b8352a5c Crazy Brix A78 PAL=true;board=A7816 -md5:a94e4560b6ad053a1c24e096f1262ebf Crossbow A78 NTSC=true;board=A78S9 -md5:63db371d67a98daec547b2abd5e7aa95 Crossbow A78 PAL=true;board=A78S9 -md5:179b76ff729d4849b8f66a502398acae CDark Chambers A78 NTSC=true;board=A78SG -md5:a2b8e2f159642c4b91de82e9a2928494 Dark Chambers A78 PAL=true;board=A78SG +md5:2e8e28f6ad8b9b9267d518d880c73ebb Commando A78 NTSC=true;board=1;Pokey=true +md5:55da6c6c3974d013f517e725aa60f48e Commando A78 PAL=true;board=1;Pokey=true +md5:db691469128d9a4217ec7e315930b646 Crack'ed A78 NTSC=true;board=1 +md5:7cbe78fa06f47ba6516a67a4b003c9ee Crack'ed A78 PAL=true;board=1 +md5:0c9b124355d5328697a3b9e0011353f2 Crazy Brix A78 NTSC=true;board=0 +md5:45e1d527becc96d1715e810d1c07ac27 Crazy Brix A78 NTSC=true;board=0 +md5:fc7db1a9243ce2140f716762b8352a5c Crazy Brix A78 PAL=true;board=0 +md5:a94e4560b6ad053a1c24e096f1262ebf Crossbow A78 NTSC=true;board=2 +md5:63db371d67a98daec547b2abd5e7aa95 Crossbow A78 PAL=true;board=2 +md5:179b76ff729d4849b8f66a502398acae CDark Chambers A78 NTSC=true;board=1 +md5:a2b8e2f159642c4b91de82e9a2928494 Dark Chambers A78 PAL=true;board=1 md5:95ac811c7d27af0032ba090f28c107bd Desert Falcon A78 NTSC=true;board=0 md5:2d5d99b993a885b063f9f22ce5e6523d Desert Falcon A78 PAL=true;board=0 md5:731879ea82fc0ca245e39e036fe293e6 Dig Dug A78 NTSC=true;board=0 @@ -42,16 +52,16 @@ md5:5e332fbfc1e0fc74223d2e73271ce650 Donkey Kong Junior A78 NTSC=true;board=0 md5:4dc5f88243250461bd61053b13777060 Donkey Kong Junior A78 PAL=true;board=0 md5:19f1ee292a23636bd57d408b62de79c7 Donkey Kong A78 NTSC=true;board=0 md5:8e96ef14ce9b5d84bcbc996b66d6d4c7 Donkey Kong A78 PAL=true;board=0 -md5:de2ebafcf0e37aaa9d0e9525a7f4dd62 Double Dragon A78 PAL=true;board=A78AC -md5:543484c00ba233736bcaba2da20eeea9 Double Dragon A78 NTSC=true;board=A78AC -md5:2251a6a0f3aec84cc0aff66fc9fa91e8 F-18 Hornet A78 NTSC=true;board=A78AB -md5:e7709da8e49d3767301947a0a0b9d2e6 F-18 Hornet A78 PAL=true;board=A78AB -md5:6287727ab36391a62f728bbdee88675c FailSafe A78 NTSC=true;board=A7848 -md5:d2bb22f704f1610a4c396c51f5188e15 FailSafe A78 NTSC=true;board=A7848 -md5:d25d5d19188e9f149977c49eb0367cd1 Fatal Run A78 NTSC=true;board=A78SG -md5:23505651ac2e47f3637152066c3aa62f Fatal Run A78 PAL=true;board=A78SG -md5:e80f24e953563e6b61556737d67d3836 Fight Night A78 PAL=true;board=A78SG -md5:07dbbfe612a0a28e283c01545e59f25e Fight Night A78 NTSC=true;board=A78SG +md5:de2ebafcf0e37aaa9d0e9525a7f4dd62 Double Dragon A78 PAL=true;board=4 +md5:543484c00ba233736bcaba2da20eeea9 Double Dragon A78 NTSC=true;board=4 +md5:2251a6a0f3aec84cc0aff66fc9fa91e8 F-18 Hornet A78 NTSC=true;board=3 +md5:e7709da8e49d3767301947a0a0b9d2e6 F-18 Hornet A78 PAL=true;board=3 +md5:6287727ab36391a62f728bbdee88675c FailSafe A78 NTSC=true;board=0 +md5:d2bb22f704f1610a4c396c51f5188e15 FailSafe A78 NTSC=true;board=0 +md5:d25d5d19188e9f149977c49eb0367cd1 Fatal Run A78 NTSC=true;board=1 +md5:23505651ac2e47f3637152066c3aa62f Fatal Run A78 PAL=true;board=1 +md5:e80f24e953563e6b61556737d67d3836 Fight Night A78 PAL=true;board=1 +md5:07dbbfe612a0a28e283c01545e59f25e Fight Night A78 NTSC=true;board=1 md5:cf76b00244105b8e03cdc37677ec1073 Food Fight A78 NTSC=true;board=0 md5:de0d4f5a9bf1c1bddee3ed2f7ec51209 Food Fight A78 PAL=true;board=0 md5:45136d1d9eddf0bebad32995647b3298 Frogger Demo A78 NTSC=true;board=0 @@ -60,97 +70,97 @@ md5:f5dc7dc8e38072d3d65bd90a660148ce Galaga A78 PAL=true;board=0 md5:06204dadc975be5e5e37e7cc66f984cf Gato A78 NTSC=true;board=0 md5:0baec96787ce17f390e204de1a136e59 Hat Trick A78 PAL=true;board=0 md5:fd9e78e201b6baafddfd3e1fbfe6ba31 Hat Trick A78 NTSC=true;board=0 -md5:c3672482ca93f70eafd9134b936c3feb Ikari Warriors A78 NTSC=true;board=A78SG -md5:8c2c2a1ea6e9a928a44c3151ba5c1ce3 Ikari Warriors A78 PAL=true;board=A78SG -md5:1745feadabb24e7cefc375904c73fa4c Impossible Mission Fixed A78 NTSC=true;board=A78SGR -md5:baebc9246c087e893dfa489632157180 Impossible Mission A78 NTSC=true;board=A78SGR -md5:80dead01ea2db5045f6f4443faa6fce8 Impossible Mission A78 PAL=true;board=A78SGR -md5:045fd12050b7f2b842d5970f2414e912 Jinks A78 NTSC=true;board=A78SGR -md5:dfb86f4d06f05ad00cf418f0a59a24f7 Jinks A78 PAL=true;board=A78SGR +md5:c3672482ca93f70eafd9134b936c3feb Ikari Warriors A78 NTSC=true;board=1 +md5:8c2c2a1ea6e9a928a44c3151ba5c1ce3 Ikari Warriors A78 PAL=true;board=1 +md5:1745feadabb24e7cefc375904c73fa4c Impossible Mission Fixed A78 NTSC=true;board=1;RAM=8 +md5:baebc9246c087e893dfa489632157180 Impossible Mission A78 NTSC=true;board=1;RAM=8 +md5:80dead01ea2db5045f6f4443faa6fce8 Impossible Mission A78 PAL=true;board=1;RAM=8 +md5:045fd12050b7f2b842d5970f2414e912 Jinks A78 NTSC=true;board=1;RAM=8 +md5:dfb86f4d06f05ad00cf418f0a59a24f7 Jinks A78 PAL=true;board=1;RAM=8 md5:f18b3b897a25ab3885b43b4bd141b396 Joust A78 NTSC=true;board=0 md5:f2dae0264a4b4a73762b9d7177e989f6 Joust A78 PAL=true;board=0 -md5:548ba2e54e4fc45ab84ed634d702c136 Jr. Ms. Pac-Man A78 NTSC=true;board=A7832P -md5:6bc2daeb48e28d103a4298a276e7e551 Jr. Pac-Man (Tunnels) A78 NTSC=true;board=A7832P -md5:0b3baf47886915dd2eec5da7671bfa63 Jr. Pac-Man A78 NTSC=true;board=A78SGR -md5:8281ab17fa3bfc0a6c497d6a4f350061 Jr. Pac-Man A78 NTSC=true;board=A78SGR -md5:17b3b764d33eae9b5260f01df7bb9d2f KLAX A78 NTSC=true;board=A78SG -md5:5e0a1e832bbcea6facb832fde23a440a Karateka A78 PAL=true;board=A78S4 +md5:548ba2e54e4fc45ab84ed634d702c136 Jr. Ms. Pac-Man A78 NTSC=true;board=0;Pokey=true +md5:6bc2daeb48e28d103a4298a276e7e551 Jr. Pac-Man (Tunnels) A78 NTSC=true;board=0;Pokey=true +md5:0b3baf47886915dd2eec5da7671bfa63 Jr. Pac-Man A78 NTSC=true;board=1;RAM=8 +md5:8281ab17fa3bfc0a6c497d6a4f350061 Jr. Pac-Man A78 NTSC=true;board=1;RAM=8 +md5:17b3b764d33eae9b5260f01df7bb9d2f KLAX A78 NTSC=true;board=1 +md5:5e0a1e832bbcea6facb832fde23a440a Karateka A78 PAL=true;board=1 md5:c3a5a8692a423d43d9d28dd5b7d109d9 Karateka A78 NTSC=true;board=0 md5:f57d0af323d4e173fb49ed447f0563d7 Kung-Fu Master A78 NTSC=true;board=0 md5:2931b75811ad03f3ac9330838f3d231b Kung-Fu Master A78 PAL=true;board=0 md5:431ca060201ee1f9eb49d44962874049 Mario Bros. A78 NTSC=true;board=0 md5:d2e861306be78e44248bb71d7475d8a3 Mario Bros. A78 PAL=true;board=0 -md5:37b5692e33a98115e574185fa8398c22 Mat Mania Challenge A78 NTSC=true;board=A78SG -md5:6819c37b96063b024898a19dbae2df54 Mat Mania Challenge A78 PAL=true;board=A78SG -md5:f2f5e5841e4dda89a2faf8933dc33ea6 Mean 18 Ultimate Golf A78 NTSC=true;board=A78SG -md5:2e9dbad6c0fa381a6cd1bb9abf98a104 Mean 18 Ultimate Golf A78 PAL=true;board=A78SG -md5:bedc30ec43587e0c98fc38c39c1ef9d0 Meltdown A78 NTSC=true;board=A78SG -md5:c80155d7eec9e3dcb79aa6b83c9ccd1e Meltdown A78 PAL=true;board=A78SG -md5:b02f93661f4b7e712810d2bf8e02ad79 Meteor Shower A78 NTSC=true;board=A7816 -md5:2f1f199ecc2b414d28e01f0de53ca8f7 Meteor Shower A78 PAL=true;board=A7816 -md5:bc1e905db1008493a9632aa83ab4682b Midnight Mutants A78 NTSC=true;board=A78SG -md5:6794ea31570eba0b88a0bf1ead3f3f1b Midnight Mutants A78 PAL=true;board=A78SG -md5:017066f522908081ec3ee624f5e4a8aa Missing in Action A78 NTSC=true;board=A78S9 -md5:d0f46bf92ed6e7b1cce63278420cae8a Missing in Action A78 NTSC=true;board=A78S9 -md5:9ff38ea62004201d870caa8bd9463525 Moon Cresta A78 NTSC=true;board=A7832 -md5:3bc8f554cf86f8132a623cc2201a564b Motor Psycho A78 NTSC=true;board=A78SG -md5:5330bfe428a6b601b7e76c2cfc4cd049 Motor Psycho A78 PAL=true;board=A78SG +md5:37b5692e33a98115e574185fa8398c22 Mat Mania Challenge A78 NTSC=true;board=1 +md5:6819c37b96063b024898a19dbae2df54 Mat Mania Challenge A78 PAL=true;board=1 +md5:f2f5e5841e4dda89a2faf8933dc33ea6 Mean 18 Ultimate Golf A78 NTSC=true;board=1 +md5:2e9dbad6c0fa381a6cd1bb9abf98a104 Mean 18 Ultimate Golf A78 PAL=true;board=1 +md5:bedc30ec43587e0c98fc38c39c1ef9d0 Meltdown A78 NTSC=true;board=1 +md5:c80155d7eec9e3dcb79aa6b83c9ccd1e Meltdown A78 PAL=true;board=1 +md5:b02f93661f4b7e712810d2bf8e02ad79 Meteor Shower A78 NTSC=true;board=0 +md5:2f1f199ecc2b414d28e01f0de53ca8f7 Meteor Shower A78 PAL=true;board=0 +md5:bc1e905db1008493a9632aa83ab4682b Midnight Mutants A78 NTSC=true;board=1 +md5:6794ea31570eba0b88a0bf1ead3f3f1b Midnight Mutants A78 PAL=true;board=1 +md5:017066f522908081ec3ee624f5e4a8aa Missing in Action A78 NTSC=true;board=2 +md5:d0f46bf92ed6e7b1cce63278420cae8a Missing in Action A78 NTSC=true;board=2 +md5:9ff38ea62004201d870caa8bd9463525 Moon Cresta A78 NTSC=true;board=0 +md5:3bc8f554cf86f8132a623cc2201a564b Motor Psycho A78 NTSC=true;board=1 +md5:5330bfe428a6b601b7e76c2cfc4cd049 Motor Psycho A78 PAL=true;board=1 md5:fc0ea52a9fac557251b65ee680d951e5 Ms. Pac-Man A78 NTSC=true;board=0 md5:56469e8c5ff8983c6cb8dadc64eb0363 Ms. Pac-Man A78 PAL=true;board=0 -md5:220121f771fc4b98cef97dc040e8d378 Ninja Golf A78 NTSC=true;board=A78SG -md5:ea0c859aa54fe5eaf4c1f327fab06221 Ninja Golf A78 PAL=true;board=A78SG +md5:220121f771fc4b98cef97dc040e8d378 Ninja Golf A78 NTSC=true;board=1 +md5:ea0c859aa54fe5eaf4c1f327fab06221 Ninja Golf A78 PAL=true;board=1 md5:74569571a208f8b0b1ccfb22d7c914e1 One on One Basketball A78 NTSC=true;board=0 md5:8dba0425f0262e5704581d8757a1a6e3 One on One Basketball A78 PAL=true;board=0 md5:5d7bc7092de69095137456733e7b685d Pac-Man Collection A78 NTSC=true;board=0 -md5:90223a8a363bdf643a19d0f97e63b1b2 PacArcade A78 NTSC=true;board=A7816 +md5:90223a8a363bdf643a19d0f97e63b1b2 PacArcade A78 NTSC=true;board=0 md5:386bded4a944bae455fedf56206dd1dd Pete Rose Baseball A78 PAL=true;board=0 md5:1a5207870dec6fae9111cb747e20d8e3 Pete Rose Baseball A78 NTSC=true;board=0 -md5:05f43244465943ce819780a71a5b572a Pitfighter A78 NTSC=true;board=A78S4 -md5:33aea1e2b6634a1dec8c7006d9afda22 Planet Smashers A78 NTSC=true;board=A78SG -md5:2837a8fd49b7fc7ccd70fd45b69c5099 Planet Smashers A78 PAL=true;board=A78SG -md5:86546808dc60961cdb1b20e761c50ab1 Plutos A78 NTSC=true;board=A78SGR +md5:05f43244465943ce819780a71a5b572a Pitfighter A78 NTSC=true;board=1 +md5:33aea1e2b6634a1dec8c7006d9afda22 Planet Smashers A78 NTSC=true;board=1 +md5:2837a8fd49b7fc7ccd70fd45b69c5099 Planet Smashers A78 PAL=true;board=1 +md5:86546808dc60961cdb1b20e761c50ab1 Plutos A78 NTSC=true;board=1;RAM=8 md5:584582bb09ee8122e7fc09dc7d1ed813 Pole Position II A78 NTSC=true;board=0 md5:865457e0e0f48253b08f77b9e18f93b2 Pole Position II A78 PAL=true;board=0 -md5:66e7230f7ef9d14db82d76b06b241bc0 Q-bert A78 NTSC=true;board=A7832 -md5:ac03806cef2558fc795a7d5d8dba7bc0 Rampage A78 NTSC=true;board=A78AC -md5:383ed9bd1efb9b6cb3388a777678c928 Realsports Baseball A78 NTSC=true;board=A78S4 -md5:8f7eb10ad0bd75474abf0c6c36c08486 Rescue on Fractalus A78 NTSC=true;board=A7832 -md5:43525a0405184875c2ecfd0196886a34 Rip Off A78 NTSC=true;board=A7816 -md5:106b409c6f4c219b1a3b3d099ead3b2b Rip Off A78 PAL=true;board=0A7816 -md5:505f05e7f161f62ccd749dab3c4a204b Robot Finds Kitten A78 NTSC=true;board=A7832 +md5:66e7230f7ef9d14db82d76b06b241bc0 Q-bert A78 NTSC=true;board=0 +md5:ac03806cef2558fc795a7d5d8dba7bc0 Rampage A78 NTSC=true;board=4 +md5:383ed9bd1efb9b6cb3388a777678c928 Realsports Baseball A78 NTSC=true;board=1 +md5:8f7eb10ad0bd75474abf0c6c36c08486 Rescue on Fractalus A78 NTSC=true;board=0 +md5:43525a0405184875c2ecfd0196886a34 Rip Off A78 NTSC=true;board=0 +md5:106b409c6f4c219b1a3b3d099ead3b2b Rip Off A78 PAL=true;board=0 +md5:505f05e7f161f62ccd749dab3c4a204b Robot Finds Kitten A78 NTSC=true;board=0 md5:66ecaafe1b82ae68ffc96267aaf7a4d7 Robotron 2084 A78 NTSC=true;board=0 -md5:ae85689b21bdf85cb9dc57c3b1fec9db Santa Simon A78 NTSC=true;board=A7848 +md5:ae85689b21bdf85cb9dc57c3b1fec9db Santa Simon A78 NTSC=true;board=0 md5:57651b6c8e62811fab0361cea537b79c Scramble A78 NTSC=true;board=0 md5:c265cfd65534a4514f226cb4c7f7d6bf Scramble A78 NTSC=true;board=0 md5:1ee26fc6b06b4c9ba74931914b7e719d Scramble A78 PAL=true;board=0 md5:65fe82f419f6583a0f9a736242cb303d Scramble A78 PAL=true;board=0 -md5:980c35ae9625773a450aa7ef51751c04 Scrapyard Dog A78 NTSC=true;board=A78SG -md5:53db322c201323fe2ca8f074c0a2bf86 Scrapyard Dog A78 PAL=true;board=A78SG -md5:b697d9c2d1b9f6cb21041286d1bbfa7f Sentinel A78 NTSC=true;board=A78SG -md5:5469b4de0608f23a5c4f98f331c9e75f Sentinel A78 PAL=true;board=A78SG -md5:2d643ac548c40e58c99d0fe433ba4ba0 Sirius A78 NTSC=true;board=A78SGR +md5:980c35ae9625773a450aa7ef51751c04 Scrapyard Dog A78 NTSC=true;board=1 +md5:53db322c201323fe2ca8f074c0a2bf86 Scrapyard Dog A78 PAL=true;board=1 +md5:b697d9c2d1b9f6cb21041286d1bbfa7f Sentinel A78 NTSC=true;board=1;Pokey=true +md5:5469b4de0608f23a5c4f98f331c9e75f Sentinel A78 PAL=true;board=1;Pokey=true +md5:2d643ac548c40e58c99d0fe433ba4ba0 Sirius A78 NTSC=true;board=1;RAM=8 md5:a84c1b2300fbfbf21b1c02387f613dad Space Duel A78 PAL=true;board=0 -md5:771cb4609347657f63e6f0eb26036e35 Space Duel A78 NTSC=true;board=A7832 +md5:771cb4609347657f63e6f0eb26036e35 Space Duel A78 NTSC=true;board=0 md5:6adf79558a3d7f5beca1bb8d34337417 Space Invaders A78 NTSC=true;board=0 -md5:cbb0746192540a13b4c7775c7ce2021f Summer Games A78 NTSC=true;board=A78SGR +md5:cbb0746192540a13b4c7775c7ce2021f Summer Games A78 NTSC=true;board=1;RAM=16 md5:cc18e3b37a507c4217eb6cb1de8c8538 Super Huey UH-IX A78 NTSC=true;board=0 md5:162f9c953f0657689cc74ab20b40280f Super Huey UH-IX A78 PAL=true;board=0 md5:59b5793bece1c80f77b55d60fb39cb94 Super Skateboardin' A78 NTSC=true;board=0 md5:95d7c321dce8f57623a9c5b4947bb375 Super Skateboardin' A78 PAL=true;board=0 -md5:5c4f752371a523f15e9980fea73b874d Tank Command A78 NTSC=true;board=A78S4 +md5:5c4f752371a523f15e9980fea73b874d Tank Command A78 NTSC=true;board=1 md5:3bb9c8d9adc912dd7f8471c97445cd8d Titlematch Pro Wrestling A78 PAL=true;board=0 md5:1af475ff6429a160752b592f0f92b287 Titlematch Pro Wrestling A78 NTSC=true;board=0 md5:c3903ab01a51222a52197dbfe6538ecf Tomcat F14 A78 NTSC=true;board=0 md5:682338364243b023ecc9d24f0abfc9a7 Tomcat F14 A78 PAL=true;board=0 -md5:208ef955fa90a29815eb097bce89bace Touchdown Football A78 NTSC=true;board=A78SG -md5:8d64763db3100aadc552db5e6868506a Tower Toppler A78 NTSC=true;board=A78S4R -md5:32a37244a9c6cc928dcdf02b45365aa8 Tower Toppler A78 PAL=true;board=A78S4R -md5:412cc5bfa08bd03244b9c4e8d46cd0a0 Wasp (Standard Edition) A78 NTSC=true;board=A7832 -md5:427cb05d0a1abb068998e2760d77f4fb Water Ski A78 NTSC=true;board=A78S4 -md5:3799d72f78dda2ee87b0ef8bf7b91186 Winter Games A78 NTSC=true;board=A78SGR -md5:6813ffff510f930c867b3f0aba78ac85 Worm (0703) A78 NTSC=true;board=A7816 -md5:05fb699db9eef564e2fe45c568746dbc Xenophobe A78 NTSC=true;board=A78SG -md5:70937c3184f0be33d06f7f4382ca54de Xenophobe A78 PAL=true;board=A78SG +md5:208ef955fa90a29815eb097bce89bace Touchdown Football A78 NTSC=true;board=1 +md5:8d64763db3100aadc552db5e6868506a Tower Toppler A78 NTSC=true;board=1;RAM=8 +md5:32a37244a9c6cc928dcdf02b45365aa8 Tower Toppler A78 PAL=true;board=1;RAM=8 +md5:412cc5bfa08bd03244b9c4e8d46cd0a0 Wasp (Standard Edition) A78 NTSC=true;board=0 +md5:427cb05d0a1abb068998e2760d77f4fb Water Ski A78 NTSC=true;board=1 +md5:3799d72f78dda2ee87b0ef8bf7b91186 Winter Games A78 NTSC=true;board=1;RAM=16 +md5:6813ffff510f930c867b3f0aba78ac85 Worm (0703) A78 NTSC=true;board=0 +md5:05fb699db9eef564e2fe45c568746dbc Xenophobe A78 NTSC=true;board=1 +md5:70937c3184f0be33d06f7f4382ca54de Xenophobe A78 PAL=true;board=1 md5:d7dc17379aa25e5ae3c14b9e780c6f6d Xevious A78 NTSC=true;board=0 md5:b1a9f196ce5f47ca8caf8fa7bc4ca46c Xevious A78 PAL=true;board=0 md5:ce6fbdc7b037a4efdaf87267f5f292cc b*nQ A78 NTSC=true;board=0 \ No newline at end of file diff --git a/BizHawk.Client.Common/PathManager.cs b/BizHawk.Client.Common/PathManager.cs index be0fdf0ca6..9543368fd8 100644 --- a/BizHawk.Client.Common/PathManager.cs +++ b/BizHawk.Client.Common/PathManager.cs @@ -134,6 +134,9 @@ namespace BizHawk.Client.Common return path; } + if (Path.IsPathRooted(path)) + return path; + //handling of initial .. was removed (Path.GetFullPath can handle it) //handling of file:// or file:\\ was removed (can Path.GetFullPath handle it? not sure) diff --git a/BizHawk.Client.Common/RomGame.cs b/BizHawk.Client.Common/RomGame.cs index 61dab97402..a30e3b64c4 100644 --- a/BizHawk.Client.Common/RomGame.cs +++ b/BizHawk.Client.Common/RomGame.cs @@ -44,7 +44,7 @@ namespace BizHawk.Client.Common // assume we have a header of that size. Otherwise, assume it's just all rom. // Other 'recognized' header sizes may need to be added. int headerOffset = fileLength % BankSize; - if (headerOffset.In(0, 512) == false) + if (headerOffset.In(0, 128, 512) == false) { Console.WriteLine("ROM was not a multiple of 1024 bytes, and not a recognized header size: {0}. Assume it's purely ROM data.", headerOffset); headerOffset = 0; @@ -86,6 +86,13 @@ namespace BizHawk.Client.Common // note: this will be taking several hashes, of a potentially large amount of data.. yikes! GameInfo = Database.GetGameInfo(RomData, file.Name); + + if (GameInfo.NotInDatabase && headerOffset==128 && file.Extension == ".A78") + { + // if the game is not in the DB, add the header back in so the core can use it + // for now only .A78 games, but probably should be for other systems as well + RomData = FileData; + } CheckForPatchOptions(); diff --git a/BizHawk.Client.Common/RomLoader.cs b/BizHawk.Client.Common/RomLoader.cs index 19804b7352..ae69793fbf 100644 --- a/BizHawk.Client.Common/RomLoader.cs +++ b/BizHawk.Client.Common/RomLoader.cs @@ -554,7 +554,7 @@ namespace BizHawk.Client.Common switch (game.System) { case "GEN": - var genesis = new GPGX(nextComm, null, disc, GetCoreSettings(), GetCoreSyncSettings()); + var genesis = new GPGX(nextComm, null, new[] { disc }, GetCoreSettings(), GetCoreSyncSettings()); nextEmulator = genesis; break; case "SAT": @@ -729,6 +729,15 @@ namespace BizHawk.Client.Common nextEmulator = new Tst(nextComm, pcfxDiscs, (Tst.Settings)GetCoreSettings(), (Tst.SyncSettings)GetCoreSyncSettings()); break; + case "GEN": + // We are assuming discs only, for now + var genDiscs = DiscsFromXml(xmlGame, "GEN", DiscType.MegaCD); + if (!genDiscs.Any()) + { + return false; + } + nextEmulator = new GPGX(nextComm, null, genDiscs, GetCoreSettings(), GetCoreSyncSettings()); + break; default: return false; } @@ -911,7 +920,6 @@ namespace BizHawk.Client.Common case "GBC": if (!Global.Config.GB_AsSGB) { - //core = CoreInventory.Instance["GB", "Pizza Boy"]; core = CoreInventory.Instance["GB", "Gambatte"]; } else @@ -925,7 +933,7 @@ namespace BizHawk.Client.Common } else { - core = CoreInventory.Instance["SGB", "Pizza Boy"]; + core = CoreInventory.Instance["SGB", "SameBoy"]; } } break; @@ -940,7 +948,7 @@ namespace BizHawk.Client.Common { nextEmulator = Global.Config.A78_UseEmu7800 ? nextEmulator = new Atari7800(nextComm, game, rom.RomData, gamedbpath) - : nextEmulator = new A7800Hawk(nextComm, game, rom.RomData, gamedbpath); + : nextEmulator = new A7800Hawk(nextComm, game, rom.RomData, gamedbpath, GetCoreSettings(), GetCoreSyncSettings()); } break; diff --git a/BizHawk.Client.Common/lua/LuaFile.cs b/BizHawk.Client.Common/lua/LuaFile.cs index 0358c3ffa5..63ae59c75e 100644 --- a/BizHawk.Client.Common/lua/LuaFile.cs +++ b/BizHawk.Client.Common/lua/LuaFile.cs @@ -49,7 +49,7 @@ public void Stop() { State = RunState.Disabled; - if(NLua.Lua.WhichLua == "NLua") + //if(NLua.Lua.WhichLua == "NLua") Thread.GetTable("keepalives")[Thread] = null; Thread = null; } diff --git a/BizHawk.Client.EmuHawk/ArgParser.cs b/BizHawk.Client.EmuHawk/ArgParser.cs index 22ac749614..939ca94b29 100644 --- a/BizHawk.Client.EmuHawk/ArgParser.cs +++ b/BizHawk.Client.EmuHawk/ArgParser.cs @@ -20,6 +20,7 @@ namespace BizHawk.Client.EmuHawk public HashSet _currAviWriterFrameList; public int _autoDumpLength; public bool _autoCloseOnDump = false; + // chrome is never shown, even in windowed mode public bool _chromeless = false; public bool startFullscreen = false; public string luaScript = null; diff --git a/BizHawk.Client.EmuHawk/CustomControls/VirtualListView.cs b/BizHawk.Client.EmuHawk/CustomControls/VirtualListView.cs index 0ae416b548..f0a2d07909 100644 --- a/BizHawk.Client.EmuHawk/CustomControls/VirtualListView.cs +++ b/BizHawk.Client.EmuHawk/CustomControls/VirtualListView.cs @@ -54,9 +54,10 @@ namespace BizHawk.Client.EmuHawk public uint dwDrawStage; public IntPtr Hdc; public RECT Rect; - public int dwItemSpec; + public IntPtr dwItemSpec; public uint ItemState; - public int lItemlParam; + private int _pad64bits; + public IntPtr lItemlParam; } [StructLayout(LayoutKind.Sequential)] @@ -596,7 +597,7 @@ namespace BizHawk.Client.EmuHawk if (QueryItemBkColor != null) { var color = Color.FromArgb(cd.ClearTextBackground & 0xFF, (cd.ClearTextBackground >> 8) & 0xFF, (cd.ClearTextBackground >> 16) & 0xFF); - QueryItemBkColor(cd.Nmcd.dwItemSpec, cd.SubItem, ref color); + 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); } diff --git a/BizHawk.Client.EmuHawk/Extensions/ControlExtensions.cs b/BizHawk.Client.EmuHawk/Extensions/ControlExtensions.cs index 5221e522ed..f03313113b 100644 --- a/BizHawk.Client.EmuHawk/Extensions/ControlExtensions.cs +++ b/BizHawk.Client.EmuHawk/Extensions/ControlExtensions.cs @@ -176,7 +176,9 @@ namespace BizHawk.Client.EmuHawk.WinFormExtensions public static DialogResult ShowHawkDialog(this CommonDialog form) { GlobalWin.Sound.StopSound(); - var result = form.ShowDialog(new Form() { TopMost = true }); + var tempForm = new Form() { TopMost = true }; + var result = form.ShowDialog(tempForm); + tempForm.Dispose(); GlobalWin.Sound.StartSound(); return result; } diff --git a/BizHawk.Client.EmuHawk/Input/GamePad360.cs b/BizHawk.Client.EmuHawk/Input/GamePad360.cs index ab0a4a2d2a..a93d1dd1b2 100644 --- a/BizHawk.Client.EmuHawk/Input/GamePad360.cs +++ b/BizHawk.Client.EmuHawk/Input/GamePad360.cs @@ -180,8 +180,8 @@ namespace BizHawk.Client.EmuHawk void InitializeButtons() { - const int dzp = 9000; - const int dzn = -9000; + const int dzp = 20000; + const int dzn = -20000; const int dzt = 40; AddItem("A", () => (state.Gamepad.wButtons & (ushort)GamepadButtonFlags.A) != 0); diff --git a/BizHawk.Client.EmuHawk/MainForm.Designer.cs b/BizHawk.Client.EmuHawk/MainForm.Designer.cs index df6e60bf23..be04630c83 100644 --- a/BizHawk.Client.EmuHawk/MainForm.Designer.cs +++ b/BizHawk.Client.EmuHawk/MainForm.Designer.cs @@ -17,440 +17,440 @@ /// private void InitializeComponent() { - this.components = new System.ComponentModel.Container(); - System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm)); - this.MainformMenu = new MenuStripEx(); - this.FileSubMenu = new System.Windows.Forms.ToolStripMenuItem(); - this.OpenRomMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.RecentRomSubMenu = new System.Windows.Forms.ToolStripMenuItem(); - this.toolStripSeparator3 = new System.Windows.Forms.ToolStripSeparator(); - this.OpenAdvancedMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.CloseRomMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.toolStripMenuItem1 = new System.Windows.Forms.ToolStripSeparator(); - this.SaveStateSubMenu = new System.Windows.Forms.ToolStripMenuItem(); - this.SaveState1MenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.SaveState2MenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.SaveState3MenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.SaveState4MenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.SaveState5MenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.SaveState6MenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.SaveState7MenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.SaveState8MenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.SaveState9MenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.SaveState0MenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.toolStripSeparator6 = new System.Windows.Forms.ToolStripSeparator(); - this.SaveNamedStateMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.LoadStateSubMenu = new System.Windows.Forms.ToolStripMenuItem(); - this.LoadState1MenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.LoadState2MenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.LoadState3MenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.LoadState4MenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.LoadState5MenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.LoadState6MenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.LoadState7MenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.LoadState8MenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.LoadState9MenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.LoadState0MenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.toolStripSeparator7 = new System.Windows.Forms.ToolStripSeparator(); - this.LoadNamedStateMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.toolStripSeparator21 = new System.Windows.Forms.ToolStripSeparator(); - this.AutoloadLastSlotMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.SaveSlotSubMenu = new System.Windows.Forms.ToolStripMenuItem(); - this.SelectSlot0MenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.SelectSlot1MenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.SelectSlot2MenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.SelectSlot3MenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.SelectSlot4MenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.SelectSlot5MenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.SelectSlot6MenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.SelectSlot7MenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.SelectSlot8MenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.SelectSlot9MenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.PreviousSlotMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.NextSlotMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.toolStripSeparator5 = new System.Windows.Forms.ToolStripSeparator(); - this.SaveToCurrentSlotMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.LoadCurrentSlotMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.SaveRAMSubMenu = new System.Windows.Forms.ToolStripMenuItem(); - this.FlushSaveRAMMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.toolStripMenuItem2 = new System.Windows.Forms.ToolStripSeparator(); - this.MovieSubMenu = new System.Windows.Forms.ToolStripMenuItem(); - this.ReadonlyMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.toolStripSeparator15 = new System.Windows.Forms.ToolStripSeparator(); - this.RecentMovieSubMenu = new System.Windows.Forms.ToolStripMenuItem(); - this.toolStripSeparator16 = new System.Windows.Forms.ToolStripSeparator(); - this.RecordMovieMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.PlayMovieMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.StopMovieMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.PlayFromBeginningMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.ImportMoviesMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.SaveMovieMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.SaveMovieAsMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.StopMovieWithoutSavingMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.toolStripSeparator14 = new System.Windows.Forms.ToolStripSeparator(); - this.AutomaticallyBackupMoviesMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.FullMovieLoadstatesMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.MovieEndSubMenu = new System.Windows.Forms.ToolStripMenuItem(); - this.MovieEndFinishMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.MovieEndRecordMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.MovieEndStopMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.MovieEndPauseMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.AVSubMenu = new System.Windows.Forms.ToolStripMenuItem(); - this.RecordAVMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.ConfigAndRecordAVMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.StopAVIMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.toolStripSeparator19 = new System.Windows.Forms.ToolStripSeparator(); - this.CaptureOSDMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.SynclessRecordingMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.ScreenshotSubMenu = new System.Windows.Forms.ToolStripMenuItem(); - this.ScreenshotMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.ScreenshotAsMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.ScreenshotClipboardMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.ScreenshotClientClipboardMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.toolStripSeparator20 = new System.Windows.Forms.ToolStripSeparator(); - this.ScreenshotCaptureOSDMenuItem1 = new System.Windows.Forms.ToolStripMenuItem(); - this.toolStripSeparator4 = new System.Windows.Forms.ToolStripSeparator(); - this.ExitMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.EmulationSubMenu = new System.Windows.Forms.ToolStripMenuItem(); - this.PauseMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.RebootCoreMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator(); - this.SoftResetMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.HardResetMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.ViewSubMenu = new System.Windows.Forms.ToolStripMenuItem(); - this.WindowSizeSubMenu = new System.Windows.Forms.ToolStripMenuItem(); - this.x1MenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.x2MenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.x3MenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.x4MenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.x5MenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.mzMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.SwitchToFullscreenMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.toolStripSeparator2 = new System.Windows.Forms.ToolStripSeparator(); - this.DisplayFPSMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.DisplayFrameCounterMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.DisplayLagCounterMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.DisplayInputMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.DisplayRerecordCountMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.DisplaySubtitlesMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.toolStripMenuItem4 = new System.Windows.Forms.ToolStripSeparator(); - this.DisplayStatusBarMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.DisplayMessagesMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.DisplayLogWindowMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.ConfigSubMenu = new System.Windows.Forms.ToolStripMenuItem(); - this.ControllersMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.HotkeysMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.DisplayConfigMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.SoundMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.PathsMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.FirmwaresMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.MessagesMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.AutofireMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.RewindOptionsMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.extensionsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.ClientOptionsMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.ProfilesMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.toolStripSeparator9 = new System.Windows.Forms.ToolStripSeparator(); - this.SpeedSkipSubMenu = new System.Windows.Forms.ToolStripMenuItem(); - this.ClockThrottleMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.AudioThrottleMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.VsyncThrottleMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.toolStripSeparator27 = new System.Windows.Forms.ToolStripSeparator(); - this.VsyncEnabledMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.toolStripMenuItem3 = new System.Windows.Forms.ToolStripSeparator(); - this.miUnthrottled = new System.Windows.Forms.ToolStripMenuItem(); - this.MinimizeSkippingMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.NeverSkipMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.toolStripMenuItem17 = new System.Windows.Forms.ToolStripMenuItem(); - this.Frameskip1MenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.Frameskip2MenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.Frameskip3MenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.Frameskip4MenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.Frameskip5MenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.Frameskip6MenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.Frameskip7MenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.Frameskip8MenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.Frameskip9MenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.toolStripMenuItem5 = new System.Windows.Forms.ToolStripSeparator(); - this.Speed50MenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.Speed75MenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.Speed100MenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.Speed150MenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.Speed200MenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.Speed400MenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.KeyPrioritySubMenu = new System.Windows.Forms.ToolStripMenuItem(); - this.BothHkAndControllerMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.InputOverHkMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.HkOverInputMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.CoresSubMenu = new System.Windows.Forms.ToolStripMenuItem(); - this.NesCoreSubMenu = new System.Windows.Forms.ToolStripMenuItem(); - this.QuicknesCoreMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.NesCoreMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.CoreSNESSubMenu = new System.Windows.Forms.ToolStripMenuItem(); - this.Coresnes9xMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.CorebsnesMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.GbaCoreSubMenu = new System.Windows.Forms.ToolStripMenuItem(); - this.VbaNextCoreMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.MgbaCoreMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.Atari7800CoreSubMenu = new System.Windows.Forms.ToolStripMenuItem(); - this.Emu7800CoreMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.Atari7800HawkCoreMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.SGBCoreSubmenu = new System.Windows.Forms.ToolStripMenuItem(); - this.SgbBsnesMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.SgbPizzaBoyMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.GBInSGBMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.toolStripMenuItem16 = new System.Windows.Forms.ToolStripSeparator(); - this.allowGameDBCoreOverridesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.toolStripSeparator8 = new System.Windows.Forms.ToolStripSeparator(); - this.N64VideoPluginSettingsMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.setLibretroCoreToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.toolStripSeparator10 = new System.Windows.Forms.ToolStripSeparator(); - this.SaveConfigMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.SaveConfigAsMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.LoadConfigMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.LoadConfigFromMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.ToolsSubMenu = new System.Windows.Forms.ToolStripMenuItem(); - this.ToolBoxMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.toolStripSeparator12 = new System.Windows.Forms.ToolStripSeparator(); - this.RamWatchMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.RamSearchMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.LuaConsoleMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.TAStudioMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.HexEditorMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.TraceLoggerMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.DebuggerMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.CodeDataLoggerMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.MacroToolMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.VirtualPadMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.BasicBotMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.toolStripSeparator11 = new System.Windows.Forms.ToolStripSeparator(); - this.CheatsMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.gameSharkConverterToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.toolStripSeparator29 = new System.Windows.Forms.ToolStripSeparator(); - this.MultiDiskBundlerFileMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.externalToolToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - 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(); - this.quickNESToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.nesHawkToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.toolStripSeparator34 = new System.Windows.Forms.ToolStripSeparator(); - this.NESPPUViewerMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.NESNametableViewerMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.NESGameGenieCodesMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.musicRipperToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.toolStripSeparator17 = new System.Windows.Forms.ToolStripSeparator(); - this.NesControllerSettingsMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.NESGraphicSettingsMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.NESSoundChannelsMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.VSSettingsMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.MovieSettingsMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.toolStripSeparator22 = new System.Windows.Forms.ToolStripSeparator(); - this.FDSControlsMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.FdsEjectDiskMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.VSControlsMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.VSInsertCoinP1MenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.VSInsertCoinP2MenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.VSServiceSwitchMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.barcodeReaderToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.PCESubMenu = new System.Windows.Forms.ToolStripMenuItem(); - this.PceControllerSettingsMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.PCEGraphicsSettingsMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.toolStripSeparator32 = new System.Windows.Forms.ToolStripSeparator(); - this.PCEBGViewerMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.PCEtileViewerToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.PceSoundDebuggerToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.toolStripSeparator25 = new System.Windows.Forms.ToolStripSeparator(); - this.PCEAlwaysPerformSpriteLimitMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.PCEAlwaysEqualizeVolumesMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.PCEArcadeCardRewindEnableMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.SMSSubMenu = new System.Windows.Forms.ToolStripMenuItem(); - this.SMSregionToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.SMSregionExportToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.SMSregionJapanToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.SMSregionAutoToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.SMSdisplayToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.SMSdisplayNtscToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.SMSdisplayPalToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.SMSdisplayAutoToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.SMStoolStripMenuItem2 = new System.Windows.Forms.ToolStripSeparator(); - this.SMSenableBIOSToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.SMSEnableFMChipMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.SMSOverclockMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.SMSForceStereoMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.SMSSpriteLimitMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.SMSDisplayOverscanMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.SMSFix3DGameDisplayToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.ShowClippedRegionsMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.HighlightActiveDisplayRegionMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.SMSGraphicsSettingsMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.toolStripSeparator24 = new System.Windows.Forms.ToolStripSeparator(); - this.SMSVDPViewerToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.GGGameGenieMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.TI83SubMenu = new System.Windows.Forms.ToolStripMenuItem(); - this.KeypadMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.LoadTIFileMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.toolStripSeparator13 = new System.Windows.Forms.ToolStripSeparator(); - this.AutoloadKeypadMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.paletteToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.AtariSubMenu = new System.Windows.Forms.ToolStripMenuItem(); - this.AtariSettingsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.A7800SubMenu = new System.Windows.Forms.ToolStripMenuItem(); - this.A7800ControllerSettingsMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.GBSubMenu = new System.Windows.Forms.ToolStripMenuItem(); - this.GBcoreSettingsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.LoadGBInSGBMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.toolStripSeparator28 = new System.Windows.Forms.ToolStripSeparator(); - this.GBGPUViewerMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.GBGameGenieMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.GBASubMenu = new System.Windows.Forms.ToolStripMenuItem(); - this.GBACoreSelectionSubMenu = new System.Windows.Forms.ToolStripMenuItem(); - this.GBAmGBAMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.GBAVBANextMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.GBAcoresettingsToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem(); - this.toolStripSeparator33 = new System.Windows.Forms.ToolStripSeparator(); - this.GbaGpuViewerMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.PSXSubMenu = new System.Windows.Forms.ToolStripMenuItem(); - this.PSXControllerSettingsMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.PSXOptionsMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.PSXDiscControlsMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.PSXHashDiscsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.SNESSubMenu = new System.Windows.Forms.ToolStripMenuItem(); - this.SNESControllerConfigurationMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.toolStripSeparator18 = new System.Windows.Forms.ToolStripSeparator(); - this.SnesGfxDebuggerMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.SnesGBInSGBMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.SnesGameGenieMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.SnesOptionsMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.ColecoSubMenu = new System.Windows.Forms.ToolStripMenuItem(); - this.ColecoControllerSettingsMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.toolStripSeparator35 = new System.Windows.Forms.ToolStripSeparator(); - this.ColecoSkipBiosMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.N64SubMenu = new System.Windows.Forms.ToolStripMenuItem(); - this.N64PluginSettingsMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.N64ControllerSettingsMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.toolStripSeparator23 = new System.Windows.Forms.ToolStripSeparator(); - this.N64CircularAnalogRangeMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.MupenStyleLagMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.N64ExpansionSlotMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.SaturnSubMenu = new System.Windows.Forms.ToolStripMenuItem(); - this.SaturnPreferencesMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.DGBSubMenu = new System.Windows.Forms.ToolStripMenuItem(); - this.DGBsettingsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.GenesisSubMenu = new System.Windows.Forms.ToolStripMenuItem(); - this.vDPViewerToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.GenesisGameGenieECDC = new System.Windows.Forms.ToolStripMenuItem(); - this.toolStripSeparator26 = new System.Windows.Forms.ToolStripSeparator(); - this.GenesisSettingsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.wonderSwanToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.settingsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.AppleSubMenu = new System.Windows.Forms.ToolStripMenuItem(); - this.AppleDisksSubMenu = new System.Windows.Forms.ToolStripMenuItem(); - this.toolStripSeparator31 = new System.Windows.Forms.ToolStripSeparator(); - this.settingsToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem(); - this.C64SubMenu = new System.Windows.Forms.ToolStripMenuItem(); - this.C64DisksSubMenu = new System.Windows.Forms.ToolStripMenuItem(); - this.toolStripSeparator36 = new System.Windows.Forms.ToolStripSeparator(); - this.C64SettingsMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.IntvSubMenu = new System.Windows.Forms.ToolStripMenuItem(); - this.IntVControllerSettingsMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.sNESToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.preferencesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.virtualBoyToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.preferencesToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem(); - this.neoGeoPocketToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.preferencesToolStripMenuItem2 = new System.Windows.Forms.ToolStripMenuItem(); - this.HelpSubMenu = new System.Windows.Forms.ToolStripMenuItem(); - this.OnlineHelpMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.ForumsMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.FeaturesMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.AboutMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.MainStatusBar = new StatusStripEx(); - this.DumpStatusButton = new System.Windows.Forms.ToolStripDropDownButton(); - this.EmuStatus = new System.Windows.Forms.ToolStripStatusLabel(); - this.PlayRecordStatusButton = new System.Windows.Forms.ToolStripDropDownButton(); - this.PauseStatusButton = new System.Windows.Forms.ToolStripDropDownButton(); - this.RebootStatusBarIcon = new System.Windows.Forms.ToolStripStatusLabel(); - this.AVIStatusLabel = new System.Windows.Forms.ToolStripStatusLabel(); - this.LedLightStatusLabel = new System.Windows.Forms.ToolStripStatusLabel(); - this.SaveSlotsStatusLabel = new System.Windows.Forms.ToolStripStatusLabel(); - this.Slot1StatusButton = new System.Windows.Forms.ToolStripStatusLabel(); - this.Slot2StatusButton = new System.Windows.Forms.ToolStripStatusLabel(); - this.Slot3StatusButton = new System.Windows.Forms.ToolStripStatusLabel(); - this.Slot4StatusButton = new System.Windows.Forms.ToolStripStatusLabel(); - this.Slot5StatusButton = new System.Windows.Forms.ToolStripStatusLabel(); - this.Slot6StatusButton = new System.Windows.Forms.ToolStripStatusLabel(); - this.Slot7StatusButton = new System.Windows.Forms.ToolStripStatusLabel(); - this.Slot8StatusButton = new System.Windows.Forms.ToolStripStatusLabel(); - this.Slot9StatusButton = new System.Windows.Forms.ToolStripStatusLabel(); - this.Slot0StatusButton = new System.Windows.Forms.ToolStripStatusLabel(); - this.CheatStatusButton = new System.Windows.Forms.ToolStripStatusLabel(); - this.KeyPriorityStatusLabel = new System.Windows.Forms.ToolStripStatusLabel(); - this.CoreNameStatusBarButton = new System.Windows.Forms.ToolStripStatusLabel(); - this.ProfileFirstBootLabel = new System.Windows.Forms.ToolStripStatusLabel(); - this.LinkConnectStatusBarButton = new System.Windows.Forms.ToolStripStatusLabel(); - this.UpdateNotification = new System.Windows.Forms.ToolStripStatusLabel(); - this.MainFormContextMenu = new System.Windows.Forms.ContextMenuStrip(this.components); - this.OpenRomContextMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.LoadLastRomContextMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.StopAVContextMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.ContextSeparator_AfterROM = new System.Windows.Forms.ToolStripSeparator(); - this.RecordMovieContextMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.PlayMovieContextMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.RestartMovieContextMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.StopMovieContextMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.LoadLastMovieContextMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.BackupMovieContextMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.StopNoSaveContextMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.ViewSubtitlesContextMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.AddSubtitleContextMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.ViewCommentsContextMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.SaveMovieContextMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.SaveMovieAsContextMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.ContextSeparator_AfterMovie = new System.Windows.Forms.ToolStripSeparator(); - this.UndoSavestateContextMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.ContextSeparator_AfterUndo = new System.Windows.Forms.ToolStripSeparator(); - this.ConfigContextMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.toolStripMenuItem6 = new System.Windows.Forms.ToolStripMenuItem(); - this.toolStripMenuItem7 = new System.Windows.Forms.ToolStripMenuItem(); - this.toolStripMenuItem8 = new System.Windows.Forms.ToolStripMenuItem(); - this.toolStripMenuItem9 = new System.Windows.Forms.ToolStripMenuItem(); - this.toolStripMenuItem10 = new System.Windows.Forms.ToolStripMenuItem(); - this.toolStripMenuItem11 = new System.Windows.Forms.ToolStripMenuItem(); - this.toolStripMenuItem12 = new System.Windows.Forms.ToolStripMenuItem(); - this.toolStripMenuItem13 = new System.Windows.Forms.ToolStripMenuItem(); - this.toolStripMenuItem14 = new System.Windows.Forms.ToolStripMenuItem(); - this.toolStripMenuItem15 = new System.Windows.Forms.ToolStripMenuItem(); - this.customizeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.toolStripSeparator30 = new System.Windows.Forms.ToolStripSeparator(); - this.SavestateTypeContextSubMenu = new System.Windows.Forms.ToolStripMenuItem(); - this.SavestateTypeDefaultContextMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.SavestateBinaryContextMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.SavestateTextContextMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.toolStripSeparator37 = new System.Windows.Forms.ToolStripSeparator(); - this.toolStripMenuItem66 = new System.Windows.Forms.ToolStripMenuItem(); - this.toolStripMenuItem67 = new System.Windows.Forms.ToolStripMenuItem(); - this.ScreenshotContextMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.CloseRomContextMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.ClearSRAMContextMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.ShowMenuContextMenuSeparator = new System.Windows.Forms.ToolStripSeparator(); - this.ShowMenuContextMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.timerMouseIdle = new System.Windows.Forms.Timer(this.components); - this.pCFXToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.preferencesToolStripMenuItem3 = new System.Windows.Forms.ToolStripMenuItem(); - this.MainformMenu.SuspendLayout(); - this.MainStatusBar.SuspendLayout(); - this.MainFormContextMenu.SuspendLayout(); - this.SuspendLayout(); - // - // MainformMenu - // - this.MainformMenu.ClickThrough = true; - this.MainformMenu.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.components = new System.ComponentModel.Container(); + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm)); + this.MainformMenu = new MenuStripEx(); + this.FileSubMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.OpenRomMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.RecentRomSubMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator3 = new System.Windows.Forms.ToolStripSeparator(); + this.OpenAdvancedMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.CloseRomMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMenuItem1 = new System.Windows.Forms.ToolStripSeparator(); + this.SaveStateSubMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.SaveState1MenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.SaveState2MenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.SaveState3MenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.SaveState4MenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.SaveState5MenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.SaveState6MenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.SaveState7MenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.SaveState8MenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.SaveState9MenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.SaveState0MenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator6 = new System.Windows.Forms.ToolStripSeparator(); + this.SaveNamedStateMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.LoadStateSubMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.LoadState1MenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.LoadState2MenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.LoadState3MenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.LoadState4MenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.LoadState5MenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.LoadState6MenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.LoadState7MenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.LoadState8MenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.LoadState9MenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.LoadState0MenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator7 = new System.Windows.Forms.ToolStripSeparator(); + this.LoadNamedStateMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator21 = new System.Windows.Forms.ToolStripSeparator(); + this.AutoloadLastSlotMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.SaveSlotSubMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.SelectSlot0MenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.SelectSlot1MenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.SelectSlot2MenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.SelectSlot3MenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.SelectSlot4MenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.SelectSlot5MenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.SelectSlot6MenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.SelectSlot7MenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.SelectSlot8MenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.SelectSlot9MenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.PreviousSlotMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.NextSlotMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator5 = new System.Windows.Forms.ToolStripSeparator(); + this.SaveToCurrentSlotMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.LoadCurrentSlotMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.SaveRAMSubMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.FlushSaveRAMMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMenuItem2 = new System.Windows.Forms.ToolStripSeparator(); + this.MovieSubMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.ReadonlyMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator15 = new System.Windows.Forms.ToolStripSeparator(); + this.RecentMovieSubMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator16 = new System.Windows.Forms.ToolStripSeparator(); + this.RecordMovieMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.PlayMovieMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.StopMovieMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.PlayFromBeginningMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.ImportMoviesMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.SaveMovieMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.SaveMovieAsMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.StopMovieWithoutSavingMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator14 = new System.Windows.Forms.ToolStripSeparator(); + this.AutomaticallyBackupMoviesMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.FullMovieLoadstatesMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.MovieEndSubMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.MovieEndFinishMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.MovieEndRecordMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.MovieEndStopMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.MovieEndPauseMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.AVSubMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.RecordAVMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.ConfigAndRecordAVMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.StopAVIMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator19 = new System.Windows.Forms.ToolStripSeparator(); + this.CaptureOSDMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.SynclessRecordingMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.ScreenshotSubMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.ScreenshotMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.ScreenshotAsMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.ScreenshotClipboardMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.ScreenshotClientClipboardMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator20 = new System.Windows.Forms.ToolStripSeparator(); + this.ScreenshotCaptureOSDMenuItem1 = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator4 = new System.Windows.Forms.ToolStripSeparator(); + this.ExitMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.EmulationSubMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.PauseMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.RebootCoreMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator(); + this.SoftResetMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.HardResetMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.ViewSubMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.WindowSizeSubMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.x1MenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.x2MenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.x3MenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.x4MenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.x5MenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.mzMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.SwitchToFullscreenMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator2 = new System.Windows.Forms.ToolStripSeparator(); + this.DisplayFPSMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.DisplayFrameCounterMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.DisplayLagCounterMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.DisplayInputMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.DisplayRerecordCountMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.DisplaySubtitlesMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMenuItem4 = new System.Windows.Forms.ToolStripSeparator(); + this.DisplayStatusBarMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.DisplayMessagesMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.DisplayLogWindowMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.ConfigSubMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.ControllersMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.HotkeysMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.DisplayConfigMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.SoundMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.PathsMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.FirmwaresMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.MessagesMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.AutofireMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.RewindOptionsMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.extensionsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.ClientOptionsMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.ProfilesMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator9 = new System.Windows.Forms.ToolStripSeparator(); + this.SpeedSkipSubMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.ClockThrottleMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.AudioThrottleMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.VsyncThrottleMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator27 = new System.Windows.Forms.ToolStripSeparator(); + this.VsyncEnabledMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMenuItem3 = new System.Windows.Forms.ToolStripSeparator(); + this.miUnthrottled = new System.Windows.Forms.ToolStripMenuItem(); + this.MinimizeSkippingMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.NeverSkipMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMenuItem17 = new System.Windows.Forms.ToolStripMenuItem(); + this.Frameskip1MenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.Frameskip2MenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.Frameskip3MenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.Frameskip4MenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.Frameskip5MenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.Frameskip6MenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.Frameskip7MenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.Frameskip8MenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.Frameskip9MenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMenuItem5 = new System.Windows.Forms.ToolStripSeparator(); + this.Speed50MenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.Speed75MenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.Speed100MenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.Speed150MenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.Speed200MenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.Speed400MenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.KeyPrioritySubMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.BothHkAndControllerMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.InputOverHkMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.HkOverInputMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.CoresSubMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.NesCoreSubMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.QuicknesCoreMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.NesCoreMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.CoreSNESSubMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.Coresnes9xMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.CorebsnesMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.GbaCoreSubMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.VbaNextCoreMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.MgbaCoreMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.Atari7800CoreSubMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.Emu7800CoreMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.Atari7800HawkCoreMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.SGBCoreSubmenu = new System.Windows.Forms.ToolStripMenuItem(); + this.SgbBsnesMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.SgbSameBoyMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.GBInSGBMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMenuItem16 = new System.Windows.Forms.ToolStripSeparator(); + this.allowGameDBCoreOverridesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator8 = new System.Windows.Forms.ToolStripSeparator(); + this.N64VideoPluginSettingsMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.setLibretroCoreToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator10 = new System.Windows.Forms.ToolStripSeparator(); + this.SaveConfigMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.SaveConfigAsMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.LoadConfigMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.LoadConfigFromMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.ToolsSubMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.ToolBoxMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator12 = new System.Windows.Forms.ToolStripSeparator(); + this.RamWatchMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.RamSearchMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.LuaConsoleMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.TAStudioMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.HexEditorMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.TraceLoggerMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.DebuggerMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.CodeDataLoggerMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.MacroToolMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.VirtualPadMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.BasicBotMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator11 = new System.Windows.Forms.ToolStripSeparator(); + this.CheatsMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.gameSharkConverterToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator29 = new System.Windows.Forms.ToolStripSeparator(); + this.MultiDiskBundlerFileMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.externalToolToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + 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(); + this.quickNESToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.nesHawkToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator34 = new System.Windows.Forms.ToolStripSeparator(); + this.NESPPUViewerMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.NESNametableViewerMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.NESGameGenieCodesMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.musicRipperToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator17 = new System.Windows.Forms.ToolStripSeparator(); + this.NesControllerSettingsMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.NESGraphicSettingsMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.NESSoundChannelsMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.VSSettingsMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.MovieSettingsMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator22 = new System.Windows.Forms.ToolStripSeparator(); + this.FDSControlsMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.FdsEjectDiskMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.VSControlsMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.VSInsertCoinP1MenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.VSInsertCoinP2MenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.VSServiceSwitchMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.barcodeReaderToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.PCESubMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.PceControllerSettingsMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.PCEGraphicsSettingsMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator32 = new System.Windows.Forms.ToolStripSeparator(); + this.PCEBGViewerMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.PCEtileViewerToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.PceSoundDebuggerToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator25 = new System.Windows.Forms.ToolStripSeparator(); + this.PCEAlwaysPerformSpriteLimitMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.PCEAlwaysEqualizeVolumesMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.PCEArcadeCardRewindEnableMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.SMSSubMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.SMSregionToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.SMSregionExportToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.SMSregionJapanToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.SMSregionAutoToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.SMSdisplayToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.SMSdisplayNtscToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.SMSdisplayPalToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.SMSdisplayAutoToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.SMStoolStripMenuItem2 = new System.Windows.Forms.ToolStripSeparator(); + this.SMSenableBIOSToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.SMSEnableFMChipMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.SMSOverclockMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.SMSForceStereoMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.SMSSpriteLimitMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.SMSDisplayOverscanMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.SMSFix3DGameDisplayToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.ShowClippedRegionsMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.HighlightActiveDisplayRegionMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.SMSGraphicsSettingsMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator24 = new System.Windows.Forms.ToolStripSeparator(); + this.SMSVDPViewerToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.GGGameGenieMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.TI83SubMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.KeypadMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.LoadTIFileMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator13 = new System.Windows.Forms.ToolStripSeparator(); + this.AutoloadKeypadMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.paletteToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.AtariSubMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.AtariSettingsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.A7800SubMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.A7800ControllerSettingsMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.GBSubMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.GBcoreSettingsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.LoadGBInSGBMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator28 = new System.Windows.Forms.ToolStripSeparator(); + this.GBGPUViewerMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.GBGameGenieMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.GBASubMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.GBACoreSelectionSubMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.GBAmGBAMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.GBAVBANextMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.GBAcoresettingsToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator33 = new System.Windows.Forms.ToolStripSeparator(); + this.GbaGpuViewerMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.PSXSubMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.PSXControllerSettingsMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.PSXOptionsMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.PSXDiscControlsMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.PSXHashDiscsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.SNESSubMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.SNESControllerConfigurationMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator18 = new System.Windows.Forms.ToolStripSeparator(); + this.SnesGfxDebuggerMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.SnesGBInSGBMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.SnesGameGenieMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.SnesOptionsMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.ColecoSubMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.ColecoControllerSettingsMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator35 = new System.Windows.Forms.ToolStripSeparator(); + this.ColecoSkipBiosMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.N64SubMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.N64PluginSettingsMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.N64ControllerSettingsMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator23 = new System.Windows.Forms.ToolStripSeparator(); + this.N64CircularAnalogRangeMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.MupenStyleLagMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.N64ExpansionSlotMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.SaturnSubMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.SaturnPreferencesMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.DGBSubMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.DGBsettingsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.GenesisSubMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.vDPViewerToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.GenesisGameGenieECDC = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator26 = new System.Windows.Forms.ToolStripSeparator(); + this.GenesisSettingsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.wonderSwanToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.settingsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.AppleSubMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.AppleDisksSubMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator31 = new System.Windows.Forms.ToolStripSeparator(); + this.settingsToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem(); + this.C64SubMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.C64DisksSubMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator36 = new System.Windows.Forms.ToolStripSeparator(); + this.C64SettingsMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.IntvSubMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.IntVControllerSettingsMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.sNESToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.preferencesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.pCFXToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.preferencesToolStripMenuItem3 = new System.Windows.Forms.ToolStripMenuItem(); + this.virtualBoyToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.preferencesToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem(); + this.neoGeoPocketToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.preferencesToolStripMenuItem2 = new System.Windows.Forms.ToolStripMenuItem(); + this.HelpSubMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.OnlineHelpMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.ForumsMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.FeaturesMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.AboutMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.MainStatusBar = new StatusStripEx(); + this.DumpStatusButton = new System.Windows.Forms.ToolStripDropDownButton(); + this.EmuStatus = new System.Windows.Forms.ToolStripStatusLabel(); + this.PlayRecordStatusButton = new System.Windows.Forms.ToolStripDropDownButton(); + this.PauseStatusButton = new System.Windows.Forms.ToolStripDropDownButton(); + this.RebootStatusBarIcon = new System.Windows.Forms.ToolStripStatusLabel(); + this.AVIStatusLabel = new System.Windows.Forms.ToolStripStatusLabel(); + this.LedLightStatusLabel = new System.Windows.Forms.ToolStripStatusLabel(); + this.SaveSlotsStatusLabel = new System.Windows.Forms.ToolStripStatusLabel(); + this.Slot1StatusButton = new System.Windows.Forms.ToolStripStatusLabel(); + this.Slot2StatusButton = new System.Windows.Forms.ToolStripStatusLabel(); + this.Slot3StatusButton = new System.Windows.Forms.ToolStripStatusLabel(); + this.Slot4StatusButton = new System.Windows.Forms.ToolStripStatusLabel(); + this.Slot5StatusButton = new System.Windows.Forms.ToolStripStatusLabel(); + this.Slot6StatusButton = new System.Windows.Forms.ToolStripStatusLabel(); + this.Slot7StatusButton = new System.Windows.Forms.ToolStripStatusLabel(); + this.Slot8StatusButton = new System.Windows.Forms.ToolStripStatusLabel(); + this.Slot9StatusButton = new System.Windows.Forms.ToolStripStatusLabel(); + this.Slot0StatusButton = new System.Windows.Forms.ToolStripStatusLabel(); + this.CheatStatusButton = new System.Windows.Forms.ToolStripStatusLabel(); + this.KeyPriorityStatusLabel = new System.Windows.Forms.ToolStripStatusLabel(); + this.CoreNameStatusBarButton = new System.Windows.Forms.ToolStripStatusLabel(); + this.ProfileFirstBootLabel = new System.Windows.Forms.ToolStripStatusLabel(); + this.LinkConnectStatusBarButton = new System.Windows.Forms.ToolStripStatusLabel(); + this.UpdateNotification = new System.Windows.Forms.ToolStripStatusLabel(); + this.MainFormContextMenu = new System.Windows.Forms.ContextMenuStrip(this.components); + this.OpenRomContextMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.LoadLastRomContextMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.StopAVContextMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.ContextSeparator_AfterROM = new System.Windows.Forms.ToolStripSeparator(); + this.RecordMovieContextMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.PlayMovieContextMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.RestartMovieContextMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.StopMovieContextMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.LoadLastMovieContextMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.BackupMovieContextMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.StopNoSaveContextMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.ViewSubtitlesContextMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.AddSubtitleContextMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.ViewCommentsContextMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.SaveMovieContextMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.SaveMovieAsContextMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.ContextSeparator_AfterMovie = new System.Windows.Forms.ToolStripSeparator(); + this.UndoSavestateContextMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.ContextSeparator_AfterUndo = new System.Windows.Forms.ToolStripSeparator(); + this.ConfigContextMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMenuItem6 = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMenuItem7 = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMenuItem8 = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMenuItem9 = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMenuItem10 = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMenuItem11 = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMenuItem12 = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMenuItem13 = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMenuItem14 = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMenuItem15 = new System.Windows.Forms.ToolStripMenuItem(); + this.customizeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator30 = new System.Windows.Forms.ToolStripSeparator(); + this.SavestateTypeContextSubMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.SavestateTypeDefaultContextMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.SavestateBinaryContextMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.SavestateTextContextMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator37 = new System.Windows.Forms.ToolStripSeparator(); + this.toolStripMenuItem66 = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMenuItem67 = new System.Windows.Forms.ToolStripMenuItem(); + this.ScreenshotContextMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.CloseRomContextMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.ClearSRAMContextMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.ShowMenuContextMenuSeparator = new System.Windows.Forms.ToolStripSeparator(); + this.ShowMenuContextMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.timerMouseIdle = new System.Windows.Forms.Timer(this.components); + this.MainformMenu.SuspendLayout(); + this.MainStatusBar.SuspendLayout(); + this.MainFormContextMenu.SuspendLayout(); + this.SuspendLayout(); + // + // MainformMenu + // + this.MainformMenu.ClickThrough = true; + this.MainformMenu.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { this.FileSubMenu, this.EmulationSubMenu, this.ViewSubMenu, @@ -480,19 +480,19 @@ this.virtualBoyToolStripMenuItem, this.neoGeoPocketToolStripMenuItem, this.HelpSubMenu}); - this.MainformMenu.LayoutStyle = System.Windows.Forms.ToolStripLayoutStyle.Flow; - this.MainformMenu.Location = new System.Drawing.Point(0, 0); - this.MainformMenu.Name = "MainformMenu"; - this.MainformMenu.Size = new System.Drawing.Size(470, 74); - this.MainformMenu.TabIndex = 0; - this.MainformMenu.Text = "menuStrip1"; - this.MainformMenu.MenuActivate += new System.EventHandler(this.MainformMenu_MenuActivate); - this.MainformMenu.MenuDeactivate += new System.EventHandler(this.MainformMenu_MenuDeactivate); - this.MainformMenu.Leave += new System.EventHandler(this.MainformMenu_Leave); - // - // FileSubMenu - // - this.FileSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.MainformMenu.LayoutStyle = System.Windows.Forms.ToolStripLayoutStyle.Flow; + this.MainformMenu.Location = new System.Drawing.Point(0, 0); + this.MainformMenu.Name = "MainformMenu"; + this.MainformMenu.Size = new System.Drawing.Size(470, 80); + this.MainformMenu.TabIndex = 0; + this.MainformMenu.Text = "menuStrip1"; + this.MainformMenu.MenuActivate += new System.EventHandler(this.MainformMenu_MenuActivate); + this.MainformMenu.MenuDeactivate += new System.EventHandler(this.MainformMenu_MenuDeactivate); + this.MainformMenu.Leave += new System.EventHandler(this.MainformMenu_Leave); + // + // FileSubMenu + // + this.FileSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.OpenRomMenuItem, this.RecentRomSubMenu, this.OpenAdvancedMenuItem, @@ -508,57 +508,57 @@ this.ScreenshotSubMenu, this.toolStripSeparator4, this.ExitMenuItem}); - this.FileSubMenu.Name = "FileSubMenu"; - this.FileSubMenu.Size = new System.Drawing.Size(35, 17); - this.FileSubMenu.Text = "&File"; - this.FileSubMenu.DropDownOpened += new System.EventHandler(this.FileSubMenu_DropDownOpened); - // - // OpenRomMenuItem - // - this.OpenRomMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.OpenFile; - this.OpenRomMenuItem.Name = "OpenRomMenuItem"; - this.OpenRomMenuItem.Size = new System.Drawing.Size(151, 22); - this.OpenRomMenuItem.Text = "&Open ROM"; - this.OpenRomMenuItem.Click += new System.EventHandler(this.OpenRomMenuItem_Click); - // - // RecentRomSubMenu - // - this.RecentRomSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.FileSubMenu.Name = "FileSubMenu"; + this.FileSubMenu.Size = new System.Drawing.Size(37, 19); + this.FileSubMenu.Text = "&File"; + this.FileSubMenu.DropDownOpened += new System.EventHandler(this.FileSubMenu_DropDownOpened); + // + // OpenRomMenuItem + // + this.OpenRomMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.OpenFile; + this.OpenRomMenuItem.Name = "OpenRomMenuItem"; + this.OpenRomMenuItem.Size = new System.Drawing.Size(159, 22); + this.OpenRomMenuItem.Text = "&Open ROM"; + this.OpenRomMenuItem.Click += new System.EventHandler(this.OpenRomMenuItem_Click); + // + // RecentRomSubMenu + // + this.RecentRomSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.toolStripSeparator3}); - this.RecentRomSubMenu.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.Recent; - this.RecentRomSubMenu.Name = "RecentRomSubMenu"; - this.RecentRomSubMenu.Size = new System.Drawing.Size(151, 22); - this.RecentRomSubMenu.Text = "&Recent ROM"; - this.RecentRomSubMenu.DropDownOpened += new System.EventHandler(this.RecentRomMenuItem_DropDownOpened); - // - // toolStripSeparator3 - // - this.toolStripSeparator3.Name = "toolStripSeparator3"; - this.toolStripSeparator3.Size = new System.Drawing.Size(57, 6); - // - // OpenAdvancedMenuItem - // - this.OpenAdvancedMenuItem.Name = "OpenAdvancedMenuItem"; - this.OpenAdvancedMenuItem.Size = new System.Drawing.Size(151, 22); - this.OpenAdvancedMenuItem.Text = "Open Ad&vanced"; - this.OpenAdvancedMenuItem.Click += new System.EventHandler(this.OpenAdvancedMenuItem_Click); - // - // CloseRomMenuItem - // - this.CloseRomMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.Close; - this.CloseRomMenuItem.Name = "CloseRomMenuItem"; - this.CloseRomMenuItem.Size = new System.Drawing.Size(151, 22); - this.CloseRomMenuItem.Text = "&Close ROM"; - this.CloseRomMenuItem.Click += new System.EventHandler(this.CloseRomMenuItem_Click); - // - // toolStripMenuItem1 - // - this.toolStripMenuItem1.Name = "toolStripMenuItem1"; - this.toolStripMenuItem1.Size = new System.Drawing.Size(148, 6); - // - // SaveStateSubMenu - // - this.SaveStateSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.RecentRomSubMenu.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.Recent; + this.RecentRomSubMenu.Name = "RecentRomSubMenu"; + this.RecentRomSubMenu.Size = new System.Drawing.Size(159, 22); + this.RecentRomSubMenu.Text = "&Recent ROM"; + this.RecentRomSubMenu.DropDownOpened += new System.EventHandler(this.RecentRomMenuItem_DropDownOpened); + // + // toolStripSeparator3 + // + this.toolStripSeparator3.Name = "toolStripSeparator3"; + this.toolStripSeparator3.Size = new System.Drawing.Size(57, 6); + // + // OpenAdvancedMenuItem + // + this.OpenAdvancedMenuItem.Name = "OpenAdvancedMenuItem"; + this.OpenAdvancedMenuItem.Size = new System.Drawing.Size(159, 22); + this.OpenAdvancedMenuItem.Text = "Open Ad&vanced"; + this.OpenAdvancedMenuItem.Click += new System.EventHandler(this.OpenAdvancedMenuItem_Click); + // + // CloseRomMenuItem + // + this.CloseRomMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.Close; + this.CloseRomMenuItem.Name = "CloseRomMenuItem"; + this.CloseRomMenuItem.Size = new System.Drawing.Size(159, 22); + this.CloseRomMenuItem.Text = "&Close ROM"; + this.CloseRomMenuItem.Click += new System.EventHandler(this.CloseRomMenuItem_Click); + // + // toolStripMenuItem1 + // + this.toolStripMenuItem1.Name = "toolStripMenuItem1"; + this.toolStripMenuItem1.Size = new System.Drawing.Size(156, 6); + // + // SaveStateSubMenu + // + this.SaveStateSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.SaveState1MenuItem, this.SaveState2MenuItem, this.SaveState3MenuItem, @@ -571,96 +571,96 @@ this.SaveState0MenuItem, this.toolStripSeparator6, this.SaveNamedStateMenuItem}); - this.SaveStateSubMenu.Name = "SaveStateSubMenu"; - this.SaveStateSubMenu.Size = new System.Drawing.Size(151, 22); - this.SaveStateSubMenu.Text = "&Save State"; - this.SaveStateSubMenu.DropDownOpened += new System.EventHandler(this.SaveStateSubMenu_DropDownOpened); - // - // SaveState1MenuItem - // - this.SaveState1MenuItem.Name = "SaveState1MenuItem"; - this.SaveState1MenuItem.Size = new System.Drawing.Size(175, 22); - this.SaveState1MenuItem.Text = "1"; - this.SaveState1MenuItem.Click += new System.EventHandler(this.Savestate1MenuItem_Click); - // - // SaveState2MenuItem - // - this.SaveState2MenuItem.Name = "SaveState2MenuItem"; - this.SaveState2MenuItem.Size = new System.Drawing.Size(175, 22); - this.SaveState2MenuItem.Text = "2"; - this.SaveState2MenuItem.Click += new System.EventHandler(this.Savestate2MenuItem_Click); - // - // SaveState3MenuItem - // - this.SaveState3MenuItem.Name = "SaveState3MenuItem"; - this.SaveState3MenuItem.Size = new System.Drawing.Size(175, 22); - this.SaveState3MenuItem.Text = "3"; - this.SaveState3MenuItem.Click += new System.EventHandler(this.Savestate3MenuItem_Click); - // - // SaveState4MenuItem - // - this.SaveState4MenuItem.Name = "SaveState4MenuItem"; - this.SaveState4MenuItem.Size = new System.Drawing.Size(175, 22); - this.SaveState4MenuItem.Text = "4"; - this.SaveState4MenuItem.Click += new System.EventHandler(this.Savestate4MenuItem_Click); - // - // SaveState5MenuItem - // - this.SaveState5MenuItem.Name = "SaveState5MenuItem"; - this.SaveState5MenuItem.Size = new System.Drawing.Size(175, 22); - this.SaveState5MenuItem.Text = "5"; - this.SaveState5MenuItem.Click += new System.EventHandler(this.Savestate5MenuItem_Click); - // - // SaveState6MenuItem - // - this.SaveState6MenuItem.Name = "SaveState6MenuItem"; - this.SaveState6MenuItem.Size = new System.Drawing.Size(175, 22); - this.SaveState6MenuItem.Text = "6"; - this.SaveState6MenuItem.Click += new System.EventHandler(this.Savestate6MenuItem_Click); - // - // SaveState7MenuItem - // - this.SaveState7MenuItem.Name = "SaveState7MenuItem"; - this.SaveState7MenuItem.Size = new System.Drawing.Size(175, 22); - this.SaveState7MenuItem.Text = "7"; - this.SaveState7MenuItem.Click += new System.EventHandler(this.Savestate7MenuItem_Click); - // - // SaveState8MenuItem - // - this.SaveState8MenuItem.Name = "SaveState8MenuItem"; - this.SaveState8MenuItem.Size = new System.Drawing.Size(175, 22); - this.SaveState8MenuItem.Text = "8"; - this.SaveState8MenuItem.Click += new System.EventHandler(this.Savestate8MenuItem_Click); - // - // SaveState9MenuItem - // - this.SaveState9MenuItem.Name = "SaveState9MenuItem"; - this.SaveState9MenuItem.Size = new System.Drawing.Size(175, 22); - this.SaveState9MenuItem.Text = "9"; - this.SaveState9MenuItem.Click += new System.EventHandler(this.Savestate9MenuItem_Click); - // - // SaveState0MenuItem - // - this.SaveState0MenuItem.Name = "SaveState0MenuItem"; - this.SaveState0MenuItem.Size = new System.Drawing.Size(175, 22); - this.SaveState0MenuItem.Text = "0"; - this.SaveState0MenuItem.Click += new System.EventHandler(this.Savestate0MenuItem_Click); - // - // toolStripSeparator6 - // - this.toolStripSeparator6.Name = "toolStripSeparator6"; - this.toolStripSeparator6.Size = new System.Drawing.Size(172, 6); - // - // SaveNamedStateMenuItem - // - this.SaveNamedStateMenuItem.Name = "SaveNamedStateMenuItem"; - this.SaveNamedStateMenuItem.Size = new System.Drawing.Size(175, 22); - this.SaveNamedStateMenuItem.Text = "Save Named State..."; - this.SaveNamedStateMenuItem.Click += new System.EventHandler(this.SaveNamedStateMenuItem_Click); - // - // LoadStateSubMenu - // - this.LoadStateSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.SaveStateSubMenu.Name = "SaveStateSubMenu"; + this.SaveStateSubMenu.Size = new System.Drawing.Size(159, 22); + this.SaveStateSubMenu.Text = "&Save State"; + this.SaveStateSubMenu.DropDownOpened += new System.EventHandler(this.SaveStateSubMenu_DropDownOpened); + // + // SaveState1MenuItem + // + this.SaveState1MenuItem.Name = "SaveState1MenuItem"; + this.SaveState1MenuItem.Size = new System.Drawing.Size(178, 22); + this.SaveState1MenuItem.Text = "1"; + this.SaveState1MenuItem.Click += new System.EventHandler(this.Savestate1MenuItem_Click); + // + // SaveState2MenuItem + // + this.SaveState2MenuItem.Name = "SaveState2MenuItem"; + this.SaveState2MenuItem.Size = new System.Drawing.Size(178, 22); + this.SaveState2MenuItem.Text = "2"; + this.SaveState2MenuItem.Click += new System.EventHandler(this.Savestate2MenuItem_Click); + // + // SaveState3MenuItem + // + this.SaveState3MenuItem.Name = "SaveState3MenuItem"; + this.SaveState3MenuItem.Size = new System.Drawing.Size(178, 22); + this.SaveState3MenuItem.Text = "3"; + this.SaveState3MenuItem.Click += new System.EventHandler(this.Savestate3MenuItem_Click); + // + // SaveState4MenuItem + // + this.SaveState4MenuItem.Name = "SaveState4MenuItem"; + this.SaveState4MenuItem.Size = new System.Drawing.Size(178, 22); + this.SaveState4MenuItem.Text = "4"; + this.SaveState4MenuItem.Click += new System.EventHandler(this.Savestate4MenuItem_Click); + // + // SaveState5MenuItem + // + this.SaveState5MenuItem.Name = "SaveState5MenuItem"; + this.SaveState5MenuItem.Size = new System.Drawing.Size(178, 22); + this.SaveState5MenuItem.Text = "5"; + this.SaveState5MenuItem.Click += new System.EventHandler(this.Savestate5MenuItem_Click); + // + // SaveState6MenuItem + // + this.SaveState6MenuItem.Name = "SaveState6MenuItem"; + this.SaveState6MenuItem.Size = new System.Drawing.Size(178, 22); + this.SaveState6MenuItem.Text = "6"; + this.SaveState6MenuItem.Click += new System.EventHandler(this.Savestate6MenuItem_Click); + // + // SaveState7MenuItem + // + this.SaveState7MenuItem.Name = "SaveState7MenuItem"; + this.SaveState7MenuItem.Size = new System.Drawing.Size(178, 22); + this.SaveState7MenuItem.Text = "7"; + this.SaveState7MenuItem.Click += new System.EventHandler(this.Savestate7MenuItem_Click); + // + // SaveState8MenuItem + // + this.SaveState8MenuItem.Name = "SaveState8MenuItem"; + this.SaveState8MenuItem.Size = new System.Drawing.Size(178, 22); + this.SaveState8MenuItem.Text = "8"; + this.SaveState8MenuItem.Click += new System.EventHandler(this.Savestate8MenuItem_Click); + // + // SaveState9MenuItem + // + this.SaveState9MenuItem.Name = "SaveState9MenuItem"; + this.SaveState9MenuItem.Size = new System.Drawing.Size(178, 22); + this.SaveState9MenuItem.Text = "9"; + this.SaveState9MenuItem.Click += new System.EventHandler(this.Savestate9MenuItem_Click); + // + // SaveState0MenuItem + // + this.SaveState0MenuItem.Name = "SaveState0MenuItem"; + this.SaveState0MenuItem.Size = new System.Drawing.Size(178, 22); + this.SaveState0MenuItem.Text = "0"; + this.SaveState0MenuItem.Click += new System.EventHandler(this.Savestate0MenuItem_Click); + // + // toolStripSeparator6 + // + this.toolStripSeparator6.Name = "toolStripSeparator6"; + this.toolStripSeparator6.Size = new System.Drawing.Size(175, 6); + // + // SaveNamedStateMenuItem + // + this.SaveNamedStateMenuItem.Name = "SaveNamedStateMenuItem"; + this.SaveNamedStateMenuItem.Size = new System.Drawing.Size(178, 22); + this.SaveNamedStateMenuItem.Text = "Save Named State..."; + this.SaveNamedStateMenuItem.Click += new System.EventHandler(this.SaveNamedStateMenuItem_Click); + // + // LoadStateSubMenu + // + this.LoadStateSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.LoadState1MenuItem, this.LoadState2MenuItem, this.LoadState3MenuItem, @@ -675,108 +675,108 @@ this.LoadNamedStateMenuItem, this.toolStripSeparator21, this.AutoloadLastSlotMenuItem}); - this.LoadStateSubMenu.Name = "LoadStateSubMenu"; - this.LoadStateSubMenu.Size = new System.Drawing.Size(151, 22); - this.LoadStateSubMenu.Text = "&Load State"; - this.LoadStateSubMenu.DropDownOpened += new System.EventHandler(this.LoadStateSubMenu_DropDownOpened); - // - // LoadState1MenuItem - // - this.LoadState1MenuItem.Name = "LoadState1MenuItem"; - this.LoadState1MenuItem.Size = new System.Drawing.Size(174, 22); - this.LoadState1MenuItem.Text = "1"; - this.LoadState1MenuItem.Click += new System.EventHandler(this.Loadstate1MenuItem_Click); - // - // LoadState2MenuItem - // - this.LoadState2MenuItem.Name = "LoadState2MenuItem"; - this.LoadState2MenuItem.Size = new System.Drawing.Size(174, 22); - this.LoadState2MenuItem.Text = "2"; - this.LoadState2MenuItem.Click += new System.EventHandler(this.Loadstate2MenuItem_Click); - // - // LoadState3MenuItem - // - this.LoadState3MenuItem.Name = "LoadState3MenuItem"; - this.LoadState3MenuItem.Size = new System.Drawing.Size(174, 22); - this.LoadState3MenuItem.Text = "3"; - this.LoadState3MenuItem.Click += new System.EventHandler(this.Loadstate3MenuItem_Click); - // - // LoadState4MenuItem - // - this.LoadState4MenuItem.Name = "LoadState4MenuItem"; - this.LoadState4MenuItem.Size = new System.Drawing.Size(174, 22); - this.LoadState4MenuItem.Text = "4"; - this.LoadState4MenuItem.Click += new System.EventHandler(this.Loadstate4MenuItem_Click); - // - // LoadState5MenuItem - // - this.LoadState5MenuItem.Name = "LoadState5MenuItem"; - this.LoadState5MenuItem.Size = new System.Drawing.Size(174, 22); - this.LoadState5MenuItem.Text = "5"; - this.LoadState5MenuItem.Click += new System.EventHandler(this.Loadstate5MenuItem_Click); - // - // LoadState6MenuItem - // - this.LoadState6MenuItem.Name = "LoadState6MenuItem"; - this.LoadState6MenuItem.Size = new System.Drawing.Size(174, 22); - this.LoadState6MenuItem.Text = "6"; - this.LoadState6MenuItem.Click += new System.EventHandler(this.Loadstate6MenuItem_Click); - // - // LoadState7MenuItem - // - this.LoadState7MenuItem.Name = "LoadState7MenuItem"; - this.LoadState7MenuItem.Size = new System.Drawing.Size(174, 22); - this.LoadState7MenuItem.Text = "7"; - this.LoadState7MenuItem.Click += new System.EventHandler(this.Loadstate7MenuItem_Click); - // - // LoadState8MenuItem - // - this.LoadState8MenuItem.Name = "LoadState8MenuItem"; - this.LoadState8MenuItem.Size = new System.Drawing.Size(174, 22); - this.LoadState8MenuItem.Text = "8"; - this.LoadState8MenuItem.Click += new System.EventHandler(this.Loadstate8MenuItem_Click); - // - // LoadState9MenuItem - // - this.LoadState9MenuItem.Name = "LoadState9MenuItem"; - this.LoadState9MenuItem.Size = new System.Drawing.Size(174, 22); - this.LoadState9MenuItem.Text = "9"; - this.LoadState9MenuItem.Click += new System.EventHandler(this.Loadstate9MenuItem_Click); - // - // LoadState0MenuItem - // - this.LoadState0MenuItem.Name = "LoadState0MenuItem"; - this.LoadState0MenuItem.Size = new System.Drawing.Size(174, 22); - this.LoadState0MenuItem.Text = "0"; - this.LoadState0MenuItem.Click += new System.EventHandler(this.Loadstate0MenuItem_Click); - // - // toolStripSeparator7 - // - this.toolStripSeparator7.Name = "toolStripSeparator7"; - this.toolStripSeparator7.Size = new System.Drawing.Size(171, 6); - // - // LoadNamedStateMenuItem - // - this.LoadNamedStateMenuItem.Name = "LoadNamedStateMenuItem"; - this.LoadNamedStateMenuItem.Size = new System.Drawing.Size(174, 22); - this.LoadNamedStateMenuItem.Text = "Load Named State..."; - this.LoadNamedStateMenuItem.Click += new System.EventHandler(this.LoadNamedStateMenuItem_Click); - // - // toolStripSeparator21 - // - this.toolStripSeparator21.Name = "toolStripSeparator21"; - this.toolStripSeparator21.Size = new System.Drawing.Size(171, 6); - // - // AutoloadLastSlotMenuItem - // - this.AutoloadLastSlotMenuItem.Name = "AutoloadLastSlotMenuItem"; - this.AutoloadLastSlotMenuItem.Size = new System.Drawing.Size(174, 22); - this.AutoloadLastSlotMenuItem.Text = "Autoload last Slot"; - this.AutoloadLastSlotMenuItem.Click += new System.EventHandler(this.AutoloadLastSlotMenuItem_Click); - // - // SaveSlotSubMenu - // - this.SaveSlotSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.LoadStateSubMenu.Name = "LoadStateSubMenu"; + this.LoadStateSubMenu.Size = new System.Drawing.Size(159, 22); + this.LoadStateSubMenu.Text = "&Load State"; + this.LoadStateSubMenu.DropDownOpened += new System.EventHandler(this.LoadStateSubMenu_DropDownOpened); + // + // LoadState1MenuItem + // + this.LoadState1MenuItem.Name = "LoadState1MenuItem"; + this.LoadState1MenuItem.Size = new System.Drawing.Size(180, 22); + this.LoadState1MenuItem.Text = "1"; + this.LoadState1MenuItem.Click += new System.EventHandler(this.Loadstate1MenuItem_Click); + // + // LoadState2MenuItem + // + this.LoadState2MenuItem.Name = "LoadState2MenuItem"; + this.LoadState2MenuItem.Size = new System.Drawing.Size(180, 22); + this.LoadState2MenuItem.Text = "2"; + this.LoadState2MenuItem.Click += new System.EventHandler(this.Loadstate2MenuItem_Click); + // + // LoadState3MenuItem + // + this.LoadState3MenuItem.Name = "LoadState3MenuItem"; + this.LoadState3MenuItem.Size = new System.Drawing.Size(180, 22); + this.LoadState3MenuItem.Text = "3"; + this.LoadState3MenuItem.Click += new System.EventHandler(this.Loadstate3MenuItem_Click); + // + // LoadState4MenuItem + // + this.LoadState4MenuItem.Name = "LoadState4MenuItem"; + this.LoadState4MenuItem.Size = new System.Drawing.Size(180, 22); + this.LoadState4MenuItem.Text = "4"; + this.LoadState4MenuItem.Click += new System.EventHandler(this.Loadstate4MenuItem_Click); + // + // LoadState5MenuItem + // + this.LoadState5MenuItem.Name = "LoadState5MenuItem"; + this.LoadState5MenuItem.Size = new System.Drawing.Size(180, 22); + this.LoadState5MenuItem.Text = "5"; + this.LoadState5MenuItem.Click += new System.EventHandler(this.Loadstate5MenuItem_Click); + // + // LoadState6MenuItem + // + this.LoadState6MenuItem.Name = "LoadState6MenuItem"; + this.LoadState6MenuItem.Size = new System.Drawing.Size(180, 22); + this.LoadState6MenuItem.Text = "6"; + this.LoadState6MenuItem.Click += new System.EventHandler(this.Loadstate6MenuItem_Click); + // + // LoadState7MenuItem + // + this.LoadState7MenuItem.Name = "LoadState7MenuItem"; + this.LoadState7MenuItem.Size = new System.Drawing.Size(180, 22); + this.LoadState7MenuItem.Text = "7"; + this.LoadState7MenuItem.Click += new System.EventHandler(this.Loadstate7MenuItem_Click); + // + // LoadState8MenuItem + // + this.LoadState8MenuItem.Name = "LoadState8MenuItem"; + this.LoadState8MenuItem.Size = new System.Drawing.Size(180, 22); + this.LoadState8MenuItem.Text = "8"; + this.LoadState8MenuItem.Click += new System.EventHandler(this.Loadstate8MenuItem_Click); + // + // LoadState9MenuItem + // + this.LoadState9MenuItem.Name = "LoadState9MenuItem"; + this.LoadState9MenuItem.Size = new System.Drawing.Size(180, 22); + this.LoadState9MenuItem.Text = "9"; + this.LoadState9MenuItem.Click += new System.EventHandler(this.Loadstate9MenuItem_Click); + // + // LoadState0MenuItem + // + this.LoadState0MenuItem.Name = "LoadState0MenuItem"; + this.LoadState0MenuItem.Size = new System.Drawing.Size(180, 22); + this.LoadState0MenuItem.Text = "0"; + this.LoadState0MenuItem.Click += new System.EventHandler(this.Loadstate0MenuItem_Click); + // + // toolStripSeparator7 + // + this.toolStripSeparator7.Name = "toolStripSeparator7"; + this.toolStripSeparator7.Size = new System.Drawing.Size(177, 6); + // + // LoadNamedStateMenuItem + // + this.LoadNamedStateMenuItem.Name = "LoadNamedStateMenuItem"; + this.LoadNamedStateMenuItem.Size = new System.Drawing.Size(180, 22); + this.LoadNamedStateMenuItem.Text = "Load Named State..."; + this.LoadNamedStateMenuItem.Click += new System.EventHandler(this.LoadNamedStateMenuItem_Click); + // + // toolStripSeparator21 + // + this.toolStripSeparator21.Name = "toolStripSeparator21"; + this.toolStripSeparator21.Size = new System.Drawing.Size(177, 6); + // + // AutoloadLastSlotMenuItem + // + this.AutoloadLastSlotMenuItem.Name = "AutoloadLastSlotMenuItem"; + this.AutoloadLastSlotMenuItem.Size = new System.Drawing.Size(180, 22); + this.AutoloadLastSlotMenuItem.Text = "Autoload last Slot"; + this.AutoloadLastSlotMenuItem.Click += new System.EventHandler(this.AutoloadLastSlotMenuItem_Click); + // + // SaveSlotSubMenu + // + this.SaveSlotSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.SelectSlot0MenuItem, this.SelectSlot1MenuItem, this.SelectSlot2MenuItem, @@ -792,140 +792,140 @@ this.toolStripSeparator5, this.SaveToCurrentSlotMenuItem, this.LoadCurrentSlotMenuItem}); - this.SaveSlotSubMenu.Name = "SaveSlotSubMenu"; - this.SaveSlotSubMenu.Size = new System.Drawing.Size(151, 22); - this.SaveSlotSubMenu.Text = "Save S&lot"; - this.SaveSlotSubMenu.DropDownOpened += new System.EventHandler(this.SaveSlotSubMenu_DropDownOpened); - // - // SelectSlot0MenuItem - // - this.SelectSlot0MenuItem.Name = "SelectSlot0MenuItem"; - this.SelectSlot0MenuItem.Size = new System.Drawing.Size(172, 22); - this.SelectSlot0MenuItem.Text = "Select Slot 0"; - this.SelectSlot0MenuItem.Click += new System.EventHandler(this.SelectSlotMenuItems_Click); - // - // SelectSlot1MenuItem - // - this.SelectSlot1MenuItem.Name = "SelectSlot1MenuItem"; - this.SelectSlot1MenuItem.Size = new System.Drawing.Size(172, 22); - this.SelectSlot1MenuItem.Text = "Select Slot 1"; - this.SelectSlot1MenuItem.Click += new System.EventHandler(this.SelectSlotMenuItems_Click); - // - // SelectSlot2MenuItem - // - this.SelectSlot2MenuItem.Name = "SelectSlot2MenuItem"; - this.SelectSlot2MenuItem.Size = new System.Drawing.Size(172, 22); - this.SelectSlot2MenuItem.Text = "Select Slot 2"; - this.SelectSlot2MenuItem.Click += new System.EventHandler(this.SelectSlotMenuItems_Click); - // - // SelectSlot3MenuItem - // - this.SelectSlot3MenuItem.Name = "SelectSlot3MenuItem"; - this.SelectSlot3MenuItem.Size = new System.Drawing.Size(172, 22); - this.SelectSlot3MenuItem.Text = "Select Slot 3"; - this.SelectSlot3MenuItem.Click += new System.EventHandler(this.SelectSlotMenuItems_Click); - // - // SelectSlot4MenuItem - // - this.SelectSlot4MenuItem.Name = "SelectSlot4MenuItem"; - this.SelectSlot4MenuItem.Size = new System.Drawing.Size(172, 22); - this.SelectSlot4MenuItem.Text = "Select Slot 4"; - this.SelectSlot4MenuItem.Click += new System.EventHandler(this.SelectSlotMenuItems_Click); - // - // SelectSlot5MenuItem - // - this.SelectSlot5MenuItem.Name = "SelectSlot5MenuItem"; - this.SelectSlot5MenuItem.Size = new System.Drawing.Size(172, 22); - this.SelectSlot5MenuItem.Text = "Select Slot 5"; - this.SelectSlot5MenuItem.Click += new System.EventHandler(this.SelectSlotMenuItems_Click); - // - // SelectSlot6MenuItem - // - this.SelectSlot6MenuItem.Name = "SelectSlot6MenuItem"; - this.SelectSlot6MenuItem.Size = new System.Drawing.Size(172, 22); - this.SelectSlot6MenuItem.Text = "Select Slot 6"; - this.SelectSlot6MenuItem.Click += new System.EventHandler(this.SelectSlotMenuItems_Click); - // - // SelectSlot7MenuItem - // - this.SelectSlot7MenuItem.Name = "SelectSlot7MenuItem"; - this.SelectSlot7MenuItem.Size = new System.Drawing.Size(172, 22); - this.SelectSlot7MenuItem.Text = "Select Slot 7"; - this.SelectSlot7MenuItem.Click += new System.EventHandler(this.SelectSlotMenuItems_Click); - // - // SelectSlot8MenuItem - // - this.SelectSlot8MenuItem.Name = "SelectSlot8MenuItem"; - this.SelectSlot8MenuItem.Size = new System.Drawing.Size(172, 22); - this.SelectSlot8MenuItem.Text = "Select Slot 8"; - this.SelectSlot8MenuItem.Click += new System.EventHandler(this.SelectSlotMenuItems_Click); - // - // SelectSlot9MenuItem - // - this.SelectSlot9MenuItem.Name = "SelectSlot9MenuItem"; - this.SelectSlot9MenuItem.Size = new System.Drawing.Size(172, 22); - this.SelectSlot9MenuItem.Text = "Select Slot 9"; - this.SelectSlot9MenuItem.Click += new System.EventHandler(this.SelectSlotMenuItems_Click); - // - // PreviousSlotMenuItem - // - this.PreviousSlotMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.MoveLeft; - this.PreviousSlotMenuItem.Name = "PreviousSlotMenuItem"; - this.PreviousSlotMenuItem.Size = new System.Drawing.Size(172, 22); - this.PreviousSlotMenuItem.Text = "Previous Slot"; - this.PreviousSlotMenuItem.Click += new System.EventHandler(this.PreviousSlotMenuItem_Click); - // - // NextSlotMenuItem - // - this.NextSlotMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.MoveRight; - this.NextSlotMenuItem.Name = "NextSlotMenuItem"; - this.NextSlotMenuItem.Size = new System.Drawing.Size(172, 22); - this.NextSlotMenuItem.Text = "Next Slot"; - this.NextSlotMenuItem.Click += new System.EventHandler(this.NextSlotMenuItem_Click); - // - // toolStripSeparator5 - // - this.toolStripSeparator5.Name = "toolStripSeparator5"; - this.toolStripSeparator5.Size = new System.Drawing.Size(169, 6); - // - // SaveToCurrentSlotMenuItem - // - this.SaveToCurrentSlotMenuItem.Name = "SaveToCurrentSlotMenuItem"; - this.SaveToCurrentSlotMenuItem.Size = new System.Drawing.Size(172, 22); - this.SaveToCurrentSlotMenuItem.Text = "Save to Current Slot"; - this.SaveToCurrentSlotMenuItem.Click += new System.EventHandler(this.SaveToCurrentSlotMenuItem_Click); - // - // LoadCurrentSlotMenuItem - // - this.LoadCurrentSlotMenuItem.Name = "LoadCurrentSlotMenuItem"; - this.LoadCurrentSlotMenuItem.Size = new System.Drawing.Size(172, 22); - this.LoadCurrentSlotMenuItem.Text = "Load Current Slot"; - this.LoadCurrentSlotMenuItem.Click += new System.EventHandler(this.LoadCurrentSlotMenuItem_Click); - // - // SaveRAMSubMenu - // - this.SaveRAMSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.SaveSlotSubMenu.Name = "SaveSlotSubMenu"; + this.SaveSlotSubMenu.Size = new System.Drawing.Size(159, 22); + this.SaveSlotSubMenu.Text = "Save S&lot"; + this.SaveSlotSubMenu.DropDownOpened += new System.EventHandler(this.SaveSlotSubMenu_DropDownOpened); + // + // SelectSlot0MenuItem + // + this.SelectSlot0MenuItem.Name = "SelectSlot0MenuItem"; + this.SelectSlot0MenuItem.Size = new System.Drawing.Size(178, 22); + this.SelectSlot0MenuItem.Text = "Select Slot 0"; + this.SelectSlot0MenuItem.Click += new System.EventHandler(this.SelectSlotMenuItems_Click); + // + // SelectSlot1MenuItem + // + this.SelectSlot1MenuItem.Name = "SelectSlot1MenuItem"; + this.SelectSlot1MenuItem.Size = new System.Drawing.Size(178, 22); + this.SelectSlot1MenuItem.Text = "Select Slot 1"; + this.SelectSlot1MenuItem.Click += new System.EventHandler(this.SelectSlotMenuItems_Click); + // + // SelectSlot2MenuItem + // + this.SelectSlot2MenuItem.Name = "SelectSlot2MenuItem"; + this.SelectSlot2MenuItem.Size = new System.Drawing.Size(178, 22); + this.SelectSlot2MenuItem.Text = "Select Slot 2"; + this.SelectSlot2MenuItem.Click += new System.EventHandler(this.SelectSlotMenuItems_Click); + // + // SelectSlot3MenuItem + // + this.SelectSlot3MenuItem.Name = "SelectSlot3MenuItem"; + this.SelectSlot3MenuItem.Size = new System.Drawing.Size(178, 22); + this.SelectSlot3MenuItem.Text = "Select Slot 3"; + this.SelectSlot3MenuItem.Click += new System.EventHandler(this.SelectSlotMenuItems_Click); + // + // SelectSlot4MenuItem + // + this.SelectSlot4MenuItem.Name = "SelectSlot4MenuItem"; + this.SelectSlot4MenuItem.Size = new System.Drawing.Size(178, 22); + this.SelectSlot4MenuItem.Text = "Select Slot 4"; + this.SelectSlot4MenuItem.Click += new System.EventHandler(this.SelectSlotMenuItems_Click); + // + // SelectSlot5MenuItem + // + this.SelectSlot5MenuItem.Name = "SelectSlot5MenuItem"; + this.SelectSlot5MenuItem.Size = new System.Drawing.Size(178, 22); + this.SelectSlot5MenuItem.Text = "Select Slot 5"; + this.SelectSlot5MenuItem.Click += new System.EventHandler(this.SelectSlotMenuItems_Click); + // + // SelectSlot6MenuItem + // + this.SelectSlot6MenuItem.Name = "SelectSlot6MenuItem"; + this.SelectSlot6MenuItem.Size = new System.Drawing.Size(178, 22); + this.SelectSlot6MenuItem.Text = "Select Slot 6"; + this.SelectSlot6MenuItem.Click += new System.EventHandler(this.SelectSlotMenuItems_Click); + // + // SelectSlot7MenuItem + // + this.SelectSlot7MenuItem.Name = "SelectSlot7MenuItem"; + this.SelectSlot7MenuItem.Size = new System.Drawing.Size(178, 22); + this.SelectSlot7MenuItem.Text = "Select Slot 7"; + this.SelectSlot7MenuItem.Click += new System.EventHandler(this.SelectSlotMenuItems_Click); + // + // SelectSlot8MenuItem + // + this.SelectSlot8MenuItem.Name = "SelectSlot8MenuItem"; + this.SelectSlot8MenuItem.Size = new System.Drawing.Size(178, 22); + this.SelectSlot8MenuItem.Text = "Select Slot 8"; + this.SelectSlot8MenuItem.Click += new System.EventHandler(this.SelectSlotMenuItems_Click); + // + // SelectSlot9MenuItem + // + this.SelectSlot9MenuItem.Name = "SelectSlot9MenuItem"; + this.SelectSlot9MenuItem.Size = new System.Drawing.Size(178, 22); + this.SelectSlot9MenuItem.Text = "Select Slot 9"; + this.SelectSlot9MenuItem.Click += new System.EventHandler(this.SelectSlotMenuItems_Click); + // + // PreviousSlotMenuItem + // + this.PreviousSlotMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.MoveLeft; + this.PreviousSlotMenuItem.Name = "PreviousSlotMenuItem"; + this.PreviousSlotMenuItem.Size = new System.Drawing.Size(178, 22); + this.PreviousSlotMenuItem.Text = "Previous Slot"; + this.PreviousSlotMenuItem.Click += new System.EventHandler(this.PreviousSlotMenuItem_Click); + // + // NextSlotMenuItem + // + this.NextSlotMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.MoveRight; + this.NextSlotMenuItem.Name = "NextSlotMenuItem"; + this.NextSlotMenuItem.Size = new System.Drawing.Size(178, 22); + this.NextSlotMenuItem.Text = "Next Slot"; + this.NextSlotMenuItem.Click += new System.EventHandler(this.NextSlotMenuItem_Click); + // + // toolStripSeparator5 + // + this.toolStripSeparator5.Name = "toolStripSeparator5"; + this.toolStripSeparator5.Size = new System.Drawing.Size(175, 6); + // + // SaveToCurrentSlotMenuItem + // + this.SaveToCurrentSlotMenuItem.Name = "SaveToCurrentSlotMenuItem"; + this.SaveToCurrentSlotMenuItem.Size = new System.Drawing.Size(178, 22); + this.SaveToCurrentSlotMenuItem.Text = "Save to Current Slot"; + this.SaveToCurrentSlotMenuItem.Click += new System.EventHandler(this.SaveToCurrentSlotMenuItem_Click); + // + // LoadCurrentSlotMenuItem + // + this.LoadCurrentSlotMenuItem.Name = "LoadCurrentSlotMenuItem"; + this.LoadCurrentSlotMenuItem.Size = new System.Drawing.Size(178, 22); + this.LoadCurrentSlotMenuItem.Text = "Load Current Slot"; + this.LoadCurrentSlotMenuItem.Click += new System.EventHandler(this.LoadCurrentSlotMenuItem_Click); + // + // SaveRAMSubMenu + // + this.SaveRAMSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.FlushSaveRAMMenuItem}); - this.SaveRAMSubMenu.Name = "SaveRAMSubMenu"; - this.SaveRAMSubMenu.Size = new System.Drawing.Size(151, 22); - this.SaveRAMSubMenu.Text = "Save &RAM"; - this.SaveRAMSubMenu.DropDownOpened += new System.EventHandler(this.FlushSaveRAMSubMenu_DropDownOpened); - // - // FlushSaveRAMMenuItem - // - this.FlushSaveRAMMenuItem.Name = "FlushSaveRAMMenuItem"; - this.FlushSaveRAMMenuItem.Size = new System.Drawing.Size(150, 22); - this.FlushSaveRAMMenuItem.Text = "&Flush Save Ram"; - this.FlushSaveRAMMenuItem.Click += new System.EventHandler(this.FlushSaveRAMMenuItem_Click); - // - // toolStripMenuItem2 - // - this.toolStripMenuItem2.Name = "toolStripMenuItem2"; - this.toolStripMenuItem2.Size = new System.Drawing.Size(148, 6); - // - // MovieSubMenu - // - this.MovieSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.SaveRAMSubMenu.Name = "SaveRAMSubMenu"; + this.SaveRAMSubMenu.Size = new System.Drawing.Size(159, 22); + this.SaveRAMSubMenu.Text = "Save &RAM"; + this.SaveRAMSubMenu.DropDownOpened += new System.EventHandler(this.FlushSaveRAMSubMenu_DropDownOpened); + // + // FlushSaveRAMMenuItem + // + this.FlushSaveRAMMenuItem.Name = "FlushSaveRAMMenuItem"; + this.FlushSaveRAMMenuItem.Size = new System.Drawing.Size(156, 22); + this.FlushSaveRAMMenuItem.Text = "&Flush Save Ram"; + this.FlushSaveRAMMenuItem.Click += new System.EventHandler(this.FlushSaveRAMMenuItem_Click); + // + // toolStripMenuItem2 + // + this.toolStripMenuItem2.Name = "toolStripMenuItem2"; + this.toolStripMenuItem2.Size = new System.Drawing.Size(156, 6); + // + // MovieSubMenu + // + this.MovieSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.ReadonlyMenuItem, this.toolStripSeparator15, this.RecentMovieSubMenu, @@ -941,338 +941,338 @@ this.AutomaticallyBackupMoviesMenuItem, this.FullMovieLoadstatesMenuItem, this.MovieEndSubMenu}); - this.MovieSubMenu.Name = "MovieSubMenu"; - this.MovieSubMenu.Size = new System.Drawing.Size(151, 22); - this.MovieSubMenu.Text = "&Movie"; - this.MovieSubMenu.DropDownOpened += new System.EventHandler(this.MovieSubMenu_DropDownOpened); - // - // ReadonlyMenuItem - // - this.ReadonlyMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.ReadOnly; - this.ReadonlyMenuItem.Name = "ReadonlyMenuItem"; - this.ReadonlyMenuItem.Size = new System.Drawing.Size(211, 22); - this.ReadonlyMenuItem.Text = "Read-only"; - this.ReadonlyMenuItem.Click += new System.EventHandler(this.ReadonlyMenuItem_Click); - // - // toolStripSeparator15 - // - this.toolStripSeparator15.Name = "toolStripSeparator15"; - this.toolStripSeparator15.Size = new System.Drawing.Size(208, 6); - // - // RecentMovieSubMenu - // - this.RecentMovieSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.MovieSubMenu.Name = "MovieSubMenu"; + this.MovieSubMenu.Size = new System.Drawing.Size(159, 22); + this.MovieSubMenu.Text = "&Movie"; + this.MovieSubMenu.DropDownOpened += new System.EventHandler(this.MovieSubMenu_DropDownOpened); + // + // ReadonlyMenuItem + // + this.ReadonlyMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.ReadOnly; + this.ReadonlyMenuItem.Name = "ReadonlyMenuItem"; + this.ReadonlyMenuItem.Size = new System.Drawing.Size(231, 22); + this.ReadonlyMenuItem.Text = "Read-only"; + this.ReadonlyMenuItem.Click += new System.EventHandler(this.ReadonlyMenuItem_Click); + // + // toolStripSeparator15 + // + this.toolStripSeparator15.Name = "toolStripSeparator15"; + this.toolStripSeparator15.Size = new System.Drawing.Size(228, 6); + // + // RecentMovieSubMenu + // + this.RecentMovieSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.toolStripSeparator16}); - this.RecentMovieSubMenu.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.Recent; - this.RecentMovieSubMenu.Name = "RecentMovieSubMenu"; - this.RecentMovieSubMenu.Size = new System.Drawing.Size(211, 22); - this.RecentMovieSubMenu.Text = "Recent"; - this.RecentMovieSubMenu.DropDownOpened += new System.EventHandler(this.RecentMovieSubMenu_DropDownOpened); - // - // toolStripSeparator16 - // - this.toolStripSeparator16.Name = "toolStripSeparator16"; - this.toolStripSeparator16.Size = new System.Drawing.Size(57, 6); - // - // RecordMovieMenuItem - // - this.RecordMovieMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.RecordHS; - this.RecordMovieMenuItem.Name = "RecordMovieMenuItem"; - this.RecordMovieMenuItem.Size = new System.Drawing.Size(211, 22); - this.RecordMovieMenuItem.Text = "&Record Movie..."; - this.RecordMovieMenuItem.Click += new System.EventHandler(this.RecordMovieMenuItem_Click); - // - // PlayMovieMenuItem - // - this.PlayMovieMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.Play; - this.PlayMovieMenuItem.Name = "PlayMovieMenuItem"; - this.PlayMovieMenuItem.Size = new System.Drawing.Size(211, 22); - this.PlayMovieMenuItem.Text = "&Play Movie..."; - this.PlayMovieMenuItem.Click += new System.EventHandler(this.PlayMovieMenuItem_Click); - // - // StopMovieMenuItem - // - this.StopMovieMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.Stop; - this.StopMovieMenuItem.Name = "StopMovieMenuItem"; - this.StopMovieMenuItem.Size = new System.Drawing.Size(211, 22); - this.StopMovieMenuItem.Text = "Stop Movie"; - this.StopMovieMenuItem.Click += new System.EventHandler(this.StopMovieMenuItem_Click); - // - // PlayFromBeginningMenuItem - // - this.PlayFromBeginningMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.restart; - this.PlayFromBeginningMenuItem.Name = "PlayFromBeginningMenuItem"; - this.PlayFromBeginningMenuItem.Size = new System.Drawing.Size(211, 22); - this.PlayFromBeginningMenuItem.Text = "Play from Beginning"; - this.PlayFromBeginningMenuItem.Click += new System.EventHandler(this.PlayFromBeginningMenuItem_Click); - // - // ImportMoviesMenuItem - // - this.ImportMoviesMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.Import; - this.ImportMoviesMenuItem.Name = "ImportMoviesMenuItem"; - this.ImportMoviesMenuItem.Size = new System.Drawing.Size(211, 22); - this.ImportMoviesMenuItem.Text = "Import Movies..."; - this.ImportMoviesMenuItem.Click += new System.EventHandler(this.ImportMovieMenuItem_Click); - // - // SaveMovieMenuItem - // - this.SaveMovieMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.SaveAs; - this.SaveMovieMenuItem.Name = "SaveMovieMenuItem"; - this.SaveMovieMenuItem.Size = new System.Drawing.Size(211, 22); - this.SaveMovieMenuItem.Text = "&Save Movie"; - this.SaveMovieMenuItem.Click += new System.EventHandler(this.SaveMovieMenuItem_Click); - // - // SaveMovieAsMenuItem - // - this.SaveMovieAsMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.SaveAs; - this.SaveMovieAsMenuItem.Name = "SaveMovieAsMenuItem"; - this.SaveMovieAsMenuItem.Size = new System.Drawing.Size(211, 22); - this.SaveMovieAsMenuItem.Text = "Save Movie As..."; - this.SaveMovieAsMenuItem.Click += new System.EventHandler(this.SaveMovieAsMenuItem_Click); - // - // StopMovieWithoutSavingMenuItem - // - this.StopMovieWithoutSavingMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.Stop; - this.StopMovieWithoutSavingMenuItem.Name = "StopMovieWithoutSavingMenuItem"; - this.StopMovieWithoutSavingMenuItem.Size = new System.Drawing.Size(211, 22); - this.StopMovieWithoutSavingMenuItem.Text = "Stop Movie without Saving"; - this.StopMovieWithoutSavingMenuItem.Click += new System.EventHandler(this.StopMovieWithoutSavingMenuItem_Click); - // - // toolStripSeparator14 - // - this.toolStripSeparator14.Name = "toolStripSeparator14"; - this.toolStripSeparator14.Size = new System.Drawing.Size(208, 6); - // - // AutomaticallyBackupMoviesMenuItem - // - this.AutomaticallyBackupMoviesMenuItem.Name = "AutomaticallyBackupMoviesMenuItem"; - this.AutomaticallyBackupMoviesMenuItem.Size = new System.Drawing.Size(211, 22); - this.AutomaticallyBackupMoviesMenuItem.Text = "Automatically Backup Movies"; - this.AutomaticallyBackupMoviesMenuItem.Click += new System.EventHandler(this.AutomaticMovieBackupMenuItem_Click); - // - // FullMovieLoadstatesMenuItem - // - this.FullMovieLoadstatesMenuItem.Name = "FullMovieLoadstatesMenuItem"; - this.FullMovieLoadstatesMenuItem.Size = new System.Drawing.Size(211, 22); - this.FullMovieLoadstatesMenuItem.Text = "Full Movie Loadstates"; - this.FullMovieLoadstatesMenuItem.Click += new System.EventHandler(this.FullMovieLoadstatesMenuItem_Click); - // - // MovieEndSubMenu - // - this.MovieEndSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.RecentMovieSubMenu.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.Recent; + this.RecentMovieSubMenu.Name = "RecentMovieSubMenu"; + this.RecentMovieSubMenu.Size = new System.Drawing.Size(231, 22); + this.RecentMovieSubMenu.Text = "Recent"; + this.RecentMovieSubMenu.DropDownOpened += new System.EventHandler(this.RecentMovieSubMenu_DropDownOpened); + // + // toolStripSeparator16 + // + this.toolStripSeparator16.Name = "toolStripSeparator16"; + this.toolStripSeparator16.Size = new System.Drawing.Size(57, 6); + // + // RecordMovieMenuItem + // + this.RecordMovieMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.RecordHS; + this.RecordMovieMenuItem.Name = "RecordMovieMenuItem"; + this.RecordMovieMenuItem.Size = new System.Drawing.Size(231, 22); + this.RecordMovieMenuItem.Text = "&Record Movie..."; + this.RecordMovieMenuItem.Click += new System.EventHandler(this.RecordMovieMenuItem_Click); + // + // PlayMovieMenuItem + // + this.PlayMovieMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.Play; + this.PlayMovieMenuItem.Name = "PlayMovieMenuItem"; + this.PlayMovieMenuItem.Size = new System.Drawing.Size(231, 22); + this.PlayMovieMenuItem.Text = "&Play Movie..."; + this.PlayMovieMenuItem.Click += new System.EventHandler(this.PlayMovieMenuItem_Click); + // + // StopMovieMenuItem + // + this.StopMovieMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.Stop; + this.StopMovieMenuItem.Name = "StopMovieMenuItem"; + this.StopMovieMenuItem.Size = new System.Drawing.Size(231, 22); + this.StopMovieMenuItem.Text = "Stop Movie"; + this.StopMovieMenuItem.Click += new System.EventHandler(this.StopMovieMenuItem_Click); + // + // PlayFromBeginningMenuItem + // + this.PlayFromBeginningMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.restart; + this.PlayFromBeginningMenuItem.Name = "PlayFromBeginningMenuItem"; + this.PlayFromBeginningMenuItem.Size = new System.Drawing.Size(231, 22); + this.PlayFromBeginningMenuItem.Text = "Play from Beginning"; + this.PlayFromBeginningMenuItem.Click += new System.EventHandler(this.PlayFromBeginningMenuItem_Click); + // + // ImportMoviesMenuItem + // + this.ImportMoviesMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.Import; + this.ImportMoviesMenuItem.Name = "ImportMoviesMenuItem"; + this.ImportMoviesMenuItem.Size = new System.Drawing.Size(231, 22); + this.ImportMoviesMenuItem.Text = "Import Movies..."; + this.ImportMoviesMenuItem.Click += new System.EventHandler(this.ImportMovieMenuItem_Click); + // + // SaveMovieMenuItem + // + this.SaveMovieMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.SaveAs; + this.SaveMovieMenuItem.Name = "SaveMovieMenuItem"; + this.SaveMovieMenuItem.Size = new System.Drawing.Size(231, 22); + this.SaveMovieMenuItem.Text = "&Save Movie"; + this.SaveMovieMenuItem.Click += new System.EventHandler(this.SaveMovieMenuItem_Click); + // + // SaveMovieAsMenuItem + // + this.SaveMovieAsMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.SaveAs; + this.SaveMovieAsMenuItem.Name = "SaveMovieAsMenuItem"; + this.SaveMovieAsMenuItem.Size = new System.Drawing.Size(231, 22); + this.SaveMovieAsMenuItem.Text = "Save Movie As..."; + this.SaveMovieAsMenuItem.Click += new System.EventHandler(this.SaveMovieAsMenuItem_Click); + // + // StopMovieWithoutSavingMenuItem + // + this.StopMovieWithoutSavingMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.Stop; + this.StopMovieWithoutSavingMenuItem.Name = "StopMovieWithoutSavingMenuItem"; + this.StopMovieWithoutSavingMenuItem.Size = new System.Drawing.Size(231, 22); + this.StopMovieWithoutSavingMenuItem.Text = "Stop Movie without Saving"; + this.StopMovieWithoutSavingMenuItem.Click += new System.EventHandler(this.StopMovieWithoutSavingMenuItem_Click); + // + // toolStripSeparator14 + // + this.toolStripSeparator14.Name = "toolStripSeparator14"; + this.toolStripSeparator14.Size = new System.Drawing.Size(228, 6); + // + // AutomaticallyBackupMoviesMenuItem + // + this.AutomaticallyBackupMoviesMenuItem.Name = "AutomaticallyBackupMoviesMenuItem"; + this.AutomaticallyBackupMoviesMenuItem.Size = new System.Drawing.Size(231, 22); + this.AutomaticallyBackupMoviesMenuItem.Text = "Automatically Backup Movies"; + this.AutomaticallyBackupMoviesMenuItem.Click += new System.EventHandler(this.AutomaticMovieBackupMenuItem_Click); + // + // FullMovieLoadstatesMenuItem + // + this.FullMovieLoadstatesMenuItem.Name = "FullMovieLoadstatesMenuItem"; + this.FullMovieLoadstatesMenuItem.Size = new System.Drawing.Size(231, 22); + this.FullMovieLoadstatesMenuItem.Text = "Full Movie Loadstates"; + this.FullMovieLoadstatesMenuItem.Click += new System.EventHandler(this.FullMovieLoadstatesMenuItem_Click); + // + // MovieEndSubMenu + // + this.MovieEndSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.MovieEndFinishMenuItem, this.MovieEndRecordMenuItem, this.MovieEndStopMenuItem, this.MovieEndPauseMenuItem}); - this.MovieEndSubMenu.Name = "MovieEndSubMenu"; - this.MovieEndSubMenu.Size = new System.Drawing.Size(211, 22); - this.MovieEndSubMenu.Text = "On Movie End"; - this.MovieEndSubMenu.DropDownOpened += new System.EventHandler(this.MovieEndSubMenu_DropDownOpened); - // - // MovieEndFinishMenuItem - // - this.MovieEndFinishMenuItem.Name = "MovieEndFinishMenuItem"; - this.MovieEndFinishMenuItem.Size = new System.Drawing.Size(160, 22); - this.MovieEndFinishMenuItem.Text = "Switch to Finished"; - this.MovieEndFinishMenuItem.Click += new System.EventHandler(this.MovieEndFinishMenuItem_Click); - // - // MovieEndRecordMenuItem - // - this.MovieEndRecordMenuItem.Name = "MovieEndRecordMenuItem"; - this.MovieEndRecordMenuItem.Size = new System.Drawing.Size(160, 22); - this.MovieEndRecordMenuItem.Text = "Switch To Record"; - this.MovieEndRecordMenuItem.Click += new System.EventHandler(this.MovieEndRecordMenuItem_Click); - // - // MovieEndStopMenuItem - // - this.MovieEndStopMenuItem.Name = "MovieEndStopMenuItem"; - this.MovieEndStopMenuItem.Size = new System.Drawing.Size(160, 22); - this.MovieEndStopMenuItem.Text = "Stop"; - this.MovieEndStopMenuItem.Click += new System.EventHandler(this.MovieEndStopMenuItem_Click); - // - // MovieEndPauseMenuItem - // - this.MovieEndPauseMenuItem.Name = "MovieEndPauseMenuItem"; - this.MovieEndPauseMenuItem.Size = new System.Drawing.Size(160, 22); - this.MovieEndPauseMenuItem.Text = "Pause"; - this.MovieEndPauseMenuItem.Click += new System.EventHandler(this.MovieEndPauseMenuItem_Click); - // - // AVSubMenu - // - this.AVSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.MovieEndSubMenu.Name = "MovieEndSubMenu"; + this.MovieEndSubMenu.Size = new System.Drawing.Size(231, 22); + this.MovieEndSubMenu.Text = "On Movie End"; + this.MovieEndSubMenu.DropDownOpened += new System.EventHandler(this.MovieEndSubMenu_DropDownOpened); + // + // MovieEndFinishMenuItem + // + this.MovieEndFinishMenuItem.Name = "MovieEndFinishMenuItem"; + this.MovieEndFinishMenuItem.Size = new System.Drawing.Size(170, 22); + this.MovieEndFinishMenuItem.Text = "Switch to Finished"; + this.MovieEndFinishMenuItem.Click += new System.EventHandler(this.MovieEndFinishMenuItem_Click); + // + // MovieEndRecordMenuItem + // + this.MovieEndRecordMenuItem.Name = "MovieEndRecordMenuItem"; + this.MovieEndRecordMenuItem.Size = new System.Drawing.Size(170, 22); + this.MovieEndRecordMenuItem.Text = "Switch To Record"; + this.MovieEndRecordMenuItem.Click += new System.EventHandler(this.MovieEndRecordMenuItem_Click); + // + // MovieEndStopMenuItem + // + this.MovieEndStopMenuItem.Name = "MovieEndStopMenuItem"; + this.MovieEndStopMenuItem.Size = new System.Drawing.Size(170, 22); + this.MovieEndStopMenuItem.Text = "Stop"; + this.MovieEndStopMenuItem.Click += new System.EventHandler(this.MovieEndStopMenuItem_Click); + // + // MovieEndPauseMenuItem + // + this.MovieEndPauseMenuItem.Name = "MovieEndPauseMenuItem"; + this.MovieEndPauseMenuItem.Size = new System.Drawing.Size(170, 22); + this.MovieEndPauseMenuItem.Text = "Pause"; + this.MovieEndPauseMenuItem.Click += new System.EventHandler(this.MovieEndPauseMenuItem_Click); + // + // AVSubMenu + // + this.AVSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.RecordAVMenuItem, this.ConfigAndRecordAVMenuItem, this.StopAVIMenuItem, this.toolStripSeparator19, this.CaptureOSDMenuItem, this.SynclessRecordingMenuItem}); - this.AVSubMenu.Name = "AVSubMenu"; - this.AVSubMenu.Size = new System.Drawing.Size(151, 22); - this.AVSubMenu.Text = "&AVI/WAV"; - this.AVSubMenu.DropDownOpened += new System.EventHandler(this.AVSubMenu_DropDownOpened); - // - // RecordAVMenuItem - // - this.RecordAVMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.RecordHS; - this.RecordAVMenuItem.Name = "RecordAVMenuItem"; - this.RecordAVMenuItem.Size = new System.Drawing.Size(210, 22); - this.RecordAVMenuItem.Text = "&Record AVI/WAV"; - this.RecordAVMenuItem.Click += new System.EventHandler(this.RecordAVMenuItem_Click); - // - // ConfigAndRecordAVMenuItem - // - this.ConfigAndRecordAVMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.AVI; - this.ConfigAndRecordAVMenuItem.Name = "ConfigAndRecordAVMenuItem"; - this.ConfigAndRecordAVMenuItem.Size = new System.Drawing.Size(210, 22); - this.ConfigAndRecordAVMenuItem.Text = "Config and Record AVI/WAV"; - this.ConfigAndRecordAVMenuItem.Click += new System.EventHandler(this.ConfigAndRecordAVMenuItem_Click); - // - // StopAVIMenuItem - // - this.StopAVIMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.Stop; - this.StopAVIMenuItem.Name = "StopAVIMenuItem"; - this.StopAVIMenuItem.Size = new System.Drawing.Size(210, 22); - this.StopAVIMenuItem.Text = "&Stop AVI/WAV"; - this.StopAVIMenuItem.Click += new System.EventHandler(this.StopAVMenuItem_Click); - // - // toolStripSeparator19 - // - this.toolStripSeparator19.Name = "toolStripSeparator19"; - this.toolStripSeparator19.Size = new System.Drawing.Size(207, 6); - // - // CaptureOSDMenuItem - // - this.CaptureOSDMenuItem.Name = "CaptureOSDMenuItem"; - this.CaptureOSDMenuItem.Size = new System.Drawing.Size(210, 22); - this.CaptureOSDMenuItem.Text = "Capture OSD"; - this.CaptureOSDMenuItem.Click += new System.EventHandler(this.CaptureOSDMenuItem_Click); - // - // SynclessRecordingMenuItem - // - this.SynclessRecordingMenuItem.Name = "SynclessRecordingMenuItem"; - this.SynclessRecordingMenuItem.Size = new System.Drawing.Size(210, 22); - this.SynclessRecordingMenuItem.Text = "S&yncless Recording Tools"; - this.SynclessRecordingMenuItem.Click += new System.EventHandler(this.SynclessRecordingMenuItem_Click); - // - // ScreenshotSubMenu - // - this.ScreenshotSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.AVSubMenu.Name = "AVSubMenu"; + this.AVSubMenu.Size = new System.Drawing.Size(159, 22); + this.AVSubMenu.Text = "&AVI/WAV"; + this.AVSubMenu.DropDownOpened += new System.EventHandler(this.AVSubMenu_DropDownOpened); + // + // RecordAVMenuItem + // + this.RecordAVMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.RecordHS; + this.RecordAVMenuItem.Name = "RecordAVMenuItem"; + this.RecordAVMenuItem.Size = new System.Drawing.Size(223, 22); + this.RecordAVMenuItem.Text = "&Record AVI/WAV"; + this.RecordAVMenuItem.Click += new System.EventHandler(this.RecordAVMenuItem_Click); + // + // ConfigAndRecordAVMenuItem + // + this.ConfigAndRecordAVMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.AVI; + this.ConfigAndRecordAVMenuItem.Name = "ConfigAndRecordAVMenuItem"; + this.ConfigAndRecordAVMenuItem.Size = new System.Drawing.Size(223, 22); + this.ConfigAndRecordAVMenuItem.Text = "Config and Record AVI/WAV"; + this.ConfigAndRecordAVMenuItem.Click += new System.EventHandler(this.ConfigAndRecordAVMenuItem_Click); + // + // StopAVIMenuItem + // + this.StopAVIMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.Stop; + this.StopAVIMenuItem.Name = "StopAVIMenuItem"; + this.StopAVIMenuItem.Size = new System.Drawing.Size(223, 22); + this.StopAVIMenuItem.Text = "&Stop AVI/WAV"; + this.StopAVIMenuItem.Click += new System.EventHandler(this.StopAVMenuItem_Click); + // + // toolStripSeparator19 + // + this.toolStripSeparator19.Name = "toolStripSeparator19"; + this.toolStripSeparator19.Size = new System.Drawing.Size(220, 6); + // + // CaptureOSDMenuItem + // + this.CaptureOSDMenuItem.Name = "CaptureOSDMenuItem"; + this.CaptureOSDMenuItem.Size = new System.Drawing.Size(223, 22); + this.CaptureOSDMenuItem.Text = "Capture OSD"; + this.CaptureOSDMenuItem.Click += new System.EventHandler(this.CaptureOSDMenuItem_Click); + // + // SynclessRecordingMenuItem + // + this.SynclessRecordingMenuItem.Name = "SynclessRecordingMenuItem"; + this.SynclessRecordingMenuItem.Size = new System.Drawing.Size(223, 22); + this.SynclessRecordingMenuItem.Text = "S&yncless Recording Tools"; + this.SynclessRecordingMenuItem.Click += new System.EventHandler(this.SynclessRecordingMenuItem_Click); + // + // ScreenshotSubMenu + // + this.ScreenshotSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.ScreenshotMenuItem, this.ScreenshotAsMenuItem, this.ScreenshotClipboardMenuItem, this.ScreenshotClientClipboardMenuItem, this.toolStripSeparator20, this.ScreenshotCaptureOSDMenuItem1}); - this.ScreenshotSubMenu.Name = "ScreenshotSubMenu"; - this.ScreenshotSubMenu.Size = new System.Drawing.Size(151, 22); - this.ScreenshotSubMenu.Text = "Scree&nshot"; - this.ScreenshotSubMenu.DropDownOpening += new System.EventHandler(this.ScreenshotSubMenu_DropDownOpening); - // - // ScreenshotMenuItem - // - this.ScreenshotMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.camera; - this.ScreenshotMenuItem.Name = "ScreenshotMenuItem"; - this.ScreenshotMenuItem.Size = new System.Drawing.Size(227, 22); - this.ScreenshotMenuItem.Text = "Screenshot"; - this.ScreenshotMenuItem.Click += new System.EventHandler(this.ScreenshotMenuItem_Click); - // - // ScreenshotAsMenuItem - // - this.ScreenshotAsMenuItem.Name = "ScreenshotAsMenuItem"; - this.ScreenshotAsMenuItem.Size = new System.Drawing.Size(227, 22); - this.ScreenshotAsMenuItem.Text = "Screenshot As..."; - this.ScreenshotAsMenuItem.Click += new System.EventHandler(this.ScreenshotAsMenuItem_Click); - // - // ScreenshotClipboardMenuItem - // - this.ScreenshotClipboardMenuItem.Name = "ScreenshotClipboardMenuItem"; - this.ScreenshotClipboardMenuItem.Size = new System.Drawing.Size(227, 22); - this.ScreenshotClipboardMenuItem.Text = "Screenshot (raw) -> Clipboard"; - this.ScreenshotClipboardMenuItem.Click += new System.EventHandler(this.ScreenshotClipboardMenuItem_Click); - // - // ScreenshotClientClipboardMenuItem - // - this.ScreenshotClientClipboardMenuItem.Name = "ScreenshotClientClipboardMenuItem"; - this.ScreenshotClientClipboardMenuItem.Size = new System.Drawing.Size(227, 22); - this.ScreenshotClientClipboardMenuItem.Text = "Screenshot (client) -> Clipboard"; - this.ScreenshotClientClipboardMenuItem.Click += new System.EventHandler(this.ScreenshotClientClipboardMenuItem_Click); - // - // toolStripSeparator20 - // - this.toolStripSeparator20.Name = "toolStripSeparator20"; - this.toolStripSeparator20.Size = new System.Drawing.Size(224, 6); - // - // ScreenshotCaptureOSDMenuItem1 - // - this.ScreenshotCaptureOSDMenuItem1.Name = "ScreenshotCaptureOSDMenuItem1"; - this.ScreenshotCaptureOSDMenuItem1.Size = new System.Drawing.Size(227, 22); - this.ScreenshotCaptureOSDMenuItem1.Text = "Capture OSD"; - this.ScreenshotCaptureOSDMenuItem1.Click += new System.EventHandler(this.ScreenshotCaptureOSDMenuItem_Click); - // - // toolStripSeparator4 - // - this.toolStripSeparator4.Name = "toolStripSeparator4"; - this.toolStripSeparator4.Size = new System.Drawing.Size(148, 6); - // - // ExitMenuItem - // - this.ExitMenuItem.Name = "ExitMenuItem"; - this.ExitMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Alt | System.Windows.Forms.Keys.F4))); - this.ExitMenuItem.Size = new System.Drawing.Size(151, 22); - this.ExitMenuItem.Text = "E&xit"; - this.ExitMenuItem.Click += new System.EventHandler(this.ExitMenuItem_Click); - // - // EmulationSubMenu - // - this.EmulationSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.ScreenshotSubMenu.Name = "ScreenshotSubMenu"; + this.ScreenshotSubMenu.Size = new System.Drawing.Size(159, 22); + this.ScreenshotSubMenu.Text = "Scree&nshot"; + this.ScreenshotSubMenu.DropDownOpening += new System.EventHandler(this.ScreenshotSubMenu_DropDownOpening); + // + // ScreenshotMenuItem + // + this.ScreenshotMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.camera; + this.ScreenshotMenuItem.Name = "ScreenshotMenuItem"; + this.ScreenshotMenuItem.Size = new System.Drawing.Size(243, 22); + this.ScreenshotMenuItem.Text = "Screenshot"; + this.ScreenshotMenuItem.Click += new System.EventHandler(this.ScreenshotMenuItem_Click); + // + // ScreenshotAsMenuItem + // + this.ScreenshotAsMenuItem.Name = "ScreenshotAsMenuItem"; + this.ScreenshotAsMenuItem.Size = new System.Drawing.Size(243, 22); + this.ScreenshotAsMenuItem.Text = "Screenshot As..."; + this.ScreenshotAsMenuItem.Click += new System.EventHandler(this.ScreenshotAsMenuItem_Click); + // + // ScreenshotClipboardMenuItem + // + this.ScreenshotClipboardMenuItem.Name = "ScreenshotClipboardMenuItem"; + this.ScreenshotClipboardMenuItem.Size = new System.Drawing.Size(243, 22); + this.ScreenshotClipboardMenuItem.Text = "Screenshot (raw) -> Clipboard"; + this.ScreenshotClipboardMenuItem.Click += new System.EventHandler(this.ScreenshotClipboardMenuItem_Click); + // + // ScreenshotClientClipboardMenuItem + // + this.ScreenshotClientClipboardMenuItem.Name = "ScreenshotClientClipboardMenuItem"; + this.ScreenshotClientClipboardMenuItem.Size = new System.Drawing.Size(243, 22); + this.ScreenshotClientClipboardMenuItem.Text = "Screenshot (client) -> Clipboard"; + this.ScreenshotClientClipboardMenuItem.Click += new System.EventHandler(this.ScreenshotClientClipboardMenuItem_Click); + // + // toolStripSeparator20 + // + this.toolStripSeparator20.Name = "toolStripSeparator20"; + this.toolStripSeparator20.Size = new System.Drawing.Size(240, 6); + // + // ScreenshotCaptureOSDMenuItem1 + // + this.ScreenshotCaptureOSDMenuItem1.Name = "ScreenshotCaptureOSDMenuItem1"; + this.ScreenshotCaptureOSDMenuItem1.Size = new System.Drawing.Size(243, 22); + this.ScreenshotCaptureOSDMenuItem1.Text = "Capture OSD"; + this.ScreenshotCaptureOSDMenuItem1.Click += new System.EventHandler(this.ScreenshotCaptureOSDMenuItem_Click); + // + // toolStripSeparator4 + // + this.toolStripSeparator4.Name = "toolStripSeparator4"; + this.toolStripSeparator4.Size = new System.Drawing.Size(156, 6); + // + // ExitMenuItem + // + this.ExitMenuItem.Name = "ExitMenuItem"; + this.ExitMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Alt | System.Windows.Forms.Keys.F4))); + this.ExitMenuItem.Size = new System.Drawing.Size(159, 22); + this.ExitMenuItem.Text = "E&xit"; + this.ExitMenuItem.Click += new System.EventHandler(this.ExitMenuItem_Click); + // + // EmulationSubMenu + // + this.EmulationSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.PauseMenuItem, this.RebootCoreMenuItem, this.toolStripSeparator1, this.SoftResetMenuItem, this.HardResetMenuItem}); - this.EmulationSubMenu.Name = "EmulationSubMenu"; - this.EmulationSubMenu.Size = new System.Drawing.Size(65, 17); - this.EmulationSubMenu.Text = "&Emulation"; - this.EmulationSubMenu.DropDownOpened += new System.EventHandler(this.EmulationMenuItem_DropDownOpened); - // - // PauseMenuItem - // - this.PauseMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.Pause; - this.PauseMenuItem.Name = "PauseMenuItem"; - this.PauseMenuItem.Size = new System.Drawing.Size(135, 22); - this.PauseMenuItem.Text = "&Pause"; - this.PauseMenuItem.Click += new System.EventHandler(this.PauseMenuItem_Click); - // - // RebootCoreMenuItem - // - this.RebootCoreMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.reboot; - this.RebootCoreMenuItem.Name = "RebootCoreMenuItem"; - this.RebootCoreMenuItem.Size = new System.Drawing.Size(135, 22); - this.RebootCoreMenuItem.Text = "&Reboot Core"; - this.RebootCoreMenuItem.Click += new System.EventHandler(this.PowerMenuItem_Click); - // - // toolStripSeparator1 - // - this.toolStripSeparator1.Name = "toolStripSeparator1"; - this.toolStripSeparator1.Size = new System.Drawing.Size(132, 6); - // - // SoftResetMenuItem - // - this.SoftResetMenuItem.Name = "SoftResetMenuItem"; - this.SoftResetMenuItem.Size = new System.Drawing.Size(135, 22); - this.SoftResetMenuItem.Text = "&Soft Reset"; - this.SoftResetMenuItem.Click += new System.EventHandler(this.SoftResetMenuItem_Click); - // - // HardResetMenuItem - // - this.HardResetMenuItem.Name = "HardResetMenuItem"; - this.HardResetMenuItem.Size = new System.Drawing.Size(135, 22); - this.HardResetMenuItem.Text = "&Hard Reset"; - this.HardResetMenuItem.Click += new System.EventHandler(this.HardResetMenuItem_Click); - // - // ViewSubMenu - // - this.ViewSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.EmulationSubMenu.Name = "EmulationSubMenu"; + this.EmulationSubMenu.Size = new System.Drawing.Size(73, 19); + this.EmulationSubMenu.Text = "&Emulation"; + this.EmulationSubMenu.DropDownOpened += new System.EventHandler(this.EmulationMenuItem_DropDownOpened); + // + // PauseMenuItem + // + this.PauseMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.Pause; + this.PauseMenuItem.Name = "PauseMenuItem"; + this.PauseMenuItem.Size = new System.Drawing.Size(140, 22); + this.PauseMenuItem.Text = "&Pause"; + this.PauseMenuItem.Click += new System.EventHandler(this.PauseMenuItem_Click); + // + // RebootCoreMenuItem + // + this.RebootCoreMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.reboot; + this.RebootCoreMenuItem.Name = "RebootCoreMenuItem"; + this.RebootCoreMenuItem.Size = new System.Drawing.Size(140, 22); + this.RebootCoreMenuItem.Text = "&Reboot Core"; + this.RebootCoreMenuItem.Click += new System.EventHandler(this.PowerMenuItem_Click); + // + // toolStripSeparator1 + // + this.toolStripSeparator1.Name = "toolStripSeparator1"; + this.toolStripSeparator1.Size = new System.Drawing.Size(137, 6); + // + // SoftResetMenuItem + // + this.SoftResetMenuItem.Name = "SoftResetMenuItem"; + this.SoftResetMenuItem.Size = new System.Drawing.Size(140, 22); + this.SoftResetMenuItem.Text = "&Soft Reset"; + this.SoftResetMenuItem.Click += new System.EventHandler(this.SoftResetMenuItem_Click); + // + // HardResetMenuItem + // + this.HardResetMenuItem.Name = "HardResetMenuItem"; + this.HardResetMenuItem.Size = new System.Drawing.Size(140, 22); + this.HardResetMenuItem.Text = "&Hard Reset"; + this.HardResetMenuItem.Click += new System.EventHandler(this.HardResetMenuItem_Click); + // + // ViewSubMenu + // + this.ViewSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.WindowSizeSubMenu, this.SwitchToFullscreenMenuItem, this.toolStripSeparator2, @@ -1286,151 +1286,151 @@ this.DisplayStatusBarMenuItem, this.DisplayMessagesMenuItem, this.DisplayLogWindowMenuItem}); - this.ViewSubMenu.Name = "ViewSubMenu"; - this.ViewSubMenu.Size = new System.Drawing.Size(41, 17); - this.ViewSubMenu.Text = "&View"; - this.ViewSubMenu.DropDownOpened += new System.EventHandler(this.ViewSubMenu_DropDownOpened); - // - // WindowSizeSubMenu - // - this.WindowSizeSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.ViewSubMenu.Name = "ViewSubMenu"; + this.ViewSubMenu.Size = new System.Drawing.Size(44, 19); + this.ViewSubMenu.Text = "&View"; + this.ViewSubMenu.DropDownOpened += new System.EventHandler(this.ViewSubMenu_DropDownOpened); + // + // WindowSizeSubMenu + // + this.WindowSizeSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.x1MenuItem, this.x2MenuItem, this.x3MenuItem, this.x4MenuItem, this.x5MenuItem, this.mzMenuItem}); - this.WindowSizeSubMenu.Name = "WindowSizeSubMenu"; - this.WindowSizeSubMenu.Size = new System.Drawing.Size(187, 22); - this.WindowSizeSubMenu.Text = "&Window Size"; - this.WindowSizeSubMenu.DropDownOpened += new System.EventHandler(this.WindowSizeSubMenu_DropDownOpened); - // - // x1MenuItem - // - this.x1MenuItem.Name = "x1MenuItem"; - this.x1MenuItem.Size = new System.Drawing.Size(94, 22); - this.x1MenuItem.Text = "&1x"; - this.x1MenuItem.Click += new System.EventHandler(this.WindowSize_Click); - // - // x2MenuItem - // - this.x2MenuItem.Name = "x2MenuItem"; - this.x2MenuItem.Size = new System.Drawing.Size(94, 22); - this.x2MenuItem.Text = "&2x"; - this.x2MenuItem.Click += new System.EventHandler(this.WindowSize_Click); - // - // x3MenuItem - // - this.x3MenuItem.Name = "x3MenuItem"; - this.x3MenuItem.Size = new System.Drawing.Size(94, 22); - this.x3MenuItem.Text = "&3x"; - this.x3MenuItem.Click += new System.EventHandler(this.WindowSize_Click); - // - // x4MenuItem - // - this.x4MenuItem.Name = "x4MenuItem"; - this.x4MenuItem.Size = new System.Drawing.Size(94, 22); - this.x4MenuItem.Text = "&4x"; - this.x4MenuItem.Click += new System.EventHandler(this.WindowSize_Click); - // - // x5MenuItem - // - this.x5MenuItem.Name = "x5MenuItem"; - this.x5MenuItem.Size = new System.Drawing.Size(94, 22); - this.x5MenuItem.Text = "&5x"; - this.x5MenuItem.Click += new System.EventHandler(this.WindowSize_Click); - // - // mzMenuItem - // - this.mzMenuItem.Name = "mzMenuItem"; - this.mzMenuItem.Size = new System.Drawing.Size(94, 22); - this.mzMenuItem.Text = "&Max"; - this.mzMenuItem.Click += new System.EventHandler(this.WindowSize_Click); - // - // SwitchToFullscreenMenuItem - // - this.SwitchToFullscreenMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.Fullscreen; - this.SwitchToFullscreenMenuItem.Name = "SwitchToFullscreenMenuItem"; - this.SwitchToFullscreenMenuItem.Size = new System.Drawing.Size(187, 22); - this.SwitchToFullscreenMenuItem.Text = "Switch to Fullscreen"; - this.SwitchToFullscreenMenuItem.Click += new System.EventHandler(this.SwitchToFullscreenMenuItem_Click); - // - // toolStripSeparator2 - // - this.toolStripSeparator2.Name = "toolStripSeparator2"; - this.toolStripSeparator2.Size = new System.Drawing.Size(184, 6); - // - // DisplayFPSMenuItem - // - this.DisplayFPSMenuItem.Name = "DisplayFPSMenuItem"; - this.DisplayFPSMenuItem.Size = new System.Drawing.Size(187, 22); - this.DisplayFPSMenuItem.Text = "Display FPS"; - this.DisplayFPSMenuItem.Click += new System.EventHandler(this.DisplayFpsMenuItem_Click); - // - // DisplayFrameCounterMenuItem - // - this.DisplayFrameCounterMenuItem.Name = "DisplayFrameCounterMenuItem"; - this.DisplayFrameCounterMenuItem.Size = new System.Drawing.Size(187, 22); - this.DisplayFrameCounterMenuItem.Text = "Display FrameCounter"; - this.DisplayFrameCounterMenuItem.Click += new System.EventHandler(this.DisplayFrameCounterMenuItem_Click); - // - // DisplayLagCounterMenuItem - // - this.DisplayLagCounterMenuItem.Name = "DisplayLagCounterMenuItem"; - this.DisplayLagCounterMenuItem.Size = new System.Drawing.Size(187, 22); - this.DisplayLagCounterMenuItem.Text = "Display Lag Counter"; - this.DisplayLagCounterMenuItem.Click += new System.EventHandler(this.DisplayLagCounterMenuItem_Click); - // - // DisplayInputMenuItem - // - this.DisplayInputMenuItem.Name = "DisplayInputMenuItem"; - this.DisplayInputMenuItem.Size = new System.Drawing.Size(187, 22); - this.DisplayInputMenuItem.Text = "Display Input"; - this.DisplayInputMenuItem.Click += new System.EventHandler(this.DisplayInputMenuItem_Click); - // - // DisplayRerecordCountMenuItem - // - this.DisplayRerecordCountMenuItem.Name = "DisplayRerecordCountMenuItem"; - this.DisplayRerecordCountMenuItem.Size = new System.Drawing.Size(187, 22); - this.DisplayRerecordCountMenuItem.Text = "Display Rerecord Count"; - this.DisplayRerecordCountMenuItem.Click += new System.EventHandler(this.DisplayRerecordsMenuItem_Click); - // - // DisplaySubtitlesMenuItem - // - this.DisplaySubtitlesMenuItem.Name = "DisplaySubtitlesMenuItem"; - this.DisplaySubtitlesMenuItem.Size = new System.Drawing.Size(187, 22); - this.DisplaySubtitlesMenuItem.Text = "Display Subtitles"; - this.DisplaySubtitlesMenuItem.Click += new System.EventHandler(this.DisplaySubtitlesMenuItem_Click); - // - // toolStripMenuItem4 - // - this.toolStripMenuItem4.Name = "toolStripMenuItem4"; - this.toolStripMenuItem4.Size = new System.Drawing.Size(184, 6); - // - // DisplayStatusBarMenuItem - // - this.DisplayStatusBarMenuItem.Name = "DisplayStatusBarMenuItem"; - this.DisplayStatusBarMenuItem.Size = new System.Drawing.Size(187, 22); - this.DisplayStatusBarMenuItem.Text = "Display Status Bar"; - this.DisplayStatusBarMenuItem.Click += new System.EventHandler(this.DisplayStatusBarMenuItem_Click); - // - // DisplayMessagesMenuItem - // - this.DisplayMessagesMenuItem.Name = "DisplayMessagesMenuItem"; - this.DisplayMessagesMenuItem.Size = new System.Drawing.Size(187, 22); - this.DisplayMessagesMenuItem.Text = "Display Messages"; - this.DisplayMessagesMenuItem.Click += new System.EventHandler(this.DisplayMessagesMenuItem_Click); - // - // DisplayLogWindowMenuItem - // - this.DisplayLogWindowMenuItem.Name = "DisplayLogWindowMenuItem"; - this.DisplayLogWindowMenuItem.Size = new System.Drawing.Size(187, 22); - this.DisplayLogWindowMenuItem.Text = "Display Log Window"; - this.DisplayLogWindowMenuItem.Click += new System.EventHandler(this.DisplayLogWindowMenuItem_Click); - // - // ConfigSubMenu - // - this.ConfigSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.WindowSizeSubMenu.Name = "WindowSizeSubMenu"; + this.WindowSizeSubMenu.Size = new System.Drawing.Size(198, 22); + this.WindowSizeSubMenu.Text = "&Window Size"; + this.WindowSizeSubMenu.DropDownOpened += new System.EventHandler(this.WindowSizeSubMenu_DropDownOpened); + // + // x1MenuItem + // + this.x1MenuItem.Name = "x1MenuItem"; + this.x1MenuItem.Size = new System.Drawing.Size(96, 22); + this.x1MenuItem.Text = "&1x"; + this.x1MenuItem.Click += new System.EventHandler(this.WindowSize_Click); + // + // x2MenuItem + // + this.x2MenuItem.Name = "x2MenuItem"; + this.x2MenuItem.Size = new System.Drawing.Size(96, 22); + this.x2MenuItem.Text = "&2x"; + this.x2MenuItem.Click += new System.EventHandler(this.WindowSize_Click); + // + // x3MenuItem + // + this.x3MenuItem.Name = "x3MenuItem"; + this.x3MenuItem.Size = new System.Drawing.Size(96, 22); + this.x3MenuItem.Text = "&3x"; + this.x3MenuItem.Click += new System.EventHandler(this.WindowSize_Click); + // + // x4MenuItem + // + this.x4MenuItem.Name = "x4MenuItem"; + this.x4MenuItem.Size = new System.Drawing.Size(96, 22); + this.x4MenuItem.Text = "&4x"; + this.x4MenuItem.Click += new System.EventHandler(this.WindowSize_Click); + // + // x5MenuItem + // + this.x5MenuItem.Name = "x5MenuItem"; + this.x5MenuItem.Size = new System.Drawing.Size(96, 22); + this.x5MenuItem.Text = "&5x"; + this.x5MenuItem.Click += new System.EventHandler(this.WindowSize_Click); + // + // mzMenuItem + // + this.mzMenuItem.Name = "mzMenuItem"; + this.mzMenuItem.Size = new System.Drawing.Size(96, 22); + this.mzMenuItem.Text = "&Max"; + this.mzMenuItem.Click += new System.EventHandler(this.WindowSize_Click); + // + // SwitchToFullscreenMenuItem + // + this.SwitchToFullscreenMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.Fullscreen; + this.SwitchToFullscreenMenuItem.Name = "SwitchToFullscreenMenuItem"; + this.SwitchToFullscreenMenuItem.Size = new System.Drawing.Size(198, 22); + this.SwitchToFullscreenMenuItem.Text = "Switch to Fullscreen"; + this.SwitchToFullscreenMenuItem.Click += new System.EventHandler(this.SwitchToFullscreenMenuItem_Click); + // + // toolStripSeparator2 + // + this.toolStripSeparator2.Name = "toolStripSeparator2"; + this.toolStripSeparator2.Size = new System.Drawing.Size(195, 6); + // + // DisplayFPSMenuItem + // + this.DisplayFPSMenuItem.Name = "DisplayFPSMenuItem"; + this.DisplayFPSMenuItem.Size = new System.Drawing.Size(198, 22); + this.DisplayFPSMenuItem.Text = "Display FPS"; + this.DisplayFPSMenuItem.Click += new System.EventHandler(this.DisplayFpsMenuItem_Click); + // + // DisplayFrameCounterMenuItem + // + this.DisplayFrameCounterMenuItem.Name = "DisplayFrameCounterMenuItem"; + this.DisplayFrameCounterMenuItem.Size = new System.Drawing.Size(198, 22); + this.DisplayFrameCounterMenuItem.Text = "Display FrameCounter"; + this.DisplayFrameCounterMenuItem.Click += new System.EventHandler(this.DisplayFrameCounterMenuItem_Click); + // + // DisplayLagCounterMenuItem + // + this.DisplayLagCounterMenuItem.Name = "DisplayLagCounterMenuItem"; + this.DisplayLagCounterMenuItem.Size = new System.Drawing.Size(198, 22); + this.DisplayLagCounterMenuItem.Text = "Display Lag Counter"; + this.DisplayLagCounterMenuItem.Click += new System.EventHandler(this.DisplayLagCounterMenuItem_Click); + // + // DisplayInputMenuItem + // + this.DisplayInputMenuItem.Name = "DisplayInputMenuItem"; + this.DisplayInputMenuItem.Size = new System.Drawing.Size(198, 22); + this.DisplayInputMenuItem.Text = "Display Input"; + this.DisplayInputMenuItem.Click += new System.EventHandler(this.DisplayInputMenuItem_Click); + // + // DisplayRerecordCountMenuItem + // + this.DisplayRerecordCountMenuItem.Name = "DisplayRerecordCountMenuItem"; + this.DisplayRerecordCountMenuItem.Size = new System.Drawing.Size(198, 22); + this.DisplayRerecordCountMenuItem.Text = "Display Rerecord Count"; + this.DisplayRerecordCountMenuItem.Click += new System.EventHandler(this.DisplayRerecordsMenuItem_Click); + // + // DisplaySubtitlesMenuItem + // + this.DisplaySubtitlesMenuItem.Name = "DisplaySubtitlesMenuItem"; + this.DisplaySubtitlesMenuItem.Size = new System.Drawing.Size(198, 22); + this.DisplaySubtitlesMenuItem.Text = "Display Subtitles"; + this.DisplaySubtitlesMenuItem.Click += new System.EventHandler(this.DisplaySubtitlesMenuItem_Click); + // + // toolStripMenuItem4 + // + this.toolStripMenuItem4.Name = "toolStripMenuItem4"; + this.toolStripMenuItem4.Size = new System.Drawing.Size(195, 6); + // + // DisplayStatusBarMenuItem + // + this.DisplayStatusBarMenuItem.Name = "DisplayStatusBarMenuItem"; + this.DisplayStatusBarMenuItem.Size = new System.Drawing.Size(198, 22); + this.DisplayStatusBarMenuItem.Text = "Display Status Bar"; + this.DisplayStatusBarMenuItem.Click += new System.EventHandler(this.DisplayStatusBarMenuItem_Click); + // + // DisplayMessagesMenuItem + // + this.DisplayMessagesMenuItem.Name = "DisplayMessagesMenuItem"; + this.DisplayMessagesMenuItem.Size = new System.Drawing.Size(198, 22); + this.DisplayMessagesMenuItem.Text = "Display Messages"; + this.DisplayMessagesMenuItem.Click += new System.EventHandler(this.DisplayMessagesMenuItem_Click); + // + // DisplayLogWindowMenuItem + // + this.DisplayLogWindowMenuItem.Name = "DisplayLogWindowMenuItem"; + this.DisplayLogWindowMenuItem.Size = new System.Drawing.Size(198, 22); + this.DisplayLogWindowMenuItem.Text = "Display Log Window"; + this.DisplayLogWindowMenuItem.Click += new System.EventHandler(this.DisplayLogWindowMenuItem_Click); + // + // ConfigSubMenu + // + this.ConfigSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.ControllersMenuItem, this.HotkeysMenuItem, this.DisplayConfigMenuItem, @@ -1452,113 +1452,113 @@ this.SaveConfigAsMenuItem, this.LoadConfigMenuItem, this.LoadConfigFromMenuItem}); - this.ConfigSubMenu.Name = "ConfigSubMenu"; - this.ConfigSubMenu.Size = new System.Drawing.Size(50, 17); - this.ConfigSubMenu.Text = "&Config"; - this.ConfigSubMenu.DropDownOpened += new System.EventHandler(this.ConfigSubMenu_DropDownOpened); - // - // ControllersMenuItem - // - this.ControllersMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.GameController; - this.ControllersMenuItem.Name = "ControllersMenuItem"; - this.ControllersMenuItem.Size = new System.Drawing.Size(170, 22); - this.ControllersMenuItem.Text = "&Controllers..."; - this.ControllersMenuItem.Click += new System.EventHandler(this.ControllersMenuItem_Click); - // - // HotkeysMenuItem - // - this.HotkeysMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.HotKeys; - this.HotkeysMenuItem.Name = "HotkeysMenuItem"; - this.HotkeysMenuItem.Size = new System.Drawing.Size(170, 22); - this.HotkeysMenuItem.Text = "&Hotkeys..."; - this.HotkeysMenuItem.Click += new System.EventHandler(this.HotkeysMenuItem_Click); - // - // DisplayConfigMenuItem - // - this.DisplayConfigMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("DisplayConfigMenuItem.Image"))); - this.DisplayConfigMenuItem.Name = "DisplayConfigMenuItem"; - this.DisplayConfigMenuItem.Size = new System.Drawing.Size(170, 22); - this.DisplayConfigMenuItem.Text = "Display..."; - this.DisplayConfigMenuItem.Click += new System.EventHandler(this.DisplayConfigMenuItem_Click); - // - // SoundMenuItem - // - this.SoundMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.AudioHS; - this.SoundMenuItem.Name = "SoundMenuItem"; - this.SoundMenuItem.Size = new System.Drawing.Size(170, 22); - this.SoundMenuItem.Text = "&Sound..."; - this.SoundMenuItem.Click += new System.EventHandler(this.SoundMenuItem_Click); - // - // PathsMenuItem - // - this.PathsMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.CopyFolderHS; - this.PathsMenuItem.Name = "PathsMenuItem"; - this.PathsMenuItem.Size = new System.Drawing.Size(170, 22); - this.PathsMenuItem.Text = "Paths..."; - this.PathsMenuItem.Click += new System.EventHandler(this.PathsMenuItem_Click); - // - // FirmwaresMenuItem - // - this.FirmwaresMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("FirmwaresMenuItem.Image"))); - this.FirmwaresMenuItem.Name = "FirmwaresMenuItem"; - this.FirmwaresMenuItem.Size = new System.Drawing.Size(170, 22); - this.FirmwaresMenuItem.Text = "&Firmwares..."; - this.FirmwaresMenuItem.Click += new System.EventHandler(this.FirmwaresMenuItem_Click); - // - // MessagesMenuItem - // - this.MessagesMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.MessageConfig; - this.MessagesMenuItem.Name = "MessagesMenuItem"; - this.MessagesMenuItem.Size = new System.Drawing.Size(170, 22); - this.MessagesMenuItem.Text = "&Messages..."; - this.MessagesMenuItem.Click += new System.EventHandler(this.MessagesMenuItem_Click); - // - // AutofireMenuItem - // - this.AutofireMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.Lightning; - this.AutofireMenuItem.Name = "AutofireMenuItem"; - this.AutofireMenuItem.Size = new System.Drawing.Size(170, 22); - this.AutofireMenuItem.Text = "&Autofire..."; - this.AutofireMenuItem.Click += new System.EventHandler(this.AutofireMenuItem_Click); - // - // RewindOptionsMenuItem - // - this.RewindOptionsMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.Previous; - this.RewindOptionsMenuItem.Name = "RewindOptionsMenuItem"; - this.RewindOptionsMenuItem.Size = new System.Drawing.Size(170, 22); - this.RewindOptionsMenuItem.Text = "&Rewind && States..."; - this.RewindOptionsMenuItem.Click += new System.EventHandler(this.RewindOptionsMenuItem_Click); - // - // extensionsToolStripMenuItem - // - this.extensionsToolStripMenuItem.Name = "extensionsToolStripMenuItem"; - this.extensionsToolStripMenuItem.Size = new System.Drawing.Size(170, 22); - this.extensionsToolStripMenuItem.Text = "File Extensions..."; - this.extensionsToolStripMenuItem.Click += new System.EventHandler(this.FileExtensionsMenuItem_Click); - // - // ClientOptionsMenuItem - // - this.ClientOptionsMenuItem.Name = "ClientOptionsMenuItem"; - this.ClientOptionsMenuItem.Size = new System.Drawing.Size(170, 22); - this.ClientOptionsMenuItem.Text = "&Customize..."; - this.ClientOptionsMenuItem.Click += new System.EventHandler(this.CustomizeMenuItem_Click); - // - // ProfilesMenuItem - // - this.ProfilesMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.user_blue_small; - this.ProfilesMenuItem.Name = "ProfilesMenuItem"; - this.ProfilesMenuItem.Size = new System.Drawing.Size(170, 22); - this.ProfilesMenuItem.Text = "&Profiles..."; - this.ProfilesMenuItem.Click += new System.EventHandler(this.ProfilesMenuItem_Click); - // - // toolStripSeparator9 - // - this.toolStripSeparator9.Name = "toolStripSeparator9"; - this.toolStripSeparator9.Size = new System.Drawing.Size(167, 6); - // - // SpeedSkipSubMenu - // - this.SpeedSkipSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.ConfigSubMenu.Name = "ConfigSubMenu"; + this.ConfigSubMenu.Size = new System.Drawing.Size(55, 19); + this.ConfigSubMenu.Text = "&Config"; + this.ConfigSubMenu.DropDownOpened += new System.EventHandler(this.ConfigSubMenu_DropDownOpened); + // + // ControllersMenuItem + // + this.ControllersMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.GameController; + this.ControllersMenuItem.Name = "ControllersMenuItem"; + this.ControllersMenuItem.Size = new System.Drawing.Size(179, 22); + this.ControllersMenuItem.Text = "&Controllers..."; + this.ControllersMenuItem.Click += new System.EventHandler(this.ControllersMenuItem_Click); + // + // HotkeysMenuItem + // + this.HotkeysMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.HotKeys; + this.HotkeysMenuItem.Name = "HotkeysMenuItem"; + this.HotkeysMenuItem.Size = new System.Drawing.Size(179, 22); + this.HotkeysMenuItem.Text = "&Hotkeys..."; + this.HotkeysMenuItem.Click += new System.EventHandler(this.HotkeysMenuItem_Click); + // + // DisplayConfigMenuItem + // + this.DisplayConfigMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("DisplayConfigMenuItem.Image"))); + this.DisplayConfigMenuItem.Name = "DisplayConfigMenuItem"; + this.DisplayConfigMenuItem.Size = new System.Drawing.Size(179, 22); + this.DisplayConfigMenuItem.Text = "Display..."; + this.DisplayConfigMenuItem.Click += new System.EventHandler(this.DisplayConfigMenuItem_Click); + // + // SoundMenuItem + // + this.SoundMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.AudioHS; + this.SoundMenuItem.Name = "SoundMenuItem"; + this.SoundMenuItem.Size = new System.Drawing.Size(179, 22); + this.SoundMenuItem.Text = "&Sound..."; + this.SoundMenuItem.Click += new System.EventHandler(this.SoundMenuItem_Click); + // + // PathsMenuItem + // + this.PathsMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.CopyFolderHS; + this.PathsMenuItem.Name = "PathsMenuItem"; + this.PathsMenuItem.Size = new System.Drawing.Size(179, 22); + this.PathsMenuItem.Text = "Paths..."; + this.PathsMenuItem.Click += new System.EventHandler(this.PathsMenuItem_Click); + // + // FirmwaresMenuItem + // + this.FirmwaresMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("FirmwaresMenuItem.Image"))); + this.FirmwaresMenuItem.Name = "FirmwaresMenuItem"; + this.FirmwaresMenuItem.Size = new System.Drawing.Size(179, 22); + this.FirmwaresMenuItem.Text = "&Firmwares..."; + this.FirmwaresMenuItem.Click += new System.EventHandler(this.FirmwaresMenuItem_Click); + // + // MessagesMenuItem + // + this.MessagesMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.MessageConfig; + this.MessagesMenuItem.Name = "MessagesMenuItem"; + this.MessagesMenuItem.Size = new System.Drawing.Size(179, 22); + this.MessagesMenuItem.Text = "&Messages..."; + this.MessagesMenuItem.Click += new System.EventHandler(this.MessagesMenuItem_Click); + // + // AutofireMenuItem + // + this.AutofireMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.Lightning; + this.AutofireMenuItem.Name = "AutofireMenuItem"; + this.AutofireMenuItem.Size = new System.Drawing.Size(179, 22); + this.AutofireMenuItem.Text = "&Autofire..."; + this.AutofireMenuItem.Click += new System.EventHandler(this.AutofireMenuItem_Click); + // + // RewindOptionsMenuItem + // + this.RewindOptionsMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.Previous; + this.RewindOptionsMenuItem.Name = "RewindOptionsMenuItem"; + this.RewindOptionsMenuItem.Size = new System.Drawing.Size(179, 22); + this.RewindOptionsMenuItem.Text = "&Rewind && States..."; + this.RewindOptionsMenuItem.Click += new System.EventHandler(this.RewindOptionsMenuItem_Click); + // + // extensionsToolStripMenuItem + // + this.extensionsToolStripMenuItem.Name = "extensionsToolStripMenuItem"; + this.extensionsToolStripMenuItem.Size = new System.Drawing.Size(179, 22); + this.extensionsToolStripMenuItem.Text = "File Extensions..."; + this.extensionsToolStripMenuItem.Click += new System.EventHandler(this.FileExtensionsMenuItem_Click); + // + // ClientOptionsMenuItem + // + this.ClientOptionsMenuItem.Name = "ClientOptionsMenuItem"; + this.ClientOptionsMenuItem.Size = new System.Drawing.Size(179, 22); + this.ClientOptionsMenuItem.Text = "&Customize..."; + this.ClientOptionsMenuItem.Click += new System.EventHandler(this.CustomizeMenuItem_Click); + // + // ProfilesMenuItem + // + this.ProfilesMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.user_blue_small; + this.ProfilesMenuItem.Name = "ProfilesMenuItem"; + this.ProfilesMenuItem.Size = new System.Drawing.Size(179, 22); + this.ProfilesMenuItem.Text = "&Profiles..."; + this.ProfilesMenuItem.Click += new System.EventHandler(this.ProfilesMenuItem_Click); + // + // toolStripSeparator9 + // + this.toolStripSeparator9.Name = "toolStripSeparator9"; + this.toolStripSeparator9.Size = new System.Drawing.Size(176, 6); + // + // SpeedSkipSubMenu + // + this.SpeedSkipSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.ClockThrottleMenuItem, this.AudioThrottleMenuItem, this.VsyncThrottleMenuItem, @@ -1576,73 +1576,73 @@ this.Speed150MenuItem, this.Speed200MenuItem, this.Speed400MenuItem}); - this.SpeedSkipSubMenu.Name = "SpeedSkipSubMenu"; - this.SpeedSkipSubMenu.Size = new System.Drawing.Size(170, 22); - this.SpeedSkipSubMenu.Text = "Speed/Skip"; - this.SpeedSkipSubMenu.DropDownOpened += new System.EventHandler(this.FrameSkipMenuItem_DropDownOpened); - // - // ClockThrottleMenuItem - // - this.ClockThrottleMenuItem.Name = "ClockThrottleMenuItem"; - this.ClockThrottleMenuItem.Size = new System.Drawing.Size(181, 22); - this.ClockThrottleMenuItem.Text = "Clock Throttle"; - this.ClockThrottleMenuItem.Click += new System.EventHandler(this.ClockThrottleMenuItem_Click); - // - // AudioThrottleMenuItem - // - this.AudioThrottleMenuItem.Name = "AudioThrottleMenuItem"; - this.AudioThrottleMenuItem.Size = new System.Drawing.Size(181, 22); - this.AudioThrottleMenuItem.Text = "Audio Throttle"; - this.AudioThrottleMenuItem.Click += new System.EventHandler(this.AudioThrottleMenuItem_Click); - // - // VsyncThrottleMenuItem - // - this.VsyncThrottleMenuItem.Name = "VsyncThrottleMenuItem"; - this.VsyncThrottleMenuItem.Size = new System.Drawing.Size(181, 22); - this.VsyncThrottleMenuItem.Text = "VSync Throttle"; - this.VsyncThrottleMenuItem.Click += new System.EventHandler(this.VsyncThrottleMenuItem_Click); - // - // toolStripSeparator27 - // - this.toolStripSeparator27.Name = "toolStripSeparator27"; - this.toolStripSeparator27.Size = new System.Drawing.Size(178, 6); - // - // VsyncEnabledMenuItem - // - this.VsyncEnabledMenuItem.Name = "VsyncEnabledMenuItem"; - this.VsyncEnabledMenuItem.Size = new System.Drawing.Size(181, 22); - this.VsyncEnabledMenuItem.Text = "VSync Enabled"; - this.VsyncEnabledMenuItem.Click += new System.EventHandler(this.VsyncEnabledMenuItem_Click); - // - // toolStripMenuItem3 - // - this.toolStripMenuItem3.Name = "toolStripMenuItem3"; - this.toolStripMenuItem3.Size = new System.Drawing.Size(178, 6); - // - // miUnthrottled - // - this.miUnthrottled.Name = "miUnthrottled"; - this.miUnthrottled.Size = new System.Drawing.Size(181, 22); - this.miUnthrottled.Text = "Unthrottled"; - this.miUnthrottled.Click += new System.EventHandler(this.UnthrottledMenuItem_Click); - // - // MinimizeSkippingMenuItem - // - this.MinimizeSkippingMenuItem.Name = "MinimizeSkippingMenuItem"; - this.MinimizeSkippingMenuItem.Size = new System.Drawing.Size(181, 22); - this.MinimizeSkippingMenuItem.Text = "Auto-minimize skipping"; - this.MinimizeSkippingMenuItem.Click += new System.EventHandler(this.MinimizeSkippingMenuItem_Click); - // - // NeverSkipMenuItem - // - this.NeverSkipMenuItem.Name = "NeverSkipMenuItem"; - this.NeverSkipMenuItem.Size = new System.Drawing.Size(181, 22); - this.NeverSkipMenuItem.Text = "Skip 0 (never)"; - this.NeverSkipMenuItem.Click += new System.EventHandler(this.NeverSkipMenuItem_Click); - // - // toolStripMenuItem17 - // - this.toolStripMenuItem17.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.SpeedSkipSubMenu.Name = "SpeedSkipSubMenu"; + this.SpeedSkipSubMenu.Size = new System.Drawing.Size(179, 22); + this.SpeedSkipSubMenu.Text = "Speed/Skip"; + this.SpeedSkipSubMenu.DropDownOpened += new System.EventHandler(this.FrameSkipMenuItem_DropDownOpened); + // + // ClockThrottleMenuItem + // + this.ClockThrottleMenuItem.Name = "ClockThrottleMenuItem"; + this.ClockThrottleMenuItem.Size = new System.Drawing.Size(202, 22); + this.ClockThrottleMenuItem.Text = "Clock Throttle"; + this.ClockThrottleMenuItem.Click += new System.EventHandler(this.ClockThrottleMenuItem_Click); + // + // AudioThrottleMenuItem + // + this.AudioThrottleMenuItem.Name = "AudioThrottleMenuItem"; + this.AudioThrottleMenuItem.Size = new System.Drawing.Size(202, 22); + this.AudioThrottleMenuItem.Text = "Audio Throttle"; + this.AudioThrottleMenuItem.Click += new System.EventHandler(this.AudioThrottleMenuItem_Click); + // + // VsyncThrottleMenuItem + // + this.VsyncThrottleMenuItem.Name = "VsyncThrottleMenuItem"; + this.VsyncThrottleMenuItem.Size = new System.Drawing.Size(202, 22); + this.VsyncThrottleMenuItem.Text = "VSync Throttle"; + this.VsyncThrottleMenuItem.Click += new System.EventHandler(this.VsyncThrottleMenuItem_Click); + // + // toolStripSeparator27 + // + this.toolStripSeparator27.Name = "toolStripSeparator27"; + this.toolStripSeparator27.Size = new System.Drawing.Size(199, 6); + // + // VsyncEnabledMenuItem + // + this.VsyncEnabledMenuItem.Name = "VsyncEnabledMenuItem"; + this.VsyncEnabledMenuItem.Size = new System.Drawing.Size(202, 22); + this.VsyncEnabledMenuItem.Text = "VSync Enabled"; + this.VsyncEnabledMenuItem.Click += new System.EventHandler(this.VsyncEnabledMenuItem_Click); + // + // toolStripMenuItem3 + // + this.toolStripMenuItem3.Name = "toolStripMenuItem3"; + this.toolStripMenuItem3.Size = new System.Drawing.Size(199, 6); + // + // miUnthrottled + // + this.miUnthrottled.Name = "miUnthrottled"; + this.miUnthrottled.Size = new System.Drawing.Size(202, 22); + this.miUnthrottled.Text = "Unthrottled"; + this.miUnthrottled.Click += new System.EventHandler(this.UnthrottledMenuItem_Click); + // + // MinimizeSkippingMenuItem + // + this.MinimizeSkippingMenuItem.Name = "MinimizeSkippingMenuItem"; + this.MinimizeSkippingMenuItem.Size = new System.Drawing.Size(202, 22); + this.MinimizeSkippingMenuItem.Text = "Auto-minimize skipping"; + this.MinimizeSkippingMenuItem.Click += new System.EventHandler(this.MinimizeSkippingMenuItem_Click); + // + // NeverSkipMenuItem + // + this.NeverSkipMenuItem.Name = "NeverSkipMenuItem"; + this.NeverSkipMenuItem.Size = new System.Drawing.Size(202, 22); + this.NeverSkipMenuItem.Text = "Skip 0 (never)"; + this.NeverSkipMenuItem.Click += new System.EventHandler(this.NeverSkipMenuItem_Click); + // + // toolStripMenuItem17 + // + this.toolStripMenuItem17.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.Frameskip1MenuItem, this.Frameskip2MenuItem, this.Frameskip3MenuItem, @@ -1652,155 +1652,155 @@ this.Frameskip7MenuItem, this.Frameskip8MenuItem, this.Frameskip9MenuItem}); - this.toolStripMenuItem17.Name = "toolStripMenuItem17"; - this.toolStripMenuItem17.Size = new System.Drawing.Size(181, 22); - this.toolStripMenuItem17.Text = "Skip 1..9"; - // - // Frameskip1MenuItem - // - this.Frameskip1MenuItem.Name = "Frameskip1MenuItem"; - this.Frameskip1MenuItem.Size = new System.Drawing.Size(80, 22); - this.Frameskip1MenuItem.Text = "1"; - this.Frameskip1MenuItem.Click += new System.EventHandler(this.Frameskip1MenuItem_Click); - // - // Frameskip2MenuItem - // - this.Frameskip2MenuItem.Name = "Frameskip2MenuItem"; - this.Frameskip2MenuItem.Size = new System.Drawing.Size(80, 22); - this.Frameskip2MenuItem.Text = "2"; - this.Frameskip2MenuItem.Click += new System.EventHandler(this.Frameskip2MenuItem_Click); - // - // Frameskip3MenuItem - // - this.Frameskip3MenuItem.Name = "Frameskip3MenuItem"; - this.Frameskip3MenuItem.Size = new System.Drawing.Size(80, 22); - this.Frameskip3MenuItem.Text = "3"; - this.Frameskip3MenuItem.Click += new System.EventHandler(this.Frameskip3MenuItem_Click); - // - // Frameskip4MenuItem - // - this.Frameskip4MenuItem.Name = "Frameskip4MenuItem"; - this.Frameskip4MenuItem.Size = new System.Drawing.Size(80, 22); - this.Frameskip4MenuItem.Text = "4"; - this.Frameskip4MenuItem.Click += new System.EventHandler(this.Frameskip4MenuItem_Click); - // - // Frameskip5MenuItem - // - this.Frameskip5MenuItem.Name = "Frameskip5MenuItem"; - this.Frameskip5MenuItem.Size = new System.Drawing.Size(80, 22); - this.Frameskip5MenuItem.Text = "5"; - this.Frameskip5MenuItem.Click += new System.EventHandler(this.Frameskip5MenuItem_Click); - // - // Frameskip6MenuItem - // - this.Frameskip6MenuItem.Name = "Frameskip6MenuItem"; - this.Frameskip6MenuItem.Size = new System.Drawing.Size(80, 22); - this.Frameskip6MenuItem.Text = "6"; - this.Frameskip6MenuItem.Click += new System.EventHandler(this.Frameskip6MenuItem_Click); - // - // Frameskip7MenuItem - // - this.Frameskip7MenuItem.Name = "Frameskip7MenuItem"; - this.Frameskip7MenuItem.Size = new System.Drawing.Size(80, 22); - this.Frameskip7MenuItem.Text = "7"; - this.Frameskip7MenuItem.Click += new System.EventHandler(this.Frameskip7MenuItem_Click); - // - // Frameskip8MenuItem - // - this.Frameskip8MenuItem.Name = "Frameskip8MenuItem"; - this.Frameskip8MenuItem.Size = new System.Drawing.Size(80, 22); - this.Frameskip8MenuItem.Text = "8"; - this.Frameskip8MenuItem.Click += new System.EventHandler(this.Frameskip8MenuItem_Click); - // - // Frameskip9MenuItem - // - this.Frameskip9MenuItem.Name = "Frameskip9MenuItem"; - this.Frameskip9MenuItem.Size = new System.Drawing.Size(80, 22); - this.Frameskip9MenuItem.Text = "9"; - this.Frameskip9MenuItem.Click += new System.EventHandler(this.Frameskip9MenuItem_Click); - // - // toolStripMenuItem5 - // - this.toolStripMenuItem5.Name = "toolStripMenuItem5"; - this.toolStripMenuItem5.Size = new System.Drawing.Size(178, 6); - // - // Speed50MenuItem - // - this.Speed50MenuItem.Name = "Speed50MenuItem"; - this.Speed50MenuItem.Size = new System.Drawing.Size(181, 22); - this.Speed50MenuItem.Text = "Speed 50%"; - this.Speed50MenuItem.Click += new System.EventHandler(this.Speed50MenuItem_Click); - // - // Speed75MenuItem - // - this.Speed75MenuItem.Name = "Speed75MenuItem"; - this.Speed75MenuItem.Size = new System.Drawing.Size(181, 22); - this.Speed75MenuItem.Text = "Speed 75%"; - this.Speed75MenuItem.Click += new System.EventHandler(this.Speed75MenuItem_Click); - // - // Speed100MenuItem - // - this.Speed100MenuItem.Name = "Speed100MenuItem"; - this.Speed100MenuItem.Size = new System.Drawing.Size(181, 22); - this.Speed100MenuItem.Text = "Speed 100%"; - this.Speed100MenuItem.Click += new System.EventHandler(this.Speed100MenuItem_Click); - // - // Speed150MenuItem - // - this.Speed150MenuItem.Name = "Speed150MenuItem"; - this.Speed150MenuItem.Size = new System.Drawing.Size(181, 22); - this.Speed150MenuItem.Text = "Speed 150%"; - this.Speed150MenuItem.Click += new System.EventHandler(this.Speed150MenuItem_Click); - // - // Speed200MenuItem - // - this.Speed200MenuItem.Name = "Speed200MenuItem"; - this.Speed200MenuItem.Size = new System.Drawing.Size(181, 22); - this.Speed200MenuItem.Text = "Speed 200%"; - this.Speed200MenuItem.Click += new System.EventHandler(this.Speed200MenuItem_Click); - // - // Speed400MenuItem - // - this.Speed400MenuItem.Name = "Speed400MenuItem"; - this.Speed400MenuItem.Size = new System.Drawing.Size(181, 22); - this.Speed400MenuItem.Text = "Speed 400%"; - this.Speed400MenuItem.Click += new System.EventHandler(this.Speed400MenuItem_Click); - // - // KeyPrioritySubMenu - // - this.KeyPrioritySubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.toolStripMenuItem17.Name = "toolStripMenuItem17"; + this.toolStripMenuItem17.Size = new System.Drawing.Size(202, 22); + this.toolStripMenuItem17.Text = "Skip 1..9"; + // + // Frameskip1MenuItem + // + this.Frameskip1MenuItem.Name = "Frameskip1MenuItem"; + this.Frameskip1MenuItem.Size = new System.Drawing.Size(80, 22); + this.Frameskip1MenuItem.Text = "1"; + this.Frameskip1MenuItem.Click += new System.EventHandler(this.Frameskip1MenuItem_Click); + // + // Frameskip2MenuItem + // + this.Frameskip2MenuItem.Name = "Frameskip2MenuItem"; + this.Frameskip2MenuItem.Size = new System.Drawing.Size(80, 22); + this.Frameskip2MenuItem.Text = "2"; + this.Frameskip2MenuItem.Click += new System.EventHandler(this.Frameskip2MenuItem_Click); + // + // Frameskip3MenuItem + // + this.Frameskip3MenuItem.Name = "Frameskip3MenuItem"; + this.Frameskip3MenuItem.Size = new System.Drawing.Size(80, 22); + this.Frameskip3MenuItem.Text = "3"; + this.Frameskip3MenuItem.Click += new System.EventHandler(this.Frameskip3MenuItem_Click); + // + // Frameskip4MenuItem + // + this.Frameskip4MenuItem.Name = "Frameskip4MenuItem"; + this.Frameskip4MenuItem.Size = new System.Drawing.Size(80, 22); + this.Frameskip4MenuItem.Text = "4"; + this.Frameskip4MenuItem.Click += new System.EventHandler(this.Frameskip4MenuItem_Click); + // + // Frameskip5MenuItem + // + this.Frameskip5MenuItem.Name = "Frameskip5MenuItem"; + this.Frameskip5MenuItem.Size = new System.Drawing.Size(80, 22); + this.Frameskip5MenuItem.Text = "5"; + this.Frameskip5MenuItem.Click += new System.EventHandler(this.Frameskip5MenuItem_Click); + // + // Frameskip6MenuItem + // + this.Frameskip6MenuItem.Name = "Frameskip6MenuItem"; + this.Frameskip6MenuItem.Size = new System.Drawing.Size(80, 22); + this.Frameskip6MenuItem.Text = "6"; + this.Frameskip6MenuItem.Click += new System.EventHandler(this.Frameskip6MenuItem_Click); + // + // Frameskip7MenuItem + // + this.Frameskip7MenuItem.Name = "Frameskip7MenuItem"; + this.Frameskip7MenuItem.Size = new System.Drawing.Size(80, 22); + this.Frameskip7MenuItem.Text = "7"; + this.Frameskip7MenuItem.Click += new System.EventHandler(this.Frameskip7MenuItem_Click); + // + // Frameskip8MenuItem + // + this.Frameskip8MenuItem.Name = "Frameskip8MenuItem"; + this.Frameskip8MenuItem.Size = new System.Drawing.Size(80, 22); + this.Frameskip8MenuItem.Text = "8"; + this.Frameskip8MenuItem.Click += new System.EventHandler(this.Frameskip8MenuItem_Click); + // + // Frameskip9MenuItem + // + this.Frameskip9MenuItem.Name = "Frameskip9MenuItem"; + this.Frameskip9MenuItem.Size = new System.Drawing.Size(80, 22); + this.Frameskip9MenuItem.Text = "9"; + this.Frameskip9MenuItem.Click += new System.EventHandler(this.Frameskip9MenuItem_Click); + // + // toolStripMenuItem5 + // + this.toolStripMenuItem5.Name = "toolStripMenuItem5"; + this.toolStripMenuItem5.Size = new System.Drawing.Size(199, 6); + // + // Speed50MenuItem + // + this.Speed50MenuItem.Name = "Speed50MenuItem"; + this.Speed50MenuItem.Size = new System.Drawing.Size(202, 22); + this.Speed50MenuItem.Text = "Speed 50%"; + this.Speed50MenuItem.Click += new System.EventHandler(this.Speed50MenuItem_Click); + // + // Speed75MenuItem + // + this.Speed75MenuItem.Name = "Speed75MenuItem"; + this.Speed75MenuItem.Size = new System.Drawing.Size(202, 22); + this.Speed75MenuItem.Text = "Speed 75%"; + this.Speed75MenuItem.Click += new System.EventHandler(this.Speed75MenuItem_Click); + // + // Speed100MenuItem + // + this.Speed100MenuItem.Name = "Speed100MenuItem"; + this.Speed100MenuItem.Size = new System.Drawing.Size(202, 22); + this.Speed100MenuItem.Text = "Speed 100%"; + this.Speed100MenuItem.Click += new System.EventHandler(this.Speed100MenuItem_Click); + // + // Speed150MenuItem + // + this.Speed150MenuItem.Name = "Speed150MenuItem"; + this.Speed150MenuItem.Size = new System.Drawing.Size(202, 22); + this.Speed150MenuItem.Text = "Speed 150%"; + this.Speed150MenuItem.Click += new System.EventHandler(this.Speed150MenuItem_Click); + // + // Speed200MenuItem + // + this.Speed200MenuItem.Name = "Speed200MenuItem"; + this.Speed200MenuItem.Size = new System.Drawing.Size(202, 22); + this.Speed200MenuItem.Text = "Speed 200%"; + this.Speed200MenuItem.Click += new System.EventHandler(this.Speed200MenuItem_Click); + // + // Speed400MenuItem + // + this.Speed400MenuItem.Name = "Speed400MenuItem"; + this.Speed400MenuItem.Size = new System.Drawing.Size(202, 22); + this.Speed400MenuItem.Text = "Speed 400%"; + this.Speed400MenuItem.Click += new System.EventHandler(this.Speed400MenuItem_Click); + // + // KeyPrioritySubMenu + // + this.KeyPrioritySubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.BothHkAndControllerMenuItem, this.InputOverHkMenuItem, this.HkOverInputMenuItem}); - this.KeyPrioritySubMenu.Name = "KeyPrioritySubMenu"; - this.KeyPrioritySubMenu.Size = new System.Drawing.Size(170, 22); - this.KeyPrioritySubMenu.Text = "Key Priority"; - this.KeyPrioritySubMenu.DropDownOpened += new System.EventHandler(this.KeyPriorityMenuItem_DropDownOpened); - // - // BothHkAndControllerMenuItem - // - this.BothHkAndControllerMenuItem.Name = "BothHkAndControllerMenuItem"; - this.BothHkAndControllerMenuItem.Size = new System.Drawing.Size(214, 22); - this.BothHkAndControllerMenuItem.Text = "Both Hotkeys and Controllers"; - this.BothHkAndControllerMenuItem.Click += new System.EventHandler(this.BothHkAndControllerMenuItem_Click); - // - // InputOverHkMenuItem - // - this.InputOverHkMenuItem.Name = "InputOverHkMenuItem"; - this.InputOverHkMenuItem.Size = new System.Drawing.Size(214, 22); - this.InputOverHkMenuItem.Text = "Input overrides Hotkeys"; - this.InputOverHkMenuItem.Click += new System.EventHandler(this.InputOverHkMenuItem_Click); - // - // HkOverInputMenuItem - // - this.HkOverInputMenuItem.Name = "HkOverInputMenuItem"; - this.HkOverInputMenuItem.Size = new System.Drawing.Size(214, 22); - this.HkOverInputMenuItem.Text = "Hotkeys override Input"; - this.HkOverInputMenuItem.Click += new System.EventHandler(this.HkOverInputMenuItem_Click); - // - // CoresSubMenu - // - this.CoresSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.KeyPrioritySubMenu.Name = "KeyPrioritySubMenu"; + this.KeyPrioritySubMenu.Size = new System.Drawing.Size(179, 22); + this.KeyPrioritySubMenu.Text = "Key Priority"; + this.KeyPrioritySubMenu.DropDownOpened += new System.EventHandler(this.KeyPriorityMenuItem_DropDownOpened); + // + // BothHkAndControllerMenuItem + // + this.BothHkAndControllerMenuItem.Name = "BothHkAndControllerMenuItem"; + this.BothHkAndControllerMenuItem.Size = new System.Drawing.Size(229, 22); + this.BothHkAndControllerMenuItem.Text = "Both Hotkeys and Controllers"; + this.BothHkAndControllerMenuItem.Click += new System.EventHandler(this.BothHkAndControllerMenuItem_Click); + // + // InputOverHkMenuItem + // + this.InputOverHkMenuItem.Name = "InputOverHkMenuItem"; + this.InputOverHkMenuItem.Size = new System.Drawing.Size(229, 22); + this.InputOverHkMenuItem.Text = "Input overrides Hotkeys"; + this.InputOverHkMenuItem.Click += new System.EventHandler(this.InputOverHkMenuItem_Click); + // + // HkOverInputMenuItem + // + this.HkOverInputMenuItem.Name = "HkOverInputMenuItem"; + this.HkOverInputMenuItem.Size = new System.Drawing.Size(229, 22); + this.HkOverInputMenuItem.Text = "Hotkeys override Input"; + this.HkOverInputMenuItem.Click += new System.EventHandler(this.HkOverInputMenuItem_Click); + // + // CoresSubMenu + // + this.CoresSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.NesCoreSubMenu, this.CoreSNESSubMenu, this.GbaCoreSubMenu, @@ -1812,208 +1812,208 @@ this.toolStripSeparator8, this.N64VideoPluginSettingsMenuItem, this.setLibretroCoreToolStripMenuItem}); - this.CoresSubMenu.Name = "CoresSubMenu"; - this.CoresSubMenu.Size = new System.Drawing.Size(170, 22); - this.CoresSubMenu.Text = "Cores"; - this.CoresSubMenu.DropDownOpened += new System.EventHandler(this.CoresSubMenu_DropDownOpened); - // - // NesCoreSubMenu - // - this.NesCoreSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.CoresSubMenu.Name = "CoresSubMenu"; + this.CoresSubMenu.Size = new System.Drawing.Size(179, 22); + this.CoresSubMenu.Text = "Cores"; + this.CoresSubMenu.DropDownOpened += new System.EventHandler(this.CoresSubMenu_DropDownOpened); + // + // NesCoreSubMenu + // + this.NesCoreSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.QuicknesCoreMenuItem, this.NesCoreMenuItem}); - this.NesCoreSubMenu.Name = "NesCoreSubMenu"; - this.NesCoreSubMenu.Size = new System.Drawing.Size(223, 22); - this.NesCoreSubMenu.Text = "NES"; - this.NesCoreSubMenu.DropDownOpened += new System.EventHandler(this.NesCoreSubMenu_DropDownOpened); - // - // QuicknesCoreMenuItem - // - this.QuicknesCoreMenuItem.Name = "QuicknesCoreMenuItem"; - this.QuicknesCoreMenuItem.Size = new System.Drawing.Size(119, 22); - this.QuicknesCoreMenuItem.Text = "QuickNES"; - this.QuicknesCoreMenuItem.Click += new System.EventHandler(this.NesCorePick_Click); - // - // NesCoreMenuItem - // - this.NesCoreMenuItem.Name = "NesCoreMenuItem"; - this.NesCoreMenuItem.Size = new System.Drawing.Size(119, 22); - this.NesCoreMenuItem.Text = "NesHawk"; - this.NesCoreMenuItem.Click += new System.EventHandler(this.NesCorePick_Click); - // - // CoreSNESSubMenu - // - this.CoreSNESSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.NesCoreSubMenu.Name = "NesCoreSubMenu"; + this.NesCoreSubMenu.Size = new System.Drawing.Size(239, 22); + this.NesCoreSubMenu.Text = "NES"; + this.NesCoreSubMenu.DropDownOpened += new System.EventHandler(this.NesCoreSubMenu_DropDownOpened); + // + // QuicknesCoreMenuItem + // + this.QuicknesCoreMenuItem.Name = "QuicknesCoreMenuItem"; + this.QuicknesCoreMenuItem.Size = new System.Drawing.Size(126, 22); + this.QuicknesCoreMenuItem.Text = "QuickNES"; + this.QuicknesCoreMenuItem.Click += new System.EventHandler(this.NesCorePick_Click); + // + // NesCoreMenuItem + // + this.NesCoreMenuItem.Name = "NesCoreMenuItem"; + this.NesCoreMenuItem.Size = new System.Drawing.Size(126, 22); + this.NesCoreMenuItem.Text = "NesHawk"; + this.NesCoreMenuItem.Click += new System.EventHandler(this.NesCorePick_Click); + // + // CoreSNESSubMenu + // + this.CoreSNESSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.Coresnes9xMenuItem, this.CorebsnesMenuItem}); - this.CoreSNESSubMenu.Name = "CoreSNESSubMenu"; - this.CoreSNESSubMenu.Size = new System.Drawing.Size(223, 22); - this.CoreSNESSubMenu.Text = "SNES"; - this.CoreSNESSubMenu.DropDownOpened += new System.EventHandler(this.CoreSNESSubMenu_DropDownOpened); - // - // Coresnes9xMenuItem - // - this.Coresnes9xMenuItem.Name = "Coresnes9xMenuItem"; - this.Coresnes9xMenuItem.Size = new System.Drawing.Size(109, 22); - this.Coresnes9xMenuItem.Text = "Snes9x"; - this.Coresnes9xMenuItem.Click += new System.EventHandler(this.CoreSnesToggle_Click); - // - // CorebsnesMenuItem - // - this.CorebsnesMenuItem.Name = "CorebsnesMenuItem"; - this.CorebsnesMenuItem.Size = new System.Drawing.Size(109, 22); - this.CorebsnesMenuItem.Text = "BSNES"; - this.CorebsnesMenuItem.Click += new System.EventHandler(this.CoreSnesToggle_Click); - // - // GbaCoreSubMenu - // - this.GbaCoreSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.CoreSNESSubMenu.Name = "CoreSNESSubMenu"; + this.CoreSNESSubMenu.Size = new System.Drawing.Size(239, 22); + this.CoreSNESSubMenu.Text = "SNES"; + this.CoreSNESSubMenu.DropDownOpened += new System.EventHandler(this.CoreSNESSubMenu_DropDownOpened); + // + // Coresnes9xMenuItem + // + this.Coresnes9xMenuItem.Name = "Coresnes9xMenuItem"; + this.Coresnes9xMenuItem.Size = new System.Drawing.Size(109, 22); + this.Coresnes9xMenuItem.Text = "Snes9x"; + this.Coresnes9xMenuItem.Click += new System.EventHandler(this.CoreSnesToggle_Click); + // + // CorebsnesMenuItem + // + this.CorebsnesMenuItem.Name = "CorebsnesMenuItem"; + this.CorebsnesMenuItem.Size = new System.Drawing.Size(109, 22); + this.CorebsnesMenuItem.Text = "BSNES"; + this.CorebsnesMenuItem.Click += new System.EventHandler(this.CoreSnesToggle_Click); + // + // GbaCoreSubMenu + // + this.GbaCoreSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.VbaNextCoreMenuItem, this.MgbaCoreMenuItem}); - this.GbaCoreSubMenu.Name = "GbaCoreSubMenu"; - this.GbaCoreSubMenu.Size = new System.Drawing.Size(223, 22); - this.GbaCoreSubMenu.Text = "GBA"; - this.GbaCoreSubMenu.DropDownOpened += new System.EventHandler(this.GbaCoreSubMenu_DropDownOpened); - // - // VbaNextCoreMenuItem - // - this.VbaNextCoreMenuItem.Name = "VbaNextCoreMenuItem"; - this.VbaNextCoreMenuItem.Size = new System.Drawing.Size(120, 22); - this.VbaNextCoreMenuItem.Text = "VBA-Next"; - this.VbaNextCoreMenuItem.Click += new System.EventHandler(this.GbaCorePick_Click); - // - // MgbaCoreMenuItem - // - this.MgbaCoreMenuItem.Name = "MgbaCoreMenuItem"; - this.MgbaCoreMenuItem.Size = new System.Drawing.Size(120, 22); - this.MgbaCoreMenuItem.Text = "mGBA"; - this.MgbaCoreMenuItem.Click += new System.EventHandler(this.GbaCorePick_Click); - // - // Atari7800CoreSubMenu - // - this.Atari7800CoreSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.GbaCoreSubMenu.Name = "GbaCoreSubMenu"; + this.GbaCoreSubMenu.Size = new System.Drawing.Size(239, 22); + this.GbaCoreSubMenu.Text = "GBA"; + this.GbaCoreSubMenu.DropDownOpened += new System.EventHandler(this.GbaCoreSubMenu_DropDownOpened); + // + // VbaNextCoreMenuItem + // + this.VbaNextCoreMenuItem.Name = "VbaNextCoreMenuItem"; + this.VbaNextCoreMenuItem.Size = new System.Drawing.Size(125, 22); + this.VbaNextCoreMenuItem.Text = "VBA-Next"; + this.VbaNextCoreMenuItem.Click += new System.EventHandler(this.GbaCorePick_Click); + // + // MgbaCoreMenuItem + // + this.MgbaCoreMenuItem.Name = "MgbaCoreMenuItem"; + this.MgbaCoreMenuItem.Size = new System.Drawing.Size(125, 22); + this.MgbaCoreMenuItem.Text = "mGBA"; + this.MgbaCoreMenuItem.Click += new System.EventHandler(this.GbaCorePick_Click); + // + // Atari7800CoreSubMenu + // + this.Atari7800CoreSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.Emu7800CoreMenuItem, this.Atari7800HawkCoreMenuItem}); - this.Atari7800CoreSubMenu.Name = "Atari7800CoreSubMenu"; - this.Atari7800CoreSubMenu.Size = new System.Drawing.Size(223, 22); - this.Atari7800CoreSubMenu.Text = "Atari 7800"; - this.Atari7800CoreSubMenu.DropDownOpened += new System.EventHandler(this.Atari7800CoreSubMenu_DropDownOpened); - // - // Emu7800CoreMenuItem - // - this.Emu7800CoreMenuItem.Name = "Emu7800CoreMenuItem"; - this.Emu7800CoreMenuItem.Size = new System.Drawing.Size(147, 22); - this.Emu7800CoreMenuItem.Text = "EMU7800"; - this.Emu7800CoreMenuItem.Click += new System.EventHandler(this.Atari7800CorePick_Click); - // - // Atari7800HawkCoreMenuItem - // - this.Atari7800HawkCoreMenuItem.Name = "Atari7800HawkCoreMenuItem"; - this.Atari7800HawkCoreMenuItem.Size = new System.Drawing.Size(147, 22); - this.Atari7800HawkCoreMenuItem.Text = "Atari7800Hawk"; - this.Atari7800HawkCoreMenuItem.Click += new System.EventHandler(this.Atari7800CorePick_Click); - // - // SGBCoreSubmenu - // - this.SGBCoreSubmenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.Atari7800CoreSubMenu.Name = "Atari7800CoreSubMenu"; + this.Atari7800CoreSubMenu.Size = new System.Drawing.Size(239, 22); + this.Atari7800CoreSubMenu.Text = "Atari 7800"; + this.Atari7800CoreSubMenu.DropDownOpened += new System.EventHandler(this.Atari7800CoreSubMenu_DropDownOpened); + // + // Emu7800CoreMenuItem + // + this.Emu7800CoreMenuItem.Name = "Emu7800CoreMenuItem"; + this.Emu7800CoreMenuItem.Size = new System.Drawing.Size(153, 22); + this.Emu7800CoreMenuItem.Text = "EMU7800"; + this.Emu7800CoreMenuItem.Click += new System.EventHandler(this.Atari7800CorePick_Click); + // + // Atari7800HawkCoreMenuItem + // + this.Atari7800HawkCoreMenuItem.Name = "Atari7800HawkCoreMenuItem"; + this.Atari7800HawkCoreMenuItem.Size = new System.Drawing.Size(153, 22); + this.Atari7800HawkCoreMenuItem.Text = "Atari7800Hawk"; + this.Atari7800HawkCoreMenuItem.Click += new System.EventHandler(this.Atari7800CorePick_Click); + // + // SGBCoreSubmenu + // + this.SGBCoreSubmenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.SgbBsnesMenuItem, - this.SgbPizzaBoyMenuItem}); - this.SGBCoreSubmenu.Name = "SGBCoreSubmenu"; - this.SGBCoreSubmenu.Size = new System.Drawing.Size(223, 22); - this.SGBCoreSubmenu.Text = "SGB"; - this.SGBCoreSubmenu.DropDownOpened += new System.EventHandler(this.SGBCoreSubmenu_DropDownOpened); - // - // SgbBsnesMenuItem - // - this.SgbBsnesMenuItem.Name = "SgbBsnesMenuItem"; - this.SgbBsnesMenuItem.Size = new System.Drawing.Size(119, 22); - this.SgbBsnesMenuItem.Text = "BSNES"; - this.SgbBsnesMenuItem.Click += new System.EventHandler(this.SgbCorePick_Click); - // - // SgbPizzaBoyMenuItem - // - this.SgbPizzaBoyMenuItem.Name = "SgbPizzaBoyMenuItem"; - this.SgbPizzaBoyMenuItem.Size = new System.Drawing.Size(119, 22); - this.SgbPizzaBoyMenuItem.Text = "Pizza Boy"; - this.SgbPizzaBoyMenuItem.Click += new System.EventHandler(this.SgbCorePick_Click); - // - // GBInSGBMenuItem - // - this.GBInSGBMenuItem.Name = "GBInSGBMenuItem"; - this.GBInSGBMenuItem.Size = new System.Drawing.Size(223, 22); - this.GBInSGBMenuItem.Text = "GB in SGB"; - this.GBInSGBMenuItem.Click += new System.EventHandler(this.GbInSgbMenuItem_Click); - // - // toolStripMenuItem16 - // - this.toolStripMenuItem16.Name = "toolStripMenuItem16"; - this.toolStripMenuItem16.Size = new System.Drawing.Size(220, 6); - // - // allowGameDBCoreOverridesToolStripMenuItem - // - this.allowGameDBCoreOverridesToolStripMenuItem.Name = "allowGameDBCoreOverridesToolStripMenuItem"; - this.allowGameDBCoreOverridesToolStripMenuItem.Size = new System.Drawing.Size(223, 22); - this.allowGameDBCoreOverridesToolStripMenuItem.Text = "Follow GameDB Core Overrides"; - this.allowGameDBCoreOverridesToolStripMenuItem.Click += new System.EventHandler(this.AllowGameDBCoreOverridesToolStripMenuItem_Click); - // - // toolStripSeparator8 - // - this.toolStripSeparator8.Name = "toolStripSeparator8"; - this.toolStripSeparator8.Size = new System.Drawing.Size(220, 6); - // - // N64VideoPluginSettingsMenuItem - // - this.N64VideoPluginSettingsMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.monitor; - this.N64VideoPluginSettingsMenuItem.Name = "N64VideoPluginSettingsMenuItem"; - this.N64VideoPluginSettingsMenuItem.Size = new System.Drawing.Size(223, 22); - this.N64VideoPluginSettingsMenuItem.Text = "N64 Video Plugin Settings"; - this.N64VideoPluginSettingsMenuItem.Click += new System.EventHandler(this.N64VideoPluginSettingsMenuItem_Click); - // - // setLibretroCoreToolStripMenuItem - // - this.setLibretroCoreToolStripMenuItem.Name = "setLibretroCoreToolStripMenuItem"; - this.setLibretroCoreToolStripMenuItem.Size = new System.Drawing.Size(223, 22); - this.setLibretroCoreToolStripMenuItem.Text = "Set Libretro Core"; - this.setLibretroCoreToolStripMenuItem.Click += new System.EventHandler(this.SetLibretroCoreMenuItem_Click); - // - // toolStripSeparator10 - // - this.toolStripSeparator10.Name = "toolStripSeparator10"; - this.toolStripSeparator10.Size = new System.Drawing.Size(167, 6); - // - // SaveConfigMenuItem - // - this.SaveConfigMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.Save; - this.SaveConfigMenuItem.Name = "SaveConfigMenuItem"; - this.SaveConfigMenuItem.Size = new System.Drawing.Size(170, 22); - this.SaveConfigMenuItem.Text = "Save Config"; - this.SaveConfigMenuItem.Click += new System.EventHandler(this.SaveConfigMenuItem_Click); - // - // SaveConfigAsMenuItem - // - this.SaveConfigAsMenuItem.Name = "SaveConfigAsMenuItem"; - this.SaveConfigAsMenuItem.Size = new System.Drawing.Size(170, 22); - this.SaveConfigAsMenuItem.Text = "Save Config As..."; - this.SaveConfigAsMenuItem.Click += new System.EventHandler(this.SaveConfigAsMenuItem_Click); - // - // LoadConfigMenuItem - // - this.LoadConfigMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.LoadConfig; - this.LoadConfigMenuItem.Name = "LoadConfigMenuItem"; - this.LoadConfigMenuItem.Size = new System.Drawing.Size(170, 22); - this.LoadConfigMenuItem.Text = "Load Config"; - this.LoadConfigMenuItem.Click += new System.EventHandler(this.LoadConfigMenuItem_Click); - // - // LoadConfigFromMenuItem - // - this.LoadConfigFromMenuItem.Name = "LoadConfigFromMenuItem"; - this.LoadConfigFromMenuItem.Size = new System.Drawing.Size(170, 22); - this.LoadConfigFromMenuItem.Text = "Load Config From..."; - this.LoadConfigFromMenuItem.Click += new System.EventHandler(this.LoadConfigFromMenuItem_Click); - // - // ToolsSubMenu - // - this.ToolsSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.SgbSameBoyMenuItem}); + this.SGBCoreSubmenu.Name = "SGBCoreSubmenu"; + this.SGBCoreSubmenu.Size = new System.Drawing.Size(239, 22); + this.SGBCoreSubmenu.Text = "SGB"; + this.SGBCoreSubmenu.DropDownOpened += new System.EventHandler(this.SGBCoreSubmenu_DropDownOpened); + // + // SgbBsnesMenuItem + // + this.SgbBsnesMenuItem.Name = "SgbBsnesMenuItem"; + this.SgbBsnesMenuItem.Size = new System.Drawing.Size(152, 22); + this.SgbBsnesMenuItem.Text = "BSNES"; + this.SgbBsnesMenuItem.Click += new System.EventHandler(this.SgbCorePick_Click); + // + // SgbSameBoyMenuItem + // + this.SgbSameBoyMenuItem.Name = "SgbSameBoyMenuItem"; + this.SgbSameBoyMenuItem.Size = new System.Drawing.Size(152, 22); + this.SgbSameBoyMenuItem.Text = "SameBoy"; + this.SgbSameBoyMenuItem.Click += new System.EventHandler(this.SgbCorePick_Click); + // + // GBInSGBMenuItem + // + this.GBInSGBMenuItem.Name = "GBInSGBMenuItem"; + this.GBInSGBMenuItem.Size = new System.Drawing.Size(239, 22); + this.GBInSGBMenuItem.Text = "GB in SGB"; + this.GBInSGBMenuItem.Click += new System.EventHandler(this.GbInSgbMenuItem_Click); + // + // toolStripMenuItem16 + // + this.toolStripMenuItem16.Name = "toolStripMenuItem16"; + this.toolStripMenuItem16.Size = new System.Drawing.Size(236, 6); + // + // allowGameDBCoreOverridesToolStripMenuItem + // + this.allowGameDBCoreOverridesToolStripMenuItem.Name = "allowGameDBCoreOverridesToolStripMenuItem"; + this.allowGameDBCoreOverridesToolStripMenuItem.Size = new System.Drawing.Size(239, 22); + this.allowGameDBCoreOverridesToolStripMenuItem.Text = "Follow GameDB Core Overrides"; + this.allowGameDBCoreOverridesToolStripMenuItem.Click += new System.EventHandler(this.AllowGameDBCoreOverridesToolStripMenuItem_Click); + // + // toolStripSeparator8 + // + this.toolStripSeparator8.Name = "toolStripSeparator8"; + this.toolStripSeparator8.Size = new System.Drawing.Size(236, 6); + // + // N64VideoPluginSettingsMenuItem + // + this.N64VideoPluginSettingsMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.monitor; + this.N64VideoPluginSettingsMenuItem.Name = "N64VideoPluginSettingsMenuItem"; + this.N64VideoPluginSettingsMenuItem.Size = new System.Drawing.Size(239, 22); + this.N64VideoPluginSettingsMenuItem.Text = "N64 Video Plugin Settings"; + this.N64VideoPluginSettingsMenuItem.Click += new System.EventHandler(this.N64VideoPluginSettingsMenuItem_Click); + // + // setLibretroCoreToolStripMenuItem + // + this.setLibretroCoreToolStripMenuItem.Name = "setLibretroCoreToolStripMenuItem"; + this.setLibretroCoreToolStripMenuItem.Size = new System.Drawing.Size(239, 22); + this.setLibretroCoreToolStripMenuItem.Text = "Set Libretro Core"; + this.setLibretroCoreToolStripMenuItem.Click += new System.EventHandler(this.SetLibretroCoreMenuItem_Click); + // + // toolStripSeparator10 + // + this.toolStripSeparator10.Name = "toolStripSeparator10"; + this.toolStripSeparator10.Size = new System.Drawing.Size(176, 6); + // + // SaveConfigMenuItem + // + this.SaveConfigMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.Save; + this.SaveConfigMenuItem.Name = "SaveConfigMenuItem"; + this.SaveConfigMenuItem.Size = new System.Drawing.Size(179, 22); + this.SaveConfigMenuItem.Text = "Save Config"; + this.SaveConfigMenuItem.Click += new System.EventHandler(this.SaveConfigMenuItem_Click); + // + // SaveConfigAsMenuItem + // + this.SaveConfigAsMenuItem.Name = "SaveConfigAsMenuItem"; + this.SaveConfigAsMenuItem.Size = new System.Drawing.Size(179, 22); + this.SaveConfigAsMenuItem.Text = "Save Config As..."; + this.SaveConfigAsMenuItem.Click += new System.EventHandler(this.SaveConfigAsMenuItem_Click); + // + // LoadConfigMenuItem + // + this.LoadConfigMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.LoadConfig; + this.LoadConfigMenuItem.Name = "LoadConfigMenuItem"; + this.LoadConfigMenuItem.Size = new System.Drawing.Size(179, 22); + this.LoadConfigMenuItem.Text = "Load Config"; + this.LoadConfigMenuItem.Click += new System.EventHandler(this.LoadConfigMenuItem_Click); + // + // LoadConfigFromMenuItem + // + this.LoadConfigFromMenuItem.Name = "LoadConfigFromMenuItem"; + this.LoadConfigFromMenuItem.Size = new System.Drawing.Size(179, 22); + this.LoadConfigFromMenuItem.Text = "Load Config From..."; + this.LoadConfigFromMenuItem.Click += new System.EventHandler(this.LoadConfigFromMenuItem_Click); + // + // ToolsSubMenu + // + this.ToolsSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.ToolBoxMenuItem, this.toolStripSeparator12, this.RamWatchMenuItem, @@ -2035,194 +2035,194 @@ this.externalToolToolStripMenuItem, this.batchRunnerToolStripMenuItem, this.ExperimentalToolsSubMenu}); - this.ToolsSubMenu.Name = "ToolsSubMenu"; - this.ToolsSubMenu.Size = new System.Drawing.Size(44, 17); - this.ToolsSubMenu.Text = "&Tools"; - this.ToolsSubMenu.DropDownOpened += new System.EventHandler(this.ToolsSubMenu_DropDownOpened); - // - // ToolBoxMenuItem - // - this.ToolBoxMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.ToolBox; - this.ToolBoxMenuItem.Name = "ToolBoxMenuItem"; - this.ToolBoxMenuItem.Size = new System.Drawing.Size(183, 22); - this.ToolBoxMenuItem.Text = "&Tool Box"; - this.ToolBoxMenuItem.Click += new System.EventHandler(this.ToolBoxMenuItem_Click); - // - // toolStripSeparator12 - // - this.toolStripSeparator12.Name = "toolStripSeparator12"; - this.toolStripSeparator12.Size = new System.Drawing.Size(180, 6); - // - // RamWatchMenuItem - // - this.RamWatchMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.watch; - this.RamWatchMenuItem.Name = "RamWatchMenuItem"; - this.RamWatchMenuItem.Size = new System.Drawing.Size(183, 22); - this.RamWatchMenuItem.Text = "RAM &Watch"; - this.RamWatchMenuItem.Click += new System.EventHandler(this.RamWatchMenuItem_Click); - // - // RamSearchMenuItem - // - this.RamSearchMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.search; - this.RamSearchMenuItem.Name = "RamSearchMenuItem"; - this.RamSearchMenuItem.Size = new System.Drawing.Size(183, 22); - this.RamSearchMenuItem.Text = "RAM &Search"; - this.RamSearchMenuItem.Click += new System.EventHandler(this.RamSearchMenuItem_Click); - // - // LuaConsoleMenuItem - // - this.LuaConsoleMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.Lua; - this.LuaConsoleMenuItem.Name = "LuaConsoleMenuItem"; - this.LuaConsoleMenuItem.Size = new System.Drawing.Size(183, 22); - this.LuaConsoleMenuItem.Text = "Lua Console"; - this.LuaConsoleMenuItem.Click += new System.EventHandler(this.LuaConsoleMenuItem_Click); - // - // TAStudioMenuItem - // - this.TAStudioMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.TAStudio; - this.TAStudioMenuItem.Name = "TAStudioMenuItem"; - this.TAStudioMenuItem.Size = new System.Drawing.Size(183, 22); - this.TAStudioMenuItem.Text = "&TAStudio"; - this.TAStudioMenuItem.Click += new System.EventHandler(this.TAStudioMenuItem_Click); - // - // HexEditorMenuItem - // - this.HexEditorMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.poke; - this.HexEditorMenuItem.Name = "HexEditorMenuItem"; - this.HexEditorMenuItem.Size = new System.Drawing.Size(183, 22); - this.HexEditorMenuItem.Text = "&Hex Editor"; - this.HexEditorMenuItem.Click += new System.EventHandler(this.HexEditorMenuItem_Click); - // - // TraceLoggerMenuItem - // - this.TraceLoggerMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.pencil; - this.TraceLoggerMenuItem.Name = "TraceLoggerMenuItem"; - this.TraceLoggerMenuItem.Size = new System.Drawing.Size(183, 22); - this.TraceLoggerMenuItem.Text = "Trace &Logger"; - this.TraceLoggerMenuItem.Click += new System.EventHandler(this.TraceLoggerMenuItem_Click); - // - // DebuggerMenuItem - // - this.DebuggerMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.Bug; - this.DebuggerMenuItem.Name = "DebuggerMenuItem"; - this.DebuggerMenuItem.Size = new System.Drawing.Size(183, 22); - this.DebuggerMenuItem.Text = "&Debugger"; - this.DebuggerMenuItem.Click += new System.EventHandler(this.DebuggerMenuItem_Click); - // - // CodeDataLoggerMenuItem - // - this.CodeDataLoggerMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.cdlogger; - this.CodeDataLoggerMenuItem.Name = "CodeDataLoggerMenuItem"; - this.CodeDataLoggerMenuItem.Size = new System.Drawing.Size(183, 22); - this.CodeDataLoggerMenuItem.Text = "Code-Data Logger"; - this.CodeDataLoggerMenuItem.Click += new System.EventHandler(this.CodeDataLoggerMenuItem_Click); - // - // MacroToolMenuItem - // - this.MacroToolMenuItem.Name = "MacroToolMenuItem"; - this.MacroToolMenuItem.Size = new System.Drawing.Size(183, 22); - this.MacroToolMenuItem.Text = "&Macro Tool"; - this.MacroToolMenuItem.Click += new System.EventHandler(this.MacroToolMenuItem_Click); - // - // VirtualPadMenuItem - // - this.VirtualPadMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.GameController; - this.VirtualPadMenuItem.Name = "VirtualPadMenuItem"; - this.VirtualPadMenuItem.Size = new System.Drawing.Size(183, 22); - this.VirtualPadMenuItem.Text = "Virtual Pad"; - this.VirtualPadMenuItem.Click += new System.EventHandler(this.VirtualPadMenuItem_Click); - // - // BasicBotMenuItem - // - this.BasicBotMenuItem.Name = "BasicBotMenuItem"; - this.BasicBotMenuItem.Size = new System.Drawing.Size(183, 22); - this.BasicBotMenuItem.Text = "Basic Bot"; - this.BasicBotMenuItem.Click += new System.EventHandler(this.BasicBotMenuItem_Click); - // - // toolStripSeparator11 - // - this.toolStripSeparator11.Name = "toolStripSeparator11"; - this.toolStripSeparator11.Size = new System.Drawing.Size(180, 6); - // - // CheatsMenuItem - // - this.CheatsMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.Freeze; - this.CheatsMenuItem.Name = "CheatsMenuItem"; - this.CheatsMenuItem.Size = new System.Drawing.Size(183, 22); - this.CheatsMenuItem.Text = "Cheats"; - this.CheatsMenuItem.Click += new System.EventHandler(this.CheatsMenuItem_Click); - // - // gameSharkConverterToolStripMenuItem - // - this.gameSharkConverterToolStripMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.Shark; - this.gameSharkConverterToolStripMenuItem.Name = "gameSharkConverterToolStripMenuItem"; - this.gameSharkConverterToolStripMenuItem.Size = new System.Drawing.Size(183, 22); - this.gameSharkConverterToolStripMenuItem.Text = "Cheat Code Converter"; - this.gameSharkConverterToolStripMenuItem.Click += new System.EventHandler(this.CheatCodeConverterMenuItem_Click); - // - // toolStripSeparator29 - // - this.toolStripSeparator29.Name = "toolStripSeparator29"; - this.toolStripSeparator29.Size = new System.Drawing.Size(180, 6); - // - // MultiDiskBundlerFileMenuItem - // - this.MultiDiskBundlerFileMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.SaveConfig; - this.MultiDiskBundlerFileMenuItem.Name = "MultiDiskBundlerFileMenuItem"; - this.MultiDiskBundlerFileMenuItem.Size = new System.Drawing.Size(183, 22); - this.MultiDiskBundlerFileMenuItem.Text = "Multi-disk Bundler"; - this.MultiDiskBundlerFileMenuItem.Click += new System.EventHandler(this.MultidiskBundlerMenuItem_Click); - // - // externalToolToolStripMenuItem - // - this.externalToolToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.ToolsSubMenu.Name = "ToolsSubMenu"; + this.ToolsSubMenu.Size = new System.Drawing.Size(47, 19); + this.ToolsSubMenu.Text = "&Tools"; + this.ToolsSubMenu.DropDownOpened += new System.EventHandler(this.ToolsSubMenu_DropDownOpened); + // + // ToolBoxMenuItem + // + this.ToolBoxMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.ToolBox; + this.ToolBoxMenuItem.Name = "ToolBoxMenuItem"; + this.ToolBoxMenuItem.Size = new System.Drawing.Size(191, 22); + this.ToolBoxMenuItem.Text = "&Tool Box"; + this.ToolBoxMenuItem.Click += new System.EventHandler(this.ToolBoxMenuItem_Click); + // + // toolStripSeparator12 + // + this.toolStripSeparator12.Name = "toolStripSeparator12"; + this.toolStripSeparator12.Size = new System.Drawing.Size(188, 6); + // + // RamWatchMenuItem + // + this.RamWatchMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.watch; + this.RamWatchMenuItem.Name = "RamWatchMenuItem"; + this.RamWatchMenuItem.Size = new System.Drawing.Size(191, 22); + this.RamWatchMenuItem.Text = "RAM &Watch"; + this.RamWatchMenuItem.Click += new System.EventHandler(this.RamWatchMenuItem_Click); + // + // RamSearchMenuItem + // + this.RamSearchMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.search; + this.RamSearchMenuItem.Name = "RamSearchMenuItem"; + this.RamSearchMenuItem.Size = new System.Drawing.Size(191, 22); + this.RamSearchMenuItem.Text = "RAM &Search"; + this.RamSearchMenuItem.Click += new System.EventHandler(this.RamSearchMenuItem_Click); + // + // LuaConsoleMenuItem + // + this.LuaConsoleMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.Lua; + this.LuaConsoleMenuItem.Name = "LuaConsoleMenuItem"; + this.LuaConsoleMenuItem.Size = new System.Drawing.Size(191, 22); + this.LuaConsoleMenuItem.Text = "Lua Console"; + this.LuaConsoleMenuItem.Click += new System.EventHandler(this.LuaConsoleMenuItem_Click); + // + // TAStudioMenuItem + // + this.TAStudioMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.TAStudio; + this.TAStudioMenuItem.Name = "TAStudioMenuItem"; + this.TAStudioMenuItem.Size = new System.Drawing.Size(191, 22); + this.TAStudioMenuItem.Text = "&TAStudio"; + this.TAStudioMenuItem.Click += new System.EventHandler(this.TAStudioMenuItem_Click); + // + // HexEditorMenuItem + // + this.HexEditorMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.poke; + this.HexEditorMenuItem.Name = "HexEditorMenuItem"; + this.HexEditorMenuItem.Size = new System.Drawing.Size(191, 22); + this.HexEditorMenuItem.Text = "&Hex Editor"; + this.HexEditorMenuItem.Click += new System.EventHandler(this.HexEditorMenuItem_Click); + // + // TraceLoggerMenuItem + // + this.TraceLoggerMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.pencil; + this.TraceLoggerMenuItem.Name = "TraceLoggerMenuItem"; + this.TraceLoggerMenuItem.Size = new System.Drawing.Size(191, 22); + this.TraceLoggerMenuItem.Text = "Trace &Logger"; + this.TraceLoggerMenuItem.Click += new System.EventHandler(this.TraceLoggerMenuItem_Click); + // + // DebuggerMenuItem + // + this.DebuggerMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.Bug; + this.DebuggerMenuItem.Name = "DebuggerMenuItem"; + this.DebuggerMenuItem.Size = new System.Drawing.Size(191, 22); + this.DebuggerMenuItem.Text = "&Debugger"; + this.DebuggerMenuItem.Click += new System.EventHandler(this.DebuggerMenuItem_Click); + // + // CodeDataLoggerMenuItem + // + this.CodeDataLoggerMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.cdlogger; + this.CodeDataLoggerMenuItem.Name = "CodeDataLoggerMenuItem"; + this.CodeDataLoggerMenuItem.Size = new System.Drawing.Size(191, 22); + this.CodeDataLoggerMenuItem.Text = "Code-Data Logger"; + this.CodeDataLoggerMenuItem.Click += new System.EventHandler(this.CodeDataLoggerMenuItem_Click); + // + // MacroToolMenuItem + // + this.MacroToolMenuItem.Name = "MacroToolMenuItem"; + this.MacroToolMenuItem.Size = new System.Drawing.Size(191, 22); + this.MacroToolMenuItem.Text = "&Macro Tool"; + this.MacroToolMenuItem.Click += new System.EventHandler(this.MacroToolMenuItem_Click); + // + // VirtualPadMenuItem + // + this.VirtualPadMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.GameController; + this.VirtualPadMenuItem.Name = "VirtualPadMenuItem"; + this.VirtualPadMenuItem.Size = new System.Drawing.Size(191, 22); + this.VirtualPadMenuItem.Text = "Virtual Pad"; + this.VirtualPadMenuItem.Click += new System.EventHandler(this.VirtualPadMenuItem_Click); + // + // BasicBotMenuItem + // + this.BasicBotMenuItem.Name = "BasicBotMenuItem"; + this.BasicBotMenuItem.Size = new System.Drawing.Size(191, 22); + this.BasicBotMenuItem.Text = "Basic Bot"; + this.BasicBotMenuItem.Click += new System.EventHandler(this.BasicBotMenuItem_Click); + // + // toolStripSeparator11 + // + this.toolStripSeparator11.Name = "toolStripSeparator11"; + this.toolStripSeparator11.Size = new System.Drawing.Size(188, 6); + // + // CheatsMenuItem + // + this.CheatsMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.Freeze; + this.CheatsMenuItem.Name = "CheatsMenuItem"; + this.CheatsMenuItem.Size = new System.Drawing.Size(191, 22); + this.CheatsMenuItem.Text = "Cheats"; + this.CheatsMenuItem.Click += new System.EventHandler(this.CheatsMenuItem_Click); + // + // gameSharkConverterToolStripMenuItem + // + this.gameSharkConverterToolStripMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.Shark; + this.gameSharkConverterToolStripMenuItem.Name = "gameSharkConverterToolStripMenuItem"; + this.gameSharkConverterToolStripMenuItem.Size = new System.Drawing.Size(191, 22); + this.gameSharkConverterToolStripMenuItem.Text = "Cheat Code Converter"; + this.gameSharkConverterToolStripMenuItem.Click += new System.EventHandler(this.CheatCodeConverterMenuItem_Click); + // + // toolStripSeparator29 + // + this.toolStripSeparator29.Name = "toolStripSeparator29"; + this.toolStripSeparator29.Size = new System.Drawing.Size(188, 6); + // + // MultiDiskBundlerFileMenuItem + // + this.MultiDiskBundlerFileMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.SaveConfig; + this.MultiDiskBundlerFileMenuItem.Name = "MultiDiskBundlerFileMenuItem"; + this.MultiDiskBundlerFileMenuItem.Size = new System.Drawing.Size(191, 22); + this.MultiDiskBundlerFileMenuItem.Text = "Multi-disk Bundler"; + this.MultiDiskBundlerFileMenuItem.Click += new System.EventHandler(this.MultidiskBundlerMenuItem_Click); + // + // externalToolToolStripMenuItem + // + this.externalToolToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.dummyExternalTool}); - this.externalToolToolStripMenuItem.Name = "externalToolToolStripMenuItem"; - this.externalToolToolStripMenuItem.Size = new System.Drawing.Size(183, 22); - this.externalToolToolStripMenuItem.Text = "External Tool"; - this.externalToolToolStripMenuItem.DropDownOpening += new System.EventHandler(this.ExternalToolToolStripMenuItem_DropDownOpening); - // - // dummyExternalTool - // - this.dummyExternalTool.Name = "dummyExternalTool"; - this.dummyExternalTool.Size = new System.Drawing.Size(99, 22); - this.dummyExternalTool.Text = "None"; - // - // batchRunnerToolStripMenuItem - // - this.batchRunnerToolStripMenuItem.Name = "batchRunnerToolStripMenuItem"; - this.batchRunnerToolStripMenuItem.Size = new System.Drawing.Size(183, 22); - this.batchRunnerToolStripMenuItem.Text = "Batch Runner"; - this.batchRunnerToolStripMenuItem.Visible = false; - this.batchRunnerToolStripMenuItem.Click += new System.EventHandler(this.BatchRunnerToolStripMenuItem_Click); - // - // ExperimentalToolsSubMenu - // - this.ExperimentalToolsSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.externalToolToolStripMenuItem.Name = "externalToolToolStripMenuItem"; + this.externalToolToolStripMenuItem.Size = new System.Drawing.Size(191, 22); + this.externalToolToolStripMenuItem.Text = "External Tool"; + this.externalToolToolStripMenuItem.DropDownOpening += new System.EventHandler(this.ExternalToolToolStripMenuItem_DropDownOpening); + // + // dummyExternalTool + // + this.dummyExternalTool.Name = "dummyExternalTool"; + this.dummyExternalTool.Size = new System.Drawing.Size(103, 22); + this.dummyExternalTool.Text = "None"; + // + // batchRunnerToolStripMenuItem + // + this.batchRunnerToolStripMenuItem.Name = "batchRunnerToolStripMenuItem"; + this.batchRunnerToolStripMenuItem.Size = new System.Drawing.Size(191, 22); + this.batchRunnerToolStripMenuItem.Text = "Batch Runner"; + this.batchRunnerToolStripMenuItem.Visible = false; + this.batchRunnerToolStripMenuItem.Click += new System.EventHandler(this.BatchRunnerToolStripMenuItem_Click); + // + // ExperimentalToolsSubMenu + // + this.ExperimentalToolsSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.AutoHawkMenuItem, this.NewHexEditorMenuItem}); - this.ExperimentalToolsSubMenu.Name = "ExperimentalToolsSubMenu"; - this.ExperimentalToolsSubMenu.Size = new System.Drawing.Size(183, 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(148, 22); - this.AutoHawkMenuItem.Text = "AutoHawk"; - this.AutoHawkMenuItem.Click += new System.EventHandler(this.AutoHawkMenuItem_Click); - // - // NewHexEditorMenuItem - // - this.NewHexEditorMenuItem.Name = "NewHexEditorMenuItem"; - this.NewHexEditorMenuItem.Size = new System.Drawing.Size(148, 22); - this.NewHexEditorMenuItem.Text = "New Hex Editor"; - this.NewHexEditorMenuItem.Click += new System.EventHandler(this.NewHexEditorMenuItem_Click); - // - // NESSubMenu - // - this.NESSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + 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"; + this.NewHexEditorMenuItem.Size = new System.Drawing.Size(155, 22); + this.NewHexEditorMenuItem.Text = "New Hex Editor"; + this.NewHexEditorMenuItem.Click += new System.EventHandler(this.NewHexEditorMenuItem_Click); + // + // NESSubMenu + // + this.NESSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.coreToolStripMenuItem, this.toolStripSeparator34, this.NESPPUViewerMenuItem, @@ -2239,173 +2239,173 @@ this.FDSControlsMenuItem, this.VSControlsMenuItem, this.barcodeReaderToolStripMenuItem}); - this.NESSubMenu.Name = "NESSubMenu"; - this.NESSubMenu.Size = new System.Drawing.Size(38, 17); - this.NESSubMenu.Text = "&NES"; - this.NESSubMenu.DropDownOpened += new System.EventHandler(this.NESSubMenu_DropDownOpened); - // - // coreToolStripMenuItem - // - this.coreToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.NESSubMenu.Name = "NESSubMenu"; + this.NESSubMenu.Size = new System.Drawing.Size(40, 19); + this.NESSubMenu.Text = "&NES"; + this.NESSubMenu.DropDownOpened += new System.EventHandler(this.NESSubMenu_DropDownOpened); + // + // coreToolStripMenuItem + // + this.coreToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.quickNESToolStripMenuItem, this.nesHawkToolStripMenuItem}); - this.coreToolStripMenuItem.Name = "coreToolStripMenuItem"; - this.coreToolStripMenuItem.Size = new System.Drawing.Size(217, 22); - this.coreToolStripMenuItem.Text = "&Core"; - this.coreToolStripMenuItem.DropDownOpened += new System.EventHandler(this.CoreToolStripMenuItem_DropDownOpened); - // - // quickNESToolStripMenuItem - // - this.quickNESToolStripMenuItem.Name = "quickNESToolStripMenuItem"; - this.quickNESToolStripMenuItem.Size = new System.Drawing.Size(118, 22); - this.quickNESToolStripMenuItem.Text = "&QuickNes"; - this.quickNESToolStripMenuItem.Click += new System.EventHandler(this.QuickNesToolStripMenuItem_Click); - // - // nesHawkToolStripMenuItem - // - this.nesHawkToolStripMenuItem.Name = "nesHawkToolStripMenuItem"; - this.nesHawkToolStripMenuItem.Size = new System.Drawing.Size(118, 22); - this.nesHawkToolStripMenuItem.Text = "&NesHawk"; - this.nesHawkToolStripMenuItem.Click += new System.EventHandler(this.NesHawkToolStripMenuItem_Click); - // - // toolStripSeparator34 - // - this.toolStripSeparator34.Name = "toolStripSeparator34"; - this.toolStripSeparator34.Size = new System.Drawing.Size(214, 6); - // - // NESPPUViewerMenuItem - // - this.NESPPUViewerMenuItem.Name = "NESPPUViewerMenuItem"; - this.NESPPUViewerMenuItem.Size = new System.Drawing.Size(217, 22); - this.NESPPUViewerMenuItem.Text = "&PPU Viewer"; - this.NESPPUViewerMenuItem.Click += new System.EventHandler(this.NesPPUViewerMenuItem_Click); - // - // NESNametableViewerMenuItem - // - this.NESNametableViewerMenuItem.Name = "NESNametableViewerMenuItem"; - this.NESNametableViewerMenuItem.Size = new System.Drawing.Size(217, 22); - this.NESNametableViewerMenuItem.Text = "&Nametable Viewer"; - this.NESNametableViewerMenuItem.Click += new System.EventHandler(this.NESNametableViewerMenuItem_Click); - // - // NESGameGenieCodesMenuItem - // - this.NESGameGenieCodesMenuItem.Name = "NESGameGenieCodesMenuItem"; - this.NESGameGenieCodesMenuItem.Size = new System.Drawing.Size(217, 22); - this.NESGameGenieCodesMenuItem.Text = "&Game Genie Encoder/Decoder"; - this.NESGameGenieCodesMenuItem.Click += new System.EventHandler(this.NESGameGenieCodesMenuItem_Click); - // - // musicRipperToolStripMenuItem - // - this.musicRipperToolStripMenuItem.Name = "musicRipperToolStripMenuItem"; - this.musicRipperToolStripMenuItem.Size = new System.Drawing.Size(217, 22); - this.musicRipperToolStripMenuItem.Text = "Music Ripper"; - this.musicRipperToolStripMenuItem.Click += new System.EventHandler(this.MusicRipperMenuItem_Click); - // - // toolStripSeparator17 - // - this.toolStripSeparator17.Name = "toolStripSeparator17"; - this.toolStripSeparator17.Size = new System.Drawing.Size(214, 6); - // - // NesControllerSettingsMenuItem - // - this.NesControllerSettingsMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.GameController; - this.NesControllerSettingsMenuItem.Name = "NesControllerSettingsMenuItem"; - this.NesControllerSettingsMenuItem.Size = new System.Drawing.Size(217, 22); - this.NesControllerSettingsMenuItem.Text = "Controller Settings..."; - this.NesControllerSettingsMenuItem.Click += new System.EventHandler(this.NesControllerSettingsMenuItem_Click); - // - // NESGraphicSettingsMenuItem - // - this.NESGraphicSettingsMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.tvIcon; - this.NESGraphicSettingsMenuItem.Name = "NESGraphicSettingsMenuItem"; - this.NESGraphicSettingsMenuItem.Size = new System.Drawing.Size(217, 22); - this.NESGraphicSettingsMenuItem.Text = "Graphics Settings..."; - this.NESGraphicSettingsMenuItem.Click += new System.EventHandler(this.NESGraphicSettingsMenuItem_Click); - // - // NESSoundChannelsMenuItem - // - this.NESSoundChannelsMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.AudioHS; - this.NESSoundChannelsMenuItem.Name = "NESSoundChannelsMenuItem"; - this.NESSoundChannelsMenuItem.Size = new System.Drawing.Size(217, 22); - this.NESSoundChannelsMenuItem.Text = "Sound Channels..."; - this.NESSoundChannelsMenuItem.Click += new System.EventHandler(this.NESSoundChannelsMenuItem_Click); - // - // VSSettingsMenuItem - // - this.VSSettingsMenuItem.Name = "VSSettingsMenuItem"; - this.VSSettingsMenuItem.Size = new System.Drawing.Size(217, 22); - this.VSSettingsMenuItem.Text = "VS Settings..."; - this.VSSettingsMenuItem.Click += new System.EventHandler(this.VsSettingsMenuItem_Click); - // - // MovieSettingsMenuItem - // - this.MovieSettingsMenuItem.Name = "MovieSettingsMenuItem"; - this.MovieSettingsMenuItem.Size = new System.Drawing.Size(217, 22); - this.MovieSettingsMenuItem.Text = "Advanced Settings..."; - this.MovieSettingsMenuItem.Click += new System.EventHandler(this.MovieSettingsMenuItem_Click); - // - // toolStripSeparator22 - // - this.toolStripSeparator22.Name = "toolStripSeparator22"; - this.toolStripSeparator22.Size = new System.Drawing.Size(214, 6); - // - // FDSControlsMenuItem - // - this.FDSControlsMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.coreToolStripMenuItem.Name = "coreToolStripMenuItem"; + this.coreToolStripMenuItem.Size = new System.Drawing.Size(233, 22); + this.coreToolStripMenuItem.Text = "&Core"; + this.coreToolStripMenuItem.DropDownOpened += new System.EventHandler(this.CoreToolStripMenuItem_DropDownOpened); + // + // quickNESToolStripMenuItem + // + this.quickNESToolStripMenuItem.Name = "quickNESToolStripMenuItem"; + this.quickNESToolStripMenuItem.Size = new System.Drawing.Size(125, 22); + this.quickNESToolStripMenuItem.Text = "&QuickNes"; + this.quickNESToolStripMenuItem.Click += new System.EventHandler(this.QuickNesToolStripMenuItem_Click); + // + // nesHawkToolStripMenuItem + // + this.nesHawkToolStripMenuItem.Name = "nesHawkToolStripMenuItem"; + this.nesHawkToolStripMenuItem.Size = new System.Drawing.Size(125, 22); + this.nesHawkToolStripMenuItem.Text = "&NesHawk"; + this.nesHawkToolStripMenuItem.Click += new System.EventHandler(this.NesHawkToolStripMenuItem_Click); + // + // toolStripSeparator34 + // + this.toolStripSeparator34.Name = "toolStripSeparator34"; + this.toolStripSeparator34.Size = new System.Drawing.Size(230, 6); + // + // NESPPUViewerMenuItem + // + this.NESPPUViewerMenuItem.Name = "NESPPUViewerMenuItem"; + this.NESPPUViewerMenuItem.Size = new System.Drawing.Size(233, 22); + this.NESPPUViewerMenuItem.Text = "&PPU Viewer"; + this.NESPPUViewerMenuItem.Click += new System.EventHandler(this.NesPPUViewerMenuItem_Click); + // + // NESNametableViewerMenuItem + // + this.NESNametableViewerMenuItem.Name = "NESNametableViewerMenuItem"; + this.NESNametableViewerMenuItem.Size = new System.Drawing.Size(233, 22); + this.NESNametableViewerMenuItem.Text = "&Nametable Viewer"; + this.NESNametableViewerMenuItem.Click += new System.EventHandler(this.NESNametableViewerMenuItem_Click); + // + // NESGameGenieCodesMenuItem + // + this.NESGameGenieCodesMenuItem.Name = "NESGameGenieCodesMenuItem"; + this.NESGameGenieCodesMenuItem.Size = new System.Drawing.Size(233, 22); + this.NESGameGenieCodesMenuItem.Text = "&Game Genie Encoder/Decoder"; + this.NESGameGenieCodesMenuItem.Click += new System.EventHandler(this.NESGameGenieCodesMenuItem_Click); + // + // musicRipperToolStripMenuItem + // + this.musicRipperToolStripMenuItem.Name = "musicRipperToolStripMenuItem"; + this.musicRipperToolStripMenuItem.Size = new System.Drawing.Size(233, 22); + this.musicRipperToolStripMenuItem.Text = "Music Ripper"; + this.musicRipperToolStripMenuItem.Click += new System.EventHandler(this.MusicRipperMenuItem_Click); + // + // toolStripSeparator17 + // + this.toolStripSeparator17.Name = "toolStripSeparator17"; + this.toolStripSeparator17.Size = new System.Drawing.Size(230, 6); + // + // NesControllerSettingsMenuItem + // + this.NesControllerSettingsMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.GameController; + this.NesControllerSettingsMenuItem.Name = "NesControllerSettingsMenuItem"; + this.NesControllerSettingsMenuItem.Size = new System.Drawing.Size(233, 22); + this.NesControllerSettingsMenuItem.Text = "Controller Settings..."; + this.NesControllerSettingsMenuItem.Click += new System.EventHandler(this.NesControllerSettingsMenuItem_Click); + // + // NESGraphicSettingsMenuItem + // + this.NESGraphicSettingsMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.tvIcon; + this.NESGraphicSettingsMenuItem.Name = "NESGraphicSettingsMenuItem"; + this.NESGraphicSettingsMenuItem.Size = new System.Drawing.Size(233, 22); + this.NESGraphicSettingsMenuItem.Text = "Graphics Settings..."; + this.NESGraphicSettingsMenuItem.Click += new System.EventHandler(this.NESGraphicSettingsMenuItem_Click); + // + // NESSoundChannelsMenuItem + // + this.NESSoundChannelsMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.AudioHS; + this.NESSoundChannelsMenuItem.Name = "NESSoundChannelsMenuItem"; + this.NESSoundChannelsMenuItem.Size = new System.Drawing.Size(233, 22); + this.NESSoundChannelsMenuItem.Text = "Sound Channels..."; + this.NESSoundChannelsMenuItem.Click += new System.EventHandler(this.NESSoundChannelsMenuItem_Click); + // + // VSSettingsMenuItem + // + this.VSSettingsMenuItem.Name = "VSSettingsMenuItem"; + this.VSSettingsMenuItem.Size = new System.Drawing.Size(233, 22); + this.VSSettingsMenuItem.Text = "VS Settings..."; + this.VSSettingsMenuItem.Click += new System.EventHandler(this.VsSettingsMenuItem_Click); + // + // MovieSettingsMenuItem + // + this.MovieSettingsMenuItem.Name = "MovieSettingsMenuItem"; + this.MovieSettingsMenuItem.Size = new System.Drawing.Size(233, 22); + this.MovieSettingsMenuItem.Text = "Advanced Settings..."; + this.MovieSettingsMenuItem.Click += new System.EventHandler(this.MovieSettingsMenuItem_Click); + // + // toolStripSeparator22 + // + this.toolStripSeparator22.Name = "toolStripSeparator22"; + this.toolStripSeparator22.Size = new System.Drawing.Size(230, 6); + // + // FDSControlsMenuItem + // + this.FDSControlsMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.FdsEjectDiskMenuItem}); - this.FDSControlsMenuItem.Name = "FDSControlsMenuItem"; - this.FDSControlsMenuItem.Size = new System.Drawing.Size(217, 22); - this.FDSControlsMenuItem.Text = "FDS Controls"; - this.FDSControlsMenuItem.DropDownOpened += new System.EventHandler(this.FdsControlsMenuItem_DropDownOpened); - // - // FdsEjectDiskMenuItem - // - this.FdsEjectDiskMenuItem.Name = "FdsEjectDiskMenuItem"; - this.FdsEjectDiskMenuItem.Size = new System.Drawing.Size(120, 22); - this.FdsEjectDiskMenuItem.Text = "&Eject Disk"; - this.FdsEjectDiskMenuItem.Click += new System.EventHandler(this.FdsEjectDiskMenuItem_Click); - // - // VSControlsMenuItem - // - this.VSControlsMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.FDSControlsMenuItem.Name = "FDSControlsMenuItem"; + this.FDSControlsMenuItem.Size = new System.Drawing.Size(233, 22); + this.FDSControlsMenuItem.Text = "FDS Controls"; + this.FDSControlsMenuItem.DropDownOpened += new System.EventHandler(this.FdsControlsMenuItem_DropDownOpened); + // + // FdsEjectDiskMenuItem + // + this.FdsEjectDiskMenuItem.Name = "FdsEjectDiskMenuItem"; + this.FdsEjectDiskMenuItem.Size = new System.Drawing.Size(124, 22); + this.FdsEjectDiskMenuItem.Text = "&Eject Disk"; + this.FdsEjectDiskMenuItem.Click += new System.EventHandler(this.FdsEjectDiskMenuItem_Click); + // + // VSControlsMenuItem + // + this.VSControlsMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.VSInsertCoinP1MenuItem, this.VSInsertCoinP2MenuItem, this.VSServiceSwitchMenuItem}); - this.VSControlsMenuItem.Name = "VSControlsMenuItem"; - this.VSControlsMenuItem.Size = new System.Drawing.Size(217, 22); - this.VSControlsMenuItem.Text = "VS Controls"; - // - // VSInsertCoinP1MenuItem - // - this.VSInsertCoinP1MenuItem.Name = "VSInsertCoinP1MenuItem"; - this.VSInsertCoinP1MenuItem.Size = new System.Drawing.Size(143, 22); - this.VSInsertCoinP1MenuItem.Text = "Insert Coin P1"; - this.VSInsertCoinP1MenuItem.Click += new System.EventHandler(this.VsInsertCoinP1MenuItem_Click); - // - // VSInsertCoinP2MenuItem - // - this.VSInsertCoinP2MenuItem.Name = "VSInsertCoinP2MenuItem"; - this.VSInsertCoinP2MenuItem.Size = new System.Drawing.Size(143, 22); - this.VSInsertCoinP2MenuItem.Text = "Insert Coin P2"; - this.VSInsertCoinP2MenuItem.Click += new System.EventHandler(this.VsInsertCoinP2MenuItem_Click); - // - // VSServiceSwitchMenuItem - // - this.VSServiceSwitchMenuItem.Name = "VSServiceSwitchMenuItem"; - this.VSServiceSwitchMenuItem.Size = new System.Drawing.Size(143, 22); - this.VSServiceSwitchMenuItem.Text = "Service Switch"; - this.VSServiceSwitchMenuItem.Click += new System.EventHandler(this.VsServiceSwitchMenuItem_Click); - // - // barcodeReaderToolStripMenuItem - // - this.barcodeReaderToolStripMenuItem.Name = "barcodeReaderToolStripMenuItem"; - this.barcodeReaderToolStripMenuItem.Size = new System.Drawing.Size(217, 22); - this.barcodeReaderToolStripMenuItem.Text = "Barcode Reader"; - this.barcodeReaderToolStripMenuItem.Click += new System.EventHandler(this.BarcodeReaderMenuItem_Click); - // - // PCESubMenu - // - this.PCESubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.VSControlsMenuItem.Name = "VSControlsMenuItem"; + this.VSControlsMenuItem.Size = new System.Drawing.Size(233, 22); + this.VSControlsMenuItem.Text = "VS Controls"; + // + // VSInsertCoinP1MenuItem + // + this.VSInsertCoinP1MenuItem.Name = "VSInsertCoinP1MenuItem"; + this.VSInsertCoinP1MenuItem.Size = new System.Drawing.Size(149, 22); + this.VSInsertCoinP1MenuItem.Text = "Insert Coin P1"; + this.VSInsertCoinP1MenuItem.Click += new System.EventHandler(this.VsInsertCoinP1MenuItem_Click); + // + // VSInsertCoinP2MenuItem + // + this.VSInsertCoinP2MenuItem.Name = "VSInsertCoinP2MenuItem"; + this.VSInsertCoinP2MenuItem.Size = new System.Drawing.Size(149, 22); + this.VSInsertCoinP2MenuItem.Text = "Insert Coin P2"; + this.VSInsertCoinP2MenuItem.Click += new System.EventHandler(this.VsInsertCoinP2MenuItem_Click); + // + // VSServiceSwitchMenuItem + // + this.VSServiceSwitchMenuItem.Name = "VSServiceSwitchMenuItem"; + this.VSServiceSwitchMenuItem.Size = new System.Drawing.Size(149, 22); + this.VSServiceSwitchMenuItem.Text = "Service Switch"; + this.VSServiceSwitchMenuItem.Click += new System.EventHandler(this.VsServiceSwitchMenuItem_Click); + // + // barcodeReaderToolStripMenuItem + // + this.barcodeReaderToolStripMenuItem.Name = "barcodeReaderToolStripMenuItem"; + this.barcodeReaderToolStripMenuItem.Size = new System.Drawing.Size(233, 22); + this.barcodeReaderToolStripMenuItem.Text = "Barcode Reader"; + this.barcodeReaderToolStripMenuItem.Click += new System.EventHandler(this.BarcodeReaderMenuItem_Click); + // + // PCESubMenu + // + this.PCESubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.PceControllerSettingsMenuItem, this.PCEGraphicsSettingsMenuItem, this.toolStripSeparator32, @@ -2416,82 +2416,82 @@ this.PCEAlwaysPerformSpriteLimitMenuItem, this.PCEAlwaysEqualizeVolumesMenuItem, this.PCEArcadeCardRewindEnableMenuItem}); - this.PCESubMenu.Name = "PCESubMenu"; - this.PCESubMenu.Size = new System.Drawing.Size(38, 17); - this.PCESubMenu.Text = "&PCE"; - this.PCESubMenu.DropDownOpened += new System.EventHandler(this.PCESubMenu_DropDownOpened); - // - // PceControllerSettingsMenuItem - // - this.PceControllerSettingsMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.GameController; - this.PceControllerSettingsMenuItem.Name = "PceControllerSettingsMenuItem"; - this.PceControllerSettingsMenuItem.Size = new System.Drawing.Size(240, 22); - this.PceControllerSettingsMenuItem.Text = "Controller Settings"; - this.PceControllerSettingsMenuItem.Click += new System.EventHandler(this.PceControllerSettingsMenuItem_Click); - // - // PCEGraphicsSettingsMenuItem - // - this.PCEGraphicsSettingsMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.tvIcon; - this.PCEGraphicsSettingsMenuItem.Name = "PCEGraphicsSettingsMenuItem"; - this.PCEGraphicsSettingsMenuItem.Size = new System.Drawing.Size(240, 22); - this.PCEGraphicsSettingsMenuItem.Text = "Graphics Settings"; - this.PCEGraphicsSettingsMenuItem.Click += new System.EventHandler(this.PceGraphicsSettingsMenuItem_Click); - // - // toolStripSeparator32 - // - this.toolStripSeparator32.Name = "toolStripSeparator32"; - this.toolStripSeparator32.Size = new System.Drawing.Size(237, 6); - // - // PCEBGViewerMenuItem - // - this.PCEBGViewerMenuItem.Name = "PCEBGViewerMenuItem"; - this.PCEBGViewerMenuItem.Size = new System.Drawing.Size(240, 22); - this.PCEBGViewerMenuItem.Text = "&BG Viewer"; - this.PCEBGViewerMenuItem.Click += new System.EventHandler(this.PceBgViewerMenuItem_Click); - // - // PCEtileViewerToolStripMenuItem - // - this.PCEtileViewerToolStripMenuItem.Name = "PCEtileViewerToolStripMenuItem"; - this.PCEtileViewerToolStripMenuItem.Size = new System.Drawing.Size(240, 22); - this.PCEtileViewerToolStripMenuItem.Text = "&Tile Viewer"; - this.PCEtileViewerToolStripMenuItem.Click += new System.EventHandler(this.PceTileViewerMenuItem_Click); - // - // PceSoundDebuggerToolStripMenuItem - // - this.PceSoundDebuggerToolStripMenuItem.Name = "PceSoundDebuggerToolStripMenuItem"; - this.PceSoundDebuggerToolStripMenuItem.Size = new System.Drawing.Size(240, 22); - this.PceSoundDebuggerToolStripMenuItem.Text = "&Sound Debugger"; - this.PceSoundDebuggerToolStripMenuItem.Click += new System.EventHandler(this.PceSoundDebuggerMenuItem_Click); - // - // toolStripSeparator25 - // - this.toolStripSeparator25.Name = "toolStripSeparator25"; - this.toolStripSeparator25.Size = new System.Drawing.Size(237, 6); - // - // PCEAlwaysPerformSpriteLimitMenuItem - // - this.PCEAlwaysPerformSpriteLimitMenuItem.Name = "PCEAlwaysPerformSpriteLimitMenuItem"; - this.PCEAlwaysPerformSpriteLimitMenuItem.Size = new System.Drawing.Size(240, 22); - this.PCEAlwaysPerformSpriteLimitMenuItem.Text = "Always Perform Sprite Limit"; - this.PCEAlwaysPerformSpriteLimitMenuItem.Click += new System.EventHandler(this.PCEAlwaysPerformSpriteLimitMenuItem_Click); - // - // PCEAlwaysEqualizeVolumesMenuItem - // - this.PCEAlwaysEqualizeVolumesMenuItem.Name = "PCEAlwaysEqualizeVolumesMenuItem"; - this.PCEAlwaysEqualizeVolumesMenuItem.Size = new System.Drawing.Size(240, 22); - this.PCEAlwaysEqualizeVolumesMenuItem.Text = "Always Equalize Volumes (PCE-CD)"; - this.PCEAlwaysEqualizeVolumesMenuItem.Click += new System.EventHandler(this.PCEAlwaysEqualizeVolumesMenuItem_Click); - // - // PCEArcadeCardRewindEnableMenuItem - // - this.PCEArcadeCardRewindEnableMenuItem.Name = "PCEArcadeCardRewindEnableMenuItem"; - this.PCEArcadeCardRewindEnableMenuItem.Size = new System.Drawing.Size(240, 22); - this.PCEArcadeCardRewindEnableMenuItem.Text = "Arcade Card Rewind-Enable Hack"; - this.PCEArcadeCardRewindEnableMenuItem.Click += new System.EventHandler(this.PCEArcadeCardRewindEnableMenuItem_Click); - // - // SMSSubMenu - // - this.SMSSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.PCESubMenu.Name = "PCESubMenu"; + this.PCESubMenu.Size = new System.Drawing.Size(40, 19); + this.PCESubMenu.Text = "&PCE"; + this.PCESubMenu.DropDownOpened += new System.EventHandler(this.PCESubMenu_DropDownOpened); + // + // PceControllerSettingsMenuItem + // + this.PceControllerSettingsMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.GameController; + this.PceControllerSettingsMenuItem.Name = "PceControllerSettingsMenuItem"; + this.PceControllerSettingsMenuItem.Size = new System.Drawing.Size(258, 22); + this.PceControllerSettingsMenuItem.Text = "Controller Settings"; + this.PceControllerSettingsMenuItem.Click += new System.EventHandler(this.PceControllerSettingsMenuItem_Click); + // + // PCEGraphicsSettingsMenuItem + // + this.PCEGraphicsSettingsMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.tvIcon; + this.PCEGraphicsSettingsMenuItem.Name = "PCEGraphicsSettingsMenuItem"; + this.PCEGraphicsSettingsMenuItem.Size = new System.Drawing.Size(258, 22); + this.PCEGraphicsSettingsMenuItem.Text = "Graphics Settings"; + this.PCEGraphicsSettingsMenuItem.Click += new System.EventHandler(this.PceGraphicsSettingsMenuItem_Click); + // + // toolStripSeparator32 + // + this.toolStripSeparator32.Name = "toolStripSeparator32"; + this.toolStripSeparator32.Size = new System.Drawing.Size(255, 6); + // + // PCEBGViewerMenuItem + // + this.PCEBGViewerMenuItem.Name = "PCEBGViewerMenuItem"; + this.PCEBGViewerMenuItem.Size = new System.Drawing.Size(258, 22); + this.PCEBGViewerMenuItem.Text = "&BG Viewer"; + this.PCEBGViewerMenuItem.Click += new System.EventHandler(this.PceBgViewerMenuItem_Click); + // + // PCEtileViewerToolStripMenuItem + // + this.PCEtileViewerToolStripMenuItem.Name = "PCEtileViewerToolStripMenuItem"; + this.PCEtileViewerToolStripMenuItem.Size = new System.Drawing.Size(258, 22); + this.PCEtileViewerToolStripMenuItem.Text = "&Tile Viewer"; + this.PCEtileViewerToolStripMenuItem.Click += new System.EventHandler(this.PceTileViewerMenuItem_Click); + // + // PceSoundDebuggerToolStripMenuItem + // + this.PceSoundDebuggerToolStripMenuItem.Name = "PceSoundDebuggerToolStripMenuItem"; + this.PceSoundDebuggerToolStripMenuItem.Size = new System.Drawing.Size(258, 22); + this.PceSoundDebuggerToolStripMenuItem.Text = "&Sound Debugger"; + this.PceSoundDebuggerToolStripMenuItem.Click += new System.EventHandler(this.PceSoundDebuggerMenuItem_Click); + // + // toolStripSeparator25 + // + this.toolStripSeparator25.Name = "toolStripSeparator25"; + this.toolStripSeparator25.Size = new System.Drawing.Size(255, 6); + // + // PCEAlwaysPerformSpriteLimitMenuItem + // + this.PCEAlwaysPerformSpriteLimitMenuItem.Name = "PCEAlwaysPerformSpriteLimitMenuItem"; + this.PCEAlwaysPerformSpriteLimitMenuItem.Size = new System.Drawing.Size(258, 22); + this.PCEAlwaysPerformSpriteLimitMenuItem.Text = "Always Perform Sprite Limit"; + this.PCEAlwaysPerformSpriteLimitMenuItem.Click += new System.EventHandler(this.PCEAlwaysPerformSpriteLimitMenuItem_Click); + // + // PCEAlwaysEqualizeVolumesMenuItem + // + this.PCEAlwaysEqualizeVolumesMenuItem.Name = "PCEAlwaysEqualizeVolumesMenuItem"; + this.PCEAlwaysEqualizeVolumesMenuItem.Size = new System.Drawing.Size(258, 22); + this.PCEAlwaysEqualizeVolumesMenuItem.Text = "Always Equalize Volumes (PCE-CD)"; + this.PCEAlwaysEqualizeVolumesMenuItem.Click += new System.EventHandler(this.PCEAlwaysEqualizeVolumesMenuItem_Click); + // + // PCEArcadeCardRewindEnableMenuItem + // + this.PCEArcadeCardRewindEnableMenuItem.Name = "PCEArcadeCardRewindEnableMenuItem"; + this.PCEArcadeCardRewindEnableMenuItem.Size = new System.Drawing.Size(258, 22); + this.PCEArcadeCardRewindEnableMenuItem.Text = "Arcade Card Rewind-Enable Hack"; + this.PCEArcadeCardRewindEnableMenuItem.Click += new System.EventHandler(this.PCEArcadeCardRewindEnableMenuItem_Click); + // + // SMSSubMenu + // + this.SMSSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.SMSregionToolStripMenuItem, this.SMSdisplayToolStripMenuItem, this.SMStoolStripMenuItem2, @@ -2508,785 +2508,800 @@ this.toolStripSeparator24, this.SMSVDPViewerToolStripMenuItem, this.GGGameGenieMenuItem}); - this.SMSSubMenu.Name = "SMSSubMenu"; - this.SMSSubMenu.Size = new System.Drawing.Size(39, 17); - this.SMSSubMenu.Text = "&SMS"; - this.SMSSubMenu.DropDownOpened += new System.EventHandler(this.SMSSubMenu_DropDownOpened); - // - // SMSregionToolStripMenuItem - // - this.SMSregionToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.SMSSubMenu.Name = "SMSSubMenu"; + this.SMSSubMenu.Size = new System.Drawing.Size(42, 19); + this.SMSSubMenu.Text = "&SMS"; + this.SMSSubMenu.DropDownOpened += new System.EventHandler(this.SMSSubMenu_DropDownOpened); + // + // SMSregionToolStripMenuItem + // + this.SMSregionToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.SMSregionExportToolStripMenuItem, this.SMSregionJapanToolStripMenuItem, this.SMSregionAutoToolStripMenuItem}); - this.SMSregionToolStripMenuItem.Name = "SMSregionToolStripMenuItem"; - this.SMSregionToolStripMenuItem.Size = new System.Drawing.Size(262, 22); - this.SMSregionToolStripMenuItem.Text = "Region"; - // - // SMSregionExportToolStripMenuItem - // - this.SMSregionExportToolStripMenuItem.Name = "SMSregionExportToolStripMenuItem"; - this.SMSregionExportToolStripMenuItem.Size = new System.Drawing.Size(106, 22); - this.SMSregionExportToolStripMenuItem.Text = "Export"; - this.SMSregionExportToolStripMenuItem.Click += new System.EventHandler(this.SMS_RegionExport_Click); - // - // SMSregionJapanToolStripMenuItem - // - this.SMSregionJapanToolStripMenuItem.Name = "SMSregionJapanToolStripMenuItem"; - this.SMSregionJapanToolStripMenuItem.Size = new System.Drawing.Size(106, 22); - this.SMSregionJapanToolStripMenuItem.Text = "Japan"; - this.SMSregionJapanToolStripMenuItem.Click += new System.EventHandler(this.SMS_RegionJapan_Click); - // - // SMSregionAutoToolStripMenuItem - // - this.SMSregionAutoToolStripMenuItem.Name = "SMSregionAutoToolStripMenuItem"; - this.SMSregionAutoToolStripMenuItem.Size = new System.Drawing.Size(106, 22); - this.SMSregionAutoToolStripMenuItem.Text = "Auto"; - this.SMSregionAutoToolStripMenuItem.Click += new System.EventHandler(this.SMS_RegionAuto_Click); - // - // SMSdisplayToolStripMenuItem - // - this.SMSdisplayToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.SMSregionToolStripMenuItem.Name = "SMSregionToolStripMenuItem"; + this.SMSregionToolStripMenuItem.Size = new System.Drawing.Size(277, 22); + this.SMSregionToolStripMenuItem.Text = "Region"; + // + // SMSregionExportToolStripMenuItem + // + this.SMSregionExportToolStripMenuItem.Name = "SMSregionExportToolStripMenuItem"; + this.SMSregionExportToolStripMenuItem.Size = new System.Drawing.Size(107, 22); + this.SMSregionExportToolStripMenuItem.Text = "Export"; + this.SMSregionExportToolStripMenuItem.Click += new System.EventHandler(this.SMS_RegionExport_Click); + // + // SMSregionJapanToolStripMenuItem + // + this.SMSregionJapanToolStripMenuItem.Name = "SMSregionJapanToolStripMenuItem"; + this.SMSregionJapanToolStripMenuItem.Size = new System.Drawing.Size(107, 22); + this.SMSregionJapanToolStripMenuItem.Text = "Japan"; + this.SMSregionJapanToolStripMenuItem.Click += new System.EventHandler(this.SMS_RegionJapan_Click); + // + // SMSregionAutoToolStripMenuItem + // + this.SMSregionAutoToolStripMenuItem.Name = "SMSregionAutoToolStripMenuItem"; + this.SMSregionAutoToolStripMenuItem.Size = new System.Drawing.Size(107, 22); + this.SMSregionAutoToolStripMenuItem.Text = "Auto"; + this.SMSregionAutoToolStripMenuItem.Click += new System.EventHandler(this.SMS_RegionAuto_Click); + // + // SMSdisplayToolStripMenuItem + // + this.SMSdisplayToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.SMSdisplayNtscToolStripMenuItem, this.SMSdisplayPalToolStripMenuItem, this.SMSdisplayAutoToolStripMenuItem}); - this.SMSdisplayToolStripMenuItem.Name = "SMSdisplayToolStripMenuItem"; - this.SMSdisplayToolStripMenuItem.Size = new System.Drawing.Size(262, 22); - this.SMSdisplayToolStripMenuItem.Text = "Display Type"; - // - // SMSdisplayNtscToolStripMenuItem - // - this.SMSdisplayNtscToolStripMenuItem.Name = "SMSdisplayNtscToolStripMenuItem"; - this.SMSdisplayNtscToolStripMenuItem.Size = new System.Drawing.Size(100, 22); - this.SMSdisplayNtscToolStripMenuItem.Text = "NTSC"; - this.SMSdisplayNtscToolStripMenuItem.Click += new System.EventHandler(this.SMS_DisplayNTSC_Click); - // - // SMSdisplayPalToolStripMenuItem - // - this.SMSdisplayPalToolStripMenuItem.Name = "SMSdisplayPalToolStripMenuItem"; - this.SMSdisplayPalToolStripMenuItem.Size = new System.Drawing.Size(100, 22); - this.SMSdisplayPalToolStripMenuItem.Text = "PAL"; - this.SMSdisplayPalToolStripMenuItem.Click += new System.EventHandler(this.SMS_DisplayPAL_Click); - // - // SMSdisplayAutoToolStripMenuItem - // - this.SMSdisplayAutoToolStripMenuItem.Name = "SMSdisplayAutoToolStripMenuItem"; - this.SMSdisplayAutoToolStripMenuItem.Size = new System.Drawing.Size(100, 22); - this.SMSdisplayAutoToolStripMenuItem.Text = "Auto"; - this.SMSdisplayAutoToolStripMenuItem.Click += new System.EventHandler(this.SMS_DisplayAuto_Click); - // - // SMStoolStripMenuItem2 - // - this.SMStoolStripMenuItem2.Name = "SMStoolStripMenuItem2"; - this.SMStoolStripMenuItem2.Size = new System.Drawing.Size(259, 6); - // - // SMSenableBIOSToolStripMenuItem - // - this.SMSenableBIOSToolStripMenuItem.Name = "SMSenableBIOSToolStripMenuItem"; - this.SMSenableBIOSToolStripMenuItem.Size = new System.Drawing.Size(262, 22); - this.SMSenableBIOSToolStripMenuItem.Text = "Enable BIOS (Must be Enabled for TAS)"; - this.SMSenableBIOSToolStripMenuItem.Click += new System.EventHandler(this.SmsBiosMenuItem_Click); - // - // SMSEnableFMChipMenuItem - // - this.SMSEnableFMChipMenuItem.Name = "SMSEnableFMChipMenuItem"; - this.SMSEnableFMChipMenuItem.Size = new System.Drawing.Size(262, 22); - this.SMSEnableFMChipMenuItem.Text = "&Enable FM Chip"; - this.SMSEnableFMChipMenuItem.Click += new System.EventHandler(this.SmsEnableFmChipMenuItem_Click); - // - // SMSOverclockMenuItem - // - this.SMSOverclockMenuItem.Name = "SMSOverclockMenuItem"; - this.SMSOverclockMenuItem.Size = new System.Drawing.Size(262, 22); - this.SMSOverclockMenuItem.Text = "&Overclock when Known Safe"; - this.SMSOverclockMenuItem.Click += new System.EventHandler(this.SMSOverclockMenuItem_Click); - // - // SMSForceStereoMenuItem - // - this.SMSForceStereoMenuItem.Name = "SMSForceStereoMenuItem"; - this.SMSForceStereoMenuItem.Size = new System.Drawing.Size(262, 22); - this.SMSForceStereoMenuItem.Text = "&Force Stereo Separation"; - this.SMSForceStereoMenuItem.Click += new System.EventHandler(this.SMSForceStereoMenuItem_Click); - // - // SMSSpriteLimitMenuItem - // - this.SMSSpriteLimitMenuItem.Name = "SMSSpriteLimitMenuItem"; - this.SMSSpriteLimitMenuItem.Size = new System.Drawing.Size(262, 22); - this.SMSSpriteLimitMenuItem.Text = "Sprite &Limit"; - this.SMSSpriteLimitMenuItem.Click += new System.EventHandler(this.SMSSpriteLimitMenuItem_Click); - // - // SMSDisplayOverscanMenuItem - // - this.SMSDisplayOverscanMenuItem.Name = "SMSDisplayOverscanMenuItem"; - this.SMSDisplayOverscanMenuItem.Size = new System.Drawing.Size(262, 22); - this.SMSDisplayOverscanMenuItem.Text = "Display Overscan"; - this.SMSDisplayOverscanMenuItem.Click += new System.EventHandler(this.SMSDisplayOverscanMenuItem_Click); - // - // SMSFix3DGameDisplayToolStripMenuItem - // - this.SMSFix3DGameDisplayToolStripMenuItem.Name = "SMSFix3DGameDisplayToolStripMenuItem"; - this.SMSFix3DGameDisplayToolStripMenuItem.Size = new System.Drawing.Size(262, 22); - this.SMSFix3DGameDisplayToolStripMenuItem.Text = "Fix 3D Game Display"; - this.SMSFix3DGameDisplayToolStripMenuItem.Click += new System.EventHandler(this.SMSFix3DDisplayMenuItem_Click); - // - // ShowClippedRegionsMenuItem - // - this.ShowClippedRegionsMenuItem.Name = "ShowClippedRegionsMenuItem"; - this.ShowClippedRegionsMenuItem.Size = new System.Drawing.Size(262, 22); - this.ShowClippedRegionsMenuItem.Text = "&Show Clipped Regions"; - this.ShowClippedRegionsMenuItem.Click += new System.EventHandler(this.ShowClippedRegionsMenuItem_Click); - // - // HighlightActiveDisplayRegionMenuItem - // - this.HighlightActiveDisplayRegionMenuItem.Name = "HighlightActiveDisplayRegionMenuItem"; - this.HighlightActiveDisplayRegionMenuItem.Size = new System.Drawing.Size(262, 22); - this.HighlightActiveDisplayRegionMenuItem.Text = "&Highlight Active Display Region"; - this.HighlightActiveDisplayRegionMenuItem.Click += new System.EventHandler(this.HighlightActiveDisplayRegionMenuItem_Click); - // - // SMSGraphicsSettingsMenuItem - // - this.SMSGraphicsSettingsMenuItem.Name = "SMSGraphicsSettingsMenuItem"; - this.SMSGraphicsSettingsMenuItem.Size = new System.Drawing.Size(262, 22); - this.SMSGraphicsSettingsMenuItem.Text = "&Graphics Settings..."; - this.SMSGraphicsSettingsMenuItem.Click += new System.EventHandler(this.SMSGraphicsSettingsMenuItem_Click); - // - // toolStripSeparator24 - // - this.toolStripSeparator24.Name = "toolStripSeparator24"; - this.toolStripSeparator24.Size = new System.Drawing.Size(259, 6); - // - // SMSVDPViewerToolStripMenuItem - // - this.SMSVDPViewerToolStripMenuItem.Name = "SMSVDPViewerToolStripMenuItem"; - this.SMSVDPViewerToolStripMenuItem.Size = new System.Drawing.Size(262, 22); - this.SMSVDPViewerToolStripMenuItem.Text = "&VDP Viewer"; - this.SMSVDPViewerToolStripMenuItem.Click += new System.EventHandler(this.SmsVdpViewerMenuItem_Click); - // - // GGGameGenieMenuItem - // - this.GGGameGenieMenuItem.Name = "GGGameGenieMenuItem"; - this.GGGameGenieMenuItem.Size = new System.Drawing.Size(262, 22); - this.GGGameGenieMenuItem.Text = "&Game Genie Encoder/Decoder"; - this.GGGameGenieMenuItem.Click += new System.EventHandler(this.GGGameGenieMenuItem_Click); - // - // TI83SubMenu - // - this.TI83SubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.SMSdisplayToolStripMenuItem.Name = "SMSdisplayToolStripMenuItem"; + this.SMSdisplayToolStripMenuItem.Size = new System.Drawing.Size(277, 22); + this.SMSdisplayToolStripMenuItem.Text = "Display Type"; + // + // SMSdisplayNtscToolStripMenuItem + // + this.SMSdisplayNtscToolStripMenuItem.Name = "SMSdisplayNtscToolStripMenuItem"; + this.SMSdisplayNtscToolStripMenuItem.Size = new System.Drawing.Size(104, 22); + this.SMSdisplayNtscToolStripMenuItem.Text = "NTSC"; + this.SMSdisplayNtscToolStripMenuItem.Click += new System.EventHandler(this.SMS_DisplayNTSC_Click); + // + // SMSdisplayPalToolStripMenuItem + // + this.SMSdisplayPalToolStripMenuItem.Name = "SMSdisplayPalToolStripMenuItem"; + this.SMSdisplayPalToolStripMenuItem.Size = new System.Drawing.Size(104, 22); + this.SMSdisplayPalToolStripMenuItem.Text = "PAL"; + this.SMSdisplayPalToolStripMenuItem.Click += new System.EventHandler(this.SMS_DisplayPAL_Click); + // + // SMSdisplayAutoToolStripMenuItem + // + this.SMSdisplayAutoToolStripMenuItem.Name = "SMSdisplayAutoToolStripMenuItem"; + this.SMSdisplayAutoToolStripMenuItem.Size = new System.Drawing.Size(104, 22); + this.SMSdisplayAutoToolStripMenuItem.Text = "Auto"; + this.SMSdisplayAutoToolStripMenuItem.Click += new System.EventHandler(this.SMS_DisplayAuto_Click); + // + // SMStoolStripMenuItem2 + // + this.SMStoolStripMenuItem2.Name = "SMStoolStripMenuItem2"; + this.SMStoolStripMenuItem2.Size = new System.Drawing.Size(274, 6); + // + // SMSenableBIOSToolStripMenuItem + // + this.SMSenableBIOSToolStripMenuItem.Name = "SMSenableBIOSToolStripMenuItem"; + this.SMSenableBIOSToolStripMenuItem.Size = new System.Drawing.Size(277, 22); + this.SMSenableBIOSToolStripMenuItem.Text = "Enable BIOS (Must be Enabled for TAS)"; + this.SMSenableBIOSToolStripMenuItem.Click += new System.EventHandler(this.SmsBiosMenuItem_Click); + // + // SMSEnableFMChipMenuItem + // + this.SMSEnableFMChipMenuItem.Name = "SMSEnableFMChipMenuItem"; + this.SMSEnableFMChipMenuItem.Size = new System.Drawing.Size(277, 22); + this.SMSEnableFMChipMenuItem.Text = "&Enable FM Chip"; + this.SMSEnableFMChipMenuItem.Click += new System.EventHandler(this.SmsEnableFmChipMenuItem_Click); + // + // SMSOverclockMenuItem + // + this.SMSOverclockMenuItem.Name = "SMSOverclockMenuItem"; + this.SMSOverclockMenuItem.Size = new System.Drawing.Size(277, 22); + this.SMSOverclockMenuItem.Text = "&Overclock when Known Safe"; + this.SMSOverclockMenuItem.Click += new System.EventHandler(this.SMSOverclockMenuItem_Click); + // + // SMSForceStereoMenuItem + // + this.SMSForceStereoMenuItem.Name = "SMSForceStereoMenuItem"; + this.SMSForceStereoMenuItem.Size = new System.Drawing.Size(277, 22); + this.SMSForceStereoMenuItem.Text = "&Force Stereo Separation"; + this.SMSForceStereoMenuItem.Click += new System.EventHandler(this.SMSForceStereoMenuItem_Click); + // + // SMSSpriteLimitMenuItem + // + this.SMSSpriteLimitMenuItem.Name = "SMSSpriteLimitMenuItem"; + this.SMSSpriteLimitMenuItem.Size = new System.Drawing.Size(277, 22); + this.SMSSpriteLimitMenuItem.Text = "Sprite &Limit"; + this.SMSSpriteLimitMenuItem.Click += new System.EventHandler(this.SMSSpriteLimitMenuItem_Click); + // + // SMSDisplayOverscanMenuItem + // + this.SMSDisplayOverscanMenuItem.Name = "SMSDisplayOverscanMenuItem"; + this.SMSDisplayOverscanMenuItem.Size = new System.Drawing.Size(277, 22); + this.SMSDisplayOverscanMenuItem.Text = "Display Overscan"; + this.SMSDisplayOverscanMenuItem.Click += new System.EventHandler(this.SMSDisplayOverscanMenuItem_Click); + // + // SMSFix3DGameDisplayToolStripMenuItem + // + this.SMSFix3DGameDisplayToolStripMenuItem.Name = "SMSFix3DGameDisplayToolStripMenuItem"; + this.SMSFix3DGameDisplayToolStripMenuItem.Size = new System.Drawing.Size(277, 22); + this.SMSFix3DGameDisplayToolStripMenuItem.Text = "Fix 3D Game Display"; + this.SMSFix3DGameDisplayToolStripMenuItem.Click += new System.EventHandler(this.SMSFix3DDisplayMenuItem_Click); + // + // ShowClippedRegionsMenuItem + // + this.ShowClippedRegionsMenuItem.Name = "ShowClippedRegionsMenuItem"; + this.ShowClippedRegionsMenuItem.Size = new System.Drawing.Size(277, 22); + this.ShowClippedRegionsMenuItem.Text = "&Show Clipped Regions"; + this.ShowClippedRegionsMenuItem.Click += new System.EventHandler(this.ShowClippedRegionsMenuItem_Click); + // + // HighlightActiveDisplayRegionMenuItem + // + this.HighlightActiveDisplayRegionMenuItem.Name = "HighlightActiveDisplayRegionMenuItem"; + this.HighlightActiveDisplayRegionMenuItem.Size = new System.Drawing.Size(277, 22); + this.HighlightActiveDisplayRegionMenuItem.Text = "&Highlight Active Display Region"; + this.HighlightActiveDisplayRegionMenuItem.Click += new System.EventHandler(this.HighlightActiveDisplayRegionMenuItem_Click); + // + // SMSGraphicsSettingsMenuItem + // + this.SMSGraphicsSettingsMenuItem.Name = "SMSGraphicsSettingsMenuItem"; + this.SMSGraphicsSettingsMenuItem.Size = new System.Drawing.Size(277, 22); + this.SMSGraphicsSettingsMenuItem.Text = "&Graphics Settings..."; + this.SMSGraphicsSettingsMenuItem.Click += new System.EventHandler(this.SMSGraphicsSettingsMenuItem_Click); + // + // toolStripSeparator24 + // + this.toolStripSeparator24.Name = "toolStripSeparator24"; + this.toolStripSeparator24.Size = new System.Drawing.Size(274, 6); + // + // SMSVDPViewerToolStripMenuItem + // + this.SMSVDPViewerToolStripMenuItem.Name = "SMSVDPViewerToolStripMenuItem"; + this.SMSVDPViewerToolStripMenuItem.Size = new System.Drawing.Size(277, 22); + this.SMSVDPViewerToolStripMenuItem.Text = "&VDP Viewer"; + this.SMSVDPViewerToolStripMenuItem.Click += new System.EventHandler(this.SmsVdpViewerMenuItem_Click); + // + // GGGameGenieMenuItem + // + this.GGGameGenieMenuItem.Name = "GGGameGenieMenuItem"; + this.GGGameGenieMenuItem.Size = new System.Drawing.Size(277, 22); + this.GGGameGenieMenuItem.Text = "&Game Genie Encoder/Decoder"; + this.GGGameGenieMenuItem.Click += new System.EventHandler(this.GGGameGenieMenuItem_Click); + // + // TI83SubMenu + // + this.TI83SubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.KeypadMenuItem, this.LoadTIFileMenuItem, this.toolStripSeparator13, this.AutoloadKeypadMenuItem, this.paletteToolStripMenuItem}); - this.TI83SubMenu.Name = "TI83SubMenu"; - this.TI83SubMenu.Size = new System.Drawing.Size(41, 17); - this.TI83SubMenu.Text = "TI83"; - this.TI83SubMenu.DropDownOpened += new System.EventHandler(this.TI83SubMenu_DropDownOpened); - // - // KeypadMenuItem - // - this.KeypadMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.calculator; - this.KeypadMenuItem.Name = "KeypadMenuItem"; - this.KeypadMenuItem.Size = new System.Drawing.Size(157, 22); - this.KeypadMenuItem.Text = "Keypad"; - this.KeypadMenuItem.Click += new System.EventHandler(this.KeypadMenuItem_Click); - // - // LoadTIFileMenuItem - // - this.LoadTIFileMenuItem.Name = "LoadTIFileMenuItem"; - this.LoadTIFileMenuItem.Size = new System.Drawing.Size(157, 22); - this.LoadTIFileMenuItem.Text = "Load TI-83 File..."; - this.LoadTIFileMenuItem.Click += new System.EventHandler(this.LoadTIFileMenuItem_Click); - // - // toolStripSeparator13 - // - this.toolStripSeparator13.Name = "toolStripSeparator13"; - this.toolStripSeparator13.Size = new System.Drawing.Size(154, 6); - // - // AutoloadKeypadMenuItem - // - this.AutoloadKeypadMenuItem.Checked = true; - this.AutoloadKeypadMenuItem.CheckState = System.Windows.Forms.CheckState.Checked; - this.AutoloadKeypadMenuItem.Name = "AutoloadKeypadMenuItem"; - this.AutoloadKeypadMenuItem.Size = new System.Drawing.Size(157, 22); - this.AutoloadKeypadMenuItem.Text = "Autoload Keypad"; - this.AutoloadKeypadMenuItem.Click += new System.EventHandler(this.AutoloadKeypadMenuItem_Click); - // - // paletteToolStripMenuItem - // - this.paletteToolStripMenuItem.Name = "paletteToolStripMenuItem"; - this.paletteToolStripMenuItem.Size = new System.Drawing.Size(157, 22); - this.paletteToolStripMenuItem.Text = "Palette..."; - this.paletteToolStripMenuItem.Click += new System.EventHandler(this.TI83PaletteMenuItem_Click); - // - // AtariSubMenu - // - this.AtariSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.TI83SubMenu.Name = "TI83SubMenu"; + this.TI83SubMenu.Size = new System.Drawing.Size(41, 19); + this.TI83SubMenu.Text = "TI83"; + this.TI83SubMenu.DropDownOpened += new System.EventHandler(this.TI83SubMenu_DropDownOpened); + // + // KeypadMenuItem + // + this.KeypadMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.calculator; + this.KeypadMenuItem.Name = "KeypadMenuItem"; + this.KeypadMenuItem.Size = new System.Drawing.Size(165, 22); + this.KeypadMenuItem.Text = "Keypad"; + this.KeypadMenuItem.Click += new System.EventHandler(this.KeypadMenuItem_Click); + // + // LoadTIFileMenuItem + // + this.LoadTIFileMenuItem.Name = "LoadTIFileMenuItem"; + this.LoadTIFileMenuItem.Size = new System.Drawing.Size(165, 22); + this.LoadTIFileMenuItem.Text = "Load TI-83 File..."; + this.LoadTIFileMenuItem.Click += new System.EventHandler(this.LoadTIFileMenuItem_Click); + // + // toolStripSeparator13 + // + this.toolStripSeparator13.Name = "toolStripSeparator13"; + this.toolStripSeparator13.Size = new System.Drawing.Size(162, 6); + // + // AutoloadKeypadMenuItem + // + this.AutoloadKeypadMenuItem.Checked = true; + this.AutoloadKeypadMenuItem.CheckState = System.Windows.Forms.CheckState.Checked; + this.AutoloadKeypadMenuItem.Name = "AutoloadKeypadMenuItem"; + this.AutoloadKeypadMenuItem.Size = new System.Drawing.Size(165, 22); + this.AutoloadKeypadMenuItem.Text = "Autoload Keypad"; + this.AutoloadKeypadMenuItem.Click += new System.EventHandler(this.AutoloadKeypadMenuItem_Click); + // + // paletteToolStripMenuItem + // + this.paletteToolStripMenuItem.Name = "paletteToolStripMenuItem"; + this.paletteToolStripMenuItem.Size = new System.Drawing.Size(165, 22); + this.paletteToolStripMenuItem.Text = "Palette..."; + this.paletteToolStripMenuItem.Click += new System.EventHandler(this.TI83PaletteMenuItem_Click); + // + // AtariSubMenu + // + this.AtariSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.AtariSettingsToolStripMenuItem}); - this.AtariSubMenu.Name = "AtariSubMenu"; - this.AtariSubMenu.Size = new System.Drawing.Size(42, 17); - this.AtariSubMenu.Text = "&Atari"; - // - // AtariSettingsToolStripMenuItem - // - this.AtariSettingsToolStripMenuItem.Name = "AtariSettingsToolStripMenuItem"; - this.AtariSettingsToolStripMenuItem.Size = new System.Drawing.Size(125, 22); - this.AtariSettingsToolStripMenuItem.Text = "Settings..."; - this.AtariSettingsToolStripMenuItem.Click += new System.EventHandler(this.AtariSettingsToolStripMenuItem_Click); - // - // A7800SubMenu - // - this.A7800SubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.AtariSubMenu.Name = "AtariSubMenu"; + this.AtariSubMenu.Size = new System.Drawing.Size(44, 19); + this.AtariSubMenu.Text = "&Atari"; + // + // AtariSettingsToolStripMenuItem + // + this.AtariSettingsToolStripMenuItem.Name = "AtariSettingsToolStripMenuItem"; + this.AtariSettingsToolStripMenuItem.Size = new System.Drawing.Size(125, 22); + this.AtariSettingsToolStripMenuItem.Text = "Settings..."; + this.AtariSettingsToolStripMenuItem.Click += new System.EventHandler(this.AtariSettingsToolStripMenuItem_Click); + // + // A7800SubMenu + // + this.A7800SubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.A7800ControllerSettingsMenuItem}); - this.A7800SubMenu.Name = "A7800SubMenu"; - this.A7800SubMenu.Size = new System.Drawing.Size(50, 17); - this.A7800SubMenu.Text = "&A7800"; - this.A7800SubMenu.DropDownOpened += new System.EventHandler(this.A7800SubMenu_DropDownOpened); - // - // A7800ControllerSettingsMenuItem - // - this.A7800ControllerSettingsMenuItem.Name = "A7800ControllerSettingsMenuItem"; - this.A7800ControllerSettingsMenuItem.Size = new System.Drawing.Size(125, 22); - this.A7800ControllerSettingsMenuItem.Text = "Settings..."; - this.A7800ControllerSettingsMenuItem.Click += new System.EventHandler(this.A7800SettingsToolStripMenuItem_Click); - // - // GBSubMenu - // - this.GBSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.A7800SubMenu.Name = "A7800SubMenu"; + this.A7800SubMenu.Size = new System.Drawing.Size(51, 19); + this.A7800SubMenu.Text = "&A7800"; + this.A7800SubMenu.DropDownOpened += new System.EventHandler(this.A7800SubMenu_DropDownOpened); + // + // A7800ControllerSettingsMenuItem + // + this.A7800ControllerSettingsMenuItem.Name = "A7800ControllerSettingsMenuItem"; + this.A7800ControllerSettingsMenuItem.Size = new System.Drawing.Size(125, 22); + this.A7800ControllerSettingsMenuItem.Text = "Settings..."; + this.A7800ControllerSettingsMenuItem.Click += new System.EventHandler(this.A7800SettingsToolStripMenuItem_Click); + // + // GBSubMenu + // + this.GBSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.GBcoreSettingsToolStripMenuItem, this.LoadGBInSGBMenuItem, this.toolStripSeparator28, this.GBGPUViewerMenuItem, this.GBGameGenieMenuItem}); - this.GBSubMenu.Name = "GBSubMenu"; - this.GBSubMenu.Size = new System.Drawing.Size(32, 17); - this.GBSubMenu.Text = "&GB"; - this.GBSubMenu.DropDownOpened += new System.EventHandler(this.GBSubMenu_DropDownOpened); - // - // GBcoreSettingsToolStripMenuItem - // - this.GBcoreSettingsToolStripMenuItem.Name = "GBcoreSettingsToolStripMenuItem"; - this.GBcoreSettingsToolStripMenuItem.Size = new System.Drawing.Size(217, 22); - this.GBcoreSettingsToolStripMenuItem.Text = "Settings..."; - this.GBcoreSettingsToolStripMenuItem.Click += new System.EventHandler(this.GBCoreSettingsMenuItem_Click); - // - // LoadGBInSGBMenuItem - // - this.LoadGBInSGBMenuItem.Name = "LoadGBInSGBMenuItem"; - this.LoadGBInSGBMenuItem.Size = new System.Drawing.Size(217, 22); - this.LoadGBInSGBMenuItem.Text = "Load GB in SGB"; - this.LoadGBInSGBMenuItem.Click += new System.EventHandler(this.LoadGbInSgbMenuItem_Click); - // - // toolStripSeparator28 - // - this.toolStripSeparator28.Name = "toolStripSeparator28"; - this.toolStripSeparator28.Size = new System.Drawing.Size(214, 6); - // - // GBGPUViewerMenuItem - // - this.GBGPUViewerMenuItem.Name = "GBGPUViewerMenuItem"; - this.GBGPUViewerMenuItem.Size = new System.Drawing.Size(217, 22); - this.GBGPUViewerMenuItem.Text = "GPU Viewer"; - this.GBGPUViewerMenuItem.Click += new System.EventHandler(this.GbGpuViewerMenuItem_Click); - // - // GBGameGenieMenuItem - // - this.GBGameGenieMenuItem.Name = "GBGameGenieMenuItem"; - this.GBGameGenieMenuItem.Size = new System.Drawing.Size(217, 22); - this.GBGameGenieMenuItem.Text = "&Game Genie Encoder/Decoder"; - this.GBGameGenieMenuItem.Click += new System.EventHandler(this.GBGameGenieMenuItem_Click); - // - // GBASubMenu - // - this.GBASubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.GBSubMenu.Name = "GBSubMenu"; + this.GBSubMenu.Size = new System.Drawing.Size(34, 19); + this.GBSubMenu.Text = "&GB"; + this.GBSubMenu.DropDownOpened += new System.EventHandler(this.GBSubMenu_DropDownOpened); + // + // GBcoreSettingsToolStripMenuItem + // + this.GBcoreSettingsToolStripMenuItem.Name = "GBcoreSettingsToolStripMenuItem"; + this.GBcoreSettingsToolStripMenuItem.Size = new System.Drawing.Size(233, 22); + this.GBcoreSettingsToolStripMenuItem.Text = "Settings..."; + this.GBcoreSettingsToolStripMenuItem.Click += new System.EventHandler(this.GBCoreSettingsMenuItem_Click); + // + // LoadGBInSGBMenuItem + // + this.LoadGBInSGBMenuItem.Name = "LoadGBInSGBMenuItem"; + this.LoadGBInSGBMenuItem.Size = new System.Drawing.Size(233, 22); + this.LoadGBInSGBMenuItem.Text = "Load GB in SGB"; + this.LoadGBInSGBMenuItem.Click += new System.EventHandler(this.LoadGbInSgbMenuItem_Click); + // + // toolStripSeparator28 + // + this.toolStripSeparator28.Name = "toolStripSeparator28"; + this.toolStripSeparator28.Size = new System.Drawing.Size(230, 6); + // + // GBGPUViewerMenuItem + // + this.GBGPUViewerMenuItem.Name = "GBGPUViewerMenuItem"; + this.GBGPUViewerMenuItem.Size = new System.Drawing.Size(233, 22); + this.GBGPUViewerMenuItem.Text = "GPU Viewer"; + this.GBGPUViewerMenuItem.Click += new System.EventHandler(this.GbGpuViewerMenuItem_Click); + // + // GBGameGenieMenuItem + // + this.GBGameGenieMenuItem.Name = "GBGameGenieMenuItem"; + this.GBGameGenieMenuItem.Size = new System.Drawing.Size(233, 22); + this.GBGameGenieMenuItem.Text = "&Game Genie Encoder/Decoder"; + this.GBGameGenieMenuItem.Click += new System.EventHandler(this.GBGameGenieMenuItem_Click); + // + // GBASubMenu + // + this.GBASubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.GBACoreSelectionSubMenu, this.GBAcoresettingsToolStripMenuItem1, this.toolStripSeparator33, this.GbaGpuViewerMenuItem}); - this.GBASubMenu.Name = "GBASubMenu"; - this.GBASubMenu.Size = new System.Drawing.Size(39, 17); - this.GBASubMenu.Text = "GBA"; - // - // GBACoreSelectionSubMenu - // - this.GBACoreSelectionSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.GBASubMenu.Name = "GBASubMenu"; + this.GBASubMenu.Size = new System.Drawing.Size(42, 19); + this.GBASubMenu.Text = "GBA"; + // + // GBACoreSelectionSubMenu + // + this.GBACoreSelectionSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.GBAmGBAMenuItem, this.GBAVBANextMenuItem}); - this.GBACoreSelectionSubMenu.Name = "GBACoreSelectionSubMenu"; - this.GBACoreSelectionSubMenu.Size = new System.Drawing.Size(129, 22); - this.GBACoreSelectionSubMenu.Text = "&Core"; - this.GBACoreSelectionSubMenu.DropDownOpened += new System.EventHandler(this.GBACoreSelectionSubMenu_DropDownOpened); - // - // GBAmGBAMenuItem - // - this.GBAmGBAMenuItem.Name = "GBAmGBAMenuItem"; - this.GBAmGBAMenuItem.Size = new System.Drawing.Size(120, 22); - this.GBAmGBAMenuItem.Text = "mGBA"; - this.GBAmGBAMenuItem.Click += new System.EventHandler(this.UsemGBAMenuItem_Click); - // - // GBAVBANextMenuItem - // - this.GBAVBANextMenuItem.Name = "GBAVBANextMenuItem"; - this.GBAVBANextMenuItem.Size = new System.Drawing.Size(120, 22); - this.GBAVBANextMenuItem.Text = "&VBA-Next"; - this.GBAVBANextMenuItem.Click += new System.EventHandler(this.UseVbaNextMenuItem_Click); - // - // GBAcoresettingsToolStripMenuItem1 - // - this.GBAcoresettingsToolStripMenuItem1.Name = "GBAcoresettingsToolStripMenuItem1"; - this.GBAcoresettingsToolStripMenuItem1.Size = new System.Drawing.Size(129, 22); - this.GBAcoresettingsToolStripMenuItem1.Text = "&Settings..."; - this.GBAcoresettingsToolStripMenuItem1.Click += new System.EventHandler(this.GBAcoresettingsToolStripMenuItem1_Click); - // - // toolStripSeparator33 - // - this.toolStripSeparator33.Name = "toolStripSeparator33"; - this.toolStripSeparator33.Size = new System.Drawing.Size(126, 6); - // - // GbaGpuViewerMenuItem - // - this.GbaGpuViewerMenuItem.Name = "GbaGpuViewerMenuItem"; - this.GbaGpuViewerMenuItem.Size = new System.Drawing.Size(129, 22); - this.GbaGpuViewerMenuItem.Text = "GPU Viewer"; - this.GbaGpuViewerMenuItem.Click += new System.EventHandler(this.GbaGpuViewerMenuItem_Click); - // - // PSXSubMenu - // - this.PSXSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.GBACoreSelectionSubMenu.Name = "GBACoreSelectionSubMenu"; + this.GBACoreSelectionSubMenu.Size = new System.Drawing.Size(135, 22); + this.GBACoreSelectionSubMenu.Text = "&Core"; + this.GBACoreSelectionSubMenu.DropDownOpened += new System.EventHandler(this.GBACoreSelectionSubMenu_DropDownOpened); + // + // GBAmGBAMenuItem + // + this.GBAmGBAMenuItem.Name = "GBAmGBAMenuItem"; + this.GBAmGBAMenuItem.Size = new System.Drawing.Size(125, 22); + this.GBAmGBAMenuItem.Text = "mGBA"; + this.GBAmGBAMenuItem.Click += new System.EventHandler(this.UsemGBAMenuItem_Click); + // + // GBAVBANextMenuItem + // + this.GBAVBANextMenuItem.Name = "GBAVBANextMenuItem"; + this.GBAVBANextMenuItem.Size = new System.Drawing.Size(125, 22); + this.GBAVBANextMenuItem.Text = "&VBA-Next"; + this.GBAVBANextMenuItem.Click += new System.EventHandler(this.UseVbaNextMenuItem_Click); + // + // GBAcoresettingsToolStripMenuItem1 + // + 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); + // + // toolStripSeparator33 + // + this.toolStripSeparator33.Name = "toolStripSeparator33"; + this.toolStripSeparator33.Size = new System.Drawing.Size(132, 6); + // + // GbaGpuViewerMenuItem + // + this.GbaGpuViewerMenuItem.Name = "GbaGpuViewerMenuItem"; + this.GbaGpuViewerMenuItem.Size = new System.Drawing.Size(135, 22); + this.GbaGpuViewerMenuItem.Text = "GPU Viewer"; + this.GbaGpuViewerMenuItem.Click += new System.EventHandler(this.GbaGpuViewerMenuItem_Click); + // + // PSXSubMenu + // + this.PSXSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.PSXControllerSettingsMenuItem, this.PSXOptionsMenuItem, this.PSXDiscControlsMenuItem, this.PSXHashDiscsToolStripMenuItem}); - this.PSXSubMenu.Name = "PSXSubMenu"; - this.PSXSubMenu.Size = new System.Drawing.Size(37, 17); - this.PSXSubMenu.Text = "PSX"; - this.PSXSubMenu.DropDownOpened += new System.EventHandler(this.PSXSubMenu_DropDownOpened); - // - // PSXControllerSettingsMenuItem - // - this.PSXControllerSettingsMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.GameController; - this.PSXControllerSettingsMenuItem.Name = "PSXControllerSettingsMenuItem"; - this.PSXControllerSettingsMenuItem.Size = new System.Drawing.Size(216, 22); - this.PSXControllerSettingsMenuItem.Text = "Controller / Memcard Settings"; - this.PSXControllerSettingsMenuItem.Click += new System.EventHandler(this.PSXControllerSettingsMenuItem_Click); - // - // PSXOptionsMenuItem - // - this.PSXOptionsMenuItem.Name = "PSXOptionsMenuItem"; - this.PSXOptionsMenuItem.Size = new System.Drawing.Size(216, 22); - this.PSXOptionsMenuItem.Text = "&Options"; - this.PSXOptionsMenuItem.Click += new System.EventHandler(this.PSXOptionsMenuItem_Click); - // - // PSXDiscControlsMenuItem - // - this.PSXDiscControlsMenuItem.Name = "PSXDiscControlsMenuItem"; - this.PSXDiscControlsMenuItem.Size = new System.Drawing.Size(216, 22); - this.PSXDiscControlsMenuItem.Text = "&Disc Controls"; - this.PSXDiscControlsMenuItem.Click += new System.EventHandler(this.PSXDiscControlsMenuItem_Click); - // - // PSXHashDiscsToolStripMenuItem - // - this.PSXHashDiscsToolStripMenuItem.Name = "PSXHashDiscsToolStripMenuItem"; - this.PSXHashDiscsToolStripMenuItem.Size = new System.Drawing.Size(216, 22); - this.PSXHashDiscsToolStripMenuItem.Text = "&Hash Discs"; - this.PSXHashDiscsToolStripMenuItem.Click += new System.EventHandler(this.PSXHashDiscsToolStripMenuItem_Click); - // - // SNESSubMenu - // - this.SNESSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.PSXSubMenu.Name = "PSXSubMenu"; + this.PSXSubMenu.Size = new System.Drawing.Size(39, 19); + this.PSXSubMenu.Text = "PSX"; + this.PSXSubMenu.DropDownOpened += new System.EventHandler(this.PSXSubMenu_DropDownOpened); + // + // PSXControllerSettingsMenuItem + // + this.PSXControllerSettingsMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.GameController; + this.PSXControllerSettingsMenuItem.Name = "PSXControllerSettingsMenuItem"; + this.PSXControllerSettingsMenuItem.Size = new System.Drawing.Size(234, 22); + this.PSXControllerSettingsMenuItem.Text = "Controller / Memcard Settings"; + this.PSXControllerSettingsMenuItem.Click += new System.EventHandler(this.PSXControllerSettingsMenuItem_Click); + // + // PSXOptionsMenuItem + // + this.PSXOptionsMenuItem.Name = "PSXOptionsMenuItem"; + this.PSXOptionsMenuItem.Size = new System.Drawing.Size(234, 22); + this.PSXOptionsMenuItem.Text = "&Options"; + this.PSXOptionsMenuItem.Click += new System.EventHandler(this.PSXOptionsMenuItem_Click); + // + // PSXDiscControlsMenuItem + // + this.PSXDiscControlsMenuItem.Name = "PSXDiscControlsMenuItem"; + this.PSXDiscControlsMenuItem.Size = new System.Drawing.Size(234, 22); + this.PSXDiscControlsMenuItem.Text = "&Disc Controls"; + this.PSXDiscControlsMenuItem.Click += new System.EventHandler(this.PSXDiscControlsMenuItem_Click); + // + // PSXHashDiscsToolStripMenuItem + // + this.PSXHashDiscsToolStripMenuItem.Name = "PSXHashDiscsToolStripMenuItem"; + this.PSXHashDiscsToolStripMenuItem.Size = new System.Drawing.Size(234, 22); + this.PSXHashDiscsToolStripMenuItem.Text = "&Hash Discs"; + this.PSXHashDiscsToolStripMenuItem.Click += new System.EventHandler(this.PSXHashDiscsToolStripMenuItem_Click); + // + // SNESSubMenu + // + this.SNESSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.SNESControllerConfigurationMenuItem, this.toolStripSeparator18, this.SnesGfxDebuggerMenuItem, this.SnesGBInSGBMenuItem, this.SnesGameGenieMenuItem, this.SnesOptionsMenuItem}); - this.SNESSubMenu.Name = "SNESSubMenu"; - this.SNESSubMenu.Size = new System.Drawing.Size(44, 17); - this.SNESSubMenu.Text = "&SNES"; - this.SNESSubMenu.DropDownOpened += new System.EventHandler(this.SNESSubMenu_DropDownOpened); - // - // SNESControllerConfigurationMenuItem - // - this.SNESControllerConfigurationMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.GameController; - this.SNESControllerConfigurationMenuItem.Name = "SNESControllerConfigurationMenuItem"; - this.SNESControllerConfigurationMenuItem.Size = new System.Drawing.Size(217, 22); - this.SNESControllerConfigurationMenuItem.Text = "Controller Configuration"; - this.SNESControllerConfigurationMenuItem.Click += new System.EventHandler(this.SNESControllerConfigurationMenuItem_Click); - // - // toolStripSeparator18 - // - this.toolStripSeparator18.Name = "toolStripSeparator18"; - this.toolStripSeparator18.Size = new System.Drawing.Size(214, 6); - // - // SnesGfxDebuggerMenuItem - // - this.SnesGfxDebuggerMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.Bug; - this.SnesGfxDebuggerMenuItem.Name = "SnesGfxDebuggerMenuItem"; - this.SnesGfxDebuggerMenuItem.Size = new System.Drawing.Size(217, 22); - this.SnesGfxDebuggerMenuItem.Text = "Graphics Debugger"; - this.SnesGfxDebuggerMenuItem.Click += new System.EventHandler(this.SnesGfxDebuggerMenuItem_Click); - // - // SnesGBInSGBMenuItem - // - this.SnesGBInSGBMenuItem.Name = "SnesGBInSGBMenuItem"; - this.SnesGBInSGBMenuItem.Size = new System.Drawing.Size(217, 22); - this.SnesGBInSGBMenuItem.Text = "Load GB in SGB"; - this.SnesGBInSGBMenuItem.Click += new System.EventHandler(this.SnesGbInSgbMenuItem_Click); - // - // SnesGameGenieMenuItem - // - this.SnesGameGenieMenuItem.Name = "SnesGameGenieMenuItem"; - this.SnesGameGenieMenuItem.Size = new System.Drawing.Size(217, 22); - this.SnesGameGenieMenuItem.Text = "&Game Genie Encoder/Decoder"; - this.SnesGameGenieMenuItem.Click += new System.EventHandler(this.SnesGameGenieMenuItem_Click); - // - // SnesOptionsMenuItem - // - this.SnesOptionsMenuItem.Name = "SnesOptionsMenuItem"; - this.SnesOptionsMenuItem.Size = new System.Drawing.Size(217, 22); - this.SnesOptionsMenuItem.Text = "&Options"; - this.SnesOptionsMenuItem.Click += new System.EventHandler(this.SnesOptionsMenuItem_Click); - // - // ColecoSubMenu - // - this.ColecoSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.SNESSubMenu.Name = "SNESSubMenu"; + this.SNESSubMenu.Size = new System.Drawing.Size(46, 19); + this.SNESSubMenu.Text = "&SNES"; + this.SNESSubMenu.DropDownOpened += new System.EventHandler(this.SNESSubMenu_DropDownOpened); + // + // SNESControllerConfigurationMenuItem + // + this.SNESControllerConfigurationMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.GameController; + this.SNESControllerConfigurationMenuItem.Name = "SNESControllerConfigurationMenuItem"; + this.SNESControllerConfigurationMenuItem.Size = new System.Drawing.Size(233, 22); + this.SNESControllerConfigurationMenuItem.Text = "Controller Configuration"; + this.SNESControllerConfigurationMenuItem.Click += new System.EventHandler(this.SNESControllerConfigurationMenuItem_Click); + // + // toolStripSeparator18 + // + this.toolStripSeparator18.Name = "toolStripSeparator18"; + this.toolStripSeparator18.Size = new System.Drawing.Size(230, 6); + // + // SnesGfxDebuggerMenuItem + // + this.SnesGfxDebuggerMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.Bug; + this.SnesGfxDebuggerMenuItem.Name = "SnesGfxDebuggerMenuItem"; + this.SnesGfxDebuggerMenuItem.Size = new System.Drawing.Size(233, 22); + this.SnesGfxDebuggerMenuItem.Text = "Graphics Debugger"; + this.SnesGfxDebuggerMenuItem.Click += new System.EventHandler(this.SnesGfxDebuggerMenuItem_Click); + // + // SnesGBInSGBMenuItem + // + this.SnesGBInSGBMenuItem.Name = "SnesGBInSGBMenuItem"; + this.SnesGBInSGBMenuItem.Size = new System.Drawing.Size(233, 22); + this.SnesGBInSGBMenuItem.Text = "Load GB in SGB"; + this.SnesGBInSGBMenuItem.Click += new System.EventHandler(this.SnesGbInSgbMenuItem_Click); + // + // SnesGameGenieMenuItem + // + this.SnesGameGenieMenuItem.Name = "SnesGameGenieMenuItem"; + this.SnesGameGenieMenuItem.Size = new System.Drawing.Size(233, 22); + this.SnesGameGenieMenuItem.Text = "&Game Genie Encoder/Decoder"; + this.SnesGameGenieMenuItem.Click += new System.EventHandler(this.SnesGameGenieMenuItem_Click); + // + // SnesOptionsMenuItem + // + this.SnesOptionsMenuItem.Name = "SnesOptionsMenuItem"; + this.SnesOptionsMenuItem.Size = new System.Drawing.Size(233, 22); + this.SnesOptionsMenuItem.Text = "&Options"; + this.SnesOptionsMenuItem.Click += new System.EventHandler(this.SnesOptionsMenuItem_Click); + // + // ColecoSubMenu + // + this.ColecoSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.ColecoControllerSettingsMenuItem, this.toolStripSeparator35, this.ColecoSkipBiosMenuItem}); - this.ColecoSubMenu.Name = "ColecoSubMenu"; - this.ColecoSubMenu.Size = new System.Drawing.Size(51, 17); - this.ColecoSubMenu.Text = "&Coleco"; - this.ColecoSubMenu.DropDownOpened += new System.EventHandler(this.ColecoSubMenu_DropDownOpened); - // - // ColecoControllerSettingsMenuItem - // - this.ColecoControllerSettingsMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.GameController; - this.ColecoControllerSettingsMenuItem.Name = "ColecoControllerSettingsMenuItem"; - this.ColecoControllerSettingsMenuItem.Size = new System.Drawing.Size(235, 22); - this.ColecoControllerSettingsMenuItem.Text = "&Controller Settings..."; - this.ColecoControllerSettingsMenuItem.Click += new System.EventHandler(this.ColecoControllerSettingsMenuItem_Click); - // - // toolStripSeparator35 - // - this.toolStripSeparator35.Name = "toolStripSeparator35"; - this.toolStripSeparator35.Size = new System.Drawing.Size(232, 6); - // - // ColecoSkipBiosMenuItem - // - this.ColecoSkipBiosMenuItem.Name = "ColecoSkipBiosMenuItem"; - this.ColecoSkipBiosMenuItem.Size = new System.Drawing.Size(235, 22); - this.ColecoSkipBiosMenuItem.Text = "&Skip BIOS intro (When Applicable)"; - this.ColecoSkipBiosMenuItem.Click += new System.EventHandler(this.ColecoSkipBiosMenuItem_Click); - // - // N64SubMenu - // - this.N64SubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.ColecoSubMenu.Name = "ColecoSubMenu"; + this.ColecoSubMenu.Size = new System.Drawing.Size(56, 19); + this.ColecoSubMenu.Text = "&Coleco"; + this.ColecoSubMenu.DropDownOpened += new System.EventHandler(this.ColecoSubMenu_DropDownOpened); + // + // ColecoControllerSettingsMenuItem + // + this.ColecoControllerSettingsMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.GameController; + this.ColecoControllerSettingsMenuItem.Name = "ColecoControllerSettingsMenuItem"; + this.ColecoControllerSettingsMenuItem.Size = new System.Drawing.Size(253, 22); + this.ColecoControllerSettingsMenuItem.Text = "&Controller Settings..."; + this.ColecoControllerSettingsMenuItem.Click += new System.EventHandler(this.ColecoControllerSettingsMenuItem_Click); + // + // toolStripSeparator35 + // + this.toolStripSeparator35.Name = "toolStripSeparator35"; + this.toolStripSeparator35.Size = new System.Drawing.Size(250, 6); + // + // ColecoSkipBiosMenuItem + // + this.ColecoSkipBiosMenuItem.Name = "ColecoSkipBiosMenuItem"; + this.ColecoSkipBiosMenuItem.Size = new System.Drawing.Size(253, 22); + this.ColecoSkipBiosMenuItem.Text = "&Skip BIOS intro (When Applicable)"; + this.ColecoSkipBiosMenuItem.Click += new System.EventHandler(this.ColecoSkipBiosMenuItem_Click); + // + // N64SubMenu + // + this.N64SubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.N64PluginSettingsMenuItem, this.N64ControllerSettingsMenuItem, this.toolStripSeparator23, this.N64CircularAnalogRangeMenuItem, this.MupenStyleLagMenuItem, this.N64ExpansionSlotMenuItem}); - this.N64SubMenu.Name = "N64SubMenu"; - this.N64SubMenu.Size = new System.Drawing.Size(38, 17); - this.N64SubMenu.Text = "N64"; - this.N64SubMenu.DropDownOpened += new System.EventHandler(this.N64SubMenu_DropDownOpened); - // - // N64PluginSettingsMenuItem - // - this.N64PluginSettingsMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("N64PluginSettingsMenuItem.Image"))); - this.N64PluginSettingsMenuItem.Name = "N64PluginSettingsMenuItem"; - this.N64PluginSettingsMenuItem.Size = new System.Drawing.Size(180, 22); - this.N64PluginSettingsMenuItem.Text = "Plugins"; - this.N64PluginSettingsMenuItem.Click += new System.EventHandler(this.N64PluginSettingsMenuItem_Click); - // - // N64ControllerSettingsMenuItem - // - this.N64ControllerSettingsMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.GameController; - this.N64ControllerSettingsMenuItem.Name = "N64ControllerSettingsMenuItem"; - this.N64ControllerSettingsMenuItem.Size = new System.Drawing.Size(180, 22); - this.N64ControllerSettingsMenuItem.Text = "Controller Settings..."; - this.N64ControllerSettingsMenuItem.Click += new System.EventHandler(this.N64ControllerSettingsMenuItem_Click); - // - // toolStripSeparator23 - // - this.toolStripSeparator23.Name = "toolStripSeparator23"; - this.toolStripSeparator23.Size = new System.Drawing.Size(177, 6); - // - // N64CircularAnalogRangeMenuItem - // - this.N64CircularAnalogRangeMenuItem.Name = "N64CircularAnalogRangeMenuItem"; - this.N64CircularAnalogRangeMenuItem.Size = new System.Drawing.Size(180, 22); - this.N64CircularAnalogRangeMenuItem.Text = "Circular Analog Range"; - this.N64CircularAnalogRangeMenuItem.Click += new System.EventHandler(this.N64CircularAnalogRangeMenuItem_Click); - // - // MupenStyleLagMenuItem - // - this.MupenStyleLagMenuItem.Name = "MupenStyleLagMenuItem"; - this.MupenStyleLagMenuItem.Size = new System.Drawing.Size(180, 22); - this.MupenStyleLagMenuItem.Text = "&Non-VI Lag Frames"; - this.MupenStyleLagMenuItem.Click += new System.EventHandler(this.MupenStyleLagMenuItem_Click); - // - // N64ExpansionSlotMenuItem - // - this.N64ExpansionSlotMenuItem.Name = "N64ExpansionSlotMenuItem"; - this.N64ExpansionSlotMenuItem.Size = new System.Drawing.Size(180, 22); - this.N64ExpansionSlotMenuItem.Text = "&Use Expansion Slot"; - this.N64ExpansionSlotMenuItem.Click += new System.EventHandler(this.N64ExpansionSlotMenuItem_Click); - // - // SaturnSubMenu - // - this.SaturnSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.N64SubMenu.Name = "N64SubMenu"; + this.N64SubMenu.Size = new System.Drawing.Size(40, 19); + this.N64SubMenu.Text = "N64"; + this.N64SubMenu.DropDownOpened += new System.EventHandler(this.N64SubMenu_DropDownOpened); + // + // N64PluginSettingsMenuItem + // + this.N64PluginSettingsMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("N64PluginSettingsMenuItem.Image"))); + this.N64PluginSettingsMenuItem.Name = "N64PluginSettingsMenuItem"; + this.N64PluginSettingsMenuItem.Size = new System.Drawing.Size(192, 22); + this.N64PluginSettingsMenuItem.Text = "Plugins"; + this.N64PluginSettingsMenuItem.Click += new System.EventHandler(this.N64PluginSettingsMenuItem_Click); + // + // N64ControllerSettingsMenuItem + // + this.N64ControllerSettingsMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.GameController; + this.N64ControllerSettingsMenuItem.Name = "N64ControllerSettingsMenuItem"; + this.N64ControllerSettingsMenuItem.Size = new System.Drawing.Size(192, 22); + this.N64ControllerSettingsMenuItem.Text = "Controller Settings..."; + this.N64ControllerSettingsMenuItem.Click += new System.EventHandler(this.N64ControllerSettingsMenuItem_Click); + // + // toolStripSeparator23 + // + this.toolStripSeparator23.Name = "toolStripSeparator23"; + this.toolStripSeparator23.Size = new System.Drawing.Size(189, 6); + // + // N64CircularAnalogRangeMenuItem + // + this.N64CircularAnalogRangeMenuItem.Name = "N64CircularAnalogRangeMenuItem"; + this.N64CircularAnalogRangeMenuItem.Size = new System.Drawing.Size(192, 22); + this.N64CircularAnalogRangeMenuItem.Text = "Circular Analog Range"; + this.N64CircularAnalogRangeMenuItem.Click += new System.EventHandler(this.N64CircularAnalogRangeMenuItem_Click); + // + // MupenStyleLagMenuItem + // + this.MupenStyleLagMenuItem.Name = "MupenStyleLagMenuItem"; + this.MupenStyleLagMenuItem.Size = new System.Drawing.Size(192, 22); + this.MupenStyleLagMenuItem.Text = "&Non-VI Lag Frames"; + this.MupenStyleLagMenuItem.Click += new System.EventHandler(this.MupenStyleLagMenuItem_Click); + // + // N64ExpansionSlotMenuItem + // + this.N64ExpansionSlotMenuItem.Name = "N64ExpansionSlotMenuItem"; + this.N64ExpansionSlotMenuItem.Size = new System.Drawing.Size(192, 22); + this.N64ExpansionSlotMenuItem.Text = "&Use Expansion Slot"; + this.N64ExpansionSlotMenuItem.Click += new System.EventHandler(this.N64ExpansionSlotMenuItem_Click); + // + // SaturnSubMenu + // + this.SaturnSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.SaturnPreferencesMenuItem}); - this.SaturnSubMenu.Name = "SaturnSubMenu"; - this.SaturnSubMenu.Size = new System.Drawing.Size(51, 17); - this.SaturnSubMenu.Text = "&Saturn"; - // - // SaturnPreferencesMenuItem - // - this.SaturnPreferencesMenuItem.Name = "SaturnPreferencesMenuItem"; - this.SaturnPreferencesMenuItem.Size = new System.Drawing.Size(144, 22); - this.SaturnPreferencesMenuItem.Text = "Preferences..."; - this.SaturnPreferencesMenuItem.Click += new System.EventHandler(this.SaturnPreferencesMenuItem_Click); - // - // DGBSubMenu - // - this.DGBSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.SaturnSubMenu.Name = "SaturnSubMenu"; + this.SaturnSubMenu.Size = new System.Drawing.Size(53, 19); + this.SaturnSubMenu.Text = "&Saturn"; + // + // SaturnPreferencesMenuItem + // + this.SaturnPreferencesMenuItem.Name = "SaturnPreferencesMenuItem"; + this.SaturnPreferencesMenuItem.Size = new System.Drawing.Size(144, 22); + this.SaturnPreferencesMenuItem.Text = "Preferences..."; + this.SaturnPreferencesMenuItem.Click += new System.EventHandler(this.SaturnPreferencesMenuItem_Click); + // + // DGBSubMenu + // + this.DGBSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.DGBsettingsToolStripMenuItem}); - this.DGBSubMenu.Name = "DGBSubMenu"; - this.DGBSubMenu.Size = new System.Drawing.Size(53, 17); - this.DGBSubMenu.Text = "&GB Link"; - // - // DGBsettingsToolStripMenuItem - // - this.DGBsettingsToolStripMenuItem.Name = "DGBsettingsToolStripMenuItem"; - this.DGBsettingsToolStripMenuItem.Size = new System.Drawing.Size(125, 22); - this.DGBsettingsToolStripMenuItem.Text = "Settings..."; - this.DGBsettingsToolStripMenuItem.Click += new System.EventHandler(this.DgbSettingsMenuItem_Click); - // - // GenesisSubMenu - // - this.GenesisSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.DGBSubMenu.Name = "DGBSubMenu"; + this.DGBSubMenu.Size = new System.Drawing.Size(59, 19); + this.DGBSubMenu.Text = "&GB Link"; + // + // DGBsettingsToolStripMenuItem + // + this.DGBsettingsToolStripMenuItem.Name = "DGBsettingsToolStripMenuItem"; + this.DGBsettingsToolStripMenuItem.Size = new System.Drawing.Size(125, 22); + this.DGBsettingsToolStripMenuItem.Text = "Settings..."; + this.DGBsettingsToolStripMenuItem.Click += new System.EventHandler(this.DgbSettingsMenuItem_Click); + // + // GenesisSubMenu + // + this.GenesisSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.vDPViewerToolStripMenuItem, this.GenesisGameGenieECDC, this.toolStripSeparator26, this.GenesisSettingsToolStripMenuItem}); - this.GenesisSubMenu.Name = "GenesisSubMenu"; - this.GenesisSubMenu.Size = new System.Drawing.Size(56, 17); - this.GenesisSubMenu.Text = "&Genesis"; - // - // vDPViewerToolStripMenuItem - // - this.vDPViewerToolStripMenuItem.Name = "vDPViewerToolStripMenuItem"; - this.vDPViewerToolStripMenuItem.Size = new System.Drawing.Size(217, 22); - this.vDPViewerToolStripMenuItem.Text = "&VDP Viewer"; - this.vDPViewerToolStripMenuItem.Click += new System.EventHandler(this.GenVdpViewerMenuItem_Click); - // - // GenesisGameGenieECDC - // - this.GenesisGameGenieECDC.Name = "GenesisGameGenieECDC"; - this.GenesisGameGenieECDC.Size = new System.Drawing.Size(217, 22); - this.GenesisGameGenieECDC.Text = "&Game Genie Encoder/Decoder"; - this.GenesisGameGenieECDC.Click += new System.EventHandler(this.GenesisGameGenieEcDc_Click); - // - // toolStripSeparator26 - // - this.toolStripSeparator26.Name = "toolStripSeparator26"; - this.toolStripSeparator26.Size = new System.Drawing.Size(214, 6); - // - // GenesisSettingsToolStripMenuItem - // - this.GenesisSettingsToolStripMenuItem.Name = "GenesisSettingsToolStripMenuItem"; - this.GenesisSettingsToolStripMenuItem.Size = new System.Drawing.Size(217, 22); - this.GenesisSettingsToolStripMenuItem.Text = "&Settings..."; - this.GenesisSettingsToolStripMenuItem.Click += new System.EventHandler(this.GenesisSettingsMenuItem_Click); - // - // wonderSwanToolStripMenuItem - // - this.wonderSwanToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.GenesisSubMenu.Name = "GenesisSubMenu"; + this.GenesisSubMenu.Size = new System.Drawing.Size(59, 19); + this.GenesisSubMenu.Text = "&Genesis"; + // + // vDPViewerToolStripMenuItem + // + this.vDPViewerToolStripMenuItem.Name = "vDPViewerToolStripMenuItem"; + this.vDPViewerToolStripMenuItem.Size = new System.Drawing.Size(233, 22); + this.vDPViewerToolStripMenuItem.Text = "&VDP Viewer"; + this.vDPViewerToolStripMenuItem.Click += new System.EventHandler(this.GenVdpViewerMenuItem_Click); + // + // GenesisGameGenieECDC + // + this.GenesisGameGenieECDC.Name = "GenesisGameGenieECDC"; + this.GenesisGameGenieECDC.Size = new System.Drawing.Size(233, 22); + this.GenesisGameGenieECDC.Text = "&Game Genie Encoder/Decoder"; + this.GenesisGameGenieECDC.Click += new System.EventHandler(this.GenesisGameGenieEcDc_Click); + // + // toolStripSeparator26 + // + this.toolStripSeparator26.Name = "toolStripSeparator26"; + this.toolStripSeparator26.Size = new System.Drawing.Size(230, 6); + // + // GenesisSettingsToolStripMenuItem + // + this.GenesisSettingsToolStripMenuItem.Name = "GenesisSettingsToolStripMenuItem"; + this.GenesisSettingsToolStripMenuItem.Size = new System.Drawing.Size(233, 22); + this.GenesisSettingsToolStripMenuItem.Text = "&Settings..."; + this.GenesisSettingsToolStripMenuItem.Click += new System.EventHandler(this.GenesisSettingsMenuItem_Click); + // + // wonderSwanToolStripMenuItem + // + this.wonderSwanToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.settingsToolStripMenuItem}); - this.wonderSwanToolStripMenuItem.Name = "wonderSwanToolStripMenuItem"; - this.wonderSwanToolStripMenuItem.Size = new System.Drawing.Size(83, 17); - this.wonderSwanToolStripMenuItem.Text = "&WonderSwan"; - // - // settingsToolStripMenuItem - // - 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); - // - // AppleSubMenu - // - this.AppleSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.wonderSwanToolStripMenuItem.Name = "wonderSwanToolStripMenuItem"; + this.wonderSwanToolStripMenuItem.Size = new System.Drawing.Size(89, 19); + this.wonderSwanToolStripMenuItem.Text = "&WonderSwan"; + // + // settingsToolStripMenuItem + // + 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); + // + // AppleSubMenu + // + this.AppleSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.AppleDisksSubMenu, this.settingsToolStripMenuItem1}); - this.AppleSubMenu.Name = "AppleSubMenu"; - this.AppleSubMenu.Size = new System.Drawing.Size(46, 17); - this.AppleSubMenu.Text = "Apple"; - this.AppleSubMenu.DropDownOpened += new System.EventHandler(this.AppleSubMenu_DropDownOpened); - // - // AppleDisksSubMenu - // - this.AppleDisksSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.AppleSubMenu.Name = "AppleSubMenu"; + this.AppleSubMenu.Size = new System.Drawing.Size(50, 19); + this.AppleSubMenu.Text = "Apple"; + this.AppleSubMenu.DropDownOpened += new System.EventHandler(this.AppleSubMenu_DropDownOpened); + // + // AppleDisksSubMenu + // + this.AppleDisksSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.toolStripSeparator31}); - this.AppleDisksSubMenu.Name = "AppleDisksSubMenu"; - this.AppleDisksSubMenu.Size = new System.Drawing.Size(125, 22); - this.AppleDisksSubMenu.Text = "Disks"; - this.AppleDisksSubMenu.DropDownOpened += new System.EventHandler(this.AppleDisksSubMenu_DropDownOpened); - // - // toolStripSeparator31 - // - this.toolStripSeparator31.Name = "toolStripSeparator31"; - this.toolStripSeparator31.Size = new System.Drawing.Size(57, 6); - // - // settingsToolStripMenuItem1 - // - this.settingsToolStripMenuItem1.Name = "settingsToolStripMenuItem1"; - this.settingsToolStripMenuItem1.Size = new System.Drawing.Size(125, 22); - this.settingsToolStripMenuItem1.Text = "&Settings..."; - this.settingsToolStripMenuItem1.Click += new System.EventHandler(this.AppleIISettingsMenuItem_Click); - // - // C64SubMenu - // - this.C64SubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.AppleDisksSubMenu.Name = "AppleDisksSubMenu"; + this.AppleDisksSubMenu.Size = new System.Drawing.Size(125, 22); + this.AppleDisksSubMenu.Text = "Disks"; + this.AppleDisksSubMenu.DropDownOpened += new System.EventHandler(this.AppleDisksSubMenu_DropDownOpened); + // + // toolStripSeparator31 + // + this.toolStripSeparator31.Name = "toolStripSeparator31"; + this.toolStripSeparator31.Size = new System.Drawing.Size(57, 6); + // + // settingsToolStripMenuItem1 + // + this.settingsToolStripMenuItem1.Name = "settingsToolStripMenuItem1"; + this.settingsToolStripMenuItem1.Size = new System.Drawing.Size(125, 22); + this.settingsToolStripMenuItem1.Text = "&Settings..."; + this.settingsToolStripMenuItem1.Click += new System.EventHandler(this.AppleIISettingsMenuItem_Click); + // + // C64SubMenu + // + this.C64SubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.C64DisksSubMenu, this.C64SettingsMenuItem}); - this.C64SubMenu.Name = "C64SubMenu"; - this.C64SubMenu.Size = new System.Drawing.Size(38, 17); - this.C64SubMenu.Text = "&C64"; - this.C64SubMenu.DropDownOpened += new System.EventHandler(this.C64SubMenu_DropDownOpened); - // - // C64DisksSubMenu - // - this.C64DisksSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.C64SubMenu.Name = "C64SubMenu"; + this.C64SubMenu.Size = new System.Drawing.Size(39, 19); + this.C64SubMenu.Text = "&C64"; + this.C64SubMenu.DropDownOpened += new System.EventHandler(this.C64SubMenu_DropDownOpened); + // + // C64DisksSubMenu + // + this.C64DisksSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.toolStripSeparator36}); - this.C64DisksSubMenu.Name = "C64DisksSubMenu"; - this.C64DisksSubMenu.Size = new System.Drawing.Size(125, 22); - this.C64DisksSubMenu.Text = "Disks"; - this.C64DisksSubMenu.DropDownOpened += new System.EventHandler(this.C64DisksSubMenu_DropDownOpened); - // - // toolStripSeparator36 - // - this.toolStripSeparator36.Name = "toolStripSeparator36"; - this.toolStripSeparator36.Size = new System.Drawing.Size(57, 6); - // - // C64SettingsMenuItem - // - this.C64SettingsMenuItem.Name = "C64SettingsMenuItem"; - this.C64SettingsMenuItem.Size = new System.Drawing.Size(125, 22); - this.C64SettingsMenuItem.Text = "&Settings..."; - this.C64SettingsMenuItem.Click += new System.EventHandler(this.C64SettingsMenuItem_Click); - // - // IntvSubMenu - // - this.IntvSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.C64DisksSubMenu.Name = "C64DisksSubMenu"; + this.C64DisksSubMenu.Size = new System.Drawing.Size(125, 22); + this.C64DisksSubMenu.Text = "Disks"; + this.C64DisksSubMenu.DropDownOpened += new System.EventHandler(this.C64DisksSubMenu_DropDownOpened); + // + // toolStripSeparator36 + // + this.toolStripSeparator36.Name = "toolStripSeparator36"; + this.toolStripSeparator36.Size = new System.Drawing.Size(57, 6); + // + // C64SettingsMenuItem + // + this.C64SettingsMenuItem.Name = "C64SettingsMenuItem"; + this.C64SettingsMenuItem.Size = new System.Drawing.Size(125, 22); + this.C64SettingsMenuItem.Text = "&Settings..."; + this.C64SettingsMenuItem.Click += new System.EventHandler(this.C64SettingsMenuItem_Click); + // + // IntvSubMenu + // + this.IntvSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.IntVControllerSettingsMenuItem}); - this.IntvSubMenu.Name = "IntvSubMenu"; - this.IntvSubMenu.Size = new System.Drawing.Size(39, 17); - this.IntvSubMenu.Text = "&Intv"; - this.IntvSubMenu.DropDownOpened += new System.EventHandler(this.IntvSubMenu_DropDownOpened); - // - // IntVControllerSettingsMenuItem - // - this.IntVControllerSettingsMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.GameController; - this.IntVControllerSettingsMenuItem.Name = "IntVControllerSettingsMenuItem"; - this.IntVControllerSettingsMenuItem.Size = new System.Drawing.Size(175, 22); - this.IntVControllerSettingsMenuItem.Text = "Controller Settings..."; - this.IntVControllerSettingsMenuItem.Click += new System.EventHandler(this.IntVControllerSettingsMenuItem_Click); - // - // sNESToolStripMenuItem - // - this.sNESToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + 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); + // + // IntVControllerSettingsMenuItem + // + this.IntVControllerSettingsMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.GameController; + this.IntVControllerSettingsMenuItem.Name = "IntVControllerSettingsMenuItem"; + this.IntVControllerSettingsMenuItem.Size = new System.Drawing.Size(181, 22); + this.IntVControllerSettingsMenuItem.Text = "Controller Settings..."; + this.IntVControllerSettingsMenuItem.Click += new System.EventHandler(this.IntVControllerSettingsMenuItem_Click); + // + // sNESToolStripMenuItem + // + this.sNESToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.preferencesToolStripMenuItem}); - this.sNESToolStripMenuItem.Name = "sNESToolStripMenuItem"; - this.sNESToolStripMenuItem.Size = new System.Drawing.Size(44, 17); - this.sNESToolStripMenuItem.Text = "&SNES"; - // - // preferencesToolStripMenuItem - // - 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); - // - // virtualBoyToolStripMenuItem - // - this.virtualBoyToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.sNESToolStripMenuItem.Name = "sNESToolStripMenuItem"; + this.sNESToolStripMenuItem.Size = new System.Drawing.Size(46, 19); + this.sNESToolStripMenuItem.Text = "&SNES"; + // + // preferencesToolStripMenuItem + // + 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); + // + // pCFXToolStripMenuItem + // + this.pCFXToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.preferencesToolStripMenuItem3}); + this.pCFXToolStripMenuItem.Name = "pCFXToolStripMenuItem"; + this.pCFXToolStripMenuItem.Size = new System.Drawing.Size(52, 19); + this.pCFXToolStripMenuItem.Text = "&PC-FX"; + // + // preferencesToolStripMenuItem3 + // + 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); + // + // virtualBoyToolStripMenuItem + // + this.virtualBoyToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.preferencesToolStripMenuItem1}); - this.virtualBoyToolStripMenuItem.Name = "virtualBoyToolStripMenuItem"; - this.virtualBoyToolStripMenuItem.Size = new System.Drawing.Size(67, 17); - this.virtualBoyToolStripMenuItem.Text = "&VirtualBoy"; - // - // preferencesToolStripMenuItem1 - // - this.preferencesToolStripMenuItem1.Name = "preferencesToolStripMenuItem1"; - this.preferencesToolStripMenuItem1.Size = new System.Drawing.Size(152, 22); - this.preferencesToolStripMenuItem1.Text = "Preferences..."; - this.preferencesToolStripMenuItem1.Click += new System.EventHandler(this.preferencesToolStripMenuItem1_Click); - // - // neoGeoPocketToolStripMenuItem - // - this.neoGeoPocketToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.virtualBoyToolStripMenuItem.Name = "virtualBoyToolStripMenuItem"; + this.virtualBoyToolStripMenuItem.Size = new System.Drawing.Size(73, 19); + this.virtualBoyToolStripMenuItem.Text = "&VirtualBoy"; + // + // preferencesToolStripMenuItem1 + // + 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); + // + // neoGeoPocketToolStripMenuItem + // + this.neoGeoPocketToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.preferencesToolStripMenuItem2}); - this.neoGeoPocketToolStripMenuItem.Name = "neoGeoPocketToolStripMenuItem"; - this.neoGeoPocketToolStripMenuItem.Size = new System.Drawing.Size(92, 17); - this.neoGeoPocketToolStripMenuItem.Text = "&NeoGeo Pocket"; - // - // preferencesToolStripMenuItem2 - // - 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); - // - // HelpSubMenu - // - this.HelpSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.neoGeoPocketToolStripMenuItem.Name = "neoGeoPocketToolStripMenuItem"; + this.neoGeoPocketToolStripMenuItem.Size = new System.Drawing.Size(101, 19); + this.neoGeoPocketToolStripMenuItem.Text = "&NeoGeo Pocket"; + // + // preferencesToolStripMenuItem2 + // + 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); + // + // HelpSubMenu + // + this.HelpSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.OnlineHelpMenuItem, this.ForumsMenuItem, this.FeaturesMenuItem, this.AboutMenuItem}); - this.HelpSubMenu.Name = "HelpSubMenu"; - this.HelpSubMenu.Size = new System.Drawing.Size(40, 17); - this.HelpSubMenu.Text = "&Help"; - this.HelpSubMenu.DropDownOpened += new System.EventHandler(this.HelpSubMenu_DropDownOpened); - // - // OnlineHelpMenuItem - // - this.OnlineHelpMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.Help; - this.OnlineHelpMenuItem.Name = "OnlineHelpMenuItem"; - this.OnlineHelpMenuItem.Size = new System.Drawing.Size(140, 22); - this.OnlineHelpMenuItem.Text = "&Online Help..."; - this.OnlineHelpMenuItem.Click += new System.EventHandler(this.OnlineHelpMenuItem_Click); - // - // ForumsMenuItem - // - this.ForumsMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.TAStudio; - this.ForumsMenuItem.Name = "ForumsMenuItem"; - this.ForumsMenuItem.Size = new System.Drawing.Size(140, 22); - this.ForumsMenuItem.Text = "Forums..."; - this.ForumsMenuItem.Click += new System.EventHandler(this.ForumsMenuItem_Click); - // - // FeaturesMenuItem - // - this.FeaturesMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.kitchensink; - this.FeaturesMenuItem.Name = "FeaturesMenuItem"; - this.FeaturesMenuItem.Size = new System.Drawing.Size(140, 22); - this.FeaturesMenuItem.Text = "&Features"; - this.FeaturesMenuItem.Click += new System.EventHandler(this.FeaturesMenuItem_Click); - // - // AboutMenuItem - // - this.AboutMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.CorpHawkSmall; - this.AboutMenuItem.Name = "AboutMenuItem"; - this.AboutMenuItem.Size = new System.Drawing.Size(140, 22); - this.AboutMenuItem.Text = "&About"; - this.AboutMenuItem.Click += new System.EventHandler(this.AboutMenuItem_Click); - // - // MainStatusBar - // - this.MainStatusBar.ClickThrough = true; - this.MainStatusBar.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.HelpSubMenu.Name = "HelpSubMenu"; + this.HelpSubMenu.Size = new System.Drawing.Size(44, 19); + this.HelpSubMenu.Text = "&Help"; + this.HelpSubMenu.DropDownOpened += new System.EventHandler(this.HelpSubMenu_DropDownOpened); + // + // OnlineHelpMenuItem + // + this.OnlineHelpMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.Help; + this.OnlineHelpMenuItem.Name = "OnlineHelpMenuItem"; + this.OnlineHelpMenuItem.Size = new System.Drawing.Size(146, 22); + this.OnlineHelpMenuItem.Text = "&Online Help..."; + this.OnlineHelpMenuItem.Click += new System.EventHandler(this.OnlineHelpMenuItem_Click); + // + // ForumsMenuItem + // + this.ForumsMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.TAStudio; + this.ForumsMenuItem.Name = "ForumsMenuItem"; + this.ForumsMenuItem.Size = new System.Drawing.Size(146, 22); + this.ForumsMenuItem.Text = "Forums..."; + this.ForumsMenuItem.Click += new System.EventHandler(this.ForumsMenuItem_Click); + // + // FeaturesMenuItem + // + this.FeaturesMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.kitchensink; + this.FeaturesMenuItem.Name = "FeaturesMenuItem"; + this.FeaturesMenuItem.Size = new System.Drawing.Size(146, 22); + this.FeaturesMenuItem.Text = "&Features"; + this.FeaturesMenuItem.Click += new System.EventHandler(this.FeaturesMenuItem_Click); + // + // AboutMenuItem + // + this.AboutMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.CorpHawkSmall; + this.AboutMenuItem.Name = "AboutMenuItem"; + this.AboutMenuItem.Size = new System.Drawing.Size(146, 22); + this.AboutMenuItem.Text = "&About"; + this.AboutMenuItem.Click += new System.EventHandler(this.AboutMenuItem_Click); + // + // MainStatusBar + // + this.MainStatusBar.ClickThrough = true; + this.MainStatusBar.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { this.DumpStatusButton, this.EmuStatus, this.PlayRecordStatusButton, @@ -3311,224 +3326,224 @@ this.ProfileFirstBootLabel, this.LinkConnectStatusBarButton, this.UpdateNotification}); - this.MainStatusBar.Location = new System.Drawing.Point(0, 386); - this.MainStatusBar.Name = "MainStatusBar"; - this.MainStatusBar.ShowItemToolTips = true; - this.MainStatusBar.Size = new System.Drawing.Size(470, 22); - this.MainStatusBar.SizingGrip = false; - this.MainStatusBar.TabIndex = 1; - this.MainStatusBar.Text = "0"; - // - // DumpStatusButton - // - this.DumpStatusButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - this.DumpStatusButton.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.Blank; - this.DumpStatusButton.ImageTransparentColor = System.Drawing.Color.Magenta; - this.DumpStatusButton.Name = "DumpStatusButton"; - this.DumpStatusButton.ShowDropDownArrow = false; - this.DumpStatusButton.Size = new System.Drawing.Size(20, 20); - this.DumpStatusButton.Text = "No ROM loaded"; - this.DumpStatusButton.Click += new System.EventHandler(this.DumpStatusButton_Click); - // - // EmuStatus - // - this.EmuStatus.Name = "EmuStatus"; - this.EmuStatus.Size = new System.Drawing.Size(0, 17); - // - // PlayRecordStatusButton - // - this.PlayRecordStatusButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - this.PlayRecordStatusButton.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.Blank; - this.PlayRecordStatusButton.ImageTransparentColor = System.Drawing.Color.Magenta; - this.PlayRecordStatusButton.Name = "PlayRecordStatusButton"; - this.PlayRecordStatusButton.ShowDropDownArrow = false; - this.PlayRecordStatusButton.Size = new System.Drawing.Size(20, 20); - this.PlayRecordStatusButton.Text = "No movie is active"; - // - // PauseStatusButton - // - this.PauseStatusButton.Alignment = System.Windows.Forms.ToolStripItemAlignment.Right; - this.PauseStatusButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - this.PauseStatusButton.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.Blank; - this.PauseStatusButton.ImageTransparentColor = System.Drawing.Color.Magenta; - this.PauseStatusButton.Name = "PauseStatusButton"; - this.PauseStatusButton.ShowDropDownArrow = false; - this.PauseStatusButton.Size = new System.Drawing.Size(20, 20); - this.PauseStatusButton.Text = "toolStripDropDownButton1"; - this.PauseStatusButton.ToolTipText = "Emulator is paused"; - this.PauseStatusButton.Click += new System.EventHandler(this.PauseMenuItem_Click); - // - // RebootStatusBarIcon - // - this.RebootStatusBarIcon.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - this.RebootStatusBarIcon.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.reboot; - this.RebootStatusBarIcon.Name = "RebootStatusBarIcon"; - this.RebootStatusBarIcon.RightToLeft = System.Windows.Forms.RightToLeft.No; - this.RebootStatusBarIcon.Size = new System.Drawing.Size(16, 17); - this.RebootStatusBarIcon.Text = "Reboot"; - this.RebootStatusBarIcon.ToolTipText = "A reboot of the core is needed for a setting change to take effect"; - this.RebootStatusBarIcon.Click += new System.EventHandler(this.PowerMenuItem_Click); - // - // AVIStatusLabel - // - this.AVIStatusLabel.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - this.AVIStatusLabel.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.Blank; - this.AVIStatusLabel.Name = "AVIStatusLabel"; - this.AVIStatusLabel.Size = new System.Drawing.Size(16, 17); - this.AVIStatusLabel.Text = "AVI Capture"; - // - // LedLightStatusLabel - // - this.LedLightStatusLabel.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.LightOff; - this.LedLightStatusLabel.Name = "LedLightStatusLabel"; - this.LedLightStatusLabel.Size = new System.Drawing.Size(16, 17); - this.LedLightStatusLabel.ToolTipText = "Disk Drive LED Light"; - // - // SaveSlotsStatusLabel - // - this.SaveSlotsStatusLabel.BackColor = System.Drawing.SystemColors.Control; - this.SaveSlotsStatusLabel.Name = "SaveSlotsStatusLabel"; - this.SaveSlotsStatusLabel.Size = new System.Drawing.Size(56, 17); - this.SaveSlotsStatusLabel.Text = "Save slots"; - // - // Slot1StatusButton - // - this.Slot1StatusButton.Name = "Slot1StatusButton"; - this.Slot1StatusButton.Size = new System.Drawing.Size(13, 17); - this.Slot1StatusButton.Text = "1"; - this.Slot1StatusButton.ToolTipText = "Save slot 1"; - this.Slot1StatusButton.MouseUp += new System.Windows.Forms.MouseEventHandler(this.SlotStatusButtons_MouseUp); - // - // Slot2StatusButton - // - this.Slot2StatusButton.Name = "Slot2StatusButton"; - this.Slot2StatusButton.Size = new System.Drawing.Size(13, 17); - this.Slot2StatusButton.Text = "2"; - this.Slot2StatusButton.ToolTipText = "Save slot 2"; - this.Slot2StatusButton.MouseUp += new System.Windows.Forms.MouseEventHandler(this.SlotStatusButtons_MouseUp); - // - // Slot3StatusButton - // - this.Slot3StatusButton.Name = "Slot3StatusButton"; - this.Slot3StatusButton.Size = new System.Drawing.Size(13, 17); - this.Slot3StatusButton.Text = "3"; - this.Slot3StatusButton.ToolTipText = "Save slot 3"; - this.Slot3StatusButton.MouseUp += new System.Windows.Forms.MouseEventHandler(this.SlotStatusButtons_MouseUp); - // - // Slot4StatusButton - // - this.Slot4StatusButton.Name = "Slot4StatusButton"; - this.Slot4StatusButton.Size = new System.Drawing.Size(13, 17); - this.Slot4StatusButton.Text = "4"; - this.Slot4StatusButton.ToolTipText = "Save slot 4"; - this.Slot4StatusButton.MouseUp += new System.Windows.Forms.MouseEventHandler(this.SlotStatusButtons_MouseUp); - // - // Slot5StatusButton - // - this.Slot5StatusButton.Name = "Slot5StatusButton"; - this.Slot5StatusButton.Size = new System.Drawing.Size(13, 17); - this.Slot5StatusButton.Text = "5"; - this.Slot5StatusButton.ToolTipText = "Save slot 5"; - this.Slot5StatusButton.MouseUp += new System.Windows.Forms.MouseEventHandler(this.SlotStatusButtons_MouseUp); - // - // Slot6StatusButton - // - this.Slot6StatusButton.Name = "Slot6StatusButton"; - this.Slot6StatusButton.Size = new System.Drawing.Size(13, 17); - this.Slot6StatusButton.Text = "6"; - this.Slot6StatusButton.ToolTipText = "Save slot 6"; - this.Slot6StatusButton.MouseUp += new System.Windows.Forms.MouseEventHandler(this.SlotStatusButtons_MouseUp); - // - // Slot7StatusButton - // - this.Slot7StatusButton.Name = "Slot7StatusButton"; - this.Slot7StatusButton.Size = new System.Drawing.Size(13, 17); - this.Slot7StatusButton.Text = "7"; - this.Slot7StatusButton.ToolTipText = "Save slot 7"; - this.Slot7StatusButton.MouseUp += new System.Windows.Forms.MouseEventHandler(this.SlotStatusButtons_MouseUp); - // - // Slot8StatusButton - // - this.Slot8StatusButton.Name = "Slot8StatusButton"; - this.Slot8StatusButton.Size = new System.Drawing.Size(13, 17); - this.Slot8StatusButton.Text = "8"; - this.Slot8StatusButton.ToolTipText = "Save slot 8"; - this.Slot8StatusButton.MouseUp += new System.Windows.Forms.MouseEventHandler(this.SlotStatusButtons_MouseUp); - // - // Slot9StatusButton - // - this.Slot9StatusButton.Name = "Slot9StatusButton"; - this.Slot9StatusButton.Size = new System.Drawing.Size(13, 17); - this.Slot9StatusButton.Text = "9"; - this.Slot9StatusButton.ToolTipText = "Save slot 9"; - this.Slot9StatusButton.MouseUp += new System.Windows.Forms.MouseEventHandler(this.SlotStatusButtons_MouseUp); - // - // Slot0StatusButton - // - this.Slot0StatusButton.Name = "Slot0StatusButton"; - this.Slot0StatusButton.Size = new System.Drawing.Size(13, 17); - this.Slot0StatusButton.Text = "0"; - this.Slot0StatusButton.ToolTipText = "Save slot 0"; - this.Slot0StatusButton.MouseUp += new System.Windows.Forms.MouseEventHandler(this.SlotStatusButtons_MouseUp); - // - // CheatStatusButton - // - this.CheatStatusButton.Name = "CheatStatusButton"; - this.CheatStatusButton.Size = new System.Drawing.Size(0, 17); - this.CheatStatusButton.Click += new System.EventHandler(this.FreezeStatus_Click); - // - // KeyPriorityStatusLabel - // - this.KeyPriorityStatusLabel.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - this.KeyPriorityStatusLabel.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.Both; - this.KeyPriorityStatusLabel.Margin = new System.Windows.Forms.Padding(5, 3, 5, 0); - this.KeyPriorityStatusLabel.Name = "KeyPriorityStatusLabel"; - this.KeyPriorityStatusLabel.Size = new System.Drawing.Size(16, 19); - this.KeyPriorityStatusLabel.Text = "KeyPriority"; - this.KeyPriorityStatusLabel.Click += new System.EventHandler(this.KeyPriorityStatusLabel_Click); - // - // CoreNameStatusBarButton - // - this.CoreNameStatusBarButton.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.CorpHawkSmall; - this.CoreNameStatusBarButton.Name = "CoreNameStatusBarButton"; - this.CoreNameStatusBarButton.Size = new System.Drawing.Size(66, 17); - this.CoreNameStatusBarButton.Text = "Neshawk"; - // - // ProfileFirstBootLabel - // - this.ProfileFirstBootLabel.AutoToolTip = true; - this.ProfileFirstBootLabel.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - this.ProfileFirstBootLabel.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.user_blue_small; - this.ProfileFirstBootLabel.Name = "ProfileFirstBootLabel"; - this.ProfileFirstBootLabel.Size = new System.Drawing.Size(16, 17); - this.ProfileFirstBootLabel.Text = "ProfileFirstBootLabel"; - this.ProfileFirstBootLabel.ToolTipText = "Set up your profile before use"; - this.ProfileFirstBootLabel.Visible = false; - this.ProfileFirstBootLabel.Click += new System.EventHandler(this.ProfileFirstBootLabel_Click); - // - // LinkConnectStatusBarButton - // - this.LinkConnectStatusBarButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - this.LinkConnectStatusBarButton.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.connect_16x16; - this.LinkConnectStatusBarButton.Name = "LinkConnectStatusBarButton"; - this.LinkConnectStatusBarButton.Size = new System.Drawing.Size(16, 17); - this.LinkConnectStatusBarButton.Text = "Link connection is currently enabled"; - this.LinkConnectStatusBarButton.ToolTipText = "Link connection is currently enabled"; - // - // UpdateNotification - // - this.UpdateNotification.IsLink = true; - this.UpdateNotification.LinkColor = System.Drawing.Color.Red; - this.UpdateNotification.Name = "UpdateNotification"; - this.UpdateNotification.Size = new System.Drawing.Size(53, 17); - this.UpdateNotification.Spring = true; - this.UpdateNotification.Text = "New version available!"; - this.UpdateNotification.TextAlign = System.Drawing.ContentAlignment.MiddleRight; - this.UpdateNotification.Click += new System.EventHandler(this.UpdateNotification_Click); - // - // MainFormContextMenu - // - this.MainFormContextMenu.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.MainStatusBar.Location = new System.Drawing.Point(0, 386); + this.MainStatusBar.Name = "MainStatusBar"; + this.MainStatusBar.ShowItemToolTips = true; + this.MainStatusBar.Size = new System.Drawing.Size(470, 22); + this.MainStatusBar.SizingGrip = false; + this.MainStatusBar.TabIndex = 1; + this.MainStatusBar.Text = "0"; + // + // DumpStatusButton + // + this.DumpStatusButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.DumpStatusButton.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.Blank; + this.DumpStatusButton.ImageTransparentColor = System.Drawing.Color.Magenta; + this.DumpStatusButton.Name = "DumpStatusButton"; + this.DumpStatusButton.ShowDropDownArrow = false; + this.DumpStatusButton.Size = new System.Drawing.Size(20, 20); + this.DumpStatusButton.Text = "No ROM loaded"; + this.DumpStatusButton.Click += new System.EventHandler(this.DumpStatusButton_Click); + // + // EmuStatus + // + this.EmuStatus.Name = "EmuStatus"; + this.EmuStatus.Size = new System.Drawing.Size(0, 17); + // + // PlayRecordStatusButton + // + this.PlayRecordStatusButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.PlayRecordStatusButton.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.Blank; + this.PlayRecordStatusButton.ImageTransparentColor = System.Drawing.Color.Magenta; + this.PlayRecordStatusButton.Name = "PlayRecordStatusButton"; + this.PlayRecordStatusButton.ShowDropDownArrow = false; + this.PlayRecordStatusButton.Size = new System.Drawing.Size(20, 20); + this.PlayRecordStatusButton.Text = "No movie is active"; + // + // PauseStatusButton + // + this.PauseStatusButton.Alignment = System.Windows.Forms.ToolStripItemAlignment.Right; + this.PauseStatusButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.PauseStatusButton.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.Blank; + this.PauseStatusButton.ImageTransparentColor = System.Drawing.Color.Magenta; + this.PauseStatusButton.Name = "PauseStatusButton"; + this.PauseStatusButton.ShowDropDownArrow = false; + this.PauseStatusButton.Size = new System.Drawing.Size(20, 20); + this.PauseStatusButton.Text = "toolStripDropDownButton1"; + this.PauseStatusButton.ToolTipText = "Emulator is paused"; + this.PauseStatusButton.Click += new System.EventHandler(this.PauseMenuItem_Click); + // + // RebootStatusBarIcon + // + this.RebootStatusBarIcon.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.RebootStatusBarIcon.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.reboot; + this.RebootStatusBarIcon.Name = "RebootStatusBarIcon"; + this.RebootStatusBarIcon.RightToLeft = System.Windows.Forms.RightToLeft.No; + this.RebootStatusBarIcon.Size = new System.Drawing.Size(16, 17); + this.RebootStatusBarIcon.Text = "Reboot"; + this.RebootStatusBarIcon.ToolTipText = "A reboot of the core is needed for a setting change to take effect"; + this.RebootStatusBarIcon.Click += new System.EventHandler(this.PowerMenuItem_Click); + // + // AVIStatusLabel + // + this.AVIStatusLabel.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.AVIStatusLabel.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.Blank; + this.AVIStatusLabel.Name = "AVIStatusLabel"; + this.AVIStatusLabel.Size = new System.Drawing.Size(16, 17); + this.AVIStatusLabel.Text = "AVI Capture"; + // + // LedLightStatusLabel + // + this.LedLightStatusLabel.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.LightOff; + this.LedLightStatusLabel.Name = "LedLightStatusLabel"; + this.LedLightStatusLabel.Size = new System.Drawing.Size(16, 17); + this.LedLightStatusLabel.ToolTipText = "Disk Drive LED Light"; + // + // SaveSlotsStatusLabel + // + this.SaveSlotsStatusLabel.BackColor = System.Drawing.SystemColors.Control; + this.SaveSlotsStatusLabel.Name = "SaveSlotsStatusLabel"; + this.SaveSlotsStatusLabel.Size = new System.Drawing.Size(58, 17); + this.SaveSlotsStatusLabel.Text = "Save slots"; + // + // Slot1StatusButton + // + this.Slot1StatusButton.Name = "Slot1StatusButton"; + this.Slot1StatusButton.Size = new System.Drawing.Size(13, 17); + this.Slot1StatusButton.Text = "1"; + this.Slot1StatusButton.ToolTipText = "Save slot 1"; + this.Slot1StatusButton.MouseUp += new System.Windows.Forms.MouseEventHandler(this.SlotStatusButtons_MouseUp); + // + // Slot2StatusButton + // + this.Slot2StatusButton.Name = "Slot2StatusButton"; + this.Slot2StatusButton.Size = new System.Drawing.Size(13, 17); + this.Slot2StatusButton.Text = "2"; + this.Slot2StatusButton.ToolTipText = "Save slot 2"; + this.Slot2StatusButton.MouseUp += new System.Windows.Forms.MouseEventHandler(this.SlotStatusButtons_MouseUp); + // + // Slot3StatusButton + // + this.Slot3StatusButton.Name = "Slot3StatusButton"; + this.Slot3StatusButton.Size = new System.Drawing.Size(13, 17); + this.Slot3StatusButton.Text = "3"; + this.Slot3StatusButton.ToolTipText = "Save slot 3"; + this.Slot3StatusButton.MouseUp += new System.Windows.Forms.MouseEventHandler(this.SlotStatusButtons_MouseUp); + // + // Slot4StatusButton + // + this.Slot4StatusButton.Name = "Slot4StatusButton"; + this.Slot4StatusButton.Size = new System.Drawing.Size(13, 17); + this.Slot4StatusButton.Text = "4"; + this.Slot4StatusButton.ToolTipText = "Save slot 4"; + this.Slot4StatusButton.MouseUp += new System.Windows.Forms.MouseEventHandler(this.SlotStatusButtons_MouseUp); + // + // Slot5StatusButton + // + this.Slot5StatusButton.Name = "Slot5StatusButton"; + this.Slot5StatusButton.Size = new System.Drawing.Size(13, 17); + this.Slot5StatusButton.Text = "5"; + this.Slot5StatusButton.ToolTipText = "Save slot 5"; + this.Slot5StatusButton.MouseUp += new System.Windows.Forms.MouseEventHandler(this.SlotStatusButtons_MouseUp); + // + // Slot6StatusButton + // + this.Slot6StatusButton.Name = "Slot6StatusButton"; + this.Slot6StatusButton.Size = new System.Drawing.Size(13, 17); + this.Slot6StatusButton.Text = "6"; + this.Slot6StatusButton.ToolTipText = "Save slot 6"; + this.Slot6StatusButton.MouseUp += new System.Windows.Forms.MouseEventHandler(this.SlotStatusButtons_MouseUp); + // + // Slot7StatusButton + // + this.Slot7StatusButton.Name = "Slot7StatusButton"; + this.Slot7StatusButton.Size = new System.Drawing.Size(13, 17); + this.Slot7StatusButton.Text = "7"; + this.Slot7StatusButton.ToolTipText = "Save slot 7"; + this.Slot7StatusButton.MouseUp += new System.Windows.Forms.MouseEventHandler(this.SlotStatusButtons_MouseUp); + // + // Slot8StatusButton + // + this.Slot8StatusButton.Name = "Slot8StatusButton"; + this.Slot8StatusButton.Size = new System.Drawing.Size(13, 17); + this.Slot8StatusButton.Text = "8"; + this.Slot8StatusButton.ToolTipText = "Save slot 8"; + this.Slot8StatusButton.MouseUp += new System.Windows.Forms.MouseEventHandler(this.SlotStatusButtons_MouseUp); + // + // Slot9StatusButton + // + this.Slot9StatusButton.Name = "Slot9StatusButton"; + this.Slot9StatusButton.Size = new System.Drawing.Size(13, 17); + this.Slot9StatusButton.Text = "9"; + this.Slot9StatusButton.ToolTipText = "Save slot 9"; + this.Slot9StatusButton.MouseUp += new System.Windows.Forms.MouseEventHandler(this.SlotStatusButtons_MouseUp); + // + // Slot0StatusButton + // + this.Slot0StatusButton.Name = "Slot0StatusButton"; + this.Slot0StatusButton.Size = new System.Drawing.Size(13, 17); + this.Slot0StatusButton.Text = "0"; + this.Slot0StatusButton.ToolTipText = "Save slot 0"; + this.Slot0StatusButton.MouseUp += new System.Windows.Forms.MouseEventHandler(this.SlotStatusButtons_MouseUp); + // + // CheatStatusButton + // + this.CheatStatusButton.Name = "CheatStatusButton"; + this.CheatStatusButton.Size = new System.Drawing.Size(0, 17); + this.CheatStatusButton.Click += new System.EventHandler(this.FreezeStatus_Click); + // + // KeyPriorityStatusLabel + // + this.KeyPriorityStatusLabel.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.KeyPriorityStatusLabel.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.Both; + this.KeyPriorityStatusLabel.Margin = new System.Windows.Forms.Padding(5, 3, 5, 0); + this.KeyPriorityStatusLabel.Name = "KeyPriorityStatusLabel"; + this.KeyPriorityStatusLabel.Size = new System.Drawing.Size(16, 19); + this.KeyPriorityStatusLabel.Text = "KeyPriority"; + this.KeyPriorityStatusLabel.Click += new System.EventHandler(this.KeyPriorityStatusLabel_Click); + // + // CoreNameStatusBarButton + // + this.CoreNameStatusBarButton.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.CorpHawkSmall; + this.CoreNameStatusBarButton.Name = "CoreNameStatusBarButton"; + this.CoreNameStatusBarButton.Size = new System.Drawing.Size(71, 17); + this.CoreNameStatusBarButton.Text = "Neshawk"; + // + // ProfileFirstBootLabel + // + this.ProfileFirstBootLabel.AutoToolTip = true; + this.ProfileFirstBootLabel.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.ProfileFirstBootLabel.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.user_blue_small; + this.ProfileFirstBootLabel.Name = "ProfileFirstBootLabel"; + this.ProfileFirstBootLabel.Size = new System.Drawing.Size(16, 17); + this.ProfileFirstBootLabel.Text = "ProfileFirstBootLabel"; + this.ProfileFirstBootLabel.ToolTipText = "Set up your profile before use"; + this.ProfileFirstBootLabel.Visible = false; + this.ProfileFirstBootLabel.Click += new System.EventHandler(this.ProfileFirstBootLabel_Click); + // + // LinkConnectStatusBarButton + // + this.LinkConnectStatusBarButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.LinkConnectStatusBarButton.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.connect_16x16; + this.LinkConnectStatusBarButton.Name = "LinkConnectStatusBarButton"; + this.LinkConnectStatusBarButton.Size = new System.Drawing.Size(16, 17); + this.LinkConnectStatusBarButton.Text = "Link connection is currently enabled"; + this.LinkConnectStatusBarButton.ToolTipText = "Link connection is currently enabled"; + // + // UpdateNotification + // + this.UpdateNotification.IsLink = true; + this.UpdateNotification.LinkColor = System.Drawing.Color.Red; + this.UpdateNotification.Name = "UpdateNotification"; + this.UpdateNotification.Size = new System.Drawing.Size(46, 17); + this.UpdateNotification.Spring = true; + this.UpdateNotification.Text = "New version available!"; + this.UpdateNotification.TextAlign = System.Drawing.ContentAlignment.MiddleRight; + this.UpdateNotification.Click += new System.EventHandler(this.UpdateNotification_Click); + // + // MainFormContextMenu + // + this.MainFormContextMenu.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { this.OpenRomContextMenuItem, this.LoadLastRomContextMenuItem, this.StopAVContextMenuItem, @@ -3554,153 +3569,153 @@ this.ClearSRAMContextMenuItem, this.ShowMenuContextMenuSeparator, this.ShowMenuContextMenuItem}); - this.MainFormContextMenu.Name = "contextMenuStrip1"; - this.MainFormContextMenu.Size = new System.Drawing.Size(202, 490); - this.MainFormContextMenu.Closing += new System.Windows.Forms.ToolStripDropDownClosingEventHandler(this.MainFormContextMenu_Closing); - this.MainFormContextMenu.Opening += new System.ComponentModel.CancelEventHandler(this.MainFormContextMenu_Opening); - // - // OpenRomContextMenuItem - // - this.OpenRomContextMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.OpenFile; - this.OpenRomContextMenuItem.Name = "OpenRomContextMenuItem"; - this.OpenRomContextMenuItem.Size = new System.Drawing.Size(201, 22); - this.OpenRomContextMenuItem.Text = "Open Rom"; - this.OpenRomContextMenuItem.Click += new System.EventHandler(this.OpenRomMenuItem_Click); - // - // LoadLastRomContextMenuItem - // - this.LoadLastRomContextMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.Recent; - this.LoadLastRomContextMenuItem.Name = "LoadLastRomContextMenuItem"; - this.LoadLastRomContextMenuItem.Size = new System.Drawing.Size(201, 22); - this.LoadLastRomContextMenuItem.Text = "Load Last ROM"; - this.LoadLastRomContextMenuItem.Click += new System.EventHandler(this.LoadLastRomContextMenuItem_Click); - // - // StopAVContextMenuItem - // - this.StopAVContextMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.Stop; - this.StopAVContextMenuItem.Name = "StopAVContextMenuItem"; - this.StopAVContextMenuItem.Size = new System.Drawing.Size(201, 22); - this.StopAVContextMenuItem.Text = "Stop AVI/WAV"; - this.StopAVContextMenuItem.Click += new System.EventHandler(this.StopAVMenuItem_Click); - // - // ContextSeparator_AfterROM - // - this.ContextSeparator_AfterROM.Name = "ContextSeparator_AfterROM"; - this.ContextSeparator_AfterROM.Size = new System.Drawing.Size(198, 6); - // - // RecordMovieContextMenuItem - // - this.RecordMovieContextMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.RecordHS; - this.RecordMovieContextMenuItem.Name = "RecordMovieContextMenuItem"; - this.RecordMovieContextMenuItem.Size = new System.Drawing.Size(201, 22); - this.RecordMovieContextMenuItem.Text = "Record Movie"; - this.RecordMovieContextMenuItem.Click += new System.EventHandler(this.RecordMovieMenuItem_Click); - // - // PlayMovieContextMenuItem - // - this.PlayMovieContextMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.Play; - this.PlayMovieContextMenuItem.Name = "PlayMovieContextMenuItem"; - this.PlayMovieContextMenuItem.Size = new System.Drawing.Size(201, 22); - this.PlayMovieContextMenuItem.Text = "Play Movie"; - this.PlayMovieContextMenuItem.Click += new System.EventHandler(this.PlayMovieMenuItem_Click); - // - // RestartMovieContextMenuItem - // - this.RestartMovieContextMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.restart; - this.RestartMovieContextMenuItem.Name = "RestartMovieContextMenuItem"; - this.RestartMovieContextMenuItem.Size = new System.Drawing.Size(201, 22); - this.RestartMovieContextMenuItem.Text = "Restart Movie"; - this.RestartMovieContextMenuItem.Click += new System.EventHandler(this.PlayFromBeginningMenuItem_Click); - // - // StopMovieContextMenuItem - // - this.StopMovieContextMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.Stop; - this.StopMovieContextMenuItem.Name = "StopMovieContextMenuItem"; - this.StopMovieContextMenuItem.Size = new System.Drawing.Size(201, 22); - this.StopMovieContextMenuItem.Text = "Stop Movie"; - this.StopMovieContextMenuItem.Click += new System.EventHandler(this.StopMovieMenuItem_Click); - // - // LoadLastMovieContextMenuItem - // - this.LoadLastMovieContextMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.Recent; - this.LoadLastMovieContextMenuItem.Name = "LoadLastMovieContextMenuItem"; - this.LoadLastMovieContextMenuItem.Size = new System.Drawing.Size(201, 22); - this.LoadLastMovieContextMenuItem.Text = "Load Last Movie"; - this.LoadLastMovieContextMenuItem.Click += new System.EventHandler(this.LoadLastMovieContextMenuItem_Click); - // - // BackupMovieContextMenuItem - // - this.BackupMovieContextMenuItem.Name = "BackupMovieContextMenuItem"; - this.BackupMovieContextMenuItem.Size = new System.Drawing.Size(201, 22); - this.BackupMovieContextMenuItem.Text = "Backup Movie"; - this.BackupMovieContextMenuItem.Click += new System.EventHandler(this.BackupMovieContextMenuItem_Click); - // - // StopNoSaveContextMenuItem - // - this.StopNoSaveContextMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.Stop; - this.StopNoSaveContextMenuItem.Name = "StopNoSaveContextMenuItem"; - this.StopNoSaveContextMenuItem.Size = new System.Drawing.Size(201, 22); - this.StopNoSaveContextMenuItem.Text = "Stop Movie without Saving"; - this.StopNoSaveContextMenuItem.Click += new System.EventHandler(this.StopMovieWithoutSavingMenuItem_Click); - // - // ViewSubtitlesContextMenuItem - // - this.ViewSubtitlesContextMenuItem.Name = "ViewSubtitlesContextMenuItem"; - this.ViewSubtitlesContextMenuItem.Size = new System.Drawing.Size(201, 22); - this.ViewSubtitlesContextMenuItem.Text = "View Subtitles"; - this.ViewSubtitlesContextMenuItem.Click += new System.EventHandler(this.ViewSubtitlesContextMenuItem_Click); - // - // AddSubtitleContextMenuItem - // - this.AddSubtitleContextMenuItem.Name = "AddSubtitleContextMenuItem"; - this.AddSubtitleContextMenuItem.Size = new System.Drawing.Size(201, 22); - this.AddSubtitleContextMenuItem.Text = "Add Subtitle"; - this.AddSubtitleContextMenuItem.Click += new System.EventHandler(this.AddSubtitleContextMenuItem_Click); - // - // ViewCommentsContextMenuItem - // - this.ViewCommentsContextMenuItem.Name = "ViewCommentsContextMenuItem"; - this.ViewCommentsContextMenuItem.Size = new System.Drawing.Size(201, 22); - this.ViewCommentsContextMenuItem.Text = "View Comments"; - this.ViewCommentsContextMenuItem.Click += new System.EventHandler(this.ViewCommentsContextMenuItem_Click); - // - // SaveMovieContextMenuItem - // - this.SaveMovieContextMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.SaveAs; - this.SaveMovieContextMenuItem.Name = "SaveMovieContextMenuItem"; - this.SaveMovieContextMenuItem.Size = new System.Drawing.Size(201, 22); - this.SaveMovieContextMenuItem.Text = "Save Movie"; - this.SaveMovieContextMenuItem.Click += new System.EventHandler(this.SaveMovieMenuItem_Click); - // - // SaveMovieAsContextMenuItem - // - this.SaveMovieAsContextMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.SaveAs; - this.SaveMovieAsContextMenuItem.Name = "SaveMovieAsContextMenuItem"; - this.SaveMovieAsContextMenuItem.Size = new System.Drawing.Size(201, 22); - this.SaveMovieAsContextMenuItem.Text = "Save Movie As..."; - this.SaveMovieAsContextMenuItem.Click += new System.EventHandler(this.SaveMovieAsMenuItem_Click); - // - // ContextSeparator_AfterMovie - // - this.ContextSeparator_AfterMovie.Name = "ContextSeparator_AfterMovie"; - this.ContextSeparator_AfterMovie.Size = new System.Drawing.Size(198, 6); - // - // UndoSavestateContextMenuItem - // - this.UndoSavestateContextMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.undo; - this.UndoSavestateContextMenuItem.Name = "UndoSavestateContextMenuItem"; - this.UndoSavestateContextMenuItem.Size = new System.Drawing.Size(201, 22); - this.UndoSavestateContextMenuItem.Text = "Undo Savestate"; - this.UndoSavestateContextMenuItem.Click += new System.EventHandler(this.UndoSavestateContextMenuItem_Click); - // - // ContextSeparator_AfterUndo - // - this.ContextSeparator_AfterUndo.Name = "ContextSeparator_AfterUndo"; - this.ContextSeparator_AfterUndo.Size = new System.Drawing.Size(198, 6); - // - // ConfigContextMenuItem - // - this.ConfigContextMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.MainFormContextMenu.Name = "contextMenuStrip1"; + this.MainFormContextMenu.Size = new System.Drawing.Size(217, 490); + this.MainFormContextMenu.Closing += new System.Windows.Forms.ToolStripDropDownClosingEventHandler(this.MainFormContextMenu_Closing); + this.MainFormContextMenu.Opening += new System.ComponentModel.CancelEventHandler(this.MainFormContextMenu_Opening); + // + // OpenRomContextMenuItem + // + this.OpenRomContextMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.OpenFile; + this.OpenRomContextMenuItem.Name = "OpenRomContextMenuItem"; + this.OpenRomContextMenuItem.Size = new System.Drawing.Size(216, 22); + this.OpenRomContextMenuItem.Text = "Open Rom"; + this.OpenRomContextMenuItem.Click += new System.EventHandler(this.OpenRomMenuItem_Click); + // + // LoadLastRomContextMenuItem + // + this.LoadLastRomContextMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.Recent; + this.LoadLastRomContextMenuItem.Name = "LoadLastRomContextMenuItem"; + this.LoadLastRomContextMenuItem.Size = new System.Drawing.Size(216, 22); + this.LoadLastRomContextMenuItem.Text = "Load Last ROM"; + this.LoadLastRomContextMenuItem.Click += new System.EventHandler(this.LoadLastRomContextMenuItem_Click); + // + // StopAVContextMenuItem + // + this.StopAVContextMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.Stop; + this.StopAVContextMenuItem.Name = "StopAVContextMenuItem"; + this.StopAVContextMenuItem.Size = new System.Drawing.Size(216, 22); + this.StopAVContextMenuItem.Text = "Stop AVI/WAV"; + this.StopAVContextMenuItem.Click += new System.EventHandler(this.StopAVMenuItem_Click); + // + // ContextSeparator_AfterROM + // + this.ContextSeparator_AfterROM.Name = "ContextSeparator_AfterROM"; + this.ContextSeparator_AfterROM.Size = new System.Drawing.Size(213, 6); + // + // RecordMovieContextMenuItem + // + this.RecordMovieContextMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.RecordHS; + this.RecordMovieContextMenuItem.Name = "RecordMovieContextMenuItem"; + this.RecordMovieContextMenuItem.Size = new System.Drawing.Size(216, 22); + this.RecordMovieContextMenuItem.Text = "Record Movie"; + this.RecordMovieContextMenuItem.Click += new System.EventHandler(this.RecordMovieMenuItem_Click); + // + // PlayMovieContextMenuItem + // + this.PlayMovieContextMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.Play; + this.PlayMovieContextMenuItem.Name = "PlayMovieContextMenuItem"; + this.PlayMovieContextMenuItem.Size = new System.Drawing.Size(216, 22); + this.PlayMovieContextMenuItem.Text = "Play Movie"; + this.PlayMovieContextMenuItem.Click += new System.EventHandler(this.PlayMovieMenuItem_Click); + // + // RestartMovieContextMenuItem + // + this.RestartMovieContextMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.restart; + this.RestartMovieContextMenuItem.Name = "RestartMovieContextMenuItem"; + this.RestartMovieContextMenuItem.Size = new System.Drawing.Size(216, 22); + this.RestartMovieContextMenuItem.Text = "Restart Movie"; + this.RestartMovieContextMenuItem.Click += new System.EventHandler(this.PlayFromBeginningMenuItem_Click); + // + // StopMovieContextMenuItem + // + this.StopMovieContextMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.Stop; + this.StopMovieContextMenuItem.Name = "StopMovieContextMenuItem"; + this.StopMovieContextMenuItem.Size = new System.Drawing.Size(216, 22); + this.StopMovieContextMenuItem.Text = "Stop Movie"; + this.StopMovieContextMenuItem.Click += new System.EventHandler(this.StopMovieMenuItem_Click); + // + // LoadLastMovieContextMenuItem + // + this.LoadLastMovieContextMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.Recent; + this.LoadLastMovieContextMenuItem.Name = "LoadLastMovieContextMenuItem"; + this.LoadLastMovieContextMenuItem.Size = new System.Drawing.Size(216, 22); + this.LoadLastMovieContextMenuItem.Text = "Load Last Movie"; + this.LoadLastMovieContextMenuItem.Click += new System.EventHandler(this.LoadLastMovieContextMenuItem_Click); + // + // BackupMovieContextMenuItem + // + this.BackupMovieContextMenuItem.Name = "BackupMovieContextMenuItem"; + this.BackupMovieContextMenuItem.Size = new System.Drawing.Size(216, 22); + this.BackupMovieContextMenuItem.Text = "Backup Movie"; + this.BackupMovieContextMenuItem.Click += new System.EventHandler(this.BackupMovieContextMenuItem_Click); + // + // StopNoSaveContextMenuItem + // + this.StopNoSaveContextMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.Stop; + this.StopNoSaveContextMenuItem.Name = "StopNoSaveContextMenuItem"; + this.StopNoSaveContextMenuItem.Size = new System.Drawing.Size(216, 22); + this.StopNoSaveContextMenuItem.Text = "Stop Movie without Saving"; + this.StopNoSaveContextMenuItem.Click += new System.EventHandler(this.StopMovieWithoutSavingMenuItem_Click); + // + // ViewSubtitlesContextMenuItem + // + this.ViewSubtitlesContextMenuItem.Name = "ViewSubtitlesContextMenuItem"; + this.ViewSubtitlesContextMenuItem.Size = new System.Drawing.Size(216, 22); + this.ViewSubtitlesContextMenuItem.Text = "View Subtitles"; + this.ViewSubtitlesContextMenuItem.Click += new System.EventHandler(this.ViewSubtitlesContextMenuItem_Click); + // + // AddSubtitleContextMenuItem + // + this.AddSubtitleContextMenuItem.Name = "AddSubtitleContextMenuItem"; + this.AddSubtitleContextMenuItem.Size = new System.Drawing.Size(216, 22); + this.AddSubtitleContextMenuItem.Text = "Add Subtitle"; + this.AddSubtitleContextMenuItem.Click += new System.EventHandler(this.AddSubtitleContextMenuItem_Click); + // + // ViewCommentsContextMenuItem + // + this.ViewCommentsContextMenuItem.Name = "ViewCommentsContextMenuItem"; + this.ViewCommentsContextMenuItem.Size = new System.Drawing.Size(216, 22); + this.ViewCommentsContextMenuItem.Text = "View Comments"; + this.ViewCommentsContextMenuItem.Click += new System.EventHandler(this.ViewCommentsContextMenuItem_Click); + // + // SaveMovieContextMenuItem + // + this.SaveMovieContextMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.SaveAs; + this.SaveMovieContextMenuItem.Name = "SaveMovieContextMenuItem"; + this.SaveMovieContextMenuItem.Size = new System.Drawing.Size(216, 22); + this.SaveMovieContextMenuItem.Text = "Save Movie"; + this.SaveMovieContextMenuItem.Click += new System.EventHandler(this.SaveMovieMenuItem_Click); + // + // SaveMovieAsContextMenuItem + // + this.SaveMovieAsContextMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.SaveAs; + this.SaveMovieAsContextMenuItem.Name = "SaveMovieAsContextMenuItem"; + this.SaveMovieAsContextMenuItem.Size = new System.Drawing.Size(216, 22); + this.SaveMovieAsContextMenuItem.Text = "Save Movie As..."; + this.SaveMovieAsContextMenuItem.Click += new System.EventHandler(this.SaveMovieAsMenuItem_Click); + // + // ContextSeparator_AfterMovie + // + this.ContextSeparator_AfterMovie.Name = "ContextSeparator_AfterMovie"; + this.ContextSeparator_AfterMovie.Size = new System.Drawing.Size(213, 6); + // + // UndoSavestateContextMenuItem + // + this.UndoSavestateContextMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.undo; + this.UndoSavestateContextMenuItem.Name = "UndoSavestateContextMenuItem"; + this.UndoSavestateContextMenuItem.Size = new System.Drawing.Size(216, 22); + this.UndoSavestateContextMenuItem.Text = "Undo Savestate"; + this.UndoSavestateContextMenuItem.Click += new System.EventHandler(this.UndoSavestateContextMenuItem_Click); + // + // ContextSeparator_AfterUndo + // + this.ContextSeparator_AfterUndo.Name = "ContextSeparator_AfterUndo"; + this.ContextSeparator_AfterUndo.Size = new System.Drawing.Size(213, 6); + // + // ConfigContextMenuItem + // + this.ConfigContextMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.toolStripMenuItem6, this.toolStripMenuItem7, this.toolStripMenuItem8, @@ -3717,232 +3732,217 @@ this.toolStripSeparator37, this.toolStripMenuItem66, this.toolStripMenuItem67}); - this.ConfigContextMenuItem.Name = "ConfigContextMenuItem"; - this.ConfigContextMenuItem.Size = new System.Drawing.Size(201, 22); - this.ConfigContextMenuItem.Text = "Config"; - // - // toolStripMenuItem6 - // - this.toolStripMenuItem6.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.GameController; - this.toolStripMenuItem6.Name = "toolStripMenuItem6"; - this.toolStripMenuItem6.Size = new System.Drawing.Size(157, 22); - this.toolStripMenuItem6.Text = "&Controllers..."; - this.toolStripMenuItem6.Click += new System.EventHandler(this.ControllersMenuItem_Click); - // - // toolStripMenuItem7 - // - this.toolStripMenuItem7.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.HotKeys; - this.toolStripMenuItem7.Name = "toolStripMenuItem7"; - this.toolStripMenuItem7.Size = new System.Drawing.Size(157, 22); - this.toolStripMenuItem7.Text = "&Hotkeys..."; - this.toolStripMenuItem7.Click += new System.EventHandler(this.HotkeysMenuItem_Click); - // - // toolStripMenuItem8 - // - this.toolStripMenuItem8.Image = ((System.Drawing.Image)(resources.GetObject("toolStripMenuItem8.Image"))); - this.toolStripMenuItem8.Name = "toolStripMenuItem8"; - this.toolStripMenuItem8.Size = new System.Drawing.Size(157, 22); - this.toolStripMenuItem8.Text = "Display..."; - this.toolStripMenuItem8.Click += new System.EventHandler(this.DisplayConfigMenuItem_Click); - // - // toolStripMenuItem9 - // - this.toolStripMenuItem9.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.AudioHS; - this.toolStripMenuItem9.Name = "toolStripMenuItem9"; - this.toolStripMenuItem9.Size = new System.Drawing.Size(157, 22); - this.toolStripMenuItem9.Text = "&Sound..."; - this.toolStripMenuItem9.Click += new System.EventHandler(this.SoundMenuItem_Click); - // - // toolStripMenuItem10 - // - this.toolStripMenuItem10.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.CopyFolderHS; - this.toolStripMenuItem10.Name = "toolStripMenuItem10"; - this.toolStripMenuItem10.Size = new System.Drawing.Size(157, 22); - this.toolStripMenuItem10.Text = "Paths..."; - this.toolStripMenuItem10.Click += new System.EventHandler(this.PathsMenuItem_Click); - // - // toolStripMenuItem11 - // - this.toolStripMenuItem11.Image = ((System.Drawing.Image)(resources.GetObject("toolStripMenuItem11.Image"))); - this.toolStripMenuItem11.Name = "toolStripMenuItem11"; - this.toolStripMenuItem11.Size = new System.Drawing.Size(157, 22); - this.toolStripMenuItem11.Text = "&Firmwares..."; - this.toolStripMenuItem11.Click += new System.EventHandler(this.FirmwaresMenuItem_Click); - // - // toolStripMenuItem12 - // - this.toolStripMenuItem12.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.MessageConfig; - this.toolStripMenuItem12.Name = "toolStripMenuItem12"; - this.toolStripMenuItem12.Size = new System.Drawing.Size(157, 22); - this.toolStripMenuItem12.Text = "&Messages..."; - this.toolStripMenuItem12.Click += new System.EventHandler(this.MessagesMenuItem_Click); - // - // toolStripMenuItem13 - // - this.toolStripMenuItem13.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.Lightning; - this.toolStripMenuItem13.Name = "toolStripMenuItem13"; - this.toolStripMenuItem13.Size = new System.Drawing.Size(157, 22); - this.toolStripMenuItem13.Text = "&Autofire..."; - this.toolStripMenuItem13.Click += new System.EventHandler(this.AutofireMenuItem_Click); - // - // toolStripMenuItem14 - // - this.toolStripMenuItem14.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.Previous; - this.toolStripMenuItem14.Name = "toolStripMenuItem14"; - this.toolStripMenuItem14.Size = new System.Drawing.Size(157, 22); - this.toolStripMenuItem14.Text = "&Rewind..."; - this.toolStripMenuItem14.Click += new System.EventHandler(this.RewindOptionsMenuItem_Click); - // - // toolStripMenuItem15 - // - this.toolStripMenuItem15.Name = "toolStripMenuItem15"; - this.toolStripMenuItem15.Size = new System.Drawing.Size(157, 22); - this.toolStripMenuItem15.Text = "File Extensions..."; - this.toolStripMenuItem15.Click += new System.EventHandler(this.FileExtensionsMenuItem_Click); - // - // customizeToolStripMenuItem - // - this.customizeToolStripMenuItem.Name = "customizeToolStripMenuItem"; - this.customizeToolStripMenuItem.Size = new System.Drawing.Size(157, 22); - this.customizeToolStripMenuItem.Text = "Customize..."; - this.customizeToolStripMenuItem.Click += new System.EventHandler(this.CustomizeMenuItem_Click); - // - // toolStripSeparator30 - // - this.toolStripSeparator30.Name = "toolStripSeparator30"; - this.toolStripSeparator30.Size = new System.Drawing.Size(154, 6); - // - // SavestateTypeContextSubMenu - // - this.SavestateTypeContextSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.ConfigContextMenuItem.Name = "ConfigContextMenuItem"; + this.ConfigContextMenuItem.Size = new System.Drawing.Size(216, 22); + this.ConfigContextMenuItem.Text = "Config"; + // + // toolStripMenuItem6 + // + this.toolStripMenuItem6.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.GameController; + this.toolStripMenuItem6.Name = "toolStripMenuItem6"; + this.toolStripMenuItem6.Size = new System.Drawing.Size(159, 22); + this.toolStripMenuItem6.Text = "&Controllers..."; + this.toolStripMenuItem6.Click += new System.EventHandler(this.ControllersMenuItem_Click); + // + // toolStripMenuItem7 + // + this.toolStripMenuItem7.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.HotKeys; + this.toolStripMenuItem7.Name = "toolStripMenuItem7"; + this.toolStripMenuItem7.Size = new System.Drawing.Size(159, 22); + this.toolStripMenuItem7.Text = "&Hotkeys..."; + this.toolStripMenuItem7.Click += new System.EventHandler(this.HotkeysMenuItem_Click); + // + // toolStripMenuItem8 + // + this.toolStripMenuItem8.Image = ((System.Drawing.Image)(resources.GetObject("toolStripMenuItem8.Image"))); + this.toolStripMenuItem8.Name = "toolStripMenuItem8"; + this.toolStripMenuItem8.Size = new System.Drawing.Size(159, 22); + this.toolStripMenuItem8.Text = "Display..."; + this.toolStripMenuItem8.Click += new System.EventHandler(this.DisplayConfigMenuItem_Click); + // + // toolStripMenuItem9 + // + this.toolStripMenuItem9.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.AudioHS; + this.toolStripMenuItem9.Name = "toolStripMenuItem9"; + this.toolStripMenuItem9.Size = new System.Drawing.Size(159, 22); + this.toolStripMenuItem9.Text = "&Sound..."; + this.toolStripMenuItem9.Click += new System.EventHandler(this.SoundMenuItem_Click); + // + // toolStripMenuItem10 + // + this.toolStripMenuItem10.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.CopyFolderHS; + this.toolStripMenuItem10.Name = "toolStripMenuItem10"; + this.toolStripMenuItem10.Size = new System.Drawing.Size(159, 22); + this.toolStripMenuItem10.Text = "Paths..."; + this.toolStripMenuItem10.Click += new System.EventHandler(this.PathsMenuItem_Click); + // + // toolStripMenuItem11 + // + this.toolStripMenuItem11.Image = ((System.Drawing.Image)(resources.GetObject("toolStripMenuItem11.Image"))); + this.toolStripMenuItem11.Name = "toolStripMenuItem11"; + this.toolStripMenuItem11.Size = new System.Drawing.Size(159, 22); + this.toolStripMenuItem11.Text = "&Firmwares..."; + this.toolStripMenuItem11.Click += new System.EventHandler(this.FirmwaresMenuItem_Click); + // + // toolStripMenuItem12 + // + this.toolStripMenuItem12.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.MessageConfig; + this.toolStripMenuItem12.Name = "toolStripMenuItem12"; + this.toolStripMenuItem12.Size = new System.Drawing.Size(159, 22); + this.toolStripMenuItem12.Text = "&Messages..."; + this.toolStripMenuItem12.Click += new System.EventHandler(this.MessagesMenuItem_Click); + // + // toolStripMenuItem13 + // + this.toolStripMenuItem13.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.Lightning; + this.toolStripMenuItem13.Name = "toolStripMenuItem13"; + this.toolStripMenuItem13.Size = new System.Drawing.Size(159, 22); + this.toolStripMenuItem13.Text = "&Autofire..."; + this.toolStripMenuItem13.Click += new System.EventHandler(this.AutofireMenuItem_Click); + // + // toolStripMenuItem14 + // + this.toolStripMenuItem14.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.Previous; + this.toolStripMenuItem14.Name = "toolStripMenuItem14"; + this.toolStripMenuItem14.Size = new System.Drawing.Size(159, 22); + this.toolStripMenuItem14.Text = "&Rewind..."; + this.toolStripMenuItem14.Click += new System.EventHandler(this.RewindOptionsMenuItem_Click); + // + // toolStripMenuItem15 + // + this.toolStripMenuItem15.Name = "toolStripMenuItem15"; + this.toolStripMenuItem15.Size = new System.Drawing.Size(159, 22); + this.toolStripMenuItem15.Text = "File Extensions..."; + this.toolStripMenuItem15.Click += new System.EventHandler(this.FileExtensionsMenuItem_Click); + // + // customizeToolStripMenuItem + // + this.customizeToolStripMenuItem.Name = "customizeToolStripMenuItem"; + this.customizeToolStripMenuItem.Size = new System.Drawing.Size(159, 22); + this.customizeToolStripMenuItem.Text = "Customize..."; + this.customizeToolStripMenuItem.Click += new System.EventHandler(this.CustomizeMenuItem_Click); + // + // toolStripSeparator30 + // + this.toolStripSeparator30.Name = "toolStripSeparator30"; + this.toolStripSeparator30.Size = new System.Drawing.Size(156, 6); + // + // SavestateTypeContextSubMenu + // + this.SavestateTypeContextSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.SavestateTypeDefaultContextMenuItem, this.SavestateBinaryContextMenuItem, this.SavestateTextContextMenuItem}); - this.SavestateTypeContextSubMenu.Name = "SavestateTypeContextSubMenu"; - this.SavestateTypeContextSubMenu.Size = new System.Drawing.Size(157, 22); - this.SavestateTypeContextSubMenu.Text = "Savestate Type"; - this.SavestateTypeContextSubMenu.DropDownOpened += new System.EventHandler(this.SavestateTypeContextSubMenu_DropDownOpened); - // - // SavestateTypeDefaultContextMenuItem - // - this.SavestateTypeDefaultContextMenuItem.Name = "SavestateTypeDefaultContextMenuItem"; - this.SavestateTypeDefaultContextMenuItem.Size = new System.Drawing.Size(109, 22); - this.SavestateTypeDefaultContextMenuItem.Text = "&Default"; - // - // SavestateBinaryContextMenuItem - // - this.SavestateBinaryContextMenuItem.Name = "SavestateBinaryContextMenuItem"; - this.SavestateBinaryContextMenuItem.Size = new System.Drawing.Size(109, 22); - this.SavestateBinaryContextMenuItem.Text = "&Binary"; - // - // SavestateTextContextMenuItem - // - this.SavestateTextContextMenuItem.Name = "SavestateTextContextMenuItem"; - this.SavestateTextContextMenuItem.Size = new System.Drawing.Size(109, 22); - this.SavestateTextContextMenuItem.Text = "&Text"; - // - // toolStripSeparator37 - // - this.toolStripSeparator37.Name = "toolStripSeparator37"; - this.toolStripSeparator37.Size = new System.Drawing.Size(154, 6); - // - // toolStripMenuItem66 - // - this.toolStripMenuItem66.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.Save; - this.toolStripMenuItem66.Name = "toolStripMenuItem66"; - this.toolStripMenuItem66.Size = new System.Drawing.Size(157, 22); - this.toolStripMenuItem66.Text = "Save Config"; - this.toolStripMenuItem66.Click += new System.EventHandler(this.SaveConfigMenuItem_Click); - // - // toolStripMenuItem67 - // - this.toolStripMenuItem67.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.LoadConfig; - this.toolStripMenuItem67.Name = "toolStripMenuItem67"; - this.toolStripMenuItem67.Size = new System.Drawing.Size(157, 22); - this.toolStripMenuItem67.Text = "Load Config"; - this.toolStripMenuItem67.Click += new System.EventHandler(this.LoadConfigMenuItem_Click); - // - // ScreenshotContextMenuItem - // - this.ScreenshotContextMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.camera; - this.ScreenshotContextMenuItem.Name = "ScreenshotContextMenuItem"; - this.ScreenshotContextMenuItem.Size = new System.Drawing.Size(201, 22); - this.ScreenshotContextMenuItem.Text = "Screenshot"; - this.ScreenshotContextMenuItem.Click += new System.EventHandler(this.ScreenshotMenuItem_Click); - // - // CloseRomContextMenuItem - // - this.CloseRomContextMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.Close; - this.CloseRomContextMenuItem.Name = "CloseRomContextMenuItem"; - this.CloseRomContextMenuItem.Size = new System.Drawing.Size(201, 22); - this.CloseRomContextMenuItem.Text = "Close ROM"; - this.CloseRomContextMenuItem.Click += new System.EventHandler(this.CloseRomMenuItem_Click); - // - // ClearSRAMContextMenuItem - // - this.ClearSRAMContextMenuItem.Name = "ClearSRAMContextMenuItem"; - this.ClearSRAMContextMenuItem.Size = new System.Drawing.Size(201, 22); - this.ClearSRAMContextMenuItem.Text = "Close and Clear SRAM"; - this.ClearSRAMContextMenuItem.Click += new System.EventHandler(this.ClearSramContextMenuItem_Click); - // - // ShowMenuContextMenuSeparator - // - this.ShowMenuContextMenuSeparator.Name = "ShowMenuContextMenuSeparator"; - this.ShowMenuContextMenuSeparator.Size = new System.Drawing.Size(198, 6); - // - // ShowMenuContextMenuItem - // - this.ShowMenuContextMenuItem.Name = "ShowMenuContextMenuItem"; - this.ShowMenuContextMenuItem.Size = new System.Drawing.Size(201, 22); - this.ShowMenuContextMenuItem.Text = "Show Menu"; - this.ShowMenuContextMenuItem.Click += new System.EventHandler(this.ShowMenuContextMenuItem_Click); - // - // timerMouseIdle - // - this.timerMouseIdle.Enabled = true; - this.timerMouseIdle.Interval = 2000; - this.timerMouseIdle.Tick += new System.EventHandler(this.TimerMouseIdle_Tick); - // - // pCFXToolStripMenuItem - // - this.pCFXToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.preferencesToolStripMenuItem3}); - this.pCFXToolStripMenuItem.Name = "pCFXToolStripMenuItem"; - this.pCFXToolStripMenuItem.Size = new System.Drawing.Size(48, 17); - this.pCFXToolStripMenuItem.Text = "&PC-FX"; - // - // preferencesToolStripMenuItem3 - // - this.preferencesToolStripMenuItem3.Name = "preferencesToolStripMenuItem3"; - this.preferencesToolStripMenuItem3.Size = new System.Drawing.Size(152, 22); - this.preferencesToolStripMenuItem3.Text = "Preferences..."; - this.preferencesToolStripMenuItem3.Click += new System.EventHandler(this.preferencesToolStripMenuItem3_Click); - // - // MainForm - // - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None; - this.ClientSize = new System.Drawing.Size(470, 408); - this.Controls.Add(this.MainStatusBar); - this.Controls.Add(this.MainformMenu); - this.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.MainMenuStrip = this.MainformMenu; - this.Name = "MainForm"; - this.Text = "BizHawk"; - this.Activated += new System.EventHandler(this.MainForm_Activated); - this.Deactivate += new System.EventHandler(this.MainForm_Deactivate); - this.Load += new System.EventHandler(this.MainForm_Load); - this.Shown += new System.EventHandler(this.MainForm_Shown); - this.Enter += new System.EventHandler(this.MainForm_Enter); - this.MouseClick += new System.Windows.Forms.MouseEventHandler(this.MainForm_MouseClick); - this.MouseMove += new System.Windows.Forms.MouseEventHandler(this.MainForm_MouseMove); - this.Resize += new System.EventHandler(this.MainForm_Resize); - this.MainformMenu.ResumeLayout(false); - this.MainformMenu.PerformLayout(); - this.MainStatusBar.ResumeLayout(false); - this.MainStatusBar.PerformLayout(); - this.MainFormContextMenu.ResumeLayout(false); - this.ResumeLayout(false); - this.PerformLayout(); + this.SavestateTypeContextSubMenu.Name = "SavestateTypeContextSubMenu"; + this.SavestateTypeContextSubMenu.Size = new System.Drawing.Size(159, 22); + this.SavestateTypeContextSubMenu.Text = "Savestate Type"; + this.SavestateTypeContextSubMenu.DropDownOpened += new System.EventHandler(this.SavestateTypeContextSubMenu_DropDownOpened); + // + // SavestateTypeDefaultContextMenuItem + // + this.SavestateTypeDefaultContextMenuItem.Name = "SavestateTypeDefaultContextMenuItem"; + this.SavestateTypeDefaultContextMenuItem.Size = new System.Drawing.Size(112, 22); + this.SavestateTypeDefaultContextMenuItem.Text = "&Default"; + // + // SavestateBinaryContextMenuItem + // + this.SavestateBinaryContextMenuItem.Name = "SavestateBinaryContextMenuItem"; + this.SavestateBinaryContextMenuItem.Size = new System.Drawing.Size(112, 22); + this.SavestateBinaryContextMenuItem.Text = "&Binary"; + // + // SavestateTextContextMenuItem + // + this.SavestateTextContextMenuItem.Name = "SavestateTextContextMenuItem"; + this.SavestateTextContextMenuItem.Size = new System.Drawing.Size(112, 22); + this.SavestateTextContextMenuItem.Text = "&Text"; + // + // toolStripSeparator37 + // + this.toolStripSeparator37.Name = "toolStripSeparator37"; + this.toolStripSeparator37.Size = new System.Drawing.Size(156, 6); + // + // toolStripMenuItem66 + // + this.toolStripMenuItem66.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.Save; + this.toolStripMenuItem66.Name = "toolStripMenuItem66"; + this.toolStripMenuItem66.Size = new System.Drawing.Size(159, 22); + this.toolStripMenuItem66.Text = "Save Config"; + this.toolStripMenuItem66.Click += new System.EventHandler(this.SaveConfigMenuItem_Click); + // + // toolStripMenuItem67 + // + this.toolStripMenuItem67.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.LoadConfig; + this.toolStripMenuItem67.Name = "toolStripMenuItem67"; + this.toolStripMenuItem67.Size = new System.Drawing.Size(159, 22); + this.toolStripMenuItem67.Text = "Load Config"; + this.toolStripMenuItem67.Click += new System.EventHandler(this.LoadConfigMenuItem_Click); + // + // ScreenshotContextMenuItem + // + this.ScreenshotContextMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.camera; + this.ScreenshotContextMenuItem.Name = "ScreenshotContextMenuItem"; + this.ScreenshotContextMenuItem.Size = new System.Drawing.Size(216, 22); + this.ScreenshotContextMenuItem.Text = "Screenshot"; + this.ScreenshotContextMenuItem.Click += new System.EventHandler(this.ScreenshotMenuItem_Click); + // + // CloseRomContextMenuItem + // + this.CloseRomContextMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.Close; + this.CloseRomContextMenuItem.Name = "CloseRomContextMenuItem"; + this.CloseRomContextMenuItem.Size = new System.Drawing.Size(216, 22); + this.CloseRomContextMenuItem.Text = "Close ROM"; + this.CloseRomContextMenuItem.Click += new System.EventHandler(this.CloseRomMenuItem_Click); + // + // ClearSRAMContextMenuItem + // + this.ClearSRAMContextMenuItem.Name = "ClearSRAMContextMenuItem"; + this.ClearSRAMContextMenuItem.Size = new System.Drawing.Size(216, 22); + this.ClearSRAMContextMenuItem.Text = "Close and Clear SRAM"; + this.ClearSRAMContextMenuItem.Click += new System.EventHandler(this.ClearSramContextMenuItem_Click); + // + // ShowMenuContextMenuSeparator + // + this.ShowMenuContextMenuSeparator.Name = "ShowMenuContextMenuSeparator"; + this.ShowMenuContextMenuSeparator.Size = new System.Drawing.Size(213, 6); + // + // ShowMenuContextMenuItem + // + this.ShowMenuContextMenuItem.Name = "ShowMenuContextMenuItem"; + this.ShowMenuContextMenuItem.Size = new System.Drawing.Size(216, 22); + this.ShowMenuContextMenuItem.Text = "Show Menu"; + this.ShowMenuContextMenuItem.Click += new System.EventHandler(this.ShowMenuContextMenuItem_Click); + // + // timerMouseIdle + // + this.timerMouseIdle.Enabled = true; + this.timerMouseIdle.Interval = 2000; + this.timerMouseIdle.Tick += new System.EventHandler(this.TimerMouseIdle_Tick); + // + // MainForm + // + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None; + this.ClientSize = new System.Drawing.Size(470, 408); + this.Controls.Add(this.MainStatusBar); + this.Controls.Add(this.MainformMenu); + this.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.MainMenuStrip = this.MainformMenu; + this.Name = "MainForm"; + this.Text = "BizHawk"; + this.Activated += new System.EventHandler(this.MainForm_Activated); + this.Deactivate += new System.EventHandler(this.MainForm_Deactivate); + this.Load += new System.EventHandler(this.MainForm_Load); + this.Shown += new System.EventHandler(this.MainForm_Shown); + this.Enter += new System.EventHandler(this.MainForm_Enter); + this.MouseClick += new System.Windows.Forms.MouseEventHandler(this.MainForm_MouseClick); + this.MouseMove += new System.Windows.Forms.MouseEventHandler(this.MainForm_MouseMove); + this.Resize += new System.EventHandler(this.MainForm_Resize); + this.MainformMenu.ResumeLayout(false); + this.MainformMenu.PerformLayout(); + this.MainStatusBar.ResumeLayout(false); + this.MainStatusBar.PerformLayout(); + this.MainFormContextMenu.ResumeLayout(false); + this.ResumeLayout(false); + this.PerformLayout(); } @@ -4368,7 +4368,7 @@ private System.Windows.Forms.ToolStripMenuItem Atari7800HawkCoreMenuItem; private System.Windows.Forms.ToolStripMenuItem SGBCoreSubmenu; private System.Windows.Forms.ToolStripMenuItem SgbBsnesMenuItem; - private System.Windows.Forms.ToolStripMenuItem SgbPizzaBoyMenuItem; + private System.Windows.Forms.ToolStripMenuItem SgbSameBoyMenuItem; private System.Windows.Forms.ToolStripMenuItem pCFXToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem preferencesToolStripMenuItem3; } diff --git a/BizHawk.Client.EmuHawk/MainForm.Events.cs b/BizHawk.Client.EmuHawk/MainForm.Events.cs index 9e671697d4..663e4fd85d 100644 --- a/BizHawk.Client.EmuHawk/MainForm.Events.cs +++ b/BizHawk.Client.EmuHawk/MainForm.Events.cs @@ -25,6 +25,7 @@ using BizHawk.Client.EmuHawk.ToolExtensions; using BizHawk.Emulation.Cores.Computers.AppleII; using BizHawk.Client.ApiHawk; using BizHawk.Emulation.Cores.Computers.Commodore64; +using BizHawk.Emulation.Cores.Nintendo.Gameboy; namespace BizHawk.Client.EmuHawk { @@ -1257,7 +1258,7 @@ namespace BizHawk.Client.EmuHawk private void SGBCoreSubmenu_DropDownOpened(object sender, EventArgs e) { SgbBsnesMenuItem.Checked = Global.Config.SGB_UseBsnes; - SgbPizzaBoyMenuItem.Checked = !Global.Config.SGB_UseBsnes; + SgbSameBoyMenuItem.Checked = !Global.Config.SGB_UseBsnes; } private void SgbCorePick_Click(object sender, EventArgs e) @@ -1270,7 +1271,6 @@ namespace BizHawk.Client.EmuHawk } } - private void GbInSgbMenuItem_Click(object sender, EventArgs e) { Global.Config.GB_AsSGB ^= true; @@ -2002,7 +2002,14 @@ namespace BizHawk.Client.EmuHawk private void GBCoreSettingsMenuItem_Click(object sender, EventArgs e) { - GBPrefs.DoGBPrefsDialog(this); + if (Global.Emulator is Gameboy) + { + GBPrefs.DoGBPrefsDialog(this); + } + else // sameboy + { + GenericCoreConfig.DoDialog(this, "Gameboy Settings"); + } } private void LoadGbInSgbMenuItem_Click(object sender, EventArgs e) @@ -2430,7 +2437,7 @@ namespace BizHawk.Client.EmuHawk showMenuVisible = true; // need to always be able to restore this as an emergency measure } - if (_chromeless) + if (argParse._chromeless) { showMenuVisible = true; // I decided this was always possible in chromeless mode, we'll see what they think } diff --git a/BizHawk.Client.EmuHawk/MainForm.cs b/BizHawk.Client.EmuHawk/MainForm.cs index 9965c31309..13f72ae46f 100644 --- a/BizHawk.Client.EmuHawk/MainForm.cs +++ b/BizHawk.Client.EmuHawk/MainForm.cs @@ -33,6 +33,7 @@ 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 { @@ -153,7 +154,6 @@ namespace BizHawk.Client.EmuHawk } }; - ArgParser argParse = new ArgParser(); argParse.parseArguments(args); Database.LoadDatabase(Path.Combine(PathManager.GetExeDirectoryAbsolute(), "gamedb", "gamedb.txt")); @@ -299,9 +299,9 @@ namespace BizHawk.Client.EmuHawk Global.MovieSession.ReadOnly = true; // if user is dumping and didnt supply dump length, make it as long as the loaded movie - if (_autoDumpLength == 0) + if (argParse._autoDumpLength == 0) { - _autoDumpLength = movie.InputLogLength; + argParse._autoDumpLength = movie.InputLogLength; } // Copy pasta from drag & drop @@ -1022,15 +1022,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 && !_chromeless; - MainStatusBar.Visible = Global.Config.DispChrome_StatusBarFullscreen && !_chromeless; + MainMenuStrip.Visible = Global.Config.DispChrome_MenuFullscreen && !argParse._chromeless; + MainStatusBar.Visible = Global.Config.DispChrome_StatusBarFullscreen && !argParse._chromeless; } else { - MainStatusBar.Visible = Global.Config.DispChrome_StatusBarWindowed && !_chromeless; - MainMenuStrip.Visible = Global.Config.DispChrome_MenuWindowed && !_chromeless; - MaximizeBox = MinimizeBox = Global.Config.DispChrome_CaptionWindowed && !_chromeless; - if (Global.Config.DispChrome_FrameWindowed == 0 || _chromeless) + MainStatusBar.Visible = Global.Config.DispChrome_StatusBarWindowed && !argParse._chromeless; + MainMenuStrip.Visible = Global.Config.DispChrome_MenuWindowed && !argParse._chromeless; + MaximizeBox = MinimizeBox = Global.Config.DispChrome_CaptionWindowed && !argParse._chromeless; + if (Global.Config.DispChrome_FrameWindowed == 0 || argParse._chromeless) { FormBorderStyle = FormBorderStyle.None; } @@ -1356,7 +1356,6 @@ namespace BizHawk.Client.EmuHawk // AVI/WAV state private IVideoWriter _currAviWriter; - private readonly HashSet _currAviWriterFrameList; private AutofireController _autofireNullControls; @@ -1399,13 +1398,9 @@ namespace BizHawk.Client.EmuHawk private Point _windowedLocation; private bool _needsFullscreenOnLoad; - private int _autoDumpLength; - private readonly bool _autoCloseOnDump; private int _lastOpenRomFilter; - // chrome is never shown, even in windowed mode - private readonly bool _chromeless; - + private ArgParser argParse = new ArgParser(); // Resources private Bitmap _statusBarDiskLightOnImage; private Bitmap _statusBarDiskLightOffImage; @@ -1472,7 +1467,7 @@ namespace BizHawk.Client.EmuHawk } } - if (!Global.Config.DispChrome_CaptionWindowed || _chromeless) + if (!Global.Config.DispChrome_CaptionWindowed || argParse._chromeless) { str = ""; } @@ -1695,10 +1690,7 @@ namespace BizHawk.Client.EmuHawk switch (system) { case "GEN": - if (!(Emulator is PicoDrive)) // Currently PicoDrive doesn't support anything in this menu - { - GenesisSubMenu.Visible = true; - } + GenesisSubMenu.Visible = true; break; case "TI83": TI83SubMenu.Visible = true; @@ -1750,6 +1742,10 @@ namespace BizHawk.Client.EmuHawk { sNESToolStripMenuItem.Visible = true; } + else if (Emulator is Sameboy) + { + GBSubMenu.Visible = true; + } break; case "Coleco": ColecoSubMenu.Visible = true; @@ -3272,9 +3268,9 @@ namespace BizHawk.Client.EmuHawk try { // is this the best time to handle this? or deeper inside? - if (_currAviWriterFrameList != null) + if (argParse._currAviWriterFrameList != null) { - if (!_currAviWriterFrameList.Contains(Emulator.Frame)) + if (!argParse._currAviWriterFrameList.Contains(Emulator.Frame)) { goto HANDLE_AUTODUMP; } @@ -3356,14 +3352,14 @@ namespace BizHawk.Client.EmuHawk AbortAv(); } - HANDLE_AUTODUMP: - if (_autoDumpLength > 0) + HANDLE_AUTODUMP: + if (argParse._autoDumpLength > 0) { - _autoDumpLength--; - if (_autoDumpLength == 0) // finish + argParse._autoDumpLength--; + if (argParse._autoDumpLength == 0) // finish { StopAv(); - if (_autoCloseOnDump) + if (argParse._autoCloseOnDump) { _exit = true; } @@ -3545,7 +3541,7 @@ namespace BizHawk.Client.EmuHawk if (result) { - + string loaderName = "*" + OpenAdvancedSerializer.Serialize(ioa); Emulator = loader.LoadedEmulator; Global.Game = loader.Game; diff --git a/BizHawk.Client.EmuHawk/config/PCE/PCEControllerConfig.Designer.cs b/BizHawk.Client.EmuHawk/config/PCE/PCEControllerConfig.Designer.cs index f52aefb6fc..c78a658baa 100644 --- a/BizHawk.Client.EmuHawk/config/PCE/PCEControllerConfig.Designer.cs +++ b/BizHawk.Client.EmuHawk/config/PCE/PCEControllerConfig.Designer.cs @@ -28,52 +28,63 @@ /// private void InitializeComponent() { - System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(PCEControllerConfig)); - this.CancelBtn = new System.Windows.Forms.Button(); - this.OkBtn = new System.Windows.Forms.Button(); - this.SuspendLayout(); - // - // CancelBtn - // - this.CancelBtn.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); - this.CancelBtn.DialogResult = System.Windows.Forms.DialogResult.Cancel; - this.CancelBtn.Location = new System.Drawing.Point(235, 145); - this.CancelBtn.Name = "CancelBtn"; - this.CancelBtn.Size = new System.Drawing.Size(60, 23); - this.CancelBtn.TabIndex = 3; - this.CancelBtn.Text = "&Cancel"; - this.CancelBtn.UseVisualStyleBackColor = true; - this.CancelBtn.Click += new System.EventHandler(this.CancelBtn_Click); - // - // OkBtn - // - this.OkBtn.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); - this.OkBtn.Location = new System.Drawing.Point(169, 145); - this.OkBtn.Name = "OkBtn"; - this.OkBtn.Size = new System.Drawing.Size(60, 23); - this.OkBtn.TabIndex = 2; - this.OkBtn.Text = "&OK"; - this.OkBtn.UseVisualStyleBackColor = true; - this.OkBtn.Click += new System.EventHandler(this.OkBtn_Click); - // - // PCEControllerConfig - // - this.AcceptButton = this.OkBtn; - this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.CancelButton = this.CancelBtn; - this.ClientSize = new System.Drawing.Size(307, 180); - this.Controls.Add(this.CancelBtn); - this.Controls.Add(this.OkBtn); - this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; - this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); - this.MaximizeBox = false; - this.MinimizeBox = false; - this.Name = "PCEControllerConfig"; - this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; - this.Text = "Controller Settings"; - this.Load += new System.EventHandler(this.PCEControllerConfig_Load); - this.ResumeLayout(false); + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(PCEControllerConfig)); + this.CancelBtn = new System.Windows.Forms.Button(); + this.OkBtn = new System.Windows.Forms.Button(); + this.ControllerPropertyGrid = new System.Windows.Forms.PropertyGrid(); + this.SuspendLayout(); + // + // CancelBtn + // + this.CancelBtn.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.CancelBtn.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.CancelBtn.Location = new System.Drawing.Point(235, 203); + this.CancelBtn.Name = "CancelBtn"; + this.CancelBtn.Size = new System.Drawing.Size(60, 23); + this.CancelBtn.TabIndex = 3; + this.CancelBtn.Text = "&Cancel"; + this.CancelBtn.UseVisualStyleBackColor = true; + this.CancelBtn.Click += new System.EventHandler(this.CancelBtn_Click); + // + // OkBtn + // + this.OkBtn.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.OkBtn.Location = new System.Drawing.Point(169, 203); + this.OkBtn.Name = "OkBtn"; + this.OkBtn.Size = new System.Drawing.Size(60, 23); + this.OkBtn.TabIndex = 2; + this.OkBtn.Text = "&OK"; + this.OkBtn.UseVisualStyleBackColor = true; + this.OkBtn.Click += new System.EventHandler(this.OkBtn_Click); + // + // ControllerPropertyGrid + // + this.ControllerPropertyGrid.Location = new System.Drawing.Point(12, 12); + this.ControllerPropertyGrid.Name = "ControllerPropertyGrid"; + this.ControllerPropertyGrid.PropertySort = System.Windows.Forms.PropertySort.Alphabetical; + this.ControllerPropertyGrid.Size = new System.Drawing.Size(283, 181); + this.ControllerPropertyGrid.TabIndex = 4; + this.ControllerPropertyGrid.ToolbarVisible = false; + // + // PCEControllerConfig + // + this.AcceptButton = this.OkBtn; + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.CancelButton = this.CancelBtn; + this.ClientSize = new System.Drawing.Size(307, 238); + this.Controls.Add(this.ControllerPropertyGrid); + this.Controls.Add(this.CancelBtn); + this.Controls.Add(this.OkBtn); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "PCEControllerConfig"; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "Controller Settings"; + this.Load += new System.EventHandler(this.PCEControllerConfig_Load); + this.ResumeLayout(false); } @@ -81,5 +92,6 @@ private System.Windows.Forms.Button CancelBtn; private System.Windows.Forms.Button OkBtn; + private System.Windows.Forms.PropertyGrid ControllerPropertyGrid; } } \ No newline at end of file diff --git a/BizHawk.Client.EmuHawk/config/PCE/PCEControllerConfig.cs b/BizHawk.Client.EmuHawk/config/PCE/PCEControllerConfig.cs index 0eec5d71e9..c67095376c 100644 --- a/BizHawk.Client.EmuHawk/config/PCE/PCEControllerConfig.cs +++ b/BizHawk.Client.EmuHawk/config/PCE/PCEControllerConfig.cs @@ -1,6 +1,4 @@ using System; -using System.Drawing; -using System.Linq; using System.Windows.Forms; using BizHawk.Emulation.Cores.PCEngine; @@ -10,6 +8,8 @@ namespace BizHawk.Client.EmuHawk { public partial class PCEControllerConfig : Form { + private PCEngine.PCESyncSettings _controllerSettings; + public PCEControllerConfig() { InitializeComponent(); @@ -18,37 +18,13 @@ namespace BizHawk.Client.EmuHawk private void PCEControllerConfig_Load(object sender, EventArgs e) { var pceSettings = ((PCEngine)Global.Emulator).GetSyncSettings(); - for (int i = 0; i < 5; i++) - { - Controls.Add(new Label - { - Text = "Controller " + (i + 1), - Location = new Point(15, 15 + (i * 25)) - }); - Controls.Add(new CheckBox - { - Text = "Connected", - Name = "Controller" + i, - Location = new Point(135, 15 + (i * 25)), - Checked = pceSettings.Controllers[i].IsConnected - }); - } + _controllerSettings = pceSettings; // Assumes only controller data is in sync settings! If there are ever more sync settings, this dialog should just become a general sync settings dialog (or both settings/sync settings) + ControllerPropertyGrid.SelectedObject = _controllerSettings; } private void OkBtn_Click(object sender, EventArgs e) { - var pceSettings = ((PCEngine)Global.Emulator).GetSyncSettings(); - - Controls - .OfType() - .OrderBy(c => c.Name) - .ToList() - .ForEach(c => - { - var index = int.Parse(c.Name.Replace("Controller", "")); - pceSettings.Controllers[index].IsConnected = c.Checked; - }); - GlobalWin.MainForm.PutCoreSyncSettings(pceSettings); + GlobalWin.MainForm.PutCoreSyncSettings(_controllerSettings); DialogResult = DialogResult.OK; Close(); } diff --git a/BizHawk.Client.EmuHawk/tools/GB/GBGPUView.cs b/BizHawk.Client.EmuHawk/tools/GB/GBGPUView.cs index 6151c05677..8dc50567ef 100644 --- a/BizHawk.Client.EmuHawk/tools/GB/GBGPUView.cs +++ b/BizHawk.Client.EmuHawk/tools/GB/GBGPUView.cs @@ -9,13 +9,15 @@ using BizHawk.Emulation.Cores.Nintendo.Gameboy; using BizHawk.Client.EmuHawk.WinFormExtensions; using System.Collections.Generic; using BizHawk.Emulation.Common; +using BizHawk.Emulation.Cores.Consoles.Nintendo.Gameboy; +using BizHawk.Common; namespace BizHawk.Client.EmuHawk { public partial class GBGPUView : Form, IToolFormAutoConfig { [RequiredService] - public Gameboy Gb { get; private set; } + public IGameboyCommon Gb { get; private set; } // TODO: freeze semantics are a bit weird: details for a mouseover or freeze are taken from the current // state, not the state at the last callback (and so can be quite different when update is set to manual). @@ -32,11 +34,8 @@ namespace BizHawk.Client.EmuHawk // g' = 8.25g // b' = 8.25b - // gambatte doesn't modify these memory locations unless you reconstruct, so we can store - private IntPtr _vram; - private IntPtr _bgpal; - private IntPtr _sppal; - private IntPtr _oam; + + private GPUMemoryAreas _memory; private bool _cgb; // set once at start private int _lcdc; // set at each callback @@ -89,13 +88,9 @@ namespace BizHawk.Client.EmuHawk _cgb = Gb.IsCGBMode(); _lcdc = 0; - // TODO: can this be a required Emulator Service, and let the tool manage the logic of closing? - if (!Gb.GetGPUMemoryAreas(out _vram, out _bgpal, out _sppal, out _oam)) - { - if (Visible) - Close(); - } - tilespal = _bgpal; + _memory = Gb.GetGPU(); + + tilespal = _memory.Bgpal; if (_cgb) label4.Enabled = true; @@ -357,112 +352,120 @@ namespace BizHawk.Client.EmuHawk #endregion - void ScanlineCallback(int lcdc) + void ScanlineCallback(byte lcdc) { - _lcdc = lcdc; - // set alpha on all pixels - unsafe + using (_memory.EnterExit()) { - int* p = (int*)_bgpal; - for (int i = 0; i < 32; i++) - p[i] |= unchecked((int)0xff000000); - p = (int*)_sppal; - for (int i = 0; i < 32; i++) - p[i] |= unchecked((int)0xff000000); - int c = Spriteback.ToArgb(); - for (int i = 0; i < 32; i += 4) - p[i] = c; - } + var _bgpal = _memory.Bgpal; + var _sppal = _memory.Sppal; + var _oam = _memory.Oam; + var _vram = _memory.Vram; - // bg maps - if (!_cgb) - { - DrawBGDMG( - bmpViewBG.BMP, - _vram + (lcdc.Bit(3) ? 0x1c00 : 0x1800), - _vram + (lcdc.Bit(4) ? 0x0000 : 0x1000), - !lcdc.Bit(4), - _bgpal); + _lcdc = lcdc; + // set alpha on all pixels + // TODO: RE: Spriteback, you can't muck with Sameboy in this way due to how SGB reads stuff...? + /*unsafe + { + int* p = (int*)_bgpal; + for (int i = 0; i < 32; i++) + p[i] |= unchecked((int)0xff000000); + p = (int*)_sppal; + for (int i = 0; i < 32; i++) + p[i] |= unchecked((int)0xff000000); + int c = Spriteback.ToArgb(); + for (int i = 0; i < 32; i += 4) + p[i] = c; + }*/ - DrawBGDMG( - bmpViewWin.BMP, - _vram + (lcdc.Bit(6) ? 0x1c00 : 0x1800), - _vram + 0x1000, // force win to second tile bank??? - true, - _bgpal); - } - else - { - DrawBGCGB( - bmpViewBG.BMP, - _vram + (lcdc.Bit(3) ? 0x1c00 : 0x1800), - _vram + (lcdc.Bit(4) ? 0x0000 : 0x1000), - !lcdc.Bit(4), - _bgpal); + // bg maps + if (!_cgb) + { + DrawBGDMG( + bmpViewBG.BMP, + _vram + (lcdc.Bit(3) ? 0x1c00 : 0x1800), + _vram + (lcdc.Bit(4) ? 0x0000 : 0x1000), + !lcdc.Bit(4), + _bgpal); - DrawBGCGB( - bmpViewWin.BMP, - _vram + (lcdc.Bit(6) ? 0x1c00 : 0x1800), - _vram + 0x1000, // force win to second tile bank??? - true, - _bgpal); - } - bmpViewBG.Refresh(); - bmpViewWin.Refresh(); + DrawBGDMG( + bmpViewWin.BMP, + _vram + (lcdc.Bit(6) ? 0x1c00 : 0x1800), + _vram + 0x1000, // force win to second tile bank??? + true, + _bgpal); + } + else + { + DrawBGCGB( + bmpViewBG.BMP, + _vram + (lcdc.Bit(3) ? 0x1c00 : 0x1800), + _vram + (lcdc.Bit(4) ? 0x0000 : 0x1000), + !lcdc.Bit(4), + _bgpal); - // tile display - // TODO: user selects palette to use, instead of fixed palette 0 - // or possibly "smart" where, if a tile is in use, it's drawn with one of the palettes actually being used with it? - DrawTiles(bmpViewTiles1.BMP, _vram, tilespal); - bmpViewTiles1.Refresh(); - if (_cgb) - { - DrawTiles(bmpViewTiles2.BMP, _vram + 0x2000, tilespal); - bmpViewTiles2.Refresh(); - } + DrawBGCGB( + bmpViewWin.BMP, + _vram + (lcdc.Bit(6) ? 0x1c00 : 0x1800), + _vram + 0x1000, // force win to second tile bank??? + true, + _bgpal); + } + bmpViewBG.Refresh(); + bmpViewWin.Refresh(); - // palettes - if (_cgb) - { - bmpViewBGPal.ChangeBitmapSize(8, 4); - if (bmpViewBGPal.Width != 128) - bmpViewBGPal.Width = 128; - bmpViewSPPal.ChangeBitmapSize(8, 4); - if (bmpViewSPPal.Width != 128) - bmpViewSPPal.Width = 128; - DrawPal(bmpViewBGPal.BMP, _bgpal, 8); - DrawPal(bmpViewSPPal.BMP, _sppal, 8); - } - else - { - bmpViewBGPal.ChangeBitmapSize(1, 4); - if (bmpViewBGPal.Width != 16) - bmpViewBGPal.Width = 16; - bmpViewSPPal.ChangeBitmapSize(2, 4); - if (bmpViewSPPal.Width != 32) - bmpViewSPPal.Width = 32; - DrawPal(bmpViewBGPal.BMP, _bgpal, 1); - DrawPal(bmpViewSPPal.BMP, _sppal, 2); - } - bmpViewBGPal.Refresh(); - bmpViewSPPal.Refresh(); + // tile display + // TODO: user selects palette to use, instead of fixed palette 0 + // or possibly "smart" where, if a tile is in use, it's drawn with one of the palettes actually being used with it? + DrawTiles(bmpViewTiles1.BMP, _vram, tilespal); + bmpViewTiles1.Refresh(); + if (_cgb) + { + DrawTiles(bmpViewTiles2.BMP, _vram + 0x2000, tilespal); + bmpViewTiles2.Refresh(); + } - // oam - if (lcdc.Bit(2)) // 8x16 - { - bmpViewOAM.ChangeBitmapSize(320, 16); - if (bmpViewOAM.Height != 16) - bmpViewOAM.Height = 16; - } - else - { - bmpViewOAM.ChangeBitmapSize(320, 8); - if (bmpViewOAM.Height != 8) - bmpViewOAM.Height = 8; - } - DrawOam(bmpViewOAM.BMP, _oam, _vram, _sppal, lcdc.Bit(2), _cgb); - bmpViewOAM.Refresh(); + // palettes + if (_cgb) + { + bmpViewBGPal.ChangeBitmapSize(8, 4); + if (bmpViewBGPal.Width != 128) + bmpViewBGPal.Width = 128; + bmpViewSPPal.ChangeBitmapSize(8, 4); + if (bmpViewSPPal.Width != 128) + bmpViewSPPal.Width = 128; + DrawPal(bmpViewBGPal.BMP, _bgpal, 8); + DrawPal(bmpViewSPPal.BMP, _sppal, 8); + } + else + { + bmpViewBGPal.ChangeBitmapSize(1, 4); + if (bmpViewBGPal.Width != 16) + bmpViewBGPal.Width = 16; + bmpViewSPPal.ChangeBitmapSize(2, 4); + if (bmpViewSPPal.Width != 32) + bmpViewSPPal.Width = 32; + DrawPal(bmpViewBGPal.BMP, _bgpal, 1); + DrawPal(bmpViewSPPal.BMP, _sppal, 2); + } + bmpViewBGPal.Refresh(); + bmpViewSPPal.Refresh(); + // oam + if (lcdc.Bit(2)) // 8x16 + { + bmpViewOAM.ChangeBitmapSize(320, 16); + if (bmpViewOAM.Height != 16) + bmpViewOAM.Height = 16; + } + else + { + bmpViewOAM.ChangeBitmapSize(320, 8); + if (bmpViewOAM.Height != 8) + bmpViewOAM.Height = 8; + } + DrawOam(bmpViewOAM.BMP, _oam, _vram, _sppal, lcdc.Bit(2), _cgb); + bmpViewOAM.Refresh(); + } // try to run the current mouseover, to refresh if the mouse is being held over a pane while the emulator runs // this doesn't really work well; the update rate seems to be throttled MouseEventArgs e = new MouseEventArgs(MouseButtons.None, 0, Cursor.Position.X, Cursor.Position.Y, 0); @@ -514,7 +517,7 @@ namespace BizHawk.Client.EmuHawk private void buttonRefresh_Click(object sender, EventArgs e) { - if (cbscanline == -2 && Gb != null) + if (cbscanline == -2) Gb.SetScanlineCallback(ScanlineCallback, -2); } @@ -614,145 +617,177 @@ namespace BizHawk.Client.EmuHawk private unsafe void PaletteMouseover(int x, int y, bool sprite) { - bmpViewDetails.ChangeBitmapSize(8, 10); - if (bmpViewDetails.Height != 80) - bmpViewDetails.Height = 80; - var sb = new StringBuilder(); - x /= 16; - y /= 16; - int* pal = (int*)(sprite ? _sppal : _bgpal) + x * 4; - int color = pal[y]; - - sb.AppendLine(string.Format("Palette {0}", x)); - sb.AppendLine(string.Format("Color {0}", y)); - sb.AppendLine(string.Format("(R,G,B) = ({0},{1},{2})", color >> 16 & 255, color >> 8 & 255, color & 255)); - - var lockdata = bmpViewDetails.BMP.LockBits(new Rectangle(0, 0, 8, 10), System.Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb); - int* dest = (int*)lockdata.Scan0; - int pitch = lockdata.Stride / sizeof(int); - - for (int py = 0; py < 10; py++) + using (_memory.EnterExit()) { - for (int px = 0; px < 8; px++) + var _bgpal = _memory.Bgpal; + var _sppal = _memory.Sppal; + var _oam = _memory.Oam; + var _vram = _memory.Vram; + + bmpViewDetails.ChangeBitmapSize(8, 10); + if (bmpViewDetails.Height != 80) + bmpViewDetails.Height = 80; + var sb = new StringBuilder(); + x /= 16; + y /= 16; + int* pal = (int*)(sprite ? _sppal : _bgpal) + x * 4; + int color = pal[y]; + + sb.AppendLine(string.Format("Palette {0}", x)); + sb.AppendLine(string.Format("Color {0}", y)); + sb.AppendLine(string.Format("(R,G,B) = ({0},{1},{2})", color >> 16 & 255, color >> 8 & 255, color & 255)); + + var lockdata = bmpViewDetails.BMP.LockBits(new Rectangle(0, 0, 8, 10), System.Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb); + int* dest = (int*)lockdata.Scan0; + int pitch = lockdata.Stride / sizeof(int); + + for (int py = 0; py < 10; py++) { - if (py < 8) - *dest++ = color; - else - *dest++ = pal[px / 2]; + for (int px = 0; px < 8; px++) + { + if (py < 8) + *dest++ = color; + else + *dest++ = pal[px / 2]; + } + dest -= 8; + dest += pitch; } - dest -= 8; - dest += pitch; + bmpViewDetails.BMP.UnlockBits(lockdata); + labelDetails.Text = sb.ToString(); + bmpViewDetails.Refresh(); } - bmpViewDetails.BMP.UnlockBits(lockdata); - labelDetails.Text = sb.ToString(); - bmpViewDetails.Refresh(); } unsafe void TileMouseover(int x, int y, bool secondbank) { - // todo: draw with a specific palette - bmpViewDetails.ChangeBitmapSize(8, 8); - if (bmpViewDetails.Height != 64) - bmpViewDetails.Height = 64; - var sb = new StringBuilder(); - x /= 8; - y /= 8; - int tileindex = y * 16 + x; - int tileoffs = tileindex * 16; - if (_cgb) - sb.AppendLine(string.Format("Tile #{0} @{2}:{1:x4}", tileindex, tileoffs + 0x8000, secondbank ? 1 : 0)); - else - sb.AppendLine(string.Format("Tile #{0} @{1:x4}", tileindex, tileoffs + 0x8000)); + using (_memory.EnterExit()) + { + var _bgpal = _memory.Bgpal; + var _sppal = _memory.Sppal; + var _oam = _memory.Oam; + var _vram = _memory.Vram; - var lockdata = bmpViewDetails.BMP.LockBits(new Rectangle(0, 0, 8, 8), System.Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb); - DrawTile((byte*)_vram + tileoffs + (secondbank ? 8192 : 0), (int*)lockdata.Scan0, lockdata.Stride / sizeof(int), (int*)tilespal); - bmpViewDetails.BMP.UnlockBits(lockdata); - labelDetails.Text = sb.ToString(); - bmpViewDetails.Refresh(); + // todo: draw with a specific palette + bmpViewDetails.ChangeBitmapSize(8, 8); + if (bmpViewDetails.Height != 64) + bmpViewDetails.Height = 64; + var sb = new StringBuilder(); + x /= 8; + y /= 8; + int tileindex = y * 16 + x; + int tileoffs = tileindex * 16; + if (_cgb) + sb.AppendLine(string.Format("Tile #{0} @{2}:{1:x4}", tileindex, tileoffs + 0x8000, secondbank ? 1 : 0)); + else + sb.AppendLine(string.Format("Tile #{0} @{1:x4}", tileindex, tileoffs + 0x8000)); + + var lockdata = bmpViewDetails.BMP.LockBits(new Rectangle(0, 0, 8, 8), System.Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb); + DrawTile((byte*)_vram + tileoffs + (secondbank ? 8192 : 0), (int*)lockdata.Scan0, lockdata.Stride / sizeof(int), (int*)tilespal); + bmpViewDetails.BMP.UnlockBits(lockdata); + labelDetails.Text = sb.ToString(); + bmpViewDetails.Refresh(); + } } unsafe void TilemapMouseover(int x, int y, bool win) { - bmpViewDetails.ChangeBitmapSize(8, 8); - if (bmpViewDetails.Height != 64) - bmpViewDetails.Height = 64; - var sb = new StringBuilder(); - bool secondmap = win ? _lcdc.Bit(6) : _lcdc.Bit(3); - int mapoffs = secondmap ? 0x1c00 : 0x1800; - x /= 8; - y /= 8; - mapoffs += y * 32 + x; - byte* mapbase = (byte*)_vram + mapoffs; - int tileindex = mapbase[0]; - if (win || !_lcdc.Bit(4)) // 0x9000 base - if (tileindex < 128) - tileindex += 256; // compute all if from 0x8000 base - int tileoffs = tileindex * 16; - var lockdata = bmpViewDetails.BMP.LockBits(new Rectangle(0, 0, 8, 8), System.Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb); - if (!_cgb) + using (_memory.EnterExit()) { - sb.AppendLine(string.Format("{0} Map ({1},{2}) @{3:x4}", win ? "Win" : "BG", x, y, mapoffs + 0x8000)); - sb.AppendLine(string.Format(" Tile #{0} @{1:x4}", tileindex, tileoffs + 0x8000)); - DrawTile((byte*)_vram + tileoffs, (int*)lockdata.Scan0, lockdata.Stride / sizeof(int), (int*)_bgpal); - } - else - { - int tileext = mapbase[8192]; + var _bgpal = _memory.Bgpal; + var _sppal = _memory.Sppal; + var _oam = _memory.Oam; + var _vram = _memory.Vram; - sb.AppendLine(string.Format("{0} Map ({1},{2}) @{3:x4}", win ? "Win" : "BG", x, y, mapoffs + 0x8000)); - sb.AppendLine(string.Format(" Tile #{0} @{2}:{1:x4}", tileindex, tileoffs + 0x8000, tileext.Bit(3) ? 1 : 0)); - sb.AppendLine(string.Format(" Palette {0}", tileext & 7)); - sb.AppendLine(string.Format(" Flags {0}{1}{2}", tileext.Bit(5) ? 'H' : ' ', tileext.Bit(6) ? 'V' : ' ', tileext.Bit(7) ? 'P' : ' ')); - DrawTileHv((byte*)_vram + tileoffs + (tileext.Bit(3) ? 8192 : 0), (int*)lockdata.Scan0, lockdata.Stride / sizeof(int), (int*)_bgpal + 4 * (tileext & 7), tileext.Bit(5), tileext.Bit(6)); + bmpViewDetails.ChangeBitmapSize(8, 8); + if (bmpViewDetails.Height != 64) + bmpViewDetails.Height = 64; + var sb = new StringBuilder(); + bool secondmap = win ? _lcdc.Bit(6) : _lcdc.Bit(3); + int mapoffs = secondmap ? 0x1c00 : 0x1800; + x /= 8; + y /= 8; + mapoffs += y * 32 + x; + byte* mapbase = (byte*)_vram + mapoffs; + int tileindex = mapbase[0]; + if (win || !_lcdc.Bit(4)) // 0x9000 base + if (tileindex < 128) + tileindex += 256; // compute all if from 0x8000 base + int tileoffs = tileindex * 16; + var lockdata = bmpViewDetails.BMP.LockBits(new Rectangle(0, 0, 8, 8), System.Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb); + if (!_cgb) + { + sb.AppendLine(string.Format("{0} Map ({1},{2}) @{3:x4}", win ? "Win" : "BG", x, y, mapoffs + 0x8000)); + sb.AppendLine(string.Format(" Tile #{0} @{1:x4}", tileindex, tileoffs + 0x8000)); + DrawTile((byte*)_vram + tileoffs, (int*)lockdata.Scan0, lockdata.Stride / sizeof(int), (int*)_bgpal); + } + else + { + int tileext = mapbase[8192]; + + sb.AppendLine(string.Format("{0} Map ({1},{2}) @{3:x4}", win ? "Win" : "BG", x, y, mapoffs + 0x8000)); + sb.AppendLine(string.Format(" Tile #{0} @{2}:{1:x4}", tileindex, tileoffs + 0x8000, tileext.Bit(3) ? 1 : 0)); + sb.AppendLine(string.Format(" Palette {0}", tileext & 7)); + sb.AppendLine(string.Format(" Flags {0}{1}{2}", tileext.Bit(5) ? 'H' : ' ', tileext.Bit(6) ? 'V' : ' ', tileext.Bit(7) ? 'P' : ' ')); + DrawTileHv((byte*)_vram + tileoffs + (tileext.Bit(3) ? 8192 : 0), (int*)lockdata.Scan0, lockdata.Stride / sizeof(int), (int*)_bgpal + 4 * (tileext & 7), tileext.Bit(5), tileext.Bit(6)); + } + bmpViewDetails.BMP.UnlockBits(lockdata); + labelDetails.Text = sb.ToString(); + bmpViewDetails.Refresh(); } - bmpViewDetails.BMP.UnlockBits(lockdata); - labelDetails.Text = sb.ToString(); - bmpViewDetails.Refresh(); } unsafe void SpriteMouseover(int x, int y) { - bool tall = _lcdc.Bit(2); - x /= 8; - y /= 8; - bmpViewDetails.ChangeBitmapSize(8, tall ? 16 : 8); - if (bmpViewDetails.Height != bmpViewDetails.BMP.Height * 8) - bmpViewDetails.Height = bmpViewDetails.BMP.Height * 8; - var sb = new StringBuilder(); + using (_memory.EnterExit()) + { + var _bgpal = _memory.Bgpal; + var _sppal = _memory.Sppal; + var _oam = _memory.Oam; + var _vram = _memory.Vram; - byte* oament = (byte*)_oam + 4 * x; - int sy = oament[0]; - int sx = oament[1]; - int tilenum = oament[2]; - int flags = oament[3]; - bool hflip = flags.Bit(5); - bool vflip = flags.Bit(6); - if (tall) - tilenum = vflip ? tilenum | 1 : tilenum & ~1; - int tileoffs = tilenum * 16; - sb.AppendLine(string.Format("Sprite #{0} @{1:x4}", x, 4 * x + 0xfe00)); - sb.AppendLine(string.Format(" (x,y) = ({0},{1})", sx, sy)); - var lockdata = bmpViewDetails.BMP.LockBits(new Rectangle(0, 0, 8, tall ? 16 : 8), System.Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb); - if (_cgb) - { - sb.AppendLine(string.Format(" Tile #{0} @{2}:{1:x4}", y == 1 ? tilenum ^ 1 : tilenum, tileoffs + 0x8000, flags.Bit(3) ? 1 : 0)); - sb.AppendLine(string.Format(" Palette {0}", flags & 7)); - DrawTileHv((byte*)_vram + tileoffs + (flags.Bit(3) ? 8192 : 0), (int*)lockdata.Scan0, lockdata.Stride / sizeof(int), (int*)_sppal + 4 * (flags & 7), hflip, vflip); + bool tall = _lcdc.Bit(2); + x /= 8; + y /= 8; + bmpViewDetails.ChangeBitmapSize(8, tall ? 16 : 8); + if (bmpViewDetails.Height != bmpViewDetails.BMP.Height * 8) + bmpViewDetails.Height = bmpViewDetails.BMP.Height * 8; + var sb = new StringBuilder(); + + byte* oament = (byte*)_oam + 4 * x; + int sy = oament[0]; + int sx = oament[1]; + int tilenum = oament[2]; + int flags = oament[3]; + bool hflip = flags.Bit(5); + bool vflip = flags.Bit(6); if (tall) - DrawTileHv((byte*)_vram + (tileoffs ^ 16) + (flags.Bit(3) ? 8192 : 0), (int*)(lockdata.Scan0 + lockdata.Stride * 8), lockdata.Stride / sizeof(int), (int*)_sppal + 4 * (flags & 7), hflip, vflip); + tilenum = vflip ? tilenum | 1 : tilenum & ~1; + int tileoffs = tilenum * 16; + sb.AppendLine(string.Format("Sprite #{0} @{1:x4}", x, 4 * x + 0xfe00)); + sb.AppendLine(string.Format(" (x,y) = ({0},{1})", sx, sy)); + var lockdata = bmpViewDetails.BMP.LockBits(new Rectangle(0, 0, 8, tall ? 16 : 8), System.Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb); + if (_cgb) + { + sb.AppendLine(string.Format(" Tile #{0} @{2}:{1:x4}", y == 1 ? tilenum ^ 1 : tilenum, tileoffs + 0x8000, flags.Bit(3) ? 1 : 0)); + sb.AppendLine(string.Format(" Palette {0}", flags & 7)); + DrawTileHv((byte*)_vram + tileoffs + (flags.Bit(3) ? 8192 : 0), (int*)lockdata.Scan0, lockdata.Stride / sizeof(int), (int*)_sppal + 4 * (flags & 7), hflip, vflip); + if (tall) + DrawTileHv((byte*)_vram + (tileoffs ^ 16) + (flags.Bit(3) ? 8192 : 0), (int*)(lockdata.Scan0 + lockdata.Stride * 8), lockdata.Stride / sizeof(int), (int*)_sppal + 4 * (flags & 7), hflip, vflip); + } + else + { + sb.AppendLine(string.Format(" Tile #{0} @{1:x4}", y == 1 ? tilenum ^ 1 : tilenum, tileoffs + 0x8000)); + sb.AppendLine(string.Format(" Palette {0}", flags.Bit(4) ? 1 : 0)); + DrawTileHv((byte*)_vram + tileoffs, (int*)lockdata.Scan0, lockdata.Stride / sizeof(int), (int*)_sppal + (flags.Bit(4) ? 4 : 0), hflip, vflip); + if (tall) + DrawTileHv((byte*)_vram + (tileoffs ^ 16), (int*)(lockdata.Scan0 + lockdata.Stride * 8), lockdata.Stride / sizeof(int), (int*)_sppal + 4 * (flags.Bit(4) ? 4 : 0), hflip, vflip); + } + sb.AppendLine(string.Format(" Flags {0}{1}{2}", hflip ? 'H' : ' ', vflip ? 'V' : ' ', flags.Bit(7) ? 'P' : ' ')); + bmpViewDetails.BMP.UnlockBits(lockdata); + labelDetails.Text = sb.ToString(); + bmpViewDetails.Refresh(); } - else - { - sb.AppendLine(string.Format(" Tile #{0} @{1:x4}", y == 1 ? tilenum ^ 1 : tilenum, tileoffs + 0x8000)); - sb.AppendLine(string.Format(" Palette {0}", flags.Bit(4) ? 1 : 0)); - DrawTileHv((byte*)_vram + tileoffs, (int*)lockdata.Scan0, lockdata.Stride / sizeof(int), (int*)_sppal + (flags.Bit(4) ? 4 : 0), hflip, vflip); - if (tall) - DrawTileHv((byte*)_vram + (tileoffs ^ 16), (int*)(lockdata.Scan0 + lockdata.Stride * 8), lockdata.Stride / sizeof(int), (int*)_sppal + 4 * (flags.Bit(4) ? 4 : 0), hflip, vflip); - } - sb.AppendLine(string.Format(" Flags {0}{1}{2}", hflip ? 'H' : ' ', vflip ? 'V' : ' ', flags.Bit(7) ? 'P' : ' ')); - bmpViewDetails.BMP.UnlockBits(lockdata); - labelDetails.Text = sb.ToString(); - bmpViewDetails.Refresh(); } private void bmpViewBG_MouseEnter(object sender, EventArgs e) @@ -882,9 +917,9 @@ namespace BizHawk.Client.EmuHawk else if (e.Button == MouseButtons.Left) { if (sender == bmpViewBGPal) - tilespal = _bgpal + e.X / 16 * 16; + tilespal = _memory.Bgpal + e.X / 16 * 16; else if (sender == bmpViewSPPal) - tilespal = _sppal + e.X / 16 * 16; + tilespal = _memory.Sppal + e.X / 16 * 16; } } diff --git a/BizHawk.Client.EmuHawk/tools/Lua/Libraries/EmuLuaLibrary.cs b/BizHawk.Client.EmuHawk/tools/Lua/Libraries/EmuLuaLibrary.cs index 97c8ac58dd..30b1c40f7c 100644 --- a/BizHawk.Client.EmuHawk/tools/Lua/Libraries/EmuLuaLibrary.cs +++ b/BizHawk.Client.EmuHawk/tools/Lua/Libraries/EmuLuaLibrary.cs @@ -18,7 +18,7 @@ namespace BizHawk.Client.EmuHawk public EmuLuaLibrary() { Docs = new LuaDocumentation(); - if(NLua.Lua.WhichLua == "NLua") + //if(NLua.Lua.WhichLua == "NLua") _lua["keepalives"] = _lua.NewTable(); } @@ -178,7 +178,7 @@ namespace BizHawk.Client.EmuHawk var content = File.ReadAllText(file); var main = lua.LoadString(content, "main"); lua.Push(main); // push main function on to stack for subsequent resuming - if (NLua.Lua.WhichLua == "NLua") + //if (NLua.Lua.WhichLua == "NLua") { _lua.GetTable("keepalives")[lua] = 1; //this not being run is the origin of a memory leak if you restart scripts too many times @@ -191,7 +191,7 @@ namespace BizHawk.Client.EmuHawk { _currThread = _lua.NewThread(); _currThread.DoString(command); - if (NLua.Lua.WhichLua == "NLua") + //if (NLua.Lua.WhichLua == "NLua") _lua.Pop(); } diff --git a/BizHawk.Client.EmuHawk/tools/MultiDiskBundler/MultiDiskBundler.Designer.cs b/BizHawk.Client.EmuHawk/tools/MultiDiskBundler/MultiDiskBundler.Designer.cs index def046ab2e..3c1e2f2e9e 100644 --- a/BizHawk.Client.EmuHawk/tools/MultiDiskBundler/MultiDiskBundler.Designer.cs +++ b/BizHawk.Client.EmuHawk/tools/MultiDiskBundler/MultiDiskBundler.Designer.cs @@ -138,12 +138,12 @@ this.SystemDropDown.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; this.SystemDropDown.FormattingEnabled = true; this.SystemDropDown.Items.AddRange(new object[] { - "GB", "AppleII", - "PSX", "C64", - "SAT", - "PCFX"}); + "GB", + "PCFX", + "PSX", + "SAT"}); this.SystemDropDown.Location = new System.Drawing.Point(425, 75); this.SystemDropDown.Name = "SystemDropDown"; this.SystemDropDown.Size = new System.Drawing.Size(69, 21); diff --git a/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.cs b/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.cs index 91954bf9af..d2d48907b7 100644 --- a/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.cs +++ b/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.cs @@ -78,7 +78,7 @@ namespace BizHawk.Client.EmuHawk DenoteMarkersWithBGColor = true; } - public RecentFiles RecentTas { get; } + public RecentFiles RecentTas { get; set; } public bool DrawInput { get; set; } public bool AutoPause { get; set; } public bool AutoRestoreLastPosition { get; set; } diff --git a/BizHawk.Client.EmuHawk/tools/VirtualPads/schema/A7800HawkSchema.cs b/BizHawk.Client.EmuHawk/tools/VirtualPads/schema/A7800HawkSchema.cs index 6e2545f634..299262e983 100644 --- a/BizHawk.Client.EmuHawk/tools/VirtualPads/schema/A7800HawkSchema.cs +++ b/BizHawk.Client.EmuHawk/tools/VirtualPads/schema/A7800HawkSchema.cs @@ -12,12 +12,13 @@ namespace BizHawk.Client.EmuHawk { private string UnpluggedControllerName => typeof(UnpluggedController).DisplayName(); private string StandardControllerName => typeof(StandardController).DisplayName(); + private string ProLineControllerName => typeof(ProLineController).DisplayName(); public IEnumerable GetPadSchemas(IEmulator core) { - var intvSyncSettings = ((A7800Hawk)core).GetSyncSettings().Clone(); - var port1 = intvSyncSettings.Port1; - var port2 = intvSyncSettings.Port2; + var A78SyncSettings = ((A7800Hawk)core).GetSyncSettings().Clone(); + var port1 = A78SyncSettings.Port1; + var port2 = A78SyncSettings.Port2; if (port1 == StandardControllerName) { @@ -28,7 +29,17 @@ namespace BizHawk.Client.EmuHawk { yield return JoystickController(2); } - + + if (port1 == ProLineControllerName) + { + yield return ProLineController(1); + } + + if (port2 == ProLineControllerName) + { + yield return ProLineController(2); + } + } private static PadSchema ProLineController(int controller) diff --git a/BizHawk.Client.EmuHawk/tools/VirtualPads/schema/PceSchema.cs b/BizHawk.Client.EmuHawk/tools/VirtualPads/schema/PceSchema.cs index 5b5f6d26f5..1b6545b7b2 100644 --- a/BizHawk.Client.EmuHawk/tools/VirtualPads/schema/PceSchema.cs +++ b/BizHawk.Client.EmuHawk/tools/VirtualPads/schema/PceSchema.cs @@ -1,7 +1,10 @@ using System.Collections.Generic; using System.Drawing; +using System.Linq; +using System.Windows.Forms; using BizHawk.Emulation.Common; +using BizHawk.Emulation.Cores.PCEngine; namespace BizHawk.Client.EmuHawk { @@ -13,9 +16,34 @@ namespace BizHawk.Client.EmuHawk { public IEnumerable GetPadSchemas(IEmulator core) { - for (var i = 0; i < core.ControllerDefinition.PlayerCount; i++) + var ss = ((PCEngine)core).GetSyncSettings(); + + var padSchemas = new[] { - yield return StandardController(i + 1); + ss.Port1, + ss.Port2, + ss.Port3, + ss.Port4, + ss.Port5, + } + .Where(p => p != PceControllerType.Unplugged) + .Select((p, i) => GenerateSchemaForPort(p, i + 1)) + .Where(s => s != null); + + return padSchemas; + } + + private static PadSchema GenerateSchemaForPort(PceControllerType type, int controller) + { + switch (type) + { + default: + MessageBox.Show($"{type} is not supported yet"); + return null; + case PceControllerType.Unplugged: + return null; + case PceControllerType.GamePad: + return StandardController(controller); } } @@ -29,7 +57,7 @@ namespace BizHawk.Client.EmuHawk { new PadSchema.ButtonSchema { - Name = "P" + controller + " Up", + Name = $"P{controller} Up", DisplayName = "", Icon = Properties.Resources.BlueUp, Location = new Point(14, 12), @@ -37,7 +65,7 @@ namespace BizHawk.Client.EmuHawk }, new PadSchema.ButtonSchema { - Name = "P" + controller + " Down", + Name = $"P{controller} Down", DisplayName = "", Icon = Properties.Resources.BlueDown, Location = new Point(14, 56), @@ -45,7 +73,7 @@ namespace BizHawk.Client.EmuHawk }, new PadSchema.ButtonSchema { - Name = "P" + controller + " Left", + Name = $"P{controller} Left", DisplayName = "", Icon = Properties.Resources.Back, Location = new Point(2, 34), @@ -53,7 +81,7 @@ namespace BizHawk.Client.EmuHawk }, new PadSchema.ButtonSchema { - Name = "P" + controller + " Right", + Name = $"P{controller} Right", DisplayName = "", Icon = Properties.Resources.Forward, Location = new Point(24, 34), @@ -61,28 +89,28 @@ namespace BizHawk.Client.EmuHawk }, new PadSchema.ButtonSchema { - Name = "P" + controller + " B2", + Name = $"P{controller} B2", DisplayName = "II", Location = new Point(122, 34), Type = PadSchema.PadInputType.Boolean }, new PadSchema.ButtonSchema { - Name = "P" + controller + " B1", + Name = $"P{controller} B1", DisplayName = "I", Location = new Point(146, 34), Type = PadSchema.PadInputType.Boolean }, new PadSchema.ButtonSchema { - Name = "P" + controller + " Select", + Name = $"P{controller} Select", DisplayName = "s", Location = new Point(52, 34), Type = PadSchema.PadInputType.Boolean }, new PadSchema.ButtonSchema { - Name = "P" + controller + " Run", + Name = $"P{controller} Run", DisplayName = "R", Location = new Point(74, 34), Type = PadSchema.PadInputType.Boolean diff --git a/BizHawk.Emulation.Common/Database/FirmwareDatabase.cs b/BizHawk.Emulation.Common/Database/FirmwareDatabase.cs index 6b56f7275e..41b60815b7 100644 --- a/BizHawk.Emulation.Common/Database/FirmwareDatabase.cs +++ b/BizHawk.Emulation.Common/Database/FirmwareDatabase.cs @@ -72,7 +72,8 @@ namespace BizHawk.Emulation.Common Option("SAT", "E", ss_100_j); Option("SAT", "E", ss_101_j); FirmwareAndOption("a67cd4f550751f8b91de2b8b74528ab4e0c11c77", 2 * 1024 * 1024, "SAT", "KOF95", "kof95.bin", "King of Fighters cartridge"); - Firmware("SAT", "ULTRAMAN", "Ultraman cartridge"); + //Firmware("SAT", "ULTRAMAN", "Ultraman cartridge"); + FirmwareAndOption("56c1b93da6b660bf393fbf48ca47569000ef4047", 2 * 1024 * 1024, "SAT", "ULTRAMAN", "Ultraman.bin", "Ultraman cartridge"); var ti83_102 = File("CE08F6A808701FC6672230A790167EE485157561", 262144, "ti83_102.rom", "TI-83 Rom v1.02"); // ?? is this size correct? var ti83_103 = File("8399E384804D8D29866CAA4C8763D7A61946A467", 262144, "ti83_103.rom", "TI-83 Rom v1.03"); // ?? is this size correct? diff --git a/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj b/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj index 07fb3f1ede..4b76b90896 100644 --- a/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj +++ b/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj @@ -357,6 +357,10 @@ + + + + A7800Hawk.cs @@ -537,8 +541,8 @@ - - + + @@ -1005,6 +1009,7 @@ + PCEngine.cs @@ -1309,6 +1314,8 @@ + + @@ -1326,4 +1333,4 @@ --> - \ No newline at end of file + diff --git a/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.IEmulator.cs b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.IEmulator.cs index 6272a42805..50e6f2783c 100644 --- a/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.IEmulator.cs +++ b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.IEmulator.cs @@ -13,6 +13,7 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk //Maria related variables public int cycle; public int cpu_cycle; + public int m6532_cycle; public bool cpu_is_haltable; public bool cpu_is_halted; public bool cpu_halt_pending; @@ -23,7 +24,15 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk public byte p2_state; public byte p1_fire; public byte p2_fire; + public byte p1_fire_2x; + public byte p2_fire_2x; public byte con_state; + public bool left_toggle; + public bool right_toggle; + public bool left_was_pressed; + public bool right_was_pressed; + public bool p1_is_2button; + public bool p2_is_2button; // there are 4 maria cycles in a CPU cycle (fast access, both NTSC and PAL) // if the 6532 or TIA are accessed (PC goes to one of those addresses) the next access will be slower by 1/2 a CPU cycle @@ -32,6 +41,7 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk public void FrameAdvance(IController controller, bool render, bool rendersound) { + Console.WriteLine("-----------------------FRAME-----------------------"); if (_tracer.Enabled) { cpu.TraceCallback = s => _tracer.Put(s); @@ -75,6 +85,14 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk tia.Execute(0); } + // tick the m6532 timer, which is still active although not recommended to use + m6532_cycle++; + if (m6532_cycle== 4) + { + m6532.Timer.Tick(); + m6532_cycle = 0; + } + if (cpu_cycle <= (2 + (slow_access ? 1 : 0))) { cpu_is_haltable = true; @@ -149,6 +167,10 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk p2_state = _controllerDeck.ReadPort2(controller); p1_fire = _controllerDeck.ReadFire1(controller); p2_fire = _controllerDeck.ReadFire2(controller); + p1_fire_2x = _controllerDeck.ReadFire1_2x(controller); + p2_fire_2x = _controllerDeck.ReadFire2_2x(controller); + p1_is_2button = _controllerDeck.Is_2_button1(controller); + p2_is_2button = _controllerDeck.Is_2_button2(controller); } public void GetConsoleState(IController controller) @@ -157,12 +179,34 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk if (controller.IsPressed("Right Difficulty")) { - result |= (1 << 7); + if (!right_was_pressed) + { + right_toggle = !right_toggle; + } + right_was_pressed = true; + result |= (byte)((right_toggle ? 1 : 0) << 7); } + else + { + right_was_pressed = false; + result |= (byte)((right_toggle ? 1 : 0) << 7); + } + if (controller.IsPressed("Left Difficulty")) { - result |= (1 << 6); + if (!left_was_pressed) + { + left_toggle = !left_toggle; + } + left_was_pressed = true; + result |= (byte)((left_toggle ? 1 : 0) << 6); } + else + { + left_was_pressed = false; + result |= (byte)((left_toggle ? 1 : 0) << 6); + } + if (!controller.IsPressed("Pause")) { result |= (1 << 3); diff --git a/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.IMemoryDomains.cs b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.IMemoryDomains.cs index cdda3798f3..551b4d5be1 100644 --- a/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.IMemoryDomains.cs +++ b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.IMemoryDomains.cs @@ -23,10 +23,10 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk 1), new MemoryDomainDelegate( "TIA Registers", - TIA_regs.Length, + 0x20, MemoryDomain.Endian.Little, - addr => TIA_regs[addr], - (addr, value) => TIA_regs[addr] = value, + addr => tia.ReadMemory((ushort)addr,true), + (addr, value) => tia.WriteMemory((ushort)addr, value, true), 1), new MemoryDomainDelegate( "Maria Registers", @@ -46,16 +46,16 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk "Ram Block 0", 0xB0, MemoryDomain.Endian.Little, - addr => RAM[addr-0x840], - (addr, value) => RAM[addr-0x840] = value, + addr => RAM[addr+0x840], + (addr, value) => RAM[addr+0x840] = value, 1 ), new MemoryDomainDelegate( "Ram Block 1", 0xB0, MemoryDomain.Endian.Little, - addr => RAM[addr-0x940], - (addr, value) => RAM[addr-0x940] = value, + addr => RAM[addr+0x940], + (addr, value) => RAM[addr+0x940] = value, 1 ), new MemoryDomainDelegate( diff --git a/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.IStatable.cs b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.IStatable.cs index 6c5b9f7dbc..deabc35700 100644 --- a/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.IStatable.cs +++ b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.IStatable.cs @@ -51,6 +51,7 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk tia.SyncState(ser); maria.SyncState(ser); m6532.SyncState(ser); + mapper.SyncState(ser); ser.BeginSection("Atari7800"); ser.Sync("core", ref core, false); @@ -62,7 +63,6 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk ser.Sync("A7800_control_register", ref A7800_control_register); ser.Sync("_isPAL", ref _isPAL); - ser.Sync("TIA_regs", ref TIA_regs, false); ser.Sync("Maria_regs", ref Maria_regs, false); ser.Sync("RAM", ref RAM, false); ser.Sync("RAM_6532", ref RAM_6532, false); @@ -70,15 +70,23 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk ser.Sync("cycle", ref cycle); ser.Sync("cpu_cycle", ref cpu_cycle); + ser.Sync("m6532_cycle", ref m6532_cycle); ser.Sync("cpu_is_haltable", ref cpu_is_haltable); ser.Sync("cpu_is_halted", ref cpu_is_halted); ser.Sync("cpu_halt_pending", ref cpu_halt_pending); ser.Sync("cpu_resume_pending", ref cpu_resume_pending); ser.Sync("slow_access", ref slow_access); + ser.Sync("small flag", ref small_flag); + ser.Sync("pal kara", ref PAL_Kara); + ser.Sync("Cart RAM", ref cart_RAM); + ser.Sync("pokey", ref pokey); + ser.Sync("left_toggle", ref left_toggle); + ser.Sync("right_toggle", ref right_toggle); + ser.Sync("left_was_pressed", ref left_was_pressed); + ser.Sync("right_was_pressed", ref right_was_pressed); - - ser.EndSection(); + ser.EndSection(); } } } diff --git a/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.cs b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.cs index 848e740291..dcf2f6c921 100644 --- a/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.cs +++ b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.cs @@ -3,6 +3,7 @@ using BizHawk.Common.BufferExtensions; using BizHawk.Emulation.Common; using BizHawk.Emulation.Cores.Components.M6502; +using BizHawk.Common.NumberExtensions; namespace BizHawk.Emulation.Cores.Atari.A7800Hawk { @@ -22,7 +23,6 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk public byte A7800_control_register; // memory domains - public byte[] TIA_regs = new byte[0x20]; public byte[] Maria_regs = new byte[0x20]; public byte[] RAM = new byte[0x1000]; public byte[] RAM_6532 = new byte[0x80]; @@ -37,16 +37,20 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk public string s_mapper; public MapperBase mapper; + public bool small_flag = false; + public bool PAL_Kara = false; + public int cart_RAM = 0; + public bool pokey = false; private readonly ITraceable _tracer; public MOS6502X cpu; public Maria maria; - private bool _isPAL; + public bool _isPAL; public M6532 m6532; public TIA tia; - public A7800Hawk(CoreComm comm, GameInfo game, byte[] rom, string gameDbFn) + public A7800Hawk(CoreComm comm, GameInfo game, byte[] rom, string gameDbFn, object settings, object syncSettings) { var ser = new BasicServiceProvider(this); @@ -70,16 +74,24 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk CoreComm = comm; + _settings = (A7800Settings)settings ?? new A7800Settings(); + _syncSettings = (A7800SyncSettings)syncSettings ?? new A7800SyncSettings(); + _controllerDeck = new A7800HawkControllerDeck(_syncSettings.Port1, _syncSettings.Port2); byte[] highscoreBios = comm.CoreFileProvider.GetFirmware("A78", "Bios_HSC", false, "Some functions may not work without the high score BIOS."); byte[] palBios = comm.CoreFileProvider.GetFirmware("A78", "Bios_PAL", false, "The game will not run if the correct region BIOS is not available."); byte[] ntscBios = comm.CoreFileProvider.GetFirmware("A78", "Bios_NTSC", false, "The game will not run if the correct region BIOS is not available."); + byte[] header = new byte[128]; + bool is_header = false; + if (rom.Length % 1024 == 128) { - Console.WriteLine("Trimming 128 byte .a78 header..."); + Console.WriteLine("128 byte header detected"); byte[] newrom = new byte[rom.Length - 128]; + is_header = true; + Buffer.BlockCopy(rom, 0, header, 0, 128); Buffer.BlockCopy(rom, 128, newrom, 0, newrom.Length); rom = newrom; } @@ -107,11 +119,77 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk s_mapper = dict["board"]; } else + { throw new Exception("No Board selected for this game"); + } + + // check if the game uses pokey or RAM + if (dict.ContainsKey("RAM")) + { + int.TryParse(dict["RAM"], out cart_RAM); + Console.WriteLine(cart_RAM); + } + + if (dict.ContainsKey("Pokey")) + { + bool.TryParse(dict["Pokey"], out pokey); + } + + // some games will not function with the high score bios + // if such a game is being played, tell the user and disable it + if (dict.ContainsKey("No_HS")) + { + bool no_hs; + bool.TryParse(dict["No_HS"], out no_hs); + + if (no_hs) + { + Console.WriteLine("This game is incompatible with the High Score BIOS, disabling it"); + highscoreBios = null; + } + } + } + else if (is_header) + { + Console.WriteLine("ROM not in DB, inferring mapper info from header"); + + byte cart_1 = header[0x35]; + byte cart_2 = header[0x36]; + + _isPAL = (header[0x39] > 0) ? true : false; + + if (cart_2.Bit(1)) + { + if (cart_2.Bit(3)) + { + s_mapper = "2"; + } + else + { + s_mapper = "1"; + } + } + else + { + s_mapper = "0"; + } + } else { - throw new Exception("ROM not in gamedb"); + throw new Exception("ROM not in gamedb and has no header"); + } + + // some games that use the Super Game mapper only have 4 banks, so let's set a flag to limit bank size + if (rom.Length < 0x14000) + { + small_flag = true; + + // additionally, PAL Karateka has bank 6 (actually 2) at 0x4000 + if (rom.HashMD5()=="5E0A1E832BBCEA6FACB832FDE23A440A") + { + PAL_Kara = true; + } } Reset_Mapper(s_mapper); @@ -131,6 +209,7 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk maria._frameHz = 50; maria._screen_width = 320; maria._screen_height = 313; + maria._vblanklines = 20; maria._palette = PALPalette; } else @@ -138,6 +217,7 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk maria._frameHz = 60; maria._screen_width = 320; maria._screen_height = 263; + maria._vblanklines = 20; maria._palette = NTSCPalette; } @@ -171,7 +251,6 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk maria.Reset(); m6532.Reset(); - TIA_regs = new byte[0x20]; Maria_regs = new byte[0x20]; RAM = new byte[0x1000]; @@ -185,10 +264,26 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk private void Reset_Mapper(string m) { - if (m=="0") + if (m == "0") { mapper = new MapperDefault(); } + if (m == "1") + { + mapper = new MapperSG(); + } + if (m == "2") + { + mapper = new MapperSGE(); + } + if (m == "3") + { + mapper = new MapperF18(); + } + if (m == "4") + { + mapper = new MapperRampage(); + } mapper.Core = this; } @@ -197,93 +292,96 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk * MariaTables.cs * * Palette tables for the Maria class. - * All derived from Dan Boris' 7800/MAME code. + * PAL derived from Dan Boris' 7800/MAME code. * - * Copyright © 2004 Mike Murphy + * PAL Table: Copyright © 2004 Mike Murphy * + * NTSC Table Source: http://atariage.com/forums/topic/95498-7800-color-palette-in-mess/?p=1174461 + * + * */ public static readonly int[] NTSCPalette = { - 0x000000, 0x1c1c1c, 0x393939, 0x595959, // Grey - 0x797979, 0x929292, 0xababab, 0xbcbcbc, - 0xcdcdcd, 0xd9d9d9, 0xe6e6e6, 0xececec, - 0xf2f2f2, 0xf8f8f8, 0xffffff, 0xffffff, + 0x000000, 0x2e2e2e, 0x3c3c3c, 0x595959, + 0x777777, 0x838383, 0xa0a0a0, 0xb7b7b7, + 0xcdcdcd, 0xd8d8d8, 0xdddddd, 0xe0e0e0, + 0xeaeaea, 0xf0f0f0, 0xf6f6f6, 0xffffff, - 0x391701, 0x5e2304, 0x833008, 0xa54716, // Gold - 0xc85f24, 0xe37820, 0xff911d, 0xffab1d, - 0xffc51d, 0xffce34, 0xffd84c, 0xffe651, - 0xfff456, 0xfff977, 0xffff98, 0xffff98, + 0x412000, 0x542800, 0x763706, 0x984f0f, + 0xbb6818, 0xd78016, 0xff911d, 0xffab1d, + 0xffc51d, 0xffd03b, 0xffd84c, 0xffe651, + 0xfff456, 0xfff977, 0xffff98, 0xffffab, - 0x451904, 0x721e11, 0x9f241e, 0xb33a20, // Orange - 0xc85122, 0xe36920, 0xff811e, 0xff8c25, - 0xff982c, 0xffae38, 0xffc545, 0xffc559, - 0xffc66d, 0xffd587, 0xffe4a1, 0xffe4a1, + 0x451904, 0x721e11, 0x9f241e, 0xb33a20, + 0xc85122, 0xe36920, 0xfc811e, 0xff8c25, + 0xff982c, 0xffae38, 0xffc455, 0xffc559, + 0xffc66d, 0xffd587, 0xffe4a1, 0xffe6ab, - 0x4a1704, 0x7e1a0d, 0xb21d17, 0xc82119, // Red Orange - 0xdf251c, 0xec3b38, 0xfa5255, 0xfc6161, - 0xff706e, 0xff7f7e, 0xff8f8f, 0xff9d9e, - 0xffabad, 0xffb9bd, 0xffc7ce, 0xffc7ce, + 0x5f1f0e, 0x7a240d, 0x9c2c0f, 0xb02f0e, + 0xbf3624, 0xd34e2a, 0xe7623e, 0xf36e4a, + 0xfd7854, 0xff8a6a, 0xff987c, 0xffa48b, + 0xffb39e, 0xffc2b2, 0xffd0c3, 0xffdad0, - 0x050568, 0x3b136d, 0x712272, 0x8b2a8c, // Pink - 0xa532a6, 0xb938ba, 0xcd3ecf, 0xdb47dd, - 0xea51eb, 0xf45ff5, 0xfe6dff, 0xfe7afd, - 0xff87fb, 0xff95fd, 0xffa4ff, 0xffa4ff, + 0x4a1704, 0x7e1a0d, 0xb21d17, 0xc82119, + 0xdf251c, 0xec3b38, 0xfa5255, 0xfc6161, + 0xff7063, 0xff7f7e, 0xff8f8f, 0xff9d9e, + 0xffabad, 0xffb9bd, 0xffc7ce, 0xffcade, - 0x280479, 0x400984, 0x590f90, 0x70249d, // Purple - 0x8839aa, 0xa441c3, 0xc04adc, 0xd054ed, - 0xe05eff, 0xe96dff, 0xf27cff, 0xf88aff, - 0xff98ff, 0xfea1ff, 0xfeabff, 0xfeabff, + 0x490136, 0x66014b, 0x80035f, 0x951874, + 0xaa2d89, 0xba3d99, 0xca4da9, 0xd75ab6, + 0xe467c3, 0xef72ce, 0xfb7eda, 0xff8de1, + 0xff9de5, 0xffa5e7, 0xffafea, 0xffb8ec, - 0x35088a, 0x420aad, 0x500cd0, 0x6428d0, // Purple Blue - 0x7945d0, 0x8d4bd4, 0xa251d9, 0xb058ec, - 0xbe60ff, 0xc56bff, 0xcc77ff, 0xd183ff, - 0xd790ff, 0xdb9dff, 0xdfaaff, 0xdfaaff, + 0x48036c, 0x5c0488, 0x650d91, 0x7b23a7, + 0x933bbf, 0x9d45c9, 0xa74fd3, 0xb25ade, + 0xbd65e9, 0xc56df1, 0xce76fa, 0xd583ff, + 0xda90ff, 0xde9cff, 0xe2a9ff, 0xe6b6ff, - 0x051e81, 0x0626a5, 0x082fca, 0x263dd4, // Blue1 - 0x444cde, 0x4f5aee, 0x5a68ff, 0x6575ff, + 0x051e81, 0x0626a5, 0x082fca, 0x263dd4, + 0x444cde, 0x4f5aec, 0x5a68ff, 0x6575ff, 0x7183ff, 0x8091ff, 0x90a0ff, 0x97a9ff, - 0x9fb2ff, 0xafbeff, 0xc0cbff, 0xc0cbff, + 0x9fb2ff, 0xafbeff, 0xc0cbff, 0xcdd3ff, - 0x0c048b, 0x2218a0, 0x382db5, 0x483ec7, // Blue2 - 0x584fda, 0x6159ec, 0x6b64ff, 0x7a74ff, - 0x8a84ff, 0x918eff, 0x9998ff, 0xa5a3ff, - 0xb1aeff, 0xb8b8ff, 0xc0c2ff, 0xc0c2ff, + 0x0b0779, 0x201c8e, 0x3531a3, 0x4642b4, + 0x5753c5, 0x615dcf, 0x6d69db, 0x7b77e9, + 0x8985f7, 0x918dff, 0x9c98ff, 0xa7a4ff, + 0xb2afff, 0xbbb8ff, 0xc3c1ff, 0xd3d1ff, - 0x1d295a, 0x1d3876, 0x1d4892, 0x1c5cac, // Light Blue - 0x1c71c6, 0x3286cf, 0x489bd9, 0x4ea8ec, + 0x1d295a, 0x1d3876, 0x1d4892, 0x1d5cac, + 0x1d71c6, 0x3286cf, 0x489bd9, 0x4ea8ec, 0x55b6ff, 0x70c7ff, 0x8cd8ff, 0x93dbff, - 0x9bdfff, 0xafe4ff, 0xc3e9ff, 0xc3e9ff, + 0x9bdfff, 0xafe4ff, 0xc3e9ff, 0xcfedff, - 0x2f4302, 0x395202, 0x446103, 0x417a12, // Turquoise - 0x3e9421, 0x4a9f2e, 0x57ab3b, 0x5cbd55, - 0x61d070, 0x69e27a, 0x72f584, 0x7cfa8d, - 0x87ff97, 0x9affa6, 0xadffb6, 0xadffb6, + 0x014b59, 0x015d6e, 0x016f84, 0x01849c, + 0x0199b5, 0x01abca, 0x01bcde, 0x01d0f5, + 0x1adcff, 0x3ee1ff, 0x64e7ff, 0x76eaff, + 0x8bedff, 0x9aefff, 0xb1f3ff, 0xc7f6ff, - 0x0a4108, 0x0d540a, 0x10680d, 0x137d0f, // Green Blue - 0x169212, 0x19a514, 0x1cb917, 0x1ec919, - 0x21d91b, 0x47e42d, 0x6ef040, 0x78f74d, - 0x83ff5b, 0x9aff7a, 0xb2ff9a, 0xb2ff9a, + 0x004800, 0x005400, 0x036b03, 0x0e760e, + 0x188018, 0x279227, 0x36a436, 0x4eb94e, + 0x51cd51, 0x72da72, 0x7ce47c, 0x85ed85, + 0xa2ffa2, 0xb5ffb5, 0xc8ffc8, 0xd0ffd0, - 0x04410b, 0x05530e, 0x066611, 0x077714, // Green - 0x088817, 0x099b1a, 0x0baf1d, 0x48c41f, - 0x86d922, 0x8fe924, 0x99f927, 0xa8fc41, - 0xb7ff5b, 0xc9ff6e, 0xdcff81, 0xdcff81, + 0x164000, 0x1c5300, 0x236600, 0x287800, + 0x2e8c00, 0x3a980c, 0x47a519, 0x51af23, + 0x5cba2e, 0x71cf43, 0x85e357, 0x8deb5f, + 0x97f569, 0xa4ff97, 0xb9ff97, 0xb9ff97, - 0x02350f, 0x073f15, 0x0c4a1c, 0x2d5f1e, // Yellow Green - 0x4f7420, 0x598324, 0x649228, 0x82a12e, - 0xa1b034, 0xa9c13a, 0xb2d241, 0xc4d945, - 0xd6e149, 0xe4f04e, 0xf2ff53, 0xf2ff53, + 0x2c3500, 0x384400, 0x445200, 0x495600, + 0x607100, 0x6c7f00, 0x798d0a, 0x8b9f1c, + 0x9eb22f, 0xabbf3c, 0xb8cc49, 0xc2d653, + 0xcde153, 0xdbef6c, 0xe8fc79, 0xf2ffab, - 0x263001, 0x243803, 0x234005, 0x51541b, // Orange Green - 0x806931, 0x978135, 0xaf993a, 0xc2a73e, - 0xd5b543, 0xdbc03d, 0xe1cb38, 0xe2d836, - 0xe3e534, 0xeff258, 0xfbff7d, 0xfbff7d, + 0x463a09, 0x4d3f09, 0x544509, 0x6c5809, + 0x907609, 0xab8b0a, 0xc1a120, 0xd0b02f, + 0xdebe3d, 0xe6c645, 0xedcd4c, 0xf6da65, + 0xfde67d, 0xfff2a2, 0xfff9c5, 0xfff9d4, - 0x401a02, 0x581f05, 0x702408, 0x8d3a13, // Light Orange - 0xab511f, 0xb56427, 0xbf7730, 0xd0853a, + 0x401a02, 0x581f05, 0x702408, 0x8d3a13, + 0xab511f, 0xb56427, 0xbf7730, 0xd0853a, 0xe19344, 0xeda04e, 0xf9ad58, 0xfcb75c, - 0xffc160, 0xffc671, 0xffcb83, 0xffcb83 + 0xffc160, 0xffc671, 0xffcb83, 0xffd498 }; public static readonly int[] PALPalette = diff --git a/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800HawkControllerDeck.cs b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800HawkControllerDeck.cs index 950377081b..3698015579 100644 --- a/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800HawkControllerDeck.cs +++ b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800HawkControllerDeck.cs @@ -70,6 +70,26 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk return Port2.ReadFire(c); } + public byte ReadFire1_2x(IController c) + { + return Port1.ReadFire2x(c); + } + + public byte ReadFire2_2x(IController c) + { + return Port2.ReadFire2x(c); + } + + public bool Is_2_button1(IController c) + { + return Port1.Is_2_button(c); + } + + public bool Is_2_button2(IController c) + { + return Port2.Is_2_button(c); + } + public ControllerDefinition Definition { get; } public void SyncState(Serializer ser) diff --git a/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800HawkControllers.cs b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800HawkControllers.cs index ab203c3011..cdf1040ffc 100644 --- a/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800HawkControllers.cs +++ b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800HawkControllers.cs @@ -9,7 +9,7 @@ using BizHawk.Emulation.Common; namespace BizHawk.Emulation.Cores.Atari.A7800Hawk { /// - /// Represents a controller plugged into a controller port on the intellivision + /// Represents a controller plugged into a controller port on the A7800 /// public interface IPort { @@ -17,6 +17,10 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk byte ReadFire(IController c); + byte ReadFire2x(IController c); + + bool Is_2_button(IController c); + ControllerDefinition Definition { get; } void SyncState(Serializer ser); @@ -42,10 +46,20 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk } public byte ReadFire(IController c) + { + return 0x80; + } + + public byte ReadFire2x(IController c) { return 0; } + public bool Is_2_button(IController c) + { + return false; + } + public ControllerDefinition Definition { get; } public void SyncState(Serializer ser) @@ -101,8 +115,17 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk return result; } - public ControllerDefinition Definition { get; } + public byte ReadFire2x(IController c) + { + return 0; // only applicable for 2 button mode + } + public bool Is_2_button(IController c) + { + return false; + } + + public ControllerDefinition Definition { get; } public void SyncState(Serializer ser) { @@ -122,4 +145,89 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk 0x0, // Right }; } + + [DisplayName("ProLine Controller")] + public class ProLineController : IPort + { + public ProLineController(int portNum) + { + PortNum = portNum; + Definition = new ControllerDefinition + { + BoolButtons = BaseDefinition + .Select(b => "P" + PortNum + " " + b) + .ToList() + }; + } + + public int PortNum { get; } + + public byte Read(IController c) + { + byte result = 0xF; + for (int i = 0; i < 4; i++) + { + if (c.IsPressed(Definition.BoolButtons[i])) + { + result -= (byte)(1 << i); + } + } + + if (PortNum == 1) + { + result = (byte)(result << 4); + } + + return result; + } + + public byte ReadFire(IController c) + { + byte result = 0x80; + if (c.IsPressed(Definition.BoolButtons[4]) || c.IsPressed(Definition.BoolButtons[5])) + { + result = 0x00; // zero means fire is pressed + } + return result; + } + + public byte ReadFire2x(IController c) + { + byte result = 0; + if (c.IsPressed(Definition.BoolButtons[4])) + { + result = 0x80; + } + if (c.IsPressed(Definition.BoolButtons[5])) + { + result |= 0x40; + } + return result; + } + + public bool Is_2_button(IController c) + { + return true; + } + + public ControllerDefinition Definition { get; } + + public void SyncState(Serializer ser) + { + // Nothing todo, I think + } + + private static readonly string[] BaseDefinition = + { + "U", "D", "L", "R", "Fire", "Fire2" + }; + + private static byte[] HandControllerButtons = + { + 0x0, // UP + 0x0, // Down + 0x0, // Left + 0x0, // Right + }; + } } diff --git a/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/M6532.cs b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/M6532.cs index 74a5209996..6ead2370e3 100644 --- a/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/M6532.cs +++ b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/M6532.cs @@ -1,4 +1,5 @@ using BizHawk.Common; +using System; namespace BizHawk.Emulation.Cores.Atari.A7800Hawk { @@ -8,9 +9,10 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk public A7800Hawk Core { get; set; } - private byte _ddRa = 0x00; - private byte _ddRb = 0x00; - private byte _outputA = 0x00; + public byte _ddRa = 0x00; + public byte _ddRb = 0x00; + public byte _outputA = 0x00; + public byte _outputB = 0x00; public TimerData Timer; @@ -52,9 +54,12 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk if (registerAddr == 0x02) { + Core._islag = false; + // Read Output reg B byte temp = Core.con_state; temp = (byte)(temp & ~_ddRb); + temp = (byte)(temp + (_outputB & _ddRb)); return temp; } @@ -166,7 +171,7 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk else if (registerAddr == 0x02) { // Write Output reg B - // But is read only + _outputB = value; } else if (registerAddr == 0x03) { @@ -187,7 +192,8 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk _ddRa = 0x00; _ddRb = 0x00; _outputA = 0x00; - } + _outputB = 0x00; + } public void SyncState(Serializer ser) { @@ -195,6 +201,7 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk ser.Sync("ddra", ref _ddRa); ser.Sync("ddrb", ref _ddRb); ser.Sync("OutputA", ref _outputA); + ser.Sync("OutputB", ref _outputB); Timer.SyncState(ser); ser.EndSection(); } diff --git a/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/Mappers/MapperDefault.cs b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/Mappers/MapperDefault.cs index 5260bdcb7f..44c0513abf 100644 --- a/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/Mappers/MapperDefault.cs +++ b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/Mappers/MapperDefault.cs @@ -38,9 +38,9 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk { return Core._rom[Core._rom.Length - (0x10000 - addr)]; } - else if (addr >= 0xF000 && !Core.A7800_control_register.Bit(2)) + else if (addr >= (0x10000-Core._bios.Length) && !Core.A7800_control_register.Bit(2)) { - return Core._bios[addr - 0xF000]; + return Core._bios[addr - (0x10000 - Core._bios.Length)]; } else { diff --git a/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/Mappers/MapperF18.cs b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/Mappers/MapperF18.cs new file mode 100644 index 0000000000..fa00abe0a9 --- /dev/null +++ b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/Mappers/MapperF18.cs @@ -0,0 +1,107 @@ +using BizHawk.Common; +using BizHawk.Common.NumberExtensions; +using System; + +namespace BizHawk.Emulation.Cores.Atari.A7800Hawk +{ + // Mapper only used by F-18 Hornet + public class MapperF18 : MapperBase + { + public byte bank = 0; + + public override byte ReadMemory(ushort addr) + { + if (addr >= 0x1000 && addr < 0x1800) + { + //could be hsbios RAM here + if (Core._hsbios != null) + { + return Core._hsram[addr - 0x1000]; + } + return 0xFF; + } + else if (addr < 0x4000) + { + // could be either RAM mirror or ROM + if (addr >= 0x3000 && Core._hsbios != null) + { + return Core._hsbios[addr - 0x3000]; + } + else + { + return Core.RAM[0x800 + addr & 0x7FF]; + } + } + else + { + // cartridge and other OPSYS + if (addr >= (0x10000 - Core._bios.Length) && !Core.A7800_control_register.Bit(2)) + { + return Core._bios[addr - (0x10000 - Core._bios.Length)]; + } + else + { + if (addr >= 0x8000) + { + // top 32k is fixed + return Core._rom[Core._rom.Length - (0x10000 - addr)]; + } + else + { + // return whichever extra 16k bank is swapped in + int temp_addr = addr - 0x4000; + + return Core._rom[temp_addr + bank * 0x4000]; + } + } + } + } + + public override byte PeekMemory(ushort addr) + { + return ReadMemory(addr); + } + + public override void WriteMemory(ushort addr, byte value) + { + if (addr >= 0x1000 && addr < 0x1800) + { + //could be hsbios RAM here + if (Core._hsbios != null) + { + Core._hsram[addr - 0x1000] = value; + } + } + else if (addr < 0x4000) + { + // could be either RAM mirror or ROM + if (addr >= 0x3000 && Core._hsbios != null) + { + } + else + { + Core.RAM[0x800 + addr & 0x7FF] = value; + } + } + else + { + // cartridge and other OPSYS + if (addr == 0x8000) // might be other addresses, but only 0x8000 is used + { + bank = (byte)(value & 3); + bank -= 1; + } + } + } + + public override void PokeMemory(ushort addr, byte value) + { + WriteMemory(addr, value); + } + + public override void SyncState(Serializer ser) + { + ser.Sync("Bank", ref bank); + } + } +} diff --git a/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/Mappers/MapperRampage.cs b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/Mappers/MapperRampage.cs new file mode 100644 index 0000000000..bd9d342f33 --- /dev/null +++ b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/Mappers/MapperRampage.cs @@ -0,0 +1,133 @@ +using BizHawk.Common; +using BizHawk.Common.NumberExtensions; +using System; + +namespace BizHawk.Emulation.Cores.Atari.A7800Hawk +{ + // Mapper only used by Rampage and Double Dragon + public class MapperRampage : MapperBase + { + public byte bank = 0; + + public override byte ReadMemory(ushort addr) + { + if (addr >= 0x1000 && addr < 0x1800) + { + //could be hsbios RAM here + if (Core._hsbios != null) + { + return Core._hsram[addr - 0x1000]; + } + return 0xFF; + } + else if (addr < 0x4000) + { + // could be either RAM mirror or ROM + if (addr >= 0x3000 && Core._hsbios != null) + { + return Core._hsbios[addr - 0x3000]; + } + else + { + return Core.RAM[0x800 + addr & 0x7FF]; + } + } + else + { + // cartridge and other OPSYS + if (addr >= (0x10000 - Core._bios.Length) && !Core.A7800_control_register.Bit(2)) + { + return Core._bios[addr - (0x10000 - Core._bios.Length)]; + } + else + { + /* + $4000 -$5fff second 8kb of bank 6 + $6000 -$7fff first 8kb of bank 6 + $8000 -$9fff second 8kb of bank 7 + $e000 -$ffff first 8kb of bank 7 + + $a000-$dfff Banked + */ + + if (addr >= 0x4000 && addr < 0x6000) + { + int temp_addr = addr - 0x4000; + + return Core._rom[6 * 0x4000 + 0x2000 + temp_addr]; + } + else if (addr >= 0x6000 && addr < 0x8000) + { + int temp_addr = addr - 0x6000; + + return Core._rom[6 * 0x4000 + temp_addr]; + } + else if (addr >= 0x8000 && addr < 0xA000) + { + int temp_addr = addr - 0x8000; + + return Core._rom[7 * 0x4000 + 0x2000 + temp_addr]; + } + else if (addr >= 0xA000 && addr < 0xE000) + { + int temp_addr = addr - 0xA000; + + return Core._rom[bank * 0x4000 + temp_addr]; + } + else + { + int temp_addr = addr - 0xE000; + + return Core._rom[7 * 0x4000 + temp_addr]; + } + } + } + } + + public override byte PeekMemory(ushort addr) + { + return ReadMemory(addr); + } + + public override void WriteMemory(ushort addr, byte value) + { + if (addr >= 0x1000 && addr < 0x1800) + { + //could be hsbios RAM here + if (Core._hsbios != null) + { + Core._hsram[addr - 0x1000] = value; + } + } + else if (addr < 0x4000) + { + // could be either RAM mirror or ROM + if (addr >= 0x3000 && Core._hsbios != null) + { + } + else + { + Core.RAM[0x800 + addr & 0x7FF] = value; + } + } + else + { + // cartridge and other OPSYS + if (addr >= 0xFF80 && addr < 0xFF88) // might be other addresses, but only these are used + { + bank = (byte)(addr & 7); + } + } + } + + public override void PokeMemory(ushort addr, byte value) + { + WriteMemory(addr, value); + } + + public override void SyncState(Serializer ser) + { + ser.Sync("Bank", ref bank); + } + } +} diff --git a/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/Mappers/MapperSG.cs b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/Mappers/MapperSG.cs new file mode 100644 index 0000000000..7fe0fdb1e3 --- /dev/null +++ b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/Mappers/MapperSG.cs @@ -0,0 +1,170 @@ +using BizHawk.Common; +using BizHawk.Common.NumberExtensions; +using System; + +namespace BizHawk.Emulation.Cores.Atari.A7800Hawk +{ + // Default Bank Switching Mapper used by most games + public class MapperSG : MapperBase + { + public byte bank = 0; + public byte[] RAM = new byte[0x4000]; + + public override byte ReadMemory(ushort addr) + { + if (addr >= 0x1000 && addr < 0x1800) + { + //could be hsbios RAM here + if (Core._hsbios != null) + { + return Core._hsram[addr - 0x1000]; + } + return 0xFF; + } + else if (addr < 0x4000) + { + // could be either RAM mirror or ROM + if (addr >= 0x3000 && Core._hsbios != null) + { + return Core._hsbios[addr - 0x3000]; + } + else + { + return Core.RAM[0x800 + addr & 0x7FF]; + } + } + else + { + // cartridge and other OPSYS + if (addr >= (0x10000 - Core._bios.Length) && !Core.A7800_control_register.Bit(2)) + { + return Core._bios[addr - (0x10000 - Core._bios.Length)]; + } + else + { + if (addr >= 0xC000) + { + // bank 7 is fixed + return Core._rom[Core._rom.Length - (0x10000 - addr)]; + } + else if (addr >= 0x8000) + { + // return whatever bank is there + int temp_addr = addr - 0x8000; + return Core._rom[temp_addr + bank * 0x4000]; + } + else + { + if (Core.cart_RAM == 0 && !Core.pokey) + { + // return bank 6 + int temp_addr = addr - 0x4000; + + if (!Core.small_flag) + { + return Core._rom[temp_addr + 6 * 0x4000]; + } + else + { + if (Core.PAL_Kara) + { + return Core._rom[temp_addr + 2 * 0x4000]; + } + else + { + // Should never get here, but in case we do just return FF + return 0xFF; + } + } + } + else if (Core.cart_RAM > 0) + { + // return RAM + if (Core.cart_RAM==8 && addr >= 0x6000) + { + return RAM[addr - 0x6000]; + } + else if (Core.cart_RAM==16) + { + return RAM[addr - 0x4000]; + } + else + { + // this would coorespond to reading from 0x4000-0x5FFF with only 8k of RAM + // Let's just return FF for now + return 0xFF; + } + } + else + { + // pokey + return 0xFF; + } + } + } + } + } + + public override byte PeekMemory(ushort addr) + { + return ReadMemory(addr); + } + + public override void WriteMemory(ushort addr, byte value) + { + if (addr >= 0x1000 && addr < 0x1800) + { + //could be hsbios RAM here + if (Core._hsbios != null) + { + Core._hsram[addr - 0x1000] = value; + } + } + else if (addr < 0x4000) + { + // could be either RAM mirror or ROM + if (addr >= 0x3000 && Core._hsbios != null) + { + } + else + { + Core.RAM[0x800 + addr & 0x7FF] = value; + } + } + else + { + // cartridge and other OPSYS + if (addr>=0x8000) + { + bank = (byte)(value & (Core.small_flag ? 0x3 : 0x7)); + } + else if (Core.pokey) + { + + } + else if (Core.cart_RAM > 0) + { + if (Core.cart_RAM==8 && addr >= 0x6000) + { + RAM[addr - 0x6000] = value; + } + else if (Core.cart_RAM==16) + { + RAM[addr - 0x4000] = value; + } + } + } + } + + public override void PokeMemory(ushort addr, byte value) + { + WriteMemory(addr, value); + } + + public override void SyncState(Serializer ser) + { + ser.Sync("Bank", ref bank); + ser.Sync("RAM", ref RAM, false); + } + } +} diff --git a/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/Mappers/MapperSGE.cs b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/Mappers/MapperSGE.cs new file mode 100644 index 0000000000..a3f5f47e98 --- /dev/null +++ b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/Mappers/MapperSGE.cs @@ -0,0 +1,113 @@ +using BizHawk.Common; +using BizHawk.Common.NumberExtensions; +using System; + +namespace BizHawk.Emulation.Cores.Atari.A7800Hawk +{ + // Super Game mapper but with extra ROM at the start of the file + // Have to add 1 to bank number to get correct bank value + public class MapperSGE : MapperBase + { + public byte bank = 0; + + public override byte ReadMemory(ushort addr) + { + if (addr >= 0x1000 && addr < 0x1800) + { + //could be hsbios RAM here + if (Core._hsbios != null) + { + return Core._hsram[addr - 0x1000]; + } + return 0xFF; + } + else if (addr < 0x4000) + { + // could be either RAM mirror or ROM + if (addr >= 0x3000 && Core._hsbios != null) + { + return Core._hsbios[addr - 0x3000]; + } + else + { + return Core.RAM[0x800 + addr & 0x7FF]; + } + } + else + { + // cartridge and other OPSYS + if (addr >= (0x10000 - Core._bios.Length) && !Core.A7800_control_register.Bit(2)) + { + return Core._bios[addr - (0x10000 - Core._bios.Length)]; + } + else + { + if (addr >=0xC000) + { + // bank 7 is fixed + return Core._rom[Core._rom.Length - (0x10000 - addr)]; + } + else if (addr >= 0x8000) + { + // return whatever bank is there + // but remember we need to add 1 to adjust for the extra bank at the beginning + int temp_addr = addr - 0x8000; + return Core._rom[temp_addr + (bank + 1) * 0x4000]; + } + else + { + // return the 16k extra ROM (located at beginning of file) + int temp_addr = addr - 0x4000; + return Core._rom[temp_addr]; + } + } + } + } + + public override byte PeekMemory(ushort addr) + { + return ReadMemory(addr); + } + + public override void WriteMemory(ushort addr, byte value) + { + if (addr >= 0x1000 && addr < 0x1800) + { + //could be hsbios RAM here + if (Core._hsbios != null) + { + Core._hsram[addr - 0x1000] = value; + } + } + else if (addr < 0x4000) + { + // could be either RAM mirror or ROM + if (addr >= 0x3000 && Core._hsbios != null) + { + } + else + { + Core.RAM[0x800 + addr & 0x7FF] = value; + } + } + else + { + // cartridge and other OPSYS + if (addr>=0x8000) + { + bank = (byte)(value & 0x7); + } + } + } + + public override void PokeMemory(ushort addr, byte value) + { + WriteMemory(addr, value); + } + + public override void SyncState(Serializer ser) + { + ser.Sync("Bank", ref bank); + } + } +} diff --git a/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/Maria.cs b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/Maria.cs index 4f92b19ac4..377424577f 100644 --- a/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/Maria.cs +++ b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/Maria.cs @@ -1,5 +1,4 @@ using System; - using BizHawk.Emulation.Common; using BizHawk.Common.NumberExtensions; using BizHawk.Common; @@ -24,17 +23,21 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk public byte[] obj; // up to 32 bytes can compose one object } - // technically there is no limit on he number of graphics objects, but since dma is automatically killed + // technically there is no limit on the number of graphics objects, but since dma is automatically killed // at the end of a scanline, we have an effective limit - GFX_Object[] GFX_Objects = new GFX_Object[128]; + GFX_Object[,] GFX_Objects = new GFX_Object[2,128]; + + int GFX_index = 0; public int _frameHz = 60; public int _screen_width = 320; public int _screen_height = 263; + public int _vblanklines = 20; public int[] _vidbuffer; public int[] _palette; public int[] scanline_buffer = new int[320]; + public int[] bg_temp = new int[320]; // since BG color can be changed midscanline, we need to account for this here. public int[] GetVideoBuffer() { @@ -42,9 +45,9 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk } public int VirtualWidth => 320; - public int VirtualHeight => _screen_height; + public int VirtualHeight => _screen_height - _vblanklines; public int BufferWidth => 320; - public int BufferHeight => _screen_height; + public int BufferHeight => _screen_height - _vblanklines; public int BackgroundColor => unchecked((int)0xff000000); public int VsyncNumerator => _frameHz; public int VsyncDenominator => 1; @@ -71,7 +74,6 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk public int header_read_time = 8; // default for 4 byte headers (10 for 5 bytes ones) public int graphics_read_time = 3; // depends on content of graphics header public int DMA_phase_next; - public int base_scanline; public ushort display_zone_pointer; public int display_zone_counter; @@ -82,12 +84,12 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk public bool current_DLL_H16; public bool current_DLL_H8; - public int header_counter; - public int header_counter_max; - public int header_pointer; // since headers could be 4 or 5 bytes, we need a seperate pointer + public bool overrun_dma; + public bool global_write_mode; - // write mode is actually persistent but exists outside of the regs - public bool global_write_mode; + public int header_counter; + public int[] header_counter_max = new int [2]; + public int header_pointer; // since headers could be 4 or 5 bytes, we need a seperate pointer // each frame contains 263 scanlines // each scanline consists of 113.5 CPU cycles (fast access) which equates to 454 Maria cycles @@ -95,13 +97,13 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk public void RunFrame() { scanline = 0; - + global_write_mode = false; Core.Maria_regs[8] = 0x80; // indicates VBlank state // we start off in VBlank for 20 scanlines // at the end of vblank is a DMA to set up the display for the start of drawing // this is free time for the CPU to set up display lists - while (scanline < 19) + while (scanline < 20) { Core.RunCPUCycle(); cycle++; @@ -120,14 +122,11 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk // Since long shut down loads up the next zone, this basically loads up the DLL for the first zone sl_DMA_complete = false; do_dma = false; + Core.Maria_regs[8] = 0; // we have now left VBLank for (int i=0; i<454;i++) { - if (i<28) - { - // DMA doesn't start until 7 CPU cycles into a scanline - } - else if (i==28 && Core.Maria_regs[0x1C].Bit(6) && !Core.Maria_regs[0x1C].Bit(5)) + if(i==28 && Core.Maria_regs[0x1C].Bit(6) && !Core.Maria_regs[0x1C].Bit(5)) { Core.cpu_halt_pending = true; DMA_phase = DMA_START_UP; @@ -161,26 +160,20 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk scanline++; cycle = 0; do_dma = false; - Core.Maria_regs[8] = 0; // we have now left VBLank - base_scanline = 0; sl_DMA_complete = false; Core.cpu.RDY = true; // Now proceed with the remaining scanlines // the first one is a pre-render line, since we didn't actually put any data into the buffer yet - while (scanline < 263) - { - - if (cycle < 28) - { - // DMA doesn't start until 7 CPU cycles into a scanline - } - else if (cycle == 28 && Core.Maria_regs[0x1C].Bit(6) && !Core.Maria_regs[0x1C].Bit(5)) + while (scanline < _screen_height) + { + if (cycle == 28 && Core.Maria_regs[0x1C].Bit(6) && !Core.Maria_regs[0x1C].Bit(5)) { Core.cpu_halt_pending = true; DMA_phase = DMA_START_UP; DMA_phase_counter = 0; do_dma = true; + sl_DMA_complete = false; } else if (!sl_DMA_complete && do_dma) { @@ -194,6 +187,20 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk current_DLL_DLI = false; } + if (overrun_dma && sl_DMA_complete) + { + if (GFX_index == 1) + { + GFX_index = 0; + } + else + { + GFX_index = 1; + } + + overrun_dma = false; + } + if (DLI_countdown > 0) { DLI_countdown--; @@ -203,6 +210,28 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk } } + if (cycle > 133) + { + bg_temp[cycle - 134] = Core.Maria_regs[0]; + } + + + if (cycle == 453 && !sl_DMA_complete && do_dma && (DMA_phase == DMA_GRAPHICS || DMA_phase == DMA_HEADER)) + { + overrun_dma = true; + //Console.WriteLine(scanline); + if (current_DLL_offset == 0) + { + DMA_phase = DMA_SHUTDOWN_LAST; + } + else + { + DMA_phase = DMA_SHUTDOWN_OTHER; + } + + DMA_phase_counter = 0; + } + Core.RunCPUCycle(); cycle++; @@ -214,14 +243,23 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk // add the current graphics to the buffer draw_scanline(scanline - 21); } - //Console.Write("Scanline"); - //Console.WriteLine(scanline - 21); scanline++; cycle = 0; Core.tia._hsyncCnt = 0; Core.cpu.RDY = true; - do_dma = false; - sl_DMA_complete = false; + + // swap sacnline buffers + if (!overrun_dma) + { + if (GFX_index == 1) + { + GFX_index = 0; + } + else + { + GFX_index = 1; + } + } } } } @@ -261,7 +299,7 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk if (DMA_phase_counter==1) { header_counter++; - GFX_Objects[header_counter].addr = ReadMemory((ushort)(current_DLL_addr + header_pointer)); + GFX_Objects[GFX_index, header_counter].addr = ReadMemory((ushort)(current_DLL_addr + header_pointer)); header_pointer++; byte temp = ReadMemory((ushort)(current_DLL_addr + header_pointer)); // if there is no width, then we must have an extended header @@ -286,12 +324,12 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk else { // we are in 5 Byte header mode (i.e. using the character map) - GFX_Objects[header_counter].write_mode = temp.Bit(7); + GFX_Objects[GFX_index, header_counter].write_mode = temp.Bit(7); global_write_mode = temp.Bit(7); - GFX_Objects[header_counter].ind_mode = temp.Bit(5); + GFX_Objects[GFX_index, header_counter].ind_mode = temp.Bit(5); header_pointer++; temp = (byte)(ReadMemory((ushort)(current_DLL_addr + header_pointer))); - GFX_Objects[header_counter].addr |= (ushort)(temp << 8); + GFX_Objects[GFX_index, header_counter].addr |= (ushort)(temp << 8); header_pointer++; temp = ReadMemory((ushort)(current_DLL_addr + header_pointer)); int temp_w = (temp & 0x1F); // this is the 2's complement of width (for reasons that escape me) @@ -299,18 +337,18 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk if (temp_w == 0) { // important note here. In 5 byte mode, width 0 actually counts as 32 - GFX_Objects[header_counter].width = 32; + GFX_Objects[GFX_index, header_counter].width = 32; } else { temp_w = (temp_w - 1); temp_w = (0x1F - temp_w); - GFX_Objects[header_counter].width = (byte)(temp_w & 0x1F); + GFX_Objects[GFX_index, header_counter].width = (byte)(temp_w & 0x1F); } - GFX_Objects[header_counter].palette = (byte)((temp & 0xE0) >> 5); + GFX_Objects[GFX_index, header_counter].palette = (byte)((temp & 0xE0) >> 5); header_pointer++; - GFX_Objects[header_counter].h_pos = ReadMemory((ushort)(current_DLL_addr + header_pointer)); + GFX_Objects[GFX_index, header_counter].h_pos = ReadMemory((ushort)(current_DLL_addr + header_pointer)); header_pointer++; DMA_phase_next = DMA_GRAPHICS; @@ -323,21 +361,21 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk int temp_w = (temp & 0x1F); // this is the 2's complement of width (for reasons that escape me) temp_w = (temp_w - 1); temp_w = (0x1F - temp_w); - GFX_Objects[header_counter].width = (byte)(temp_w & 0x1F); + GFX_Objects[GFX_index, header_counter].width = (byte)(temp_w & 0x1F); - GFX_Objects[header_counter].palette = (byte)((temp & 0xE0) >> 5); + GFX_Objects[GFX_index, header_counter].palette = (byte)((temp & 0xE0) >> 5); header_pointer++; temp = (byte)(ReadMemory((ushort)(current_DLL_addr + header_pointer))); - GFX_Objects[header_counter].addr |= (ushort)(temp << 8); + GFX_Objects[GFX_index, header_counter].addr |= (ushort)(temp << 8); header_pointer++; - GFX_Objects[header_counter].h_pos = ReadMemory((ushort)(current_DLL_addr + header_pointer)); + GFX_Objects[GFX_index, header_counter].h_pos = ReadMemory((ushort)(current_DLL_addr + header_pointer)); header_pointer++; DMA_phase_next = DMA_GRAPHICS; - GFX_Objects[header_counter].write_mode = global_write_mode; + GFX_Objects[GFX_index, header_counter].write_mode = global_write_mode; - GFX_Objects[header_counter].ind_mode = false; + GFX_Objects[GFX_index, header_counter].ind_mode = false; header_read_time = 8; } @@ -358,37 +396,38 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk ushort addr_t = 0; // in 5 byte mode, we first have to check if we are in direct or indirect mode - if (GFX_Objects[header_counter].ind_mode) + if (GFX_Objects[GFX_index, header_counter].ind_mode) { int ch_size = 0; if (Core.Maria_regs[0x1C].Bit(4)) { - graphics_read_time = 9 * GFX_Objects[header_counter].width + 3; + graphics_read_time = 9 * GFX_Objects[GFX_index, header_counter].width; ch_size = 2; + GFX_Objects[GFX_index, header_counter].width *= 2; } else { - graphics_read_time = 6 * GFX_Objects[header_counter].width + 3; + graphics_read_time = 6 * GFX_Objects[GFX_index, header_counter].width; ch_size = 1; } // the address here is specified by CHAR_BASE maria registers - //ushort addr = (ushort)(GFX_Objects[header_counter].addr & 0xFF); - for (int i = 0; i < GFX_Objects[header_counter].width; i++) + // ushort addr = (ushort)(GFX_Objects[header_counter].addr & 0xFF); + for (int i = 0; i < GFX_Objects[GFX_index, header_counter].width; i++) { - addr_t = ReadMemory((ushort)(GFX_Objects[header_counter].addr + i)); + addr_t = ReadMemory((ushort)(GFX_Objects[GFX_index, header_counter].addr + i)); addr_t |= (ushort)((Core.Maria_regs[0x14] + current_DLL_offset) << 8); - if ((current_DLL_H16 && addr_t.Bit(12)) || (current_DLL_H8 && addr_t.Bit(11))) + if (((current_DLL_H16 && addr_t.Bit(12)) || (current_DLL_H8 && addr_t.Bit(11))) && (addr_t >= 0x8000)) { - if (i * ch_size < 32) + if (i * ch_size < 128) { - GFX_Objects[header_counter].obj[i * ch_size] = 0; + GFX_Objects[GFX_index, header_counter].obj[i * ch_size] = 0; } - if ((i * ch_size + 1 < 32) && (ch_size == 2)) + if ((i * ch_size + 1 < 128) && (ch_size == 2)) { - GFX_Objects[header_counter].obj[i * ch_size + 1] = 0; + GFX_Objects[GFX_index, header_counter].obj[i * ch_size + 1] = 0; } if (ch_size == 1) { @@ -398,36 +437,37 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk { graphics_read_time -= 9; } - + } else { - if (i * ch_size < 32) + if (i * ch_size < 128) { - GFX_Objects[header_counter].obj[i * ch_size] = ReadMemory(addr_t); + GFX_Objects[GFX_index, header_counter].obj[i * ch_size] = ReadMemory(addr_t); } - if ((i * ch_size + 1 < 32) && (ch_size == 2)) + if (((i * ch_size + 1) < 128) && (ch_size == 2)) { - GFX_Objects[header_counter].obj[i * ch_size + 1] = ReadMemory(addr_t); + GFX_Objects[GFX_index, header_counter].obj[i * ch_size + 1] = ReadMemory((ushort)(addr_t + 1)); } } } } else { - graphics_read_time = 3 * GFX_Objects[header_counter].width; + graphics_read_time = 3 * GFX_Objects[GFX_index, header_counter].width; - for (int i = 0; i < GFX_Objects[header_counter].width; i++) + for (int i = 0; i < GFX_Objects[GFX_index, header_counter].width; i++) { - addr_t = (ushort)(GFX_Objects[header_counter].addr + (current_DLL_offset << 8) + i); - if ((current_DLL_H16 && addr_t.Bit(12)) || (current_DLL_H8 && addr_t.Bit(11))) + addr_t = (ushort)(GFX_Objects[GFX_index, header_counter].addr + (current_DLL_offset << 8) + i); + + if (((current_DLL_H16 && addr_t.Bit(12)) || (current_DLL_H8 && addr_t.Bit(11))) && (addr_t >= 0x8000)) { - GFX_Objects[header_counter].obj[i] = 0; + GFX_Objects[GFX_index, header_counter].obj[i] = 0; graphics_read_time -= 3; } else { - GFX_Objects[header_counter].obj[i] = ReadMemory(addr_t); + GFX_Objects[GFX_index, header_counter].obj[i] = ReadMemory(addr_t); } } } @@ -448,7 +488,7 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk Core.cpu_resume_pending = true; sl_DMA_complete = true; current_DLL_offset -= 1; // this is reduced by one for each scanline, which changes where graphics are fetched - header_counter_max = header_counter; + header_counter_max[GFX_index] = header_counter; header_counter = -1; header_pointer = 0; return; @@ -471,10 +511,11 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk current_DLL_offset = (byte)(temp & 0xF); current_DLL_DLI = temp.Bit(7); + current_DLL_H16 = temp.Bit(6); current_DLL_H8 = temp.Bit(5); - header_counter_max = header_counter; + header_counter_max[GFX_index] = header_counter; header_counter = -1; header_pointer = 0; } @@ -490,70 +531,60 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk int local_palette; int index; int color; + int local_GFX_index; + + local_GFX_index = (GFX_index == 1) ? 0 : 1; // whatever the current index is, we use the opposite int disp_mode = Core.Maria_regs[0x1C] & 0x3; - int temp_bg = Core.Maria_regs[0]; - - for (int i = 0; i < 320; i++) { - scanline_buffer[i] = _palette[temp_bg]; + scanline_buffer[i] = _palette[bg_temp[i]]; } - for (int i = 0; i < header_counter_max; i++) + for (int i = 0; i < header_counter_max[local_GFX_index]; i++) { - local_start = GFX_Objects[i].h_pos; - local_palette = GFX_Objects[i].palette; + local_start = GFX_Objects[local_GFX_index, i].h_pos; + local_palette = GFX_Objects[local_GFX_index, i].palette; // the two different rendering paths are basically controlled by write mode - if (GFX_Objects[i].write_mode) - { - - } - else + if (GFX_Objects[local_GFX_index, i].write_mode) { if (disp_mode == 0) { - local_width = GFX_Objects[i].width; + local_width = GFX_Objects[local_GFX_index, i].width; for (int j = 0; j < local_width; j++) { - for (int k = 7; k >= 0; k--) + for (int k = 3; k >= 0; k--) { - index = local_start * 2 + j * 8 + (7 - k); + index = local_start * 2 + j * 4 + (3 - k); + + if (index > 511) + { + index -= 512; + } - if (index > 511) index -= 512; if (index < 320) { - color = GFX_Objects[i].obj[j]; + color = GFX_Objects[local_GFX_index, i].obj[j]; // this is now the color index (0-3) we choose from the palette - if (k>=6) + if (k >= 2) { - color = (color >> 6) & 0x3; - - } - else if (k>=4) - { - color = (color >> 4) & 0x3; - - } - else if (k>=2) - { - color = (color >> 2) & 0x3; + color = (((color >> 2) & 0x3) << 2) + ((color >> 6) & 0x3); } else { - color = color & 0x3; + color = ((color & 0x3) << 2) + ((color >> 4) & 0x3); } - - if (color != 0) // transparent - { - color = Core.Maria_regs[local_palette * 4 + color]; - // the top 4 bits from this are the color, the bottom 4 are the luminosity - // this is already conveniently arranged in the palette + if ((color != 0) && (color != 4) && (color != 8) && (color != 12)) // transparent + { + color = ((local_palette & 4) << 2) + color; + + color = Core.Maria_regs[color]; + scanline_buffer[index] = _palette[color]; } } @@ -562,53 +593,203 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk } else if (disp_mode == 2) // note: 1 is not used { - local_width = GFX_Objects[i].width; - // here the palette is determined by palette bit 2 only - // hence only palette 0 or 4 is available - local_palette = GFX_Objects[i].palette & 0x4; - - int temp_c0 = GFX_Objects[i].palette & 0x1; - int temp_c1 = GFX_Objects[i].palette & 0x2; + local_width = GFX_Objects[local_GFX_index, i].width; for (int j = 0; j < local_width; j++) { for (int k = 7; k >= 0; k--) { - color = (GFX_Objects[i].obj[j] >> k) & 1; + index = local_start * 4 + j * 8 + (7 - k); + + if (index > 511) + { + index -= 512; + } + + if (index < 320) + { + color = GFX_Objects[local_GFX_index, i].obj[j]; + + // this is now the color index (0-3) we choose from the palette + if (k >= 6) + { + color = ((color >> 6) & 0x2) + ((color >> 3) & 0x1); + } + else if (k >= 4) + { + color = ((color >> 5) & 0x2) + ((color >> 2) & 0x1); + + } + else if (k >= 2) + { + color = ((color >> 4) & 0x2) + ((color >> 1) & 0x1); + } + else + { + color = ((color >> 3) & 0x2) + (color & 0x1); + } + + if (color != 0) // transparent + { + color = ((local_palette & 4) << 2) + color; + + color = Core.Maria_regs[color]; + + scanline_buffer[index] = _palette[color]; + } + } + } + } + } + else + { + local_width = GFX_Objects[local_GFX_index, i].width; + + for (int j = 0; j < local_width; j++) + { + for (int k = 3; k >= 0; k--) + { + index = local_start * 2 + j * 4 + (3 - k); + + if (index > 511) + { + index -= 512; + } + + if (index < 320) + { + color = GFX_Objects[local_GFX_index, i].obj[j]; + int temp_color = color; + + // this is now the color index (0-3) we choose from the palette + if (k >= 3) + { + color = ((color >> 7) & 0x1); + temp_color = (local_palette & 4) + ((temp_color >> 2) & 3); + } + else if (k >= 2) + { + color = ((color >> 6) & 0x1); + temp_color = (local_palette & 4) + ((temp_color >> 2) & 3); + + } + else if (k >= 1) + { + color = ((color >> 5) & 0x1); + temp_color = (local_palette & 4) + (temp_color & 3); + } + else + { + color = ((color >> 4) & 0x1); + temp_color = (local_palette & 4) + (temp_color & 3); + } + + if (color != 0) // transparent + { + color = (temp_color << 2) + 2; + + color = Core.Maria_regs[color]; + + scanline_buffer[index] = _palette[color]; + } + } + } + } + } + } + else + { + if (disp_mode == 0) + { + local_width = GFX_Objects[local_GFX_index, i].width; + + for (int j = 0; j < local_width; j++) + { + for (int k = 7; k >= 0; k--) + { + index = local_start * 2 + j * 8 + (7 - k); + + if (index > 511) + { + index -= 512; + } + + if (index < 320) + { + color = GFX_Objects[local_GFX_index, i].obj[j]; + + // this is now the color index (0-3) we choose from the palette + if (k >= 6) + { + color = (color >> 6) & 0x3; + } + else if (k >= 4) + { + color = (color >> 4) & 0x3; + + } + else if (k >= 2) + { + color = (color >> 2) & 0x3; + } + else + { + color = color & 0x3; + } + + if (color != 0) // transparent + { + color = Core.Maria_regs[local_palette * 4 + color]; + + scanline_buffer[index] = _palette[color]; + } + } + } + } + } + else if (disp_mode == 2) // note: 1 is not used + { + local_width = GFX_Objects[local_GFX_index, i].width; + // here the palette is determined by palette bit 2 only + // hence only palette 0 or 4 is available + local_palette = GFX_Objects[local_GFX_index, i].palette & 0x4; + + int temp_c0 = GFX_Objects[local_GFX_index, i].palette & 0x1; + int temp_c1 = GFX_Objects[local_GFX_index, i].palette & 0x2; + + for (int j = 0; j < local_width; j++) + { + for (int k = 7; k >= 0; k--) + { + color = (GFX_Objects[local_GFX_index, i].obj[j] >> k) & 1; color = (color << 1) | ((k % 2 == 0) ? temp_c0 : temp_c1); index = local_start * 2 + j * 8 + (7 - k); if (index > 511) index -= 512; if (index < 320) { - color = Core.Maria_regs[local_palette + color]; - // the top 4 bits from this are the color, the bottom 4 are the luminosity - // this is already conveniently arranged in the palette scanline_buffer[index] = _palette[color]; } } } - } else { - local_width = GFX_Objects[i].width; + local_width = GFX_Objects[local_GFX_index, i].width; for (int j = 0; j < local_width; j++) { for (int k = 7; k >= 0; k--) { - color = (GFX_Objects[i].obj[j] >> k) & 1; + color = (GFX_Objects[local_GFX_index, i].obj[j] >> k) & 1; index = local_start * 2 + j * 8 + (7 - k); if (index > 511) index -= 512; if (index < 320 && color == 1) { color = Core.Maria_regs[local_palette * 4 + 2]; // automatically use index 2 here - // the top 4 bits from this are the color, the bottom 4 are the luminosity - // this is already conveniently arranged in the palette scanline_buffer[index] = _palette[color]; } } @@ -628,10 +809,13 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk { _vidbuffer = new int[VirtualWidth * VirtualHeight]; - for (int i = 0; i < 128; i++) + for (int j = 0; j < 2; j++) { - GFX_Objects[i].obj = new byte[32]; - } + for (int i = 0; i < 128; i++) + { + GFX_Objects[j, i].obj = new byte[128]; + } + } } // Most of the Maria state is captured in Maria Regs in the core @@ -641,7 +825,7 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk { ser.BeginSection("Maria"); - ser.Sync("global write mode", ref global_write_mode); + ser.Sync("GFX_index", ref GFX_index); ser.EndSection(); } diff --git a/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/MemoryMap.cs b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/MemoryMap.cs index 4eb62900b1..f8229d38c5 100644 --- a/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/MemoryMap.cs +++ b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/MemoryMap.cs @@ -35,7 +35,6 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk else { return tia.ReadMemory((ushort)(addr & 0x1F), false); - //return TIA_regs[addr & 0x1F]; // TODO: what to return here? } } else if ((addr & 0xFCE0) == 0x20) @@ -110,7 +109,6 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk } else { - TIA_regs[addr & 0x1F] = value; tia.WriteMemory((ushort)(addr & 0x1F), value, false); } } @@ -120,12 +118,20 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk { // register 8 is read only and controlled by Maria var temp = addr & 0x1F; + if (temp != 8) Maria_regs[temp] = value; if (temp == 4) // WSYNC cpu.RDY = false; - + /* + for (int i = 0; i < 0x20; i++) + { + Console.Write(Maria_regs[i]); + Console.Write(" "); + } + Console.WriteLine(maria.scanline); + */ } else { diff --git a/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/TIA_Sound/TIA.cs b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/TIA_Sound/TIA.cs index 0e964de66c..1a9b012e4b 100644 --- a/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/TIA_Sound/TIA.cs +++ b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/TIA_Sound/TIA.cs @@ -14,6 +14,8 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk private bool _doTicks; + private int _spf; + public int _hsyncCnt; private int _capChargeStart; private bool _capCharging; @@ -31,7 +33,7 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk _capChargeStart = 0; _capCharging = false; AudioClocks = 0; - + _spf = (Core.maria._frameHz > 55) ? 740 : 880; _doTicks = false; } @@ -92,34 +94,94 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk // inputs 0-3 are measured by a charging capacitor, these inputs are used with the paddles and the keyboard // Changing the hard coded value will change the paddle position. The range seems to be roughly 0-56000 according to values from stella // 6105 roughly centers the paddle in Breakout + + //INPT0-3 are used to read 2 button joysticks as well for the A7800 if (maskedAddr == 0x08) // INPT0 { - return 0; + if ((Core.m6532._outputB & 0x04) == 0 && (Core.m6532._ddRb & 0x04) == 0x04) + { + Core._islag = false; + return (byte)(Core.p1_fire_2x & 0x80); + } + else + { + return 0; + } } if (maskedAddr == 0x09) // INPT1 { - return 0; + if ((Core.m6532._outputB & 0x04) == 0 && (Core.m6532._ddRb & 0x04) == 0x04) + { + Core._islag = false; + return (byte)((Core.p1_fire_2x & 0x40)<<1); + } + else + { + return 0; + } } if (maskedAddr == 0x0A) // INPT2 { - return 0; + if ((Core.m6532._outputB & 0x10) == 0 && (Core.m6532._ddRb & 0x10) == 0x10) + { + Core._islag = false; + return (byte)(Core.p2_fire_2x & 0x80); + } + else + { + return 0; + } } if (maskedAddr == 0x0B) // INPT3 { - return 0; + if ((Core.m6532._outputB & 0x10) == 0 && (Core.m6532._ddRb & 0x10) == 0x10) + { + Core._islag = false; + return (byte)((Core.p2_fire_2x & 0x40)<<1); + } + else + { + return 0; + } } if (maskedAddr == 0x0C) // INPT4 { - return Core.p1_fire; + Core._islag = false; + + if (!Core.p1_is_2button) + { + return Core.p1_fire; + } + else if ((Core.m6532._outputB & 0x04) != 0 || (Core.m6532._ddRb & 0x04) != 0x04) + { + return Core.p1_fire; + } + else + { + return 0x80; + } } if (maskedAddr == 0x0D) // INPT5 { - return Core.p2_fire; + Core._islag = false; + + if (!Core.p2_is_2button) + { + return Core.p2_fire; + } + else if ((Core.m6532._outputB & 0x10) != 0 || (Core.m6532._ddRb & 0x10) != 0x10) + { + return Core.p2_fire; + } + else + { + return 0x80; + } } return 0; diff --git a/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/TIA_Sound/Tia.ISoundProvider.cs b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/TIA_Sound/Tia.ISoundProvider.cs index 783c5acbf2..0cdba141aa 100644 --- a/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/TIA_Sound/Tia.ISoundProvider.cs +++ b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/TIA_Sound/Tia.ISoundProvider.cs @@ -19,8 +19,8 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk public void GetSamplesSync(out short[] samples, out int nsamp) { - short[] ret = new short[AudioClocks * 2]; - nsamp = AudioClocks; + short[] ret = new short[_spf * 2]; + nsamp = _spf; GetSamples(ret); samples = ret; } @@ -35,8 +35,6 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk AudioClocks = 0; } - private readonly int _spf; - // Exposing this as GetSamplesAsync would allow this to provide async sound // However, it does nothing special for async sound so I don't see a point private void GetSamples(short[] samples) diff --git a/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/TIA_Sound/Tia.SyncState.cs b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/TIA_Sound/Tia.SyncState.cs index 89a2c50cfd..58fa1b875a 100644 --- a/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/TIA_Sound/Tia.SyncState.cs +++ b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/TIA_Sound/Tia.SyncState.cs @@ -14,6 +14,7 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk ser.Sync("Bus_State", ref BusState); ser.Sync("Ticks", ref _doTicks); + ser.Sync("_spf", ref _spf); // some of these things weren't in the state because they weren't needed if // states were always taken at frame boundaries diff --git a/BizHawk.Emulation.Cores/Consoles/Intellivision/STIC.cs b/BizHawk.Emulation.Cores/Consoles/Intellivision/STIC.cs index 3f5b94b041..97097e097e 100644 --- a/BizHawk.Emulation.Cores/Consoles/Intellivision/STIC.cs +++ b/BizHawk.Emulation.Cores/Consoles/Intellivision/STIC.cs @@ -492,10 +492,10 @@ namespace BizHawk.Emulation.Cores.Intellivision // also if the pixel is on set it in the collision matrix // note that the collision field is attached to the lower right corner of the BG // so we add 8 to x and 16 to y here - if ((card_col * 8 + (7-pict_col) + 8) < 167) + if ((card_col * 8 + (7 - pict_col) + 8) < 167) { - Collision[card_col * 8 + (7-pict_col) + 8, (card_row * 8 + pict_row) * 2 + 16] = 1 << 8; - Collision[card_col * 8 + (7-pict_col) + 8, (card_row * 8 + pict_row) * 2 + 16 + 1] = 1 << 8; + Collision[card_col * 8 + (7 - pict_col) + 8, (card_row * 8 + pict_row) * 2 + 16] = 1 << 8; + Collision[card_col * 8 + (7 - pict_col) + 8, (card_row * 8 + pict_row) * 2 + 16 + 1] = 1 << 8; } } else @@ -521,7 +521,7 @@ namespace BizHawk.Emulation.Cores.Intellivision int min_x = x_border == 0 ? x_delay : x_border; int min_y = y_border == 0 ? y_delay : y_border; - for (int j=input_row*8;j < (input_row * 8)+8; j++) + for (int j = input_row * 8; j < (input_row * 8) + 8; j++) { for (int i = 0; i < 159; i++) { @@ -602,8 +602,11 @@ namespace BizHawk.Emulation.Cores.Intellivision bool gram = attr.Bit(11); byte loc_color = (byte)(attr & 7); bool color_3 = attr.Bit(12); + if (color_3 && gram) + { loc_color += 8; + } bool priority = attr.Bit(13); byte loc_x = (byte)(x & 0xFF); @@ -619,7 +622,7 @@ namespace BizHawk.Emulation.Cores.Intellivision ushort y_size = (ushort)(ysiz2 * ysiz4); // setting yres implicitly uses an even card first - if (yres>1) + if (yres > 1) card &= 0xFE; // in GRAM mode only take the first 6 bits of the card number @@ -642,7 +645,7 @@ namespace BizHawk.Emulation.Cores.Intellivision } // assign the y_mob, used to double vertical resolution - if (yres>1) + if (yres > 1) { for (int j = 0; j < 8; j++) { @@ -752,15 +755,15 @@ namespace BizHawk.Emulation.Cores.Intellivision { cur_y = j * y_size + m; - if ((cur_x) < (167 - x_delay) && (loc_y * 2 + cur_y) < (208 - y_delay * 2) && pixel && vis && (cur_x) >= (8 - x_delay) && (loc_y * 2 + cur_y) >= (16 - y_delay * 2)) + if ((cur_x) < (167 - x_delay) && (loc_y * 2 + cur_y) < (208 - y_delay * 2) && pixel && vis && cur_x >= (8 - x_delay) && (loc_y * 2 + cur_y) >= (16 - y_delay * 2)) { if (!(priority && (Collision[cur_x, loc_y * 2 + cur_y]&0x100)>0)) - FrameBuffer[(loc_y * 2 + cur_y - (16 - y_delay * 2)) * 176 + (cur_x + 8) - (8 - x_delay) + BORDER_OFFSET] = ColorToRGBA(loc_color); + FrameBuffer[(loc_y * 2 + cur_y - (16 - y_delay * 2)) * 176 + cur_x + x_delay + BORDER_OFFSET] = ColorToRGBA(loc_color); } // a MOB does not need to be visible for it to be interracting // special case: a mob with x position 0 is counted as off - if (intr && pixel && (cur_x) <= 167 && (loc_y * 2 + cur_y) < 210 && loc_x != 0) + if (intr && pixel && cur_x <= 167 && (loc_y * 2 + cur_y) < 210 && loc_x != 0) { Collision[cur_x, loc_y * 2 + cur_y] |= (ushort)(1 << i); } @@ -770,7 +773,7 @@ namespace BizHawk.Emulation.Cores.Intellivision if ((cur_x + 1) < (167 - x_delay) && (loc_y * 2 + cur_y) < (208 - y_delay * 2) && pixel && vis && (cur_x + 1) >= (8 - x_delay) && (loc_y * 2 + cur_y) >= (16 - y_delay * 2)) { if (!(priority && (Collision[cur_x + 1, loc_y * 2 + cur_y] & 0x100) > 0)) - FrameBuffer[(loc_y * 2 + cur_y - (16 - y_delay * 2)) * 176 + (cur_x + 8) + 1 - (8 - x_delay) + BORDER_OFFSET] = ColorToRGBA(loc_color); + FrameBuffer[(loc_y * 2 + cur_y - (16 - y_delay * 2)) * 176 + cur_x + x_delay + 1 + BORDER_OFFSET] = ColorToRGBA(loc_color); } //a MOB does not need to be visible for it to be interracting //special case: a mob with x position 0 is counted as off @@ -797,15 +800,15 @@ namespace BizHawk.Emulation.Cores.Intellivision { cur_y = j * y_size + m; - if ((cur_x) < (167 - x_delay) && ((loc_y + 4 * y_size) * 2 + cur_y) < (208 - y_delay * 2) && pixel && vis && (cur_x) >= (8 - x_delay) && ((loc_y + 4 * y_size) * 2 + cur_y) >= (16 - y_delay * 2)) + if ((cur_x) < (167 - x_delay) && ((loc_y + 4 * y_size) * 2 + cur_y) < (208 - y_delay * 2) && pixel && vis && cur_x >= (8 - x_delay) && ((loc_y + 4 * y_size) * 2 + cur_y) >= (16 - y_delay * 2)) { if (!(priority && (Collision[cur_x, (loc_y + 4 * y_size) * 2 + cur_y] & 0x100) > 0)) - FrameBuffer[((loc_y + 4 * y_size) * 2 + cur_y - (16 - y_delay * 2)) * 176 + (cur_x + 8) - (8 - x_delay) + BORDER_OFFSET] = ColorToRGBA(loc_color); + FrameBuffer[((loc_y + 4 * y_size) * 2 + cur_y - (16 - y_delay * 2)) * 176 + cur_x + x_delay + BORDER_OFFSET] = ColorToRGBA(loc_color); } // a MOB does not need to be visible for it to be interracting // special case: a mob with x position 0 is counted as off - if (intr && pixel && (cur_x) <= 167 && ((loc_y + 4 * y_size) * 2 + cur_y) < 210 && loc_x != 0) + if (intr && pixel && cur_x <= 167 && ((loc_y + 4 * y_size) * 2 + cur_y) < 210 && loc_x != 0) { Collision[cur_x, (loc_y + 4 * y_size) * 2 + cur_y] |= (ushort)(1 << i); } @@ -815,7 +818,7 @@ namespace BizHawk.Emulation.Cores.Intellivision if ((cur_x + 1) < (167 - x_delay) && ((loc_y + 4 * y_size) * 2 + cur_y) < (208 - y_delay * 2) && pixel && vis && (cur_x + 1) >= (8 - x_delay) && ((loc_y + 4 * y_size) * 2 + cur_y) >= (16 - y_delay * 2)) { if (!(priority && (Collision[cur_x + 1, (loc_y + 4 * y_size) * 2 + cur_y] & 0x100) > 0)) - FrameBuffer[((loc_y + 4 * y_size) * 2 + cur_y - (16 - y_delay * 2)) * 176 + (cur_x + 8) + 1 - (8 - x_delay) + BORDER_OFFSET] = ColorToRGBA(loc_color); + FrameBuffer[((loc_y + 4 * y_size) * 2 + cur_y - (16 - y_delay * 2)) * 176 + cur_x + x_delay + 1 + BORDER_OFFSET] = ColorToRGBA(loc_color); } // a MOB does not need to be visible for it to be interracting @@ -833,8 +836,8 @@ namespace BizHawk.Emulation.Cores.Intellivision // by now we have collision information for all 8 mobs and the BG // so we can store data in the collision registers here - int x_border = Register[0x32].Bit(0) ? 15-x_delay : 7-x_delay; - int y_border = Register[0x32].Bit(1) ? 30-y_delay*2 : 14-y_delay*2; + int x_border = Register[0x32].Bit(0) ? 15 - x_delay : 7 - x_delay; + int y_border = Register[0x32].Bit(1) ? 30 - y_delay * 2 : 14 - y_delay * 2; int x_border_2 = Register[0x32].Bit(0) ? 8 : 0; int y_border_2 = Register[0x32].Bit(1) ? 16 : 0; @@ -844,17 +847,17 @@ namespace BizHawk.Emulation.Cores.Intellivision for (int j = 0; j < 210; j++) { // while we are here we can set collision detection bits for the border region - if (i == x_border || i == (167-x_delay)) + if (i == x_border || i == (167 - x_delay)) { Collision[i, j] |= (1 << 9); } - if (j == y_border || j == y_border+1 || j == (208-y_delay*2) || j == (208 - y_delay * 2+1)) + if (j == y_border || j == y_border + 1 || j == (208 - y_delay * 2) || j == (208 - y_delay * 2 + 1)) { Collision[i, j] |= (1 << 9); } // and also make sure the border region is all the border color - if ((i-x_delay)>=0 && (i-x_delay)<=159 && (j-y_delay*2)>=0 && (j-y_delay*2)<192) + if ((i-x_delay)>=0 && (i-x_delay) <= 159 && (j-y_delay*2) >= 0 && (j-y_delay*2) < 192) { if ((i-x_delay) < x_border_2) FrameBuffer[(j - y_delay*2) * 176 + ((i + 8) - x_delay) + BORDER_OFFSET] = ColorToRGBA(Register[0x2C] & 0xF); @@ -869,7 +872,7 @@ namespace BizHawk.Emulation.Cores.Intellivision } // the extra condition here is to ignore only border/BG collsion bit set - if (Collision[i, j] != 0 && Collision[i,j] != (1<<9) && Collision[i,j] != (1<<8)) + if (Collision[i, j] != 0 && Collision[i,j] != (1 << 9) && Collision[i,j] != (1 << 8)) { for (int k = 0; k < 8; k++) { diff --git a/BizHawk.Emulation.Cores/Consoles/NEC/PCFX/LibTst.cs b/BizHawk.Emulation.Cores/Consoles/NEC/PCFX/LibTst.cs index c6fdf48c55..a108e501d7 100644 --- a/BizHawk.Emulation.Cores/Consoles/NEC/PCFX/LibTst.cs +++ b/BizHawk.Emulation.Cores/Consoles/NEC/PCFX/LibTst.cs @@ -49,6 +49,7 @@ namespace BizHawk.Emulation.Cores.Consoles.NEC.PCFX public int CpuEmulation; public int Port1; public int Port2; + public int PixelPro; } [BizImport(CC)] diff --git a/BizHawk.Emulation.Cores/Consoles/NEC/PCFX/Tst.cs b/BizHawk.Emulation.Cores/Consoles/NEC/PCFX/Tst.cs index b89760ba34..e0ee26e575 100644 --- a/BizHawk.Emulation.Cores/Consoles/NEC/PCFX/Tst.cs +++ b/BizHawk.Emulation.Cores/Consoles/NEC/PCFX/Tst.cs @@ -222,6 +222,10 @@ namespace BizHawk.Emulation.Cores.Consoles.NEC.PCFX [DeepEqualsIgnore] private bool _showLayerRAINBOW; + [Description("Pixel Pro. Overrides HiResEmulation if set")] + [DefaultValue(false)] + public bool PixelPro { get; set; } + public Settings Clone() { return (Settings)MemberwiseClone(); @@ -321,7 +325,8 @@ namespace BizHawk.Emulation.Cores.Consoles.NEC.PCFX CdSpeed = _syncSettings.CdSpeed, CpuEmulation = (int)_syncSettings.CpuEmulation, Port1 = (int)_syncSettings.Port1, - Port2 = (int)_syncSettings.Port2 + Port2 = (int)_syncSettings.Port2, + PixelPro = _settings.PixelPro ? 1 : 0 }; _core.PutSettingsBeforeInit(s); } diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.cs index 9e04730e4a..864cdd856d 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.cs @@ -439,7 +439,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy #region ppudebug - public bool GetGPUMemoryAreas(out IntPtr vram, out IntPtr bgpal, out IntPtr sppal, out IntPtr oam) + public GPUMemoryAreas GetGPU() { IntPtr _vram = IntPtr.Zero; IntPtr _bgpal = IntPtr.Zero; @@ -451,23 +451,11 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy || !LibGambatte.gambatte_getmemoryarea(GambatteState, LibGambatte.MemoryAreas.sppal, ref _sppal, ref unused) || !LibGambatte.gambatte_getmemoryarea(GambatteState, LibGambatte.MemoryAreas.oam, ref _oam, ref unused)) { - vram = IntPtr.Zero; - bgpal = IntPtr.Zero; - sppal = IntPtr.Zero; - oam = IntPtr.Zero; - return false; + throw new InvalidOperationException("Unexpected error in gambatte_getmemoryarea"); } - vram = _vram; - bgpal = _bgpal; - sppal = _sppal; - oam = _oam; - return true; - } + return new GPUMemoryAreas(_vram, _oam, _sppal, _bgpal); - /// - /// - /// current value of register $ff40 (LCDC) - public delegate void ScanlineCallback(int lcdc); + } /// /// set up callback diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/IGameboyCommon.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/IGameboyCommon.cs index fa236b8f47..b874919ad7 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/IGameboyCommon.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/IGameboyCommon.cs @@ -1,4 +1,6 @@ -using System; +using BizHawk.Common; +using BizHawk.Emulation.Common; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -6,8 +8,49 @@ using System.Threading.Tasks; namespace BizHawk.Emulation.Cores.Consoles.Nintendo.Gameboy { - public interface IGameboyCommon + /// + /// + /// current value of register $ff40 (LCDC) + public delegate void ScanlineCallback(byte lcdc); + + public interface IGameboyCommon : ISpecializedEmulatorService { bool IsCGBMode(); + GPUMemoryAreas GetGPU(); + + /// + /// set up callback + /// + /// scanline. -1 = end of frame, -2 = RIGHT NOW + void SetScanlineCallback(ScanlineCallback callback, int line); + } + + public class GPUMemoryAreas : IMonitor + { + public IntPtr Vram { get; } + public IntPtr Oam { get; } + public IntPtr Sppal { get; } + public IntPtr Bgpal { get; } + + private readonly IMonitor _monitor; + + public GPUMemoryAreas(IntPtr vram, IntPtr oam, IntPtr sppal, IntPtr bgpal, IMonitor monitor = null) + { + Vram = vram; + Oam = oam; + Sppal = sppal; + Bgpal = bgpal; + _monitor = monitor; + } + + public void Enter() + { + _monitor?.Enter(); + } + + public void Exit() + { + _monitor?.Exit(); + } } } diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/LibPizza.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/LibSameboy.cs similarity index 58% rename from BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/LibPizza.cs rename to BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/LibSameboy.cs index e8306aea35..405635404c 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/LibPizza.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/LibSameboy.cs @@ -9,7 +9,7 @@ using System.Threading.Tasks; namespace BizHawk.Emulation.Cores.Consoles.Nintendo.Gameboy { - public abstract class LibPizza : LibWaterboxCore, ICustomSaveram + public abstract class LibSameboy : LibWaterboxCore { [Flags] public enum Buttons : uint @@ -23,21 +23,33 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.Gameboy UP = 0x40, DOWN = 0x80 } + [StructLayout(LayoutKind.Sequential)] public new class FrameInfo : LibWaterboxCore.FrameInfo { public long Time; public Buttons Keys; } + [BizImport(CC)] - public abstract bool Init(byte[] rom, int romlen, bool sgb, byte[] spc, int spclen); + public abstract bool Init(bool cgb, byte[] spc, int spclen); + [BizImport(CC)] - public abstract bool IsCGB(); + public abstract void GetGpuMemory(IntPtr[] ptrs); + [BizImport(CC)] - public abstract int GetSaveramSize(); + public abstract void SetScanlineCallback(ScanlineCallback callback, int ly); + [BizImport(CC)] - public abstract void PutSaveram(byte[] data, int size); + public abstract byte GetIoReg(byte port); + [BizImport(CC)] - public abstract void GetSaveram(byte[] data, int size); + public abstract void PutSaveRam(); + + [BizImport(CC)] + public abstract void GetSaveRam(); + + [BizImport(CC)] + public abstract bool HasSaveRam(); } } diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Pizza.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Pizza.cs deleted file mode 100644 index 52b966647b..0000000000 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Pizza.cs +++ /dev/null @@ -1,169 +0,0 @@ -using BizHawk.Common; -using BizHawk.Common.BizInvoke; -using BizHawk.Emulation.Common; -using BizHawk.Emulation.Cores.Waterbox; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace BizHawk.Emulation.Cores.Consoles.Nintendo.Gameboy -{ - [Core("Pizza Boy", "Davide Berra", true, true, "c7bc6ee376028b3766de8d7a02e60ab794841f45", - "https://github.com/davideberra/emu-pizza/", false)] - public class Pizza : WaterboxCore, IGameboyCommon - { - private LibPizza _pizza; - private readonly bool _sgb; - - [CoreConstructor("SGB")] - public Pizza(byte[] rom, CoreComm comm) - : this(rom, comm, true) - { } - - [CoreConstructor("GB")] - public Pizza(CoreComm comm, byte[] rom) - : this(rom, comm, false) - { } - - public Pizza(byte[] rom, CoreComm comm, bool sgb) - : base(comm, new Configuration - { - DefaultWidth = 160, - DefaultHeight = 144, - MaxWidth = 256, - MaxHeight = 224, - MaxSamples = 1024, - DefaultFpsNumerator = TICKSPERSECOND, - DefaultFpsDenominator = TICKSPERFRAME - }) - { - if (sgb && (rom[0x143] & 0xc0) == 0xc0) - { - throw new CGBNotSupportedException(); - } - - _pizza = PreInit(new PeRunnerOptions - { - Filename = "pizza.wbx", - SbrkHeapSizeKB = 128, - InvisibleHeapSizeKB = 16, - SealedHeapSizeKB = 5 * 1024, - PlainHeapSizeKB = 16, - MmapHeapSizeKB = 0 - }); - - var spc = sgb - ? Util.DecompressGzipFile(new MemoryStream(Properties.Resources.SgbCartPresent_SPC)) - : new byte[0]; - _sgb = sgb; - if (!_pizza.Init(rom, rom.Length, _sgb, spc, spc.Length)) - { - throw new InvalidOperationException("Core rejected the rom!"); - } - - PostInit(); - - if (_sgb) - { - VsyncNumerator = TICKSPERSECOND_SGB; - BufferWidth = 256; - BufferHeight = 224; - } - InitializeRtc(new DateTime(2010, 1, 1)); // TODO: connect to syncsettings - Console.WriteLine("Pizza Initialized: CGB {0} SGB {1}", IsCGBMode(), IsSGBMode()); - } - - /// - /// the nominal length of one frame - /// - private const int TICKSPERFRAME = 35112; - - /// - /// number of ticks per second (GB, CGB) - /// - private const int TICKSPERSECOND = 2097152; - - /// - /// number of ticks per second (SGB) - /// - private const int TICKSPERSECOND_SGB = 2147727; - - #region Controller - - private static readonly ControllerDefinition _gbDefinition; - private static readonly ControllerDefinition _sgbDefinition; - public override ControllerDefinition ControllerDefinition => _sgb ? _sgbDefinition : _gbDefinition; - - private static ControllerDefinition CreateControllerDefinition(int p) - { - var ret = new ControllerDefinition { Name = "Gameboy Controller" }; - for (int i = 0; i < p; i++) - { - ret.BoolButtons.AddRange( - new[] { "Up", "Down", "Left", "Right", "A", "B", "Select", "Start" } - .Select(s => $"P{i + 1} {s}")); - } - return ret; - } - - static Pizza() - { - _gbDefinition = CreateControllerDefinition(1); - _sgbDefinition = CreateControllerDefinition(4); - } - - private LibPizza.Buttons GetButtons(IController c) - { - LibPizza.Buttons b = 0; - for (int i = _sgb ? 4 : 1; i > 0; i--) - { - if (c.IsPressed($"P{i} Up")) - b |= LibPizza.Buttons.UP; - if (c.IsPressed($"P{i} Down")) - b |= LibPizza.Buttons.DOWN; - if (c.IsPressed($"P{i} Left")) - b |= LibPizza.Buttons.LEFT; - if (c.IsPressed($"P{i} Right")) - b |= LibPizza.Buttons.RIGHT; - if (c.IsPressed($"P{i} A")) - b |= LibPizza.Buttons.A; - if (c.IsPressed($"P{i} B")) - b |= LibPizza.Buttons.B; - if (c.IsPressed($"P{i} Select")) - b |= LibPizza.Buttons.SELECT; - if (c.IsPressed($"P{i} Start")) - b |= LibPizza.Buttons.START; - if (i != 1) - b = (LibPizza.Buttons)((uint)b << 8); - } - return b; - } - - #endregion - - LibPizza.FrameInfo _tmp; // TODO: clean this up so it's not so hacky - - protected override LibWaterboxCore.FrameInfo FrameAdvancePrep(IController controller, bool render, bool rendersound) - { - return _tmp = new LibPizza.FrameInfo - { - Time = GetRtcTime(false), - Keys = GetButtons(controller) - }; - } - - protected override void FrameAdvancePost() - { - //Console.WriteLine(_tmp.Cycles); - _tmp = null; - } - - public bool IsCGBMode() => _pizza.IsCGB(); - public bool IsSGBMode() => _sgb; - - public override string SystemId => _sgb ? "SGB" : "GB"; - } -} diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Sameboy.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Sameboy.cs new file mode 100644 index 0000000000..c9d5269710 --- /dev/null +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Sameboy.cs @@ -0,0 +1,298 @@ +using BizHawk.Common; +using BizHawk.Emulation.Common; +using BizHawk.Emulation.Cores.Properties; +using BizHawk.Emulation.Cores.Waterbox; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BizHawk.Emulation.Cores.Consoles.Nintendo.Gameboy +{ + [Core("SameBoy", "LIJI32", true, false, "efc11783c7fb6da66e1dd084e41ba6a85c0bd17e", + "https://sameboy.github.io/", false)] + public class Sameboy : WaterboxCore, + IGameboyCommon, ISaveRam, + ISettable + { + /// + /// the nominal length of one frame + /// + private const int TICKSPERFRAME = 35112; + + /// + /// number of ticks per second (GB, CGB) + /// + private const int TICKSPERSECOND = 2097152; + + /// + /// number of ticks per second (SGB) + /// + private const int TICKSPERSECOND_SGB = 2147727; + + private LibSameboy _core; + private bool _cgb; + private bool _sgb; + + [CoreConstructor("SGB")] + public Sameboy(byte[] rom, CoreComm comm, SyncSettings syncSettings, bool deterministic) + : this(rom, comm, true, syncSettings, deterministic) + { } + + [CoreConstructor("GB")] + public Sameboy(CoreComm comm, byte[] rom, SyncSettings syncSettings, bool deterministic) + : this(rom, comm, false, syncSettings, deterministic) + { } + + public Sameboy(byte[] rom, CoreComm comm, bool sgb, SyncSettings syncSettings, bool deterministic) + : base(comm, new Configuration + { + DefaultWidth = sgb ? 256 : 160, + DefaultHeight = sgb ? 224 : 144, + MaxWidth = sgb ? 256 : 160, + MaxHeight = sgb ? 224 : 144, + MaxSamples = 1024, + DefaultFpsNumerator = sgb ? TICKSPERSECOND_SGB : TICKSPERSECOND, + DefaultFpsDenominator = TICKSPERFRAME, + SystemId = sgb ? "SGB" : "GB" + }) + { + _core = PreInit(new PeRunnerOptions + { + Filename = "sameboy.wbx", + SbrkHeapSizeKB = 192, + InvisibleHeapSizeKB = 4, + SealedHeapSizeKB = 9 * 1024, + PlainHeapSizeKB = 4, + MmapHeapSizeKB = 1024 + }); + + _cgb = (rom[0x143] & 0xc0) == 0xc0 && !sgb; + _sgb = sgb; + Console.WriteLine("Automaticly detected CGB to " + _cgb); + _syncSettings = syncSettings ?? new SyncSettings(); + + var bios = _syncSettings.UseRealBIOS && !sgb + ? comm.CoreFileProvider.GetFirmware(_cgb ? "GBC" : "GB", "World", true) + : Util.DecompressGzipFile(new MemoryStream(_cgb ? Resources.SameboyCgbBoot : Resources.SameboyDmgBoot)); + + var spc = sgb + ? Util.DecompressGzipFile(new MemoryStream(Resources.SgbCartPresent_SPC)) + : null; + + _exe.AddReadonlyFile(rom, "game.rom"); + _exe.AddReadonlyFile(bios, "boot.rom"); + + if (!_core.Init(_cgb, spc, spc?.Length ?? 0)) + { + throw new InvalidOperationException("Core rejected the rom!"); + } + + _exe.RemoveReadonlyFile("game.rom"); + _exe.RemoveReadonlyFile("boot.rom"); + + PostInit(); + + var scratch = new IntPtr[4]; + _core.GetGpuMemory(scratch); + _gpuMemory = new GPUMemoryAreas(scratch[0], scratch[1], scratch[3], scratch[2], _exe); + + DeterministicEmulation = deterministic || !_syncSettings.UseRealTime; + InitializeRtc(_syncSettings.InitialTime); + } + + #region Controller + + private static readonly ControllerDefinition _gbDefinition; + private static readonly ControllerDefinition _sgbDefinition; + public override ControllerDefinition ControllerDefinition => _sgb ? _sgbDefinition : _gbDefinition; + + private static ControllerDefinition CreateControllerDefinition(int p) + { + var ret = new ControllerDefinition { Name = "Gameboy Controller" }; + for (int i = 0; i < p; i++) + { + ret.BoolButtons.AddRange( + new[] { "Up", "Down", "Left", "Right", "A", "B", "Select", "Start" } + .Select(s => $"P{i + 1} {s}")); + } + return ret; + } + + static Sameboy() + { + _gbDefinition = CreateControllerDefinition(1); + _sgbDefinition = CreateControllerDefinition(4); + } + + private LibSameboy.Buttons GetButtons(IController c) + { + LibSameboy.Buttons b = 0; + for (int i = _sgb ? 4 : 1; i > 0; i--) + { + if (c.IsPressed($"P{i} Up")) + b |= LibSameboy.Buttons.UP; + if (c.IsPressed($"P{i} Down")) + b |= LibSameboy.Buttons.DOWN; + if (c.IsPressed($"P{i} Left")) + b |= LibSameboy.Buttons.LEFT; + if (c.IsPressed($"P{i} Right")) + b |= LibSameboy.Buttons.RIGHT; + if (c.IsPressed($"P{i} A")) + b |= LibSameboy.Buttons.A; + if (c.IsPressed($"P{i} B")) + b |= LibSameboy.Buttons.B; + if (c.IsPressed($"P{i} Select")) + b |= LibSameboy.Buttons.SELECT; + if (c.IsPressed($"P{i} Start")) + b |= LibSameboy.Buttons.START; + if (i != 1) + b = (LibSameboy.Buttons)((uint)b << 8); + } + return b; + } + + #endregion + + #region ISaveram + + public new bool SaveRamModified => _core.HasSaveRam(); + + public new byte[] CloneSaveRam() + { + _exe.AddTransientFile(null, "save.ram"); + _core.GetSaveRam(); + return _exe.RemoveTransientFile("save.ram"); + } + + public new void StoreSaveRam(byte[] data) + { + _exe.AddReadonlyFile(data, "save.ram"); + _core.PutSaveRam(); + _exe.RemoveReadonlyFile("save.ram"); + } + + #endregion + + #region ISettable + + private SyncSettings _syncSettings; + + public class SyncSettings + { + [DisplayName("Initial Time")] + [Description("Initial time of emulation. Only relevant when UseRealTime is false.")] + [DefaultValue(typeof(DateTime), "2010-01-01")] + public DateTime InitialTime { get; set; } + + [DisplayName("Use RealTime")] + [Description("If true, RTC clock will be based off of real time instead of emulated time. Ignored (set to false) when recording a movie.")] + [DefaultValue(false)] + public bool UseRealTime { get; set; } + + [Description("If true, real BIOS files will be used. Ignored in SGB mode.")] + [DefaultValue(false)] + public bool UseRealBIOS { get; set; } + + public SyncSettings Clone() + { + return (SyncSettings)MemberwiseClone(); + } + + public static bool NeedsReboot(SyncSettings x, SyncSettings y) + { + return !DeepEquality.DeepEquals(x, y); + } + + public SyncSettings() + { + SettingsUtil.SetDefaultValues(this); + } + } + + public object GetSettings() + { + return null; + } + + public SyncSettings GetSyncSettings() + { + return _syncSettings.Clone(); + } + + public bool PutSettings(object o) + { + return false; + } + + public bool PutSyncSettings(SyncSettings o) + { + var ret = SyncSettings.NeedsReboot(_syncSettings, o); + _syncSettings = o; + return ret; + } + + #endregion + + protected override LibWaterboxCore.FrameInfo FrameAdvancePrep(IController controller, bool render, bool rendersound) + { + return new LibSameboy.FrameInfo + { + Time = GetRtcTime(!DeterministicEmulation), + Keys = GetButtons(controller) + }; + } + + protected override void FrameAdvancePost() + { + if (_scanlineCallback != null && _scanlineCallbackLine == -1) + _scanlineCallback(_core.GetIoReg(0x40)); + } + + protected override void LoadStateBinaryInternal(BinaryReader reader) + { + UpdateCoreScanlineCallback(false); + } + + public bool IsCGBMode() => _cgb; + + private GPUMemoryAreas _gpuMemory; + + public GPUMemoryAreas GetGPU() => _gpuMemory; + private ScanlineCallback _scanlineCallback; + private int _scanlineCallbackLine; + + public void SetScanlineCallback(ScanlineCallback callback, int line) + { + _scanlineCallback = callback; + _scanlineCallbackLine = line; + UpdateCoreScanlineCallback(true); + } + + private void UpdateCoreScanlineCallback(bool now) + { + if (_scanlineCallback == null) + { + _core.SetScanlineCallback(null, -1); + } + else + { + if (_scanlineCallbackLine >= 0 && _scanlineCallbackLine <= 153) + { + _core.SetScanlineCallback(_scanlineCallback, _scanlineCallbackLine); + } + else + { + _core.SetScanlineCallback(null, -1); + if (_scanlineCallbackLine == -2 && now) + { + _scanlineCallback(_core.GetIoReg(0x40)); + } + } + } + } + } +} diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/VB/LibVirtualBoyee.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/VB/LibVirtualBoyee.cs index 89beef4e9a..619f304736 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/VB/LibVirtualBoyee.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/VB/LibVirtualBoyee.cs @@ -37,10 +37,23 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.VB } [StructLayout(LayoutKind.Sequential)] - public class NativeSettings + public class NativeSyncSettings { public int InstantReadHack; public int DisableParallax; + + public static NativeSyncSettings FromFrontendSettings(VirtualBoyee.SyncSettings ss) + { + return new NativeSyncSettings + { + InstantReadHack = ss.InstantReadHack ? 1 : 0, + DisableParallax = ss.DisableParallax ? 1 : 0, + }; + } + } + + public class NativeSettings + { public int ThreeDeeMode; public int SwapViews; public int AnaglyphPreset; @@ -56,12 +69,10 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.VB return c.ToArgb(); } - public static NativeSettings FromFrontendSettings(VirtualBoyee.Settings s, VirtualBoyee.SyncSettings ss) + public static NativeSettings FromFrontendSettings(VirtualBoyee.Settings s) { return new NativeSettings { - InstantReadHack = ss.InstantReadHack ? 1 : 0, - DisableParallax = ss.DisableParallax ? 1 : 0, ThreeDeeMode = (int)s.ThreeDeeMode, SwapViews = s.SwapViews ? 1 : 0, AnaglyphPreset = (int)s.AnaglyphPreset, @@ -77,7 +88,10 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.VB [BizImport(CC)] - public abstract bool Load(byte[] rom, int length, [In]NativeSettings settings); + public abstract bool Load(byte[] rom, int length, NativeSyncSettings settings); + + [BizImport(CC)] + public abstract void SetSettings(NativeSettings settings); [BizImport(CC)] public abstract void HardReset(); diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/VB/VirtualBoyee.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/VB/VirtualBoyee.cs index 43b7e26ada..2b564a11e3 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/VB/VirtualBoyee.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/VB/VirtualBoyee.cs @@ -24,7 +24,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.VB [CoreConstructor("VB")] public VirtualBoyee(CoreComm comm, byte[] rom, Settings settings, SyncSettings syncSettings) - :base(comm, new Configuration + : base(comm, new Configuration { DefaultFpsNumerator = 20000000, DefaultFpsDenominator = 397824, @@ -38,8 +38,6 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.VB { _settings = settings ?? new Settings(); _syncSettings = syncSettings ?? new SyncSettings(); - // TODO: the way settings work in this core, changing the non-sync ones will invalidate savestates - var nativeSettings = LibVirtualBoyee.NativeSettings.FromFrontendSettings(_settings, _syncSettings); _boyee = PreInit(new PeRunnerOptions { @@ -50,7 +48,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.VB PlainHeapSizeKB = 256 }); - if (!_boyee.Load(rom, rom.Length, nativeSettings)) + if (!_boyee.Load(rom, rom.Length, LibVirtualBoyee.NativeSyncSettings.FromFrontendSettings(_syncSettings))) throw new InvalidOperationException("Core rejected the rom"); // do a quick hack up for frame zero size @@ -60,6 +58,8 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.VB BufferHeight = tmp.Height; PostInit(); + + _boyee.SetSettings(LibVirtualBoyee.NativeSettings.FromFrontendSettings(_settings)); } protected override LibWaterboxCore.FrameInfo FrameAdvancePrep(IController controller, bool render, bool rendersound) diff --git a/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.IEmulator.cs b/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.IEmulator.cs index ce4d1af49a..5fa7f01d7e 100644 --- a/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.IEmulator.cs +++ b/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.IEmulator.cs @@ -6,7 +6,7 @@ namespace BizHawk.Emulation.Cores.PCEngine { public IEmulatorServiceProvider ServiceProvider { get; private set; } - public ControllerDefinition ControllerDefinition => PCEngineController; + public ControllerDefinition ControllerDefinition => _controllerDeck.Definition; public void FrameAdvance(IController controller, bool render, bool rendersound) { diff --git a/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.ISettable.cs b/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.ISettable.cs index 28694b69d5..00f27089c4 100644 --- a/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.ISettable.cs +++ b/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.ISettable.cs @@ -1,4 +1,7 @@ -using BizHawk.Emulation.Common; +using System.ComponentModel; + +using BizHawk.Common; +using BizHawk.Emulation.Common; namespace BizHawk.Emulation.Cores.PCEngine { @@ -35,7 +38,6 @@ namespace BizHawk.Emulation.Cores.PCEngine { bool ret = PCESyncSettings.NeedsReboot(o, _syncSettings); _syncSettings = o; - // SetControllerButtons(); // not safe to change the controller during emulation, so instead make it a reboot event return ret; } @@ -62,42 +64,48 @@ namespace BizHawk.Emulation.Cores.PCEngine public class PCESyncSettings { - public ControllerSetting[] Controllers = - { - new ControllerSetting { IsConnected = true }, - new ControllerSetting { IsConnected = false }, - new ControllerSetting { IsConnected = false }, - new ControllerSetting { IsConnected = false }, - new ControllerSetting { IsConnected = false } - }; + [DefaultValue(PceControllerType.GamePad)] + [DisplayName("Port 1 Device")] + [Description("The type of controller plugged into the first controller port")] + [TypeConverter(typeof(DescribableEnumConverter))] + public PceControllerType Port1 { get; set; } = PceControllerType.GamePad; + + [DefaultValue(PceControllerType.Unplugged)] + [DisplayName("Port 2 Device")] + [Description("The type of controller plugged into the second controller port")] + [TypeConverter(typeof(DescribableEnumConverter))] + public PceControllerType Port2 { get; set; } = PceControllerType.Unplugged; + + [DefaultValue(PceControllerType.Unplugged)] + [DisplayName("Port 3 Device")] + [Description("The type of controller plugged into the third controller port")] + [TypeConverter(typeof(DescribableEnumConverter))] + public PceControllerType Port3 { get; set; } = PceControllerType.Unplugged; + + [DefaultValue(PceControllerType.Unplugged)] + [DisplayName("Port 4 Device")] + [Description("The type of controller plugged into the fourth controller port")] + [TypeConverter(typeof(DescribableEnumConverter))] + public PceControllerType Port4 { get; set; } = PceControllerType.Unplugged; + + [DefaultValue(PceControllerType.Unplugged)] + [DisplayName("Port 5 Device")] + [Description("The type of controller plugged into the fifth controller port")] + [TypeConverter(typeof(DescribableEnumConverter))] + public PceControllerType Port5 { get; set; } = PceControllerType.Unplugged; public PCESyncSettings Clone() { - var ret = new PCESyncSettings(); - for (int i = 0; i < Controllers.Length; i++) - { - ret.Controllers[i].IsConnected = Controllers[i].IsConnected; - } - - return ret; - } - - public class ControllerSetting - { - public bool IsConnected { get; set; } + return (PCESyncSettings)MemberwiseClone(); } public static bool NeedsReboot(PCESyncSettings x, PCESyncSettings y) { - for (int i = 0; i < x.Controllers.Length; i++) - { - if (x.Controllers[i].IsConnected != y.Controllers[i].IsConnected) - { - return true; - } - } - - return false; + return x.Port1 != y.Port1 + || x.Port2 != y.Port2 + || x.Port3 != y.Port3 + || x.Port4 != y.Port4 + || x.Port5 != y.Port5; } } } diff --git a/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.Input.cs b/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.Input.cs index c40788c08a..015f16f8ad 100644 --- a/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.Input.cs +++ b/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.Input.cs @@ -1,92 +1,41 @@ -using BizHawk.Emulation.Common; - -namespace BizHawk.Emulation.Cores.PCEngine +namespace BizHawk.Emulation.Cores.PCEngine { public partial class PCEngine { - private readonly ControllerDefinition PCEngineController = new ControllerDefinition - { - Name = "PC Engine Controller", - BoolButtons = - { - "P1 Up", "P1 Down", "P1 Left", "P1 Right", "P1 Select", "P1 Run", "P1 B2", "P1 B1", - "P2 Up", "P2 Down", "P2 Left", "P2 Right", "P2 Select", "P2 Run", "P2 B2", "P2 B1", - "P3 Up", "P3 Down", "P3 Left", "P3 Right", "P3 Select", "P3 Run", "P3 B2", "P3 B1", - "P4 Up", "P4 Down", "P4 Left", "P4 Right", "P4 Select", "P4 Run", "P4 B2", "P4 B1", - "P5 Up", "P5 Down", "P5 Left", "P5 Right", "P5 Select", "P5 Run", "P5 B2", "P5 B1" - } - }; + private int _selectedController; + private byte _inputByte; - private void SetControllerButtons() - { - ControllerDefinition.BoolButtons.Clear(); - ControllerDefinition.FloatControls.Clear(); - - for (int i = 0; i < 5; i++) - { - if (_syncSettings.Controllers[i].IsConnected) - { - ControllerDefinition.BoolButtons.AddRange(new[] - { - "P" + (i + 1) + " Up", - "P" + (i + 1) + " Down", - "P" + (i + 1) + " Left", - "P" + (i + 1) + " Right", - "P" + (i + 1) + " Select", - "P" + (i + 1) + " Run", - "P" + (i + 1) + " B1", - "P" + (i + 1) + " B2" - }); - } - } - } - - private int SelectedController; - private byte InputByte; - - public bool SEL => (InputByte & 1) != 0; - public bool CLR => (InputByte & 2) != 0; + private bool Sel => (_inputByte & 1) != 0; + private bool Clr => (_inputByte & 2) != 0; private void WriteInput(byte value) { - bool prevSEL = SEL; - InputByte = value; + bool prevSel = Sel; + _inputByte = value; - if (SEL && CLR) + if (Sel && Clr) { - SelectedController = 0; + _selectedController = 0; } - if (CLR == false && prevSEL == false && SEL == true) + if (Clr == false && prevSel == false && Sel) { - SelectedController = (SelectedController + 1); + _selectedController = _selectedController + 1; } } + private readonly PceControllerDeck _controllerDeck; + private byte ReadInput() { InputCallbacks.Call(); byte value = 0x3F; - int player = SelectedController + 1; + int player = _selectedController + 1; if (player < 6) { _lagged = false; - if (SEL == false) // return buttons - { - if (_controller.IsPressed("P" + player + " B1")) value &= 0xFE; - if (_controller.IsPressed("P" + player + " B2")) value &= 0xFD; - if (_controller.IsPressed("P" + player + " Select")) value &= 0xFB; - if (_controller.IsPressed("P" + player + " Run")) value &= 0xF7; - } - else - { - //return directions - if (_controller.IsPressed("P" + player + " Up")) value &= 0xFE; - if (_controller.IsPressed("P" + player + " Right")) value &= 0xFD; - if (_controller.IsPressed("P" + player + " Down")) value &= 0xFB; - if (_controller.IsPressed("P" + player + " Left")) value &= 0xF7; - } + value &= _controllerDeck.Read(player, _controller, Sel); } if (Region == "Japan") diff --git a/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.cs b/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.cs index 32ca565b65..3eda6208b5 100644 --- a/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.cs +++ b/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.cs @@ -41,7 +41,13 @@ namespace BizHawk.Emulation.Cores.PCEngine Settings = (PCESettings)settings ?? new PCESettings(); _syncSettings = (PCESyncSettings)syncSettings ?? new PCESyncSettings(); Init(game, rom); - SetControllerButtons(); + + _controllerDeck = new PceControllerDeck( + _syncSettings.Port1, + _syncSettings.Port2, + _syncSettings.Port3, + _syncSettings.Port4, + _syncSettings.Port5); } public PCEngine(CoreComm comm, GameInfo game, Disc disc, object Settings, object syncSettings) @@ -96,7 +102,13 @@ namespace BizHawk.Emulation.Cores.PCEngine // the default RomStatusDetails don't do anything with Disc CoreComm.RomStatusDetails = string.Format("{0}\r\nDisk partial hash:{1}", game.Name, new DiscSystem.DiscHasher(disc).OldHash()); - SetControllerButtons(); + + _controllerDeck = new PceControllerDeck( + _syncSettings.Port1, + _syncSettings.Port2, + _syncSettings.Port3, + _syncSettings.Port4, + _syncSettings.Port5); } // ROM diff --git a/BizHawk.Emulation.Cores/Consoles/PC Engine/PceControllerDeck.cs b/BizHawk.Emulation.Cores/Consoles/PC Engine/PceControllerDeck.cs new file mode 100644 index 0000000000..6108be5955 --- /dev/null +++ b/BizHawk.Emulation.Cores/Consoles/PC Engine/PceControllerDeck.cs @@ -0,0 +1,162 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +using BizHawk.Emulation.Common; + +namespace BizHawk.Emulation.Cores.PCEngine +{ + public enum PceControllerType + { + Unplugged, + GamePad + } + + public class PceControllerDeck + { + private static readonly Type[] Implementors = + { + typeof(UnpluggedController), // Order must match PceControllerType enum values + typeof(StandardController) + }; + + public PceControllerDeck( + PceControllerType controller1, + PceControllerType controller2, + PceControllerType controller3, + PceControllerType controller4, + PceControllerType controller5) + { + _port1 = (IPort)Activator.CreateInstance(Implementors[(int)controller1], 1); + _port2 = (IPort)Activator.CreateInstance(Implementors[(int)controller2], 2); + _port3 = (IPort)Activator.CreateInstance(Implementors[(int)controller3], 3); + _port4 = (IPort)Activator.CreateInstance(Implementors[(int)controller4], 4); + _port5 = (IPort)Activator.CreateInstance(Implementors[(int)controller5], 5); + + Definition = new ControllerDefinition + { + Name = "PC Engine Controller", + BoolButtons = _port1.Definition.BoolButtons + .Concat(_port2.Definition.BoolButtons) + .Concat(_port3.Definition.BoolButtons) + .Concat(_port4.Definition.BoolButtons) + .Concat(_port5.Definition.BoolButtons) + .ToList() + }; + + Definition.FloatControls.AddRange(_port1.Definition.FloatControls); + Definition.FloatControls.AddRange(_port2.Definition.FloatControls); + Definition.FloatControls.AddRange(_port3.Definition.FloatControls); + Definition.FloatControls.AddRange(_port4.Definition.FloatControls); + Definition.FloatControls.AddRange(_port5.Definition.FloatControls); + + Definition.FloatRanges.AddRange(_port1.Definition.FloatRanges); + Definition.FloatRanges.AddRange(_port2.Definition.FloatRanges); + Definition.FloatRanges.AddRange(_port3.Definition.FloatRanges); + Definition.FloatRanges.AddRange(_port4.Definition.FloatRanges); + Definition.FloatRanges.AddRange(_port5.Definition.FloatRanges); + } + + private readonly IPort _port1; + private readonly IPort _port2; + private readonly IPort _port3; + private readonly IPort _port4; + private readonly IPort _port5; + + public byte Read(int portNum, IController c, bool sel) + { + switch (portNum) + { + default: + throw new ArgumentException($"Invalid {nameof(portNum)}: {portNum}"); + case 1: + return _port1.Read(c, sel); + case 2: + return _port2.Read(c, sel); + case 3: + return _port3.Read(c, sel); + case 4: + return _port4.Read(c, sel); + case 5: + return _port5.Read(c, sel); + } + } + + public ControllerDefinition Definition { get; } + } + + public interface IPort + { + byte Read(IController c, bool sel); + + ControllerDefinition Definition { get; } + + int PortNum { get; } + } + + public class UnpluggedController : IPort + { + public UnpluggedController(int portNum) + { + PortNum = portNum; + Definition = new ControllerDefinition + { + BoolButtons = new List() + }; + } + + public byte Read(IController c, bool sel) + { + return 0x3F; + } + + public ControllerDefinition Definition { get; } + + public int PortNum { get; } + } + + public class StandardController : IPort + { + public StandardController(int portNum) + { + PortNum = portNum; + Definition = new ControllerDefinition + { + BoolButtons = BaseDefinition + .Select(b => $"P{PortNum} " + b) + .ToList() + }; + } + + public ControllerDefinition Definition { get; } + + public int PortNum { get; } + + public byte Read(IController c, bool sel) + { + byte result = 0x3F; + + if (sel == false) + { + if (c.IsPressed($"P{PortNum} B1")) result &= 0xFE; + if (c.IsPressed($"P{PortNum} B2")) result &= 0xFD; + if (c.IsPressed($"P{PortNum} Select")) result &= 0xFB; + if (c.IsPressed($"P{PortNum} Run")) result &= 0xF7; + } + else + { + if (c.IsPressed($"P{PortNum} Up")) { result &= 0xFE; } + if (c.IsPressed($"P{PortNum} Right")) { result &= 0xFD; } + if (c.IsPressed($"P{PortNum} Down")) { result &= 0xFB; } + if (c.IsPressed($"P{PortNum} Left")) { result &= 0xF7; } + } + + return result; + } + + private static readonly string[] BaseDefinition = + { + "Up", "Down", "Left", "Right", "Select", "Run", "B2", "B1" + }; + } +} diff --git a/BizHawk.Emulation.Cores/Consoles/Sega/PicoDrive/LibPicoDrive.cs b/BizHawk.Emulation.Cores/Consoles/Sega/PicoDrive/LibPicoDrive.cs index 820ce63e14..425e99eb76 100644 --- a/BizHawk.Emulation.Cores/Consoles/Sega/PicoDrive/LibPicoDrive.cs +++ b/BizHawk.Emulation.Cores/Consoles/Sega/PicoDrive/LibPicoDrive.cs @@ -20,6 +20,15 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.PicoDrive [UnmanagedFunctionPointer(CC)] public delegate void CDReadCallback(int lba, IntPtr dest, bool audio); + public enum Region : int + { + Auto = 0, + JapanNTSC = 1, + JapanPAL = 2, + US = 4, + Europe = 8 + } + /// /// /// @@ -28,7 +37,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.PicoDrive /// 32X games will still run, but will not have memory domains /// [BizImport(CC)] - public abstract bool Init(bool cd, bool _32xPreinit); + public abstract bool Init(bool cd, bool _32xPreinit, Region regionAutoOrder, Region regionOverride); [BizImport(CC)] public abstract void SetCDReadCallback(CDReadCallback callback); diff --git a/BizHawk.Emulation.Cores/Consoles/Sega/PicoDrive/PicoDrive.cs b/BizHawk.Emulation.Cores/Consoles/Sega/PicoDrive/PicoDrive.cs index ddca184c04..826e3b1298 100644 --- a/BizHawk.Emulation.Cores/Consoles/Sega/PicoDrive/PicoDrive.cs +++ b/BizHawk.Emulation.Cores/Consoles/Sega/PicoDrive/PicoDrive.cs @@ -8,12 +8,14 @@ using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; using System.IO; +using BizHawk.Common; +using System.ComponentModel; namespace BizHawk.Emulation.Cores.Consoles.Sega.PicoDrive { [Core("PicoDrive", "notaz", true, true, "0e352905c7aa80b166933970abbcecfce96ad64e", "https://github.com/notaz/picodrive", false)] - public class PicoDrive : WaterboxCore, IDriveLight, IRegionable + public class PicoDrive : WaterboxCore, IDriveLight, IRegionable, ISettable { private LibPicoDrive _core; private LibPicoDrive.CDReadCallback _cdcallback; @@ -22,15 +24,15 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.PicoDrive private bool _isPal; [CoreConstructor("GEN")] - public PicoDrive(CoreComm comm, GameInfo game, byte[] rom, bool deterministic) - :this(comm, game, rom, null, deterministic) + public PicoDrive(CoreComm comm, GameInfo game, byte[] rom, bool deterministic, SyncSettings syncSettings) + : this(comm, game, rom, null, deterministic, syncSettings) { } - public PicoDrive(CoreComm comm, GameInfo game, Disc cd, bool deterministic) - :this(comm, game, null, cd, deterministic) + public PicoDrive(CoreComm comm, GameInfo game, Disc cd, bool deterministic, SyncSettings syncSettings) + : this(comm, game, null, cd, deterministic, syncSettings) { } - private PicoDrive(CoreComm comm, GameInfo game, byte[] rom, Disc cd, bool deterministic) + private PicoDrive(CoreComm comm, GameInfo game, byte[] rom, Disc cd, bool deterministic, SyncSettings syncSettings) : base(comm, new Configuration { MaxSamples = 2048, @@ -49,6 +51,8 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.PicoDrive throw new InvalidOperationException("32X BIOS files are required for deterministic mode"); deterministic |= has32xBios; + _syncSettings = syncSettings ?? new SyncSettings(); + _core = PreInit(new PeRunnerOptions { Filename = "picodrive.wbx", @@ -83,7 +87,12 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.PicoDrive _exe.AddReadonlyFile(rom, "romfile.md"); } - if (!_core.Init(cd != null, game["32X"])) + var regionAutoOrder = (LibPicoDrive.Region)( + (int)_syncSettings.FirstChoice | + (int)_syncSettings.SecondChoice << 4 | + (int)_syncSettings.ThirdChoice << 8); + + if (!_core.Init(cd != null, game["32X"], regionAutoOrder, _syncSettings.RegionOverride)) throw new InvalidOperationException("Core rejected the file!"); if (cd != null) @@ -174,6 +183,68 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.PicoDrive _core.SetCDReadCallback(_cdcallback); } + #region ISettable + + public class SyncSettings + { + [DefaultValue(LibPicoDrive.Region.Auto)] + [Description("If set, force the console to this region")] + public LibPicoDrive.Region RegionOverride { get; set; } + + [DefaultValue(LibPicoDrive.Region.Auto)] + [Description("When region is set to automatic, highest priority region to use if the game supports multiple regions")] + public LibPicoDrive.Region FirstChoice { get; set; } + + [DefaultValue(LibPicoDrive.Region.Auto)] + [Description("When region is set to automatic, second highest priority region to use if the game supports multiple regions")] + public LibPicoDrive.Region SecondChoice { get; set; } + + [DefaultValue(LibPicoDrive.Region.Auto)] + [Description("When region is set to automatic, lowest priority region to use if the game supports multiple regions")] + public LibPicoDrive.Region ThirdChoice { get; set; } + + public SyncSettings Clone() + { + return (SyncSettings)MemberwiseClone(); + } + + public static bool NeedsReboot(SyncSettings x, SyncSettings y) + { + return !DeepEquality.DeepEquals(x, y); + } + + public SyncSettings() + { + SettingsUtil.SetDefaultValues(this); + } + } + + private SyncSettings _syncSettings; + + public object GetSettings() + { + return new object(); + } + + public SyncSettings GetSyncSettings() + { + return _syncSettings.Clone(); + } + + public bool PutSettings(object o) + { + return false; + } + + public bool PutSyncSettings(SyncSettings o) + { + var ret = SyncSettings.NeedsReboot(_syncSettings, o); + _syncSettings = o; + return ret; + } + + #endregion + #region IDriveLight public bool DriveLightEnabled { get; private set; } diff --git a/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGX.IEmulator.cs b/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGX.IEmulator.cs index ed54dfcee5..e0a3ac20b1 100644 --- a/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGX.IEmulator.cs +++ b/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGX.IEmulator.cs @@ -7,20 +7,45 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx { public IEmulatorServiceProvider ServiceProvider { get; private set; } - public ControllerDefinition ControllerDefinition { get; private set; } - - // TODO: use render and rendersound + public ControllerDefinition ControllerDefinition { get; private set; } + + // TODO: use render and rendersound public void FrameAdvance(IController controller, bool render, bool rendersound = true) { if (controller.IsPressed("Reset")) Core.gpgx_reset(false); if (controller.IsPressed("Power")) - Core.gpgx_reset(true); - - // this shouldn't be needed, as nothing has changed - // if (!Core.gpgx_get_control(input, inputsize)) - // throw new Exception("gpgx_get_control() failed!"); - + Core.gpgx_reset(true); + if (_cds != null) + { + var prev = controller.IsPressed("Previous Disk"); + var next = controller.IsPressed("Next Disk"); + int newDisk = _discIndex; + if (prev && !_prevDiskPressed) + newDisk--; + if (next && !_nextDiskPressed) + newDisk++; + + _prevDiskPressed = prev; + _nextDiskPressed = next; + + if (newDisk < -1) + newDisk = -1; + if (newDisk >= _cds.Length) + newDisk = _cds.Length - 1; + + if (newDisk != _discIndex) + { + _discIndex = newDisk; + Core.gpgx_swap_disc(_discIndex == -1 ? null : GetCDDataStruct(_cds[_discIndex])); + Console.WriteLine("IMMA CHANGING MAH DISKS"); + } + } + + // this shouldn't be needed, as nothing has changed + // if (!Core.gpgx_get_control(input, inputsize)) + // throw new Exception("gpgx_get_control() failed!"); + ControlConverter.ScreenWidth = vwidth; ControlConverter.ScreenHeight = vheight; ControlConverter.Convert(controller, input); @@ -39,7 +64,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx if (IsLagFrame) LagCount++; - if (CD != null) + if (_cds != null) DriveLightOn = _drivelight; } @@ -70,8 +95,9 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx { if (_elf != null) _elf.Dispose(); - if (CD != null) - CD.Dispose(); + if (_cds != null) + foreach (var cd in _cds) + cd.Dispose(); _disposed = true; } } diff --git a/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGX.IStatable.cs b/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGX.IStatable.cs index a31c1233dc..312bc3e69c 100644 --- a/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGX.IStatable.cs +++ b/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGX.IStatable.cs @@ -36,6 +36,9 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx Frame = reader.ReadInt32(); LagCount = reader.ReadInt32(); IsLagFrame = reader.ReadBoolean(); + _discIndex = reader.ReadInt32(); + _prevDiskPressed = reader.ReadBoolean(); + _nextDiskPressed = reader.ReadBoolean(); // any managed pointers that we sent to the core need to be resent now! Core.gpgx_set_input_callback(InputCallback); RefreshMemCallbacks(); @@ -51,6 +54,9 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx writer.Write(Frame); writer.Write(LagCount); writer.Write(IsLagFrame); + writer.Write(_discIndex); + writer.Write(_prevDiskPressed); + writer.Write(_nextDiskPressed); } public byte[] SaveStateBinary() diff --git a/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGX.cs b/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGX.cs index b94e50ab42..fafb34dde3 100644 --- a/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGX.cs +++ b/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGX.cs @@ -7,6 +7,8 @@ using BizHawk.Emulation.Common; using BizHawk.Emulation.Cores.Waterbox; using BizHawk.Common; using BizHawk.Emulation.DiscSystem; +using System.Collections.Generic; +using System.Linq; namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx { @@ -27,7 +29,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx { } - public GPGX(CoreComm comm, byte[] rom, DiscSystem.Disc CD, object settings, object syncSettings) + public GPGX(CoreComm comm, byte[] rom, IEnumerable cds, object settings, object syncSettings) { ServiceProvider = new BasicServiceProvider(this); // this can influence some things internally (autodetect romtype, etc) @@ -63,13 +65,15 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx LoadCallback = new LibGPGX.load_archive_cb(load_archive); - this.romfile = rom; - this.CD = CD; - if (CD != null) + _romfile = rom; + + if (cds != null) { - this.DiscSectorReader = new DiscSystem.DiscSectorReader(CD); + _cds = cds.ToArray(); + _cdReaders = cds.Select(c => new DiscSectorReader(c)).ToArray(); cd_callback_handle = new LibGPGX.cd_read_cb(CDRead); Core.gpgx_set_cdd_callback(cd_callback_handle); + DriveLightEnabled = true; } LibGPGX.INPUT_SYSTEM system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_NONE; @@ -139,9 +143,6 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx InputCallback = new LibGPGX.input_cb(input_callback); Core.gpgx_set_input_callback(InputCallback); - if (CD != null) - DriveLightEnabled = true; - // process the non-init settings now PutSettings(_settings); @@ -154,14 +155,20 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx Tracer = new GPGXTraceBuffer(this, MemoryDomains, this); (ServiceProvider as BasicServiceProvider).Register(Tracer); } + + _romfile = null; } private LibGPGX Core; private PeRunner _elf; - DiscSystem.Disc CD; - DiscSystem.DiscSectorReader DiscSectorReader; - byte[] romfile; + private Disc[] _cds; + private int _discIndex; + private DiscSectorReader[] _cdReaders; + private bool _prevDiskPressed; + private bool _nextDiskPressed; + + byte[] _romfile; private bool _disposed = false; @@ -201,28 +208,28 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx if (filename == "PRIMARY_ROM") { - if (romfile == null) + if (_romfile == null) { Console.WriteLine("Couldn't satisfy firmware request PRIMARY_ROM because none was provided."); return 0; } - srcdata = romfile; + srcdata = _romfile; } else if (filename == "PRIMARY_CD" || filename == "SECONDARY_CD") { - if (filename == "PRIMARY_CD" && romfile != null) + if (filename == "PRIMARY_CD" && _romfile != null) { Console.WriteLine("Declined to satisfy firmware request PRIMARY_CD because PRIMARY_ROM was provided."); return 0; } else { - if (CD == null) + if (_cds == null) { Console.WriteLine("Couldn't satisfy firmware request {0} because none was provided.", filename); return 0; } - srcdata = GetCDData(CD); + srcdata = GetCDData(_cds[0]); if (srcdata.Length != maxsize) { Console.WriteLine("Couldn't satisfy firmware request {0} because of struct size.", filename); @@ -283,36 +290,38 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx void CDRead(int lba, IntPtr dest, bool audio) { - if (audio) + if ((uint)_discIndex < _cds.Length) { - byte[] data = new byte[2352]; - if (lba < CD.Session1.LeadoutLBA) + if (audio) { - DiscSectorReader.ReadLBA_2352(lba, data, 0); + byte[] data = new byte[2352]; + if (lba < _cds[_discIndex].Session1.LeadoutLBA) + { + _cdReaders[_discIndex].ReadLBA_2352(lba, data, 0); + } + else + { + // audio seems to read slightly past the end of disks; probably innoculous + // just send back 0s. + // Console.WriteLine("!!{0} >= {1}", lba, CD.LBACount); + } + Marshal.Copy(data, 0, dest, 2352); } else { - // audio seems to read slightly past the end of disks; probably innoculous - // just send back 0s. - // Console.WriteLine("!!{0} >= {1}", lba, CD.LBACount); + byte[] data = new byte[2048]; + _cdReaders[_discIndex].ReadLBA_2048(lba, data, 0); + Marshal.Copy(data, 0, dest, 2048); + _drivelight = true; } - Marshal.Copy(data, 0, dest, 2352); - } - else - { - byte[] data = new byte[2048]; - DiscSectorReader.ReadLBA_2048(lba, data, 0); - Marshal.Copy(data, 0, dest, 2048); - _drivelight = true; } } LibGPGX.cd_read_cb cd_callback_handle; - public static unsafe byte[] GetCDData(Disc cd) + public static LibGPGX.CDData GetCDDataStruct(Disc cd) { - LibGPGX.CDData ret = new LibGPGX.CDData(); - int size = Marshal.SizeOf(ret); + var ret = new LibGPGX.CDData(); var ses = cd.Session1; int ntrack = ses.InformationTrackCount; @@ -338,6 +347,13 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx } } + return ret; + } + + public static unsafe byte[] GetCDData(Disc cd) + { + var ret = GetCDDataStruct(cd); + int size = Marshal.SizeOf(ret); byte[] retdata = new byte[size]; fixed (byte* p = &retdata[0]) @@ -360,7 +376,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx if (!Core.gpgx_get_control(input, inputsize)) throw new Exception("gpgx_get_control() failed"); - ControlConverter = new GPGXControlConverter(input); + ControlConverter = new GPGXControlConverter(input, false); // _cds != null); ControllerDefinition = ControlConverter.ControllerDef; } @@ -369,7 +385,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx return (LibGPGX.INPUT_DEVICE[])input.dev.Clone(); } - public bool IsMegaCD { get { return CD != null; } } + public bool IsMegaCD { get { return _cds != null; } } public class VDPView : IMonitor { diff --git a/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGXControlConverter.cs b/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGXControlConverter.cs index f1af5af62f..99a7a7745b 100644 --- a/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGXControlConverter.cs +++ b/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGXControlConverter.cs @@ -175,7 +175,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx }); } - public GPGXControlConverter(LibGPGX.InputData input) + public GPGXControlConverter(LibGPGX.InputData input, bool cdButtons) { Console.WriteLine("Genesis Controller report:"); foreach (var e in input.system) @@ -189,6 +189,11 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx ControllerDef.BoolButtons.Add("Power"); ControllerDef.BoolButtons.Add("Reset"); + if (cdButtons) + { + ControllerDef.BoolButtons.Add("Previous Disk"); + ControllerDef.BoolButtons.Add("Next Disk"); + } for (int i = 0; i < LibGPGX.MAX_DEVICES; i++) { diff --git a/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/LibGPGX.cs b/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/LibGPGX.cs index aaea926d69..5892f53513 100644 --- a/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/LibGPGX.cs +++ b/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/LibGPGX.cs @@ -49,7 +49,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx public uint BackdropColor; } - [BizImport(CallingConvention.Cdecl, Compatibility=true)] + [BizImport(CallingConvention.Cdecl, Compatibility = true)] public abstract bool gpgx_init(string feromextension, load_archive_cb feload_archive_cb, bool sixbutton, INPUT_SYSTEM system_a, INPUT_SYSTEM system_b, Region region, [In]InitSettings settings); [BizImport(CallingConvention.Cdecl)] @@ -84,34 +84,34 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx public enum INPUT_SYSTEM : byte { - SYSTEM_NONE = 0, // unconnected port - SYSTEM_MD_GAMEPAD = 1, // single 3-buttons or 6-buttons Control Pad - SYSTEM_MOUSE = 2, // Sega Mouse - SYSTEM_MENACER = 3, // Sega Menacer -- port B only - SYSTEM_JUSTIFIER = 4, // Konami Justifiers -- port B only - SYSTEM_XE_A1P = 5, // XE-A1P analog controller -- port A only - SYSTEM_ACTIVATOR = 6, // Sega Activator - SYSTEM_MS_GAMEPAD = 7, // single 2-buttons Control Pad -- Master System - SYSTEM_LIGHTPHASER = 8, // Sega Light Phaser -- Master System - SYSTEM_PADDLE = 9, // Sega Paddle Control -- Master System - SYSTEM_SPORTSPAD = 10, // Sega Sports Pad -- Master System - SYSTEM_TEAMPLAYER = 11, // Multi Tap -- Sega TeamPlayer - SYSTEM_WAYPLAY = 12, // Multi Tap -- EA 4-Way Play -- use both ports + SYSTEM_NONE = 0, // unconnected port + SYSTEM_MD_GAMEPAD = 1, // single 3-buttons or 6-buttons Control Pad + SYSTEM_MOUSE = 2, // Sega Mouse + SYSTEM_MENACER = 3, // Sega Menacer -- port B only + SYSTEM_JUSTIFIER = 4, // Konami Justifiers -- port B only + SYSTEM_XE_A1P = 5, // XE-A1P analog controller -- port A only + SYSTEM_ACTIVATOR = 6, // Sega Activator + SYSTEM_MS_GAMEPAD = 7, // single 2-buttons Control Pad -- Master System + SYSTEM_LIGHTPHASER = 8, // Sega Light Phaser -- Master System + SYSTEM_PADDLE = 9, // Sega Paddle Control -- Master System + SYSTEM_SPORTSPAD = 10, // Sega Sports Pad -- Master System + SYSTEM_TEAMPLAYER = 11, // Multi Tap -- Sega TeamPlayer + SYSTEM_WAYPLAY = 12, // Multi Tap -- EA 4-Way Play -- use both ports }; public enum INPUT_DEVICE : byte { - DEVICE_NONE = 0xff, // unconnected device = fixed ID for Team Player) - DEVICE_PAD3B = 0x00, // 3-buttons Control Pad = fixed ID for Team Player) - DEVICE_PAD6B = 0x01, // 6-buttons Control Pad = fixed ID for Team Player) - DEVICE_PAD2B = 0x02, // 2-buttons Control Pad - DEVICE_MOUSE = 0x03, // Sega Mouse + DEVICE_NONE = 0xff, // unconnected device = fixed ID for Team Player) + DEVICE_PAD3B = 0x00, // 3-buttons Control Pad = fixed ID for Team Player) + DEVICE_PAD6B = 0x01, // 6-buttons Control Pad = fixed ID for Team Player) + DEVICE_PAD2B = 0x02, // 2-buttons Control Pad + DEVICE_MOUSE = 0x03, // Sega Mouse DEVICE_LIGHTGUN = 0x04, // Sega Light Phaser, Menacer or Konami Justifiers - DEVICE_PADDLE = 0x05, // Sega Paddle Control + DEVICE_PADDLE = 0x05, // Sega Paddle Control DEVICE_SPORTSPAD = 0x06,// Sega Sports Pad - DEVICE_PICO = 0x07, // PICO tablet - DEVICE_TEREBI = 0x08, // Terebi Oekaki tablet - DEVICE_XE_A1P = 0x09, // XE-A1P analog controller + DEVICE_PICO = 0x07, // PICO tablet + DEVICE_TEREBI = 0x08, // Terebi Oekaki tablet + DEVICE_XE_A1P = 0x09, // XE-A1P analog controller DEVICE_ACTIVATOR = 0x0a,// Activator }; @@ -151,8 +151,6 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx [BizImport(CallingConvention.Cdecl)] public abstract void gpgx_set_cd_callback(CDCallback cd); - - /// /// not every flag is valid for every device! /// @@ -277,6 +275,9 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx [BizImport(CallingConvention.Cdecl)] public abstract void gpgx_set_cdd_callback(cd_read_cb cddcb); + [BizImport(CallingConvention.Cdecl, Compatibility = true)] + public abstract void gpgx_swap_disc(CDData toc); + [StructLayout(LayoutKind.Sequential)] public struct VDPNameTable { diff --git a/BizHawk.Emulation.Cores/Properties/Resources.Designer.cs b/BizHawk.Emulation.Cores/Properties/Resources.Designer.cs index 59d6602caf..5a3bbcce9a 100644 --- a/BizHawk.Emulation.Cores/Properties/Resources.Designer.cs +++ b/BizHawk.Emulation.Cores/Properties/Resources.Designer.cs @@ -60,6 +60,26 @@ namespace BizHawk.Emulation.Cores.Properties { } } + /// + /// Looks up a localized resource of type System.Byte[]. + /// + internal static byte[] SameboyCgbBoot { + get { + object obj = ResourceManager.GetObject("SameboyCgbBoot", resourceCulture); + return ((byte[])(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Byte[]. + /// + internal static byte[] SameboyDmgBoot { + get { + object obj = ResourceManager.GetObject("SameboyDmgBoot", resourceCulture); + return ((byte[])(obj)); + } + } + /// /// Looks up a localized resource of type System.Byte[]. /// diff --git a/BizHawk.Emulation.Cores/Properties/Resources.resx b/BizHawk.Emulation.Cores/Properties/Resources.resx index 1378c9e6e9..bdb07b9a9f 100644 --- a/BizHawk.Emulation.Cores/Properties/Resources.resx +++ b/BizHawk.Emulation.Cores/Properties/Resources.resx @@ -118,6 +118,12 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + ..\Resources\cgb_boot.bin.gz;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + ..\Resources\dmg_boot.bin.gz;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + ..\Resources\sgb-cart-present.spc.gz;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 diff --git a/BizHawk.Emulation.Cores/Resources/cgb_boot.bin.gz b/BizHawk.Emulation.Cores/Resources/cgb_boot.bin.gz new file mode 100644 index 0000000000..ab0eb54bfd Binary files /dev/null and b/BizHawk.Emulation.Cores/Resources/cgb_boot.bin.gz differ diff --git a/BizHawk.Emulation.Cores/Resources/dmg_boot.bin.gz b/BizHawk.Emulation.Cores/Resources/dmg_boot.bin.gz new file mode 100644 index 0000000000..85f1e8276a Binary files /dev/null and b/BizHawk.Emulation.Cores/Resources/dmg_boot.bin.gz differ diff --git a/BizHawk.Emulation.Cores/Waterbox/PeRunner.cs b/BizHawk.Emulation.Cores/Waterbox/PeRunner.cs index 1db3950b0a..080b91e4b3 100644 --- a/BizHawk.Emulation.Cores/Waterbox/PeRunner.cs +++ b/BizHawk.Emulation.Cores/Waterbox/PeRunner.cs @@ -308,6 +308,68 @@ namespace BizHawk.Emulation.Cores.Waterbox } } + private class TransientFile : IFileObject + { + private bool _inUse = false; + public string Name { get; } + public Stream Stream { get; } + public bool Close() + { + if (_inUse) + { + _inUse = false; + return true; + } + else + { + return false; + } + } + + public bool Open(FileAccess access) + { + if (_inUse) + { + return false; + } + else + { + // TODO: if access != RW, the resultant handle lets you do those all anyway + _inUse = true; + Stream.Position = 0; + return true; + } + } + + public void LoadStateBinary(BinaryReader br) + { + throw new InvalidOperationException("Internal savestate error!"); + } + + public void SaveStateBinary(BinaryWriter bw) + { + throw new InvalidOperationException("Transient files cannot be savestated!"); + } + + public TransientFile(byte[] data, string name) + { + Stream = new MemoryStream(); + Name = name; + if (data != null) + { + Stream.Write(data, 0, data.Length); + Stream.Position = 0; + } + } + + public byte[] GetContents() + { + if (_inUse) + throw new InvalidOperationException(); + return ((MemoryStream)Stream).ToArray(); + } + } + private readonly List _openFiles = new List(); private readonly Dictionary _availableFiles = new Dictionary(); @@ -697,6 +759,21 @@ namespace BizHawk.Emulation.Cores.Waterbox } } + + private T RemoveFileInternal(string name) + where T : IFileObject + { + IFileObject o; + if (!_availableFiles.TryGetValue(name, out o)) + throw new InvalidOperationException("File was never registered!"); + if (o.GetType() != typeof(T)) + throw new InvalidOperationException("Object was not a the right kind of file"); + if (_openFiles.Contains(o)) + throw new InvalidOperationException("Core never closed the file!"); + _availableFiles.Remove(name); + return (T)o; + } + public void AddReadonlyFile(byte[] data, string name) { _availableFiles.Add(name, new ReadonlyFirmware(data, name)); @@ -704,15 +781,16 @@ namespace BizHawk.Emulation.Cores.Waterbox public void RemoveReadonlyFile(string name) { - IFileObject o; - if (!_availableFiles.TryGetValue(name, out o)) - throw new InvalidOperationException("Firmware was never registered!"); - var f = o as ReadonlyFirmware; - if (f == null) - throw new InvalidOperationException("Object was not a firmware!"); - if (_openFiles.Contains(o)) - throw new InvalidOperationException("Core never closed the firmware!"); - _availableFiles.Remove(name); + RemoveFileInternal(name); + } + + public void AddTransientFile(byte[] data, string name) + { + _availableFiles.Add(name, new TransientFile(data, name)); + } + public byte[] RemoveTransientFile(string name) + { + return RemoveFileInternal(name).GetContents(); } } @@ -1090,6 +1168,24 @@ namespace BizHawk.Emulation.Cores.Waterbox _syscalls.RemoveReadonlyFile(name); } + /// + /// Add a transient file that will appear to the waterbox core's libc. The file will be readable + /// and writable. Any attempt to save state while the file is loaded will fail. + /// + public void AddTransientFile(byte[] data, string name) + { + _syscalls.AddTransientFile(data, name); // don't need to clone data, as it's used at init only + } + + /// + /// Remove a file previously added by AddTransientFile + /// + /// The state of the file when it was removed + public byte[] RemoveTransientFile(string name) + { + return _syscalls.RemoveTransientFile(name); + } + public void SaveStateBinary(BinaryWriter bw) { bw.Write(_createstamp); diff --git a/BizHawk.Emulation.Cores/Waterbox/PeWrapper.cs b/BizHawk.Emulation.Cores/Waterbox/PeWrapper.cs index 14bba95a76..8f2e5d3d28 100644 --- a/BizHawk.Emulation.Cores/Waterbox/PeWrapper.cs +++ b/BizHawk.Emulation.Cores/Waterbox/PeWrapper.cs @@ -344,6 +344,13 @@ namespace BizHawk.Emulation.Cores.Waterbox Marshal.Copy(Z.US(_imports.Start), impData, 0, (int)_imports.Size); WaterboxUtils.ZeroMemory(Z.US(_imports.Start), (long)_imports.Size); } + byte[] invData = null; + if (_invisible != null) + { + invData = new byte[_invisible.Size]; + Marshal.Copy(Z.US(_invisible.Start), invData, 0, (int)_invisible.Size); + WaterboxUtils.ZeroMemory(Z.US(_invisible.Start), (long)_invisible.Size); + } Memory.SaveXorSnapshot(); if (_imports != null) { @@ -351,6 +358,10 @@ namespace BizHawk.Emulation.Cores.Waterbox _imports.W = false; Memory.Protect(_imports.Start, _imports.Size, _imports.Prot); } + if (_invisible != null) + { + Marshal.Copy(invData, 0, Z.US(_invisible.Start), (int)_invisible.Size); + } if (_sealed != null) { _sealed.W = false; diff --git a/Bizware/BizHawk.Bizware.BizwareGL.OpenTK/IGL_TK.cs b/Bizware/BizHawk.Bizware.BizwareGL.OpenTK/IGL_TK.cs index 7bf1154656..0dd236b7b7 100644 --- a/Bizware/BizHawk.Bizware.BizwareGL.OpenTK/IGL_TK.cs +++ b/Bizware/BizHawk.Bizware.BizwareGL.OpenTK/IGL_TK.cs @@ -346,6 +346,11 @@ namespace BizHawk.Bizware.BizwareGL.Drivers.OpenTK public void FreePipeline(Pipeline pipeline) { var pw = pipeline.Opaque as PipelineWrapper; + + //unavailable pipelines will have no opaque + if (pw == null) + return; + GL.DeleteProgram(pw.pid); pw.FragmentShader.Release(); @@ -686,9 +691,13 @@ namespace BizHawk.Bizware.BizwareGL.Drivers.OpenTK { var cgc = new CGC(); var results = cgc.Run(source, entry, type == ShaderType.FragmentShader ? "glslf" : "glslv", false); - + if (!results.Succeeded) + { + Console.WriteLine("CGC failed"); + Console.WriteLine(results.Errors); return new Shader(this, null, false); + } source = results.Code; sw.MapCodeToNative = results.MapCodeToNative; diff --git a/LuaInterface/Lua/src/LuaDLL.cpp b/LuaInterface/Lua/src/LuaDLL.cpp index d191a1444a..67ac0c4e21 100644 --- a/LuaInterface/Lua/src/LuaDLL.cpp +++ b/LuaInterface/Lua/src/LuaDLL.cpp @@ -618,6 +618,18 @@ namespace Lua511 static void lua_atunlock(IntPtr luaState, LuaCSFunction^ unlockf); #endif + //zero 22-jul-2017 + static int lua_pushthread(IntPtr luaState) + { + return ::lua_pushthread(((lua_State *)luaState.ToPointer())); + } + + static void lua_xmove(IntPtr from, IntPtr to, int n) + { + ::lua_xmove(((lua_State *)from.ToPointer()), ((lua_State *)to.ToPointer()),n); + } + + static void lua_pushnumber(IntPtr luaState, double number) { ::lua_pushnumber(toState, number); diff --git a/LuaInterface/LuaInterface/Lua.cs b/LuaInterface/LuaInterface/Lua.cs index bf4dc94404..5e9bb9065c 100644 --- a/LuaInterface/LuaInterface/Lua.cs +++ b/LuaInterface/LuaInterface/Lua.cs @@ -68,7 +68,7 @@ namespace NLua "-- Preload the mscorlib assembly \n"+ "luanet.load_assembly(\"mscorlib\") \n"; - /*readonly */ IntPtr luaState; + /*readonly */ public IntPtr luaState; //zero 22-jul-2017 - made public ObjectTranslator translator; LuaCSFunction panicCallback, lockCallback, unlockCallback; diff --git a/LuaInterface/LuaInterface/ObjectTranslator.cs b/LuaInterface/LuaInterface/ObjectTranslator.cs index 5235c1412b..193763378f 100644 --- a/LuaInterface/LuaInterface/ObjectTranslator.cs +++ b/LuaInterface/LuaInterface/ObjectTranslator.cs @@ -803,6 +803,13 @@ namespace NLua { ((LuaFunction)o).push(luaState); } + //zero 22-jul-2017 + else if (o is Lua) + { + var lua = o as Lua; + LuaDLL.lua_pushthread(lua.luaState); + LuaDLL.lua_xmove(lua.luaState, luaState, 1); + } else { pushObject(luaState,o,"luaNet_metatable"); diff --git a/output/dll/LuaInterface.dll b/output/dll/LuaInterface.dll index 3f048ff5da..f566c8a5a4 100644 Binary files a/output/dll/LuaInterface.dll and b/output/dll/LuaInterface.dll differ diff --git a/output/dll/OpenAL32.dll b/output/dll/OpenAL32.dll new file mode 100644 index 0000000000..259177ac33 Binary files /dev/null and b/output/dll/OpenAL32.dll differ diff --git a/output/dll/gpgx.wbx.gz b/output/dll/gpgx.wbx.gz index fc7827b49e..3a0c836d14 100644 Binary files a/output/dll/gpgx.wbx.gz and b/output/dll/gpgx.wbx.gz differ diff --git a/output/dll/lua51.dll b/output/dll/lua51.dll index fd053342d1..09644398cf 100644 Binary files a/output/dll/lua51.dll and b/output/dll/lua51.dll differ diff --git a/output/dll/mgba.dll b/output/dll/mgba.dll index 12a7522a86..df75e9790d 100644 Binary files a/output/dll/mgba.dll and b/output/dll/mgba.dll differ diff --git a/output/dll/nlua/KopiLua.dll b/output/dll/nlua/KopiLua.dll index 0c58ba7027..5d1f39048f 100644 Binary files a/output/dll/nlua/KopiLua.dll and b/output/dll/nlua/KopiLua.dll differ diff --git a/output/dll/nlua/NLua.dll b/output/dll/nlua/NLua.dll index 59fe2bc9d5..5bdc058e66 100644 Binary files a/output/dll/nlua/NLua.dll and b/output/dll/nlua/NLua.dll differ diff --git a/output/dll/pcfx.wbx.gz b/output/dll/pcfx.wbx.gz index a8d7576f4a..855f4fea14 100644 Binary files a/output/dll/pcfx.wbx.gz and b/output/dll/pcfx.wbx.gz differ diff --git a/output/dll/picodrive.wbx.gz b/output/dll/picodrive.wbx.gz index d6e2dbd967..d1426e85ab 100644 Binary files a/output/dll/picodrive.wbx.gz and b/output/dll/picodrive.wbx.gz differ diff --git a/output/dll/pizza.wbx.gz b/output/dll/pizza.wbx.gz deleted file mode 100644 index 3df3e57b0f..0000000000 Binary files a/output/dll/pizza.wbx.gz and /dev/null differ diff --git a/output/dll/sameboy.wbx.gz b/output/dll/sameboy.wbx.gz new file mode 100644 index 0000000000..10f48206a4 Binary files /dev/null and b/output/dll/sameboy.wbx.gz differ diff --git a/output/dll/vb.wbx.gz b/output/dll/vb.wbx.gz index cda73284d9..cec6e7d75b 100644 Binary files a/output/dll/vb.wbx.gz and b/output/dll/vb.wbx.gz differ diff --git a/output/dll/wrap_oal.dll b/output/dll/wrap_oal.dll new file mode 100644 index 0000000000..2713dae65a Binary files /dev/null and b/output/dll/wrap_oal.dll differ diff --git a/waterbox/emulibc/emulibc.h b/waterbox/emulibc/emulibc.h index da0eccc7c8..29d0ff7baa 100644 --- a/waterbox/emulibc/emulibc.h +++ b/waterbox/emulibc/emulibc.h @@ -10,7 +10,11 @@ extern "C" { // mark an entry point or callback pointer #define ECL_ENTRY // mark a visible symbol +#ifdef __cplusplus +#define ECL_EXPORT extern "C" __attribute__((visibility("default"))) +#else #define ECL_EXPORT __attribute__((visibility("default"))) +#endif // allocate memory from the "sealed" pool. this memory can never be freed, // and can only be allocated or written to during the init phase. after that, the host diff --git a/waterbox/gpgx/cinterface/cinterface.c b/waterbox/gpgx/cinterface/cinterface.c index 9f2c53217c..84efe5fa24 100644 --- a/waterbox/gpgx/cinterface/cinterface.c +++ b/waterbox/gpgx/cinterface/cinterface.c @@ -192,6 +192,14 @@ GPGX_EX void gpgx_advance(void) nsamples = audio_update(soundbuffer); } +GPGX_EX void gpgx_swap_disc(const toc_t* toc) +{ + if (system_hw == SYSTEM_MCD) + { + cdd_hotswap(toc); + } +} + typedef struct { uint32 width; // in cells diff --git a/waterbox/gpgx/core/cd_hw/cdd.c b/waterbox/gpgx/core/cd_hw/cdd.c index 0eb4890317..cfebb81a45 100644 --- a/waterbox/gpgx/core/cd_hw/cdd.c +++ b/waterbox/gpgx/core/cd_hw/cdd.c @@ -1,826 +1,841 @@ -/*************************************************************************************** - * Genesis Plus - * CD drive processor & CD-DA fader - * - * Copyright (C) 2012-2013 Eke-Eke (Genesis Plus GX) - * - * Redistribution and use of this code or any derivative works are permitted - * provided that the following conditions are met: - * - * - Redistributions may not be sold, nor may they be used in a commercial - * product or activity. - * - * - Redistributions that are modified from the original source must include the - * complete source code, including the source code for all components used by a - * binary built from the modified sources. However, as a special exception, the - * source code distributed need not include anything that is normally distributed - * (in either source or binary form) with the major components (compiler, kernel, - * and so on) of the operating system on which the executable runs, unless that - * component itself accompanies the executable. - * - * - Redistributions must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - ****************************************************************************************/ -#include "shared.h" -#include "../cinterface/callbacks.h" - -/* BCD conversion lookup tables */ -static const uint8 lut_BCD_8[100] = -{ - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, - 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, - 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, - 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, - 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, - 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, - 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, - 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, -}; - -static const uint16 lut_BCD_16[100] = -{ - 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, - 0x0100, 0x0101, 0x0102, 0x0103, 0x0104, 0x0105, 0x0106, 0x0107, 0x0108, 0x0109, - 0x0200, 0x0201, 0x0202, 0x0203, 0x0204, 0x0205, 0x0206, 0x0207, 0x0208, 0x0209, - 0x0300, 0x0301, 0x0302, 0x0303, 0x0304, 0x0305, 0x0306, 0x0307, 0x0308, 0x0309, - 0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0406, 0x0407, 0x0408, 0x0409, - 0x0500, 0x0501, 0x0502, 0x0503, 0x0504, 0x0505, 0x0506, 0x0507, 0x0508, 0x0509, - 0x0600, 0x0601, 0x0602, 0x0603, 0x0604, 0x0605, 0x0606, 0x0607, 0x0608, 0x0609, - 0x0700, 0x0701, 0x0702, 0x0703, 0x0704, 0x0705, 0x0706, 0x0707, 0x0708, 0x0709, - 0x0800, 0x0801, 0x0802, 0x0803, 0x0804, 0x0805, 0x0806, 0x0807, 0x0808, 0x0809, - 0x0900, 0x0901, 0x0902, 0x0903, 0x0904, 0x0905, 0x0906, 0x0907, 0x0908, 0x0909, -}; - -/* pre-build TOC */ -static const uint16 toc_snatcher[21] = -{ - 56014, 495, 10120, 20555, 1580, 5417, 12502, 16090, 6553, 9681, - 8148, 20228, 8622, 6142, 5858, 1287, 7424, 3535, 31697, 2485, - 31380 -}; - -static const uint16 toc_lunar[52] = -{ - 5422, 1057, 7932, 5401, 6380, 6592, 5862, 5937, 5478, 5870, - 6673, 6613, 6429, 4996, 4977, 5657, 3720, 5892, 3140, 3263, - 6351, 5187, 3249, 1464, 1596, 1750, 1751, 6599, 4578, 5205, - 1550, 1827, 2328, 1346, 1569, 1613, 7199, 4928, 1656, 2549, - 1875, 3901, 1850, 2399, 2028, 1724, 4889, 14551, 1184, 2132, - 685, 3167 -}; - -static const uint32 toc_shadow[15] = -{ - 10226, 70054, 11100, 12532, 12444, 11923, 10059, 10167, 10138, 13792, - 11637, 2547, 2521, 3856, 900 -}; - -static const uint32 toc_dungeon[13] = -{ - 2250, 22950, 16350, 24900, 13875, 19950, 13800, 15375, 17400, 17100, - 3325, 6825, 25275 -}; - -static const uint32 toc_ffight[26] = -{ - 11994, 9742, 10136, 9685, 9553, 14588, 9430, 8721, 9975, 9764, - 9704, 12796, 585, 754, 951, 624, 9047, 1068, 817, 9191, 1024, - 14562, 10320, 8627, 3795, 3047 -}; - -static const uint32 toc_ffightj[29] = -{ - 11994, 9752, 10119, 9690, 9567, 14575, 9431, 8731, 9965, 9763, - 9716, 12791, 579, 751, 958, 630, 9050, 1052, 825, 9193, 1026, - 14553, 9834, 10542, 1699, 1792, 1781, 3783, 3052 -}; - -/* supported WAVE file header (16-bit stereo samples @44.1kHz) */ -static const unsigned char waveHeader[32] = -{ - 0x57,0x41,0x56,0x45,0x66,0x6d,0x74,0x20,0x10,0x00,0x00,0x00,0x01,0x00,0x02,0x00, - 0x44,0xac,0x00,0x00,0x10,0xb1,0x02,0x00,0x04,0x00,0x10,0x00,0x64,0x61,0x74,0x61 -}; - -static blip_t* blip[2]; - -typedef struct -{ - toc_t toc; -} frontendcd_t; - -int cdd_load(const char *key, char *header) -{ - frontendcd_t fecd; - char data[2048]; - int startoffs; - - - int bytes = sizeof(frontendcd_t); - if (load_archive(key, (unsigned char *)&fecd, bytes, NULL) != bytes) - return 0; - - // look for valid header - cdd_readcallback(0, data, 0); - if (memcmp("SEGADISCSYSTEM", data, 14) == 0) - startoffs = 0; - else if (memcmp("SEGADISCSYSTEM", data + 16, 14) == 0) - startoffs = 16; - else - return 0; - // copy security block - memcpy(header, data + startoffs, 0x210); - - // copy disk information - memcpy(&cdd.toc, &fecd.toc, sizeof(toc_t)); - - cdd.loaded = 1; - return 1; -} - -void cdd_init(blip_t* left, blip_t* right) -{ - /* CD-DA is running by default at 44100 Hz */ - /* Audio stream is resampled to desired rate using Blip Buffer */ - blip[0] = left; - blip[1] = right; - blip_set_rates(left, 44100, snd.sample_rate); - blip_set_rates(right, 44100, snd.sample_rate); -} - -void cdd_reset(void) -{ - /* reset cycle counter */ - cdd.cycles = 0; - - /* reset drive access latency */ - cdd.latency = 0; - - /* reset track index */ - cdd.index = 0; - - /* reset logical block address */ - cdd.lba = 0; - - // reset audio subblock position - cdd.sampleOffset = 0; - - // reset audio read position - cdd.sampleLba = 0; - - /* reset status */ - cdd.status = cdd.loaded ? CD_STOP : NO_DISC; - - /* reset CD-DA fader (full volume) */ - cdd.volume = 0x400; - - /* clear CD-DA output */ - cdd.audio[0] = cdd.audio[1] = 0; -} - -void cdd_unload(void) -{ - cdd.loaded = 0; - cdd_readcallback = NULL; - - /* reset TOC */ - memset(&cdd.toc, 0x00, sizeof(cdd.toc)); -} - -void cdd_read_data(uint8 *dst) -{ - /* only read DATA track sectors */ - if ((cdd.lba >= 0) && (cdd.lba < cdd.toc.tracks[0].end)) - { - cdd_readcallback(cdd.lba, dst, 0); - } -} - -void cdd_read_audio(unsigned int samples) -{ - // previous audio outputs // - int16 l = cdd.audio[0]; - int16 r = cdd.audio[1]; - - // get number of internal clocks (samples) needed // - samples = blip_clocks_needed(blip[0], samples); - - // audio track playing ? // - if (!scd.regs[0x36>>1].byte.h) - { - int i, mul, delta; - - // current CD-DA fader volume // - int curVol = cdd.volume; - - // CD-DA fader volume setup (0-1024) // - int endVol = scd.regs[0x34>>1].w >> 4; - - // read samples from current block // - { -#ifdef LSB_FIRST - int16 *ptr = (int16 *) (cdc.ram); -#else - uint8 *ptr = cdc.ram; -#endif - { - char scratch[2352]; - // copy the end of current sector - int nsampreq = samples; - unsigned char *dest = cdc.ram; - cdd_readcallback(cdd.sampleLba, scratch, 1); - memcpy(cdc.ram, scratch + cdd.sampleOffset * 4, 2352 - cdd.sampleOffset * 4); - cdd.sampleLba++; - nsampreq -= 588 - cdd.sampleOffset; - dest += 2352 - cdd.sampleOffset * 4; - cdd.sampleOffset = 0; - // fill full sectors - while (nsampreq >= 588) - { - cdd_readcallback(cdd.sampleLba, scratch, 1); - memcpy(dest, scratch, 2352); - cdd.sampleLba++; - nsampreq -= 588; - dest += 2352; - } - // do last partial sector - if (nsampreq > 0) - { - cdd_readcallback(cdd.sampleLba, scratch, 1); - memcpy(dest, scratch, nsampreq * 4); - cdd.sampleOffset = nsampreq; - dest += nsampreq * 4; - nsampreq = 0; - } - //printf("samples: %i\n", samples); - //memset(cdc.ram, 0, samples * 4); - //fread(cdc.ram, 1, samples * 4, cdd.toc.tracks[cdd.index].fd); - } - - // process 16-bit (little-endian) stereo samples // - for (i=0; i endVol) - { - // fade-out // - curVol--; - } - else if (!curVol) - { - // audio will remain muted until next setup // - break; - } - } - } - - // save current CD-DA fader volume // - cdd.volume = curVol; - - // save last audio output for next frame // - cdd.audio[0] = l; - cdd.audio[1] = r; - } - else - { - // no audio output // - if (l) blip_add_delta_fast(blip[0], 0, -l); - if (r) blip_add_delta_fast(blip[1], 0, -r); - - // save audio output for next frame // - cdd.audio[0] = 0; - cdd.audio[1] = 0; - } - - // end of Blip Buffer timeframe // - blip_end_frame(blip[0], samples); - blip_end_frame(blip[1], samples); -} - - -void cdd_update(void) -{ -#ifdef LOG_CDD - error("LBA = %d (track n°%d)(latency=%d)\n", cdd.lba, cdd.index, cdd.latency); -#endif - - /* seeking disc */ - if (cdd.status == CD_SEEK) - { - /* drive latency */ - if (cdd.latency > 0) - { - cdd.latency--; - return; - } - - /* drive is ready */ - cdd.status = CD_READY; - } - - /* reading disc */ - else if (cdd.status == CD_PLAY) - { - /* drive latency */ - if (cdd.latency > 0) - { - cdd.latency--; - return; - } - - /* track type */ - if (!cdd.index) - { - /* DATA sector header (CD-ROM Mode 1) */ - uint8 header[4]; - uint32 msf = cdd.lba + 150; - header[0] = lut_BCD_8[(msf / 75) / 60]; - header[1] = lut_BCD_8[(msf / 75) % 60]; - header[2] = lut_BCD_8[(msf % 75)]; - header[3] = 0x01; - - /* data track sector read is controlled by CDC */ - cdd.lba += cdc_decoder_update(*(uint32 *)(header)); - } - else if (cdd.index < cdd.toc.last) - { - /* check against audio track start index */ - if (cdd.lba >= cdd.toc.tracks[cdd.index].start) - { - /* audio track playing */ - // if it wasn't before, set the audio start position - if (scd.regs[0x36>>1].byte.h) - { - cdd.sampleLba = cdd.lba + 1; - cdd.sampleOffset = 0; - } - scd.regs[0x36>>1].byte.h = 0x00; - } - - /* audio blocks are still sent to CDC as well as CD DAC/Fader */ - cdc_decoder_update(0); - - /* next audio block is automatically read */ - cdd.lba++; - } - else - { - /* end of disc */ - cdd.status = CD_END; - return; - } - - /* check end of current track */ - if (cdd.lba >= cdd.toc.tracks[cdd.index].end) - { - /* play next track */ - cdd.index++; - - /* PAUSE between tracks */ - scd.regs[0x36>>1].byte.h = 0x01; - } - } - - /* scanning disc */ - else if (cdd.status == CD_SCAN) - { - /* fast-forward or fast-rewind */ - cdd.lba += cdd.scanOffset; - cdd.sampleLba += cdd.scanOffset; - - /* check current track limits */ - if (cdd.lba >= cdd.toc.tracks[cdd.index].end) - { - /* next track */ - cdd.index++; - - /* skip directly to track start position */ - cdd.lba = cdd.toc.tracks[cdd.index].start; - - /* AUDIO track playing ? */ - if (cdd.status == CD_PLAY) - { - scd.regs[0x36>>1].byte.h = 0x00; - // set audio start point - cdd.sampleLba = cdd.lba; - cdd.sampleOffset = 0; - } - } - else if (cdd.lba < cdd.toc.tracks[cdd.index].start) - { - /* previous track */ - cdd.index--; - - /* skip directly to track end position */ - cdd.lba = cdd.toc.tracks[cdd.index].end; - } - - /* check disc limits */ - if (cdd.index < 0) - { - cdd.index = 0; - cdd.lba = 0; - } - else if (cdd.index >= cdd.toc.last) - { - /* no AUDIO track playing */ - scd.regs[0x36>>1].byte.h = 0x01; - - /* end of disc */ - cdd.index = cdd.toc.last; - cdd.lba = cdd.toc.end; - cdd.status = CD_END; - return; - } - } -} - -void cdd_process(void) -{ - /* Process CDD command */ - switch (scd.regs[0x42>>1].byte.h & 0x0f) - { - case 0x00: /* Drive Status */ - { - /* RS1-RS8 normally unchanged */ - scd.regs[0x38>>1].byte.h = cdd.status; - - /* unless RS1 indicated invalid track infos */ - if (scd.regs[0x38>>1].byte.l == 0x0f) - { - /* and SEEK has ended */ - if (cdd.status != CD_SEEK) - { - /* then return valid track infos, e.g current track number in RS2-RS3 (fixes Lunar - The Silver Star) */ - scd.regs[0x38>>1].byte.l = 0x02; - scd.regs[0x3a>>1].w = (cdd.index < cdd.toc.last) ? lut_BCD_16[cdd.index + 1] : 0x0A0A; - } - } - break; - } - - case 0x01: /* Stop Drive */ - { - /* update status */ - cdd.status = cdd.loaded ? CD_STOP : NO_DISC; - - /* no audio track playing */ - scd.regs[0x36>>1].byte.h = 0x01; - - /* RS1-RS8 ignored, expects 0x0 ("no disc" ?) in RS0 once */ - scd.regs[0x38>>1].w = 0x0000; - scd.regs[0x3a>>1].w = 0x0000; - scd.regs[0x3c>>1].w = 0x0000; - scd.regs[0x3e>>1].w = 0x0000; - scd.regs[0x40>>1].w = 0x000f; - return; - } - - case 0x02: /* Read TOC */ - { - /* Infos automatically retrieved by CDD processor from Q-Channel */ - /* commands 0x00-0x02 (current block) and 0x03-0x05 (Lead-In) */ - switch (scd.regs[0x44>>1].byte.l) - { - case 0x00: /* Current Absolute Time (MM:SS:FF) */ - { - int lba = cdd.lba + 150; - scd.regs[0x38>>1].w = cdd.status << 8; - scd.regs[0x3a>>1].w = lut_BCD_16[(lba/75)/60]; - scd.regs[0x3c>>1].w = lut_BCD_16[(lba/75)%60]; - scd.regs[0x3e>>1].w = lut_BCD_16[(lba%75)]; - scd.regs[0x40>>1].byte.h = cdd.index ? 0x00 : 0x04; /* Current block flags in RS8 (bit0 = mute status, bit1: pre-emphasis status, bit2: track type) */ - break; - } - - case 0x01: /* Current Track Relative Time (MM:SS:FF) */ - { - int lba = cdd.lba - cdd.toc.tracks[cdd.index].start; - scd.regs[0x38>>1].w = (cdd.status << 8) | 0x01; - scd.regs[0x3a>>1].w = lut_BCD_16[(lba/75)/60]; - scd.regs[0x3c>>1].w = lut_BCD_16[(lba/75)%60]; - scd.regs[0x3e>>1].w = lut_BCD_16[(lba%75)]; - scd.regs[0x40>>1].byte.h = cdd.index ? 0x00 : 0x04; /* Current block flags in RS8 (bit0 = mute status, bit1: pre-emphasis status, bit2: track type) */ - break; - } - - case 0x02: /* Current Track Number */ - { - scd.regs[0x38>>1].w = (cdd.status << 8) | 0x02; - scd.regs[0x3a>>1].w = (cdd.index < cdd.toc.last) ? lut_BCD_16[cdd.index + 1] : 0x0A0A; - scd.regs[0x3c>>1].w = 0x0000; - scd.regs[0x3e>>1].w = 0x0000; /* Disk Control Code (?) in RS6 */ - scd.regs[0x40>>1].byte.h = 0x00; - break; - } - - case 0x03: /* Total length (MM:SS:FF) */ - { - int lba = cdd.toc.end + 150; - scd.regs[0x38>>1].w = (cdd.status << 8) | 0x03; - scd.regs[0x3a>>1].w = lut_BCD_16[(lba/75)/60]; - scd.regs[0x3c>>1].w = lut_BCD_16[(lba/75)%60]; - scd.regs[0x3e>>1].w = lut_BCD_16[(lba%75)]; - scd.regs[0x40>>1].byte.h = 0x00; - break; - } - - case 0x04: /* First & Last Track Numbers */ - { - scd.regs[0x38>>1].w = (cdd.status << 8) | 0x04; - scd.regs[0x3a>>1].w = 0x0001; - scd.regs[0x3c>>1].w = lut_BCD_16[cdd.toc.last]; - scd.regs[0x3e>>1].w = 0x0000; /* Drive Version (?) in RS6-RS7 */ - scd.regs[0x40>>1].byte.h = 0x00; /* Lead-In flags in RS8 (bit0 = mute status, bit1: pre-emphasis status, bit2: track type) */ - break; - } - - case 0x05: /* Track Start Time (MM:SS:FF) */ - { - int track = scd.regs[0x46>>1].byte.h * 10 + scd.regs[0x46>>1].byte.l; - int lba = cdd.toc.tracks[track-1].start + 150; - scd.regs[0x38>>1].w = (cdd.status << 8) | 0x05; - scd.regs[0x3a>>1].w = lut_BCD_16[(lba/75)/60]; - scd.regs[0x3c>>1].w = lut_BCD_16[(lba/75)%60]; - scd.regs[0x3e>>1].w = lut_BCD_16[(lba%75)]; - scd.regs[0x40>>1].byte.h = track % 10; /* Track Number (low digit) */ - if (track == 1) - { - /* RS6 bit 3 is set for the first (DATA) track */ - scd.regs[0x3e>>1].byte.h |= 0x08; - } - break; - } - - default: - { -#ifdef LOG_ERROR - error("Unknown CDD Command %02X (%X)\n", scd.regs[0x44>>1].byte.l, s68k.pc); -#endif - return; - } - } - break; - } - - case 0x03: /* Play */ - { - /* reset track index */ - int index = 0; - - /* new LBA position */ - int lba = ((scd.regs[0x44>>1].byte.h * 10 + scd.regs[0x44>>1].byte.l) * 60 + - (scd.regs[0x46>>1].byte.h * 10 + scd.regs[0x46>>1].byte.l)) * 75 + - (scd.regs[0x48>>1].byte.h * 10 + scd.regs[0x48>>1].byte.l) - 150; - - /* CD drive latency */ - if (!cdd.latency) - { - /* Fixes a few games hanging during intro because they expect data to be read with some delay */ - /* Radical Rex needs at least one interrupt delay */ - /* Wolf Team games (Anet Futatabi, Cobra Command, Road Avenger & Time Gal) need at least 6 interrupts delay */ - /* Space Adventure Cobra (2nd morgue scene) needs at least 13 interrupts delay (incl. seek time, so 6 is OK) */ - /* Jeopardy & ESPN Sunday Night NFL are picky about this as well: 10 interrupts delay (+ seek time) seems OK */ - cdd.latency = 10; - } - - /* CD drive seek time */ - /* max. seek time = 1.5 s = 1.5 x 75 = 112.5 CDD interrupts (rounded to 120) for 270000 sectors max on disc. */ - /* Note: This is only a rough approximation since, on real hardware, seek time is much likely not linear and */ - /* latency much larger than above value, but this model works fine for Sonic CD (track 26 playback needs to */ - /* be enough delayed to start in sync with intro sequence, as compared with real hardware recording). */ - if (lba > cdd.lba) - { - cdd.latency += (((lba - cdd.lba) * 120) / 270000); - } - else - { - cdd.latency += (((cdd.lba - lba) * 120) / 270000); - } - - /* update current LBA */ - cdd.lba = lba; - - /* get track index */ - while ((cdd.toc.tracks[index].end <= lba) && (index < cdd.toc.last)) index++; - - /* update current track index */ - cdd.index = index; - - /* no audio track playing (yet) */ - scd.regs[0x36>>1].byte.h = 0x01; - - /* update status */ - cdd.status = CD_PLAY; - - /* return track index in RS2-RS3 */ - scd.regs[0x38>>1].w = (CD_PLAY << 8) | 0x02; - scd.regs[0x3a>>1].w = (cdd.index < cdd.toc.last) ? lut_BCD_16[index + 1] : 0x0A0A; - scd.regs[0x3c>>1].w = 0x0000; - scd.regs[0x3e>>1].w = 0x0000; - scd.regs[0x40>>1].byte.h = 0x00; - break; - } - - case 0x04: /* Seek */ - { - /* reset track index */ - int index = 0; - - /* new LBA position */ - int lba = ((scd.regs[0x44>>1].byte.h * 10 + scd.regs[0x44>>1].byte.l) * 60 + - (scd.regs[0x46>>1].byte.h * 10 + scd.regs[0x46>>1].byte.l)) * 75 + - (scd.regs[0x48>>1].byte.h * 10 + scd.regs[0x48>>1].byte.l) - 150; - - /* CD drive seek time */ - /* We are using similar linear model as above, although still not exactly accurate, */ - /* it works fine for Switch/Panic! intro (Switch needs at least 30 interrupts while */ - /* seeking from 00:05:63 to 24:03:19, Panic! when seeking from 00:05:60 to 24:06:07) */ - if (lba > cdd.lba) - { - cdd.latency = ((lba - cdd.lba) * 120) / 270000; - } - else - { - cdd.latency = ((cdd.lba - lba) * 120) / 270000; - } - - /* update current LBA */ - cdd.lba = lba; - - /* get current track index */ - while ((cdd.toc.tracks[index].end <= lba) && (index < cdd.toc.last)) index++; - - /* update current track index */ - cdd.index = index; - - /* no audio track playing */ - scd.regs[0x36>>1].byte.h = 0x01; - - /* update status */ - cdd.status = CD_SEEK; - - /* unknown RS1-RS8 values (returning 0xF in RS1 invalidates track infos in RS2-RS8 and fixes Final Fight CD intro when seek time is emulated) */ - scd.regs[0x38>>1].w = (CD_SEEK << 8) | 0x0f; - scd.regs[0x3a>>1].w = 0x0000; - scd.regs[0x3c>>1].w = 0x0000; - scd.regs[0x3e>>1].w = 0x0000; - scd.regs[0x40>>1].w = ~(CD_SEEK + 0xf) & 0x0f; - return; - } - - case 0x06: /* Pause */ - { - /* no audio track playing */ - scd.regs[0x36>>1].byte.h = 0x01; - - /* update status (RS1-RS8 unchanged) */ - cdd.status = scd.regs[0x38>>1].byte.h = CD_READY; - break; - } - - case 0x07: /* Resume */ - { - /* update status (RS1-RS8 unchanged) */ - cdd.status = scd.regs[0x38>>1].byte.h = CD_PLAY; - break; - } - - case 0x08: /* Forward Scan */ - { - /* reset scanning direction / speed */ - cdd.scanOffset = CD_SCAN_SPEED; - - /* update status (RS1-RS8 unchanged) */ - cdd.status = scd.regs[0x38>>1].byte.h = CD_SCAN; - break; - } - - case 0x09: /* Rewind Scan */ - { - /* reset scanning direction / speed */ - cdd.scanOffset = -CD_SCAN_SPEED; - - /* update status (RS1-RS8 unchanged) */ - cdd.status = scd.regs[0x38>>1].byte.h = CD_SCAN; - break; - } - - - case 0x0a: /* N-Track Jump Control ? (usually sent before CD_SEEK or CD_PLAY commands) */ - { - /* TC3 corresponds to seek direction (00=forward, FF=reverse) */ - /* TC4-TC7 are related to seek length (4x4 bits i.e parameter values are between -65535 and +65535) */ - /* Maybe related to number of auto-sequenced track jumps/moves for CD DSP (cf. CXD2500BQ datasheet) */ - /* also see US Patent nr. 5222054 for a detailled description of seeking operation using Track Jump */ - - /* no audio track playing */ - scd.regs[0x36>>1].byte.h = 0x01; - - /* update status (RS1-RS8 unchanged) */ - cdd.status = scd.regs[0x38>>1].byte.h = CD_READY; - break; - } - - case 0x0c: /* Close Tray */ - { - /* no audio track playing */ - scd.regs[0x36>>1].byte.h = 0x01; - - /* update status */ - cdd.status = cdd.loaded ? CD_STOP : NO_DISC; - - /* RS1-RS8 ignored, expects 0x0 ("no disc" ?) in RS0 once */ - scd.regs[0x38>>1].w = 0x0000; - scd.regs[0x3a>>1].w = 0x0000; - scd.regs[0x3c>>1].w = 0x0000; - scd.regs[0x3e>>1].w = 0x0000; - scd.regs[0x40>>1].w = 0x000f; - -#ifdef CD_TRAY_CALLBACK - CD_TRAY_CALLBACK -#endif - return; - } - - case 0x0d: /* Open Tray */ - { - /* no audio track playing */ - scd.regs[0x36>>1].byte.h = 0x01; - - /* update status (RS1-RS8 ignored) */ - cdd.status = CD_OPEN; - scd.regs[0x38>>1].w = CD_OPEN << 8; - scd.regs[0x3a>>1].w = 0x0000; - scd.regs[0x3c>>1].w = 0x0000; - scd.regs[0x3e>>1].w = 0x0000; - scd.regs[0x40>>1].w = ~CD_OPEN & 0x0f; - -#ifdef CD_TRAY_CALLBACK - CD_TRAY_CALLBACK -#endif - return; - } - - default: /* Unknown command */ -#ifdef LOG_CDD - error("Unknown CDD Command !!!\n"); -#endif - scd.regs[0x38>>1].byte.h = cdd.status; - break; - } - - /* only compute checksum when necessary */ - scd.regs[0x40>>1].byte.l = ~(scd.regs[0x38>>1].byte.h + scd.regs[0x38>>1].byte.l + - scd.regs[0x3a>>1].byte.h + scd.regs[0x3a>>1].byte.l + - scd.regs[0x3c>>1].byte.h + scd.regs[0x3c>>1].byte.l + - scd.regs[0x3e>>1].byte.h + scd.regs[0x3e>>1].byte.l + - scd.regs[0x40>>1].byte.h) & 0x0f; -} +/*************************************************************************************** + * Genesis Plus + * CD drive processor & CD-DA fader + * + * Copyright (C) 2012-2013 Eke-Eke (Genesis Plus GX) + * + * Redistribution and use of this code or any derivative works are permitted + * provided that the following conditions are met: + * + * - Redistributions may not be sold, nor may they be used in a commercial + * product or activity. + * + * - Redistributions that are modified from the original source must include the + * complete source code, including the source code for all components used by a + * binary built from the modified sources. However, as a special exception, the + * source code distributed need not include anything that is normally distributed + * (in either source or binary form) with the major components (compiler, kernel, + * and so on) of the operating system on which the executable runs, unless that + * component itself accompanies the executable. + * + * - Redistributions must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************************/ +#include "shared.h" +#include "../cinterface/callbacks.h" + +/* BCD conversion lookup tables */ +static const uint8 lut_BCD_8[100] = +{ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, + 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, +}; + +static const uint16 lut_BCD_16[100] = +{ + 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, + 0x0100, 0x0101, 0x0102, 0x0103, 0x0104, 0x0105, 0x0106, 0x0107, 0x0108, 0x0109, + 0x0200, 0x0201, 0x0202, 0x0203, 0x0204, 0x0205, 0x0206, 0x0207, 0x0208, 0x0209, + 0x0300, 0x0301, 0x0302, 0x0303, 0x0304, 0x0305, 0x0306, 0x0307, 0x0308, 0x0309, + 0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0406, 0x0407, 0x0408, 0x0409, + 0x0500, 0x0501, 0x0502, 0x0503, 0x0504, 0x0505, 0x0506, 0x0507, 0x0508, 0x0509, + 0x0600, 0x0601, 0x0602, 0x0603, 0x0604, 0x0605, 0x0606, 0x0607, 0x0608, 0x0609, + 0x0700, 0x0701, 0x0702, 0x0703, 0x0704, 0x0705, 0x0706, 0x0707, 0x0708, 0x0709, + 0x0800, 0x0801, 0x0802, 0x0803, 0x0804, 0x0805, 0x0806, 0x0807, 0x0808, 0x0809, + 0x0900, 0x0901, 0x0902, 0x0903, 0x0904, 0x0905, 0x0906, 0x0907, 0x0908, 0x0909, +}; + +/* pre-build TOC */ +static const uint16 toc_snatcher[21] = +{ + 56014, 495, 10120, 20555, 1580, 5417, 12502, 16090, 6553, 9681, + 8148, 20228, 8622, 6142, 5858, 1287, 7424, 3535, 31697, 2485, + 31380 +}; + +static const uint16 toc_lunar[52] = +{ + 5422, 1057, 7932, 5401, 6380, 6592, 5862, 5937, 5478, 5870, + 6673, 6613, 6429, 4996, 4977, 5657, 3720, 5892, 3140, 3263, + 6351, 5187, 3249, 1464, 1596, 1750, 1751, 6599, 4578, 5205, + 1550, 1827, 2328, 1346, 1569, 1613, 7199, 4928, 1656, 2549, + 1875, 3901, 1850, 2399, 2028, 1724, 4889, 14551, 1184, 2132, + 685, 3167 +}; + +static const uint32 toc_shadow[15] = +{ + 10226, 70054, 11100, 12532, 12444, 11923, 10059, 10167, 10138, 13792, + 11637, 2547, 2521, 3856, 900 +}; + +static const uint32 toc_dungeon[13] = +{ + 2250, 22950, 16350, 24900, 13875, 19950, 13800, 15375, 17400, 17100, + 3325, 6825, 25275 +}; + +static const uint32 toc_ffight[26] = +{ + 11994, 9742, 10136, 9685, 9553, 14588, 9430, 8721, 9975, 9764, + 9704, 12796, 585, 754, 951, 624, 9047, 1068, 817, 9191, 1024, + 14562, 10320, 8627, 3795, 3047 +}; + +static const uint32 toc_ffightj[29] = +{ + 11994, 9752, 10119, 9690, 9567, 14575, 9431, 8731, 9965, 9763, + 9716, 12791, 579, 751, 958, 630, 9050, 1052, 825, 9193, 1026, + 14553, 9834, 10542, 1699, 1792, 1781, 3783, 3052 +}; + +/* supported WAVE file header (16-bit stereo samples @44.1kHz) */ +static const unsigned char waveHeader[32] = +{ + 0x57,0x41,0x56,0x45,0x66,0x6d,0x74,0x20,0x10,0x00,0x00,0x00,0x01,0x00,0x02,0x00, + 0x44,0xac,0x00,0x00,0x10,0xb1,0x02,0x00,0x04,0x00,0x10,0x00,0x64,0x61,0x74,0x61 +}; + +static blip_t* blip[2]; + +typedef struct +{ + toc_t toc; +} frontendcd_t; + +int cdd_load(const char *key, char *header) +{ + frontendcd_t fecd; + char data[2048]; + int startoffs; + + + int bytes = sizeof(frontendcd_t); + if (load_archive(key, (unsigned char *)&fecd, bytes, NULL) != bytes) + return 0; + + // look for valid header + cdd_readcallback(0, data, 0); + if (memcmp("SEGADISCSYSTEM", data, 14) == 0) + startoffs = 0; + else if (memcmp("SEGADISCSYSTEM", data + 16, 14) == 0) + startoffs = 16; + else + return 0; + // copy security block + memcpy(header, data + startoffs, 0x210); + + // copy disk information + memcpy(&cdd.toc, &fecd.toc, sizeof(toc_t)); + + cdd.loaded = 1; + return 1; +} + +void cdd_init(blip_t* left, blip_t* right) +{ + /* CD-DA is running by default at 44100 Hz */ + /* Audio stream is resampled to desired rate using Blip Buffer */ + blip[0] = left; + blip[1] = right; + blip_set_rates(left, 44100, snd.sample_rate); + blip_set_rates(right, 44100, snd.sample_rate); +} + +void cdd_reset(void) +{ + /* reset cycle counter */ + cdd.cycles = 0; + + /* reset drive access latency */ + cdd.latency = 0; + + /* reset track index */ + cdd.index = 0; + + /* reset logical block address */ + cdd.lba = 0; + + // reset audio subblock position + cdd.sampleOffset = 0; + + // reset audio read position + cdd.sampleLba = 0; + + /* reset status */ + cdd.status = cdd.loaded ? CD_STOP : NO_DISC; + + /* reset CD-DA fader (full volume) */ + cdd.volume = 0x400; + + /* clear CD-DA output */ + cdd.audio[0] = cdd.audio[1] = 0; +} + +void cdd_unload(void) +{ + cdd.loaded = 0; + cdd_readcallback = NULL; + + /* reset TOC */ + memset(&cdd.toc, 0x00, sizeof(cdd.toc)); +} + +void cdd_hotswap(const toc_t *toc) +{ + if (toc) + { + cdd.loaded = 1; + memcpy(&cdd.toc, &toc, sizeof(cdd.toc)); + } + else + { + cdd.loaded = 0; + memset(&cdd.toc, 0x00, sizeof(cdd.toc)); + } + cdd_reset(); +} + +void cdd_read_data(uint8 *dst) +{ + /* only read DATA track sectors */ + if ((cdd.lba >= 0) && (cdd.lba < cdd.toc.tracks[0].end)) + { + cdd_readcallback(cdd.lba, dst, 0); + } +} + +void cdd_read_audio(unsigned int samples) +{ + // previous audio outputs // + int16 l = cdd.audio[0]; + int16 r = cdd.audio[1]; + + // get number of internal clocks (samples) needed // + samples = blip_clocks_needed(blip[0], samples); + + // audio track playing ? // + if (!scd.regs[0x36>>1].byte.h) + { + int i, mul, delta; + + // current CD-DA fader volume // + int curVol = cdd.volume; + + // CD-DA fader volume setup (0-1024) // + int endVol = scd.regs[0x34>>1].w >> 4; + + // read samples from current block // + { +#ifdef LSB_FIRST + int16 *ptr = (int16 *) (cdc.ram); +#else + uint8 *ptr = cdc.ram; +#endif + { + char scratch[2352]; + // copy the end of current sector + int nsampreq = samples; + unsigned char *dest = cdc.ram; + cdd_readcallback(cdd.sampleLba, scratch, 1); + memcpy(cdc.ram, scratch + cdd.sampleOffset * 4, 2352 - cdd.sampleOffset * 4); + cdd.sampleLba++; + nsampreq -= 588 - cdd.sampleOffset; + dest += 2352 - cdd.sampleOffset * 4; + cdd.sampleOffset = 0; + // fill full sectors + while (nsampreq >= 588) + { + cdd_readcallback(cdd.sampleLba, scratch, 1); + memcpy(dest, scratch, 2352); + cdd.sampleLba++; + nsampreq -= 588; + dest += 2352; + } + // do last partial sector + if (nsampreq > 0) + { + cdd_readcallback(cdd.sampleLba, scratch, 1); + memcpy(dest, scratch, nsampreq * 4); + cdd.sampleOffset = nsampreq; + dest += nsampreq * 4; + nsampreq = 0; + } + //printf("samples: %i\n", samples); + //memset(cdc.ram, 0, samples * 4); + //fread(cdc.ram, 1, samples * 4, cdd.toc.tracks[cdd.index].fd); + } + + // process 16-bit (little-endian) stereo samples // + for (i=0; i endVol) + { + // fade-out // + curVol--; + } + else if (!curVol) + { + // audio will remain muted until next setup // + break; + } + } + } + + // save current CD-DA fader volume // + cdd.volume = curVol; + + // save last audio output for next frame // + cdd.audio[0] = l; + cdd.audio[1] = r; + } + else + { + // no audio output // + if (l) blip_add_delta_fast(blip[0], 0, -l); + if (r) blip_add_delta_fast(blip[1], 0, -r); + + // save audio output for next frame // + cdd.audio[0] = 0; + cdd.audio[1] = 0; + } + + // end of Blip Buffer timeframe // + blip_end_frame(blip[0], samples); + blip_end_frame(blip[1], samples); +} + + +void cdd_update(void) +{ +#ifdef LOG_CDD + error("LBA = %d (track n�%d)(latency=%d)\n", cdd.lba, cdd.index, cdd.latency); +#endif + + /* seeking disc */ + if (cdd.status == CD_SEEK) + { + /* drive latency */ + if (cdd.latency > 0) + { + cdd.latency--; + return; + } + + /* drive is ready */ + cdd.status = CD_READY; + } + + /* reading disc */ + else if (cdd.status == CD_PLAY) + { + /* drive latency */ + if (cdd.latency > 0) + { + cdd.latency--; + return; + } + + /* track type */ + if (!cdd.index) + { + /* DATA sector header (CD-ROM Mode 1) */ + uint8 header[4]; + uint32 msf = cdd.lba + 150; + header[0] = lut_BCD_8[(msf / 75) / 60]; + header[1] = lut_BCD_8[(msf / 75) % 60]; + header[2] = lut_BCD_8[(msf % 75)]; + header[3] = 0x01; + + /* data track sector read is controlled by CDC */ + cdd.lba += cdc_decoder_update(*(uint32 *)(header)); + } + else if (cdd.index < cdd.toc.last) + { + /* check against audio track start index */ + if (cdd.lba >= cdd.toc.tracks[cdd.index].start) + { + /* audio track playing */ + // if it wasn't before, set the audio start position + if (scd.regs[0x36>>1].byte.h) + { + cdd.sampleLba = cdd.lba + 1; + cdd.sampleOffset = 0; + } + scd.regs[0x36>>1].byte.h = 0x00; + } + + /* audio blocks are still sent to CDC as well as CD DAC/Fader */ + cdc_decoder_update(0); + + /* next audio block is automatically read */ + cdd.lba++; + } + else + { + /* end of disc */ + cdd.status = CD_END; + return; + } + + /* check end of current track */ + if (cdd.lba >= cdd.toc.tracks[cdd.index].end) + { + /* play next track */ + cdd.index++; + + /* PAUSE between tracks */ + scd.regs[0x36>>1].byte.h = 0x01; + } + } + + /* scanning disc */ + else if (cdd.status == CD_SCAN) + { + /* fast-forward or fast-rewind */ + cdd.lba += cdd.scanOffset; + cdd.sampleLba += cdd.scanOffset; + + /* check current track limits */ + if (cdd.lba >= cdd.toc.tracks[cdd.index].end) + { + /* next track */ + cdd.index++; + + /* skip directly to track start position */ + cdd.lba = cdd.toc.tracks[cdd.index].start; + + /* AUDIO track playing ? */ + if (cdd.status == CD_PLAY) + { + scd.regs[0x36>>1].byte.h = 0x00; + // set audio start point + cdd.sampleLba = cdd.lba; + cdd.sampleOffset = 0; + } + } + else if (cdd.lba < cdd.toc.tracks[cdd.index].start) + { + /* previous track */ + cdd.index--; + + /* skip directly to track end position */ + cdd.lba = cdd.toc.tracks[cdd.index].end; + } + + /* check disc limits */ + if (cdd.index < 0) + { + cdd.index = 0; + cdd.lba = 0; + } + else if (cdd.index >= cdd.toc.last) + { + /* no AUDIO track playing */ + scd.regs[0x36>>1].byte.h = 0x01; + + /* end of disc */ + cdd.index = cdd.toc.last; + cdd.lba = cdd.toc.end; + cdd.status = CD_END; + return; + } + } +} + +void cdd_process(void) +{ + /* Process CDD command */ + switch (scd.regs[0x42>>1].byte.h & 0x0f) + { + case 0x00: /* Drive Status */ + { + /* RS1-RS8 normally unchanged */ + scd.regs[0x38>>1].byte.h = cdd.status; + + /* unless RS1 indicated invalid track infos */ + if (scd.regs[0x38>>1].byte.l == 0x0f) + { + /* and SEEK has ended */ + if (cdd.status != CD_SEEK) + { + /* then return valid track infos, e.g current track number in RS2-RS3 (fixes Lunar - The Silver Star) */ + scd.regs[0x38>>1].byte.l = 0x02; + scd.regs[0x3a>>1].w = (cdd.index < cdd.toc.last) ? lut_BCD_16[cdd.index + 1] : 0x0A0A; + } + } + break; + } + + case 0x01: /* Stop Drive */ + { + /* update status */ + cdd.status = cdd.loaded ? CD_STOP : NO_DISC; + + /* no audio track playing */ + scd.regs[0x36>>1].byte.h = 0x01; + + /* RS1-RS8 ignored, expects 0x0 ("no disc" ?) in RS0 once */ + scd.regs[0x38>>1].w = 0x0000; + scd.regs[0x3a>>1].w = 0x0000; + scd.regs[0x3c>>1].w = 0x0000; + scd.regs[0x3e>>1].w = 0x0000; + scd.regs[0x40>>1].w = 0x000f; + return; + } + + case 0x02: /* Read TOC */ + { + /* Infos automatically retrieved by CDD processor from Q-Channel */ + /* commands 0x00-0x02 (current block) and 0x03-0x05 (Lead-In) */ + switch (scd.regs[0x44>>1].byte.l) + { + case 0x00: /* Current Absolute Time (MM:SS:FF) */ + { + int lba = cdd.lba + 150; + scd.regs[0x38>>1].w = cdd.status << 8; + scd.regs[0x3a>>1].w = lut_BCD_16[(lba/75)/60]; + scd.regs[0x3c>>1].w = lut_BCD_16[(lba/75)%60]; + scd.regs[0x3e>>1].w = lut_BCD_16[(lba%75)]; + scd.regs[0x40>>1].byte.h = cdd.index ? 0x00 : 0x04; /* Current block flags in RS8 (bit0 = mute status, bit1: pre-emphasis status, bit2: track type) */ + break; + } + + case 0x01: /* Current Track Relative Time (MM:SS:FF) */ + { + int lba = cdd.lba - cdd.toc.tracks[cdd.index].start; + scd.regs[0x38>>1].w = (cdd.status << 8) | 0x01; + scd.regs[0x3a>>1].w = lut_BCD_16[(lba/75)/60]; + scd.regs[0x3c>>1].w = lut_BCD_16[(lba/75)%60]; + scd.regs[0x3e>>1].w = lut_BCD_16[(lba%75)]; + scd.regs[0x40>>1].byte.h = cdd.index ? 0x00 : 0x04; /* Current block flags in RS8 (bit0 = mute status, bit1: pre-emphasis status, bit2: track type) */ + break; + } + + case 0x02: /* Current Track Number */ + { + scd.regs[0x38>>1].w = (cdd.status << 8) | 0x02; + scd.regs[0x3a>>1].w = (cdd.index < cdd.toc.last) ? lut_BCD_16[cdd.index + 1] : 0x0A0A; + scd.regs[0x3c>>1].w = 0x0000; + scd.regs[0x3e>>1].w = 0x0000; /* Disk Control Code (?) in RS6 */ + scd.regs[0x40>>1].byte.h = 0x00; + break; + } + + case 0x03: /* Total length (MM:SS:FF) */ + { + int lba = cdd.toc.end + 150; + scd.regs[0x38>>1].w = (cdd.status << 8) | 0x03; + scd.regs[0x3a>>1].w = lut_BCD_16[(lba/75)/60]; + scd.regs[0x3c>>1].w = lut_BCD_16[(lba/75)%60]; + scd.regs[0x3e>>1].w = lut_BCD_16[(lba%75)]; + scd.regs[0x40>>1].byte.h = 0x00; + break; + } + + case 0x04: /* First & Last Track Numbers */ + { + scd.regs[0x38>>1].w = (cdd.status << 8) | 0x04; + scd.regs[0x3a>>1].w = 0x0001; + scd.regs[0x3c>>1].w = lut_BCD_16[cdd.toc.last]; + scd.regs[0x3e>>1].w = 0x0000; /* Drive Version (?) in RS6-RS7 */ + scd.regs[0x40>>1].byte.h = 0x00; /* Lead-In flags in RS8 (bit0 = mute status, bit1: pre-emphasis status, bit2: track type) */ + break; + } + + case 0x05: /* Track Start Time (MM:SS:FF) */ + { + int track = scd.regs[0x46>>1].byte.h * 10 + scd.regs[0x46>>1].byte.l; + int lba = cdd.toc.tracks[track-1].start + 150; + scd.regs[0x38>>1].w = (cdd.status << 8) | 0x05; + scd.regs[0x3a>>1].w = lut_BCD_16[(lba/75)/60]; + scd.regs[0x3c>>1].w = lut_BCD_16[(lba/75)%60]; + scd.regs[0x3e>>1].w = lut_BCD_16[(lba%75)]; + scd.regs[0x40>>1].byte.h = track % 10; /* Track Number (low digit) */ + if (track == 1) + { + /* RS6 bit 3 is set for the first (DATA) track */ + scd.regs[0x3e>>1].byte.h |= 0x08; + } + break; + } + + default: + { +#ifdef LOG_ERROR + error("Unknown CDD Command %02X (%X)\n", scd.regs[0x44>>1].byte.l, s68k.pc); +#endif + return; + } + } + break; + } + + case 0x03: /* Play */ + { + /* reset track index */ + int index = 0; + + /* new LBA position */ + int lba = ((scd.regs[0x44>>1].byte.h * 10 + scd.regs[0x44>>1].byte.l) * 60 + + (scd.regs[0x46>>1].byte.h * 10 + scd.regs[0x46>>1].byte.l)) * 75 + + (scd.regs[0x48>>1].byte.h * 10 + scd.regs[0x48>>1].byte.l) - 150; + + /* CD drive latency */ + if (!cdd.latency) + { + /* Fixes a few games hanging during intro because they expect data to be read with some delay */ + /* Radical Rex needs at least one interrupt delay */ + /* Wolf Team games (Anet Futatabi, Cobra Command, Road Avenger & Time Gal) need at least 6 interrupts delay */ + /* Space Adventure Cobra (2nd morgue scene) needs at least 13 interrupts delay (incl. seek time, so 6 is OK) */ + /* Jeopardy & ESPN Sunday Night NFL are picky about this as well: 10 interrupts delay (+ seek time) seems OK */ + cdd.latency = 10; + } + + /* CD drive seek time */ + /* max. seek time = 1.5 s = 1.5 x 75 = 112.5 CDD interrupts (rounded to 120) for 270000 sectors max on disc. */ + /* Note: This is only a rough approximation since, on real hardware, seek time is much likely not linear and */ + /* latency much larger than above value, but this model works fine for Sonic CD (track 26 playback needs to */ + /* be enough delayed to start in sync with intro sequence, as compared with real hardware recording). */ + if (lba > cdd.lba) + { + cdd.latency += (((lba - cdd.lba) * 120) / 270000); + } + else + { + cdd.latency += (((cdd.lba - lba) * 120) / 270000); + } + + /* update current LBA */ + cdd.lba = lba; + + /* get track index */ + while ((cdd.toc.tracks[index].end <= lba) && (index < cdd.toc.last)) index++; + + /* update current track index */ + cdd.index = index; + + /* no audio track playing (yet) */ + scd.regs[0x36>>1].byte.h = 0x01; + + /* update status */ + cdd.status = CD_PLAY; + + /* return track index in RS2-RS3 */ + scd.regs[0x38>>1].w = (CD_PLAY << 8) | 0x02; + scd.regs[0x3a>>1].w = (cdd.index < cdd.toc.last) ? lut_BCD_16[index + 1] : 0x0A0A; + scd.regs[0x3c>>1].w = 0x0000; + scd.regs[0x3e>>1].w = 0x0000; + scd.regs[0x40>>1].byte.h = 0x00; + break; + } + + case 0x04: /* Seek */ + { + /* reset track index */ + int index = 0; + + /* new LBA position */ + int lba = ((scd.regs[0x44>>1].byte.h * 10 + scd.regs[0x44>>1].byte.l) * 60 + + (scd.regs[0x46>>1].byte.h * 10 + scd.regs[0x46>>1].byte.l)) * 75 + + (scd.regs[0x48>>1].byte.h * 10 + scd.regs[0x48>>1].byte.l) - 150; + + /* CD drive seek time */ + /* We are using similar linear model as above, although still not exactly accurate, */ + /* it works fine for Switch/Panic! intro (Switch needs at least 30 interrupts while */ + /* seeking from 00:05:63 to 24:03:19, Panic! when seeking from 00:05:60 to 24:06:07) */ + if (lba > cdd.lba) + { + cdd.latency = ((lba - cdd.lba) * 120) / 270000; + } + else + { + cdd.latency = ((cdd.lba - lba) * 120) / 270000; + } + + /* update current LBA */ + cdd.lba = lba; + + /* get current track index */ + while ((cdd.toc.tracks[index].end <= lba) && (index < cdd.toc.last)) index++; + + /* update current track index */ + cdd.index = index; + + /* no audio track playing */ + scd.regs[0x36>>1].byte.h = 0x01; + + /* update status */ + cdd.status = CD_SEEK; + + /* unknown RS1-RS8 values (returning 0xF in RS1 invalidates track infos in RS2-RS8 and fixes Final Fight CD intro when seek time is emulated) */ + scd.regs[0x38>>1].w = (CD_SEEK << 8) | 0x0f; + scd.regs[0x3a>>1].w = 0x0000; + scd.regs[0x3c>>1].w = 0x0000; + scd.regs[0x3e>>1].w = 0x0000; + scd.regs[0x40>>1].w = ~(CD_SEEK + 0xf) & 0x0f; + return; + } + + case 0x06: /* Pause */ + { + /* no audio track playing */ + scd.regs[0x36>>1].byte.h = 0x01; + + /* update status (RS1-RS8 unchanged) */ + cdd.status = scd.regs[0x38>>1].byte.h = CD_READY; + break; + } + + case 0x07: /* Resume */ + { + /* update status (RS1-RS8 unchanged) */ + cdd.status = scd.regs[0x38>>1].byte.h = CD_PLAY; + break; + } + + case 0x08: /* Forward Scan */ + { + /* reset scanning direction / speed */ + cdd.scanOffset = CD_SCAN_SPEED; + + /* update status (RS1-RS8 unchanged) */ + cdd.status = scd.regs[0x38>>1].byte.h = CD_SCAN; + break; + } + + case 0x09: /* Rewind Scan */ + { + /* reset scanning direction / speed */ + cdd.scanOffset = -CD_SCAN_SPEED; + + /* update status (RS1-RS8 unchanged) */ + cdd.status = scd.regs[0x38>>1].byte.h = CD_SCAN; + break; + } + + + case 0x0a: /* N-Track Jump Control ? (usually sent before CD_SEEK or CD_PLAY commands) */ + { + /* TC3 corresponds to seek direction (00=forward, FF=reverse) */ + /* TC4-TC7 are related to seek length (4x4 bits i.e parameter values are between -65535 and +65535) */ + /* Maybe related to number of auto-sequenced track jumps/moves for CD DSP (cf. CXD2500BQ datasheet) */ + /* also see US Patent nr. 5222054 for a detailled description of seeking operation using Track Jump */ + + /* no audio track playing */ + scd.regs[0x36>>1].byte.h = 0x01; + + /* update status (RS1-RS8 unchanged) */ + cdd.status = scd.regs[0x38>>1].byte.h = CD_READY; + break; + } + + case 0x0c: /* Close Tray */ + { + /* no audio track playing */ + scd.regs[0x36>>1].byte.h = 0x01; + + /* update status */ + cdd.status = cdd.loaded ? CD_STOP : NO_DISC; + + /* RS1-RS8 ignored, expects 0x0 ("no disc" ?) in RS0 once */ + scd.regs[0x38>>1].w = 0x0000; + scd.regs[0x3a>>1].w = 0x0000; + scd.regs[0x3c>>1].w = 0x0000; + scd.regs[0x3e>>1].w = 0x0000; + scd.regs[0x40>>1].w = 0x000f; + +#ifdef CD_TRAY_CALLBACK + CD_TRAY_CALLBACK +#endif + return; + } + + case 0x0d: /* Open Tray */ + { + /* no audio track playing */ + scd.regs[0x36>>1].byte.h = 0x01; + + /* update status (RS1-RS8 ignored) */ + cdd.status = CD_OPEN; + scd.regs[0x38>>1].w = CD_OPEN << 8; + scd.regs[0x3a>>1].w = 0x0000; + scd.regs[0x3c>>1].w = 0x0000; + scd.regs[0x3e>>1].w = 0x0000; + scd.regs[0x40>>1].w = ~CD_OPEN & 0x0f; + +#ifdef CD_TRAY_CALLBACK + CD_TRAY_CALLBACK +#endif + return; + } + + default: /* Unknown command */ +#ifdef LOG_CDD + error("Unknown CDD Command !!!\n"); +#endif + scd.regs[0x38>>1].byte.h = cdd.status; + break; + } + + /* only compute checksum when necessary */ + scd.regs[0x40>>1].byte.l = ~(scd.regs[0x38>>1].byte.h + scd.regs[0x38>>1].byte.l + + scd.regs[0x3a>>1].byte.h + scd.regs[0x3a>>1].byte.l + + scd.regs[0x3c>>1].byte.h + scd.regs[0x3c>>1].byte.l + + scd.regs[0x3e>>1].byte.h + scd.regs[0x3e>>1].byte.l + + scd.regs[0x40>>1].byte.h) & 0x0f; +} diff --git a/waterbox/gpgx/core/cd_hw/cdd.h b/waterbox/gpgx/core/cd_hw/cdd.h index e1300b4eac..fdfb62b127 100644 --- a/waterbox/gpgx/core/cd_hw/cdd.h +++ b/waterbox/gpgx/core/cd_hw/cdd.h @@ -1,106 +1,110 @@ -/*************************************************************************************** - * Genesis Plus - * CD drive processor & CD-DA fader - * - * Copyright (C) 2012-2013 Eke-Eke (Genesis Plus GX) - * - * Redistribution and use of this code or any derivative works are permitted - * provided that the following conditions are met: - * - * - Redistributions may not be sold, nor may they be used in a commercial - * product or activity. - * - * - Redistributions that are modified from the original source must include the - * complete source code, including the source code for all components used by a - * binary built from the modified sources. However, as a special exception, the - * source code distributed need not include anything that is normally distributed - * (in either source or binary form) with the major components (compiler, kernel, - * and so on) of the operating system on which the executable runs, unless that - * component itself accompanies the executable. - * - * - Redistributions must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - ****************************************************************************************/ -#ifndef _HW_CDD_ -#define _HW_CDD_ - -#include "blip_buf.h" - -#ifdef USE_LIBTREMOR -#include "tremor/ivorbisfile.h" -#endif - -#define cdd scd.cdd_hw - -/* CDD status */ -#define NO_DISC 0x00 -#define CD_PLAY 0x01 -#define CD_SEEK 0x02 -#define CD_SCAN 0x03 -#define CD_READY 0x04 -#define CD_OPEN 0x05 /* similar to 0x0E ? */ -#define CD_STOP 0x09 -#define CD_END 0x0C - -/* CD blocks scanning speed */ -#define CD_SCAN_SPEED 30 - -#define CD_MAX_TRACKS 100 - -/* CD track */ -typedef struct -{ - int start; - int end; -} track_t; - -/* CD TOC */ -typedef struct -{ - int end; - int last; - track_t tracks[CD_MAX_TRACKS]; -} toc_t; - -/* CDD hardware */ -typedef struct -{ - uint32 cycles; - uint32 latency; - int loaded; - int index; - int lba; - int scanOffset; - int volume; - int sampleOffset; - int sampleLba; - uint8 status; - toc_t toc; - int16 audio[2]; -} cdd_t; - -/* Function prototypes */ -extern void cdd_init(blip_t* left, blip_t* right); -extern void cdd_reset(void); -extern int cdd_load(const char *key, char *header); -extern void cdd_unload(void); -extern void cdd_read_data(uint8 *dst); -extern void cdd_read_audio(unsigned int samples); -extern void cdd_update(void); -extern void cdd_process(void); - -#endif +/*************************************************************************************** + * Genesis Plus + * CD drive processor & CD-DA fader + * + * Copyright (C) 2012-2013 Eke-Eke (Genesis Plus GX) + * + * Redistribution and use of this code or any derivative works are permitted + * provided that the following conditions are met: + * + * - Redistributions may not be sold, nor may they be used in a commercial + * product or activity. + * + * - Redistributions that are modified from the original source must include the + * complete source code, including the source code for all components used by a + * binary built from the modified sources. However, as a special exception, the + * source code distributed need not include anything that is normally distributed + * (in either source or binary form) with the major components (compiler, kernel, + * and so on) of the operating system on which the executable runs, unless that + * component itself accompanies the executable. + * + * - Redistributions must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************************/ +#ifndef _HW_CDD_ +#define _HW_CDD_ + +#include "blip_buf.h" + +#ifdef USE_LIBTREMOR +#include "tremor/ivorbisfile.h" +#endif + +#define cdd scd.cdd_hw + +/* CDD status */ +#define NO_DISC 0x00 +#define CD_PLAY 0x01 +#define CD_SEEK 0x02 +#define CD_SCAN 0x03 +#define CD_READY 0x04 +#define CD_OPEN 0x05 /* similar to 0x0E ? */ +#define CD_STOP 0x09 +#define CD_END 0x0C + +/* CD blocks scanning speed */ +#define CD_SCAN_SPEED 30 + +#define CD_MAX_TRACKS 100 + +/* CD track */ +typedef struct +{ + int start; + int end; +} track_t; + +/* CD TOC */ +typedef struct +{ + int end; + int last; + track_t tracks[CD_MAX_TRACKS]; +} toc_t; + +/* CDD hardware */ +typedef struct +{ + uint32 cycles; + uint32 latency; + int loaded; + int index; + int lba; + int scanOffset; + int volume; + int sampleOffset; + int sampleLba; + uint8 status; + toc_t toc; + int16 audio[2]; +} cdd_t; + +/* Function prototypes */ +extern void cdd_init(blip_t* left, blip_t* right); +extern void cdd_reset(void); +extern int cdd_load(const char *key, char *header); +extern void cdd_unload(void); +extern void cdd_read_data(uint8 *dst); +extern void cdd_read_audio(unsigned int samples); +extern void cdd_update(void); +extern void cdd_process(void); + +// switch disks after emulation was started +// pass NULL to open tray +void cdd_hotswap(const toc_t *toc); + +#endif diff --git a/waterbox/pcfx/.vscode/settings.json b/waterbox/pcfx/.vscode/settings.json index ed2aea06d3..63ffa1793c 100644 --- a/waterbox/pcfx/.vscode/settings.json +++ b/waterbox/pcfx/.vscode/settings.json @@ -10,6 +10,7 @@ "xiosbase": "cpp", "iosfwd": "cpp", "xlocale": "cpp", - "xstring": "cpp" + "xstring": "cpp", + "queue": "cpp" } } \ No newline at end of file diff --git a/waterbox/pcfx/defs.h b/waterbox/pcfx/defs.h index d6ec6a9f47..1c1245fa95 100644 --- a/waterbox/pcfx/defs.h +++ b/waterbox/pcfx/defs.h @@ -80,7 +80,7 @@ typedef struct // Set by the system emulation code every frame, to denote the horizontal and vertical offsets of the image, and the size // of the image. If the emulated system sets the elements of LineWidths, then the width(w) of this structure // is ignored while drawing the image. - int32 x, y, w, h; + int32 y, w, h; // Set(optionally) by emulation code. If InterlaceOn is true, then assume field height is 1/2 DisplayRect.h, and // only every other line in surface (with the start line defined by InterlacedField) has valid data @@ -118,3 +118,5 @@ extern bool Setting_AdpcmNoClicks; extern bool Setting_ChromaInterpolate; extern int Setting_PortDevice[2]; + +extern bool Setting_PixelPro; diff --git a/waterbox/pcfx/king.cpp b/waterbox/pcfx/king.cpp index 6a691a83ff..c2b67e446e 100644 --- a/waterbox/pcfx/king.cpp +++ b/waterbox/pcfx/king.cpp @@ -2628,7 +2628,6 @@ void KING_StartFrame(VDC **arg_vdc_chips, EmulateSpecStruct *espec) LineWidths[0] = 0; // These 2 should be overwritten in the big loop below. - espec->x = 0; espec->w = 256; espec->y = Setting_SlStart; @@ -3104,7 +3103,6 @@ static void MixLayers(void) #undef YUV888_TO_xxx } Ess->w = fx_vce.dot_clock ? HighDotClockWidth : 256; - Ess->x = 0; // FIXME if (fx_vce.frame_interlaced) diff --git a/waterbox/pcfx/pcfx.cpp b/waterbox/pcfx/pcfx.cpp index 96623ed54f..f201921d48 100644 --- a/waterbox/pcfx/pcfx.cpp +++ b/waterbox/pcfx/pcfx.cpp @@ -706,6 +706,90 @@ EXPORT bool Init(int numDisks, const uint8_t *bios) static int ActiveDisk; static uint32_t PrevConsoleButtons; +static void Blit(MyFrameInfo &f) +{ + // two widths to deal with: 256 and "341" (which can be 256, 341, or 1024 wide depending on settings) + // two heights: 240 and 480, but watch out for scanlinestart / scanline end + + // in pixel pro mode, 341 width is forced to 1024. we upsize 256 to 1024 as well, and double 240 tall + + const uint32_t *src = FrameBuffer; + uint32_t *dst = f.VideoBuffer; + const int srcp = 1024; + src += Ess.y * srcp; + + if (Setting_PixelPro) + { + f.Width = 1024; + f.Height = Ess.h; + + const int dstp = 1024; + + if (Ess.h > 240) // interlace + { + if (Ess.w == 256) + { + for (int j = 0; j < Ess.h; j++, src += srcp, dst += dstp) + { + for (int i = 0; i < 256; i++) + { + auto c = src[i]; + dst[i * 4 + 0] = c; + dst[i * 4 + 1] = c; + dst[i * 4 + 2] = c; + dst[i * 4 + 3] = c; + } + } + } + else + { + for (int j = 0; j < Ess.h; j++, src += srcp, dst += dstp) + { + memcpy(dst, src, LineWidths[j + Ess.y] * sizeof(uint32_t)); + } + } + } + else // progressive: line double + { + f.Height *= 2; + if (Ess.w == 256) + { + for (int j = 0; j < Ess.h; j++, src += srcp, dst += dstp * 2) + { + for (int i = 0; i < 256; i++) + { + auto c = src[i]; + dst[i * 4 + 0] = c; + dst[i * 4 + 1] = c; + dst[i * 4 + 2] = c; + dst[i * 4 + 3] = c; + } + memcpy(dst + dstp, dst, 4096); + } + } + else + { + for (int j = 0; j < Ess.h; j++, src += srcp, dst += dstp * 2) + { + memcpy(dst, src, 4096); + memcpy(dst + dstp, src, 4096); + } + } + } + } + else + { + f.Width = Ess.w; + f.Height = Ess.h; + + const int dstp = Ess.w; + for (int j = 0; j < Ess.h; j++, src += srcp, dst += dstp) + { + memcpy(dst, src, LineWidths[j + Ess.y] * sizeof(uint32_t)); + } + } +} + EXPORT void FrameAdvance(MyFrameInfo &f) { for (int i = 0; i < 2; i++) @@ -733,20 +817,10 @@ EXPORT void FrameAdvance(MyFrameInfo &f) Ess.SoundBuf = f.SoundBuffer; Emulate(&Ess); f.Cycles = Ess.MasterCycles; - f.Width = Ess.w; - f.Height = Ess.h; f.Samples = Ess.SoundBufSize; f.Lagged = Lagged; - const uint32_t *src = FrameBuffer; - uint32_t *dst = f.VideoBuffer; - const int srcp = 1024; - const int dstp = Ess.w; - src += Ess.y * srcp + Ess.x; - for (int j = 0; j < Ess.h; j++, src += srcp, dst += dstp) - { - memcpy(dst, src, LineWidths[j + Ess.y] * sizeof(uint32_t)); - } + Blit(f); } EXPORT void GetMemoryAreas(MemoryArea *m) @@ -821,6 +895,8 @@ ECL_SEALED bool Setting_ChromaInterpolate = false; ECL_SEALED int Setting_PortDevice[2]; +ECL_SEALED bool Setting_PixelPro; + struct FrontendSettings { int32_t AdpcmEmulateBuggyCodec; @@ -834,13 +910,14 @@ struct FrontendSettings int32_t CpuEmulation; int32_t Port1; int32_t Port2; + int32_t PixelPro; }; EXPORT void PutSettingsBeforeInit(const FrontendSettings &s) { Setting_AdpcmBuggy = s.AdpcmEmulateBuggyCodec; Setting_AdpcmNoClicks = s.AdpcmSuppressChannelResetClicks; - Setting_HighDotclockWidth = s.HiResEmulation; + Setting_HighDotclockWidth = s.PixelPro ? 1024 : s.HiResEmulation; Setting_NoSpriteLimit = s.DisableSpriteLimit; Setting_ChromaInterpolate = s.ChromaInterpolation; Setting_SlStart = s.ScanlineStart; @@ -849,6 +926,7 @@ EXPORT void PutSettingsBeforeInit(const FrontendSettings &s) Setting_CpuEmulation = s.CpuEmulation; Setting_PortDevice[0] = s.Port1; Setting_PortDevice[1] = s.Port2; + Setting_PixelPro = s.PixelPro; } /*MDFNGI EmulatedPCFX = diff --git a/waterbox/picodrive/bizhawk.c b/waterbox/picodrive/bizhawk.c index 187723f14f..35e52d3059 100644 --- a/waterbox/picodrive/bizhawk.c +++ b/waterbox/picodrive/bizhawk.c @@ -138,8 +138,11 @@ static const uint8_t *TryLoadBios(const char *name) return ret; } -ECL_EXPORT int Init(int cd, int _32xPreinit) +ECL_EXPORT int Init(int cd, int _32xPreinit, int regionAutoOrder, int regionOverride) { + PicoAutoRgnOrder = regionAutoOrder; + PicoRegionOverride = regionOverride; + p32x_bios_g = TryLoadBios("32x.g"); p32x_bios_m = TryLoadBios("32x.m"); p32x_bios_s = TryLoadBios("32x.s"); diff --git a/waterbox/pizza/README.md b/waterbox/pizza/README.md deleted file mode 100644 index edc069a750..0000000000 --- a/waterbox/pizza/README.md +++ /dev/null @@ -1,49 +0,0 @@ -# Emu-pizza -A new born Gameboy Classic/Color emulator.... - -Requirements ------------ -Emu-pizza requires libSDL2 to compile and run Space Invaders and Gameboy games. To install it - -on an APT based distro: -``` -sudo apt-get install libsdl2-dev -``` - -on a YUM based distro: -``` -sudo yum install SDL2-devel -``` - -Compile -------- -``` -make -``` - -Usage ------ -``` -emu-pizza [gameboy rom] -``` - -Gameboy keys -------------------- -* Arrows -- Arrows (rly?) -* Enter -- Start -* Space -- Select -* Z/X -- A/B buttons -* Q -- Exit - -Supported ROMS --------------- -* Almost totality of Gameboy roms - -Todo ----- -* Serial cable emulation - -Credits -------- - -Thanks to [Emulator 101](http://www.emulator101.com), the source of all my current knowledge on 8080 emulation diff --git a/waterbox/pizza/lib/cartridge.c b/waterbox/pizza/lib/cartridge.c deleted file mode 100644 index 89835aad17..0000000000 --- a/waterbox/pizza/lib/cartridge.c +++ /dev/null @@ -1,233 +0,0 @@ -/* - - This file is part of Emu-Pizza - - Emu-Pizza is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Emu-Pizza is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Emu-Pizza. If not, see . - -*/ - -#include -#include -#include -#include - -#include "global.h" -#include "mmu.h" -#include "utils.h" - -/* guess what */ -/* return values */ -/* 0: OK */ -/* 1: Can't open/read file */ -/* 2: Unknown cartridge */ - -char cartridge_load(const void *data, size_t sz) -{ - int i, z = 0; - - if (sz < 1 || sz > 1 << 22) - return 1; - - const uint8_t *rom = (const uint8_t *)data; - - /* gameboy color? */ - if (rom[0x143] == 0xC0 || rom[0x143] == 0x80) - { - utils_log("Gameboy Color cartridge\n"); - global_cgb = global_sgb ? 0 : 1; - } - else - { - utils_log("Gameboy Classic cartridge\n"); - global_cgb = 0; - } - - /* get cartridge infos */ - uint8_t mbc = rom[0x147]; - - utils_log("Cartridge code: %02x\n", mbc); - - switch (mbc) - { - case 0x00: - utils_log("ROM ONLY\n"); - break; - case 0x01: - utils_log("MBC1\n"); - break; - case 0x02: - utils_log("MBC1 + RAM\n"); - break; - case 0x03: - utils_log("MBC1 + RAM + BATTERY\n"); - break; - case 0x05: - utils_log("MBC2\n"); - break; - case 0x06: - mmu_init_ram(512); - utils_log("MBC2 + BATTERY\n"); - break; - case 0x10: - utils_log("MBC3 + TIMER + RAM + BATTERY\n"); - break; - case 0x11: - utils_log("MBC3\n"); - break; - case 0x12: - utils_log("MBC3 + RAM\n"); - break; - case 0x13: - utils_log("MBC3 + RAM + BATTERY\n"); - break; - case 0x19: - utils_log("MBC5\n"); - break; - case 0x1A: - utils_log("MBC5 + RAM\n"); - break; - case 0x1B: - utils_log("MBC5 + RAM + BATTERY\n"); - break; - case 0x1C: - global_rumble = 1; - utils_log("MBC5 + RUMBLE\n"); - break; - case 0x1D: - global_rumble = 1; - utils_log("MBC5 + RUMBLE + RAM\n"); - break; - case 0x1E: - global_rumble = 1; - utils_log("MBC5 + RUMBLE + RAM + BATTERY\n"); - break; - - default: - utils_log("Unknown cartridge type: %02x\n", mbc); - return 2; - } - - /* title */ - for (i = 0x134; i < 0x143; i++) - if (rom[i] > 0x40 && rom[i] < 0x5B) - global_cart_name[z++] = rom[i]; - - global_cart_name[z] = '\0'; - - utils_log("%s\n", global_cart_name); - - /* get ROM banks */ - uint8_t byte = rom[0x148]; - - utils_log("ROM: "); - - switch (byte) - { - case 0x00: - utils_log("0 banks\n"); - break; - case 0x01: - utils_log("4 banks\n"); - break; - case 0x02: - utils_log("8 banks\n"); - break; - case 0x03: - utils_log("16 banks\n"); - break; - case 0x04: - utils_log("32 banks\n"); - break; - case 0x05: - utils_log("64 banks\n"); - break; - case 0x06: - utils_log("128 banks\n"); - break; - case 0x07: - utils_log("256 banks\n"); - break; - case 0x52: - utils_log("72 banks\n"); - break; - case 0x53: - utils_log("80 banks\n"); - break; - case 0x54: - utils_log("96 banks\n"); - break; - } - - /* init MMU */ - mmu_init(mbc, byte); - - /* get RAM banks */ - byte = rom[0x149]; - - utils_log("RAM: "); - - switch (byte) - { - case 0x00: - utils_log("NO RAM\n"); - break; - case 0x01: - mmu_init_ram(1 << 11); - utils_log("2 kB\n"); - break; - case 0x02: - /* MBC5 got bigger values */ - if (mbc >= 0x19 && mbc <= 0x1E) - { - mmu_init_ram(1 << 16); - utils_log("64 kB\n"); - } - else - { - mmu_init_ram(1 << 13); - utils_log("8 kB\n"); - } - break; - case 0x03: - mmu_init_ram(1 << 15); - utils_log("32 kB\n"); - break; - case 0x04: - mmu_init_ram(1 << 17); - utils_log("128 kB\n"); - break; - case 0x05: - mmu_init_ram(1 << 16); - utils_log("64 kB\n"); - break; - } - - /* restore saved RAM if it's the case */ - //mmu_restore_ram(file_sav); - - /* restore saved RTC if it's the case */ - //mmu_restore_rtc(file_rtc); - - /* load FULL ROM at 0x0000 address of system memory */ - mmu_load_cartridge(rom, sz); - - return 0; -} - -/*void cartridge_term() -{ - // save persistent data (battery backed RAM and RTC clock) - mmu_save_ram(file_sav); - mmu_save_rtc(file_rtc); -}*/ diff --git a/waterbox/pizza/lib/cartridge.h b/waterbox/pizza/lib/cartridge.h deleted file mode 100644 index ebc95de13c..0000000000 --- a/waterbox/pizza/lib/cartridge.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - - This file is part of Emu-Pizza - - Emu-Pizza is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Emu-Pizza is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Emu-Pizza. If not, see . - -*/ - -#ifndef __CARTRIDGE_HDR__ -#define __CARTRIDGE_HDR__ - -#include - -/* prototypes */ -char cartridge_load(const void* data, size_t sz); - -#endif diff --git a/waterbox/pizza/lib/cycles.c b/waterbox/pizza/lib/cycles.c deleted file mode 100644 index f8a350462e..0000000000 --- a/waterbox/pizza/lib/cycles.c +++ /dev/null @@ -1,321 +0,0 @@ -/* - - This file is part of Emu-Pizza - - Emu-Pizza is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Emu-Pizza is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Emu-Pizza. If not, see . - -*/ - -#include -#include "cycles.h" -#include "global.h" -#include "gpu.h" -#include "mmu.h" -#include "serial.h" -#include "sound.h" -#include "timer.h" -#include "interrupt.h" -#include "utils.h" - -interrupts_flags_t *cycles_if; - -/* instance of the main struct */ -cycles_t cycles = {0, 0, 0, 0}; - -#define CYCLES_PAUSES 256 - -/* hard sync stuff (for remote connection) */ -uint8_t cycles_hs_mode = 0; - -/* type of next */ -typedef enum { - CYCLES_NEXT_TYPE_CYCLES, - CYCLES_NEXT_TYPE_CYCLES_HS, - CYCLES_NEXT_TYPE_DMA, -} cycles_next_type_enum_e; - -/* closest next and its type */ -uint_fast32_t cycles_very_next; -cycles_next_type_enum_e cycles_next_type; - -/* set hard sync mode. sync is given by the remote peer + local timer */ -void cycles_start_hs() -{ - utils_log("Hard sync mode ON\n"); - - /* boolean set to on */ - cycles_hs_mode = 1; -} - -void cycles_stop_hs() -{ - utils_log("Hard sync mode OFF\n"); - - /* boolean set to on */ - cycles_hs_mode = 0; -} - -/* set double or normal speed */ -void cycles_set_speed(char dbl) -{ - /* set global */ - global_cpu_double_speed = dbl; - - /* update clock */ - if (global_cpu_double_speed) - cycles.clock = 4194304 * 2; - else - cycles.clock = 4194304; - - /* calculate the mask */ - cycles_change_emulation_speed(); -} - -/* set emulation speed */ -void cycles_change_emulation_speed() -{ - cycles.step = ((4194304 / CYCLES_PAUSES) - << global_cpu_double_speed); -} - -void cycles_closest_next() -{ - int_fast32_t diff = cycles.cnt - cycles.next; - - /* init */ - cycles_very_next = cycles.next; - cycles_next_type = CYCLES_NEXT_TYPE_CYCLES; - - int_fast32_t diff_new = cycles.cnt - mmu.dma_next; - - /* DMA? */ - if (diff_new < diff) - { - /* this is the new lowest */ - cycles_very_next = mmu.dma_next; - cycles_next_type = CYCLES_NEXT_TYPE_DMA; - } -} - -/* this function is gonna be called every M-cycle = 4 ticks of CPU */ -void cycles_step() -{ - cycles.cnt += 4; - cycles.sampleclock += 2 >> global_cpu_double_speed; - - /* - while (cycles.cnt >= cycles_very_next) - { - switch (cycles_next_type) - { - case CYCLES_NEXT_TYPE_CYCLES: - - deadline.tv_nsec += 1000000000 / CYCLES_PAUSES; - - if (deadline.tv_nsec > 1000000000) - { - deadline.tv_sec += 1; - deadline.tv_nsec -= 1000000000; - } - - clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, - &deadline, NULL); - - cycles.next += cycles.step; - - if (cycles.cnt % cycles.clock == 0) - cycles.seconds++; - - break; - - case CYCLES_NEXT_TYPE_DMA: - - memcpy(&mmu.memory[0xFE00], &mmu.memory[mmu.dma_address], 160); - - mmu.dma_address = 0x0000; - - mmu.dma_next = 1; - - break; - } - - cycles_closest_next(); - } -*/ - - /* 65536 == cpu clock / CYCLES_PAUSES pauses every second */ - if (cycles.cnt == cycles.next) - { - cycles.next += cycles.step; - } - - /* hard sync next step */ - if (cycles.cnt == cycles.hs_next) - { - /* set cycles for hard sync */ - cycles.hs_next += ((4096 * 4) << global_cpu_double_speed); - - /* hard sync is on? */ - if (cycles_hs_mode) - { - /* send my status and wait for peer status back */ - serial_send_byte(); - - /* wait for reply */ - serial_wait_data(); - - /* verify if we need to trigger an interrupt */ - serial_verify_intr(); - } - } - - /* DMA */ - if (mmu.dma_next == cycles.cnt) - { - memcpy(&mmu.memory[0xFE00], &mmu.memory[mmu.dma_address], 160); - - /* reset address */ - mmu.dma_address = 0x0000; - - /* reset */ - mmu.dma_next = 1; - } - - /* update GPU state */ - if (gpu.next == cycles.cnt) - gpu_step(); - - /* fs clock */ - if (sound.fs_cycles_next == cycles.cnt) - sound_step_fs(); - - /* channel one */ - if (sound.channel_one.duty_cycles_next == cycles.cnt) - sound_step_ch1(); - - /* channel two */ - if (sound.channel_two.duty_cycles_next == cycles.cnt) - sound_step_ch2(); - - /* channel three */ - if (sound.channel_three.cycles_next <= cycles.cnt) - sound_step_ch3(); - - /* channel four */ - if (sound.channel_four.cycles_next == cycles.cnt) - sound_step_ch4(); - - /* update timer state */ - if (cycles.cnt == timer.next) - { - timer.next += 256; - timer.div++; - } - - /* timer is on? */ - if (timer.sub_next == cycles.cnt) - { - timer.sub_next += timer.threshold; - timer.cnt++; - - /* cnt value > 255? trigger an interrupt */ - if (timer.cnt > 255) - { - timer.cnt = timer.mod; - - /* trigger timer interrupt */ - cycles_if->timer = 1; - } - } - - /* update serial state */ - if (serial.next == cycles.cnt) - { - /* nullize serial next */ - serial.next -= 1; - - /* reset counter */ - serial.bits_sent = 0; - - /* gotta reply with 0xff when asking for ff01 */ - serial.data = 0xFF; - - /* reset transfer_start flag to yell I'M DONE */ - serial.transfer_start = 0; - - /* if not connected, trig the fucking interrupt */ - cycles_if->serial_io = 1; - } -} - -/* things to do when vsync kicks in */ -void cycles_vblank() -{ - return; -} - -/* stuff tied to entering into hblank state */ -void cycles_hdma() -{ - /* HDMA (only CGB) */ - if (mmu.hdma_to_transfer) - { - /* hblank transfer */ - if (mmu.hdma_transfer_mode) - { - /* transfer when line is changed and we're into HBLANK phase */ - if (mmu.memory[0xFF44] < 143 && - mmu.hdma_current_line != mmu.memory[0xFF44] && - (mmu.memory[0xFF41] & 0x03) == 0x00) - { - /* update current line */ - mmu.hdma_current_line = mmu.memory[0xFF44]; - - /* copy 0x10 bytes */ - if (mmu.vram_idx) - memcpy(mmu_addr_vram1() + mmu.hdma_dst_address - 0x8000, - &mmu.memory[mmu.hdma_src_address], 0x10); - else - memcpy(mmu_addr_vram0() + mmu.hdma_dst_address - 0x8000, - &mmu.memory[mmu.hdma_src_address], 0x10); - - /* decrease bytes to transfer */ - mmu.hdma_to_transfer -= 0x10; - - /* increase pointers */ - mmu.hdma_dst_address += 0x10; - mmu.hdma_src_address += 0x10; - } - } - } -} - -char cycles_init() -{ - cycles.inited = 1; - - /* interrupt registers */ - cycles_if = mmu_addr(0xFF0F); - - /* init clock and counter */ - cycles.clock = 4194304; - cycles.cnt = 0; - cycles.hs_next = 70224; - - /* mask for pauses cycles fast calc */ - cycles.step = 4194304 / CYCLES_PAUSES; - cycles.next = 4194304 / CYCLES_PAUSES; - - return 0; -} diff --git a/waterbox/pizza/lib/cycles.h b/waterbox/pizza/lib/cycles.h deleted file mode 100644 index 58c7c2bb4c..0000000000 --- a/waterbox/pizza/lib/cycles.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - - This file is part of Emu-Pizza - - Emu-Pizza is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Emu-Pizza is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Emu-Pizza. If not, see . - -*/ - -#ifndef __CYCLES_HDR__ -#define __CYCLES_HDR__ - -#include -#include - -typedef struct cycles_s -{ - /* am i init'ed? */ - uint_fast32_t inited; - - /* ticks counter */ - uint64_t cnt; - - // CPU clock. advances at 4MHz or 8MHz depending on current cgb setting - uint_fast32_t clock; - - /* handy for calculation */ - uint64_t next; - - /* step varying on cpu and emulation speed */ - uint_fast32_t step; - - /* 2 spares */ - uint64_t hs_next; - - // reference clock. advances at 2MHz always - uint64_t sampleclock; -} cycles_t; - -extern cycles_t cycles; - -// extern uint8_t cycles_hs_local_cnt; -// extern uint8_t cycles_hs_peer_cnt; - -/* callback function */ -typedef void (*cycles_send_cb_t)(uint32_t v); - -/* prototypes */ -void cycles_change_emulation_speed(); -void cycles_hdma(); -char cycles_init(); -void cycles_set_speed(char dbl); -void cycles_start_hs(); -void cycles_step(); -void cycles_stop_hs(); -void cycles_vblank(); - -#endif diff --git a/waterbox/pizza/lib/gameboy.c b/waterbox/pizza/lib/gameboy.c deleted file mode 100644 index be64e6436d..0000000000 --- a/waterbox/pizza/lib/gameboy.c +++ /dev/null @@ -1,235 +0,0 @@ -/* - - This file is part of Emu-Pizza - - Emu-Pizza is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Emu-Pizza is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Emu-Pizza. If not, see . - -*/ - -#include -#include -#include "cartridge.h" -#include "sound.h" -#include "mmu.h" -#include "cycles.h" -#include "gpu.h" -#include "global.h" -#include "input.h" -#include "timer.h" -#include "serial.h" -#include "utils.h" -#include "z80_gameboy_regs.h" -#include "z80_gameboy.h" - -char gameboy_inited = 0; - -void gameboy_init() -{ - /* init z80 */ - z80_init(); - - /* init cycles syncronizer */ - cycles_init(); - - /* init timer */ - timer_init(); - - /* init serial */ - serial_init(); - - /* init sound (this will start audio thread) */ - sound_init(); - - /* reset GPU counters */ - gpu_reset(); - - /* reset to default values */ - mmu_write_no_cyc(0xFF05, 0x00); - mmu_write_no_cyc(0xFF06, 0x00); - mmu_write_no_cyc(0xFF07, 0x00); - mmu_write_no_cyc(0xFF10, 0x80); - mmu_write_no_cyc(0xFF11, 0xBF); - mmu_write_no_cyc(0xFF12, 0xF3); - mmu_write_no_cyc(0xFF14, 0xBF); - mmu_write_no_cyc(0xFF16, 0x3F); - mmu_write_no_cyc(0xFF17, 0x00); - mmu_write_no_cyc(0xFF19, 0xBF); - mmu_write_no_cyc(0xFF1A, 0x7F); - mmu_write_no_cyc(0xFF1B, 0xFF); - mmu_write_no_cyc(0xFF1C, 0x9F); - mmu_write_no_cyc(0xFF1E, 0xBF); - mmu_write_no_cyc(0xFF20, 0xFF); - mmu_write_no_cyc(0xFF21, 0x00); - mmu_write_no_cyc(0xFF22, 0x00); - mmu_write_no_cyc(0xFF23, 0xBF); - mmu_write_no_cyc(0xFF24, 0x77); - mmu_write_no_cyc(0xFF25, 0xF3); - mmu_write_no_cyc(0xFF26, 0xF1); - mmu_write_no_cyc(0xFF40, 0x91); - mmu_write_no_cyc(0xFF41, 0x80); - mmu_write_no_cyc(0xFF42, 0x00); - mmu_write_no_cyc(0xFF43, 0x00); - mmu_write_no_cyc(0xFF44, 0x00); - mmu_write_no_cyc(0xFF45, 0x00); - mmu_write_no_cyc(0xFF47, 0xFC); - mmu_write_no_cyc(0xFF48, 0xFF); - mmu_write_no_cyc(0xFF49, 0xFF); - mmu_write_no_cyc(0xFF4A, 0x00); - mmu_write_no_cyc(0xFF4B, 0x00); - mmu_write_no_cyc(0xFF98, 0xDC); - mmu_write_no_cyc(0xFFFF, 0x00); - mmu_write_no_cyc(0xC000, 0x08); - mmu_write_no_cyc(0xFFFE, 0x69); - - if (global_cgb) - state.a = 0x11; - else - state.a = 0x00; - - state.b = 0x00; - state.c = 0x13; - state.d = 0x00; - state.e = 0xd8; - state.h = 0x01; - state.l = 0x4d; - state.pc = 0x0100; - state.sp = 0xFFFE; - *state.f = 0xB0; - - /* reset counter */ - cycles.cnt = 0; - /* start at normal speed */ - global_cpu_double_speed = 0; - - /* mark as inited */ - gameboy_inited = 1; - - return; -} - -void gameboy_run(uint64_t target) -{ - uint8_t op; - - /* get interrupt flags and interrupt enables */ - uint8_t *int_e; - uint8_t *int_f; - - /* pointers to memory location of interrupt enables/flags */ - int_e = mmu_addr(0xFFFF); - int_f = mmu_addr(0xFF0F); - - /* run stuff! */ - /* mechanism is simple. */ - /* 1) execute instruction 2) update cycles counter 3) check interrupts */ - /* and repeat forever */ - while (cycles.sampleclock < target) - { - /* get op */ - op = mmu_read(state.pc); - - /* print out CPU state if enabled by debug flag */ - if (global_debug) - { - utils_log("OP: %02x F: %02x PC: %04x:%02x:%02x SP: %04x:%02x:%02x ", - op, *state.f & 0xd0, state.pc, - mmu_read_no_cyc(state.pc + 1), - mmu_read_no_cyc(state.pc + 2), state.sp, - mmu_read_no_cyc(state.sp), - mmu_read_no_cyc(state.sp + 1)); - - utils_log("A: %02x BC: %04x DE: %04x HL: %04x FF41: %02x " - "FF44: %02x ENAB: %02x INTE: %02x INTF: %02x\n", - state.a, *state.bc, - *state.de, *state.hl, - mmu_read_no_cyc(0xFF41), - mmu_read_no_cyc(0xFF44), - state.int_enable, - *int_e, *int_f); - } - - /* execute instruction by the GB Z80 version */ - z80_execute(op); - - /* if last op was Interrupt Enable (0xFB) */ - /* we need to check for INTR on next cycle */ - if (op == 0xFB) - continue; - - /* interrupts filtered by enable flags */ - uint8_t int_r = (*int_f & *int_e); - - /* check for interrupts */ - if ((state.int_enable || op == 0x76) && (int_r != 0)) - { - /* discard useless bits */ - if ((int_r & 0x1F) == 0x00) - continue; - - /* beware of instruction that doesn't move PC! */ - /* like HALT (0x76) */ - if (op == 0x76) - { - state.pc++; - - if (state.int_enable == 0) - continue; - } - - /* reset int-enable flag, it will be restored after a RETI op */ - state.int_enable = 0; - - if ((int_r & 0x01) == 0x01) - { - /* vblank interrupt triggers RST 5 */ - - /* reset flag */ - *int_f &= 0xFE; - - /* handle the interrupt */ - z80_intr(0x0040); - } - else if ((int_r & 0x02) == 0x02) - { - /* LCD Stat interrupt */ - - /* reset flag */ - *int_f &= 0xFD; - - /* handle the interrupt! */ - z80_intr(0x0048); - } - else if ((int_r & 0x04) == 0x04) - { - /* timer interrupt */ - - /* reset flag */ - *int_f &= 0xFB; - - /* handle the interrupt! */ - z80_intr(0x0050); - } - else if ((int_r & 0x08) == 0x08) - { - /* serial interrupt */ - - /* reset flag */ - *int_f &= 0xF7; - - /* handle the interrupt! */ - z80_intr(0x0058); - } - } - } -} diff --git a/waterbox/pizza/lib/gameboy.h b/waterbox/pizza/lib/gameboy.h deleted file mode 100644 index 06efa026a8..0000000000 --- a/waterbox/pizza/lib/gameboy.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - - This file is part of Emu-Pizza - - Emu-Pizza is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Emu-Pizza is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Emu-Pizza. If not, see . - -*/ - -#ifndef __GAMEBOY_HDR__ -#define __GAMEBOY_HDR__ - -/* prototypes */ -void gameboy_init(); -void gameboy_run(uint64_t target); -void gameboy_stop(); - -#endif diff --git a/waterbox/pizza/lib/global.c b/waterbox/pizza/lib/global.c deleted file mode 100644 index e14d158dc3..0000000000 --- a/waterbox/pizza/lib/global.c +++ /dev/null @@ -1,47 +0,0 @@ -/* - - This file is part of Emu-Pizza - - Emu-Pizza is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Emu-Pizza is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Emu-Pizza. If not, see . - -*/ - -#include -#include - -#include "global.h" - -char global_cart_name[256]; -char global_cgb; // if true, in CGB mode -char global_sgb; // if true, in SGB mode -char global_cpu_double_speed; -char global_debug; -char global_rumble; -char global_window; // if true, show window -int global_lagged; -void (*global_input_callback)(void); -int64_t global_currenttime; - -void global_init() -{ - global_window = 1; - global_debug = 0; - global_cgb = 0; - global_sgb = 0; - global_cpu_double_speed = 0; - global_rumble = 0; - global_lagged = 0; - global_input_callback = NULL; - sprintf(global_cart_name, "NOCARTIRDGE"); -} diff --git a/waterbox/pizza/lib/global.h b/waterbox/pizza/lib/global.h deleted file mode 100644 index 06e3cff320..0000000000 --- a/waterbox/pizza/lib/global.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - - This file is part of Emu-Pizza - - Emu-Pizza is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Emu-Pizza is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Emu-Pizza. If not, see . - -*/ - -#ifndef __GLOBAL__ -#define __GLOBAL__ - -#include - -extern char global_window; -extern char global_debug; -extern char global_cgb; -extern char global_sgb; -// extern char global_started; -extern char global_cpu_double_speed; -extern char global_rumble; -extern char global_cart_name[256]; -extern int global_lagged; -extern void (*global_input_callback)(void); -extern int64_t global_currenttime; - -/* prototypes */ -void global_init(); - -#endif diff --git a/waterbox/pizza/lib/gpu.c b/waterbox/pizza/lib/gpu.c deleted file mode 100644 index 44859f824d..0000000000 --- a/waterbox/pizza/lib/gpu.c +++ /dev/null @@ -1,1072 +0,0 @@ -/* - - This file is part of Emu-Pizza - - Emu-Pizza is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Emu-Pizza is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Emu-Pizza. If not, see . - -*/ - -#include -#include - -#include "cycles.h" -#include "gameboy.h" -#include "global.h" -#include "gpu.h" -#include "interrupt.h" -#include "mmu.h" -#include "utils.h" -#include "sgb.h" - -/* Gameboy OAM 4 bytes data */ -typedef struct gpu_oam_s -{ - uint8_t y; - uint8_t x; - uint8_t pattern; - - uint8_t palette_cgb : 3; - uint8_t vram_bank : 1; - uint8_t palette : 1; - uint8_t x_flip : 1; - uint8_t y_flip : 1; - uint8_t priority : 1; - -} gpu_oam_t; - -/* Gameboy Color additional tile attributes */ -typedef struct gpu_cgb_bg_tile_s -{ - uint8_t palette : 3; - uint8_t vram_bank : 1; - uint8_t spare : 1; - uint8_t x_flip : 1; - uint8_t y_flip : 1; - uint8_t priority : 1; - -} gpu_cgb_bg_tile_t; - -/* ordered sprite list */ -typedef struct oam_list_s -{ - int idx; - struct oam_list_s *next; -} oam_list_t; - -/* pointer to interrupt flags (handy) */ -interrupts_flags_t *gpu_if; - -/* internal functions prototypes */ -void gpu_draw_sprite_line(gpu_oam_t *oam, - uint8_t sprites_size, - uint8_t line); -void gpu_draw_window_line(int tile_idx, uint8_t frame_x, - uint8_t frame_y, uint8_t line); - -/* 2 bit to 8 bit color lookup */ -// TODO: hook these up to the same color logic that that the other GB core uses -static const uint32_t gpu_color_lookup[] = {0xffffffff, 0xffaaaaaa, 0xff555555, 0xff000000}; - -/* function to call when frame is ready */ -gpu_frame_ready_cb_t gpu_frame_ready_cb; - -/* global state of GPU */ -gpu_t gpu; - -void gpu_dump_oam() -{ - /* make it point to the first OAM object */ - gpu_oam_t *oam = (gpu_oam_t *)mmu_addr(0xFE00); - - int i; - - for (i = 0; i < 40; i++) - { - if (oam[i].x != 0 && oam[i].y != 0) - printf("OAM X %d Y %d VRAM %d PATTERN %d\n", oam[i].x, oam[i].y, - oam[i].vram_bank, - oam[i].pattern); - } -} - -/* init pointers */ -void gpu_init_pointers() -{ - /* make gpu field points to the related memory area */ - gpu.lcd_ctrl = mmu_addr(0xFF40); - gpu.lcd_status = mmu_addr(0xFF41); - gpu.scroll_y = mmu_addr(0xFF42); - gpu.scroll_x = mmu_addr(0xFF43); - gpu.window_y = mmu_addr(0xFF4A); - gpu.window_x = mmu_addr(0xFF4B); - gpu.ly = mmu_addr(0xFF44); - gpu.lyc = mmu_addr(0xFF45); - gpu_if = mmu_addr(0xFF0F); -} - -/* reset */ -void gpu_reset() -{ - /* init counters */ - gpu.next = 456 << global_cpu_double_speed; - gpu.frame_counter = 0; -} - -/* init GPU states */ -void gpu_init(gpu_frame_ready_cb_t cb) -{ - /* reset gpu structure */ - bzero(&gpu, sizeof(gpu_t)); - - /* init memory pointers */ - gpu_init_pointers(); - - /* init counters */ - gpu.next = 456 << global_cpu_double_speed; - gpu.frame_counter = 0; - - /* step for normal CPU speed */ - gpu.step = 4; - - /* init palette */ - memcpy(gpu.bg_palette, gpu_color_lookup, sizeof(uint32_t) * 4); - memcpy(gpu.obj_palette_0, gpu_color_lookup, sizeof(uint32_t) * 4); - memcpy(gpu.obj_palette_1, gpu_color_lookup, sizeof(uint32_t) * 4); - - /* set callback */ - gpu_frame_ready_cb = cb; -} - -/* turn on/off lcd */ -void gpu_toggle(uint8_t state) -{ - /* from off to on */ - if (state & 0x80) - { - /* LCD turned on */ - gpu.next = cycles.cnt + (456 << global_cpu_double_speed); - *gpu.ly = 0; - (*gpu.lcd_status).mode = 0x00; - (*gpu.lcd_status).ly_coincidence = 0x00; - } - else - { - /* LCD turned off - reset stuff */ - gpu.next = cycles.cnt - 1; // + (80 << global_cpu_double_speed); - *gpu.ly = 0; - (*gpu.lcd_status).mode = 0x00; - } -} - -/* push frame on screen */ -void gpu_draw_frame() -{ - /* increase frame counter */ - gpu.frame_counter++; - - /* is it the case to push samples? */ - /*if ((global_emulation_speed == GLOBAL_EMULATION_SPEED_DOUBLE && - (gpu.frame_counter & 0x0001) != 0) || - (global_emulation_speed == GLOBAL_EMULATION_SPEED_4X && - (gpu.frame_counter & 0x0003) != 0)) - return;*/ - - if (global_sgb) - { - sgb_take_frame(gpu.frame_buffer); - } - - /* call the callback */ - if (gpu_frame_ready_cb) - (*gpu_frame_ready_cb)(); - - /* reset priority matrix */ - bzero(gpu.priority, 160 * 144); - bzero(gpu.palette_idx, 160 * 144); - - return; -} - -/* draw a single line */ -void gpu_draw_line(uint8_t line) -{ - /* avoid mess */ - if (line > 144) - return; - - /* is it the case to push samples? */ - /*if ((global_emulation_speed == GLOBAL_EMULATION_SPEED_DOUBLE && - (gpu.frame_counter & 0x0001) != 0) || - (global_emulation_speed == GLOBAL_EMULATION_SPEED_4X && - (gpu.frame_counter & 0x0003) != 0)) - return;*/ - - int i, t, y, px_start, px_drawn; - uint8_t *tiles_map, tile_subline, palette_idx, x_flip, priority; - uint16_t tiles_addr, tile_n, tile_idx, tile_line; - uint16_t tile_y; - - /* gotta show BG? Answer is always YES in case of Gameboy Color */ - if ((*gpu.lcd_ctrl).bg || global_cgb) - { - gpu_cgb_bg_tile_t *tiles_map_cgb = NULL; - uint8_t *tiles = NULL; - uint32_t *palette; - - if (global_cgb) - { - /* CGB tile map into VRAM0 */ - tiles_map = mmu_addr_vram0() + ((*gpu.lcd_ctrl).bg_tiles_map ? 0x1C00 : 0x1800); - - /* additional attribute table is into VRAM1 */ - tiles_map_cgb = mmu_addr_vram1() + ((*gpu.lcd_ctrl).bg_tiles_map ? 0x1C00 : 0x1800); - } - else - { - /* never flip */ - x_flip = 0; - - /* get tile map offset */ - tiles_map = mmu_addr((*gpu.lcd_ctrl).bg_tiles_map ? 0x9C00 : 0x9800); - - if ((*gpu.lcd_ctrl).bg_tiles) - tiles_addr = 0x8000; - else - tiles_addr = 0x9000; - - /* get absolute address of tiles area */ - tiles = mmu_addr(tiles_addr); - - /* monochrome GB uses a single BG palette */ - palette = gpu.bg_palette; - - /* always priority = 0 */ - priority = 0; - } - - /* calc tile y */ - tile_y = (*(gpu.scroll_y) + line) & 0xFF; - - /* calc first tile idx */ - tile_idx = ((tile_y >> 3) * 32) + (*(gpu.scroll_x) / 8); - - /* tile line because if we reach the end of the line, */ - /* we have to rewind to the first tile of the same line */ - tile_line = ((tile_y >> 3) * 32); - - /* calc first pixel of frame buffer of the current line */ - uint_fast16_t pos_fb = line * 160; - uint_fast16_t pos; - - /* calc tile subline */ - tile_subline = tile_y % 8; - - /* walk through different tiles */ - for (t = 0; t < 21; t++) - { - /* resolv tile data memory area */ - if ((*gpu.lcd_ctrl).bg_tiles == 0) - tile_n = (int8_t)tiles_map[tile_idx]; - else - tile_n = (tiles_map[tile_idx] & 0x00FF); - - /* if color gameboy, resolv which palette is bound */ - if (global_cgb) - { - /* extract palette index (0-31) */ - palette_idx = tiles_map_cgb[tile_idx].palette; - - /* get palette pointer to 4 (16bit) colors */ - palette = &gpu.cgb_palette_bg_rgb888[palette_idx * 4]; - - /* get priority of the tile */ - priority = tiles_map_cgb[tile_idx].priority; - - if (tiles_map_cgb[tile_idx].vram_bank) - tiles = mmu_addr_vram1() + - ((*gpu.lcd_ctrl).bg_tiles ? 0x0000 : 0x1000); - else - tiles = mmu_addr_vram0() + - ((*gpu.lcd_ctrl).bg_tiles ? 0x0000 : 0x1000); - - /* calc subline in case of flip_y */ - if (tiles_map_cgb[tile_idx].y_flip) - tile_subline = 7 - (tile_y % 8); - else - tile_subline = tile_y % 8; - - /* save x_flip */ - x_flip = tiles_map_cgb[tile_idx].x_flip; - } - - /* calc tile data pointer */ - int16_t tile_ptr = (tile_n * 16) + (tile_subline * 2); - - /* pixels are handled in a super shitty way */ - /* bit 0 of the pixel is taken from even position tile bytes */ - /* bit 1 of the pixel is taken from odd position tile bytes */ - - uint8_t pxa[8]; - uint8_t shft; - uint8_t b1 = *(tiles + tile_ptr); - uint8_t b2 = *(tiles + tile_ptr + 1); - - for (y = 0; y < 8; y++) - { - if (x_flip) - shft = (1 << (7 - y)); - else - shft = (1 << y); - - pxa[y] = ((b1 & shft) ? 1 : 0) | - ((b2 & shft) ? 2 : 0); - } - - /* particular cases for first and last tile */ - /* (could be shown just a part) */ - if (t == 0) - { - px_start = (*(gpu.scroll_x) % 8); - - px_drawn = 8 - px_start; - - /* set n pixels */ - for (i = 0; i < px_drawn; i++) - { - pos = pos_fb + (px_drawn - i - 1); - - gpu.priority[pos] = priority; - gpu.palette_idx[pos] = pxa[i]; - gpu.frame_buffer[pos] = palette[pxa[i]]; - } - } - else if (t == 20) - { - px_drawn = *(gpu.scroll_x) % 8; - - /* set n pixels */ - for (i = 0; i < px_drawn; i++) - { - pos = pos_fb + (px_drawn - i - 1); - - gpu.priority[pos] = priority; - gpu.palette_idx[pos] = pxa[i]; - gpu.frame_buffer[pos] = palette[pxa[i + (8 - px_drawn)]]; - } - } - else - { - /* set 8 pixels */ - for (i = 0; i < 8; i++) - { - pos = pos_fb + (7 - i); - - gpu.priority[pos] = priority; - gpu.palette_idx[pos] = pxa[i]; - gpu.frame_buffer[pos] = palette[pxa[i]]; - } - - px_drawn = 8; - } - - /* go to the next tile and rewind in case we reached the 32th */ - tile_idx++; - - /* don't go to the next line, just rewind */ - if (tile_idx == (tile_line + 32)) - tile_idx = tile_line; - - /* go to the next block of 8 pixels of the frame buffer */ - pos_fb += px_drawn; - } - } - - /* gotta show sprites? */ - if ((*gpu.lcd_ctrl).sprites) - { - /* make it point to the first OAM object */ - gpu_oam_t *oam = (gpu_oam_t *)mmu_addr(0xFE00); - - /* calc sprite height */ - uint8_t h = ((*gpu.lcd_ctrl).sprites_size + 1) * 8; - - int sort[40]; - int j = 0; - - /* prepare sorted list of oams */ - for (i = 0; i < 40; i++) - sort[i] = -1; - - for (i = 0; i < 40; i++) - { - /* the sprite intersects the current line? */ - if (oam[i].x != 0 && oam[i].y != 0 && - oam[i].x < 168 && oam[i].y < 160 && - line < (oam[i].y + h - 16) && - line >= (oam[i].y - 16)) - { - /* color GB uses memory position as priority criteria */ - if (global_cgb) - { - sort[j++] = i; - continue; - } - - /* find its position on sort array */ - for (j = 0; j < 40; j++) - { - if (sort[j] == -1) - { - sort[j] = i; - break; - } - - if (global_cgb) - continue; - - if ((oam[i].y < oam[sort[j]].y) || - ((oam[i].y == oam[sort[j]].y) && - (oam[i].x < oam[sort[j]].x))) - { - int z; - - for (z = 40; z > j; z--) - sort[z] = sort[z - 1]; - - sort[j] = i; - break; - } - } - } - } - - /* draw ordered sprite list */ - for (i = 0; i < 40 && sort[i] != -1; i++) - gpu_draw_sprite_line(&oam[sort[i]], - (*gpu.lcd_ctrl).sprites_size, line); - } - - /* wanna show window? */ - if (global_window && (*gpu.lcd_ctrl).window) - { - /* at least the current line is covering the window area? */ - if (line < *(gpu.window_y)) - return; - - /* TODO - reset this in a better place */ - if (line == *(gpu.window_y)) - gpu.window_skipped_lines = 0; - - int z, first_z; - uint8_t tile_pos_x, tile_pos_y; - - /* gotta draw a window? check if it is inside screen coordinates */ - if (*(gpu.window_y) >= 144 || - *(gpu.window_x) >= 160) - { - gpu.window_skipped_lines++; - return; - } - - /* calc the first interesting tile */ - first_z = ((line - *(gpu.window_y) - - gpu.window_skipped_lines) >> - 3) - << 5; - - for (z = first_z; z < first_z + 21; z++) - { - /* calc tile coordinates on frame buffer */ - tile_pos_x = ((z & 0x1F) << 3) + *(gpu.window_x) - 7; - tile_pos_y = ((z >> 5) << 3) + *(gpu.window_y) + - gpu.window_skipped_lines; - - /* gone over the current line? */ - if (tile_pos_y > line) - break; - - if (tile_pos_y < (line - 7)) - continue; - - /* gone over the screen visible X? */ - /* being between last column and first one is valid */ - if (tile_pos_x >= 160 && tile_pos_x < 248) - break; - - /* gone over the screen visible section? stop it */ - if (tile_pos_y >= 144) // || (tile_pos_x >= 160)) - break; - - /* put tile on frame buffer */ - gpu_draw_window_line(z, (uint8_t)tile_pos_x, - (uint8_t)tile_pos_y, line); - } - } -} - -/* draw a tile in x,y coordinates */ -void gpu_draw_window_line(int tile_idx, uint8_t frame_x, - uint8_t frame_y, uint8_t line) -{ - int i, p, y, pos; - int16_t tile_n; - uint8_t *tiles_map; - gpu_cgb_bg_tile_t *tiles_map_cgb = NULL; - uint8_t *tiles, x_flip; - uint32_t *palette; - - if (global_cgb) - { - /* CGB tile map into VRAM0 */ - tiles_map = mmu_addr_vram0() + ((*gpu.lcd_ctrl).window_tiles_map ? 0x1C00 : 0x1800); - - /* additional attribute table is into VRAM1 */ - tiles_map_cgb = mmu_addr_vram1() + ((*gpu.lcd_ctrl).window_tiles_map ? 0x1C00 : 0x1800); - - /* get palette index */ - uint8_t palette_idx = tiles_map_cgb[tile_idx].palette; - x_flip = tiles_map_cgb[tile_idx].x_flip; - - /* get palette pointer to 4 (16bit) colors */ - palette = &gpu.cgb_palette_bg_rgb888[palette_idx * 4]; - - /* attribute table will tell us where is the tile */ - if (tiles_map_cgb[tile_idx].vram_bank) - tiles = mmu_addr_vram1() + - ((*gpu.lcd_ctrl).bg_tiles ? 0x0000 : 0x1000); - else - tiles = mmu_addr_vram0() + - ((*gpu.lcd_ctrl).bg_tiles ? 0x0000 : 0x1000); - } - else - { - /* get tile map offset */ - tiles_map = mmu_addr((*gpu.lcd_ctrl).window_tiles_map ? 0x9C00 : 0x9800); - - /* get tile offset */ - if ((*gpu.lcd_ctrl).bg_tiles) - tiles = mmu_addr(0x8000); - else - tiles = mmu_addr(0x9000); - - /* monochrome GB uses a single BG palette */ - palette = gpu.bg_palette; - - /* never flip */ - x_flip = 0; - } - - /* obtain tile number */ - if ((*gpu.lcd_ctrl).bg_tiles == 0) - tile_n = (int8_t)tiles_map[tile_idx]; - else - tile_n = (tiles_map[tile_idx] & 0x00ff); - - /* calc vertical offset INSIDE the tile */ - p = (line - frame_y) * 2; - - /* calc frame position buffer for 4 pixels */ - uint32_t pos_fb = (line * 160); - - /* calc tile pointer */ - int16_t tile_ptr = (tile_n * 16) + p; - - /* pixels are handled in a super shitty way */ - /* bit 0 of the pixel is taken from even position tile bytes */ - /* bit 1 of the pixel is taken from odd position tile bytes */ - - uint8_t pxa[8]; - uint8_t shft; - - for (y = 0; y < 8; y++) - { - //uint8_t shft = (1 << y); - - if (x_flip) - shft = (1 << (7 - y)); - else - shft = (1 << y); - - pxa[y] = ((*(tiles + tile_ptr) & shft) ? 1 : 0) | - ((*(tiles + tile_ptr + 1) & shft) ? 2 : 0); - } - - /* set 8 pixels (full tile line) */ - for (i = 0; i < 8; i++) - { - /* over the last column? */ - uint8_t x = frame_x + (7 - i); - - if (x > 159) - continue; - - /* calc position on frame buffer */ - pos = pos_fb + x; - - /* can overwrite sprites? depends on pixel priority */ - if (gpu.priority[pos] != 0x02) - gpu.frame_buffer[pos] = palette[pxa[i]]; - } -} - -/* draw a sprite tile in x,y coordinates */ -void gpu_draw_sprite_line(gpu_oam_t *oam, uint8_t sprites_size, uint8_t line) -{ - int_fast32_t x, y, pos, fb_x, off; - uint_fast16_t p, i, j; - uint8_t sprite_bytes; - int16_t tile_ptr; - uint32_t *palette; - uint8_t *tiles; - - /* REMEMBER! position of sprites is relative to the visible screen area */ - /* ... and y is shifted by 16 pixels, x by 8 */ - y = oam->y - 16; - x = oam->x - 8; - - if (x < -7) - return; - - /* first pixel on frame buffer position */ - uint32_t tile_pos_fb = (y * 160) + x; - - /* choose palette */ - if (global_cgb) - { - uint8_t palette_idx = oam->palette_cgb; - - /* get palette pointer to 4 (16bit) colors */ - palette = &gpu.cgb_palette_oam_rgb888[palette_idx * 4]; - - /* tiles are into vram0 */ - if (oam->vram_bank) - tiles = mmu_addr_vram1(); - else - tiles = mmu_addr_vram0(); - } - else - { - /* tiles are int fixed 0x8000 address */ - tiles = mmu_addr(0x8000); - - if (oam->palette) - palette = gpu.obj_palette_1; - else - palette = gpu.obj_palette_0; - } - - /* calc sprite in byte */ - sprite_bytes = 16 * (sprites_size + 1); - - /* walk through 8x8 pixels (2bit per pixel -> 4 pixels per byte) */ - /* 1 line is 8 pixels -> 2 bytes per line */ - for (p = 0; p < sprite_bytes; p += 2) - { - uint8_t tile_y = p / 2; - - if (tile_y + y != line) - continue; - - /* calc frame position buffer for 4 pixels */ - uint32_t pos_fb = (tile_pos_fb + (tile_y * 160)) & 0xFFFF; //% 65536; - - /* calc tile pointer */ - if (oam->y_flip) - tile_ptr = (oam->pattern * 16) + (sprite_bytes - p - 2); - else - tile_ptr = (oam->pattern * 16) + p; - - /* pixels are handled in a super shitty way */ - /* bit 0 of the pixel is taken from even position tile bytes */ - /* bit 1 of the pixel is taken from odd position tile bytes */ - - uint8_t pxa[8]; - - for (j = 0; j < 8; j++) - { - uint8_t shft = (1 << j); - - pxa[j] = ((*(tiles + tile_ptr) & shft) ? 1 : 0) | - ((*(tiles + tile_ptr + 1) & shft) ? 2 : 0); - } - - /* set 8 pixels (full tile line) */ - for (i = 0; i < 8; i++) - { - if (oam->x_flip) - off = i; - else - off = 7 - i; - - /* is it on screen? */ - fb_x = x + off; - - if (fb_x < 0 || fb_x > 160) - continue; - - /* set serial position on frame buffer */ - pos = pos_fb + off; - - /* is it inside the screen? */ - if (pos >= 144 * 160 || pos < 0) - continue; - - if (global_cgb) - { - /* sprite color 0 = transparent */ - if (pxa[i] != 0x00) - { - /* flag clr = sprites always on top of bg and window */ - if ((*gpu.lcd_ctrl).bg == 0) - { - gpu.frame_buffer[pos] = palette[pxa[i]]; - gpu.priority[pos] = 0x02; - } - else - { - if (((gpu.priority[pos] == 0) && - (oam->priority == 0 || - (oam->priority == 1 && - gpu.palette_idx[pos] == 0x00))) || - (gpu.priority[pos] == 1 && - gpu.palette_idx[pos] == 0x00)) - { - gpu.frame_buffer[pos] = palette[pxa[i]]; - gpu.priority[pos] = (oam->priority ? 0x00 : 0x02); - } - } - } - } - else - { - /* push on screen pixels not set to zero (transparent) */ - /* and if the priority is set to one, overwrite just */ - /* bg pixels set to zero */ - if ((pxa[i] != 0x00) && - (oam->priority == 0 || - (oam->priority == 1 && - gpu.frame_buffer[pos] == gpu.bg_palette[0x00]))) - { - gpu.frame_buffer[pos] = palette[pxa[i]]; - gpu.priority[pos] = (oam->priority ? 0x00 : 0x02); - } - } - } - } -} - -/* update GPU internal state given CPU T-states */ -void gpu_step() -{ - char ly_changed = 0; - char mode_changed = 0; - - /* take different action based on current state */ - switch ((*gpu.lcd_status).mode) - { - /* - * during HBLANK (CPU can access VRAM) - */ - case 0: - /* handle HDMA stuff during hblank */ - cycles_hdma(); - - /* - * if current line == 143 (and it's about to turn 144) - * enter mode 01 (VBLANK) - */ - if (*gpu.ly == 143) - { - /* notify mode has changes */ - mode_changed = 1; - - (*gpu.lcd_status).mode = 0x01; - - /* mode one lasts 456 cycles */ - gpu.next = cycles.cnt + - (456 << global_cpu_double_speed); - - /* DRAW! TODO */ - /* CHECK INTERRUPTS! TODO */ - cycles_vblank(); - - /* set VBLANK interrupt flag */ - gpu_if->lcd_vblank = 1; - - /* apply gameshark patches */ - //mmu_apply_gs(); - - /* and finally push it on screen! */ - gpu_draw_frame(); - } - else - { - /* notify mode has changed */ - mode_changed = 1; - - /* enter OAM mode */ - (*gpu.lcd_status).mode = 0x02; - - /* mode 2 needs 80 cycles */ - gpu.next = cycles.cnt + - (80 << global_cpu_double_speed); - } - - /* notify mode has changed */ - ly_changed = 1; - - /* inc current line */ - (*gpu.ly)++; - - // cycles_hblank(*gpu.ly); - - break; - - /* - * during VBLANK (CPU can access VRAM) - */ - case 1: - /* notify ly has changed */ - ly_changed = 1; - - /* inc current line */ - (*gpu.ly)++; - - /* reached the bottom? */ - if ((*gpu.ly) > 153) - { - /* go back to line 0 */ - (*gpu.ly) = 0; - - /* switch to OAM mode */ - (*gpu.lcd_status).mode = 0x02; - - /* */ - gpu.next = - cycles.cnt + (80 << global_cpu_double_speed); - } - else - gpu.next = - cycles.cnt + (456 << global_cpu_double_speed); - - break; - - /* - * during OAM (LCD access FE00-FE90, so CPU cannot) - */ - case 2: - /* reset clock counter */ - gpu.next = - cycles.cnt + (172 << global_cpu_double_speed); - - /* notify mode has changed */ - mode_changed = 1; - - /* switch to VRAM mode */ - (*gpu.lcd_status).mode = 0x03; - - break; - - /* - * during VRAM (LCD access both OAM and VRAM, so CPU cannot) - */ - case 3: - /* reset clock counter */ - gpu.next = - cycles.cnt + (204 << global_cpu_double_speed); - - /* notify mode has changed */ - mode_changed = 1; - - /* go back to HBLANK mode */ - (*gpu.lcd_status).mode = 0x00; - - /* draw line */ - gpu_draw_line(*gpu.ly); - - /* notify cycles */ - // cycles_hblank(*gpu.ly); - - //printf("COLLA %d\n", *gpu.ly); - - break; - } - - /* ly changed? is it the case to trig an interrupt? */ - if (ly_changed) - { - /* check if we gotta trigger an interrupt */ - if ((*gpu.ly) == (*gpu.lyc)) - { - /* set lcd status flags indicating there's a concidence */ - (*gpu.lcd_status).ly_coincidence = 1; - - /* an interrupt is desiderable? */ - if ((*gpu.lcd_status).ir_ly_coincidence) - gpu_if->lcd_ctrl = 1; - } - else - { - /* set lcd status flags indicating there's NOT a concidence */ - (*gpu.lcd_status).ly_coincidence = 0; - } - } - - /* mode changed? is is the case to trig an interrupt? */ - if (mode_changed) - { - if ((*gpu.lcd_status).mode == 0x00 && - (*gpu.lcd_status).ir_mode_00) - gpu_if->lcd_ctrl = 1; - else if ((*gpu.lcd_status).mode == 0x01 && - (*gpu.lcd_status).ir_mode_01) - gpu_if->lcd_ctrl = 1; - else if ((*gpu.lcd_status).mode == 0x02 && - (*gpu.lcd_status).ir_mode_10) - gpu_if->lcd_ctrl = 1; - } -} - -uint8_t gpu_read_reg(uint16_t a) -{ - switch (a) - { - case 0xFF68: - - return (gpu.cgb_palette_bg_autoinc << 7 | gpu.cgb_palette_bg_idx); - - case 0xFF69: - - if ((gpu.cgb_palette_bg_idx & 0x01) == 0x00) - return gpu.cgb_palette_bg[gpu.cgb_palette_bg_idx / 2] & - 0x00ff; - else - return (gpu.cgb_palette_bg[gpu.cgb_palette_bg_idx / 2] & - 0xff00) >> - 8; - - case 0xFF6A: - - return (gpu.cgb_palette_oam_autoinc << 7 | gpu.cgb_palette_oam_idx); - - case 0xFF6B: - - if ((gpu.cgb_palette_oam_idx & 0x01) == 0x00) - return gpu.cgb_palette_oam[gpu.cgb_palette_oam_idx / 2] & - 0x00ff; - else - return (gpu.cgb_palette_oam[gpu.cgb_palette_oam_idx / 2] & - 0xff00) >> - 8; - } - - return 0x00; -} - -static uint32_t makecol(uint16_t c) -{ - // TODO: hook this up to the same color logic that the other cores use - return c >> 7 & 0xf8 | c >> 12 & 0x07 - | c << 6 & 0xf800 | c << 1 & 0x0700 - | c << 19 & 0xf80000 | c << 14 & 0x070000 - | 0xff000000; -} - -void gpu_write_reg(uint16_t a, uint8_t v) -{ - int i; - switch (a) - { - case 0xFF47: - gpu.bg_palette[0] = gpu_color_lookup[v & 0x03]; - gpu.bg_palette[1] = gpu_color_lookup[(v & 0x0c) >> 2]; - gpu.bg_palette[2] = gpu_color_lookup[(v & 0x30) >> 4]; - gpu.bg_palette[3] = gpu_color_lookup[(v & 0xc0) >> 6]; - break; - - case 0xFF48: - gpu.obj_palette_0[0] = gpu_color_lookup[v & 0x03]; - gpu.obj_palette_0[1] = gpu_color_lookup[(v & 0x0c) >> 2]; - gpu.obj_palette_0[2] = gpu_color_lookup[(v & 0x30) >> 4]; - gpu.obj_palette_0[3] = gpu_color_lookup[(v & 0xc0) >> 6]; - break; - - case 0xFF49: - gpu.obj_palette_1[0] = gpu_color_lookup[v & 0x03]; - gpu.obj_palette_1[1] = gpu_color_lookup[(v & 0x0c) >> 2]; - gpu.obj_palette_1[2] = gpu_color_lookup[(v & 0x30) >> 4]; - gpu.obj_palette_1[3] = gpu_color_lookup[(v & 0xc0) >> 6]; - break; - - case 0xFF68: - gpu.cgb_palette_bg_idx = (v & 0x3f); - gpu.cgb_palette_bg_autoinc = ((v & 0x80) == 0x80); - break; - - case 0xFF69: - i = gpu.cgb_palette_bg_idx / 2; - - if ((gpu.cgb_palette_bg_idx & 0x01) == 0x00) - { - gpu.cgb_palette_bg[i] &= 0xff00; - gpu.cgb_palette_bg[i] |= v; - } - else - { - gpu.cgb_palette_bg[i] &= 0x00ff; - gpu.cgb_palette_bg[i] |= (v << 8); - } - - gpu.cgb_palette_bg_rgb888[i] = makecol(gpu.cgb_palette_bg[i]); - - if (gpu.cgb_palette_bg_autoinc) - gpu.cgb_palette_bg_idx = (gpu.cgb_palette_bg_idx + 1) & 0x3f; - - break; - - case 0xFF6A: - gpu.cgb_palette_oam_idx = v & 0x3f; - gpu.cgb_palette_oam_autoinc = ((v & 0x80) == 0x80); - break; - - case 0xFF6B: - i = gpu.cgb_palette_oam_idx / 2; - - if ((gpu.cgb_palette_oam_idx & 0x01) == 0x00) - { - gpu.cgb_palette_oam[i] &= 0xff00; - gpu.cgb_palette_oam[i] |= v; - } - else - { - gpu.cgb_palette_oam[i] &= 0x00ff; - gpu.cgb_palette_oam[i] |= (v << 8); - } - - gpu.cgb_palette_oam_rgb888[i] = makecol(gpu.cgb_palette_oam[i]); - - if (gpu.cgb_palette_oam_autoinc) - gpu.cgb_palette_oam_idx = (gpu.cgb_palette_oam_idx + 1) & 0x3f; - - break; - } -} - -void gpu_set_speed(char speed) -{ - if (speed == 1) - gpu.step = 2; - else - gpu.step = 4; -} diff --git a/waterbox/pizza/lib/gpu.h b/waterbox/pizza/lib/gpu.h deleted file mode 100644 index 1fd8105d4e..0000000000 --- a/waterbox/pizza/lib/gpu.h +++ /dev/null @@ -1,133 +0,0 @@ -/* - - This file is part of Emu-Pizza - - Emu-Pizza is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Emu-Pizza is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Emu-Pizza. If not, see . - -*/ - -#ifndef __GPU_HDR__ -#define __GPU_HDR__ - -#include -#include - -/* callback function */ -typedef void (*gpu_frame_ready_cb_t) (); - -/* prototypes */ -void gpu_dump_oam(); -void gpu_init(gpu_frame_ready_cb_t cb); -void gpu_reset(); -void gpu_set_speed(char speed); -void gpu_step(); -void gpu_toggle(uint8_t state); -void gpu_write_reg(uint16_t a, uint8_t v); -uint8_t gpu_read_reg(uint16_t a); - - -/* Gameboy LCD Control - R/W accessing 0xFF40 address */ -typedef struct gpu_lcd_ctrl_s -{ - uint8_t bg:1; /* 0 = BG off, 1 = BG on */ - uint8_t sprites:1; /* ??? */ - uint8_t sprites_size:1; /* 0 = 8x8, 1 = 8x16 */ - uint8_t bg_tiles_map:1; /* 0 = 9800-9BFF, 1 = 9C00-9FFF */ - uint8_t bg_tiles:1; /* 0 = 8800-97FF, 1 = 8000-8FFF */ - uint8_t window:1; /* 0 = window off, 1 = on */ - uint8_t window_tiles_map:1; /* 0 = 9800-9BFF, 1 = 9C00-9FFF */ - uint8_t display:1; /* 0 = LCD off, 1 = LCD on */ -} gpu_lcd_ctrl_t; - -/* Gameboy LCD Status - R/W accessing 0xFF41 address */ -typedef struct gpu_lcd_status_s -{ - uint8_t mode:2; - uint8_t ly_coincidence:1; - uint8_t ir_mode_00:1; - uint8_t ir_mode_01:1; - uint8_t ir_mode_10:1; - uint8_t ir_ly_coincidence:1; - uint8_t spare:1; -} gpu_lcd_status_t; - -/* RGB color */ -typedef struct rgb_s -{ - uint8_t r; - uint8_t g; - uint8_t b; - uint8_t a; -} rgb_t; - -/* Gameboy GPU status */ -typedef struct gpu_s -{ - gpu_lcd_ctrl_t *lcd_ctrl; - gpu_lcd_status_t *lcd_status; - - /* scroll positions */ - uint8_t *scroll_x; - uint8_t *scroll_y; - - /* window position */ - uint8_t *window_x; - uint8_t *window_y; - - /* current scanline and it's compare values */ - uint8_t *ly; - uint8_t *lyc; - - /* clocks counter */ - uint64_t next; - - /* gpu step span */ - uint_fast32_t step; - - /* window last drawn lines */ - uint8_t window_last_ly; - uint8_t window_skipped_lines; - uint16_t spare; - - /* frame counter */ - uint_fast16_t frame_counter; - - /* BG palette */ - uint32_t bg_palette[4]; - - /* Obj palette 0/1 */ - uint32_t obj_palette_0[4]; - uint32_t obj_palette_1[4]; - - /* CGB palette for background */ - uint32_t cgb_palette_bg_rgb888[0x20]; - uint16_t cgb_palette_bg[0x20]; - uint8_t cgb_palette_bg_idx; - uint8_t cgb_palette_bg_autoinc; - - /* CGB palette for sprites */ - uint32_t cgb_palette_oam_rgb888[0x20]; - uint16_t cgb_palette_oam[0x20]; - uint8_t cgb_palette_oam_idx; - uint8_t cgb_palette_oam_autoinc; - - /* frame buffer */ - uint32_t frame_buffer[160 * 144]; - uint8_t priority[160 * 144]; - uint8_t palette_idx[160 * 144]; -} gpu_t; - -extern gpu_t gpu; - -#endif diff --git a/waterbox/pizza/lib/input.c b/waterbox/pizza/lib/input.c deleted file mode 100644 index 4dfde8d5aa..0000000000 --- a/waterbox/pizza/lib/input.c +++ /dev/null @@ -1,50 +0,0 @@ -/* - - This file is part of Emu-Pizza - - Emu-Pizza is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Emu-Pizza is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Emu-Pizza. If not, see . - -*/ - -#include "global.h" -#include "utils.h" - -#include - -/* button states */ -static uint8_t input_keys; - -void input_set_keys(uint8_t keys) -{ - // 7......0 - // DULRSsBA - input_keys = keys & 0xff; -} - -uint8_t input_get_keys(uint8_t line) -{ - uint8_t v = line | 0x0f; - - if ((line & 0x30) == 0x20) - { - v ^= input_keys >> 4; - } - - if ((line & 0x30) == 0x10) - { - v ^= input_keys & 0x0f; - } - - return v | 0xc0; -} diff --git a/waterbox/pizza/lib/input.h b/waterbox/pizza/lib/input.h deleted file mode 100644 index 3f678ea009..0000000000 --- a/waterbox/pizza/lib/input.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - - This file is part of Emu-Pizza - - Emu-Pizza is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Emu-Pizza is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Emu-Pizza. If not, see . - -*/ - -#ifndef __INPUT_HDR__ -#define __INPUT_HDR__ - -/* prototypes */ -uint8_t input_get_keys(uint8_t line); -void input_set_keys(uint8_t keys); - -#endif diff --git a/waterbox/pizza/lib/interrupt.h b/waterbox/pizza/lib/interrupt.h deleted file mode 100644 index 0fbc4b0873..0000000000 --- a/waterbox/pizza/lib/interrupt.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - - This file is part of Emu-Pizza - - Emu-Pizza is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Emu-Pizza is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Emu-Pizza. If not, see . - -*/ - -#ifndef __INTERRUPTS_HDR__ -#define __INTERRUPTS_HDR__ - -#include - -typedef struct interrupts_flags_s -{ - uint8_t lcd_vblank:1; - uint8_t lcd_ctrl:1; - uint8_t timer:1; - uint8_t serial_io:1; - uint8_t pins1013:1; - uint8_t spare:3; -} interrupts_flags_t; - -#endif \ No newline at end of file diff --git a/waterbox/pizza/lib/mmu.c b/waterbox/pizza/lib/mmu.c deleted file mode 100644 index 8a8bc9b30b..0000000000 --- a/waterbox/pizza/lib/mmu.c +++ /dev/null @@ -1,1029 +0,0 @@ -/* - - This file is part of Emu-Pizza - - Emu-Pizza is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Emu-Pizza is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Emu-Pizza. If not, see . - -*/ - -#include "cycles.h" -#include "global.h" -#include "gpu.h" -#include "interrupt.h" -#include "input.h" -#include "mmu.h" -#include "sound.h" -#include "serial.h" -#include "timer.h" -#include "utils.h" - -#include -#include -#include -#include -#include "sgb.h" -#include - -/* GAMEBOY MEMORY AREAS - -0x0000 - 0x00FF - BIOS -0x0000 - 0x3FFF - First 16k of game ROM (permanent) -0x4000 - 0x7FFF - ROM banks (switchable) -0x8000 - 0x9FFF - Video RAM (8kb - keeps pixels data) -0xA000 - 0xBFFF - External RAM (switchable, it was on cartridge, - 8kb banks, max 32k, NON volatile) -0xC000 - 0xDFFF - Gameboy RAM -0xE000 - 0xEFFF - ???????????????? -0xFE00 - 0xFF7F - I/O -0xFF80 - 0xFFFE - Temp RAM -0xFFFF - Turn on/off interrupts - -*/ - -/* cartridge memory (max 8MB) */ -uint8_t* cart_memory; - -/* RAM memory area */ -uint8_t *ram; -uint32_t ram_sz; - -/* main struct */ -mmu_t mmu; - -/* function to call when rumble */ -mmu_rumble_cb_t mmu_rumble_cb = NULL; - - -/* return absolute memory address */ -void *mmu_addr(uint16_t a) -{ - return (void *) &mmu.memory[a]; -} - -/* return absolute memory address */ -void *mmu_addr_vram0() -{ - return (void *) &mmu.vram0; -} - -/* return absolute memory address */ -void *mmu_addr_vram1() -{ - return (void *) &mmu.vram1; -} - -/* debug purposes */ -void mmu_dump_all() -{ - int i; - - printf("#### MAIN MEMORY ####\n\n"); - - for (i=0; i<0x10000; i++) - { - if ((i & 0x0f) == 0x00) - printf("\n%04x: ", i); - printf(" %02x", mmu.memory[i]); - } - - if (global_cgb) - { - printf("#### VRAM 0 ####\n\n"); - - for (i=0; i<0x2000; i++) - { - if ((i & 0x0f) == 0x00) - printf("\n%04x: ", i); - printf(" %02x", mmu.vram0[i]); - } - - printf("#### VRAM 1 ####\n\n"); - - for (i=0; i<0x2000; i++) - { - if ((i & 0x0f) == 0x00) - printf("\n%04x: ", i); - printf(" %02x", mmu.vram1[i]); - } - } -} - -/* init (alloc) system state.memory */ -void mmu_init(uint8_t c, uint8_t rn) -{ - mmu.rom_current_bank = 0x01; - mmu.ram_current_bank = 0x00; - - /* set ram to NULL */ - ram = NULL; - - /* save carttype and qty of ROM blocks */ - mmu.carttype = c; - mmu.roms = rn; - - mmu.vram_idx = 0; - mmu.wram_current_bank = 1; - mmu.ram_current_bank = 0; - mmu.ram_external_enabled = 0; - mmu.dma_cycles = 0; - mmu.dma_address = 0; - mmu.rtc_mode = 0; - - /* reset memory */ - bzero(mmu.memory, 65536); -} - -/* init (alloc) system state.memory */ -void mmu_init_ram(uint32_t c) -{ - ram_sz = c; - - ram = malloc(c); - - bzero(ram, c); -} - -/* load data in a certain address */ -void mmu_load(uint8_t *data, size_t sz, uint16_t a) -{ - memcpy(&mmu.memory[a], data, sz); -} - -/* load full cartridge */ -void mmu_load_cartridge(const uint8_t *data, size_t sz) -{ - /* copy max 32k into working memory */ - memcpy(mmu.memory, data, 2 << 14); - - cart_memory = alloc_sealed(1 << 22); - /* copy full cartridge */ - memcpy(cart_memory, data, sz); -} - -/* move 8 bit from s to d */ -void mmu_move(uint16_t d, uint16_t s) -{ - mmu_write(d, mmu_read(s)); -} - -/* read 8 bit data from a memory addres */ -uint8_t mmu_read(uint16_t a) -{ - /* always takes 4 cycles */ - cycles_step(); - - /* 90% of the read is in the ROM area */ - if (a < 0x8000) - return mmu.memory[a]; - - /* test VRAM */ - if (a < 0xA000) - { - if (global_cgb) - { - if (mmu.vram_idx == 0) - return mmu.vram0[a - 0x8000]; - else - return mmu.vram1[a - 0x8000]; - } - - return mmu.memory[a]; - } - - if (a < 0xC000) - { - if (mmu.rtc_mode != 0x00) - { - int64_t diff = mmu.rtc_latch_time - mmu.rtc_time; - - switch (mmu.rtc_mode) - { - case 0x08: - return (diff % 60); - case 0x09: - return ((diff / 60) % 60); - case 0x0A: - return (diff / 3600) % 24; - case 0x0B: - return (diff / (3600 * 24)) & 0x00FF; - case 0x0C: - return ((diff / (3600 * 24)) & 0xFF00) >> 8; - } - } - else - return mmu.memory[a]; - } - - /* RAM */ - if (a < 0xE000) - return mmu.memory[a]; - - /* RAM mirror */ - if (a < 0xFE00) - return mmu.memory[a - 0x2000]; - - switch (a) - { - /* serial registers */ - case 0xFF01: - case 0xFF02: - return serial_read_reg(a); - - /* don't ask me why.... */ - case 0xFF44: - return (mmu.memory[0xFF44] == 153 ? 0 : mmu.memory[0xFF44]); - - /* sound registers */ - case 0xFF10 ... 0xFF3F: - return sound_read_reg(a, mmu.memory[a]); - - /* joypad reading */ - case 0xFF00: - global_lagged = 0; - if (global_input_callback) - global_input_callback(); - return global_sgb ? sgb_read_ff00(cycles.sampleclock) : input_get_keys(mmu.memory[a]); - - /* CGB HDMA transfer */ - case 0xFF55: - - if (!global_cgb) break; - - /* HDMA result */ - if (mmu.hdma_to_transfer) - return (mmu.hdma_to_transfer / 0x10 - 0x01); - else - return 0xFF; - - /* CGB color palette registers */ - case 0xFF68: - case 0xFF69: - case 0xFF6A: - case 0xFF6B: - - if (!global_cgb) break; - - /* color palettes registers */ - return gpu_read_reg(a); - - /* timer registers */ - case 0xFF04 ... 0xFF07: - return timer_read_reg(a); - - } - - return mmu.memory[a]; -} - -/* read 16 bit data from a memory addres */ -unsigned int mmu_read_16(uint16_t a) -{ - return (mmu_read(a) | (mmu_read(a + 1) << 8)); -} - -/* read 8 bit data from a memory addres (not affecting cycles) */ -uint8_t mmu_read_no_cyc(uint16_t a) -{ - if (a >= 0xE000 && a <= 0xFDFF) - return mmu.memory[a - 0x2000]; - - return mmu.memory[a]; -} - -static int has_saveram(void) -{ - return mmu.carttype == 0x03 || - mmu.carttype == 0x06 || - mmu.carttype == 0x09 || - mmu.carttype == 0x0D || - mmu.carttype == 0x0F || - mmu.carttype == 0x10 || - mmu.carttype == 0x13 || - mmu.carttype == 0x17 || - mmu.carttype == 0x1B || - mmu.carttype == 0x1E || - mmu.carttype == 0x22 || - mmu.carttype == 0xFF; -} - -int mmu_saveram_size(void) -{ - return has_saveram() ? ram_sz : 0; -} - -void mmu_restore_saveram(const uint8_t* data, int sz) -{ - if (sz == mmu_saveram_size()) - { - if (ram_sz <= 0x2000) - { - memcpy(&mmu.memory[0xa000], data, ram_sz); - } - else - { - memcpy(ram, data, ram_sz); - if (mmu.ram_external_enabled) - memcpy(&mmu.memory[0xa000], &ram[0x2000 * mmu.ram_current_bank], 0x2000); - } - } -} - -void mmu_save_saveram(uint8_t* dest, int sz) -{ - if (sz == mmu_saveram_size()) - { - if (ram_sz <= 0x2000) - { - memcpy(dest, &mmu.memory[0xa000], ram_sz); - } - else - { - memcpy(dest, ram, ram_sz); - if (mmu.ram_external_enabled) - memcpy(&dest[0x2000 * mmu.ram_current_bank], &mmu.memory[0xa000], 0x2000); - } - } -} - -void mmu_set_rumble_cb(mmu_rumble_cb_t cb) -{ - mmu_rumble_cb = cb; -} - -/* write 16 bit block on a memory address */ -void mmu_write(uint16_t a, uint8_t v) -{ - /* update cycles AFTER memory set */ - cycles_step(); - - /* color gameboy stuff */ - if (global_cgb) - { - /* VRAM write? */ - if (a >= 0x8000 && a < 0xA000) - { - if (mmu.vram_idx == 0) - mmu.vram0[a - 0x8000] = v; - else - mmu.vram1[a - 0x8000] = v; - - return; - } - else - { - /* wanna access to RTC register? */ - if (a >= 0xA000 && a <= 0xBFFF && mmu.rtc_mode != 0x00) - { - int64_t t,s1,s2,m1,m2,h1,h2,d1,d2,days; - - t = global_currenttime; - - /* extract parts in seconds from current and ref times */ - s1 = t % 60; - s2 = mmu.rtc_time % 60; - - m1 = (t - s1) % (60 * 60); - m2 = (mmu.rtc_time - s2) % (60 * 60); - - h1 = (t - m1 - s1) % (60 * 60 * 24); - h2 = (mmu.rtc_time - m2 - s2) % (60 * 60 * 24); - - d1 = t - h1 - m1 - s1; - d2 = mmu.rtc_time - h2 - m2 - s2; - - switch (mmu.rtc_mode) - { - case 0x08: - - /* remove seconds from current time */ - mmu.rtc_time -= s2; - - /* set new seconds */ - mmu.rtc_time += (s1 - v); - - return; - - case 0x09: - - /* remove seconds from current time */ - mmu.rtc_time -= m2; - - /* set new seconds */ - mmu.rtc_time += (m1 - (v * 60)); - - return; - - case 0x0A: - - /* remove seconds from current time */ - mmu.rtc_time -= h2; - - /* set new seconds */ - mmu.rtc_time += (h1 - (v * 60 * 24)); - - return; - - case 0x0B: - - days = (((d1 - d2) / - (60 * 60 * 24)) & 0xFF00) | v; - - /* remove seconds from current time */ - mmu.rtc_time -= d2; - - /* set new seconds */ - mmu.rtc_time += (d1 - (days * 60 * 60 * 24)); - - return; - - case 0x0C: - - days = (((d1 - d2) / - (60 * 60 * 24)) & 0xFEFF) | (v << 8); - - /* remove seconds from current time */ - mmu.rtc_time -= d2; - - /* set new seconds */ - mmu.rtc_time += (d1 - (days * 60 * 60 * 24)); - - return; - } - } - } - - /* switch WRAM */ - if (a == 0xFF70) - { - /* number goes from 1 to 7 */ - uint8_t new = (v & 0x07); - - if (new == 0) - new = 1; - - if (new == mmu.wram_current_bank) - return; - - /* save current bank */ - memcpy(&mmu.wram[0x1000 * mmu.wram_current_bank], - &mmu.memory[0xD000], 0x1000); - - mmu.wram_current_bank = new; - - /* move new ram bank */ - memcpy(&mmu.memory[0xD000], - &mmu.wram[0x1000 * mmu.wram_current_bank], - 0x1000); - - /* save current bank */ - mmu.memory[0xFF70] = new; - - return; - } - - if (a == 0xFF4F) - { - /* extract VRAM index from last bit */ - mmu.vram_idx = (v & 0x01); - - /* save current VRAM bank */ - mmu.memory[0xFF4F] = mmu.vram_idx; - - return; - } - } - - /* wanna write on ROM? */ - if (a < 0x8000) - { - /* return in case of ONLY ROM */ - if (mmu.carttype == 0x00) - return; - - /* TODO - MBC strategies */ - uint8_t b = mmu.rom_current_bank; - - switch (mmu.carttype) - { - /* MBC1 */ - case 0x01: - case 0x02: - case 0x03: - - if (a >= 0x2000 && a <= 0x3FFF) - { - /* reset 5 bits */ - b = mmu.rom_current_bank & 0xE0; - - /* set them with new value */ - b |= v & 0x1F; - - /* doesn't fit on max rom number? */ - if (b > (2 << mmu.roms)) - { - /* filter result to get a value < max rom number */ - b %= (2 << mmu.roms); - } - - /* 0x00 is not valid, switch it to 0x01 */ - if (b == 0x00) - b = 0x01; - } - else if (a >= 0x4000 && a <= 0x5FFF) - { - /* ROM banking? it's about 2 higher bits */ - if (mmu.banking == 0) - { - /* reset 5 bits */ - b = mmu.rom_current_bank & 0x1F; - - /* set them with new value */ - b |= (v << 5); - - /* doesn't fit on max rom number? */ - if (b > (2 << mmu.roms)) - { - /* filter result to get a value < max rom number */ - b %= (2 << mmu.roms); - } - } - else - { - if ((0x2000 * v) < ram_sz) - { - /* save current bank */ - memcpy(&ram[0x2000 * mmu.ram_current_bank], - &mmu.memory[0xA000], 0x2000); - - mmu.ram_current_bank = v; - - /* move new ram bank */ - memcpy(&mmu.memory[0xA000], - &ram[0x2000 * mmu.ram_current_bank], - 0x2000); - } - } - } - else if (a >= 0x6000 && a <= 0x7FFF) - mmu.banking = v; - - break; - - /* MBC2 */ - case 0x05: - case 0x06: - - if (a >= 0x2000 && a <= 0x3FFF) - { - /* use lower nibble to set current bank */ - b = v & 0x0f; - - /*if (b != rom_current_bank) - memcpy(&memory[0x4000], - &cart_memory[b * 0x4000], 0x4000); - - rom_current_bank = b;*/ - } - - break; - - /* MBC3 */ - case 0x10: - case 0x13: - - if (a >= 0x0000 && a <= 0x1FFF) - { - if (v == 0x0A) - { - /* already enabled? */ - if (mmu.ram_external_enabled) - return; - - /* restore external ram bank */ - memcpy(&mmu.memory[0xA000], - &ram[0x2000 * mmu.ram_current_bank], - 0x2000); - - /* set external RAM eanbled flag */ - mmu.ram_external_enabled = 1; - - return; - } - - if (v == 0x00) - { - /* already disabled? */ - if (mmu.ram_external_enabled == 0) - return; - - /* save current bank */ - memcpy(&ram[0x2000 * mmu.ram_current_bank], - &mmu.memory[0xA000], 0x2000); - - /* clear external RAM eanbled flag */ - mmu.ram_external_enabled = 0; - } - } - else if (a >= 0x2000 && a <= 0x3FFF) - { - /* set them with new value */ - b = v & 0x7F; - - /* doesn't fit on max rom number? */ - if (b > (2 << mmu.roms)) - { - /* filter result to get a value < max rom number */ - b %= (2 << mmu.roms); - } - - /* 0x00 is not valid, switch it to 0x01 */ - if (b == 0x00) - b = 0x01; - } - else if (a >= 0x4000 && a <= 0x5FFF) - { - /* 0x00 to 0x07 is referred to RAM bank */ - if (v < 0x08) - { - /* not on RTC mode anymore */ - mmu.rtc_mode = 0x00; - - if ((0x2000 * (v & 0x0f)) < ram_sz) - { - /* save current bank */ - memcpy(&ram[0x2000 * mmu.ram_current_bank], - &mmu.memory[0xA000], 0x2000); - - mmu.ram_current_bank = v & 0x0f; - - /* move new ram bank */ - memcpy(&mmu.memory[0xA000], - &ram[0x2000 * mmu.ram_current_bank], - 0x2000); - } - } - else if (v < 0x0d) - { - /* from 0x08 to 0x0C trigger RTC mode */ - mmu.rtc_mode = v; - } - - } - else if (a >= 0x6000 && a <= 0x7FFF) - { - /* latch clock data. move clock data to RTC registers */ - mmu.rtc_latch_time = global_currenttime; - } - - - break; - - /* MBC5 */ - case 0x19: - case 0x1A: - case 0x1B: - case 0x1C: - case 0x1D: - case 0x1E: - - if (a >= 0x0000 && a <= 0x1FFF) - { - if (v == 0x0A) - { - /* we got external RAM? some stupid game try */ - /* to access it despite it doesn't have it */ - if (ram_sz == 0) - return; - - /* already enabled? */ - if (mmu.ram_external_enabled) - return; - - /* restore external ram bank */ - memcpy(&mmu.memory[0xA000], - &ram[0x2000 * mmu.ram_current_bank], - 0x2000); - - /* set external RAM eanbled flag */ - mmu.ram_external_enabled = 1; - - return; - } - - if (v == 0x00) - { - /* we got external RAM? some stpd game try to do shit */ - if (ram_sz == 0) - return; - - /* already disabled? */ - if (mmu.ram_external_enabled == 0) - return; - - /* save current bank */ - memcpy(&ram[0x2000 * mmu.ram_current_bank], - &mmu.memory[0xA000], 0x2000); - - /* clear external RAM eanbled flag */ - mmu.ram_external_enabled = 0; - } - } - if (a >= 0x2000 && a <= 0x2FFF) - { - /* set them with new value */ - b = (mmu.rom_current_bank & 0xFF00) | v; - - /* doesn't fit on max rom number? */ - if (b > (2 << mmu.roms)) - { - /* filter result to get a value < max rom number */ - b %= (2 << mmu.roms); - } - } - else if (a >= 0x3000 && a <= 0x3FFF) - { - /* set them with new value */ - b = (mmu.rom_current_bank & 0x00FF) | ((v & 0x01) << 8); - - /* doesn't fit on max rom number? */ - if (b > (2 << mmu.roms)) - { - /* filter result to get a value < max rom number */ - b %= (2 << mmu.roms); - } - } - else if (a >= 0x4000 && a <= 0x5FFF) - { - uint8_t mask = 0x0F; - - if (global_rumble) - { - mask = 0x07; - - if (mmu_rumble_cb) - (*mmu_rumble_cb) ((v & 0x08) ? 1 : 0); - - /* check if we want to appizz the motor */ -/* if (v & 0x08) - printf("APPIZZ MOTOR\n"); - else - printf("SPEGN MOTOR\n");*/ - } - - if ((0x2000 * (v & mask)) < ram_sz) - { - /* is externa RAM enabled? */ - if (!mmu.ram_external_enabled) - break; - - /* wanna switch on the same bank? =\ just discard it */ - if ((v & 0x0f) == mmu.ram_current_bank) - break; - - /* save current bank */ - memcpy(&ram[0x2000 * mmu.ram_current_bank], - &mmu.memory[0xA000], 0x2000); - - mmu.ram_current_bank = (v & 0x0f); - - /* move new ram bank */ - memcpy(&mmu.memory[0xA000], - &ram[0x2000 * mmu.ram_current_bank], - 0x2000); - } - } - - break; - - } - - /* need to switch? */ - if (b != mmu.rom_current_bank) - { - /* copy from cartridge rom to GB switchable bank area */ - memcpy(&mmu.memory[0x4000], &cart_memory[b * 0x4000], 0x4000); - - /* save new current bank */ - mmu.rom_current_bank = b; - } - - return; - } - - if (a >= 0xE000) - { - /* changes on sound registers? */ - if (a >= 0xFF10 && a <= 0xFF3F) - { - /* set memory */ - sound_write_reg(a, v); - - return; - } - - /* mirror area */ - if (a >= 0xE000 && a <= 0xFDFF) - { - mmu.memory[a - 0x2000] = v; - return; - } - - /* TODO - put them all */ - switch(a) - { - case 0xFF00: - sgb_write_ff00(v, cycles.sampleclock); - break; - case 0xFF01: - case 0xFF02: - serial_write_reg(a, v); - return; - case 0xFF04 ... 0xFF07: - timer_write_reg(a, v); - return; - } - - /* LCD turned on/off? */ - if (a == 0xFF40) - { - if ((v ^ mmu.memory[0xFF40]) & 0x80) - gpu_toggle(v); - } - - /* only 5 high bits are writable */ - if (a == 0xFF41) - { - mmu.memory[a] = (mmu.memory[a] & 0x07) | (v & 0xf8); - return; - } - - /* palette update */ - if ((a >= 0xFF47 && a <= 0xFF49) || - (a >= 0xFF68 && a <= 0xFF6B)) - gpu_write_reg(a, v); - - /* CGB only registers */ - if (global_cgb) - { - switch (a) - { - case 0xFF4D: - - /* wanna switch speed? */ - if (v & 0x01) - { - global_cpu_double_speed ^= 0x01; - - /* update new clock */ - // cycles_clock = 4194304 << global_double_speed; - cycles_set_speed(1); - sound_set_speed(1); - gpu_set_speed(1); - - /* save into memory i'm working at double speed */ - if (global_cpu_double_speed) - mmu.memory[a] = 0x80; - else - mmu.memory[a] = 0x00; - } - - return; - - case 0xFF52: - - /* high byte of HDMA source address */ - mmu.hdma_src_address &= 0xff00; - - /* lower 4 bits are ignored */ - mmu.hdma_src_address |= (v & 0xf0); - - break; - - case 0xFF51: - - /* low byte of HDMA source address */ - mmu.hdma_src_address &= 0x00ff; - - /* highet 3 bits are ignored (always 100 binary) */ - mmu.hdma_src_address |= (v << 8); - - break; - - case 0xFF54: - - /* high byte of HDMA source address */ - mmu.hdma_dst_address &= 0xff00; - - /* lower 4 bits are ignored */ - mmu.hdma_dst_address |= (v & 0xf0); - - break; - - case 0xFF53: - - /* low byte of HDMA source address */ - mmu.hdma_dst_address &= 0x00ff; - - /* highet 3 bits are ignored (always 100 binary) */ - mmu.hdma_dst_address |= ((v & 0x1f) | 0x80) << 8; - - break; - - case 0xFF55: - - /* wanna stop HBLANK transfer? a zero on 7th bit will do */ - if ((v & 0x80) == 0 && - mmu.hdma_transfer_mode == 0x01 && - mmu.hdma_to_transfer) - { - mmu.hdma_to_transfer = 0x00; - mmu.hdma_transfer_mode = 0x00; - - return; - } - - /* general (0) or hblank (1) ? */ - mmu.hdma_transfer_mode = ((v & 0x80) ? 1 : 0); - - /* calc how many bytes gotta be transferred */ - uint16_t to_transfer = ((v & 0x7f) + 1) * 0x10; - - /* general must be done immediately */ - if (mmu.hdma_transfer_mode == 0) - { - /* copy right now */ - if (mmu.vram_idx) - memcpy(mmu_addr_vram1() + - (mmu.hdma_dst_address - 0x8000), - &mmu.memory[mmu.hdma_src_address], - to_transfer); - else - memcpy(mmu_addr_vram0() + - (mmu.hdma_dst_address - 0x8000), - &mmu.memory[mmu.hdma_src_address], - to_transfer); - - /* reset to_transfer var */ - mmu.hdma_to_transfer = 0; - - /* move forward src and dst addresses =| */ - mmu.hdma_src_address += to_transfer; - mmu.hdma_dst_address += to_transfer; - } - else - { - mmu.hdma_to_transfer = to_transfer; - - /* check if we're already into hblank phase */ - cycles_hdma(); - } - - break; - } - } - - /* finally set memory byte with data */ - mmu.memory[a] = v; - - /* DMA access */ - if (a == 0xFF46) - { - /* calc source address */ - mmu.dma_address = v * 256; - - /* initialize counter, DMA needs 672 ticks */ - mmu.dma_next = cycles.cnt + 4; // 168 / 2; - } - } - else - mmu.memory[a] = v; -} - -/* write 16 bit block on a memory address */ -void mmu_write_16(uint16_t a, uint16_t v) -{ - mmu.memory[a] = (uint8_t) (v & 0x00ff); - mmu.memory[a + 1] = (uint8_t) (v >> 8); - - /* 16 bit write = +8 cycles */ - cycles_step(); - cycles_step(); -} - - -/* write 16 bit block on a memory address (no cycles affected) */ -void mmu_write_no_cyc(uint16_t a, uint8_t v) -{ - mmu.memory[a] = v; -} diff --git a/waterbox/pizza/lib/mmu.h b/waterbox/pizza/lib/mmu.h deleted file mode 100644 index cc36b8e0cc..0000000000 --- a/waterbox/pizza/lib/mmu.h +++ /dev/null @@ -1,112 +0,0 @@ -/* - - This file is part of Emu-Pizza - - Emu-Pizza is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Emu-Pizza is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Emu-Pizza. If not, see . - -*/ - -#ifndef __MMU_HDR__ -#define __MMU_HDR__ - -#include -#include - -typedef struct mmu_s -{ - /* main 64K of memory */ - uint8_t memory[65536]; - - /* vram in standby */ - uint8_t vram0[0x2000]; - uint8_t vram1[0x2000]; - - /* vram current idx */ - uint8_t vram_idx; - uint8_t spare; - uint16_t spare2; - - // cartridge RAM - uint8_t ram_external_enabled; - uint8_t ram_current_bank; - - /* cartridge type */ - uint8_t carttype; - - /* number of switchable roms */ - uint8_t roms; - - /* current ROM bank */ - uint8_t rom_current_bank; - - /* type of banking */ - uint8_t banking; - - /* working RAM (only CGB) */ - uint8_t wram[0x8000]; - - /* current WRAM bank (only CGB) */ - uint8_t wram_current_bank; - uint8_t spare3; - uint16_t spare4; - - /* DMA transfer stuff */ - uint_fast16_t dma_address; - uint_fast16_t dma_cycles; - - /* HDMA transfer stuff */ - uint16_t hdma_src_address; - uint16_t hdma_dst_address; - uint16_t hdma_to_transfer; - uint8_t hdma_transfer_mode; - uint8_t hdma_current_line; - - /* RTC stuff */ - uint8_t rtc_mode; - int64_t rtc_time; - int64_t rtc_latch_time; - - uint64_t dma_next; -} mmu_t; - -extern mmu_t mmu; - -/* callback function */ -typedef void (*mmu_rumble_cb_t)(uint8_t onoff); - -/* functions prototypes */ -void *mmu_addr(uint16_t a); -void *mmu_addr_vram0(); -void *mmu_addr_vram1(); -void mmu_dump_all(); -void mmu_init(uint8_t c, uint8_t rn); -void mmu_init_ram(uint32_t c); -void mmu_load(uint8_t *data, size_t sz, uint16_t a); -void mmu_load_cartridge(const uint8_t *data, size_t sz); -void mmu_move(uint16_t d, uint16_t s); -uint8_t mmu_read_no_cyc(uint16_t a); -uint8_t mmu_read(uint16_t a); -unsigned int mmu_read_16(uint16_t a); -int mmu_saveram_size(void); -void mmu_restore_saveram(const uint8_t *data, int sz); -void mmu_save_saveram(uint8_t *dest, int sz); -void mmu_restore_rtc(char *fn); -void mmu_save_rtc(char *fn); -void mmu_set_rumble_cb(mmu_rumble_cb_t cb); -void mmu_step(); -void mmu_write_no_cyc(uint16_t a, uint8_t v); -void mmu_write(uint16_t a, uint8_t v); -void mmu_write_16(uint16_t a, uint16_t v); - -#endif diff --git a/waterbox/pizza/lib/serial.c b/waterbox/pizza/lib/serial.c deleted file mode 100644 index 497d8a65c1..0000000000 --- a/waterbox/pizza/lib/serial.c +++ /dev/null @@ -1,192 +0,0 @@ -/* - - This file is part of Emu-Pizza - - Emu-Pizza is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Emu-Pizza is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Emu-Pizza. If not, see . - -*/ - -#include "cycles.h" -#include "interrupt.h" -#include "mmu.h" -#include "serial.h" -#include "utils.h" - -/* main variable */ -serial_t serial; - -/* function to call when frame is ready */ -serial_data_send_cb_t serial_data_send_cb; - -interrupts_flags_t *serial_if; - -/* second message before the first was handled? */ -uint8_t serial_second_set = 0; -uint8_t serial_second_data = 0; -uint8_t serial_second_clock = 0; -uint8_t serial_second_transfer_start = 0; -uint8_t serial_waiting_data = 0; - -void serial_verify_intr() -{ - if (serial.data_recv && serial.data_sent) - { - serial.data_recv = 0; - serial.data_sent = 0; - - /* valid couple of messages for a serial interrupt? */ - if ((serial.data_recv_clock != serial.data_sent_clock) && - serial.data_recv_transfer_start && - serial.data_sent_transfer_start) - { - /* put received data into 0xFF01 (serial.data) */ - /* and notify with an interrupt */ - serial.transfer_start = 0; - serial.data = serial.data_to_recv; - - serial_if->serial_io = 1; - } - - /* a message is already on queue? */ - if (serial_second_set) - { - serial_second_set = 0; - serial.data_recv = 1; - serial.data_to_recv = serial_second_data; - serial.data_recv_clock = serial_second_clock; - serial.data_recv_transfer_start = serial_second_transfer_start; - } - } -} - -void serial_init() -{ - /* pointer to interrupt flags */ - serial_if = mmu_addr(0xFF0F); - - /* init counters */ - serial.bits_sent = 0; - - /* start as not connected */ - serial.peer_connected = 0; -} - -void serial_write_reg(uint16_t a, uint8_t v) -{ - switch (a) - { - case 0xFF01: - serial.data = v; - return; - case 0xFF02: - serial.clock = v & 0x01; - serial.speed = (v & 0x02) ? 0x01 : 0x00; - serial.spare = ((v >> 2) & 0x1F); - serial.transfer_start = (v & 0x80) ? 0x01 : 0x00; - - /* reset? */ - serial.data_sent = 0; - break; - } - - if (serial.transfer_start && - !serial.peer_connected && - serial.clock) - { - if (serial.speed) - serial.next = cycles.cnt + 8 * 8; - else - serial.next = cycles.cnt + 256 * 8; - } -} - -uint8_t serial_read_reg(uint16_t a) -{ - uint8_t v = 0xFF; - - switch (a) - { - case 0xFF01: v = serial.data; break; - case 0xFF02: v = ((serial.clock) ? 0x01 : 0x00) | - ((serial.speed) ? 0x02 : 0x00) | - (serial.spare << 2) | - ((serial.transfer_start) ? 0x80 : 0x00); - } - - return v; -} - -void serial_recv_byte(uint8_t v, uint8_t clock, uint8_t transfer_start) -{ - /* second message during same span time? */ - if (serial.data_recv) - { - /* store it. handle it later */ - serial_second_set = 1; - serial_second_data = v; - serial_second_clock = clock; - serial_second_transfer_start = transfer_start; - return; - } - - /* received side OK */ - serial.data_recv = 1; - serial.data_recv_clock = clock; - serial.data_to_recv = v; - serial.data_recv_transfer_start = transfer_start; - - /* notify main thread in case it's waiting */ - //if (serial_waiting_data) - //pthread_cond_signal(&serial_cond); -} - -void serial_send_byte() -{ - serial.data_sent = 1; - serial.data_to_send = serial.data; - serial.data_sent_clock = serial.clock; - serial.data_sent_transfer_start = serial.transfer_start; - - if (serial_data_send_cb) - (*serial_data_send_cb) (serial.data, serial.clock, - serial.transfer_start); -} - -void serial_set_send_cb(serial_data_send_cb_t cb) -{ - serial_data_send_cb = cb; -} - -void serial_wait_data() -{ - if (serial.data_sent && serial.data_recv == 0) - { - /* wait max 3 seconds */ - //struct timespec wait; - - //wait.tv_sec = time(NULL) + 3; - - /* this is very important to avoid EINVAL return! */ - //wait.tv_nsec = 0; - - /* declare i'm waiting for data */ - //serial_waiting_data = 1; - - /* notify something has arrived */ - // pthread_cond_timedwait(&serial_cond, &serial_mutex, &wait); - - /* not waiting anymore */ - //serial_waiting_data = 0; - } -} diff --git a/waterbox/pizza/lib/serial.h b/waterbox/pizza/lib/serial.h deleted file mode 100644 index d4cfb918eb..0000000000 --- a/waterbox/pizza/lib/serial.h +++ /dev/null @@ -1,92 +0,0 @@ -/* - - This file is part of Emu-Pizza - - Emu-Pizza is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Emu-Pizza is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Emu-Pizza. If not, see . - -*/ - -#ifndef __SERIAL_HDR__ -#define __SERIAL_HDR__ - -#include -#include - -typedef struct serial_ctrl_s -{ - uint8_t clock; - uint8_t speed; - uint8_t spare; - uint8_t transfer_start; -} serial_ctrl_t; - -typedef struct serial_s { - - /* pointer to serial controller register */ - // serial_ctrl_t ctrl; - - uint8_t clock; - uint8_t speed; - uint8_t spare; - uint8_t transfer_start; - - /* pointer to FF01 data */ - uint8_t data; - - /* sent bits */ - uint8_t bits_sent; - - /* data to send */ - uint8_t data_to_send; - - /* peer clock */ - uint8_t data_to_recv; - - /* counter */ - uint64_t next; - - /* peer connected? */ - uint8_t peer_connected:1; - uint8_t data_sent:1; - uint8_t data_sent_clock:1; - uint8_t data_sent_transfer_start:1; - uint8_t data_recv:1; - uint8_t data_recv_clock:1; - uint8_t data_recv_transfer_start:1; - uint8_t spare10:1; - - uint_fast32_t last_send_cnt; - -} serial_t; - -extern serial_t serial; - -/* callback when receive something on serial */ -typedef void (*serial_data_send_cb_t) (uint8_t v, uint8_t clock, - uint8_t transfer_start); - -/* prototypes */ -void serial_init(); -void serial_lock(); -void serial_write_reg(uint16_t a, uint8_t v); -void serial_verify_intr(); -uint8_t serial_read_reg(uint16_t a); -void serial_recv_byte(uint8_t v, uint8_t clock, uint8_t transfer_start); -void serial_recv_clock(); -void serial_send_byte(); -void serial_set_send_cb(serial_data_send_cb_t cb); -void serial_unlock(); -void serial_wait_data(); - -#endif diff --git a/waterbox/pizza/lib/sound.c b/waterbox/pizza/lib/sound.c deleted file mode 100644 index 183e07a6b7..0000000000 --- a/waterbox/pizza/lib/sound.c +++ /dev/null @@ -1,1159 +0,0 @@ -/* - - This file is part of Emu-Pizza - - Emu-Pizza is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Emu-Pizza is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Emu-Pizza. If not, see . - -*/ - -#include "cycles.h" -#include "global.h" -#include "gpu.h" -#include "mmu.h" -#include "sound.h" -#include "utils.h" -#include "sound_output.h" - -#include -#include -#include - -/* super variable for audio controller */ -sound_t sound; - -// functions to connect to blip buf -static int16_t last_sample[8]; - -#define BLIP_LEFT(v,i) if(1){int32_t d = (v)-last_sample[(i)*2];blip_left(d);last_sample[(i)*2] = (v);} -#define BLIP_RIGHT(v,i) if(1){int32_t d = (v)-last_sample[(i)*2+1];blip_right(d);last_sample[(i)*2+1] = (v);} - -static void blip_ch1() -{ - if (sound.channel_one.active) - { - if (sound.nr51->ch1_to_so1) - BLIP_RIGHT(sound.channel_one.sample, 0); - if (sound.nr51->ch1_to_so2) - BLIP_LEFT(sound.channel_one.sample, 0); - } -} -static void blip_ch2() -{ - if (sound.channel_two.active) - { - if (sound.nr51->ch2_to_so1) - BLIP_RIGHT(sound.channel_two.sample, 1); - if (sound.nr51->ch2_to_so2) - BLIP_LEFT(sound.channel_two.sample, 1); - } -} -static void blip_ch3() -{ - if (sound.channel_three.active) - { - uint16_t sample; - uint8_t shift = sound.nr32->volume_code == 0 ? 4 : sound.nr32->volume_code - 1; - - /* volume is zero in any case */ - if (shift == 4) - sample = 0; - else - { - /* apply volume change */ - uint8_t idx = sound.channel_three.index; - uint16_t s; - - /* extract current sample */ - if ((idx & 0x01) == 0) - s = (sound.wave_table[idx >> 1] & 0xf0) >> 4; - else - s = sound.wave_table[idx >> 1] & 0x0f; - - /* transform it into signed 16 bit sample */ - sample = ((s * 0x222) >> shift); - } - - if (sound.nr51->ch3_to_so1) - BLIP_RIGHT(sample, 2); - if (sound.nr51->ch3_to_so2) - BLIP_LEFT(sample, 2); - } -} -static void blip_ch4() -{ - if (sound.channel_four.active) - { - if (sound.nr51->ch4_to_so1) - BLIP_RIGHT(sound.channel_four.sample, 3); - if (sound.nr51->ch4_to_so2) - BLIP_LEFT(sound.channel_four.sample, 3); - } -} - -/* internal prototypes */ -void sound_envelope_step(); -void sound_length_ctrl_step(); -void sound_sweep_step(); -void sound_write_wave(uint16_t a, uint8_t v); - -void sound_init_pointers() -{ - /* point sound structures to their memory areas */ - sound.nr10 = (nr10_t *) mmu_addr(0xFF10); - sound.nr11 = (nr11_t *) mmu_addr(0xFF11); - sound.nr12 = (nr12_t *) mmu_addr(0xFF12); - sound.nr13 = (nr13_t *) mmu_addr(0xFF13); - sound.nr14 = (nr14_t *) mmu_addr(0xFF14); - - sound.nr21 = (nr21_t *) mmu_addr(0xFF16); - sound.nr22 = (nr22_t *) mmu_addr(0xFF17); - sound.nr23 = (nr23_t *) mmu_addr(0xFF18); - sound.nr24 = (nr24_t *) mmu_addr(0xFF19); - - sound.nr30 = (nr30_t *) mmu_addr(0xFF1A); - sound.nr31 = (nr31_t *) mmu_addr(0xFF1B); - sound.nr32 = (nr32_t *) mmu_addr(0xFF1C); - sound.nr33 = (nr33_t *) mmu_addr(0xFF1D); - sound.nr34 = (nr34_t *) mmu_addr(0xFF1E); - - sound.nr41 = (nr41_t *) mmu_addr(0xFF20); - sound.nr42 = (nr42_t *) mmu_addr(0xFF21); - sound.nr43 = (nr43_t *) mmu_addr(0xFF22); - sound.nr44 = (nr44_t *) mmu_addr(0xFF23); - - sound.nr50 = mmu_addr(0xFF24); - sound.nr51 = mmu_addr(0xFF25); - sound.nr52 = mmu_addr(0xFF26); - - sound.wave_table = mmu_addr(0xFF30); -} - -/* init sound states */ -void sound_init() -{ - /* reset structure */ - bzero(&sound, sizeof(sound_t)); - - /* point sound structures to their memory areas */ - sound_init_pointers(); - - /* how many cpu cycles we need to emit a 512hz clock (frame sequencer) */ - sound.fs_cycles = 4194304 / 512; - - /* how many cpu cycles to generate a single frame seq clock? */ - sound.fs_cycles_next = sound.fs_cycles; -} - -void sound_set_speed(char dbl) -{ -} - -/* update sound internal state given CPU T-states */ -void sound_step_fs() -{ - /* rotate from 0 to 7 */ - sound.fs_cycles_idx = (sound.fs_cycles_idx + 1) & 0x07; - - /* reset fs cycles counter */ - sound.fs_cycles_next = cycles.cnt + - (sound.fs_cycles << global_cpu_double_speed); - - /* length controller works at 256hz */ - if ((sound.fs_cycles_idx & 0x01) == 0) - sound_length_ctrl_step(); - - /* sweep works at 128hz */ - if (sound.fs_cycles_idx == 2 || sound.fs_cycles_idx == 6) - sound_sweep_step(); - - /* envelope works at 64hz */ - if (sound.fs_cycles_idx == 7) - sound_envelope_step(); - blip_ch1(); - blip_ch2(); - blip_ch3(); - blip_ch4(); -} - -/* update all channels */ -void sound_step_ch1() -{ - /* recalc current samples */ - if ((sound.channel_one.duty >> sound.channel_one.duty_idx) & 0x01) - sound.channel_one.sample = sound.channel_one.volume; - else - sound.channel_one.sample = -sound.channel_one.volume; - - /* step to the next duty value */ - sound.channel_one.duty_idx = - (sound.channel_one.duty_idx + 1) & 0x07; - - /* go back */ - sound.channel_one.duty_cycles_next += sound.channel_one.duty_cycles; - blip_ch1(); -} - -void sound_step_ch2() -{ - /* recalc current samples */ - if ((sound.channel_two.duty >> sound.channel_two.duty_idx) & 0x01) - sound.channel_two.sample = sound.channel_two.volume; - else - sound.channel_two.sample = -sound.channel_two.volume; - - /* step to the next duty value */ - sound.channel_two.duty_idx = - (sound.channel_two.duty_idx + 1) & 0x07; - - /* go back */ - sound.channel_two.duty_cycles_next += sound.channel_two.duty_cycles; - blip_ch2(); -} - -void sound_step_ch3() -{ - /* switch to the next wave sample */ - sound.channel_three.index = (sound.channel_three.index + 1) & 0x1F; - - /* set the new current sample */ - sound.channel_three.sample = - sound.channel_three.wave[sound.channel_three.index]; - - /* reload new period */ - uint_fast16_t freq = sound.nr33->frequency_lsb | - (sound.nr34->frequency_msb << 8); - - /* qty of cpu ticks needed for a wave sample change */ - sound.channel_three.cycles = ((2048 - freq) * 2) << global_cpu_double_speed; - sound.channel_three.cycles_next += sound.channel_three.cycles; - blip_ch3(); -} - -void sound_step_ch4() -{ - /* update LSFR */ - if (sound.nr43->shift < 14) - { - /* shift register one bit right */ - uint16_t s = sound.channel_four.reg >> 1; - - /* xor current register and the shifted version */ - /* and extract bit zero */ - uint16_t x = (sound.channel_four.reg ^ s) & 1; - - /* update register */ - sound.channel_four.reg = s | x << 14; - - /* if width is set... */ - if (sound.nr43->width) - sound.channel_four.reg = - (sound.channel_four.reg & 0xBF) | x << 6; - } - - /* update sample */ - if (sound.channel_four.reg & 0x01) - sound.channel_four.sample = -sound.channel_four.volume; - else - sound.channel_four.sample = sound.channel_four.volume; - - /* qty of cpu ticks needed for a wave sample change */ - sound.channel_four.cycles_next += sound.channel_four.period_lfsr; - blip_ch4(); -} - -/* update length of channel1 */ -void static inline sound_length_ctrl_step_ch(char length_enable, - uint_fast32_t *length, - uint8_t *active) -{ - if (length_enable && *length != 0) - { - (*length)--; - - /* if ZERO is reached, turn off the channel */ - if (*length == 0) - *active = 0; - } -} - -/* length controller step */ -void sound_length_ctrl_step() -{ - /* step every channel */ - sound_length_ctrl_step_ch(sound.nr14->length_enable, - &sound.channel_one.length, - &sound.channel_one.active); - - sound_length_ctrl_step_ch(sound.nr24->length_enable, - &sound.channel_two.length, - &sound.channel_two.active); - - sound_length_ctrl_step_ch(sound.nr34->length_enable, - &sound.channel_three.length, - &sound.channel_three.active); - - sound_length_ctrl_step_ch(sound.nr44->length_enable, - &sound.channel_four.length, - &sound.channel_four.active); -} - -/* calc the new frequency by sweep module */ -uint_fast32_t sound_sweep_calc() -{ - uint_fast32_t new_freq; - - /* time to update frequency */ - uint_fast32_t diff = - sound.channel_one.sweep_shadow_frequency >> - sound.nr10->shift; - - /* the calculated diff must be summed or subtracted to frequency */ - if (sound.nr10->negate) - { - new_freq = sound.channel_one.sweep_shadow_frequency - diff; - sound.channel_one.sweep_neg = 1; - } - else - new_freq = sound.channel_one.sweep_shadow_frequency + diff; - - /* if freq > 2047, turn off the channel */ - if (new_freq > 2047) - sound.channel_one.active = 0; - - return new_freq; -} - -/* set channel one new frequency */ -void sound_set_frequency(uint_fast32_t new_freq) -{ - /* too high? */ - if (new_freq > 2047) - { - sound.channel_one.active = 0; - return; - } - - /* update with the new frequency */ - sound.channel_one.frequency = new_freq; - - /* update them also into memory */ - sound.nr13->frequency_lsb = (uint8_t) (new_freq & 0x000000ff); - sound.nr14->frequency_msb = (uint8_t) ((new_freq >> 8) & 0x00000007); - - /* update the duty cycles */ - sound.channel_one.duty_cycles = - ((2048 - new_freq) * 4) << global_cpu_double_speed; - - /* and reset them */ - sound.channel_one.duty_cycles_next = - cycles.cnt + sound.channel_one.duty_cycles; -} - -/* step of frequency sweep at 128hz */ -void sound_sweep_step() -{ - uint_fast32_t new_freq; - - if (sound.channel_one.active && - sound.channel_one.sweep_active) - { - /* make it rotate from 0 to 8 */ - sound.channel_one.sweep_cnt++; - - /* enough cycles? */ - if (sound.channel_one.sweep_cnt == sound.channel_one.sweep_next) - { - /* reload the next step - 0 is treated as 8 */ - sound.channel_one.sweep_next = - sound.nr10->sweep_period ? - sound.nr10->sweep_period : 8; - - /* reset sweep counter */ - sound.channel_one.sweep_cnt = 0; - - /* period must be > 0 if new freq gotta be updated */ - if (sound.nr10->sweep_period == 0) - return; - - /* calc new frequency */ - new_freq = sound_sweep_calc(); - - /* set it only if < 2048 and shift != 0 */ - if (sound.nr10->shift && - new_freq < 2048) - { - /* copy new_freq into shadow register */ - sound.channel_one.sweep_shadow_frequency = new_freq; - - /* update all the stuff related to new frequency */ - sound_set_frequency(new_freq); - - /* update freq again (but only in shadow register) */ - sound_sweep_calc(); - } - } - } -} - -/* step of envelope at 64hz */ -void sound_envelope_step() -{ - if (sound.channel_one.active && sound.nr12->period) - { - /* update counter */ - sound.channel_one.envelope_cnt++; - - /* if counter reaches period, update volume */ - if (sound.channel_one.envelope_cnt == sound.nr12->period) - { - if (sound.nr12->add) - { - if (sound.channel_one.volume < (14 * 0x111)) - sound.channel_one.volume += 0x111; - } - else - { - if (sound.channel_one.volume >= 0x111) - sound.channel_one.volume -= 0x111; - } - - /* reset counter */ - sound.channel_one.envelope_cnt = 0; - } - } - - if (sound.channel_two.active && sound.nr22->period) - { - /* update counter */ - sound.channel_two.envelope_cnt++; - - /* if counter reaches period, update volume */ - if (sound.channel_two.envelope_cnt == sound.nr22->period) - { - if (sound.nr22->add) - { - if (sound.channel_two.volume < (14 * 0x111)) - sound.channel_two.volume += 0x111; - } - else - { - if (sound.channel_two.volume >= 0x111) - sound.channel_two.volume -= 0x111; - } - - /* reset counter */ - sound.channel_two.envelope_cnt = 0; - } - } - - if (sound.channel_four.active && sound.nr42->period) - { - /* update counter */ - sound.channel_four.envelope_cnt++; - - /* if counter reaches period, update volume */ - if (sound.channel_four.envelope_cnt == sound.nr42->period) - { - if (sound.nr42->add) - { - if (sound.channel_four.volume < (14 * 0x111)) - sound.channel_four.volume += 0x111; - } - else - { - if (sound.channel_four.volume > 0x111) - sound.channel_four.volume -= 0x111; - } - - /* reset counter */ - sound.channel_four.envelope_cnt = 0; - } - } -} - -uint8_t sound_read_reg(uint16_t a, uint8_t v) -{ - switch (a) - { - /* NR1X */ - case 0xFF10: return v | 0x80; - case 0xFF11: return v | 0x3F; - case 0xFF12: return v; - case 0xFF13: return v | 0xFF; - case 0xFF14: return v | 0xBF; - /* NR2X */ - case 0xFF15: return v | 0xFF; - case 0xFF16: return v | 0x3F; - case 0xFF17: return v; - case 0xFF18: return v | 0xFF; - case 0xFF19: return v | 0xBF; - /* NR3X */ - case 0xFF1A: return v | 0x7F; - case 0xFF1B: return v | 0xFF; - case 0xFF1C: return v | 0x9F; - case 0xFF1D: return v | 0xFF; - case 0xFF1E: return v | 0xBF; - /* NR4X */ - case 0xFF1F: return v | 0xFF; - case 0xFF20: return v | 0xFF; - case 0xFF21: return v; - case 0xFF22: return v; - case 0xFF23: return v | 0xBF; - /* NR5X */ - case 0xFF24: return v; - case 0xFF25: return v; - case 0xFF26: - if (sound.nr52->power) - return 0xf0 | - sound.channel_one.active | - (sound.channel_two.active << 1) | - (sound.channel_three.active << 2) | - (sound.channel_four.active << 3); - else - return 0x70; - case 0xFF27: - case 0xFF28: - case 0xFF29: - case 0xFF2A: - case 0xFF2B: - case 0xFF2C: - case 0xFF2D: - case 0xFF2E: - case 0xFF2F: return 0xFF; - case 0xFF30: - case 0xFF31: - case 0xFF32: - case 0xFF33: - case 0xFF34: - case 0xFF35: - case 0xFF36: - case 0xFF37: - case 0xFF38: - case 0xFF39: - case 0xFF3A: - case 0xFF3B: - case 0xFF3C: - case 0xFF3D: - case 0xFF3E: - case 0xFF3F: - if (sound.channel_three.active) - { -/* if (!global_cgb && sound.channel_three.ram_access != 0) - { - printf("RAM ACCESSO NON ZERO %u - CNT %d NEXT %d\n", - sound.channel_three.ram_access, cycles.cnt, sound.channel_three.ram_access_next); - return 0xFF; - }*/ - if (!global_cgb && - cycles.cnt < sound.channel_three.ram_access_next) - return 0xFF; - - return sound.wave_table[sound.channel_three.index >> 1]; - } - - default: return v; - } -} - -void sound_write_reg(uint16_t a, uint8_t v) -{ - /* when turned off, only write to NR52 (0xFF26) is legit */ - if (!sound.nr52->power && a != 0xFF26) - { - /* CGB mode doesnt allow any write on register during power off */ - if (global_cgb) - return; - - /* in DMG mode, update length is legit while no power */ - switch (a) - { - case 0xFF11: sound.channel_one.length = 64 - (v & 0x3f); return; - case 0xFF16: sound.channel_two.length = 64 - (v & 0x3f); return; - case 0xFF1B: sound.channel_three.length = 256 - v; return; - case 0xFF20: sound.channel_four.length = 64 - (v & 0x3f); return; - default: return; - } - } - - /* wave write */ - if (a >= 0xFF30 && a <= 0xFF3F) - return sound_write_wave(a, v); - - /* save old value */ - uint8_t old = *((uint8_t *) mmu_addr(a)); - - /* confirm write on memory */ - *((uint8_t *) mmu_addr(a)) = v; - - switch (a) - { - case 0xFF10: - - if (!sound.nr10->negate && sound.channel_one.sweep_neg) - sound.channel_one.active = 0; - - break; - - case 0xFF11: - - /* set length as 64 - length_load */ - sound.channel_one.length = 64 - sound.nr11->length_load; - - /* update duty type */ - switch (sound.nr11->duty) - { - /* 12.5 % */ - case 0x00: sound.channel_one.duty = 0x80; - break; - - /* 25% */ - case 0x01: sound.channel_one.duty = 0x81; - break; - - /* 50% */ - case 0x02: sound.channel_one.duty = 0xE1; - break; - - /* 75% */ - case 0x03: sound.channel_one.duty = 0x7E; - break; - } - - break; - - case 0xFF12: - - /* volume 0 = turn off the DAC = turn off channeru */ - if (sound.nr12->volume == 0 && - sound.nr12->add == 0) - sound.channel_one.active = 0; - - break; - - case 0xFF13: - - /* update frequncy */ - sound.channel_one.frequency = sound.nr13->frequency_lsb | - (sound.nr14->frequency_msb << 8); - - /* update duty cycles */ - sound.channel_one.duty_cycles = - ((2048 - sound.channel_one.frequency) * 4) - << global_cpu_double_speed; - - break; - - case 0xFF14: - - /* length counter turned on */ - if (sound.nr14->length_enable) - { - nr14_t *old_nr14 = (nr14_t *) &old; - - /* give an extra length clock if */ - /* 1) we switched from off to on the len counter */ - /* 2) we are in the first half of len clock */ - /* 3) actual length is not zero */ - if ((old_nr14->length_enable == 0) && - ((sound.fs_cycles_idx & 0x01) == 0x00) && - (sound.channel_one.length != 0)) - sound_length_ctrl_step_ch(sound.nr14->length_enable, - &sound.channel_one.length, - &sound.channel_one.active); - } - - /* always update frequency, even if it's not a trigger */ - sound.channel_one.frequency = sound.nr13->frequency_lsb | - (sound.nr14->frequency_msb << 8); - - /* qty of cpu ticks needed for a duty change */ - /* (1/8 of wave cycle) */ - sound.channel_one.duty_cycles = - ((2048 - sound.channel_one.frequency) * 4) - << global_cpu_double_speed; - - if (v & 0x80) - { - /* if we switch from OFF to ON, reset duty idx */ - if (sound.channel_two.active == 0) - sound.channel_two.duty_idx = 0; - - /* setting internal modules data with stuff taken from memory */ - sound.channel_one.active = 1; - sound.channel_one.duty_cycles_next = - cycles.cnt + sound.channel_one.duty_cycles; - - /* set the 8 phase of a duty cycle by setting 8 bits */ - switch (sound.nr11->duty) - { - /* 12.5 % */ - case 0x00: sound.channel_one.duty = 0x80; - break; - - /* 25% */ - case 0x01: sound.channel_one.duty = 0x81; - break; - - /* 50% */ - case 0x02: sound.channel_one.duty = 0xE1; - break; - - /* 75% */ - case 0x03: sound.channel_one.duty = 0x7E; - break; - } - - /* calc length */ - if (sound.channel_one.length == 0) - sound.channel_one.length = 64; - - /* base volume */ - sound.channel_one.volume = - sound.nr12->volume * 0x111; - - /* reset envelope counter */ - sound.channel_one.envelope_cnt = 0; - - /* save current freq into sweep shadow register */ - sound.channel_one.sweep_shadow_frequency = - sound.channel_one.frequency; - - /* reset sweep timer */ - sound.channel_one.sweep_cnt = 0; - - /* reset sweep neg bool */ - sound.channel_one.sweep_neg = 0; - - /* reload the next step */ - sound.channel_one.sweep_next = sound.nr10->sweep_period ? - sound.nr10->sweep_period : 8; - - /* set sweep as active if period != 0 or shift != 0 */ - if (sound.nr10->sweep_period != 0 || - sound.nr10->shift != 0) - sound.channel_one.sweep_active = 1; - else - sound.channel_one.sweep_active = 0; - - /* if shift is != 0, calc the new frequency */ - if (sound.nr10->shift != 0) - { - uint32_t new_freq = sound_sweep_calc(); - - /* update all the stuff related to new frequency */ - sound_set_frequency(new_freq); - } - - /* if DAC is off, turn off the channel */ - if (sound.nr12->add == 0 && - sound.nr12->volume == 0) - sound.channel_one.active = 0; - - /* extra length clock if length == 64 */ - /* and FS is in the fist half */ - if ((sound.fs_cycles_idx & 0x01) == 0x00 && - sound.channel_one.length == 64) - sound_length_ctrl_step_ch(sound.nr14->length_enable, - &sound.channel_one.length, - &sound.channel_one.active); - } - - - break; - - case 0xFF16: - - sound.channel_two.length = 64 - sound.nr21->length_load; - - /* update duty type */ - switch (sound.nr21->duty) - { - /* 12.5 % */ - case 0x00: sound.channel_two.duty = 0x80; - break; - - /* 25% */ - case 0x01: sound.channel_two.duty = 0x81; - break; - - /* 50% */ - case 0x02: sound.channel_two.duty = 0xE1; - break; - - /* 75% */ - case 0x03: sound.channel_two.duty = 0x7E; - break; - } - - break; - - case 0xFF17: - - /* volume 0 = turn off the DAC = turn off channeru */ - if (sound.nr22->volume == 0 && - sound.nr22->add == 0) - sound.channel_two.active = 0; - - break; - - case 0xFF18: - - /* update frequncy */ - sound.channel_two.frequency = (sound.nr23->frequency_lsb | - (sound.nr24->frequency_msb << 8)); - - /* update duty cycles */ - sound.channel_two.duty_cycles = - ((2048 - sound.channel_two.frequency) * 4) - << global_cpu_double_speed; - - break; - - case 0xFF19: - - /* length counter turned on */ - if (sound.nr24->length_enable) - { - nr24_t *old_nr24 = (nr24_t *) &old; - - /* give an extra length clock if */ - /* 1) we switched from off to on the len counter */ - /* 2) we are in the first half of len clock */ - /* 3) actual length is not zero */ - if ((old_nr24->length_enable == 0) && - ((sound.fs_cycles_idx & 0x01) == 0x00) && - (sound.channel_two.length != 0)) - sound_length_ctrl_step_ch(sound.nr24->length_enable, - &sound.channel_two.length, - &sound.channel_two.active); - } - - /* always update frequency, even if it's not a trigger */ - sound.channel_two.frequency = sound.nr23->frequency_lsb | - (sound.nr24->frequency_msb << 8); - - /* qty of cpu ticks needed for a duty change */ - /* (1/8 of wave cycle) */ - sound.channel_two.duty_cycles = - ((2048 - sound.channel_two.frequency) * 4) - << global_cpu_double_speed; - - if (v & 0x80) - { - /* if we switch from OFF to ON, reset duty idx */ - if (sound.channel_two.active == 0) - sound.channel_two.duty_idx = 0; - - /* setting internal modules data with stuff taken from memory */ - sound.channel_two.active = 1; - sound.channel_two.duty_cycles_next = - cycles.cnt + sound.channel_two.duty_cycles; - - /* set the 8 phase of a duty cycle by setting 8 bits */ - switch (sound.nr21->duty) - { - /* 12.5 % */ - case 0x00: sound.channel_two.duty = 0x80; - break; - - /* 25% */ - case 0x01: sound.channel_two.duty = 0x81; - break; - - /* 50% */ - case 0x02: sound.channel_two.duty = 0xE1; - break; - - /* 75% */ - case 0x03: sound.channel_two.duty = 0x7E; - break; - } - - /* calc length */ - if (sound.channel_two.length == 0) - sound.channel_two.length = 64; - - /* base volume */ - sound.channel_two.volume = - sound.nr22->volume * 0x111; - - /* reset envelope counter */ - sound.channel_two.envelope_cnt = 0; - - /* if DAC is off, turn off the channel */ - if (sound.nr22->add == 0 && - sound.nr22->volume == 0) - sound.channel_two.active = 0; - - /* extra length clock if length == 64 */ - /* and FS is in the fist half */ - if ((sound.fs_cycles_idx & 0x01) == 0x00 && - sound.channel_two.length == 64) - sound_length_ctrl_step_ch(sound.nr24->length_enable, - &sound.channel_two.length, - &sound.channel_two.active); - } - - break; - - case 0xFF1A: - - /* if DAC is off, disable the channel */ - if (sound.nr30->dac == 0) - sound.channel_three.active = 0; - - break; - - case 0xFF1B: - - sound.channel_three.length = - 256 - sound.nr31->length_load; - - break; - - case 0xFF1C: - - break; - - case 0xFF1E: - - /* length counter turned on */ - if (sound.nr34->length_enable) - { - nr34_t *old_nr34 = (nr34_t *) &old; - - /* give an extra length clock if */ - /* 1) we switched from off to on the len counter */ - /* 2) we are in the first half of len clock */ - /* 3) actual length is not zero */ - if ((old_nr34->length_enable == 0) && - ((sound.fs_cycles_idx & 0x01) == 0x00) && - (sound.channel_three.length != 0)) - sound_length_ctrl_step_ch(sound.nr34->length_enable, - &sound.channel_three.length, - &sound.channel_three.active); - } - - if (v & 0x80) - { - uint16_t freq = sound.nr33->frequency_lsb | - (sound.nr34->frequency_msb << 8); - - /* setting internal modules data with stuff taken from memory */ - sound.channel_three.active = 1; - - uint_fast32_t old_cycles = sound.channel_three.cycles; - - /* qty of cpu ticks needed for a wave sample change */ - sound.channel_three.cycles = - (((2048 - freq) * 2) + 6) << global_cpu_double_speed; - - - /* treat obscure behaviours.... */ - if (!global_cgb && - cycles.cnt + 8 == sound.channel_three.cycles_next + - sound.channel_three.cycles - - old_cycles) - { - uint8_t next = - ((sound.channel_three.index + 1) & 0x1F) >> 1; - - if (next < 4) - sound.wave_table[0] = sound.wave_table[next]; - else - memcpy(sound.wave_table, - &sound.wave_table[next & 0xfc], 4); - } - - /* init wave table index */ - sound.channel_three.index = 0; - sound.channel_three.cycles_next = - cycles.cnt + sound.channel_three.cycles; - - /* calc length */ - if (sound.channel_three.length == 0) - sound.channel_three.length = 256; - - /* if DAC is off, disable the channel */ - if (sound.nr30->dac == 0) - sound.channel_three.active = 0; - - /* extra length clock if length == 256 */ - /* and FS is in the fist half */ - if ((sound.fs_cycles_idx & 0x01) == 0x00 && - sound.channel_three.length == 256) - sound_length_ctrl_step_ch(sound.nr34->length_enable, - &sound.channel_three.length, - &sound.channel_three.active); - - /* i accessed to the wave RAM... */ - sound.channel_three.ram_access = sound.channel_three.cycles; - - if (sound.channel_three.cycles % 4 == 0) - sound.channel_three.ram_access_next = - cycles.cnt + sound.channel_three.cycles; - else - sound.channel_three.ram_access_next = -1; - -/* printf("RAM ACCESS RICARICATO %u - CNT %d CYCLES %d \n", - sound.channel_three.ram_access, - cycles.cnt, sound.channel_three.cycles);*/ - } - break; - - case 0xFF20: - - sound.channel_four.length = 64 - sound.nr41->length_load; - - break; - - case 0xFF21: - - /* highest 5 bits cleared = turn off the DAC = turn off channeru */ - if (sound.nr42->volume == 0 && - sound.nr42->add == 0) - sound.channel_four.active = 0; - - break; - - case 0xFF23: - - /* length counter turned on */ - if (sound.nr44->length_enable) - { - nr44_t *old_nr44 = (nr44_t *) &old; - - /* give an extra length clock if */ - /* 1) we switched from off to on the len counter */ - /* 2) we are in the first half of len clock */ - /* 3) actual length is not zero */ - if ((old_nr44->length_enable == 0) && - ((sound.fs_cycles_idx & 0x01) == 0x00) && - (sound.channel_four.length != 0)) - sound_length_ctrl_step_ch(sound.nr44->length_enable, - &sound.channel_four.length, - &sound.channel_four.active); - } - - if (v & 0x80) - { - /* setting internal modules data with stuff taken from memory */ - sound.channel_four.active = 1; - - /* calc length */ - if (sound.channel_four.length == 0) - sound.channel_four.length = 64; - - uint16_t divisor; - - /* calc LFSR period */ - switch (sound.nr43->divisor) - { - case 0: divisor = 8; break; - case 1: divisor = 16; break; - case 2: divisor = 32; break; - case 3: divisor = 48; break; - case 4: divisor = 64; break; - case 5: divisor = 80; break; - case 6: divisor = 96; break; - case 7: divisor = 112; break; - } - - /* calc LFSR period */ - sound.channel_four.period_lfsr = divisor << sound.nr43->shift; - sound.channel_four.cycles_next = - cycles.cnt + sound.channel_four.period_lfsr; - - /* init reg to all bits to 1 */ - sound.channel_four.reg = 0x7FFF; - - /* base volume */ - sound.channel_four.volume = - sound.nr42->volume * 0x111; - - /* reset envelope counter */ - sound.channel_four.envelope_cnt = 0; - - /* if DAC is off, turn off the channel */ - if (sound.nr42->add == 0 && - sound.nr42->volume == 0) - sound.channel_four.active = 0; - - /* extra length clock if length == 64 */ - /* and FS is in the fist half */ - if ((sound.fs_cycles_idx & 0x01) == 0x00 && - sound.channel_four.length == 64) - sound_length_ctrl_step_ch(sound.nr44->length_enable, - &sound.channel_four.length, - &sound.channel_four.active); - } - - break; - - case 0xFF26: - - if (v & 0x80) - { - /* power from off to on! */ - if (!(old & 0x80)) - { - /* reset frame sequencer so the next step will be zero */ - sound.fs_cycles_idx = 7; - - /* reset wave index */ - sound.channel_three.index = 0; - - /* wave samples are resetted */ - bzero(sound.wave_table, 16); - } - } - else - { - /* power off */ - - /* clear all the sound memory */ - bzero(mmu_addr(0xFF10), 22); - - if (global_cgb) - { - sound.nr41->length_load = 0; - sound.channel_four.length = 0; - } - - /* turn off every channeru */ - sound.channel_one.active = 0; - sound.channel_two.active = 0; - sound.channel_three.active = 0; - sound.channel_four.active = 0; - } - - } -} - -void sound_write_wave(uint16_t a, uint8_t v) -{ - if (sound.channel_three.active) - { -// if (!global_cgb && sound.channel_three.ram_access != 0) -// return; - if (!global_cgb && cycles.cnt < sound.channel_three.ram_access_next) - return; - - sound.wave_table[sound.channel_three.index >> 1] = v; - - return; - } - - sound.wave_table[a - 0xFF30] = v; -} diff --git a/waterbox/pizza/lib/sound.h b/waterbox/pizza/lib/sound.h deleted file mode 100644 index 226b8650bd..0000000000 --- a/waterbox/pizza/lib/sound.h +++ /dev/null @@ -1,300 +0,0 @@ -/* - - This file is part of Emu-Pizza - - Emu-Pizza is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Emu-Pizza is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Emu-Pizza. If not, see . - -*/ - -#ifndef __SOUND_HDR__ -#define __SOUND_HDR__ - -#define SOUND_SAMPLES 4096 - -typedef struct nr10_s -{ - uint8_t shift:3; - uint8_t negate:1; - uint8_t sweep_period:3; - uint8_t spare:1; - -} nr10_t; - -typedef struct nr11_s -{ - uint8_t length_load:6; - uint8_t duty:2; - -} nr11_t; - -typedef struct nr12_s -{ - uint8_t period:3; - uint8_t add:1; - uint8_t volume:4; - -} nr12_t; - -typedef struct nr13_s -{ - uint8_t frequency_lsb; - -} nr13_t; - -typedef struct nr14_s -{ - uint8_t frequency_msb:3; - uint8_t spare:3; - uint8_t length_enable:1; - uint8_t trigger:1; - -} nr14_t; - -typedef struct nr21_s -{ - uint8_t length_load:6; - uint8_t duty:2; - -} nr21_t; - -typedef struct nr22_s -{ - uint8_t period:3; - uint8_t add:1; - uint8_t volume:4; - -} nr22_t; - -typedef struct nr23_s -{ - uint8_t frequency_lsb; - -} nr23_t; - -typedef struct nr24_s -{ - uint8_t frequency_msb:3; - uint8_t spare:3; - uint8_t length_enable:1; - uint8_t trigger:1; - -} nr24_t; - - -typedef struct nr30_s -{ - uint8_t spare:7; - uint8_t dac:1; - -} nr30_t; - -typedef struct nr31_s -{ - uint8_t length_load; - -} nr31_t; - -typedef struct nr32_s -{ - uint8_t spare:5; - uint8_t volume_code:2; - uint8_t spare2:1; - -} nr32_t; - -typedef struct nr33_s -{ - uint8_t frequency_lsb; - -} nr33_t; - -typedef struct nr34_s -{ - uint8_t frequency_msb:3; - uint8_t spare:3; - uint8_t length_enable:1; - uint8_t trigger:1; - -} nr34_t; - -typedef struct nr41_s -{ - uint8_t length_load:6; - uint8_t spare:2; - -} nr41_t; - -typedef struct nr42_s -{ - uint8_t period:3; - uint8_t add:1; - uint8_t volume:4; - -} nr42_t; - -typedef struct nr43_s -{ - uint8_t divisor:3; - uint8_t width:1; - uint8_t shift:4; - -} nr43_t; - -typedef struct nr44_s -{ - uint8_t spare:6; - uint8_t length_enable:1; - uint8_t trigger:1; - -} nr44_t; - -typedef struct nr50_s -{ - uint8_t so1_volume:3; - uint8_t vin_to_so1:1; - uint8_t so2_volume:3; - uint8_t vin_to_so2:1; -} nr50_t; - -typedef struct nr51_s -{ - uint8_t ch1_to_so1:1; - uint8_t ch2_to_so1:1; - uint8_t ch3_to_so1:1; - uint8_t ch4_to_so1:1; - uint8_t ch1_to_so2:1; - uint8_t ch2_to_so2:1; - uint8_t ch3_to_so2:1; - uint8_t ch4_to_so2:1; -} nr51_t; - -typedef struct nr52_s -{ - uint8_t spare:7; - uint8_t power:1; -} nr52_t; - -typedef struct channel_square_s -{ - uint8_t active; - uint8_t duty; - uint8_t duty_idx; - uint8_t envelope_cnt; - uint_fast16_t duty_cycles; - uint64_t duty_cycles_next; - uint_fast32_t length; - uint_fast32_t frequency; - int16_t sample; - int16_t spare; - uint_fast16_t sweep_active; - uint_fast16_t sweep_cnt; - uint_fast16_t sweep_neg; - uint_fast16_t sweep_next; - int16_t volume; - int16_t spare2; - uint32_t sweep_shadow_frequency; - -} channel_square_t; - -typedef struct channel_wave_s -{ - uint8_t active; - uint8_t index; - uint16_t ram_access; - int16_t sample; - int16_t spare; - int16_t wave[32]; - uint_fast32_t cycles; - uint64_t cycles_next; - uint_fast32_t ram_access_next; - uint_fast32_t length; - -} channel_wave_t; - -typedef struct channel_noise_s -{ - uint8_t active; - uint8_t envelope_cnt; - uint16_t spare; - uint_fast32_t length; - uint_fast16_t period_lfsr; - uint64_t cycles_next; - int16_t volume; - int16_t sample; - uint16_t reg; - uint16_t spare2; - -} channel_noise_t; - -typedef struct sound_s -{ - nr10_t *nr10; - nr11_t *nr11; - nr12_t *nr12; - nr13_t *nr13; - nr14_t *nr14; - - nr21_t *nr21; - nr22_t *nr22; - nr23_t *nr23; - nr24_t *nr24; - - nr30_t *nr30; - nr31_t *nr31; - nr32_t *nr32; - nr33_t *nr33; - nr34_t *nr34; - - nr41_t *nr41; - nr42_t *nr42; - nr43_t *nr43; - nr44_t *nr44; - - nr50_t *nr50; - nr51_t *nr51; - nr52_t *nr52; - - uint8_t *wave_table; - - channel_square_t channel_one; - channel_square_t channel_two; - channel_wave_t channel_three; - channel_noise_t channel_four; - - /* emulation speed stuff */ - uint_fast16_t frame_counter; - - /* output rate */ - uint_fast32_t output_rate; - - /* CPU cycles to internal cycles counters */ - uint_fast32_t fs_cycles; - uint_fast32_t fs_cycles_idx; - uint64_t fs_cycles_next; -} sound_t; - -extern sound_t sound; - -/* prototypes */ -void sound_init(); -uint8_t sound_read_reg(uint16_t a, uint8_t v); -void sound_set_speed(char dbl); -void sound_step_fs(); -void sound_step_ch1(); -void sound_step_ch2(); -void sound_step_ch3(); -void sound_step_ch4(); -void sound_write_reg(uint16_t a, uint8_t v); - -#endif diff --git a/waterbox/pizza/lib/sound_output.c b/waterbox/pizza/lib/sound_output.c deleted file mode 100644 index cf9d32c949..0000000000 --- a/waterbox/pizza/lib/sound_output.c +++ /dev/null @@ -1,57 +0,0 @@ -#include "../blip_buf/blip_buf.h" -#include "sound_output.h" -#include "cycles.h" -#include "sgb.h" -#include "global.h" - -static blip_t* lb; -static blip_t* rb; -static uint64_t startclock; - -#define RELATIVECLOCK (cycles.sampleclock - startclock) - -void blip_left(int delta) -{ - if (delta) - blip_add_delta(lb, RELATIVECLOCK, delta); -} -void blip_right(int delta) -{ - if (delta) - blip_add_delta(rb, RELATIVECLOCK, delta); -} - -void sound_output_init(double clock_rate, double sample_rate) -{ - lb = blip_new(1024); - rb = blip_new(1024); - blip_set_rates(lb, clock_rate, sample_rate); - blip_set_rates(rb, clock_rate, sample_rate); -} - -static int32_t sgb_last_l; -static int32_t sgb_last_r; - -static void sgb_audio_callback(int16_t l, int16_t r, uint64_t time) -{ - uint64_t t = time - startclock; - int32_t ld = l - sgb_last_l; - int32_t rd = r - sgb_last_r; - blip_add_delta(lb, t, ld); - blip_add_delta(rb, t, rd); - sgb_last_l = l; - sgb_last_r = r; -} - -int sound_output_read(int16_t* output) -{ - if (global_sgb) - sgb_render_audio(cycles.sampleclock, sgb_audio_callback); - - blip_end_frame(lb, RELATIVECLOCK); - blip_end_frame(rb, RELATIVECLOCK); - startclock = cycles.sampleclock; - int ret = blip_read_samples(lb, output, 2048, 1); - blip_read_samples(rb, output + 1, 2048, 1); - return ret; -} diff --git a/waterbox/pizza/lib/sound_output.h b/waterbox/pizza/lib/sound_output.h deleted file mode 100644 index 91561da49a..0000000000 --- a/waterbox/pizza/lib/sound_output.h +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once - -#include - -void blip_left(int delta); -void blip_right(int delta); - -void sound_output_init(double clock_rate, double sample_rate); -int sound_output_read(int16_t* output); diff --git a/waterbox/pizza/lib/timer.c b/waterbox/pizza/lib/timer.c deleted file mode 100644 index a46c224bda..0000000000 --- a/waterbox/pizza/lib/timer.c +++ /dev/null @@ -1,79 +0,0 @@ -/* - - This file is part of Emu-Pizza - - Emu-Pizza is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Emu-Pizza is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Emu-Pizza. If not, see . - -*/ - -#include "cycles.h" -#include "interrupt.h" -#include "mmu.h" -#include "timer.h" - -/* pointer to interrupt flags (handy) */ -interrupts_flags_t *timer_if; - - -void timer_init() -{ - /* reset values */ - timer.next = 256; - timer.sub = 0; - - /* pointer to interrupt flags */ - timer_if = mmu_addr(0xFF0F); -} - -void timer_write_reg(uint16_t a, uint8_t v) -{ - switch (a) - { - case 0xFF04: timer.div = 0; return; - case 0xFF05: timer.cnt = v; return; - case 0xFF06: timer.mod = v; return; - case 0xFF07: timer.ctrl = v; - } - - if (timer.ctrl & 0x04) - timer.active = 1; - else - timer.active = 0; - - switch (timer.ctrl & 0x03) - { - case 0x00: timer.threshold = 1024; break; - case 0x01: timer.threshold = 16; break; - case 0x02: timer.threshold = 64; break; - case 0x03: timer.threshold = 256; break; - } - - if (timer.active) - timer.sub_next = cycles.cnt + timer.threshold; -} - -uint8_t timer_read_reg(uint16_t a) -{ - switch (a) - { - case 0xFF04: return timer.div; - case 0xFF05: return timer.cnt; - case 0xFF06: return timer.mod; - case 0xFF07: return timer.ctrl; - } - - return 0xFF; -} - - diff --git a/waterbox/pizza/lib/timer.h b/waterbox/pizza/lib/timer.h deleted file mode 100644 index 531116121b..0000000000 --- a/waterbox/pizza/lib/timer.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - - This file is part of Emu-Pizza - - Emu-Pizza is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Emu-Pizza is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Emu-Pizza. If not, see . - -*/ - -#ifndef __TIMER_HDR__ -#define __TIMER_HDR__ - -#include - -/* timer status */ -typedef struct timer_gb_s -{ - /* is it active? */ - uint8_t active; - - /* divider - 0xFF04 */ - uint8_t div; - - /* modulo - 0xFF06 */ - uint8_t mod; - - /* control - 0xFF07 */ - uint8_t ctrl; - - /* counter - 0xFF05 */ - uint_fast32_t cnt; - - /* threshold */ - uint32_t threshold; - - /* current value */ - uint_fast32_t sub; - uint64_t next; - - /* spare */ - uint_fast32_t sub_next; -} timer_gb_t; - -/* global status of timer */ -timer_gb_t timer; - -/* prototypes */ -void timer_init(); -void timer_step(); -void timer_write_reg(uint16_t a, uint8_t v); -uint8_t timer_read_reg(uint16_t a); - -#endif diff --git a/waterbox/pizza/lib/utils.c b/waterbox/pizza/lib/utils.c deleted file mode 100644 index e413d644cc..0000000000 --- a/waterbox/pizza/lib/utils.c +++ /dev/null @@ -1,75 +0,0 @@ -/* - - This file is part of Emu-Pizza - - Emu-Pizza is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Emu-Pizza is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Emu-Pizza. If not, see . - -*/ - -#include -#include - -#include -#include - -#include "cycles.h" -#include "gpu.h" -#include "utils.h" - -uint64_t prev_cycles = 0; - -void utils_log(const char *format, ...) -{ - char buf[256]; - - va_list args; - va_start(args, format); - vsnprintf(buf, 256, format, args); - fputs(buf, stdout); - va_end(args); -} - - -void utils_log_urgent(const char *format, ...) -{ - char buf[256]; - - va_list args; - va_start(args, format); - vsnprintf(buf, 256, format, args); - fputs(buf, stdout); - va_end(args); -} - -void utils_ts_log(const char *format, ...) -{ - va_list args; - va_start(args, format); - - char buf[256]; - char buf2[512]; - struct timeval tv; - - - vsprintf(buf, format, args); - //gettimeofday(&tv, NULL); -// printf("%ld - %s\n", tv.tv_sec, buf); - sprintf(buf2, "LINE %u - CYCLES %lu - DIFF %lu - %ld:%06ld - %s", - *(gpu.ly), cycles.cnt, cycles.cnt - prev_cycles, - tv.tv_sec, tv.tv_usec, buf); - _debug_puts(buf2); - prev_cycles = cycles.cnt; - - va_end(args); -} diff --git a/waterbox/pizza/lib/utils.h b/waterbox/pizza/lib/utils.h deleted file mode 100644 index 17e632de51..0000000000 --- a/waterbox/pizza/lib/utils.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - - This file is part of Emu-Pizza - - Emu-Pizza is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Emu-Pizza is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Emu-Pizza. If not, see . - -*/ - -#ifndef __UTILS_HDR__ -#define __UTILS_HDR__ - -void utils_log(const char *format, ...); -void utils_log_urgent(const char *format, ...); -void utils_ts_log(const char *format, ...); - -#endif diff --git a/waterbox/pizza/lib/z80_gameboy.h b/waterbox/pizza/lib/z80_gameboy.h deleted file mode 100644 index db8c78c66d..0000000000 --- a/waterbox/pizza/lib/z80_gameboy.h +++ /dev/null @@ -1,2480 +0,0 @@ -/* - - This file is part of Emu-Pizza - - Emu-Pizza is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Emu-Pizza is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Emu-Pizza. If not, see . - -*/ - -#include -#include -#include -#include -#include -#include "mmu.h" -#include "z80_gameboy_regs.h" - -/* main struct describing CPU state */ - -typedef struct z80_state_s -{ - uint8_t spare; - uint8_t a; -#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ - uint8_t c; - uint8_t b; -#else - uint8_t b; - uint8_t c; -#endif -#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ - uint8_t e; - uint8_t d; -#else - uint8_t d; - uint8_t e; -#endif -#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ - uint8_t l; - uint8_t h; -#else - uint8_t h; - uint8_t l; -#endif - - uint16_t sp; - uint16_t pc; - - /* shortcuts */ - uint16_t *bc; - uint16_t *de; - uint16_t *hl; - uint8_t *f; - - uint32_t spare4; - uint32_t skip_cycle; - - z80_flags_t flags; - uint8_t int_enable; - - /* latest T-state */ - uint16_t spare3; - - /* total cycles */ - uint64_t cycles; - -} z80_state_t; - -#define Z80_MAX_MEMORY 65536 - - -/* state of the Z80 CPU */ -z80_state_t state; - -/* precomputed flags masks */ -uint8_t zc[1 << 9]; -uint8_t z[1 << 9]; - -/* macro to access addresses passed as parameters */ -#define ADDR mmu_read_16(state.pc + 1) -#define NN mmu_read_16(state.pc + 2) - -/* dummy value for 0x06 regs resulution table */ -uint8_t dummy; - -/* Registers table */ -uint8_t **regs_dst; -uint8_t **regs_src; - -#define FLAG_MASK_Z (1 << FLAG_OFFSET_Z) -#define FLAG_MASK_AC (1 << FLAG_OFFSET_AC) -#define FLAG_MASK_N (1 << FLAG_OFFSET_N) -#define FLAG_MASK_CY (1 << FLAG_OFFSET_CY) - - -/********************************/ -/* */ -/* FLAGS OPS */ -/* */ -/********************************/ - -/* calc flags SZ with 16 bit param */ -void static inline z80_set_flags_z(unsigned int v) -{ - state.flags.z = (v & 0xff) == 0; -} - -/* calc flags SZC with 16 bit param */ -void static inline z80_set_flags_zc(unsigned int v) -{ - state.flags.z = (v & 0xff) == 0; - state.flags.cy = (v > 0xff); -} - -/* calc flags SZC with 32 bit result */ -void static inline z80_set_flags_zc_16(unsigned int v) -{ - state.flags.z = (v & 0xffff) == 0; - state.flags.cy = (v > 0xffff); -} - -/* calc AC for given operands */ -void static inline z80_set_flags_ac(uint8_t a, uint8_t b, - unsigned int r) -{ - /* calc xor for AC and overflow */ - unsigned int c = (a ^ b ^ r); - - /* set AC */ - state.flags.ac = ((c & 0x10) != 0); - - return; -} - -/* calc AC and overflow flag given operands (16 bit flavour) */ -void static inline z80_set_flags_ac_16(unsigned int a, - unsigned int b, - unsigned int r) -{ - /* calc xor for AC and overflow */ - unsigned int c = (a ^ b ^ r); - - /* set AC */ - state.flags.ac = ((c & 0x01000) != 0); - - return; -} - -/* calc AC flag given operands and result */ -char static inline z80_calc_ac(uint8_t a, uint8_t b, unsigned int r) -{ - /* calc xor for AC and overflow */ - unsigned int c = a ^ b ^ r; - - /* AC */ - if (c & 0x10) - return 1; - - return 0; -} - -/* calculate flags mask array */ -void static z80_calc_flags_mask_array() -{ - z80_flags_t f; - unsigned int i; - - // bzero(sz53pc, sizeof(sz53pc)); - - /* create a mask for bit 5 and 3 and its reverse */ -/* f.spare = 0= 1; f.z = 1; f.u5 = 0; f.ac = 1; f.u3 = 0; f.p = 1; f.n = 1; f.cy = 1; - u53_mask = *((uint8_t *) &f); - r53_mask = ~(u53_mask); */ - - bzero(&f, 1); - - for (i=0; i<512; i++) - { - f.z = ((i & 0xff) == 0); - f.cy = (i > 0xff); - - zc[i] = *((uint8_t *) &f); - - f.cy = 0; - - z[i] = *((uint8_t *) &f); - - /* no CY and parity */ -/* f.cy = 0; - f.p = parity[i & 0xff]; - sz53p[i] = *((uint8_t *) &f); -*/ - /* similar but with no u3 and u5 */ -/* f.u3 = 0; - f.u5 = 0; - szp[i] = *((uint8_t *) &f); -*/ - /* similar but with carry and no p */ -/* f.cy = (i > 0xff); - f.p = 0; - szc[i] = *((uint8_t *) &f); */ - } -} - - -/********************************/ -/* */ -/* INSTRUCTIONS SEGMENT */ -/* ordered by name */ -/* */ -/********************************/ - - -/* add A register, b parameter and Carry flag, then calculate flags */ -void static inline z80_adc(uint8_t b) -{ - /* calc result */ - unsigned int result = state.a + b + state.flags.cy; - - /* set flags - SZ5H3V0C */ - *state.f = zc[result & 0x1ff]; - - /* set AC and overflow flags */ - z80_set_flags_ac(state.a, b, result); - - /* save result into A register */ - state.a = (uint8_t) result; - - return; -} - -/* add a and b parameters (both 16 bits) and the carry, thencalculate flags */ -unsigned int static inline z80_adc_16(unsigned int a, unsigned int b) -{ - /* calc result */ - unsigned int result = a + b + state.flags.cy; - - /* set them - SZ5H3V0C */ - z80_set_flags_zc_16(result); - state.flags.n = 0; - - /* get only high byte */ - // unsigned int r16 = (result >> 8); - - /* set AC and overflow flags */ - z80_set_flags_ac_16(a, b, result); - - return result; -} - -/* add A register and b parameter and calculate flags */ -void static inline z80_add(uint8_t b) -{ - /* calc result */ - unsigned int result = state.a + b; - - /* set them - SZ5H3P0C */ - *state.f = zc[result & 0x1ff]; - - /* set AC and overflow flags - given AC and V set to 0 */ - z80_set_flags_ac(state.a, b, result); - - /* save result into A register */ - state.a = result; - - return; -} - -/* add a and b parameters (both 16 bits), then calculate flags */ -unsigned int static inline z80_add_16(unsigned int a, unsigned int b) -{ - /* calc result */ - unsigned int result = a + b; - - /* get only high byte */ - // uint8_t r16 = (result >> 8); - - /* not a subtraction */ - state.flags.n = 0; - - /* calc xor for AC */ - z80_set_flags_ac(a, b, result); - - /* set CY */ - state.flags.cy = (result > 0xffff); - - return result; -} - -/* b AND A register and calculate flags */ -void static inline z80_ana(uint8_t b) -{ - /* calc result */ - uint8_t result = state.a & b; - - /* set them */ - *state.f = zc[result] | FLAG_MASK_AC; - - /* save result into A register */ - state.a = result; - - return; -} - -/* BIT instruction, test pos-th bit and set flags */ -void static inline z80_bit(uint8_t *v, uint8_t pos, uint8_t muffa) -{ - uint8_t r = *v & (0x01 << pos); - - /* set flags AC,Z, N = 0 */ - state.flags.n = 0; - state.flags.ac = 1; - state.flags.z = (r == 0) ; - - return; -} - -/* push the current PC on the stack and move PC to the function addr */ -int static inline z80_call(unsigned int addr) -{ - /* move to the next instruction */ - state.pc += 3; - - /* add 4 more cycles */ - cycles_step(); - - /* save it into stack */ - mmu_write_16(state.sp - 2, state.pc); - - /* update stack pointer */ - state.sp -= 2; - - /* move PC to the called function address */ - state.pc = addr; - - return 0; -} - -/* compare b parameter against A register and calculate flags */ -void static inline z80_cmp(uint8_t b) -{ - /* calc result */ - unsigned int result = state.a - b; - - /* set flags - SZ5H3PN* */ - *state.f = zc[result & 0x1ff] | - FLAG_MASK_N; - - /* set AC and overflow flags */ - z80_set_flags_ac(state.a, b, result); - - return; -} - -/* compare b parameter against A register and calculate flags */ -void static inline z80_cpid(uint8_t b, int8_t add) -{ - /* calc result */ - unsigned int result = state.a - b; - - /* calc AC */ - state.flags.ac = z80_calc_ac(state.a, b, result); - - /* increase (add = +1) or decrease (add = -1) HL */ - *state.hl += add; - - /* decrease BC */ - *state.bc = *state.bc - 1; - - /* calc n as result - half carry flag */ - // unsigned int n = result - state.flags.ac; - - /* set flags - SZ5H3P1* */ - state.flags.z = (result & 0xff) == 0; - -// z80_set_flags_z(result); - - /* cmp = subtraction */ - state.flags.n = 1; - - /* set P if BC != 0 */ - // state.flags.p = (*state.bc != 0); - - /* flag 3 and 5 are taken from (result - ac) and not the result */ - /* and u5 is taken exceptionally from the bit 1 */ -// state.flags.u5 = (n & 0x0002) != 0; -// state.flags.u3 = (n & 0x0008) != 0; - - return; -} - -/* DAA instruction... what else? */ -void static inline z80_daa() -{ - unsigned int a = state.a; - uint8_t al = state.a & 0x0f; - - if (state.flags.n) - { - if (state.flags.ac) - a = (a - 6) & 0xFF; - - if (state.flags.cy) - a -= 0x60; - } - else - { - if (al > 9 || state.flags.ac) - { - state.flags.ac = (al > 9); - a += 6; - } - - if (state.flags.cy || ((a & 0x1f0) > 0x90)) - a += 0x60; - } - - if (a & 0x0100) state.flags.cy = 1; - - /* set computer A value */ - state.a = a & 0xff; - - state.flags.ac = 0; - state.flags.z = (state.a == 0); - - return; -} - -/* DAA instruction... what else? */ -void static inline z80_daa_ignore_n() -{ - unsigned int a = state.a; - uint8_t al = state.a & 0x0f; - - if (al > 9 || state.flags.ac) - { - state.flags.ac = (al > 9); - a += 6; - } - - if (state.flags.cy || ((a & 0x1f0) > 0x90)) - a += 0x60; - - if (a & 0x0100) state.flags.cy = 1; - - /* set computer A value */ - state.a = a & 0xff; - - /* reset H flag */ - state.flags.z = (state.a == 0x00); - state.flags.ac = 0; - - /* and its flags */ - // z80_set_flags_sz53p(state.a); - - return; -} - -/* add a and b parameters (both 16 bits) and the carry, thencalculate flags */ -unsigned int static inline dad_16(unsigned int a, unsigned int b) -{ - /* calc result */ - unsigned int result = a + b; - - /* reset n */ - state.flags.n = 0; - - /* calc xor for AC and overflow */ - unsigned int c = a ^ b ^ result; - - /* set AC */ - state.flags.ac = ((c & 0x1000) != 0); - - /* set CY */ - state.flags.cy = (result > 0xffff); - - return result; -} - -/* dec the operand and return result increased by one */ -uint8_t static inline z80_dcr(uint8_t b) -{ - unsigned int result = b - 1; - - /* set flags - SZ5H3V1* */ - z80_set_flags_z(result); - - /* it's a subtraction */ - state.flags.n = 1; - - /* set overflow and AC */ - z80_set_flags_ac(b, 1, result); - -// state.flags.ac = 0; - - return result; -} - -/* inc the operand and return result increased by one */ -uint8_t static inline z80_inr(uint8_t b) -{ - unsigned int result = b + 1; - - /* set flags - SZ5H3V1* */ - z80_set_flags_z(result); - - /* it's not a subtraction */ - state.flags.n = 0; - - /* set overflow and AC */ - z80_set_flags_ac(1, b, result); - - return result; -} - -/* same as call, but save on the stack the current PC instead of next instr */ -int static inline z80_intr(unsigned int addr) -{ - /* push the current PC into stack */ - mmu_write_16(state.sp - 2, state.pc); - - cycles_step(); - - /* update stack pointer */ - state.sp -= 2; - - /* move PC to the called function address */ - state.pc = addr; - - return 0; -} - -/* copy (HL) in (DE) and decrease HL, DE and BC */ -void static inline z80_ldd() -{ - uint8_t byte; - - /* copy! */ - mmu_move(*state.de, *state.hl); - - /* get last moved byte and sum A */ - byte = mmu_read(*state.de); - byte += state.a; - - /* decrease HL, DE and BC */ - *state.hl = *state.hl - 1; - *state.de = *state.de - 1; - *state.bc = *state.bc - 1; - - /* reset flags - preserve ZC */ - *state.f &= FLAG_MASK_Z | - FLAG_MASK_CY; - - return; -} - -/* copy (HL) in (DE) and increase HL and DE. BC is decreased */ -void static inline z80_ldi() -{ - uint8_t byte; - - /* copy! */ - mmu_move(*state.de, *state.hl); - - /* get last moved byte and sum A */ - byte = mmu_read(*state.de); - byte += state.a; - - /* u5 flag is bit 1 of last moved byte + A (WTF?) */ - // state.flags.u5 = (byte & 0x02) >> 1; - - /* u3 flag is bit 3 of last moved byte + A (WTF?) */ - // state.flags.u3 = (byte & 0x08) >> 3; - - /* decrease HL, DE and BC */ - *state.hl = *state.hl + 1; - *state.de = *state.de + 1; - *state.bc = *state.bc - 1; - - /* reset negative, half carry and parity flags */ - state.flags.n = 0; - state.flags.ac = 0; - // state.flags.p = (*state.bc != 0); - - return; -} - -/* negate register A */ -void static inline z80_neg() -{ - /* calc result */ - unsigned int result = 0 - state.a; - - /* set flags - SZ5H3V1C */ - *state.f = zc[result & 0x1ff] | FLAG_MASK_N; - - /* set AC and overflow */ - z80_set_flags_ac(0, state.a, result); - - /* save result into A register */ - state.a = (uint8_t) result; - - return; -} - -/* OR b parameter and A register and calculate flags */ -void static inline z80_ora(uint8_t b) -{ - state.a |= b; - - /* set them SZ503P0C */ - *state.f = zc[state.a]; - - return; -} - -/* RES instruction, put a 0 on pos-th bit and set flags */ -uint8_t static inline z80_res(uint8_t *v, uint8_t pos) -{ - *v &= ~(0x01 << pos); - - return *v; -} - -/* pop the return address from the stack and move PC to that address */ -int static inline z80_ret() -{ - state.pc = mmu_read_16(state.sp); - state.sp += 2; - - /* add 4 cycles */ - cycles_step(); - - return 0; -} - -/* RL (Rotate Left) instruction */ -uint8_t static inline z80_rl(uint8_t *v, char with_carry) -{ - uint8_t carry; - - /* apply RLC to the memory pointed byte */ - carry = (*v & 0x80) >> 7; - *v = *v << 1; - - if (with_carry) - *v |= carry; - else - *v |= state.flags.cy; - - /* set flags - SZ503P0C */ - *state.f = 0; // sz53p[*v]; - - state.flags.z = (*v == 0); - state.flags.cy = carry; - - return *v; -} - -/* RLA instruction */ -uint8_t static inline z80_rla(uint8_t *v, char with_carry) -{ - uint8_t carry; - - /* apply RLA to the memory pointed byte */ - carry = (*v & 0x80) >> 7; - *v = *v << 1; - - if (with_carry) - *v |= carry; - else - *v |= state.flags.cy; - - /* reset flags */ - *state.f = 0; - - /* just set carry */ - state.flags.cy = carry; - - return *v; -} - -/* RLD instruction */ -void static inline z80_rld() -{ - uint8_t hl = mmu_read(*state.hl); - - /* save lowest A 4 bits */ - uint8_t al = state.a & 0x0f; - - /* A lowest bits are overwritten by (HL) highest ones */ - state.a &= 0xf0; - state.a |= (hl >> 4); - - /* (HL) highest bits are overwritten by (HL) lowest ones */ - hl <<= 4; - - /* finally, (HL) lowest bits are overwritten by A lowest */ - hl &= 0xf0; - hl |= al; - - /* set (HL) with his new value ((HL) low | A low) */ - mmu_write(*state.hl, hl); - - /* reset flags - preserve CY */ - *state.f &= FLAG_MASK_CY; - - /* set flags - SZ503P0* */ - *state.f |= z[state.a]; - - return; -} - -/* RR instruction */ -uint8_t static inline z80_rr(uint8_t *v, char with_carry) -{ - uint8_t carry; - - /* apply RRC to the memory pointed byte */ - carry = *v & 0x01; - *v = (*v >> 1); - - /* 7th bit taken from old bit 0 or from CY */ - if (with_carry) - *v |= (carry << 7); - else - *v |= (state.flags.cy << 7); - - /* set flags - SZ503P0C */ - *state.f = z[*v]; - - state.flags.cy = carry; - - return *v; -} - -/* RRA instruction */ -uint8_t static inline z80_rra(uint8_t *v, char with_carry) -{ - uint8_t carry; - - /* apply RRC to the memory pointed byte */ - carry = *v & 0x01; - *v = (*v >> 1); - - /* 7th bit taken from old bit 0 or from CY */ - if (with_carry) - *v |= (carry << 7); - else - *v |= (state.flags.cy << 7); - - /* reset flags */ - *state.f = 0; - - state.flags.cy = carry; - -// state.flags.n = 0; -// state.flags.ac = 0; - - /* copy bit 3 and 5 of the result */ - // state.flags.u3 = ((*v & 0x08) != 0); - // state.flags.u5 = ((*v & 0x20) != 0); - - return *v; -} - -/* RRD instruction */ -void static inline z80_rrd() -{ - uint8_t hl = mmu_read(*state.hl); - - /* save lowest (HL) 4 bits */ - uint8_t hll = hl & 0x0f; - - /* (HL) lowest bits are overwritten by (HL) highest ones */ - hl >>= 4; - - /* (HL) highest bits are overwritten by A lowest ones */ - hl |= ((state.a & 0x0f) << 4); - - /* set (HL) with his new value (A low | (HL) high) */ - mmu_write(*state.hl, hl); - - /* finally, A lowest bits are overwritten by (HL) lowest */ - state.a &= 0xf0; - state.a |= hll; - - /* reset flags - preserve CY */ - *state.f &= FLAG_MASK_CY; - - /* set flags - SZ503P0* */ - *state.f |= z[state.a]; - - return; -} - -/* subtract b parameter and Carry from A register and calculate flags */ -void static inline z80_sbc(uint8_t b) -{ - /* calc result */ - unsigned int result = state.a - b - state.flags.cy; - - /* set flags - ZC and N = 1 */ - *state.f = zc[result & 0x1ff] | FLAG_MASK_N; - - /* set AC */ - z80_set_flags_ac(state.a, b, result); - - /* save result into A register */ - state.a = (uint8_t) result; - - return; -} - -/* subtract a and b parameters (both 16 bits) and the carry, then calculate flags */ -unsigned int static inline z80_sbc_16(unsigned int a, unsigned int b) -{ - /* calc result */ - unsigned int result = a - b - state.flags.cy; - - /* set flags - SZ5H3V1C */ - z80_set_flags_zc_16(result); - state.flags.n = 1; - - /* get only high byte */ - // unsigned int r16 = (result >> 8); - - /* set AC and overflow flags */ - z80_set_flags_ac_16(a, b, result); - - return result; -} - -/* SET instruction, put a 1 on pos-th bit and set flags */ -uint8_t static inline z80_set(uint8_t *v, uint8_t pos) -{ - *v |= (0x01 << pos); - - return *v; -} - -/* SL instruction (SLA = v * 2, SLL = v * 2 + 1) */ -uint8_t static inline z80_sl(uint8_t *v, char one_insertion) -{ - /* move pointed value to local (gives an huge boost in perf!) */ - uint8_t l = *v; - - /* apply SL to the memory pointed byte */ - uint8_t cy = (l & 0x80) != 0; - l = (l << 1) | one_insertion; - - /* set flags - SZ503P0C */ - *state.f = z[l]; - - state.flags.cy = cy; - - /* re-assign local value */ - *v = l; - - return l; -} - -/* SR instruction (SRA = preserve 8th bit, SRL = discard 8th bit) */ -uint8_t static inline z80_sr(uint8_t *v, char preserve) -{ - uint8_t bit = 0; - - /* save the bit 0 */ - uint8_t cy = (*v & 0x01); - - /* apply SL to the memory pointed byte */ - if (preserve) - bit = *v & 0x80; - - /* move 1 pos right and restore highest bit (in case of SRA) */ - *v = (*v >> 1) | bit; - - /* set flags - SZ503P0C */ - *state.f = z[*v]; - - state.flags.cy = cy; - - return *v; -} - -/* subtract b parameter from A register and calculate flags */ -void static inline z80_sub(uint8_t b) -{ - /* calc result */ - unsigned int result = state.a - b; - - /* set them - SZ5H3V1C */ - *state.f = zc[result & 0x1ff] | FLAG_MASK_N; - - /* set AC and overflow flags */ - z80_set_flags_ac(state.a, b, result); - - /* save result into A register */ - state.a = (uint8_t) result; - - return; -} - -/* xor b parameter and A register and calculate flags */ -void static inline z80_xra(uint8_t b) -{ - /* calc result */ - state.a ^= b; - - /* set them SZ503P00 */ - *state.f = z[state.a]; - - return; -} - - - -/********************************/ -/* */ -/* INSTRUCTIONS BRANCHES */ -/* */ -/********************************/ - - -/* Z80 extended OPs */ -int static inline z80_ext_cb_execute() -{ - uint8_t byte = 1; - int b = 2; - - /* CB family (ROT, BIT, RES, SET) */ - uint8_t cbfam; - - /* CB operation */ - uint8_t cbop; - - /* choosen register */ - uint8_t reg; - - /* get CB code */ - uint8_t code = mmu_read(state.pc + 1); - - /* extract family */ - cbfam = code >> 6; - - /* extract involved register */ - reg = code & 0x07; - - /* if reg == 0x06, refresh the pointer */ - // if (reg == 0x06 && code != 0x36) - // { - /* add 4 more cycles for reading data from memory */ - // cycles_step(); - - // regs_src[0x06] = mmu_addr(*state.hl); - // } - - switch (cbfam) - { - /* Rotate Family */ - case 0x00: cbop = code & 0xf8; - - switch(cbop) - { - /* RLC REG */ - case 0x00: if (reg == 0x06) - { - byte = mmu_read(*state.hl); - mmu_write(*state.hl, z80_rl(&byte, 1)); - } - else - z80_rl(regs_src[reg], 1); - break; - - /* RRC REG */ - case 0x08: if (reg == 0x06) - { - byte = mmu_read(*state.hl); - mmu_write(*state.hl, z80_rr(&byte, 1)); - } - else - z80_rr(regs_src[reg], 1); - - break; - - /* RL REG */ - case 0x10: if (reg == 0x06) - { - byte = mmu_read(*state.hl); - mmu_write(*state.hl, z80_rl(&byte, 0)); - } - else - z80_rl(regs_src[reg], 0); - - break; - - /* RR REG */ - case 0x18: if (reg == 0x06) - { - byte = mmu_read(*state.hl); - mmu_write(*state.hl, z80_rr(&byte, 0)); - } - else - z80_rr(regs_src[reg], 0); - - break; - - /* SLA REG */ - case 0x20: if (reg == 0x06) - { - byte = mmu_read(*state.hl); - mmu_write(*state.hl, z80_sl(&byte, 0)); - } - else - z80_sl(regs_src[reg], 0); - - break; - - /* SRA REG */ - case 0x28: if (reg == 0x06) - { - byte = mmu_read(*state.hl); - mmu_write(*state.hl, z80_sr(&byte, 1)); - } - else - z80_sr(regs_src[reg], 1); - - break; - - /* SWAP */ - case 0x30: - switch (code & 0x37) - { - /* SWAP B */ - case 0x30: byte = state.b; - state.b = ((byte & 0xf0) >> 4) | - ((byte & 0x0f) << 4); - break; - - /* SWAP C */ - case 0x31: byte = state.c; - state.c = ((byte & 0xf0) >> 4) | - ((byte & 0x0f) << 4); - break; - - /* SWAP D */ - case 0x32: byte = state.d; - state.d = ((byte & 0xf0) >> 4) | - ((byte & 0x0f) << 4); - break; - - /* SWAP E */ - case 0x33: byte = state.e; - state.e = ((byte & 0xf0) >> 4) | - ((byte & 0x0f) << 4); - break; - - /* SWAP H */ - case 0x34: byte = state.h; - state.h = ((byte & 0xf0) >> 4) | - ((byte & 0x0f) << 4); - break; - - /* SWAP L */ - case 0x35: byte = state.l; - state.l = ((byte & 0xf0) >> 4) | - ((byte & 0x0f) << 4); - break; - - /* SWAP *HL */ - case 0x36: byte = mmu_read(*state.hl); - mmu_write(*state.hl, - ((byte & 0xf0) >> 4) | - ((byte & 0x0f) << 4)); - - break; - - /* SWAP A */ - case 0x37: - byte = state.a; - state.a = ((byte & 0xf0) >> 4) | - ((byte & 0x0f) << 4); - break; - - } - - /* swap functions set Z flags */ - state.flags.z = (byte == 0x00); - - /* reset all the others */ - state.flags.ac = 0; - state.flags.cy = 0; - state.flags.n = 0; - - break; - - /* SRL REG */ - case 0x38: if (reg == 0x06) - { - byte = mmu_read(*state.hl); - mmu_write(*state.hl, z80_sr(&byte, 0)); - } - else - z80_sr(regs_src[reg], 0); - - break; - } - - /* accessing HL needs more T-cycles */ - //if (reg == 0x06 && code != 0x36) - // cycles_step(); - - /* accessing HL needs more T-cycles */ -// if (reg == 0x06) -// cycles_step(); - - break; - - /* BIT Family */ - case 0x01: if (reg == 0x06) - { - byte = mmu_read(*state.hl); - z80_bit(&byte, (code >> 3) & 0x07, - (uint8_t) *state.hl); - } - else - z80_bit(regs_src[reg], (code >> 3) & 0x07, - *regs_src[reg]); - break; - - /* RES Family */ - case 0x02: if (reg == 0x06) - { - byte = mmu_read(*state.hl); - mmu_write(*state.hl, z80_res(&byte, (code >> 3) & 0x07)); - } - else - z80_res(regs_src[reg], (code >> 3) & 0x07); - - break; - - /* SET Family */ - case 0x03: if (reg == 0x06) - { - byte = mmu_read(*state.hl); - mmu_write(*state.hl, z80_set(&byte, (code >> 3) & 0x07)); - } - else - z80_set(regs_src[reg], (code >> 3) & 0x07); - - break; - -// default: printf("Unimplemented CB family: %02x\n", -// cbfam); - - } - - return b; -} - - -/* really execute the OP. Could be ran by normal execution or * - * because an interrupt occours */ -int static inline z80_execute(unsigned char code) -{ - int b = 1; - uint8_t *p; - uint8_t byte = 1; - uint8_t byte2 = 1; - unsigned int result; - uint_fast16_t addr; - - switch (code) - { - /* NOP */ - case 0x00: break; - - /* LXI B */ - case 0x01: *state.bc = ADDR; - b = 3; - break; - - /* STAX B */ - case 0x02: mmu_write(*state.bc, state.a); - break; - - /* INX B */ - case 0x03: (*state.bc)++; - cycles_step(); - break; - - /* INR B */ - case 0x04: state.b = z80_inr(state.b); - break; - - /* DCR B */ - case 0x05: state.b = z80_dcr(state.b); - break; - - /* MVI B */ - case 0x06: state.b = mmu_read(state.pc + 1); - b = 2; - break; - - /* RLCA */ - case 0x07: z80_rla(&state.a, 1); - break; - - /* LD (NN),SP */ - case 0x08: mmu_write_16(ADDR, state.sp); - b = 3; - break; - - /* DAD B */ - case 0x09: *state.hl = dad_16(*state.hl, *state.bc); - - /* needs 4 more cycles */ - cycles_step(); - - break; - - /* LDAX B */ - case 0x0A: state.a = mmu_read(*state.bc); - break; - - /* DCX B */ - case 0x0B: (*state.bc)--; - cycles_step(); - break; - - /* INR C */ - case 0x0C: state.c = z80_inr(state.c); - break; - - /* DCR C */ - case 0x0D: state.c = z80_dcr(state.c); - break; - - /* MVI C */ - case 0x0E: state.c = mmu_read(state.pc + 1); - b = 2; - break; - - /* RRC */ - case 0x0F: z80_rra(&state.a, 1); - break; - - /* STOP */ - case 0x10: b = 2; - break; - - /* LXI D */ - case 0x11: *state.de = ADDR; - b = 3; - break; - - /* STAX D */ - case 0x12: mmu_write(*state.de, state.a); - break; - - /* INX D */ - case 0x13: (*state.de)++; - cycles_step(); - break; - - /* INR D */ - case 0x14: state.d = z80_inr(state.d); - break; - - /* DCR D */ - case 0x15: state.d = z80_dcr(state.d); - break; - - /* MVI D */ - case 0x16: state.d = mmu_read(state.pc + 1); - b = 2; - break; - - /* RLA */ - case 0x17: z80_rla(&state.a, 0); - break; - - /* JR */ - case 0x18: cycles_step(); - state.pc += (int8_t) mmu_read(state.pc + 1); - b = 2; - break; - - /* DAD D */ - case 0x19: *state.hl = dad_16(*state.hl, *state.de); - - /* needs 4 more cycles */ - cycles_step(); - - break; - - /* LDAX D */ - case 0x1A: state.a = mmu_read(*state.de); - break; - - /* DCX D */ - case 0x1B: (*state.de)--; - cycles_step(); - break; - - /* INR E */ - case 0x1C: state.e = z80_inr(state.e); - break; - - /* DCR E */ - case 0x1D: state.e = z80_dcr(state.e); - break; - - /* MVI E */ - case 0x1E: state.e = mmu_read(state.pc + 1); - b = 2; - break; - - /* RRA */ - case 0x1F: z80_rra(&state.a, 0); - break; - - /* JRNZ */ - case 0x20: cycles_step(); - - if (!state.flags.z) - state.pc += (int8_t) mmu_read(state.pc + 1); - - b = 2; - break; - - /* LXI H */ - case 0x21: *state.hl = ADDR; - b = 3; - break; - - /* LDI (HL), A */ - case 0x22: mmu_write(*state.hl, state.a); - (*state.hl)++; - break; - - /* INX H */ - case 0x23: (*state.hl)++; - cycles_step(); - break; - - /* INR H */ - case 0x24: state.h = z80_inr(state.h); - break; - - /* DCR H */ - case 0x25: state.h = z80_dcr(state.h); - break; - - /* MVI H */ - case 0x26: state.h = mmu_read(state.pc + 1); - b = 2; - break; - - /* DAA */ - case 0x27: z80_daa(); - break; - - /* JRZ */ - case 0x28: cycles_step(); - if (state.flags.z) - state.pc += (int8_t) mmu_read(state.pc + 1); - - b = 2; - break; - - /* DAD H */ - case 0x29: *state.hl = dad_16(*state.hl, *state.hl); - - /* needs 4 more cycles */ - cycles_step(); - - break; - - /* LDI A,(HL) */ - case 0x2A: state.a = mmu_read(*state.hl); - (*state.hl)++; - break; - - /* DCX H */ - case 0x2B: (*state.hl)--; - cycles_step(); - break; - - /* INR L */ - case 0x2C: state.l = z80_inr(state.l); - break; - - /* DCR L */ - case 0x2D: state.l = z80_dcr(state.l); - break; - - /* MVI L */ - case 0x2E: state.l = mmu_read(state.pc + 1); - b = 2; - break; - - /* CMA A */ - case 0x2F: state.a = ~state.a; - state.flags.ac = 1; - state.flags.n = 1; - break; - - /* JRNC */ - case 0x30: cycles_step(); - - if (!state.flags.cy) - state.pc += (int8_t) mmu_read(state.pc + 1); - - b = 2; - break; - - /* LXI SP */ - case 0x31: state.sp = ADDR; - b = 3; - break; - - /* LDD (HL), A */ - case 0x32: mmu_write(*state.hl, state.a); - (*state.hl)--; - break; - - /* INX SP */ - case 0x33: state.sp++; - cycles_step(); - break; - - /* INR M */ - case 0x34: mmu_write(*state.hl, z80_inr(mmu_read(*state.hl))); - break; - - /* DCR M */ - case 0x35: mmu_write(*state.hl, z80_dcr(mmu_read(*state.hl))); - break; - - /* MVI M */ - case 0x36: mmu_move(*state.hl, state.pc + 1); - b = 2; - break; - - /* STC */ - case 0x37: state.flags.cy = 1; - state.flags.ac = 0; - state.flags.n = 0; - break; - - /* JRC */ - case 0x38: cycles_step(); - if (state.flags.cy) - state.pc += (int8_t) mmu_read(state.pc + 1); - - b = 2; - break; - - /* DAD SP */ - case 0x39: *state.hl = dad_16(*state.hl, state.sp); - - /* needs 4 more cycles */ - cycles_step(); - - break; - - /* LDD A,(HL) */ - case 0x3A: state.a = mmu_read(*state.hl); - (*state.hl)--; - break; - - /* DCX SP */ - case 0x3B: state.sp--; - cycles_step(); - break; - - /* INR A */ - case 0x3C: state.a = z80_inr(state.a); - break; - - /* DCR A */ - case 0x3D: state.a = z80_dcr(state.a); - break; - - /* MVI A */ - case 0x3E: state.a = mmu_read(state.pc + 1); - b = 2; - break; - - /* CCF */ - case 0x3F: state.flags.ac = 0; - state.flags.cy = !state.flags.cy; - state.flags.n = 0; - - break; - - /* MOV B,B */ - case 0x40: state.b = state.b; - break; - - /* MOV B,C */ - case 0x41: state.b = state.c; - break; - - /* MOV B,D */ - case 0x42: state.b = state.d; - break; - - /* MOV B,E */ - case 0x43: state.b = state.e; - break; - - /* MOV B,H */ - case 0x44: state.b = state.h; - break; - - /* MOV B,L */ - case 0x45: state.b = state.l; - break; - - /* MOV B,M */ - case 0x46: state.b = mmu_read(*state.hl); - break; - - /* MOV B,A */ - case 0x47: state.b = state.a; - break; - - /* MOV C,B */ - case 0x48: state.c = state.b; - break; - - /* MOV C,C */ - case 0x49: state.c = state.c; - break; - - /* MOV C,D */ - case 0x4A: state.c = state.d; - break; - - /* MOV C,E */ - case 0x4B: state.c = state.e; - break; - - /* MOV C,H */ - case 0x4C: state.c = state.h; - break; - - /* MOV C,L */ - case 0x4D: state.c = state.l; - break; - - /* MOV C,M */ - case 0x4E: state.c = mmu_read(*state.hl); - break; - - /* MOV C,A */ - case 0x4F: state.c = state.a; - break; - - /* MOV D,B */ - case 0x50: state.d = state.b; - break; - - /* MOV D,C */ - case 0x51: state.d = state.c; - break; - - /* MOV D,D */ - case 0x52: state.d = state.d; - break; - - /* MOV D,E */ - case 0x53: state.d = state.e; - break; - - /* MOV D,H */ - case 0x54: state.d = state.h; - break; - - /* MOV D,L */ - case 0x55: state.d = state.l; - break; - - /* MOV D,M */ - case 0x56: state.d = mmu_read(*state.hl); - break; - - /* MOV D,A */ - case 0x57: state.d = state.a; - break; - - /* MOV E,B */ - case 0x58: state.e = state.b; - break; - - /* MOV E,C */ - case 0x59: state.e = state.c; - break; - - /* MOV E,D */ - case 0x5A: state.e = state.d; - break; - - /* MOV E,E */ - case 0x5B: state.e = state.e; - break; - - /* MOV E,H */ - case 0x5C: state.e = state.h; - break; - - /* MOV E,L */ - case 0x5D: state.e = state.l; - break; - - /* MOV E,M */ - case 0x5E: state.e = mmu_read(*state.hl); - break; - - /* MOV E,A */ - case 0x5F: state.e = state.a; - break; - - /* MOV H,B */ - case 0x60: state.h = state.b; - break; - - /* MOV H,C */ - case 0x61: state.h = state.c; - break; - - /* MOV H,D */ - case 0x62: state.h = state.d; - break; - - /* MOV H,E */ - case 0x63: state.h = state.e; - break; - - /* MOV H,H */ - case 0x64: state.h = state.h; - break; - - /* MOV H,L */ - case 0x65: state.h = state.l; - break; - - /* MOV H,M */ - case 0x66: state.h = mmu_read(*state.hl); - break; - - /* MOV H,A */ - case 0x67: state.h = state.a; - break; - - /* MOV L,B */ - case 0x68: state.l = state.b; - break; - - /* MOV L,C */ - case 0x69: state.l = state.c; - break; - - /* MOV L,D */ - case 0x6A: state.l = state.d; - break; - - /* MOV L,E */ - case 0x6B: state.l = state.e; - break; - - /* MOV L,H */ - case 0x6C: state.l = state.h; - break; - - /* MOV L,L */ - case 0x6D: state.l = state.l; - break; - - /* MOV L,M */ - case 0x6E: state.l = mmu_read(*state.hl); - break; - - /* MOV L,A */ - case 0x6F: state.l = state.a; - break; - - /* MOV M,B */ - case 0x70: mmu_write(*state.hl, state.b); - break; - - /* MOV M,C */ - case 0x71: mmu_write(*state.hl, state.c); - break; - - /* MOV M,D */ - case 0x72: mmu_write(*state.hl, state.d); - break; - - /* MOV M,E */ - case 0x73: mmu_write(*state.hl, state.e); - break; - - /* MOV M,H */ - case 0x74: mmu_write(*state.hl, state.h); - break; - - /* MOV M,L */ - case 0x75: mmu_write(*state.hl, state.l); - break; - - /* HLT */ - case 0x76: return 1; - - /* MOV M,A */ - case 0x77: mmu_write(*state.hl, state.a); - break; - - /* MOV A,B */ - case 0x78: state.a = state.b; - break; - - /* MOV A,C */ - case 0x79: state.a = state.c; - break; - - /* MOV A,D */ - case 0x7A: state.a = state.d; - break; - - /* MOV A,E */ - case 0x7B: state.a = state.e; - break; - - /* MOV A,H */ - case 0x7C: state.a = state.h; - break; - - /* MOV A,L */ - case 0x7D: state.a = state.l; - break; - - /* MOV A,M */ - case 0x7E: state.a = mmu_read(*state.hl); - break; - - /* MOV A,A */ - case 0x7F: state.a = state.a; - break; - - /* ADD B */ - case 0x80: z80_add(state.b); - break; - - /* ADD C */ - case 0x81: z80_add(state.c); - break; - - /* ADD D */ - case 0x82: z80_add(state.d); - break; - - /* ADD E */ - case 0x83: z80_add(state.e); - break; - - /* ADD H */ - case 0x84: z80_add(state.h); - break; - - /* ADD L */ - case 0x85: z80_add(state.l); - break; - - /* ADD M */ - case 0x86: z80_add(mmu_read(*state.hl)); - break; - - /* ADD A */ - case 0x87: z80_add(state.a); - break; - - /* ADC B */ - case 0x88: z80_adc(state.b); - break; - - /* ADC C */ - case 0x89: z80_adc(state.c); - break; - - /* ADC D */ - case 0x8A: z80_adc(state.d); - break; - - /* ADC E */ - case 0x8B: z80_adc(state.e); - break; - - /* ADC H */ - case 0x8C: z80_adc(state.h); - break; - - /* ADC L */ - case 0x8D: z80_adc(state.l); - break; - - /* ADC M */ - case 0x8E: z80_adc(mmu_read(*state.hl)); - break; - - /* ADC A */ - case 0x8F: z80_adc(state.a); - break; - - /* SUB B */ - case 0x90: z80_sub(state.b); - break; - - /* SUB C */ - case 0x91: z80_sub(state.c); - break; - - /* SUB D */ - case 0x92: z80_sub(state.d); - break; - - /* SUB E */ - case 0x93: z80_sub(state.e); - break; - - /* SUB H */ - case 0x94: z80_sub(state.h); - break; - - /* SUB L */ - case 0x95: z80_sub(state.l); - break; - - /* SUB M */ - case 0x96: z80_sub(mmu_read(*state.hl)); - break; - - /* SUB A */ - case 0x97: z80_sub(state.a); - break; - - /* SBC B */ - case 0x98: z80_sbc(state.b); - break; - - /* SBC C */ - case 0x99: z80_sbc(state.c); - break; - - /* SBC D */ - case 0x9a: z80_sbc(state.d); - break; - - /* SBC E */ - case 0x9b: z80_sbc(state.e); - break; - - /* SBC H */ - case 0x9c: z80_sbc(state.h); - break; - - /* SBC L */ - case 0x9d: z80_sbc(state.l); - break; - - /* SBC M */ - case 0x9E: z80_sbc(mmu_read(*state.hl)); - break; - - /* SBC A */ - case 0x9f: z80_sbc(state.a); - break; - - /* ANA B */ - case 0xA0: z80_ana(state.b); - break; - - /* ANA C */ - case 0xA1: z80_ana(state.c); - break; - - /* ANA D */ - case 0xA2: z80_ana(state.d); - break; - - /* ANA E */ - case 0xA3: z80_ana(state.e); - break; - - /* ANA H */ - case 0xA4: z80_ana(state.h); - break; - - /* ANA L */ - case 0xA5: z80_ana(state.l); - break; - - /* ANA M */ - case 0xA6: z80_ana(mmu_read(*state.hl)); - break; - - /* ANA A */ - case 0xA7: z80_ana(state.a); - break; - - /* XRA B */ - case 0xA8: z80_xra(state.b); - break; - - /* XRA C */ - case 0xA9: z80_xra(state.c); - break; - - /* XRA D */ - case 0xAA: z80_xra(state.d); - break; - - /* XRA E */ - case 0xAB: z80_xra(state.e); - break; - - /* XRA H */ - case 0xAC: z80_xra(state.h); - break; - - /* XRA L */ - case 0xAD: z80_xra(state.l); - break; - - /* XRA M */ - case 0xAE: z80_xra(mmu_read(*state.hl)); - break; - - /* XRA A */ - case 0xAF: z80_xra(state.a); - break; - - /* ORA B */ - case 0xB0: z80_ora(state.b); - break; - - /* ORA C */ - case 0xB1: z80_ora(state.c); - break; - - /* ORA D */ - case 0xB2: z80_ora(state.d); - break; - - /* ORA E */ - case 0xB3: z80_ora(state.e); - break; - - /* ORA H */ - case 0xB4: z80_ora(state.h); - break; - - /* ORA L */ - case 0xB5: z80_ora(state.l); - break; - - /* ORA M */ - case 0xB6: z80_ora(mmu_read(*state.hl)); - break; - - /* ORA A */ - case 0xB7: z80_ora(state.a); - break; - - /* CMP B */ - case 0xB8: z80_cmp(state.b); - break; - - /* CMP C */ - case 0xB9: z80_cmp(state.c); - break; - - /* CMP D */ - case 0xBA: z80_cmp(state.d); - break; - - /* CMP E */ - case 0xBB: z80_cmp(state.e); - break; - - /* CMP H */ - case 0xBC: z80_cmp(state.h); - break; - - /* CMP L */ - case 0xBD: z80_cmp(state.l); - break; - - /* CMP M */ - case 0xBE: z80_cmp(mmu_read(*state.hl)); - break; - - /* CMP A */ - case 0xBF: z80_cmp(state.a); - break; - - /* RNZ */ - case 0xC0: cycles_step(); - - if (state.flags.z == 0) - return z80_ret(); - - break; - - /* POP B */ - case 0xC1: *state.bc = mmu_read_16(state.sp); - state.sp += 2; - break; - - /* JNZ addr */ - case 0xC2: /* this will add 8 cycles */ - addr = ADDR; - - if (state.flags.z == 0) - { - /* add 4 more cycles */ - cycles_step(); - - state.pc = addr; - return 0; - } - - b = 3; - break; - - /* JMP addr */ - case 0xC3: state.pc = ADDR; - - /* add 4 cycles */ - cycles_step(); - - return 0; - - /* CNZ */ - case 0xC4: addr = ADDR; - - if (state.flags.z == 0) - return z80_call(addr); - - b = 3; - break; - - /* PUSH B */ - case 0xC5: cycles_step(); - mmu_write_16(state.sp - 2, *state.bc); - state.sp -= 2; - break; - - /* ADI */ - case 0xC6: z80_add(mmu_read(state.pc + 1)); - b = 2; - break; - - /* RST 0 */ - case 0xC7: state.pc++; - return z80_intr(0x0008 * 0); - - /* RZ */ - case 0xC8: cycles_step(); - - if (state.flags.z) - return z80_ret(); - - break; - - /* RET */ - case 0xC9: return z80_ret(); - - /* JZ */ - case 0xCA: /* add 8 cycles */ - addr = ADDR; - - if (state.flags.z) - { - /* add 4 more cycles */ - cycles_step(); - - state.pc = addr; - return 0; - } - - b = 3; - break; - - /* CB */ - case 0xCB: b = z80_ext_cb_execute(); - break; - - /* CZ */ - case 0xCC: addr = ADDR; - - if (state.flags.z) - return z80_call(addr); - - b = 3; - break; - - /* CALL addr */ - case 0xCD: return z80_call(ADDR); - - /* ACI */ - case 0xCE: z80_adc(mmu_read(state.pc + 1)); - b = 2; - break; - - /* RST 1 */ - case 0xCF: state.pc++; - return z80_intr(0x0008 * 1); - - /* RNC */ - case 0xD0: cycles_step(); - - if (state.flags.cy == 0) - return z80_ret(); - - break; - - /* POP D */ - case 0xD1: *state.de = mmu_read_16(state.sp); - state.sp += 2; - break; - - /* JNC */ - case 0xD2: /* add 8 cycles */ - addr = ADDR; - - if (state.flags.cy == 0) - { - /* add 4 more cycles */ - cycles_step(); - - state.pc = addr; - return 0; - } - - b = 3; - break; - - /* not present */ - case 0xD3: // b = 2; - break; - - /* CNC */ - case 0xD4: addr = ADDR; - - if (state.flags.cy == 0) - return z80_call(addr); - - b = 3; - break; - - /* PUSH D */ - case 0xD5: cycles_step(); - mmu_write_16(state.sp - 2, *state.de); - state.sp -= 2; - break; - - /* SUI */ - case 0xD6: z80_sub(mmu_read(state.pc + 1)); - b = 2; - break; - - /* RST 2 */ - case 0xD7: state.pc++; - return z80_intr(0x0008 * 2); - - /* RC */ - case 0xD8: cycles_step(); - - if (state.flags.cy) - return z80_ret(); - - break; - - /* RETI */ - case 0xD9: state.int_enable = 1; - return z80_ret(); - break; - - /* JC */ - case 0xDA: /* add 8 cycles */ - addr = ADDR; - - if (state.flags.cy) - { - /* add 4 more cycles */ - cycles_step(); - - state.pc = addr; - return 0; - } - - b = 3; - break; - - /* not present */ - case 0xDB: break; - - /* CC */ - case 0xDC: addr = ADDR; - - if (state.flags.cy) - return z80_call(addr); - - b = 3; - break; - - /* SBI */ - case 0xDE: z80_sbc(mmu_read(state.pc + 1)); - b = 2; - break; - - /* RST 3 */ - case 0xDF: state.pc++; - return z80_intr(0x0008 * 3); - - /* LD (FF00+N),A */ - case 0xE0: mmu_write(0xFF00 + mmu_read(state.pc + 1), state.a); - b = 2; - break; - - /* POP H */ - case 0xE1: *state.hl = mmu_read_16(state.sp); - state.sp += 2; - break; - - /* LD (FF00+C),A */ - case 0xE2: mmu_write(0xFF00 + state.c, state.a); - break; - - /* not present on Gameboy Z80 */ - case 0xE3: - case 0xE4: break; - - /* PUSH H */ - case 0xE5: cycles_step(); - mmu_write_16(state.sp - 2, *state.hl); - state.sp -= 2; - break; - - /* ANI */ - case 0xE6: z80_ana(mmu_read(state.pc + 1)); - b = 2; - break; - - /* RST 4 */ - case 0xE7: state.pc++; - return z80_intr(0x0008 * 4); - - /* ADD SP,dd */ - case 0xE8: byte = mmu_read(state.pc + 1); - byte2 = (uint8_t) (state.sp & 0x00ff); - result = byte2 + byte; - - state.flags.z = 0; - state.flags.n = 0; - - state.flags.cy = (result > 0xff); - - /* add 8 cycles */ - cycles_step(); - cycles_step(); - - /* calc xor for AC */ - z80_set_flags_ac(byte2, byte, result); - - /* set sp */ - state.sp += (int8_t) byte; // result & 0xffff; - - b = 2; - break; - - /* PCHL */ - case 0xE9: state.pc = *state.hl; - return 0; - - /* LD (NN),A */ - case 0xEA: mmu_write(ADDR, state.a); - b = 3; - break; - - /* not present on Gameboy Z80 */ - case 0xEB: - case 0xEC: - case 0xED: break; - - /* XRI */ - case 0xEE: z80_xra(mmu_read(state.pc + 1)); - b = 2; - break; - - /* RST 5 */ - case 0xEF: state.pc++; - return z80_intr(0x0008 * 5); - - /* LD A,(FF00+N) */ - case 0xF0: state.a = mmu_read(0xFF00 + mmu_read(state.pc + 1)); - b = 2; - break; - - /* POP PSW */ - case 0xF1: p = (uint8_t *) &state.flags; - *p = (mmu_read(state.sp) & 0xf0); - state.a = mmu_read(state.sp + 1); - - state.sp += 2; - break; - - /* LD A,(FF00+C) */ - case 0xF2: state.a = mmu_read(0xFF00 + state.c); - break; - - /* DI */ - case 0xF3: state.int_enable = 0; - break; - - /* not present on Gameboy Z80 */ - case 0xF4: break; - - /* PUSH PSW */ - case 0xF5: p = (uint8_t *) &state.flags; - - cycles_step(); - - mmu_write(state.sp - 1, state.a); - mmu_write(state.sp - 2, *p); - state.sp -= 2; - break; - - /* ORI */ - case 0xF6: z80_ora(mmu_read(state.pc + 1)); - b = 2; - break; - - /* RST 6 */ - case 0xF7: state.pc++; - return z80_intr(0x0008 * 6); - - /* LD HL,SP+dd */ - case 0xF8: byte = mmu_read(state.pc + 1); - byte2 = (uint8_t) (state.sp & 0x00ff); - result = byte2 + byte; - - state.flags.z = 0; - state.flags.n = 0; - - state.flags.cy = (result > 0xff); - - /* add 4 cycles */ - cycles_step(); - - /* calc xor for AC */ - z80_set_flags_ac(byte2, byte, result); - - /* set sp */ - *state.hl = state.sp + (int8_t) byte; // result & 0xffff; - - b = 2; - break; - - /* SPHL */ - case 0xF9: cycles_step(); - state.sp = *state.hl; - break; - - /* LD A, (NN) */ - case 0xFA: state.a = mmu_read(ADDR); - b = 3; - break; - - /* EI */ - case 0xFB: state.int_enable = 1; - break; - - /* not present on Gameboy Z80 */ - case 0xFC: - case 0xFD: break; - - /* CPI */ - case 0xFE: z80_cmp(mmu_read(state.pc + 1)); - b = 2; - break; - - /* RST 7 */ - case 0xFF: state.pc++; - return z80_intr(0x0008 * 7); - - default: return 1; - } - - /* make the PC points to the next instruction */ - state.pc += b; - - return 0; -} - -/* init registers, flags and state.memory of Gameboy Z80 CPU */ -z80_state_t static *z80_init() -{ - /* wipe all the structs */ - bzero(&state, sizeof(z80_state_t)); - -/* 16 bit values just point to the first reg of the pairs */ -#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ - state.hl = (uint16_t *) &state.l; - state.bc = (uint16_t *) &state.c; - state.de = (uint16_t *) &state.e; -#else - state.hl = (uint16_t *) &state.h; - state.bc = (uint16_t *) &state.b; - state.de = (uint16_t *) &state.d; -#endif - - state.sp = 0xffff; - state.a = 0xff; - - state.b = 0x7f; - state.c = 0xbc; - state.d = 0x00; - state.e = 0x00; - state.h = 0x34; - state.l = 0xc0; - - regs_dst = malloc(8 * sizeof(uint8_t *)); - - regs_dst[0x00] = &state.b; - regs_dst[0x01] = &state.c; - regs_dst[0x02] = &state.d; - regs_dst[0x03] = &state.e; - regs_dst[0x04] = &state.h; - regs_dst[0x05] = &state.l; - regs_dst[0x06] = &dummy; - regs_dst[0x07] = &state.a; - - regs_src = malloc(8 * sizeof(uint8_t *)); - - regs_src[0x00] = &state.b; - regs_src[0x01] = &state.c; - regs_src[0x02] = &state.d; - regs_src[0x03] = &state.e; - regs_src[0x04] = &state.h; - regs_src[0x05] = &state.l; - regs_src[0x06] = mmu_addr(*state.hl); - regs_src[0x07] = &state.a; - - state.flags.cy = 1; - state.flags.n = 1; - state.flags.ac = 1; - state.flags.z = 1; - - /* flags shortcut */ - state.f = (uint8_t *) &state.flags; - - /* flags mask array */ - z80_calc_flags_mask_array(); - - return &state; -} diff --git a/waterbox/pizza/lib/z80_gameboy_regs.h b/waterbox/pizza/lib/z80_gameboy_regs.h deleted file mode 100644 index 6b403005f1..0000000000 --- a/waterbox/pizza/lib/z80_gameboy_regs.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - - This file is part of Emu-Pizza - - Emu-Pizza is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Emu-Pizza is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Emu-Pizza. If not, see . - -*/ - - -#ifndef Z80_REGS_H -#define Z80_REGS_H - -#include - -/* structs emulating z80 registers and flags */ -typedef struct z80_flags_s -{ - uint8_t spare:4; - uint8_t cy:1; - uint8_t ac:1; - uint8_t n:1; - uint8_t z:1; -} z80_flags_t; - - -/* flags offsets */ -#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ - - #define FLAG_OFFSET_CY 4 - #define FLAG_OFFSET_AC 5 - #define FLAG_OFFSET_N 6 - #define FLAG_OFFSET_Z 7 - -#endif - - -#endif diff --git a/waterbox/pizza/pizza.c b/waterbox/pizza/pizza.c deleted file mode 100644 index e88a33d59a..0000000000 --- a/waterbox/pizza/pizza.c +++ /dev/null @@ -1,194 +0,0 @@ -/* - - This file is part of Emu-Pizza - - Emu-Pizza is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Emu-Pizza is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Emu-Pizza. If not, see . - -*/ - -#include -#include -#include -#include "../emulibc/emulibc.h" -#include "../emulibc/waterboxcore.h" -#include - -#define EXPORT ECL_EXPORT - -#include "cartridge.h" -#include "cycles.h" -#include "gameboy.h" -#include "global.h" -#include "gpu.h" -#include "input.h" -#include "sound.h" -#include "serial.h" -#include "utils.h" -#include "mmu.h" -#include "sound_output.h" -#include "sgb.h" - -/* proto */ -void frame_cb(); -void connected_cb(); -void disconnected_cb(); -void rumble_cb(uint8_t rumble); -void network_send_data(uint8_t v); -void *start_thread(void *args); -void *start_thread_network(void *args); - -/* cartridge name */ -char cart_name[64]; - -int main(void) -{ -} - -EXPORT int Init(const void *rom, int romlen, int sgb, const void *spc, int spclen) -{ - /* init global variables */ - global_init(); - - /* first, load cartridge */ - char ret = cartridge_load(rom, romlen); - - if (ret != 0) - return 0; // failure - global_sgb = !!sgb; - if (global_sgb && global_cgb) - utils_log("Warn: CGB game in SGB mode\n"); - if (sgb && !sgb_init((const uint8_t*)spc, spclen)) - return 0; - - gameboy_init(); - - /* init GPU */ - gpu_init(frame_cb); - - /* set rumble cb */ - mmu_set_rumble_cb(&rumble_cb); - - sound_output_init(global_sgb ? 2147727 : 2097152, 44100); - - return 1; -} - -typedef struct -{ - uint32_t *VideoBuffer; - int16_t *SoundBuffer; - int64_t Cycles; - int32_t Width; - int32_t Height; - int32_t Samples; - int32_t Lagged; - int64_t Time; - uint32_t Keys; -} MyFrameInfo; - -static uint32_t *current_vbuff; -static uint64_t overflow; - -EXPORT void FrameAdvance(MyFrameInfo *frame) -{ - if (global_sgb) - sgb_set_controller_data((uint8_t *)&frame->Keys); - else - input_set_keys(frame->Keys); - current_vbuff = frame->VideoBuffer; - global_lagged = 1; - global_currenttime = frame->Time; - - uint64_t current = cycles.sampleclock; - uint64_t target = current + 35112 - overflow; - gameboy_run(target); - uint64_t elapsed = cycles.sampleclock - current; - frame->Cycles = elapsed; - overflow = cycles.sampleclock - target; - - frame->Samples = sound_output_read(frame->SoundBuffer); - if (global_sgb) - { - frame->Width = 256; - frame->Height = 224; - } - else - { - frame->Width = 160; - frame->Height = 144; - } - frame->Lagged = global_lagged; - current_vbuff = NULL; -} - -EXPORT int IsCGB(void) -{ - return global_cgb; -} - -EXPORT void SetInputCallback(void (*callback)(void)) -{ - global_input_callback = callback; -} - -EXPORT void GetMemoryAreas(MemoryArea *m) -{ - m[0].Data = mmu.memory; - m[0].Name = "Fake System Bus"; - m[0].Size = 0x10000; - m[0].Flags = MEMORYAREA_FLAGS_PRIMARY | MEMORYAREA_FLAGS_WRITABLE | MEMORYAREA_FLAGS_WORDSIZE1; -} - -EXPORT int GetSaveramSize(void) -{ - return mmu_saveram_size(); -} - -EXPORT void PutSaveram(const uint8_t* data, int size) -{ - mmu_restore_saveram(data, size); -} - -EXPORT void GetSaveram(uint8_t* data, int size) -{ - mmu_save_saveram(data, size); -} - -void frame_cb() -{ - if (global_sgb) - { - sgb_render_frame(current_vbuff); - } - else - { - memcpy(current_vbuff, gpu.frame_buffer, sizeof(gpu.frame_buffer)); - } -} - -void connected_cb() -{ - utils_log("Connected\n"); -} - -void disconnected_cb() -{ - utils_log("Disconnected\n"); -} - -void rumble_cb(uint8_t rumble) -{ - if (rumble) - printf("RUMBLE\n"); -} diff --git a/waterbox/pizza/.vscode/settings.json b/waterbox/sameboy/.vscode/settings.json similarity index 99% rename from waterbox/pizza/.vscode/settings.json rename to waterbox/sameboy/.vscode/settings.json index d5073385ae..a5401e1c1f 100644 --- a/waterbox/pizza/.vscode/settings.json +++ b/waterbox/sameboy/.vscode/settings.json @@ -1,6 +1,6 @@ // Place your settings in this file to overwrite default and user settings. { - "editor.insertSpaces": false, "editor.tabSize": 4, + "editor.insertSpaces": false, "editor.detectIndentation": false } \ No newline at end of file diff --git a/waterbox/sameboy/CHANGES.md b/waterbox/sameboy/CHANGES.md new file mode 100644 index 0000000000..b94aec4c71 --- /dev/null +++ b/waterbox/sameboy/CHANGES.md @@ -0,0 +1 @@ +See https://sameboy.github.io/changelog/ \ No newline at end of file diff --git a/waterbox/sameboy/LICENSE b/waterbox/sameboy/LICENSE new file mode 100644 index 0000000000..008851f512 --- /dev/null +++ b/waterbox/sameboy/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2015-2017 Lior Halphon + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/waterbox/pizza/Makefile b/waterbox/sameboy/Makefile similarity index 79% rename from waterbox/pizza/Makefile rename to waterbox/sameboy/Makefile index 4893bc03f3..e694a321e1 100644 --- a/waterbox/pizza/Makefile +++ b/waterbox/sameboy/Makefile @@ -2,17 +2,17 @@ CC = x86_64-nt64-midipix-gcc CPP = x86_64-nt64-midipix-g++ FLAGS:=-Wall -Werror=pointer-to-int-cast -Werror=int-to-pointer-cast -Werror=implicit-function-declaration \ - -fomit-frame-pointer -fvisibility=hidden \ + -Wno-multichar \ + -fomit-frame-pointer \ -O3 -flto -CCFLAGS:=$(FLAGS) -Ilib \ - -I../emulibc \ - -std=c99 \ - -DLSB_FIRST -D_GNU_SOURCE +CCFLAGS:=$(FLAGS) \ + -std=gnu99 \ + -DLSB_FIRST -D_GNU_SOURCE -DGB_INTERNAL -CPPFLAGS:=$(FLAGS) -DSPC_NO_COPY_STATE_FUNCS +CPPFLAGS:=$(FLAGS) -DSPC_NO_COPY_STATE_FUNCS -std=c++0x -D_GNU_SOURCE -DGB_INTERNAL -TARGET = pizza.wbx +TARGET = sameboy.wbx LDFLAGS = -Wl,--dynamicbase,--export-all-symbols diff --git a/waterbox/sameboy/README.md b/waterbox/sameboy/README.md new file mode 100644 index 0000000000..9aa5201b63 --- /dev/null +++ b/waterbox/sameboy/README.md @@ -0,0 +1,51 @@ +# SameBoy + +SameBoy is an open source Gameboy (DMG) and Gameboy Color (CGB) emulator, written in portable C. It has a native Cocoa frontend for OS X, and an incomplete experimental SDL frontend for other operating systems. It also includes a text-based debugger with an expression evaluator. Visit [the website](https://sameboy.github.io/). + +## Features +Features common to both Cocoa and SDL versions: + * Supports Gameboy (DMG) and Gameboy Color (CGB) emulation + * Lets you choose the model you want to emulate regardless of ROM + * High quality 96KHz audio + * Battery save support + * Save states + * Includes open source DMG and CGB boot ROMs: + * Complete support for (and documentation of) *all* game-specific palettes in the CGB boot ROM, for accurate emulation of Gameboy games on a Gameboy Color + * Supports manual palette selection with key combinations, with 4 additional new palettes (A + B + direction) + * Supports palette selection in a CGB game, forcing it to run in 'paletted' DMG mode, if ROM allows doing so. + * Support for games with a non-Nintendo logo in the header + * No long animation in the DMG boot + * Advanced text-based debugger with an expression evaluator, disassembler, conditional breakpoints, conditional watchpoints, backtracing and other features + * Emulates [PCM_12 and PCM_34 registers](https://github.com/LIJI32/GBVisualizer) + * Emulates LCD timing effects, supporting the Demotronic trick, [GBVideoPlayer](https://github.com/LIJI32/GBVideoPlayer) and other tech demos + * Extermely high accuracy + * Real time clock emulation + +Features currently supported only with the Cocoa version: + * Native Cocoa interface, with support for all system-wide features, such as drag-and-drop and smart titlebars + * Retina display support, allowing a wider range of scaling factors without artifacts + * Optional frame blending + * Several [scaling algorithms](https://sameboy.github.io/scaling/) (Including exclusive algorithms like OmniScale and Anti-aliased Scale2x) + * GameBoy Camera support + +[Read more](https://sameboy.github.io/features/). + +## Compatibility +SameBoy passes many of [blargg's test ROMs](http://gbdev.gg8.se/wiki/articles/Test_ROMs#Blargg.27s_tests), as well as 77 out of 78 of [mooneye-gb's](https://github.com/Gekkio/mooneye-gb) tests (Some tests require the original boot ROMs). SameBoy should work with most games and demos, please [report](https://github.com/LIJI32/SameBoy/issues/new) any broken ROM. The latest results for SameBoy's automatic tester are available [here](https://sameboy.github.io/automation/). + +## Compilation +SameBoy requires the following tools and libraries to build: + * clang + * make + * Cocoa port: OS X SDK and Xcode command line tools + * SDL port: SDL2.framework (OS X) or libsdl2 (Other platforms) + * [rgbds](https://github.com/bentley/rgbds/releases/), for boot ROM compilation + +On Windows, SameBoy also requires: + * Visual Studio (For headers, etc.) + * [GnuWin](http://gnuwin32.sourceforge.net/) + * Running vcvars32 before running make. Make sure all required tools and libraries are in %PATH% and %lib%, repsectively. + +To compile, simply run `make`. The targets are cocoa (Default for OS X), sdl (Default for everything else), bootroms and tester. You may also specify CONF=debug (default), CONF=release or CONF=native_release to control optimization and symbols. native_release is faster than release, but is optimized to the host's CPU and therefore is not portable. You may set BOOTROMS_DIR=... to a directory containing precompiled dmg_boot.bin and cgb_boot.bin files, otherwise the build system will compile and use SameBoy's own boot ROMs. + +SameBoy was compiled and tested on macOS, Ubuntu and 32-bit Windows 7. diff --git a/waterbox/sameboy/apu.c b/waterbox/sameboy/apu.c new file mode 100644 index 0000000000..10b5bf9bea --- /dev/null +++ b/waterbox/sameboy/apu.c @@ -0,0 +1,402 @@ +#include +#include +#include +#include "gb.h" + +#undef max +#define max(a,b) \ +({ __typeof__ (a) _a = (a); \ +__typeof__ (b) _b = (b); \ +_a > _b ? _a : _b; }) + +#undef min +#define min(a,b) \ +({ __typeof__ (a) _a = (a); \ +__typeof__ (b) _b = (b); \ +_a < _b ? _a : _b; }) + +#define APU_FREQUENCY 0x80000 + +static int16_t generate_square(uint64_t phase, uint32_t wave_length, int16_t amplitude, uint8_t duty) +{ + if (!wave_length) return 0; + if (phase % wave_length > wave_length * duty / 8) { + return amplitude; + } + return 0; +} + +static int16_t generate_wave(uint64_t phase, uint32_t wave_length, int16_t amplitude, int8_t *wave, uint8_t shift) +{ + if (!wave_length) wave_length = 1; + phase = phase % wave_length; + return ((wave[(int)(phase * 32 / wave_length)]) >> shift) * (int)amplitude / 0xF; +} + +static int16_t generate_noise(int16_t amplitude, uint16_t lfsr) +{ + if (lfsr & 1) { + return amplitude; + } + return 0; +} + +static int16_t step_lfsr(uint16_t lfsr, bool uses_7_bit) +{ + bool xor = (lfsr & 1) ^ ((lfsr & 2) >> 1); + lfsr >>= 1; + if (xor) { + lfsr |= 0x4000; + } + if (uses_7_bit) { + lfsr &= ~0x40; + if (xor) { + lfsr |= 0x40; + } + } + return lfsr; +} + +/* General Todo: The APU emulation seems to fail many accuracy tests. It might require a rewrite with + these tests in mind. */ + +static void GB_apu_run_internal(GB_gameboy_t *gb) +{ + uint32_t steps = gb->apu.apu_cycles / (CPU_FREQUENCY/APU_FREQUENCY); + if (!steps) + return; + + gb->apu.apu_cycles %= (CPU_FREQUENCY/APU_FREQUENCY); + for (uint8_t i = 0; i < 4; i++) { + /* Phase */ + gb->apu.wave_channels[i].phase += steps; + while (gb->apu.wave_channels[i].wave_length && gb->apu.wave_channels[i].phase >= gb->apu.wave_channels[i].wave_length) { + if (i == 3) { + gb->apu.lfsr = step_lfsr(gb->apu.lfsr, gb->apu.lfsr_7_bit); + } + + gb->apu.wave_channels[i].phase -= gb->apu.wave_channels[i].wave_length; + } + /* Stop on Length */ + if (gb->apu.wave_channels[i].stop_on_length) { + if (gb->apu.wave_channels[i].sound_length > 0) { + gb->apu.wave_channels[i].sound_length -= steps; + } + if (gb->apu.wave_channels[i].sound_length <= 0) { + gb->apu.wave_channels[i].amplitude = 0; + gb->apu.wave_channels[i].is_playing = false; + gb->apu.wave_channels[i].sound_length = i == 2? APU_FREQUENCY : APU_FREQUENCY / 4; + } + } + } + + gb->apu.envelope_step_timer += steps; + while (gb->apu.envelope_step_timer >= APU_FREQUENCY / 64) { + gb->apu.envelope_step_timer -= APU_FREQUENCY / 64; + for (uint8_t i = 0; i < 4; i++) { + if (gb->apu.wave_channels[i].envelope_steps && !--gb->apu.wave_channels[i].cur_envelope_steps) { + gb->apu.wave_channels[i].amplitude = min(max(gb->apu.wave_channels[i].amplitude + gb->apu.wave_channels[i].envelope_direction * CH_STEP, 0), MAX_CH_AMP); + gb->apu.wave_channels[i].cur_envelope_steps = gb->apu.wave_channels[i].envelope_steps; + } + } + } + + gb->apu.sweep_step_timer += steps; + while (gb->apu.sweep_step_timer >= APU_FREQUENCY / 128) { + gb->apu.sweep_step_timer -= APU_FREQUENCY / 128; + if (gb->apu.wave_channels[0].sweep_steps && !--gb->apu.wave_channels[0].cur_sweep_steps) { + + // Convert back to GB format + uint16_t temp = 2048 - gb->apu.wave_channels[0].wave_length / (APU_FREQUENCY / 131072); + + // Apply sweep + temp = temp + gb->apu.wave_channels[0].sweep_direction * + (temp / (1 << gb->apu.wave_channels[0].sweep_shift)); + if (temp > 2047) { + temp = 0; + } + + // Back to frequency + gb->apu.wave_channels[0].wave_length = (2048 - temp) * (APU_FREQUENCY / 131072); + gb->apu.wave_channels[0].cur_sweep_steps = gb->apu.wave_channels[0].sweep_steps; + } + } +} + +void GB_apu_get_samples_and_update_pcm_regs(GB_gameboy_t *gb, GB_sample_t *samples) +{ + GB_apu_run_internal(gb); + + samples->left = samples->right = 0; + if (!gb->apu.global_enable) { + return; + } + + gb->io_registers[GB_IO_PCM_12] = 0; + gb->io_registers[GB_IO_PCM_34] = 0; + + { + int16_t sample = generate_square(gb->apu.wave_channels[0].phase, + gb->apu.wave_channels[0].wave_length, + gb->apu.wave_channels[0].amplitude, + gb->apu.wave_channels[0].duty); + if (gb->apu.wave_channels[0].left_on ) samples->left += sample; + if (gb->apu.wave_channels[0].right_on) samples->right += sample; + gb->io_registers[GB_IO_PCM_12] = ((int)sample) * 0xF / MAX_CH_AMP; + } + + { + int16_t sample = generate_square(gb->apu.wave_channels[1].phase, + gb->apu.wave_channels[1].wave_length, + gb->apu.wave_channels[1].amplitude, + gb->apu.wave_channels[1].duty); + if (gb->apu.wave_channels[1].left_on ) samples->left += sample; + if (gb->apu.wave_channels[1].right_on) samples->right += sample; + gb->io_registers[GB_IO_PCM_12] |= (((int)sample) * 0xF / MAX_CH_AMP) << 4; + } + + if (gb->apu.wave_channels[2].is_playing) + { + int16_t sample = generate_wave(gb->apu.wave_channels[2].phase, + gb->apu.wave_channels[2].wave_length, + MAX_CH_AMP, + gb->apu.wave_form, + gb->apu.wave_shift); + if (gb->apu.wave_channels[2].left_on ) samples->left += sample; + if (gb->apu.wave_channels[2].right_on) samples->right += sample; + gb->io_registers[GB_IO_PCM_34] = ((int)sample) * 0xF / MAX_CH_AMP; + } + + { + int16_t sample = generate_noise(gb->apu.wave_channels[3].amplitude, + gb->apu.lfsr); + if (gb->apu.wave_channels[3].left_on ) samples->left += sample; + if (gb->apu.wave_channels[3].right_on) samples->right += sample; + gb->io_registers[GB_IO_PCM_34] |= (((int)sample) * 0xF / MAX_CH_AMP) << 4; + } + + samples->left = (int) samples->left * gb->apu.left_volume / 7; + samples->right = (int) samples->right * gb->apu.right_volume / 7; +} + +void GB_apu_run(GB_gameboy_t *gb) +{ + GB_sample_t sample; + GB_apu_get_samples_and_update_pcm_regs(gb, &sample); + gb->sample_callback(gb, sample, gb->cycles_since_epoch); +} + +void GB_apu_init(GB_gameboy_t *gb) +{ + memset(&gb->apu, 0, sizeof(gb->apu)); + gb->apu.wave_channels[0].duty = gb->apu.wave_channels[1].duty = 4; + gb->apu.lfsr = 0x7FFF; + gb->apu.left_volume = 7; + gb->apu.right_volume = 7; + for (int i = 0; i < 4; i++) { + gb->apu.wave_channels[i].left_on = gb->apu.wave_channels[i].right_on = 1; + } +} + +uint8_t GB_apu_read(GB_gameboy_t *gb, uint8_t reg) +{ + GB_apu_run_internal(gb); + + if (reg == GB_IO_NR52) { + uint8_t value = 0; + for (int i = 0; i < 4; i++) { + value >>= 1; + if (gb->apu.wave_channels[i].is_playing) { + value |= 0x8; + } + } + if (gb->apu.global_enable) { + value |= 0x80; + } + value |= 0x70; + return value; + } + + static const char read_mask[GB_IO_WAV_END - GB_IO_NR10 + 1] = { + /* NRX0 NRX1 NRX2 NRX3 NRX4 */ + 0x80, 0x3F, 0x00, 0xFF, 0xBF, // NR1X + 0xFF, 0x3F, 0x00, 0xFF, 0xBF, // NR2X + 0x7F, 0xFF, 0x9F, 0xFF, 0xBF, // NR3X + 0xFF, 0xFF, 0x00, 0x00, 0xBF, // NR4X + 0x00, 0x00, 0x70, 0xFF, 0xFF, // NR5X + + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // Unused + // Wave RAM + 0, /* ... */ + }; + + if (reg >= GB_IO_WAV_START && reg <= GB_IO_WAV_END && gb->apu.wave_channels[2].is_playing) { + if (gb->apu.wave_channels[2].wave_length == 0) { + return gb->apu.wave_form[0]; + } + gb->apu.wave_channels[2].phase %= gb->apu.wave_channels[2].wave_length; + return gb->apu.wave_form[(int)(gb->apu.wave_channels[2].phase * 32 / gb->apu.wave_channels[2].wave_length)]; + } + + return gb->io_registers[reg] | read_mask[reg - GB_IO_NR10]; +} + +void GB_apu_write(GB_gameboy_t *gb, uint8_t reg, uint8_t value) +{ + GB_apu_run_internal(gb); + + static const uint8_t duties[] = {1, 2, 4, 6}; /* Values are in 1/8 */ + uint8_t channel = 0; + + if (!gb->apu.global_enable && reg != GB_IO_NR52) { + return; + } + + gb->io_registers[reg] = value; + + switch (reg) { + case GB_IO_NR10: + case GB_IO_NR11: + case GB_IO_NR12: + case GB_IO_NR13: + case GB_IO_NR14: + channel = 0; + break; + case GB_IO_NR21: + case GB_IO_NR22: + case GB_IO_NR23: + case GB_IO_NR24: + channel = 1; + break; + case GB_IO_NR33: + case GB_IO_NR34: + channel = 2; + break; + case GB_IO_NR41: + case GB_IO_NR42: + channel = 3; + default: + break; + } + + switch (reg) { + case GB_IO_NR10: + gb->apu.wave_channels[channel].sweep_direction = value & 8? -1 : 1; + gb->apu.wave_channels[channel].cur_sweep_steps = + gb->apu.wave_channels[channel].sweep_steps = (value & 0x70) >> 4; + gb->apu.wave_channels[channel].sweep_shift = value & 7; + break; + case GB_IO_NR11: + case GB_IO_NR21: + case GB_IO_NR41: + gb->apu.wave_channels[channel].duty = duties[value >> 6]; + gb->apu.wave_channels[channel].sound_length = (64 - (value & 0x3F)) * (APU_FREQUENCY / 256); + if (gb->apu.wave_channels[channel].sound_length == 0) { + gb->apu.wave_channels[channel].is_playing = false; + } + break; + case GB_IO_NR12: + case GB_IO_NR22: + case GB_IO_NR42: + gb->apu.wave_channels[channel].start_amplitude = + gb->apu.wave_channels[channel].amplitude = CH_STEP * (value >> 4); + if (value >> 4 == 0) { + gb->apu.wave_channels[channel].is_playing = false; + } + gb->apu.wave_channels[channel].envelope_direction = value & 8? 1 : -1; + gb->apu.wave_channels[channel].cur_envelope_steps = + gb->apu.wave_channels[channel].envelope_steps = value & 7; + break; + case GB_IO_NR13: + case GB_IO_NR23: + case GB_IO_NR33: + gb->apu.wave_channels[channel].NRX3_X4_temp = (gb->apu.wave_channels[channel].NRX3_X4_temp & 0xFF00) | value; + gb->apu.wave_channels[channel].wave_length = (2048 - gb->apu.wave_channels[channel].NRX3_X4_temp) * (APU_FREQUENCY / 131072); + if (channel == 2) { + gb->apu.wave_channels[channel].wave_length *= 2; + } + break; + case GB_IO_NR14: + case GB_IO_NR24: + case GB_IO_NR34: + gb->apu.wave_channels[channel].stop_on_length = value & 0x40; + if ((value & 0x80) && (channel != 2 || gb->apu.wave_enable)) { + gb->apu.wave_channels[channel].is_playing = true; + gb->apu.wave_channels[channel].phase = 0; + gb->apu.wave_channels[channel].amplitude = gb->apu.wave_channels[channel].start_amplitude; + gb->apu.wave_channels[channel].cur_envelope_steps = gb->apu.wave_channels[channel].envelope_steps; + } + + gb->apu.wave_channels[channel].NRX3_X4_temp = (gb->apu.wave_channels[channel].NRX3_X4_temp & 0xFF) | ((value & 0x7) << 8); + gb->apu.wave_channels[channel].wave_length = (2048 - gb->apu.wave_channels[channel].NRX3_X4_temp) * (APU_FREQUENCY / 131072); + if (channel == 2) { + gb->apu.wave_channels[channel].wave_length *= 2; + } + break; + case GB_IO_NR30: + gb->apu.wave_enable = value & 0x80; + gb->apu.wave_channels[2].is_playing &= gb->apu.wave_enable; + break; + case GB_IO_NR31: + gb->apu.wave_channels[2].sound_length = (256 - value) * (APU_FREQUENCY / 256); + if (gb->apu.wave_channels[2].sound_length == 0) { + gb->apu.wave_channels[2].is_playing = false; + } + break; + case GB_IO_NR32: + gb->apu.wave_shift = ((value >> 5) + 3) & 3; + if (gb->apu.wave_shift == 3) { + gb->apu.wave_shift = 4; + } + break; + case GB_IO_NR43: + { + double r = value & 0x7; + if (r == 0) r = 0.5; + uint8_t s = value >> 4; + gb->apu.wave_channels[3].wave_length = r * (1 << s) * (APU_FREQUENCY / 262144) ; + gb->apu.lfsr_7_bit = value & 0x8; + break; + } + case GB_IO_NR44: + gb->apu.wave_channels[3].stop_on_length = value & 0x40; + if (value & 0x80) { + gb->apu.wave_channels[3].is_playing = true; + gb->apu.lfsr = 0x7FFF; + gb->apu.wave_channels[3].amplitude = gb->apu.wave_channels[3].start_amplitude; + gb->apu.wave_channels[3].cur_envelope_steps = gb->apu.wave_channels[3].envelope_steps; + } + break; + + case GB_IO_NR50: + gb->apu.left_volume = (value & 7); + gb->apu.right_volume = ((value >> 4) & 7); + break; + + case GB_IO_NR51: + for (int i = 0; i < 4; i++) { + gb->apu.wave_channels[i].left_on = value & 1; + gb->apu.wave_channels[i].right_on = value & 0x10; + value >>= 1; + } + break; + case GB_IO_NR52: + + if ((value & 0x80) && !gb->apu.global_enable) { + GB_apu_init(gb); + gb->apu.global_enable = true; + } + else if (!(value & 0x80) && gb->apu.global_enable) { + memset(&gb->apu, 0, sizeof(gb->apu)); + memset(gb->io_registers + GB_IO_NR10, 0, GB_IO_WAV_START - GB_IO_NR10); + } + break; + + default: + if (reg >= GB_IO_WAV_START && reg <= GB_IO_WAV_END) { + gb->apu.wave_form[(reg - GB_IO_WAV_START) * 2] = value >> 4; + gb->apu.wave_form[(reg - GB_IO_WAV_START) * 2 + 1] = value & 0xF; + } + break; + } +} diff --git a/waterbox/sameboy/apu.h b/waterbox/sameboy/apu.h new file mode 100644 index 0000000000..a8eab55fd6 --- /dev/null +++ b/waterbox/sameboy/apu.h @@ -0,0 +1,65 @@ +#ifndef apu_h +#define apu_h +#include +#include +#include "gb_struct_def.h" +/* Divides nicely and never overflows with 4 channels */ +#define MAX_CH_AMP 0x1E00 +#define CH_STEP (0x1E00/0xF) + + +typedef struct +{ + int16_t left; + int16_t right; +} GB_sample_t; + +/* Not all used on all channels */ +/* All lengths are in APU ticks */ +typedef struct +{ + uint32_t phase; + uint32_t wave_length; + int32_t sound_length; + bool stop_on_length; + uint8_t duty; + int16_t amplitude; + int16_t start_amplitude; + uint8_t envelope_steps; + uint8_t cur_envelope_steps; + int8_t envelope_direction; + uint8_t sweep_steps; + uint8_t cur_sweep_steps; + int8_t sweep_direction; + uint8_t sweep_shift; + bool is_playing; + uint16_t NRX3_X4_temp; + bool left_on; + bool right_on; +} GB_apu_channel_t; + +typedef struct +{ + uint16_t apu_cycles; + bool global_enable; + uint32_t envelope_step_timer; + uint32_t sweep_step_timer; + int8_t wave_form[32]; + uint8_t wave_shift; + bool wave_enable; + uint16_t lfsr; + bool lfsr_7_bit; + uint8_t left_volume; + uint8_t right_volume; + GB_apu_channel_t wave_channels[4]; +} GB_apu_t; + +#ifdef GB_INTERNAL +void GB_apu_write(GB_gameboy_t *gb, uint8_t reg, uint8_t value); +uint8_t GB_apu_read(GB_gameboy_t *gb, uint8_t reg); +void GB_apu_get_samples_and_update_pcm_regs(GB_gameboy_t *gb, GB_sample_t *samples); +void GB_apu_init(GB_gameboy_t *gb); +void GB_apu_run(GB_gameboy_t *gb); +#endif + +#endif /* apu_h */ diff --git a/waterbox/sameboy/bizhawk.cpp b/waterbox/sameboy/bizhawk.cpp new file mode 100644 index 0000000000..28c6cda11e --- /dev/null +++ b/waterbox/sameboy/bizhawk.cpp @@ -0,0 +1,251 @@ +#include +#include "../emulibc/emulibc.h" +#include "../emulibc/waterboxcore.h" +#include "blip_buf/blip_buf.h" + +#define _Static_assert static_assert + +extern "C" { +#include "gb.h" +#include "joypad.h" +#include "apu.h" +#include "sgb.h" +} + +static GB_gameboy_t GB; + +static uint32_t GBPixels[160 * 144]; +static uint32_t *CurrentFramebuffer; +static bool sgb; +static void VBlankCallback(GB_gameboy_t *gb) +{ + if (sgb) + { + sgb_take_frame(GBPixels); + sgb_render_frame(CurrentFramebuffer); + } + else + { + memcpy(CurrentFramebuffer, GBPixels, sizeof(GBPixels)); + } +} + +static void LogCallback(GB_gameboy_t *gb, const char *string, GB_log_attributes attributes) +{ + fputs(string, stdout); +} + +static uint32_t RgbEncodeCallback(GB_gameboy_t *gb, uint8_t r, uint8_t g, uint8_t b) +{ + return b | g << 8 | r << 16 | 0xff000000; +} + +static void InfraredCallback(GB_gameboy_t *gb, bool on, long cycles_since_last_update) +{ +} + +static void RumbleCallback(GB_gameboy_t *gb, bool rumble_on) +{ +} + +static void SerialStartCallback(GB_gameboy_t *gb, uint8_t byte_to_send) +{ +} + +static uint8_t SerialEndCallback(GB_gameboy_t *gb) +{ + return 0; +} + +static void (*FrontendInputCallback)(); + +static void InputCallback(GB_gameboy_t *gb) +{ + FrontendInputCallback(); +} + +static blip_t *leftblip; +static blip_t *rightblip; +const int SOUND_RATE_GB = 2097152; +const int SOUND_RATE_SGB = 2147727; +static uint64_t sound_start_clock; +static GB_sample_t sample_gb; +static GB_sample_t sample_sgb; + +static void SampleCallback(GB_gameboy_t *gb, GB_sample_t sample, uint64_t clock) +{ + int l = sample.left - sample_gb.left; + int r = sample.right - sample_gb.right; + if (l) + blip_add_delta(leftblip, clock - sound_start_clock, l); + if (r) + blip_add_delta(rightblip, clock - sound_start_clock, r); + sample_gb = sample; +} +static void SgbSampleCallback(int16_t sl, int16_t sr, uint64_t clock) +{ + int l = sl - sample_sgb.left; + int r = sr - sample_sgb.right; + if (l) + blip_add_delta(leftblip, clock - sound_start_clock, l); + if (r) + blip_add_delta(rightblip, clock - sound_start_clock, r); + sample_sgb.left = sl; + sample_sgb.right = sr; +} + +ECL_EXPORT bool Init(bool cgb, const uint8_t *spc, int spclen) +{ + if (spc) + { + GB_init_sgb(&GB); + if (!sgb_init(spc, spclen)) + return false; + sgb = true; + } + else if (cgb) + { + GB_init_cgb(&GB); + } + else + { + GB_init(&GB); + } + + if (GB_load_boot_rom(&GB, "boot.rom") != 0) + return false; + if (GB_load_rom(&GB, "game.rom") != 0) + return false; + + GB_set_pixels_output(&GB, GBPixels); + GB_set_vblank_callback(&GB, VBlankCallback); + GB_set_log_callback(&GB, LogCallback); + GB_set_rgb_encode_callback(&GB, RgbEncodeCallback); + GB_set_infrared_callback(&GB, InfraredCallback); + GB_set_rumble_callback(&GB, RumbleCallback); + GB_set_sample_callback(&GB, SampleCallback); + + leftblip = blip_new(1024); + rightblip = blip_new(1024); + blip_set_rates(leftblip, sgb ? SOUND_RATE_SGB : SOUND_RATE_GB, 44100); + blip_set_rates(rightblip, sgb ? SOUND_RATE_SGB : SOUND_RATE_GB, 44100); + + return true; +} + +struct MyFrameInfo : public FrameInfo +{ + int64_t Time; + uint32_t Keys; +}; + +static int FrameOverflow; + +ECL_EXPORT void FrameAdvance(MyFrameInfo &f) +{ + if (sgb) + { + sgb_set_controller_data((uint8_t *)&f.Keys); + } + else + { + GB_set_key_state(&GB, f.Keys & 0xff); + } + sound_start_clock = GB_epoch(&GB); + CurrentFramebuffer = f.VideoBuffer; + GB_set_lagged(&GB, true); + GB.frontend_rtc_time = f.Time; + + uint32_t target = 35112 - FrameOverflow; + f.Cycles = GB_run_cycles(&GB, target); + FrameOverflow = f.Cycles - target; + if (sgb) + { + f.Width = 256; + f.Height = 224; + sgb_render_audio(GB_epoch(&GB), SgbSampleCallback); + } + else + { + f.Width = 160; + f.Height = 144; + } + blip_end_frame(leftblip, f.Cycles); + blip_end_frame(rightblip, f.Cycles); + f.Samples = blip_read_samples(leftblip, f.SoundBuffer, 2048, 1); + blip_read_samples(rightblip, f.SoundBuffer + 1, 2048, 1); + CurrentFramebuffer = NULL; + f.Lagged = GB_get_lagged(&GB); +} + +static void SetMemoryArea(MemoryArea *m, GB_direct_access_t access, const char *name, int32_t flags) +{ + size_t size; + m->Name = name; + m->Data = GB_get_direct_access(&GB, access, &size, nullptr); + m->Size = size; + m->Flags = flags; +} + +ECL_EXPORT void GetMemoryAreas(MemoryArea *m) +{ + // TODO: "System Bus" + SetMemoryArea(m + 0, GB_DIRECT_ACCESS_RAM, "WRAM", MEMORYAREA_FLAGS_WORDSIZE1 | MEMORYAREA_FLAGS_WRITABLE | MEMORYAREA_FLAGS_PRIMARY); + SetMemoryArea(m + 1, GB_DIRECT_ACCESS_ROM, "ROM", MEMORYAREA_FLAGS_WORDSIZE1); + SetMemoryArea(m + 2, GB_DIRECT_ACCESS_VRAM, "VRAM", MEMORYAREA_FLAGS_WORDSIZE1 | MEMORYAREA_FLAGS_WRITABLE); + SetMemoryArea(m + 3, GB_DIRECT_ACCESS_CART_RAM, "CartRAM", MEMORYAREA_FLAGS_WORDSIZE1 | MEMORYAREA_FLAGS_WRITABLE); + SetMemoryArea(m + 4, GB_DIRECT_ACCESS_OAM, "OAM", MEMORYAREA_FLAGS_WORDSIZE1 | MEMORYAREA_FLAGS_WRITABLE); + SetMemoryArea(m + 5, GB_DIRECT_ACCESS_HRAM, "HRAM", MEMORYAREA_FLAGS_WORDSIZE1 | MEMORYAREA_FLAGS_WRITABLE); + SetMemoryArea(m + 6, GB_DIRECT_ACCESS_IO, "IO", MEMORYAREA_FLAGS_WORDSIZE1); + SetMemoryArea(m + 7, GB_DIRECT_ACCESS_BOOTROM, "BOOTROM", MEMORYAREA_FLAGS_WORDSIZE1); + SetMemoryArea(m + 8, GB_DIRECT_ACCESS_BGP, "BGP", MEMORYAREA_FLAGS_WORDSIZE1 | MEMORYAREA_FLAGS_WRITABLE); + SetMemoryArea(m + 9, GB_DIRECT_ACCESS_OBP, "OBP", MEMORYAREA_FLAGS_WORDSIZE1 | MEMORYAREA_FLAGS_WRITABLE); +} + +ECL_EXPORT void SetInputCallback(void (*callback)()) +{ + FrontendInputCallback = callback; + GB_set_input_callback(&GB, callback ? InputCallback : nullptr); +} + +ECL_EXPORT void GetGpuMemory(void **p) +{ + p[0] = GB_get_direct_access(&GB, GB_DIRECT_ACCESS_VRAM, nullptr, nullptr); + p[1] = GB_get_direct_access(&GB, GB_DIRECT_ACCESS_OAM, nullptr, nullptr); + p[2] = GB.background_palettes_rgb; + p[3] = GB.sprite_palettes_rgb; +} + +ECL_EXPORT void SetScanlineCallback(void (*callback)(uint8_t), int ly) +{ + GB.scanline_callback = callback; + GB.scanline_callback_ly = ly; +} +ECL_EXPORT uint8_t GetIoReg(uint8_t port) +{ + return GB.io_registers[port]; +} + +ECL_EXPORT void PutSaveRam() +{ + GB_load_battery(&GB, "save.ram"); +} + +ECL_EXPORT void GetSaveRam() +{ + GB_save_battery(&GB, "save.ram"); +} + +ECL_EXPORT bool HasSaveRam() +{ + if (!GB.cartridge_type->has_battery) + return false; // Nothing to save. + if (GB.mbc_ram_size == 0 && !GB.cartridge_type->has_rtc) + return false; /* Claims to have battery, but has no RAM or RTC */ + return true; +} + +int main() +{ + return 0; +} diff --git a/waterbox/pizza/blip_buf/blip_buf.c b/waterbox/sameboy/blip_buf/blip_buf.c similarity index 100% rename from waterbox/pizza/blip_buf/blip_buf.c rename to waterbox/sameboy/blip_buf/blip_buf.c diff --git a/waterbox/pizza/blip_buf/blip_buf.h b/waterbox/sameboy/blip_buf/blip_buf.h similarity index 100% rename from waterbox/pizza/blip_buf/blip_buf.h rename to waterbox/sameboy/blip_buf/blip_buf.h diff --git a/waterbox/sameboy/camera.c b/waterbox/sameboy/camera.c new file mode 100644 index 0000000000..6ce2c0d89e --- /dev/null +++ b/waterbox/sameboy/camera.c @@ -0,0 +1,149 @@ +#include "gb.h" + +static int noise_seed = 0; + +/* This is not a complete emulation of the camera chip. Only the features used by the GameBoy Camera ROMs are supported. + We also do not emulate the timing of the real cart, as it might be actually faster than the webcam. */ + +static uint8_t generate_noise(uint8_t x, uint8_t y) +{ + int value = (x + y * 128 + noise_seed); + uint8_t *data = (uint8_t *) &value; + unsigned hash = 0; + + while ((int *) data != &value + 1) { + hash ^= (*data << 8); + if (hash & 0x8000) { + hash ^= 0x8a00; + hash ^= *data; + } + data++; + hash <<= 1; + } + return (hash >> 8); +} + +static long get_processed_color(GB_gameboy_t *gb, uint8_t x, uint8_t y) +{ + if (x >= 128) { + x = 0; + } + if (y >= 112) { + y = 0; + } + + long color = gb->camera_get_pixel_callback? gb->camera_get_pixel_callback(gb, x, y) : (generate_noise(x, y)); + + static const double gain_values[] = + {0.8809390, 0.9149149, 0.9457498, 0.9739758, + 1.0000000, 1.0241412, 1.0466537, 1.0677433, + 1.0875793, 1.1240310, 1.1568911, 1.1868043, + 1.2142561, 1.2396208, 1.2743837, 1.3157323, + 1.3525190, 1.3856512, 1.4157897, 1.4434309, + 1.4689574, 1.4926697, 1.5148087, 1.5355703, + 1.5551159, 1.5735801, 1.5910762, 1.6077008, + 1.6235366, 1.6386550, 1.6531183, 1.6669808}; + /* Multiply color by gain value */ + color *= gain_values[gb->camera_registers[GB_CAMERA_GAIN_AND_EDGE_ENHACEMENT_FLAGS] & 0x1F]; + + + /* Color is multiplied by the exposure register to simulate exposure. */ + color = color * ((gb->camera_registers[GB_CAMERA_EXPOSURE_HIGH] << 8) + gb->camera_registers[GB_CAMERA_EXPOSURE_LOW]) / 0x1000; + + return color; +} + +uint8_t GB_camera_read_image(GB_gameboy_t *gb, uint16_t addr) +{ + if (gb->camera_registers[GB_CAMERA_SHOOT_AND_1D_FLAGS] & 1) { + /* Forbid reading the image while the camera is busy. */ + return 0xFF; + } + uint8_t tile_x = addr / 0x10 % 0x10; + uint8_t tile_y = addr / 0x10 / 0x10; + + uint8_t y = ((addr >> 1) & 0x7) + tile_y * 8; + uint8_t bit = addr & 1; + + uint8_t ret = 0; + + for (uint8_t x = tile_x * 8; x < tile_x * 8 + 8; x++) { + + long color = get_processed_color(gb, x, y); + + static const double edge_enhancement_ratios[] = {0.5, 0.75, 1, 1.25, 2, 3, 4, 5}; + double edge_enhancement_ratio = edge_enhancement_ratios[(gb->camera_registers[GB_CAMERA_EDGE_ENHANCEMENT_INVERT_AND_VOLTAGE] >> 4) & 0x7]; + if ((gb->camera_registers[GB_CAMERA_GAIN_AND_EDGE_ENHACEMENT_FLAGS] & 0xE0) == 0xE0) { + color += (color * 4) * edge_enhancement_ratio; + color -= get_processed_color(gb, x - 1, y) * edge_enhancement_ratio; + color -= get_processed_color(gb, x + 1, y) * edge_enhancement_ratio; + color -= get_processed_color(gb, x, y - 1) * edge_enhancement_ratio; + color -= get_processed_color(gb, x, y + 1) * edge_enhancement_ratio; + } + + + /* The camera's registers are used as a threshold pattern, which defines the dithering */ + uint8_t pattern_base = ((x & 3) + (y & 3) * 4) * 3 + GB_CAMERA_DITHERING_PATTERN_START; + + if (color < gb->camera_registers[pattern_base]) { + color = 3; + } + else if (color < gb->camera_registers[pattern_base + 1]) { + color = 2; + } + else if (color < gb->camera_registers[pattern_base + 2]) { + color = 1; + } + else { + color = 0; + } + + ret <<= 1; + ret |= (color >> bit) & 1; + } + + return ret; +} + +void GB_set_camera_get_pixel_callback(GB_gameboy_t *gb, GB_camera_get_pixel_callback_t callback) +{ + gb->camera_get_pixel_callback = callback; +} + +void GB_set_camera_update_request_callback(GB_gameboy_t *gb, GB_camera_update_request_callback_t callback) +{ + gb->camera_update_request_callback = callback; +} + +void GB_camera_updated(GB_gameboy_t *gb) +{ + gb->camera_registers[GB_CAMERA_SHOOT_AND_1D_FLAGS] &= ~1; +} + +void GB_camera_write_register(GB_gameboy_t *gb, uint16_t addr, uint8_t value) +{ + addr &= 0x7F; + if (addr == GB_CAMERA_SHOOT_AND_1D_FLAGS) { + value &= 0x7; + noise_seed = 42; // rand(); + if ((value & 1) && !(gb->camera_registers[GB_CAMERA_SHOOT_AND_1D_FLAGS] & 1) && gb->camera_update_request_callback) { + /* If no callback is set, ignore the write as if the camera is instantly done */ + gb->camera_registers[GB_CAMERA_SHOOT_AND_1D_FLAGS] |= 1; + gb->camera_update_request_callback(gb); + } + } + else { + if (addr >= 0x36) { + GB_log(gb, "Wrote invalid camera register %02x: %2x\n", addr, value); + return; + } + gb->camera_registers[addr] = value; + } +} +uint8_t GB_camera_read_register(GB_gameboy_t *gb, uint16_t addr) +{ + if ((addr & 0x7F) == 0) { + return gb->camera_registers[GB_CAMERA_SHOOT_AND_1D_FLAGS]; + } + return 0; +} diff --git a/waterbox/sameboy/camera.h b/waterbox/sameboy/camera.h new file mode 100644 index 0000000000..21c69b68e6 --- /dev/null +++ b/waterbox/sameboy/camera.h @@ -0,0 +1,29 @@ +#ifndef camera_h +#define camera_h +#include +#include "gb_struct_def.h" + +typedef uint8_t (*GB_camera_get_pixel_callback_t)(GB_gameboy_t *gb, uint8_t x, uint8_t y); +typedef void (*GB_camera_update_request_callback_t)(GB_gameboy_t *gb); + +enum { + GB_CAMERA_SHOOT_AND_1D_FLAGS = 0, + GB_CAMERA_GAIN_AND_EDGE_ENHACEMENT_FLAGS = 1, + GB_CAMERA_EXPOSURE_HIGH = 2, + GB_CAMERA_EXPOSURE_LOW = 3, + GB_CAMERA_EDGE_ENHANCEMENT_INVERT_AND_VOLTAGE = 4, + GB_CAMERA_DITHERING_PATTERN_START = 6, + GB_CAMERA_DITHERING_PATTERN_END = 0x35, +}; + +uint8_t GB_camera_read_image(GB_gameboy_t *gb, uint16_t addr); + +void GB_set_camera_get_pixel_callback(GB_gameboy_t *gb, GB_camera_get_pixel_callback_t callback); +void GB_set_camera_update_request_callback(GB_gameboy_t *gb, GB_camera_update_request_callback_t callback); + +void GB_camera_updated(GB_gameboy_t *gb); + +void GB_camera_write_register(GB_gameboy_t *gb, uint16_t addr, uint8_t value); +uint8_t GB_camera_read_register(GB_gameboy_t *gb, uint16_t addr); + +#endif diff --git a/waterbox/sameboy/display.c b/waterbox/sameboy/display.c new file mode 100644 index 0000000000..28dd5f07ec --- /dev/null +++ b/waterbox/sameboy/display.c @@ -0,0 +1,796 @@ +#include +#include +#include +#include +#include "gb.h" + +/* + Each line is 456 cycles, approximately: + Mode 2 - 80 cycles / OAM Transfer + Mode 3 - 172 cycles / Rendering + Mode 0 - 204 cycles / HBlank + + Mode 1 is VBlank + + Todo: Mode lengths are not constants, see http://blog.kevtris.org/blogfiles/Nitty%20Gritty%20Gameboy%20VRAM%20Timing.txt + */ + +#define MODE2_LENGTH (80) +#define MODE3_LENGTH (172) +#define MODE0_LENGTH (204) +#define LINE_LENGTH (MODE2_LENGTH + MODE3_LENGTH + MODE0_LENGTH) // = 456 +#define LINES (144) +#define WIDTH (160) +#define VIRTUAL_LINES (LCDC_PERIOD / LINE_LENGTH) // = 154 + +typedef struct __attribute__((packed)) { + uint8_t y; + uint8_t x; + uint8_t tile; + uint8_t flags; +} GB_sprite_t; + +static bool window_enabled(GB_gameboy_t *gb) +{ + if ((gb->io_registers[GB_IO_LCDC] & 0x1) == 0) { + if (!gb->cgb_mode && gb->is_cgb) { + return false; + } + } + return (gb->io_registers[GB_IO_LCDC] & 0x20) && gb->io_registers[GB_IO_WX] < 167; +} + +static uint32_t get_pixel(GB_gameboy_t *gb, uint8_t x, uint8_t y) +{ + /* + Bit 7 - LCD Display Enable (0=Off, 1=On) + Bit 6 - Window Tile Map Display Select (0=9800-9BFF, 1=9C00-9FFF) + Bit 5 - Window Display Enable (0=Off, 1=On) + Bit 4 - BG & Window Tile Data Select (0=8800-97FF, 1=8000-8FFF) + Bit 3 - BG Tile Map Display Select (0=9800-9BFF, 1=9C00-9FFF) + Bit 2 - OBJ (Sprite) Size (0=8x8, 1=8x16) + Bit 1 - OBJ (Sprite) Display Enable (0=Off, 1=On) + Bit 0 - BG Display (for CGB see below) (0=Off, 1=On) + */ + uint16_t map = 0x1800; + uint8_t tile = 0; + uint8_t attributes = 0; + uint8_t sprite_palette = 0; + uint16_t tile_address = 0; + uint8_t background_pixel = 0, sprite_pixel = 0; + GB_sprite_t *sprite = (GB_sprite_t *) &gb->oam; + uint8_t sprites_in_line = 0; + bool lcd_8_16_mode = (gb->io_registers[GB_IO_LCDC] & 4) != 0; + bool sprites_enabled = (gb->io_registers[GB_IO_LCDC] & 2) != 0; + uint8_t lowest_sprite_x = 0xFF; + bool use_obp1 = false, priority = false; + bool in_window = false; + bool bg_enabled = true; + bool bg_behind = false; + if ((gb->io_registers[GB_IO_LCDC] & 0x1) == 0) { + if (gb->cgb_mode) { + bg_behind = true; + } + else { + bg_enabled = false; + } + } + if (window_enabled(gb) && y >= gb->io_registers[GB_IO_WY] && x + 7 >= gb->io_registers[GB_IO_WX] && gb->current_window_line != 0xFF) { + in_window = true; + } + + if (sprites_enabled) { + // Loop all sprites + for (uint8_t i = 40; i--; sprite++) { + int sprite_y = sprite->y - 16; + int sprite_x = sprite->x - 8; + // Is sprite in our line? + if (sprite_y <= y && sprite_y + (lcd_8_16_mode? 16:8) > y) { + uint8_t tile_x, tile_y, current_sprite_pixel; + uint16_t line_address; + // Limit to 10 sprites in one scan line. + if (++sprites_in_line == 11) break; + // Does not overlap our pixel. + if (sprite_x > x || sprite_x + 8 <= x) continue; + tile_x = x - sprite_x; + tile_y = y - sprite_y; + if (sprite->flags & 0x20) tile_x = 7 - tile_x; + if (sprite->flags & 0x40) tile_y = (lcd_8_16_mode? 15:7) - tile_y; + line_address = (lcd_8_16_mode? sprite->tile & 0xFE : sprite->tile) * 0x10 + tile_y * 2; + if (gb->cgb_mode && (sprite->flags & 0x8)) { + line_address += 0x2000; + } + current_sprite_pixel = (((gb->vram[line_address ] >> ((~tile_x)&7)) & 1 ) | + ((gb->vram[line_address + 1] >> ((~tile_x)&7)) & 1) << 1 ); + /* From Pandocs: + When sprites with different x coordinate values overlap, the one with the smaller x coordinate + (closer to the left) will have priority and appear above any others. This applies in Non CGB Mode + only. When sprites with the same x coordinate values overlap, they have priority according to table + ordering. (i.e. $FE00 - highest, $FE04 - next highest, etc.) In CGB Mode priorities are always + assigned like this. + */ + if (current_sprite_pixel != 0) { + if (!gb->cgb_mode && sprite->x >= lowest_sprite_x) { + break; + } + sprite_pixel = current_sprite_pixel; + lowest_sprite_x = sprite->x; + use_obp1 = (sprite->flags & 0x10) != 0; + sprite_palette = sprite->flags & 7; + priority = (sprite->flags & 0x80) != 0; + if (gb->cgb_mode) { + break; + } + } + } + } + } + + if (in_window) { + x -= gb->io_registers[GB_IO_WX] - 7; // Todo: This value is probably latched + y = gb->current_window_line; + } + else { + x += gb->effective_scx; + y += gb->io_registers[GB_IO_SCY]; + } + if (gb->io_registers[GB_IO_LCDC] & 0x08 && !in_window) { + map = 0x1C00; + } + else if (gb->io_registers[GB_IO_LCDC] & 0x40 && in_window) { + map = 0x1C00; + } + tile = gb->vram[map + x/8 + y/8 * 32]; + if (gb->cgb_mode) { + attributes = gb->vram[map + x/8 + y/8 * 32 + 0x2000]; + } + + if (attributes & 0x80) { + priority = !bg_behind && bg_enabled; + } + + if (!priority && sprite_pixel) { + if (!gb->cgb_mode) { + sprite_pixel = (gb->io_registers[use_obp1? GB_IO_OBP1:GB_IO_OBP0] >> (sprite_pixel << 1)) & 3; + sprite_palette = use_obp1; + } + return gb->sprite_palettes_rgb[sprite_palette * 4 + sprite_pixel]; + } + + if (bg_enabled) { + if (gb->io_registers[GB_IO_LCDC] & 0x10) { + tile_address = tile * 0x10; + } + else { + tile_address = (int8_t) tile * 0x10 + 0x1000; + } + if (attributes & 0x8) { + tile_address += 0x2000; + } + + if (attributes & 0x20) { + x = ~x; + } + + if (attributes & 0x40) { + y = ~y; + } + + background_pixel = (((gb->vram[tile_address + (y & 7) * 2 ] >> ((~x)&7)) & 1 ) | + ((gb->vram[tile_address + (y & 7) * 2 + 1] >> ((~x)&7)) & 1) << 1 ); + } + + if (priority && sprite_pixel && !background_pixel) { + if (!gb->cgb_mode) { + sprite_pixel = (gb->io_registers[use_obp1? GB_IO_OBP1:GB_IO_OBP0] >> (sprite_pixel << 1)) & 3; + sprite_palette = use_obp1; + } + return gb->sprite_palettes_rgb[sprite_palette * 4 + sprite_pixel]; + } + + if (!gb->cgb_mode) { + background_pixel = ((gb->io_registers[GB_IO_BGP] >> (background_pixel << 1)) & 3); + } + + return gb->background_palettes_rgb[(attributes & 7) * 4 + background_pixel]; +} + +static void display_vblank(GB_gameboy_t *gb) +{ + if (!gb->disable_rendering && ((!(gb->io_registers[GB_IO_LCDC] & 0x80) || gb->stopped) || gb->frame_skip_state == GB_FRAMESKIP_LCD_TURNED_ON)) { + /* LCD is off, set screen to white */ + uint32_t white = gb->rgb_encode_callback(gb, 0xFF, 0xFF, 0xFF); + for (unsigned i = 0; i < WIDTH * LINES; i++) { + gb ->screen[i] = white; + } + } + + gb->vblank_callback(gb); + + gb->vblank_just_occured = true; +} + +static inline uint8_t scale_channel(uint8_t x) +{ + x &= 0x1f; + return (x << 3) | (x >> 2); +} + +void GB_palette_changed(GB_gameboy_t *gb, bool background_palette, uint8_t index) +{ + uint8_t *palette_data = background_palette? gb->background_palettes_data : gb->sprite_palettes_data; + uint16_t color = palette_data[index & ~1] | (palette_data[index | 1] << 8); + + // No need to &, scale channel does that. + uint8_t r = scale_channel(color); + uint8_t g = scale_channel(color >> 5); + uint8_t b = scale_channel(color >> 10); + assert (gb->rgb_encode_callback); + (background_palette? gb->background_palettes_rgb : gb->sprite_palettes_rgb)[index / 2] = gb->rgb_encode_callback(gb, r, g, b); +} + +/* + STAT interrupt is implemented based on this finding: + http://board.byuu.org/phpbb3/viewtopic.php?p=25527#p25531 + + General timing is based on GiiBiiAdvance's documents: + https://github.com/AntonioND/giibiiadvance + + */ + +static void update_display_state(GB_gameboy_t *gb, uint8_t cycles) +{ + uint8_t previous_stat_interrupt_line = gb->stat_interrupt_line; + gb->stat_interrupt_line = false; + + if (!(gb->io_registers[GB_IO_LCDC] & 0x80)) { + /* LCD is disabled, state is constant */ + + /* When the LCD is off, LY is 0 and STAT mode is 0. + Todo: Verify the LY=LYC flag should be on. */ + gb->io_registers[GB_IO_LY] = 0; + gb->io_registers[GB_IO_STAT] &= ~3; + gb->io_registers[GB_IO_STAT] |= 4; + if (gb->hdma_on_hblank) { + gb->hdma_on_hblank = false; + gb->hdma_on = false; + + /* Todo: is this correct? */ + gb->hdma_steps_left = 0xff; + } + + gb->oam_read_blocked = false; + gb->vram_read_blocked = false; + gb->oam_write_blocked = false; + gb->vram_write_blocked = false; + + /* Keep sending vblanks to user even if the screen is off */ + gb->display_cycles += cycles; + if (gb->display_cycles >= LCDC_PERIOD) { + /* VBlank! */ + gb->display_cycles -= LCDC_PERIOD; + display_vblank(gb); + } + + /* Reset window rendering state */ + gb->current_window_line = 0xFF; + return; + } + + uint8_t atomic_increase = gb->cgb_double_speed? 2 : 4; + uint8_t stat_delay = gb->cgb_double_speed? 2 : (gb->cgb_mode? 0 : 4); + /* Todo: This is correct for DMG. Is it correct for the 3 CGB modes (DMG/single/double)?*/ + uint8_t scx_delay = ((gb->effective_scx & 7) + atomic_increase - 1) & ~(atomic_increase - 1); + /* Todo: These are correct for DMG, DMG-mode CGB, and single speed CGB. Is is correct for double speed CGB? */ + uint8_t oam_blocking_rush = gb->cgb_double_speed? 2 : 4; + uint8_t vram_blocking_rush = gb->is_cgb? 0 : 4; + + for (; cycles; cycles -= atomic_increase) { + + gb->display_cycles += atomic_increase; + /* The very first line is 2 (4 from the CPU's perseptive) clocks shorter when the LCD turns on. + Todo: Verify on the 3 CGB modes, especially double speed mode. */ + if (gb->first_scanline && gb->display_cycles >= LINE_LENGTH - atomic_increase) { + gb->first_scanline = false; + gb->display_cycles += atomic_increase; + } + bool should_compare_ly = true; + uint8_t ly_for_comparison = gb->io_registers[GB_IO_LY] = gb->display_cycles / LINE_LENGTH; + + if (gb->scanline_callback && gb->display_cycles % LINE_LENGTH == 0 && gb->scanline_callback_ly == ly_for_comparison) { + gb->scanline_callback(gb->io_registers[GB_IO_LCDC]); + } + + /* Handle cycle completion. STAT's initial value depends on model and mode */ + if (gb->display_cycles == LCDC_PERIOD) { + /* VBlank! */ + gb->display_cycles = 0; + gb->io_registers[GB_IO_STAT] &= ~3; + if (gb->is_cgb) { + if (stat_delay) { + gb->io_registers[GB_IO_STAT] |= 1; + } + else { + gb->io_registers[GB_IO_STAT] |= 2; + } + } + ly_for_comparison = gb->io_registers[GB_IO_LY] = 0; + + /* Todo: verify timing */ + gb->oam_read_blocked = true; + gb->vram_read_blocked = false; + gb->oam_write_blocked = true; + gb->vram_write_blocked = false; + + + /* Reset window rendering state */ + gb->current_window_line = 0xFF; + } + + /* Entered VBlank state, update STAT and IF */ + else if (gb->display_cycles == LINES * LINE_LENGTH + stat_delay) { + gb->io_registers[GB_IO_STAT] &= ~3; + gb->io_registers[GB_IO_STAT] |= 1; + gb->io_registers[GB_IO_IF] |= 1; + + /* Entering VBlank state triggers the OAM interrupt. In CGB, it happens 4 cycles earlier */ + if (gb->io_registers[GB_IO_STAT] & 0x20 && !gb->is_cgb) { + gb->stat_interrupt_line = true; + } + if (gb->frame_skip_state == GB_FRAMESKIP_LCD_TURNED_ON) { + if (!gb->is_cgb) { + display_vblank(gb); + gb->frame_skip_state = GB_FRAMESKIP_SECOND_FRAME_RENDERED; + } + else { + gb->frame_skip_state = GB_FRAMESKIP_FIRST_FRAME_SKIPPED; + } + } + else { + gb->frame_skip_state = GB_FRAMESKIP_SECOND_FRAME_RENDERED; + display_vblank(gb); + } + } + + + /* Handle line 0 right after turning the LCD on */ + else if (gb->first_scanline) { + /* OAM and VRAM blocking is not rushed in the very first scanline */ + if (gb->display_cycles == atomic_increase) { + gb->io_registers[GB_IO_STAT] &= ~3; + gb->oam_read_blocked = false; + gb->vram_read_blocked = false; + gb->oam_write_blocked = false; + gb->vram_write_blocked = false; + } + else if (gb->display_cycles == MODE2_LENGTH) { + gb->io_registers[GB_IO_STAT] &= ~3; + gb->io_registers[GB_IO_STAT] |= 3; + gb->oam_read_blocked = true; + gb->vram_read_blocked = true; + gb->oam_write_blocked = true; + gb->vram_write_blocked = true; + } + else if (gb->display_cycles == MODE2_LENGTH + MODE3_LENGTH) { + gb->io_registers[GB_IO_STAT] &= ~3; + gb->oam_read_blocked = false; + gb->vram_read_blocked = false; + gb->oam_write_blocked = false; + gb->vram_write_blocked = false; + } + } + + /* Handle STAT changes for lines 0-143 */ + else if (gb->display_cycles < LINES * LINE_LENGTH) { + unsigned position_in_line = gb->display_cycles % LINE_LENGTH; + + /* Handle OAM and VRAM blocking */ + /* Todo: verify CGB timing for write blocking */ + if (position_in_line == stat_delay - oam_blocking_rush || + // In case stat_delay is 0 + (position_in_line == LINE_LENGTH + stat_delay - oam_blocking_rush && gb->io_registers[GB_IO_LY] != 143)) { + gb->oam_read_blocked = true; + gb->oam_write_blocked = gb->is_cgb; + } + else if (position_in_line == MODE2_LENGTH + stat_delay - vram_blocking_rush) { + gb->vram_read_blocked = true; + gb->vram_write_blocked = gb->is_cgb; + } + + if (position_in_line == stat_delay) { + gb->oam_write_blocked = true; + } + else if (!gb->is_cgb && position_in_line == MODE2_LENGTH + stat_delay - oam_blocking_rush) { + gb->oam_write_blocked = false; + } + else if (position_in_line == MODE2_LENGTH + stat_delay) { + gb->vram_write_blocked = true; + gb->oam_write_blocked = true; + } + + /* Handle everything else */ + if (position_in_line == stat_delay) { + gb->io_registers[GB_IO_STAT] &= ~3; + gb->io_registers[GB_IO_STAT] |= 2; + if (window_enabled(gb) && gb->display_cycles / LINE_LENGTH >= gb->io_registers[GB_IO_WY]) { + gb->current_window_line++; + } + } + else if (position_in_line == 0 && gb->display_cycles != 0) { + should_compare_ly = gb->is_cgb; + ly_for_comparison--; + } + else if (position_in_line == MODE2_LENGTH + stat_delay) { + gb->io_registers[GB_IO_STAT] &= ~3; + gb->io_registers[GB_IO_STAT] |= 3; + gb->effective_scx = gb->io_registers[GB_IO_SCX]; + gb->previous_lcdc_x = - (gb->effective_scx & 0x7); + + /* Todo: This works on both 007 - The World Is Not Enough and Donkey Kong 94, but should be verified better */ + if (window_enabled(gb) && gb->display_cycles / LINE_LENGTH == gb->io_registers[GB_IO_WY] && gb->current_window_line == 0xFF) { + gb->current_window_line = 0; + } + } + else if (position_in_line == MODE2_LENGTH + MODE3_LENGTH + stat_delay + scx_delay) { + gb->io_registers[GB_IO_STAT] &= ~3; + gb->oam_read_blocked = false; + gb->vram_read_blocked = false; + gb->oam_write_blocked = false; + gb->vram_write_blocked = false; + if (gb->hdma_on_hblank) { + gb->hdma_on = true; + gb->hdma_cycles = 0; + } + } + } + + /* Line 153 is special */ + else if (gb->display_cycles >= (VIRTUAL_LINES - 1) * LINE_LENGTH) { + /* DMG */ + if (!gb->is_cgb) { + switch (gb->display_cycles - (VIRTUAL_LINES - 1) * LINE_LENGTH) { + case 0: + should_compare_ly = false; + break; + case 4: + gb->io_registers[GB_IO_LY] = 0; + ly_for_comparison = VIRTUAL_LINES - 1; + break; + case 8: + gb->io_registers[GB_IO_LY] = 0; + should_compare_ly = false; + break; + default: + gb->io_registers[GB_IO_LY] = 0; + ly_for_comparison = 0; + } + } + /* CGB in DMG mode */ + else if (!gb->cgb_mode) { + switch (gb->display_cycles - (VIRTUAL_LINES - 1) * LINE_LENGTH) { + case 0: + ly_for_comparison = VIRTUAL_LINES - 2; + break; + case 4: + break; + case 8: + gb->io_registers[GB_IO_LY] = 0; + break; + default: + gb->io_registers[GB_IO_LY] = 0; + ly_for_comparison = 0; + } + } + /* Single speed CGB */ + else if (!gb->cgb_double_speed) { + switch (gb->display_cycles - (VIRTUAL_LINES - 1) * LINE_LENGTH) { + case 0: + break; + case 4: + gb->io_registers[GB_IO_LY] = 0; + break; + default: + gb->io_registers[GB_IO_LY] = 0; + ly_for_comparison = 0; + } + } + + /* Double speed CGB */ + else { + switch (gb->display_cycles - (VIRTUAL_LINES - 1) * LINE_LENGTH) { + case 0: + ly_for_comparison = VIRTUAL_LINES - 2; + break; + case 2: + case 4: + break; + case 6: + case 8: + gb->io_registers[GB_IO_LY] = 0; + break; + default: + gb->io_registers[GB_IO_LY] = 0; + ly_for_comparison = 0; + } + } + } + + /* Lines 144 - 152 */ + else { + if (stat_delay && gb->display_cycles % LINE_LENGTH == 0) { + should_compare_ly = gb->is_cgb; + ly_for_comparison--; + } + } + + /* Set LY=LYC bit */ + if (should_compare_ly && (ly_for_comparison == gb->io_registers[GB_IO_LYC])) { + gb->io_registers[GB_IO_STAT] |= 4; + } + else { + gb->io_registers[GB_IO_STAT] &= ~4; + } + + if (!gb->stat_interrupt_line) { + switch (gb->io_registers[GB_IO_STAT] & 3) { + case 0: gb->stat_interrupt_line = gb->io_registers[GB_IO_STAT] & 8; break; + case 1: gb->stat_interrupt_line = gb->io_registers[GB_IO_STAT] & 0x10; break; + case 2: gb->stat_interrupt_line = gb->io_registers[GB_IO_STAT] & 0x20; break; + } + + /* Use requested a LY=LYC interrupt and the LY=LYC bit is on */ + if ((gb->io_registers[GB_IO_STAT] & 0x44) == 0x44) { + gb->stat_interrupt_line = true; + } + } + } + + /* On the CGB, the last cycle of line 144 triggers an OAM interrupt + Todo: Verify timing for CGB in CGB mode and double speed CGB */ + if (gb->is_cgb && + gb->display_cycles == LINES * LINE_LENGTH + stat_delay - atomic_increase && + (gb->io_registers[GB_IO_STAT] & 0x20)) { + gb->stat_interrupt_line = true; + } + + if (gb->stat_interrupt_line && !previous_stat_interrupt_line) { + gb->io_registers[GB_IO_IF] |= 2; + } + + /* The value of LY is glitched in the last cycle of every line in CGB mode CGB in single speed + This is based on GiiBiiAdvance's docs */ + if (gb->cgb_mode && !gb->cgb_double_speed && + gb->display_cycles % LINE_LENGTH == LINE_LENGTH - 4) { + uint8_t glitch_pattern[] = {0, 0, 2, 0, 4, 4, 6, 0, 8}; + if ((gb->io_registers[GB_IO_LY] & 0xF) == 0xF) { + gb->io_registers[GB_IO_LY] = glitch_pattern[gb->io_registers[GB_IO_LY] >> 4] << 4; + } + else { + gb->io_registers[GB_IO_LY] = glitch_pattern[gb->io_registers[GB_IO_LY] & 7] | (gb->io_registers[GB_IO_LY] & 0xF8); + } + } +} + +void GB_display_run(GB_gameboy_t *gb, uint8_t cycles) +{ + update_display_state(gb, cycles); + if (gb->disable_rendering) { + return; + } + + /* + Display controller bug: For some reason, the OAM STAT interrupt is called, as expected, for LY = 0..143. + However, it is also called from LY = 144. + + See http://forums.nesdev.com/viewtopic.php?f=20&t=13727 + */ + + if (!(gb->io_registers[GB_IO_LCDC] & 0x80)) { + /* LCD is disabled, do nothing */ + return; + } + if (gb->display_cycles >= LINE_LENGTH * 144) { /* VBlank */ + return; + } + + uint8_t effective_ly = gb->display_cycles / LINE_LENGTH; + + + if (gb->display_cycles % LINE_LENGTH < MODE2_LENGTH) { /* Mode 2 */ + return; + } + + + /* Render */ + /* Todo: it appears that the actual rendering starts 4 cycles after mode 3 starts. Is this correct? */ + int16_t current_lcdc_x = gb->display_cycles % LINE_LENGTH - MODE2_LENGTH - (gb->effective_scx & 0x7) - 4; + + for (;gb->previous_lcdc_x < current_lcdc_x; gb->previous_lcdc_x++) { + if (gb->previous_lcdc_x >= WIDTH) { + continue; + } + if (gb->previous_lcdc_x < 0) { + continue; + } + gb->screen[effective_ly * WIDTH + gb->previous_lcdc_x] = + get_pixel(gb, gb->previous_lcdc_x, effective_ly); + } +} + +void GB_draw_tileset(GB_gameboy_t *gb, uint32_t *dest, GB_palette_type_t palette_type, uint8_t palette_index) +{ + uint32_t none_palette[4]; + uint32_t *palette = NULL; + + switch (gb->is_cgb? palette_type : GB_PALETTE_NONE) { + default: + case GB_PALETTE_NONE: + none_palette[0] = gb->rgb_encode_callback(gb, 0xFF, 0xFF, 0xFF); + none_palette[1] = gb->rgb_encode_callback(gb, 0xAA, 0xAA, 0xAA); + none_palette[2] = gb->rgb_encode_callback(gb, 0x55, 0x55, 0x55); + none_palette[3] = gb->rgb_encode_callback(gb, 0, 0, 0 ); + palette = none_palette; + break; + case GB_PALETTE_BACKGROUND: + palette = gb->background_palettes_rgb + (4 * (palette_index & 7)); + break; + case GB_PALETTE_OAM: + palette = gb->sprite_palettes_rgb + (4 * (palette_index & 7)); + break; + } + + for (unsigned y = 0; y < 192; y++) { + for (unsigned x = 0; x < 256; x++) { + if (x >= 128 && !gb->is_cgb) { + *(dest++) = gb->background_palettes_rgb[0]; + continue; + } + uint16_t tile = (x % 128) / 8 + y / 8 * 16; + uint16_t tile_address = tile * 0x10 + (x >= 128? 0x2000 : 0); + uint8_t pixel = (((gb->vram[tile_address + (y & 7) * 2 ] >> ((~x)&7)) & 1 ) | + ((gb->vram[tile_address + (y & 7) * 2 + 1] >> ((~x)&7)) & 1) << 1); + + if (!gb->cgb_mode) { + if (palette_type == GB_PALETTE_BACKGROUND) { + pixel = ((gb->io_registers[GB_IO_BGP] >> (pixel << 1)) & 3); + } + else if (!gb->cgb_mode) { + if (palette_type == GB_PALETTE_OAM) { + pixel = ((gb->io_registers[palette_index == 0? GB_IO_OBP0 : GB_IO_OBP1] >> (pixel << 1)) & 3); + } + } + } + + + *(dest++) = palette[pixel]; + } + } +} + +void GB_draw_tilemap(GB_gameboy_t *gb, uint32_t *dest, GB_palette_type_t palette_type, uint8_t palette_index, GB_map_type_t map_type, GB_tileset_type_t tileset_type) +{ + uint32_t none_palette[4]; + uint32_t *palette = NULL; + uint16_t map = 0x1800; + + switch (gb->is_cgb? palette_type : GB_PALETTE_NONE) { + case GB_PALETTE_NONE: + none_palette[0] = gb->rgb_encode_callback(gb, 0xFF, 0xFF, 0xFF); + none_palette[1] = gb->rgb_encode_callback(gb, 0xAA, 0xAA, 0xAA); + none_palette[2] = gb->rgb_encode_callback(gb, 0x55, 0x55, 0x55); + none_palette[3] = gb->rgb_encode_callback(gb, 0, 0, 0 ); + palette = none_palette; + break; + case GB_PALETTE_BACKGROUND: + palette = gb->background_palettes_rgb + (4 * (palette_index & 7)); + break; + case GB_PALETTE_OAM: + palette = gb->sprite_palettes_rgb + (4 * (palette_index & 7)); + break; + case GB_PALETTE_AUTO: + break; + } + + if (map_type == GB_MAP_9C00 || (map_type == GB_MAP_AUTO && gb->io_registers[GB_IO_LCDC] & 0x08)) { + map = 0x1c00; + } + + if (tileset_type == GB_TILESET_AUTO) { + tileset_type = (gb->io_registers[GB_IO_LCDC] & 0x10)? GB_TILESET_8800 : GB_TILESET_8000; + } + + for (unsigned y = 0; y < 256; y++) { + for (unsigned x = 0; x < 256; x++) { + uint8_t tile = gb->vram[map + x/8 + y/8 * 32]; + uint16_t tile_address; + uint8_t attributes = 0; + + if (tileset_type == GB_TILESET_8800) { + tile_address = tile * 0x10; + } + else { + tile_address = (int8_t) tile * 0x10 + 0x1000; + } + + if (gb->cgb_mode) { + attributes = gb->vram[map + x/8 + y/8 * 32 + 0x2000]; + } + + if (attributes & 0x8) { + tile_address += 0x2000; + } + + uint8_t pixel = (((gb->vram[tile_address + (((attributes & 0x40)? ~y : y) & 7) * 2 ] >> (((attributes & 0x20)? x : ~x)&7)) & 1 ) | + ((gb->vram[tile_address + (((attributes & 0x40)? ~y : y) & 7) * 2 + 1] >> (((attributes & 0x20)? x : ~x)&7)) & 1) << 1); + + if (!gb->cgb_mode && (palette_type == GB_PALETTE_BACKGROUND || palette_type == GB_PALETTE_AUTO)) { + pixel = ((gb->io_registers[GB_IO_BGP] >> (pixel << 1)) & 3); + } + + if (palette) { + *(dest++) = palette[pixel]; + } + else { + *(dest++) = gb->background_palettes_rgb[(attributes & 7) * 4 + pixel]; + } + } + } +} + +uint8_t GB_get_oam_info(GB_gameboy_t *gb, GB_oam_info_t *dest, uint8_t *sprite_height) +{ + uint8_t count = 0; + *sprite_height = (gb->io_registers[GB_IO_LCDC] & 4) ? 16:8; + uint8_t oam_to_dest_index[40] = {0,}; + for (unsigned y = 0; y < LINES; y++) { + GB_sprite_t *sprite = (GB_sprite_t *) &gb->oam; + uint8_t sprites_in_line = 0; + for (uint8_t i = 0; i < 40; i++, sprite++) { + int sprite_y = sprite->y - 16; + bool obscured = false; + // Is sprite not in this line? + if (sprite_y > y || sprite_y + *sprite_height <= y) continue; + if (++sprites_in_line == 11) obscured = true; + + GB_oam_info_t *info = NULL; + if (!oam_to_dest_index[i]) { + info = dest + count; + oam_to_dest_index[i] = ++count; + info->x = sprite->x; + info->y = sprite->y; + info->tile = *sprite_height == 16? sprite->tile & 0xFE : sprite->tile; + info->flags = sprite->flags; + info->obscured_by_line_limit = false; + info->oam_addr = 0xFE00 + i * sizeof(*sprite); + } + else { + info = dest + oam_to_dest_index[i] - 1; + } + info->obscured_by_line_limit |= obscured; + } + } + + + for (unsigned i = 0; i < count; i++) { + uint16_t vram_address = dest[i].tile * 0x10; + uint8_t flags = dest[i].flags; + uint8_t palette = gb->cgb_mode? (flags & 7) : ((flags & 0x10)? 1 : 0); + if (gb->is_cgb && (flags & 0x8)) { + vram_address += 0x2000; + } + + for (unsigned y = 0; y < *sprite_height; y++) { + for (unsigned x = 0; x < 8; x++) { + uint8_t color = (((gb->vram[vram_address ] >> ((~x)&7)) & 1 ) | + ((gb->vram[vram_address + 1] >> ((~x)&7)) & 1) << 1 ); + + if (!gb->cgb_mode) { + color = (gb->io_registers[palette? GB_IO_OBP1:GB_IO_OBP0] >> (color << 1)) & 3; + } + dest[i].image[((flags & 0x20)?7-x:x) + ((flags & 0x40)?*sprite_height - 1 -y:y) * 8] = gb->sprite_palettes_rgb[palette * 4 + color]; + } + vram_address += 2; + } + } + return count; +} diff --git a/waterbox/sameboy/display.h b/waterbox/sameboy/display.h new file mode 100644 index 0000000000..3967787237 --- /dev/null +++ b/waterbox/sameboy/display.h @@ -0,0 +1,40 @@ +#ifndef display_h +#define display_h + +#include "gb.h" +#ifdef GB_INTERNAL +void GB_display_run(GB_gameboy_t *gb, uint8_t cycles); +void GB_palette_changed(GB_gameboy_t *gb, bool background_palette, uint8_t index); +#endif + +typedef enum { + GB_PALETTE_NONE, + GB_PALETTE_BACKGROUND, + GB_PALETTE_OAM, + GB_PALETTE_AUTO, +} GB_palette_type_t; + +typedef enum { + GB_MAP_AUTO, + GB_MAP_9800, + GB_MAP_9C00, +} GB_map_type_t; + +typedef enum { + GB_TILESET_AUTO, + GB_TILESET_8800, + GB_TILESET_8000, +} GB_tileset_type_t; + +typedef struct { + uint32_t image[128]; + uint8_t x, y, tile, flags; + uint16_t oam_addr; + bool obscured_by_line_limit; +} GB_oam_info_t; + +void GB_draw_tileset(GB_gameboy_t *gb, uint32_t *dest, GB_palette_type_t palette_type, uint8_t palette_index); +void GB_draw_tilemap(GB_gameboy_t *gb, uint32_t *dest, GB_palette_type_t palette_type, uint8_t palette_index, GB_map_type_t map_type, GB_tileset_type_t tileset_type); +uint8_t GB_get_oam_info(GB_gameboy_t *gb, GB_oam_info_t *dest, uint8_t *sprite_height); + +#endif /* display_h */ diff --git a/waterbox/sameboy/gb.c b/waterbox/sameboy/gb.c new file mode 100644 index 0000000000..ce14dc647c --- /dev/null +++ b/waterbox/sameboy/gb.c @@ -0,0 +1,473 @@ +#include +#include +#include +#include +#include +#include +#include +#include "gb.h" +#include "../emulibc/emulibc.h" + +void GB_attributed_logv(GB_gameboy_t *gb, GB_log_attributes attributes, const char *fmt, va_list args) +{ + char *string = NULL; + vasprintf(&string, fmt, args); + if (string) { + if (gb->log_callback) { + gb->log_callback(gb, string, attributes); + } + else { + /* Todo: Add ANSI escape sequences for attributed text */ + printf("%s", string); + } + } + free(string); +} + +void GB_attributed_log(GB_gameboy_t *gb, GB_log_attributes attributes, const char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + GB_attributed_logv(gb, attributes, fmt, args); + va_end(args); +} + +void GB_log(GB_gameboy_t *gb, const char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + GB_attributed_logv(gb, 0, fmt, args); + va_end(args); +} + +void GB_init(GB_gameboy_t *gb) +{ + memset(gb, 0, sizeof(*gb)); + gb->ram = malloc(gb->ram_size = 0x2000); + gb->vram = malloc(gb->vram_size = 0x2000); + gb->cartridge_type = &GB_cart_defs[0]; // Default cartridge type + + GB_reset(gb); +} + +void GB_init_sgb(GB_gameboy_t *gb) +{ + memset(gb, 0, sizeof(*gb)); + gb->ram = malloc(gb->ram_size = 0x2000); + gb->vram = malloc(gb->vram_size = 0x2000); + gb->is_sgb = true; + gb->cartridge_type = &GB_cart_defs[0]; // Default cartridge type + + GB_reset(gb); +} + +void GB_init_cgb(GB_gameboy_t *gb) +{ + memset(gb, 0, sizeof(*gb)); + gb->ram = malloc(gb->ram_size = 0x2000 * 8); + gb->vram = malloc(gb->vram_size = 0x2000 * 2); + gb->is_cgb = true; + gb->cartridge_type = &GB_cart_defs[0]; // Default cartridge type + + GB_reset(gb); +} + +int GB_load_boot_rom(GB_gameboy_t *gb, const char *path) +{ + FILE *f = fopen(path, "rb"); + if (!f) { + GB_log(gb, "Could not open boot ROM: %s.\n", strerror(errno)); + return errno; + } + fread(gb->boot_rom, sizeof(gb->boot_rom), 1, f); + fclose(f); + return 0; +} + +int GB_load_rom(GB_gameboy_t *gb, const char *path) +{ + FILE *f = fopen(path, "rb"); + if (!f) { + GB_log(gb, "Could not open ROM: %s.\n", strerror(errno)); + return errno; + } + fseek(f, 0, SEEK_END); + gb->rom_size = (ftell(f) + 0x3FFF) & ~0x3FFF; /* Round to bank */ + /* And then round to a power of two */ + while (gb->rom_size & (gb->rom_size - 1)) { + /* I promise this works. */ + gb->rom_size |= gb->rom_size >> 1; + gb->rom_size++; + } + fseek(f, 0, SEEK_SET); + if (gb->rom) { + free(gb->rom); + } + gb->rom = alloc_sealed(gb->rom_size); + memset(gb->rom, 0xFF, gb->rom_size); /* Pad with 0xFFs */ + fread(gb->rom, gb->rom_size, 1, f); + fclose(f); + GB_configure_cart(gb); + + return 0; +} + +int GB_save_battery(GB_gameboy_t *gb, const char *path) +{ + if (!gb->cartridge_type->has_battery) return 0; // Nothing to save. + if (gb->mbc_ram_size == 0 && !gb->cartridge_type->has_rtc) return 0; /* Claims to have battery, but has no RAM or RTC */ + FILE *f = fopen(path, "wb"); + if (!f) { + GB_log(gb, "Could not open battery save: %s.\n", strerror(errno)); + return errno; + } + + if (fwrite(gb->mbc_ram, 1, gb->mbc_ram_size, f) != gb->mbc_ram_size) { + fclose(f); + return EIO; + } + if (gb->cartridge_type->has_rtc) { + if (fwrite(&gb->rtc_real, 1, sizeof(gb->rtc_real), f) != sizeof(gb->rtc_real)) { + fclose(f); + return EIO; + } + + if (fwrite(&gb->last_rtc_second, 1, sizeof(gb->last_rtc_second), f) != sizeof(gb->last_rtc_second)) { + fclose(f); + return EIO; + } + } + + errno = 0; + fclose(f); + return errno; +} + +/* Loading will silently stop if the format is incomplete */ +void GB_load_battery(GB_gameboy_t *gb, const char *path) +{ + FILE *f = fopen(path, "rb"); + if (!f) { + return; + } + + if (fread(gb->mbc_ram, 1, gb->mbc_ram_size, f) != gb->mbc_ram_size) { + goto reset_rtc; + } + + if (fread(&gb->rtc_real, 1, sizeof(gb->rtc_real), f) != sizeof(gb->rtc_real)) { + goto reset_rtc; + } + + if (fread(&gb->last_rtc_second, 1, sizeof(gb->last_rtc_second), f) != sizeof(gb->last_rtc_second)) { + goto reset_rtc; + } + + if (gb->last_rtc_second > time(NULL)) { + /* We must reset RTC here, or it will not advance. */ + goto reset_rtc; + } + + if (gb->last_rtc_second < 852076800) { /* 1/1/97. There weren't any RTC games that time, + so if the value we read is lower it means it wasn't + really RTC data. */ + goto reset_rtc; + } + goto exit; +reset_rtc: + gb->last_rtc_second = time(NULL); + gb->rtc_real.high |= 0x80; /* This gives the game a hint that the clock should be reset. */ +exit: + fclose(f); + return; +} + +void GB_run(GB_gameboy_t *gb) +{ + GB_cpu_run(gb); + if (gb->vblank_just_occured) { + GB_update_joyp(gb); + GB_rtc_run(gb); + } +} + +uint64_t GB_run_cycles(GB_gameboy_t *gb, uint32_t cycles) +{ + GB_update_joyp(gb); + GB_rtc_run(gb); + uint64_t start = gb->cycles_since_epoch; + uint64_t target = start + cycles; + while (gb->cycles_since_epoch < target) { + GB_run(gb); + } + return gb->cycles_since_epoch - start; +} + +uint64_t GB_epoch(GB_gameboy_t *gb) +{ + return gb->cycles_since_epoch; +} + +void GB_set_pixels_output(GB_gameboy_t *gb, uint32_t *output) +{ + gb->screen = output; +} + +void GB_set_vblank_callback(GB_gameboy_t *gb, GB_vblank_callback_t callback) +{ + gb->vblank_callback = callback; +} + +void GB_set_log_callback(GB_gameboy_t *gb, GB_log_callback_t callback) +{ + gb->log_callback = callback; +} + +void GB_set_input_callback(GB_gameboy_t *gb, GB_input_callback_t callback) +{ + gb->input_callback = callback; +} + +void GB_set_rgb_encode_callback(GB_gameboy_t *gb, GB_rgb_encode_callback_t callback) +{ + if (!gb->rgb_encode_callback && !gb->is_cgb) { + gb->sprite_palettes_rgb[4] = gb->sprite_palettes_rgb[0] = gb->background_palettes_rgb[0] = + callback(gb, 0xFF, 0xFF, 0xFF); + gb->sprite_palettes_rgb[5] = gb->sprite_palettes_rgb[1] = gb->background_palettes_rgb[1] = + callback(gb, 0xAA, 0xAA, 0xAA); + gb->sprite_palettes_rgb[6] = gb->sprite_palettes_rgb[2] = gb->background_palettes_rgb[2] = + callback(gb, 0x55, 0x55, 0x55); + gb->sprite_palettes_rgb[7] = gb->sprite_palettes_rgb[3] = gb->background_palettes_rgb[3] = + callback(gb, 0, 0, 0); + } + gb->rgb_encode_callback = callback; +} + +void GB_set_infrared_callback(GB_gameboy_t *gb, GB_infrared_callback_t callback) +{ + gb->infrared_callback = callback; +} + +void GB_set_infrared_input(GB_gameboy_t *gb, bool state) +{ + gb->infrared_input = state; + gb->cycles_since_input_ir_change = 0; + gb->ir_queue_length = 0; +} + +void GB_queue_infrared_input(GB_gameboy_t *gb, bool state, long cycles_after_previous_change) +{ + if (gb->ir_queue_length == GB_MAX_IR_QUEUE) { + GB_log(gb, "IR Queue is full\n"); + return; + } + gb->ir_queue[gb->ir_queue_length++] = (GB_ir_queue_item_t){state, cycles_after_previous_change}; +} + +void GB_set_rumble_callback(GB_gameboy_t *gb, GB_rumble_callback_t callback) +{ + gb->rumble_callback = callback; +} + +void GB_set_sample_callback(GB_gameboy_t *gb, GB_sample_callback_t callback) +{ + gb->sample_callback = callback; +} + +void GB_set_serial_transfer_start_callback(GB_gameboy_t *gb, GB_serial_transfer_start_callback_t callback) +{ + gb->serial_transfer_start_callback = callback; +} + +void GB_set_serial_transfer_end_callback(GB_gameboy_t *gb, GB_serial_transfer_end_callback_t callback) +{ + gb->serial_transfer_end_callback = callback; +} + +uint8_t GB_serial_get_data(GB_gameboy_t *gb) +{ + if (gb->io_registers[GB_IO_SC] & 1) { + /* Internal Clock */ + GB_log(gb, "Serial read request while using internal clock. \n"); + return 0xFF; + } + return gb->io_registers[GB_IO_SB]; +} +void GB_serial_set_data(GB_gameboy_t *gb, uint8_t data) +{ + if (gb->io_registers[GB_IO_SC] & 1) { + /* Internal Clock */ + GB_log(gb, "Serial write request while using internal clock. \n"); + return; + } + gb->io_registers[GB_IO_SB] = data; + gb->io_registers[GB_IO_IF] |= 8; +} + +void GB_disconnect_serial(GB_gameboy_t *gb) +{ + gb->serial_transfer_start_callback = NULL; + gb->serial_transfer_end_callback = NULL; + + /* Reset any internally-emulated device. Currently, only the printer. */ + memset(&gb->printer, 0, sizeof(gb->printer)); +} + +bool GB_is_inited(GB_gameboy_t *gb) +{ + return gb->magic == 'SAME'; +} + +bool GB_is_cgb(GB_gameboy_t *gb) +{ + return gb->is_cgb; +} + +void GB_set_rendering_disabled(GB_gameboy_t *gb, bool disabled) +{ + gb->disable_rendering = disabled; +} + +void *GB_get_user_data(GB_gameboy_t *gb) +{ + return gb->user_data; +} + +void GB_set_user_data(GB_gameboy_t *gb, void *data) +{ + gb->user_data = data; +} + +void GB_reset(GB_gameboy_t *gb) +{ + uint32_t mbc_ram_size = gb->mbc_ram_size; + bool cgb = gb->is_cgb; + // memset(gb, 0, (size_t)GB_GET_SECTION((GB_gameboy_t *) 0, unsaved)); + gb->version = GB_STRUCT_VERSION; + + gb->mbc_rom_bank = 1; + gb->last_rtc_second = time(NULL); + gb->cgb_ram_bank = 1; + gb->io_registers[GB_IO_JOYP] = 0xF; + gb->mbc_ram_size = mbc_ram_size; + if (cgb) { + gb->ram_size = 0x2000 * 8; + memset(gb->ram, 0, gb->ram_size); + gb->vram_size = 0x2000 * 2; + memset(gb->vram, 0, gb->vram_size); + + gb->is_cgb = true; + gb->cgb_mode = true; + gb->io_registers[GB_IO_OBP0] = gb->io_registers[GB_IO_OBP1] = 0x00; + } + else { + gb->ram_size = 0x2000; + memset(gb->ram, 0, gb->ram_size); + gb->vram_size = 0x2000; + memset(gb->vram, 0, gb->vram_size); + + if (gb->rgb_encode_callback) { + gb->sprite_palettes_rgb[4] = gb->sprite_palettes_rgb[0] = gb->background_palettes_rgb[0] = + gb->rgb_encode_callback(gb, 0xFF, 0xFF, 0xFF); + gb->sprite_palettes_rgb[5] = gb->sprite_palettes_rgb[1] = gb->background_palettes_rgb[1] = + gb->rgb_encode_callback(gb, 0xAA, 0xAA, 0xAA); + gb->sprite_palettes_rgb[6] = gb->sprite_palettes_rgb[2] = gb->background_palettes_rgb[2] = + gb->rgb_encode_callback(gb, 0x55, 0x55, 0x55); + gb->sprite_palettes_rgb[7] = gb->sprite_palettes_rgb[3] = gb->background_palettes_rgb[3] = + gb->rgb_encode_callback(gb, 0, 0, 0); + } + gb->io_registers[GB_IO_OBP0] = gb->io_registers[GB_IO_OBP1] = 0xFF; + } + /* The serial interrupt always occur on the 0xF8th cycle of every 0x100 cycle since boot. */ + gb->serial_cycles = 0x100 - 0xF8; + gb->io_registers[GB_IO_SC] = 0x7E; + gb->magic = (uintptr_t)'SAME'; +} + +void GB_switch_model_and_reset(GB_gameboy_t *gb, bool is_cgb) +{ + if (is_cgb) { + gb->ram = realloc(gb->ram, gb->ram_size = 0x2000 * 8); + gb->vram = realloc(gb->vram, gb->vram_size = 0x2000 * 2); + } + else { + gb->ram = realloc(gb->ram, gb->ram_size = 0x2000); + gb->vram = realloc(gb->vram, gb->vram_size = 0x2000); + } + gb->is_cgb = is_cgb; + GB_reset(gb); + +} + +void *GB_get_direct_access(GB_gameboy_t *gb, GB_direct_access_t access, size_t *size, uint16_t *bank) +{ + /* Set size and bank to dummy pointers if not set */ + size_t dummy_size; + uint16_t dummy_bank; + if (!size) { + size = &dummy_size; + } + + if (!bank) { + bank = &dummy_bank; + } + + + switch (access) { + case GB_DIRECT_ACCESS_ROM: + *size = gb->rom_size; + *bank = gb->mbc_rom_bank; + return gb->rom; + case GB_DIRECT_ACCESS_RAM: + *size = gb->ram_size; + *bank = gb->cgb_ram_bank; + return gb->ram; + case GB_DIRECT_ACCESS_CART_RAM: + *size = gb->mbc_ram_size; + *bank = gb->mbc_ram_bank; + return gb->mbc_ram; + case GB_DIRECT_ACCESS_VRAM: + *size = gb->vram_size; + *bank = gb->cgb_vram_bank; + return gb->vram; + case GB_DIRECT_ACCESS_HRAM: + *size = sizeof(gb->hram); + *bank = 0; + return &gb->hram; + case GB_DIRECT_ACCESS_IO: + *size = sizeof(gb->io_registers); + *bank = 0; + return &gb->io_registers; + case GB_DIRECT_ACCESS_BOOTROM: + *size = gb->is_cgb? sizeof(gb->boot_rom) : 0x100; + *bank = 0; + return &gb->boot_rom; + case GB_DIRECT_ACCESS_OAM: + *size = sizeof(gb->oam); + *bank = 0; + return &gb->oam; + case GB_DIRECT_ACCESS_BGP: + *size = sizeof(gb->background_palettes_data); + *bank = 0; + return &gb->background_palettes_data; + case GB_DIRECT_ACCESS_OBP: + *size = sizeof(gb->sprite_palettes_data); + *bank = 0; + return &gb->sprite_palettes_data; + default: + *size = 0; + *bank = 0; + return NULL; + } +} + +void GB_set_lagged(GB_gameboy_t *gb, bool lagged) +{ + gb->lagged = lagged; +} + +bool GB_get_lagged(GB_gameboy_t *gb) +{ + return gb->lagged; +} + diff --git a/waterbox/sameboy/gb.h b/waterbox/sameboy/gb.h new file mode 100644 index 0000000000..098a3d2ea3 --- /dev/null +++ b/waterbox/sameboy/gb.h @@ -0,0 +1,523 @@ +#ifndef GB_h +#define GB_h +#include +#include +#include +#include +#include + +#include "gb_struct_def.h" + +#include "apu.h" +#include "camera.h" +#include "display.h" +#include "joypad.h" +#include "mbc.h" +#include "memory.h" +#include "printer.h" +#include "timing.h" +#include "z80_cpu.h" + +#define GB_STRUCT_VERSION 11 + +enum { + GB_REGISTER_AF, + GB_REGISTER_BC, + GB_REGISTER_DE, + GB_REGISTER_HL, + GB_REGISTER_SP, + GB_REGISTERS_16_BIT /* Count */ +}; + +/* Todo: Actually use these! */ +enum { + GB_CARRY_FLAG = 16, + GB_HALF_CARRY_FLAG = 32, + GB_SUBSTRACT_FLAG = 64, + GB_ZERO_FLAG = 128, +}; + +#define GB_MAX_IR_QUEUE 256 + +enum { + /* Joypad and Serial */ + GB_IO_JOYP = 0x00, // Joypad (R/W) + GB_IO_SB = 0x01, // Serial transfer data (R/W) + GB_IO_SC = 0x02, // Serial Transfer Control (R/W) + + /* Missing */ + + /* Timers */ + GB_IO_DIV = 0x04, // Divider Register (R/W) + GB_IO_TIMA = 0x05, // Timer counter (R/W) + GB_IO_TMA = 0x06, // Timer Modulo (R/W) + GB_IO_TAC = 0x07, // Timer Control (R/W) + + /* Missing */ + + GB_IO_IF = 0x0f, // Interrupt Flag (R/W) + + /* Sound */ + GB_IO_NR10 = 0x10, // Channel 1 Sweep register (R/W) + GB_IO_NR11 = 0x11, // Channel 1 Sound length/Wave pattern duty (R/W) + GB_IO_NR12 = 0x12, // Channel 1 Volume Envelope (R/W) + GB_IO_NR13 = 0x13, // Channel 1 Frequency lo (Write Only) + GB_IO_NR14 = 0x14, // Channel 1 Frequency hi (R/W) + GB_IO_NR21 = 0x16, // Channel 2 Sound Length/Wave Pattern Duty (R/W) + GB_IO_NR22 = 0x17, // Channel 2 Volume Envelope (R/W) + GB_IO_NR23 = 0x18, // Channel 2 Frequency lo data (W) + GB_IO_NR24 = 0x19, // Channel 2 Frequency hi data (R/W) + GB_IO_NR30 = 0x1a, // Channel 3 Sound on/off (R/W) + GB_IO_NR31 = 0x1b, // Channel 3 Sound Length + GB_IO_NR32 = 0x1c, // Channel 3 Select output level (R/W) + GB_IO_NR33 = 0x1d, // Channel 3 Frequency's lower data (W) + GB_IO_NR34 = 0x1e, // Channel 3 Frequency's higher data (R/W) + + /* Missing */ + + GB_IO_NR41 = 0x20, // Channel 4 Sound Length (R/W) + GB_IO_NR42 = 0x21, // Channel 4 Volume Envelope (R/W) + GB_IO_NR43 = 0x22, // Channel 4 Polynomial Counter (R/W) + GB_IO_NR44 = 0x23, // Channel 4 Counter/consecutive, Inital (R/W) + GB_IO_NR50 = 0x24, // Channel control / ON-OFF / Volume (R/W) + GB_IO_NR51 = 0x25, // Selection of Sound output terminal (R/W) + GB_IO_NR52 = 0x26, // Sound on/off + + /* Missing */ + + GB_IO_WAV_START = 0x30, // Wave pattern start + GB_IO_WAV_END = 0x3f, // Wave pattern end + + /* Graphics */ + GB_IO_LCDC = 0x40, // LCD Control (R/W) + GB_IO_STAT = 0x41, // LCDC Status (R/W) + GB_IO_SCY = 0x42, // Scroll Y (R/W) + GB_IO_SCX = 0x43, // Scroll X (R/W) + GB_IO_LY = 0x44, // LCDC Y-Coordinate (R) + GB_IO_LYC = 0x45, // LY Compare (R/W) + GB_IO_DMA = 0x46, // DMA Transfer and Start Address (W) + GB_IO_BGP = 0x47, // BG Palette Data (R/W) - Non CGB Mode Only + GB_IO_OBP0 = 0x48, // Object Palette 0 Data (R/W) - Non CGB Mode Only + GB_IO_OBP1 = 0x49, // Object Palette 1 Data (R/W) - Non CGB Mode Only + GB_IO_WY = 0x4a, // Window Y Position (R/W) + GB_IO_WX = 0x4b, // Window X Position minus 7 (R/W) + // Has some undocumented compatibility flags written at boot. + // Unfortunately it is not readable or writable after boot has finished, so research of this + // register is quite limited. The value written to this register, however, can be controlled + // in some cases. + GB_IO_DMG_EMULATION = 0x4c, + + /* General CGB features */ + GB_IO_KEY1 = 0x4d, // CGB Mode Only - Prepare Speed Switch + + /* Missing */ + + GB_IO_VBK = 0x4f, // CGB Mode Only - VRAM Bank + GB_IO_BIOS = 0x50, // Write to disable the BIOS mapping + + /* CGB DMA */ + GB_IO_HDMA1 = 0x51, // CGB Mode Only - New DMA Source, High + GB_IO_HDMA2 = 0x52, // CGB Mode Only - New DMA Source, Low + GB_IO_HDMA3 = 0x53, // CGB Mode Only - New DMA Destination, High + GB_IO_HDMA4 = 0x54, // CGB Mode Only - New DMA Destination, Low + GB_IO_HDMA5 = 0x55, // CGB Mode Only - New DMA Length/Mode/Start + + /* IR */ + GB_IO_RP = 0x56, // CGB Mode Only - Infrared Communications Port + + /* Missing */ + + /* CGB Paletts */ + GB_IO_BGPI = 0x68, // CGB Mode Only - Background Palette Index + GB_IO_BGPD = 0x69, // CGB Mode Only - Background Palette Data + GB_IO_OBPI = 0x6a, // CGB Mode Only - Sprite Palette Index + GB_IO_OBPD = 0x6b, // CGB Mode Only - Sprite Palette Data + + // 1 is written for DMG ROMs on a CGB. Does not appear to have an effect. + GB_IO_DMG_EMULATION_INDICATION = 0x6c, // (FEh) Bit 0 (Read/Write) + + /* Missing */ + + GB_IO_SVBK = 0x70, // CGB Mode Only - WRAM Bank + GB_IO_UNKNOWN2 = 0x72, // (00h) - Bit 0-7 (Read/Write) + GB_IO_UNKNOWN3 = 0x73, // (00h) - Bit 0-7 (Read/Write) + GB_IO_UNKNOWN4 = 0x74, // (00h) - Bit 0-7 (Read/Write) - CGB Mode Only + GB_IO_UNKNOWN5 = 0x75, // (8Fh) - Bit 4-6 (Read/Write) + GB_IO_PCM_12 = 0x76, // Channels 1 and 2 amplitudes + GB_IO_PCM_34 = 0x77, // Channels 3 and 4 amplitudes + GB_IO_UNKNOWN8 = 0x7F, // Unknown, write only +}; + +typedef enum { + GB_LOG_BOLD = 1, + GB_LOG_DASHED_UNDERLINE = 2, + GB_LOG_UNDERLINE = 4, + GB_LOG_UNDERLINE_MASK = GB_LOG_DASHED_UNDERLINE | GB_LOG_UNDERLINE +} GB_log_attributes; + +#ifdef GB_INTERNAL +#define LCDC_PERIOD 70224 +#define CPU_FREQUENCY 0x400000 +#define DIV_CYCLES (0x100) +#define INTERNAL_DIV_CYCLES (0x40000) +#define FRAME_LENGTH 16742706 // in nanoseconds +#endif + +typedef void (*GB_vblank_callback_t)(GB_gameboy_t *gb); +typedef void (*GB_log_callback_t)(GB_gameboy_t *gb, const char *string, GB_log_attributes attributes); +typedef void (*GB_input_callback_t)(GB_gameboy_t *gb); +typedef uint32_t (*GB_rgb_encode_callback_t)(GB_gameboy_t *gb, uint8_t r, uint8_t g, uint8_t b); +typedef void (*GB_infrared_callback_t)(GB_gameboy_t *gb, bool on, long cycles_since_last_update); +typedef void (*GB_rumble_callback_t)(GB_gameboy_t *gb, bool rumble_on); +typedef void (*GB_serial_transfer_start_callback_t)(GB_gameboy_t *gb, uint8_t byte_to_send); +typedef uint8_t (*GB_serial_transfer_end_callback_t)(GB_gameboy_t *gb); +typedef void (*GB_sample_callback_t)(GB_gameboy_t *gb, GB_sample_t sample, uint64_t clock); +typedef void (*GB_scanline_callback_t)(uint8_t lcdc); + +typedef struct { + bool state; + long delay; +} GB_ir_queue_item_t; + +/* When state saving, each section is dumped independently of other sections. + This allows adding data to the end of the section without worrying about future compatibility. + Some other changes might be "safe" as well. + This struct is not packed, but dumped sections exclusively use types that have the same alignment in both 32 and 64 + bit platforms. */ + +/* We make sure bool is 1 for cross-platform save state compatibility. */ +/* Todo: We might want to typedef our own bool if this prevents SameBoy from working on specific platforms. */ +_Static_assert(sizeof(bool) == 1, "sizeof(bool) != 1"); + +#ifdef GB_INTERNAL +struct GB_gameboy_s { +#else +struct GB_gameboy_internal_s { +#endif + /* The magic makes sure a state file is: + - Indeed a SameBoy state file. + - Has the same endianess has the current platform. */ + volatile uint32_t magic; + /* The version field makes sure we don't load save state files with a completely different structure. + This happens when struct fields are removed/resized in an backward incompatible manner. */ + uint32_t version; + + /* Registers */ + uint16_t pc; + union { + uint16_t registers[GB_REGISTERS_16_BIT]; + struct { + uint16_t af, + bc, + de, + hl, + sp; + }; + struct { +#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + uint8_t a, f, + b, c, + d, e, + h, l; +#elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + uint8_t f, a, + c, b, + e, d, + l, h; +#else +#error Unable to detect endianess +#endif + }; + + }; + uint8_t ime; + uint8_t interrupt_enable; + uint8_t cgb_ram_bank; + + /* CPU and General Hardware Flags*/ + bool is_sgb; + bool cgb_mode; + bool is_cgb; + bool cgb_double_speed; + bool halted; + bool stopped; + bool boot_rom_finished; + bool ime_toggle; /* ei (and di in CGB) have delayed effects.*/ + bool halt_bug; + + /* Misc state */ + bool infrared_input; + GB_printer_t printer; + + /* DMA and HDMA */ + bool hdma_on; + bool hdma_on_hblank; + uint8_t hdma_steps_left; + uint16_t hdma_cycles; + uint16_t hdma_current_src, hdma_current_dest; + + uint8_t dma_steps_left; + uint8_t dma_current_dest; + uint16_t dma_current_src; + int16_t dma_cycles; + bool is_dma_restarting; + + /* MBC */ + uint16_t mbc_rom_bank; + uint8_t mbc_ram_bank; + uint32_t mbc_ram_size; + bool mbc_ram_enable; + union { + struct { + uint8_t bank_low:5; + uint8_t bank_high:2; + uint8_t padding:1; // Save state compatibility with 0.9 + uint8_t mode:1; + } mbc1; + + struct { + uint8_t rom_bank:4; + } mbc2; + + struct { + uint8_t rom_bank:7; + uint8_t padding:1; + uint8_t ram_bank:4; + } mbc3; + + struct { + uint8_t rom_bank_low; + uint8_t rom_bank_high:1; + uint8_t ram_bank:4; + } mbc5; + + struct { + uint8_t bank_low:6; + uint8_t bank_high:3; + uint8_t mode:1; + } huc1; + + struct { + uint8_t rom_bank; + uint8_t ram_bank; + } huc3; + }; + uint16_t mbc_rom0_bank; /* For some MBC1 wirings. */ + bool camera_registers_mapped; + uint8_t camera_registers[0x36]; + bool rumble_state; + + + /* HRAM and HW Registers */ + uint8_t hram[0xFFFF - 0xFF80]; + uint8_t io_registers[0x80]; + + /* Timing */ + uint32_t display_cycles; + uint32_t div_cycles; + uint8_t tima_reload_state; /* After TIMA overflows, it becomes 0 for 4 cycles before actually reloading. */ + uint16_t serial_cycles; /* This field changed its meaning in v0.10 */ + uint16_t serial_length; + + /* APU */ + GB_apu_t apu; + + /* RTC */ + union { + struct { + uint8_t seconds; + uint8_t minutes; + uint8_t hours; + uint8_t days; + uint8_t high; + }; + uint8_t data[5]; + } rtc_real, rtc_latched; + time_t last_rtc_second; + bool rtc_latch; + + /* Video Display */ + uint32_t vram_size; // Different between CGB and DMG + uint8_t cgb_vram_bank; + uint8_t oam[0xA0]; + uint8_t background_palettes_data[0x40]; + uint8_t sprite_palettes_data[0x40]; + uint32_t background_palettes_rgb[0x20]; + uint32_t sprite_palettes_rgb[0x20]; + int16_t previous_lcdc_x; + bool stat_interrupt_line; + uint8_t effective_scx; + uint8_t current_window_line; + /* The LCDC will skip the first frame it renders after turning it on. + On the CGB, a frame is not skipped if the previous frame was skipped as well. + See https://www.reddit.com/r/EmuDev/comments/6exyxu/ */ + enum { + GB_FRAMESKIP_LCD_TURNED_ON, // On a DMG, the LCD renders a blank screen during this state, + // on a CGB, the previous frame is repeated (which might be + // blank if the LCD was off for more than a few cycles) + GB_FRAMESKIP_FIRST_FRAME_SKIPPED, // This state is 'skipped' when emulating a DMG + GB_FRAMESKIP_SECOND_FRAME_RENDERED, + } frame_skip_state; + bool first_scanline; // The very first scan line after turning the LCD behaves differently. + bool oam_read_blocked; + bool vram_read_blocked; + bool oam_write_blocked; + bool vram_write_blocked; + + /* Unsaved data. This includes all pointers, as well as everything that shouldn't be on a save state */ + /* This data is reserved on reset and must come last in the struct */ + /* ROM */ + uint8_t *rom; + uint32_t rom_size; + const GB_cartridge_t *cartridge_type; + enum { + GB_STANDARD_MBC1_WIRING, + GB_MBC1M_WIRING, + } mbc1_wiring; + + /* Various RAMs */ + uint8_t *ram; + uint8_t *vram; + uint8_t *mbc_ram; + + /* I/O */ + uint32_t *screen; + int keys; + bool lagged; + + /* Timing */ + uint64_t cycles_since_epoch; + + /* Callbacks */ + void *user_data; + GB_log_callback_t log_callback; + GB_input_callback_t input_callback; + GB_rgb_encode_callback_t rgb_encode_callback; + GB_vblank_callback_t vblank_callback; + GB_infrared_callback_t infrared_callback; + GB_camera_get_pixel_callback_t camera_get_pixel_callback; + GB_camera_update_request_callback_t camera_update_request_callback; + GB_rumble_callback_t rumble_callback; + GB_serial_transfer_start_callback_t serial_transfer_start_callback; + GB_serial_transfer_end_callback_t serial_transfer_end_callback; + GB_sample_callback_t sample_callback; + + GB_scanline_callback_t scanline_callback; + int scanline_callback_ly; + + /* IR */ + long cycles_since_ir_change; + long cycles_since_input_ir_change; + GB_ir_queue_item_t ir_queue[GB_MAX_IR_QUEUE]; + size_t ir_queue_length; + + /* Breakpoints */ + uint16_t n_breakpoints; + struct GB_breakpoint_s *breakpoints; + + /* SLD (Todo: merge with backtrace) */ + bool stack_leak_detection; + int debug_call_depth; + uint16_t sp_for_call_depth[0x200]; /* Should be much more than enough */ + uint16_t addr_for_call_depth[0x200]; + + /* Backtrace */ + unsigned int backtrace_size; + uint16_t backtrace_sps[0x200]; + struct { + uint16_t bank; + uint16_t addr; + } backtrace_returns[0x200]; + + /* Misc */ + bool disable_rendering; + uint32_t ram_size; // Different between CGB and DMG + uint8_t boot_rom[0x900]; + bool vblank_just_occured; // For slow operations involving syscalls; these should only run once per vblank + + int64_t frontend_rtc_time; +}; + +#ifndef GB_INTERNAL +struct GB_gameboy_s { + char __internal[sizeof(struct GB_gameboy_internal_s)]; +}; +#endif + + +#ifndef __printflike +/* Missing from Linux headers. */ +#define __printflike(fmtarg, firstvararg) \ +__attribute__((__format__ (__printf__, fmtarg, firstvararg))) +#endif + +void GB_init(GB_gameboy_t *gb); +void GB_init_sgb(GB_gameboy_t *gb); +void GB_init_cgb(GB_gameboy_t *gb); +bool GB_is_inited(GB_gameboy_t *gb); +bool GB_is_cgb(GB_gameboy_t *gb); +void GB_free(GB_gameboy_t *gb); +void GB_reset(GB_gameboy_t *gb); +void GB_switch_model_and_reset(GB_gameboy_t *gb, bool is_cgb); +void GB_run(GB_gameboy_t *gb); +uint64_t GB_run_cycles(GB_gameboy_t *gb, uint32_t cycles); +uint64_t GB_epoch(GB_gameboy_t *gb); + +typedef enum { + GB_DIRECT_ACCESS_ROM, + GB_DIRECT_ACCESS_RAM, + GB_DIRECT_ACCESS_CART_RAM, + GB_DIRECT_ACCESS_VRAM, + GB_DIRECT_ACCESS_HRAM, + GB_DIRECT_ACCESS_IO, /* Warning: Some registers can only be read/written correctly via GB_memory_read/write. */ + GB_DIRECT_ACCESS_BOOTROM, + GB_DIRECT_ACCESS_OAM, + GB_DIRECT_ACCESS_BGP, + GB_DIRECT_ACCESS_OBP, +} GB_direct_access_t; + +/* Returns a mutable pointer to various hardware memories. If that memory is banked, the current bank + is returned at *bank, even if only a portion of the memory is banked. */ +void *GB_get_direct_access(GB_gameboy_t *gb, GB_direct_access_t access, size_t *size, uint16_t *bank); + +void *GB_get_user_data(GB_gameboy_t *gb); +void GB_set_user_data(GB_gameboy_t *gb, void *data); + +int GB_load_boot_rom(GB_gameboy_t *gb, const char *path); +int GB_load_rom(GB_gameboy_t *gb, const char *path); + +int GB_save_battery(GB_gameboy_t *gb, const char *path); +void GB_load_battery(GB_gameboy_t *gb, const char *path); + +void GB_set_rendering_disabled(GB_gameboy_t *gb, bool disabled); + +void GB_log(GB_gameboy_t *gb, const char *fmt, ...) __printflike(2, 3); +void GB_attributed_log(GB_gameboy_t *gb, GB_log_attributes attributes, const char *fmt, ...) __printflike(3, 4); + +void GB_set_pixels_output(GB_gameboy_t *gb, uint32_t *output); + +void GB_set_infrared_input(GB_gameboy_t *gb, bool state); +void GB_queue_infrared_input(GB_gameboy_t *gb, bool state, long cycles_after_previous_change); + +void GB_set_vblank_callback(GB_gameboy_t *gb, GB_vblank_callback_t callback); +void GB_set_log_callback(GB_gameboy_t *gb, GB_log_callback_t callback); +void GB_set_input_callback(GB_gameboy_t *gb, GB_input_callback_t callback); +void GB_set_rgb_encode_callback(GB_gameboy_t *gb, GB_rgb_encode_callback_t callback); +void GB_set_infrared_callback(GB_gameboy_t *gb, GB_infrared_callback_t callback); +void GB_set_rumble_callback(GB_gameboy_t *gb, GB_rumble_callback_t callback); +void GB_set_sample_callback(GB_gameboy_t *gb, GB_sample_callback_t callback); + +/* These APIs are used when using internal clock */ +void GB_set_serial_transfer_start_callback(GB_gameboy_t *gb, GB_serial_transfer_start_callback_t callback); +void GB_set_serial_transfer_end_callback(GB_gameboy_t *gb, GB_serial_transfer_end_callback_t callback); + +/* These APIs are used when using external clock */ +uint8_t GB_serial_get_data(GB_gameboy_t *gb); +void GB_serial_set_data(GB_gameboy_t *gb, uint8_t data); + +void GB_disconnect_serial(GB_gameboy_t *gb); + +void GB_set_lagged(GB_gameboy_t *gb, bool lagged); +bool GB_get_lagged(GB_gameboy_t *gb); + +#endif /* GB_h */ diff --git a/waterbox/sameboy/gb_struct_def.h b/waterbox/sameboy/gb_struct_def.h new file mode 100644 index 0000000000..0e0ebd12ee --- /dev/null +++ b/waterbox/sameboy/gb_struct_def.h @@ -0,0 +1,5 @@ +#ifndef gb_struct_def_h +#define gb_struct_def_h +struct GB_gameboy_s; +typedef struct GB_gameboy_s GB_gameboy_t; +#endif diff --git a/waterbox/sameboy/joypad.c b/waterbox/sameboy/joypad.c new file mode 100644 index 0000000000..0cad7ab084 --- /dev/null +++ b/waterbox/sameboy/joypad.c @@ -0,0 +1,48 @@ +#include +#include "gb.h" +#include + +void GB_update_joyp(GB_gameboy_t *gb) +{ + uint8_t key_selection = 0; + uint8_t previous_state = 0; + + /* Todo: add delay to key selection */ + previous_state = gb->io_registers[GB_IO_JOYP] & 0xF; + key_selection = gb->io_registers[GB_IO_JOYP] >> 4 & 3; + gb->io_registers[GB_IO_JOYP] &= 0xF0; + switch (key_selection) { + case 3: + /* Nothing is wired, all up */ + gb->io_registers[GB_IO_JOYP] |= 0x0F; + break; + + case 2: + /* Direction keys */ + gb->io_registers[GB_IO_JOYP] |= ~gb->keys >> 4 & 0xf; + break; + + case 1: + /* Other keys */ + gb->io_registers[GB_IO_JOYP] |= ~gb->keys & 0xf; + break; + + case 0: + /* Todo: verifiy this is correct */ + gb->io_registers[GB_IO_JOYP] |= ~(gb->keys >> 4 & gb->keys) & 0xf; + break; + + default: + break; + } + if (previous_state != (gb->io_registers[GB_IO_JOYP] & 0xF)) { + /* Todo: disable when emulating CGB */ + gb->io_registers[GB_IO_IF] |= 0x10; + } + gb->io_registers[GB_IO_JOYP] |= 0xC0; // No SGB support +} + +void GB_set_key_state(GB_gameboy_t *gb, int keys) +{ + gb->keys = keys; +} diff --git a/waterbox/sameboy/joypad.h b/waterbox/sameboy/joypad.h new file mode 100644 index 0000000000..f7ffdfdec4 --- /dev/null +++ b/waterbox/sameboy/joypad.h @@ -0,0 +1,10 @@ +#ifndef joypad_h +#define joypad_h +#include "gb_struct_def.h" + +void GB_set_key_state(GB_gameboy_t *gb, int keys); + +#ifdef GB_INTERNAL +void GB_update_joyp(GB_gameboy_t *gb); +#endif +#endif /* joypad_h */ diff --git a/waterbox/sameboy/mbc.c b/waterbox/sameboy/mbc.c new file mode 100644 index 0000000000..d3791a180f --- /dev/null +++ b/waterbox/sameboy/mbc.c @@ -0,0 +1,154 @@ +#include +#include +#include +#include "gb.h" + +const GB_cartridge_t GB_cart_defs[256] = { + // From http://gbdev.gg8.se/wiki/articles/The_Cartridge_Header#0147_-_Cartridge_Type + /* MBC SUBTYPE RAM BAT. RTC RUMB. */ + { GB_NO_MBC, GB_STANDARD_MBC, false, false, false, false}, // 00h ROM ONLY + { GB_MBC1 , GB_STANDARD_MBC, false, false, false, false}, // 01h MBC1 + { GB_MBC1 , GB_STANDARD_MBC, true , false, false, false}, // 02h MBC1+RAM + { GB_MBC1 , GB_STANDARD_MBC, true , true , false, false}, // 03h MBC1+RAM+BATTERY + [5] = + { GB_MBC2 , GB_STANDARD_MBC, true , false, false, false}, // 05h MBC2 + { GB_MBC2 , GB_STANDARD_MBC, true , true , false, false}, // 06h MBC2+BATTERY + [8] = + { GB_NO_MBC, GB_STANDARD_MBC, true , false, false, false}, // 08h ROM+RAM + { GB_NO_MBC, GB_STANDARD_MBC, true , true , false, false}, // 09h ROM+RAM+BATTERY + [0xB] = + /* Todo: Not supported yet */ + { GB_NO_MBC, GB_STANDARD_MBC, false, false, false, false}, // 0Bh MMM01 + { GB_NO_MBC, GB_STANDARD_MBC, false, false, false, false}, // 0Ch MMM01+RAM + { GB_NO_MBC, GB_STANDARD_MBC, false, false, false, false}, // 0Dh MMM01+RAM+BATTERY + [0xF] = + { GB_MBC3 , GB_STANDARD_MBC, false, true, true , false}, // 0Fh MBC3+TIMER+BATTERY + { GB_MBC3 , GB_STANDARD_MBC, true , true, true , false}, // 10h MBC3+TIMER+RAM+BATTERY + { GB_MBC3 , GB_STANDARD_MBC, false, false, false, false}, // 11h MBC3 + { GB_MBC3 , GB_STANDARD_MBC, true , false, false, false}, // 12h MBC3+RAM + { GB_MBC3 , GB_STANDARD_MBC, true , true , false, false}, // 13h MBC3+RAM+BATTERY + [0x19] = + { GB_MBC5 , GB_STANDARD_MBC, false, false, false, false}, // 19h MBC5 + { GB_MBC5 , GB_STANDARD_MBC, true , false, false, false}, // 1Ah MBC5+RAM + { GB_MBC5 , GB_STANDARD_MBC, true , true , false, false}, // 1Bh MBC5+RAM+BATTERY + { GB_MBC5 , GB_STANDARD_MBC, false, false, false, true }, // 1Ch MBC5+RUMBLE + { GB_MBC5 , GB_STANDARD_MBC, true , false, false, true }, // 1Dh MBC5+RUMBLE+RAM + { GB_MBC5 , GB_STANDARD_MBC, true , true , false, true }, // 1Eh MBC5+RUMBLE+RAM+BATTERY + [0xFC] = + { GB_MBC5 , GB_CAMERA , true , true , false, false}, // FCh POCKET CAMERA + { GB_NO_MBC, GB_STANDARD_MBC, false, false, false, false}, // FDh BANDAI TAMA5 (Todo: Not supported) + { GB_HUC3 , GB_STANDARD_MBC, true , true , false, false}, // FEh HuC3 (Todo: Mapper support only) + { GB_HUC1 , GB_STANDARD_MBC, true , true , false, false}, // FFh HuC1+RAM+BATTERY (Todo: No IR bindings) +}; + +void GB_update_mbc_mappings(GB_gameboy_t *gb) +{ + switch (gb->cartridge_type->mbc_type) { + case GB_NO_MBC: return; + case GB_MBC1: + switch (gb->mbc1_wiring) { + case GB_STANDARD_MBC1_WIRING: + gb->mbc_rom_bank = gb->mbc1.bank_low | (gb->mbc1.bank_high << 5); + if (gb->mbc1.mode == 0) { + gb->mbc_ram_bank = 0; + gb->mbc_rom0_bank = 0; + } + else { + gb->mbc_ram_bank = gb->mbc1.bank_high; + gb->mbc_rom0_bank = gb->mbc1.bank_high << 5; + } + if ((gb->mbc_rom_bank & 0x1F) == 0) { + gb->mbc_rom_bank++; + } + break; + case GB_MBC1M_WIRING: + gb->mbc_rom_bank = (gb->mbc1.bank_low & 0xF) | (gb->mbc1.bank_high << 4); + if (gb->mbc1.mode == 0) { + gb->mbc_ram_bank = 0; + gb->mbc_rom0_bank = 0; + } + else { + gb->mbc_rom0_bank = gb->mbc1.bank_high << 4; + gb->mbc_ram_bank = 0; + } + if ((gb->mbc1.bank_low & 0x1F) == 0) { + gb->mbc_rom_bank++; + } + break; + } + break; + case GB_MBC2: + gb->mbc_rom_bank = gb->mbc2.rom_bank; + if ((gb->mbc_rom_bank & 0xF) == 0) { + gb->mbc_rom_bank = 1; + } + break; + case GB_MBC3: + gb->mbc_rom_bank = gb->mbc3.rom_bank; + gb->mbc_ram_bank = gb->mbc3.ram_bank; + if (gb->mbc_rom_bank == 0) { + gb->mbc_rom_bank = 1; + } + break; + case GB_MBC5: + gb->mbc_rom_bank = gb->mbc5.rom_bank_low | (gb->mbc5.rom_bank_high << 8); + gb->mbc_ram_bank = gb->mbc5.ram_bank; + break; + case GB_HUC1: + if (gb->huc1.mode == 0) { + gb->mbc_rom_bank = gb->huc1.bank_low | (gb->mbc1.bank_high << 6); + gb->mbc_ram_bank = 0; + } + else { + gb->mbc_rom_bank = gb->huc1.bank_low; + gb->mbc_ram_bank = gb->huc1.bank_high; + } + break; + case GB_HUC3: + gb->mbc_rom_bank = gb->huc3.rom_bank; + gb->mbc_ram_bank = gb->huc3.ram_bank; + break; + } +} + +void GB_configure_cart(GB_gameboy_t *gb) +{ + gb->cartridge_type = &GB_cart_defs[gb->rom[0x147]]; + + if (gb->rom[0x147] == 0 && gb->rom_size > 0x8000) { + GB_log(gb, "ROM header reports no MBC, but file size is over 32Kb. Assuming cartridge uses MBC3.\n"); + gb->cartridge_type = &GB_cart_defs[0x11]; + } + else if (gb->rom[0x147] != 0 && memcmp(gb->cartridge_type, &GB_cart_defs[0], sizeof(GB_cart_defs[0])) == 0) { + GB_log(gb, "Cartridge type %02x is not yet supported.\n", gb->rom[0x147]); + } + + if (gb->cartridge_type->has_ram) { + if (gb->cartridge_type->mbc_type == GB_MBC2) { + gb->mbc_ram_size = 0x200; + } + else { + static const int ram_sizes[256] = {0, 0x800, 0x2000, 0x8000, 0x20000, 0x10000}; + gb->mbc_ram_size = ram_sizes[gb->rom[0x149]]; + } + gb->mbc_ram = malloc(gb->mbc_ram_size); + + /* Todo: Some games assume unintialized MBC RAM is 0xFF. It this true for all cartridges types? */ + memset(gb->mbc_ram, 0xFF, gb->mbc_ram_size); + } + + /* MBC1 has at least 3 types of wiring (We currently support two (Standard and 4bit-MBC1M) of these). + See http://forums.nesdev.com/viewtopic.php?f=20&t=14099 */ + + /* Attempt to "guess" wiring */ + if (gb->cartridge_type->mbc_type == GB_MBC1) { + if (gb->rom_size >= 0x44000 && memcmp(gb->rom + 0x104, gb->rom + 0x40104, 0x30) == 0) { + gb->mbc1_wiring = GB_MBC1M_WIRING; + } + } + + /* Set MBC5's bank to 1 correctly */ + if (gb->cartridge_type->mbc_type == GB_MBC5) { + gb->mbc5.rom_bank_low = 1; + } +} diff --git a/waterbox/sameboy/mbc.h b/waterbox/sameboy/mbc.h new file mode 100644 index 0000000000..e7260f5643 --- /dev/null +++ b/waterbox/sameboy/mbc.h @@ -0,0 +1,31 @@ +#ifndef MBC_h +#define MBC_h +#include "gb_struct_def.h" + +typedef struct { + enum { + GB_NO_MBC, + GB_MBC1, + GB_MBC2, + GB_MBC3, + GB_MBC5, + GB_HUC1, /* Todo: HUC1 features are not emulated. Should be unified with the CGB IR sensor API. */ + GB_HUC3, + } mbc_type; + enum { + GB_STANDARD_MBC, + GB_CAMERA, + } mbc_subtype; + bool has_ram; + bool has_battery; + bool has_rtc; + bool has_rumble; +} GB_cartridge_t; + +#ifdef GB_INTERNAL +extern const GB_cartridge_t GB_cart_defs[256]; +void GB_update_mbc_mappings(GB_gameboy_t *gb); +void GB_configure_cart(GB_gameboy_t *gb); +#endif + +#endif /* MBC_h */ diff --git a/waterbox/sameboy/memory.c b/waterbox/sameboy/memory.c new file mode 100644 index 0000000000..6988beb4cd --- /dev/null +++ b/waterbox/sameboy/memory.c @@ -0,0 +1,733 @@ +#include +#include +#include "gb.h" +#include "sgb.h" + +typedef uint8_t GB_read_function_t(GB_gameboy_t *gb, uint16_t addr); +typedef void GB_write_function_t(GB_gameboy_t *gb, uint16_t addr, uint8_t value); + +typedef enum { + GB_BUS_MAIN, /* In DMG: Cart and RAM. In CGB: Cart only */ + GB_BUS_RAM, /* In CGB only. */ + GB_BUS_VRAM, + GB_BUS_INTERNAL, /* Anything in highram. Might not be the most correct name. */ +} GB_bus_t; + +static GB_bus_t bus_for_addr(GB_gameboy_t *gb, uint16_t addr) +{ + if (addr < 0x8000) { + return GB_BUS_MAIN; + } + if (addr < 0xA000) { + return GB_BUS_VRAM; + } + if (addr < 0xC000) { + return GB_BUS_MAIN; + } + if (addr < 0xFE00) { + return gb->is_cgb? GB_BUS_RAM : GB_BUS_MAIN; + } + return GB_BUS_INTERNAL; +} + +static bool is_addr_in_dma_use(GB_gameboy_t *gb, uint16_t addr) +{ + if (!gb->dma_steps_left || (gb->dma_cycles < 0 && !gb->is_dma_restarting)) return false; + return bus_for_addr(gb, addr) == bus_for_addr(gb, gb->dma_current_src); +} + +static uint8_t read_rom(GB_gameboy_t *gb, uint16_t addr) +{ + if (addr < 0x100 && !gb->boot_rom_finished) { + return gb->boot_rom[addr]; + } + + if (addr >= 0x200 && addr < 0x900 && gb->is_cgb && !gb->boot_rom_finished) { + return gb->boot_rom[addr]; + } + + if (!gb->rom_size) { + return 0xFF; + } + unsigned int effective_address = (addr & 0x3FFF) + gb->mbc_rom0_bank * 0x4000; + return gb->rom[effective_address & (gb->rom_size - 1)]; +} + +static uint8_t read_mbc_rom(GB_gameboy_t *gb, uint16_t addr) +{ + unsigned int effective_address = (addr & 0x3FFF) + gb->mbc_rom_bank * 0x4000; + return gb->rom[effective_address & (gb->rom_size - 1)]; +} + +static uint8_t read_vram(GB_gameboy_t *gb, uint16_t addr) +{ + if (gb->vram_read_blocked) { + return 0xFF; + } + return gb->vram[(addr & 0x1FFF) + (uint16_t) gb->cgb_vram_bank * 0x2000]; +} + +static uint8_t read_mbc_ram(GB_gameboy_t *gb, uint16_t addr) +{ + if ((!gb->mbc_ram_enable || !gb->mbc_ram_size) && + gb->cartridge_type->mbc_subtype != GB_CAMERA && + gb->cartridge_type->mbc_type != GB_HUC1) return 0xFF; + + if (gb->cartridge_type->has_rtc && gb->mbc_ram_bank >= 8 && gb->mbc_ram_bank <= 0xC) { + /* RTC read */ + gb->rtc_latched.high |= ~0xC1; /* Not all bytes in RTC high are used. */ + return gb->rtc_latched.data[gb->mbc_ram_bank - 8]; + } + + if (gb->camera_registers_mapped) { + return GB_camera_read_register(gb, addr); + } + + if (!gb->mbc_ram) { + return 0xFF; + } + + if (gb->cartridge_type->mbc_subtype == GB_CAMERA && gb->mbc_ram_bank == 0 && addr >= 0xa100 && addr < 0xaf00) { + return GB_camera_read_image(gb, addr - 0xa100); + } + + uint8_t ret = gb->mbc_ram[((addr & 0x1FFF) + gb->mbc_ram_bank * 0x2000) & (gb->mbc_ram_size - 1)]; + if (gb->cartridge_type->mbc_type == GB_MBC2) { + ret |= 0xF0; + } + return ret; +} + +static uint8_t read_ram(GB_gameboy_t *gb, uint16_t addr) +{ + return gb->ram[addr & 0x0FFF]; +} + +static uint8_t read_banked_ram(GB_gameboy_t *gb, uint16_t addr) +{ + return gb->ram[(addr & 0x0FFF) + gb->cgb_ram_bank * 0x1000]; +} + +static uint8_t read_high_memory(GB_gameboy_t *gb, uint16_t addr) +{ + + if (addr < 0xFE00) { + return gb->ram[addr & 0x0FFF]; + } + + if (addr < 0xFEA0) { + if (gb->oam_read_blocked || (gb->dma_steps_left && (gb->dma_cycles > 0 || gb->is_dma_restarting))) { + return 0xFF; + } + return gb->oam[addr & 0xFF]; + } + + if (addr < 0xFF00) { + /* Unusable. CGB results are verified, but DMG results were tested on a SGB2 */ + if ((gb->io_registers[GB_IO_STAT] & 0x3) >= 2) { /* Seems to be disabled in Modes 2 and 3 */ + return 0xFF; + } + if (gb->is_cgb) { + return (addr & 0xF0) | ((addr >> 4) & 0xF); + } + return 0; + + } + + if (addr < 0xFF80) { + if (addr == 0xff00) + { + if (gb->input_callback) + gb->input_callback(gb); + gb->lagged = false; + if (gb->is_sgb) { + return sgb_read_ff00(gb->cycles_since_epoch); + } + } + + switch (addr & 0xFF) { + case GB_IO_IF: + return gb->io_registers[GB_IO_IF] | 0xE0; + case GB_IO_TAC: + return gb->io_registers[GB_IO_TAC] | 0xF8; + case GB_IO_STAT: + return gb->io_registers[GB_IO_STAT] | 0x80; + case GB_IO_DMG_EMULATION_INDICATION: + if (!gb->cgb_mode) { + return 0xFF; + } + return gb->io_registers[GB_IO_DMG_EMULATION_INDICATION] | 0xFE; + + case GB_IO_PCM_12: + case GB_IO_PCM_34: + { + if (!gb->is_cgb) return 0xFF; + GB_sample_t dummy; + GB_apu_get_samples_and_update_pcm_regs(gb, &dummy); + } + /* Fall through */ + case GB_IO_JOYP: + case GB_IO_TMA: + case GB_IO_LCDC: + case GB_IO_SCY: + case GB_IO_SCX: + case GB_IO_LY: + case GB_IO_LYC: + case GB_IO_BGP: + case GB_IO_OBP0: + case GB_IO_OBP1: + case GB_IO_WY: + case GB_IO_WX: + case GB_IO_SC: + case GB_IO_SB: + return gb->io_registers[addr & 0xFF]; + case GB_IO_TIMA: + if (gb->tima_reload_state == GB_TIMA_RELOADING) { + return 0; + } + return gb->io_registers[GB_IO_TIMA]; + case GB_IO_DIV: + return gb->div_cycles >> 8; + case GB_IO_HDMA5: + if (!gb->cgb_mode) return 0xFF; + return ((gb->hdma_on || gb->hdma_on_hblank)? 0 : 0x80) | ((gb->hdma_steps_left - 1) & 0x7F); + case GB_IO_SVBK: + if (!gb->cgb_mode) { + return 0xFF; + } + return gb->cgb_ram_bank | ~0x7; + case GB_IO_VBK: + if (!gb->is_cgb) { + return 0xFF; + } + return gb->cgb_vram_bank | ~0x1; + + /* Todo: It seems that a CGB in DMG mode can access BGPI and OBPI, but not BGPD and OBPD? */ + case GB_IO_BGPI: + case GB_IO_OBPI: + if (!gb->is_cgb) { + return 0xFF; + } + return gb->io_registers[addr & 0xFF] | 0x40; + + case GB_IO_BGPD: + case GB_IO_OBPD: + { + if (!gb->cgb_mode && gb->boot_rom_finished) { + return 0xFF; + } + uint8_t index_reg = (addr & 0xFF) - 1; + return ((addr & 0xFF) == GB_IO_BGPD? + gb->background_palettes_data : + gb->sprite_palettes_data)[gb->io_registers[index_reg] & 0x3F]; + } + + case GB_IO_KEY1: + if (!gb->cgb_mode) { + return 0xFF; + } + return (gb->io_registers[GB_IO_KEY1] & 0x7F) | (gb->cgb_double_speed? 0xFE : 0x7E); + + case GB_IO_RP: { + if (!gb->cgb_mode) return 0xFF; + /* You will read your own IR LED if it's on. */ + bool read_value = gb->infrared_input || (gb->io_registers[GB_IO_RP] & 1); + uint8_t ret = (gb->io_registers[GB_IO_RP] & 0xC1) | 0x3C; + if ((gb->io_registers[GB_IO_RP] & 0xC0) == 0xC0 && read_value) { + ret |= 2; + } + return ret; + } + case GB_IO_DMA: + /* Todo: is this documented? */ + return gb->is_cgb? 0x00 : 0xFF; + case GB_IO_UNKNOWN2: + case GB_IO_UNKNOWN3: + return gb->is_cgb? gb->io_registers[addr & 0xFF] : 0xFF; + case GB_IO_UNKNOWN4: + return gb->cgb_mode? gb->io_registers[addr & 0xFF] : 0xFF; + case GB_IO_UNKNOWN5: + return gb->is_cgb? gb->io_registers[addr & 0xFF] | 0x8F : 0xFF; + default: + if ((addr & 0xFF) >= GB_IO_NR10 && (addr & 0xFF) <= GB_IO_WAV_END) { + return GB_apu_read(gb, addr & 0xFF); + } + return 0xFF; + } + /* Hardware registers */ + return 0; + } + + if (addr == 0xFFFF) { + /* Interrupt Mask */ + return gb->interrupt_enable; + } + + /* HRAM */ + return gb->hram[addr - 0xFF80]; +} + +static GB_read_function_t * const read_map[] = +{ + read_rom, read_rom, read_rom, read_rom, /* 0XXX, 1XXX, 2XXX, 3XXX */ + read_mbc_rom, read_mbc_rom, read_mbc_rom, read_mbc_rom, /* 4XXX, 5XXX, 6XXX, 7XXX */ + read_vram, read_vram, /* 8XXX, 9XXX */ + read_mbc_ram, read_mbc_ram, /* AXXX, BXXX */ + read_ram, read_banked_ram, /* CXXX, DXXX */ + read_high_memory, read_high_memory, /* EXXX FXXX */ +}; + +uint8_t GB_read_memory(GB_gameboy_t *gb, uint16_t addr) +{ + if (is_addr_in_dma_use(gb, addr)) { + addr = gb->dma_current_src; + } + return read_map[addr >> 12](gb, addr); +} + +static void write_mbc(GB_gameboy_t *gb, uint16_t addr, uint8_t value) +{ + switch (gb->cartridge_type->mbc_type) { + case GB_NO_MBC: return; + case GB_MBC1: + switch (addr & 0xF000) { + case 0x0000: case 0x1000: gb->mbc_ram_enable = (value & 0xF) == 0xA; break; + case 0x2000: case 0x3000: gb->mbc1.bank_low = value; break; + case 0x4000: case 0x5000: gb->mbc1.bank_high = value; break; + case 0x6000: case 0x7000: gb->mbc1.mode = value; break; + } + break; + case GB_MBC2: + switch (addr & 0xF000) { + case 0x0000: case 0x1000: if (!(addr & 0x100)) gb->mbc_ram_enable = (value & 0xF) == 0xA; break; + case 0x2000: case 0x3000: if ( addr & 0x100) gb->mbc2.rom_bank = value; break; + } + break; + case GB_MBC3: + switch (addr & 0xF000) { + case 0x0000: case 0x1000: gb->mbc_ram_enable = (value & 0xF) == 0xA; break; + case 0x2000: case 0x3000: gb->mbc3.rom_bank = value; break; + case 0x4000: case 0x5000: gb->mbc3.ram_bank = value; break; + case 0x6000: case 0x7000: + if (!gb->rtc_latch && (value & 1)) { /* Todo: verify condition is correct */ + memcpy(&gb->rtc_latched, &gb->rtc_real, sizeof(gb->rtc_real)); + } + gb->rtc_latch = value & 1; + break; + } + break; + case GB_MBC5: + switch (addr & 0xF000) { + case 0x0000: case 0x1000: gb->mbc_ram_enable = (value & 0xF) == 0xA; break; + case 0x2000: gb->mbc5.rom_bank_low = value; break; + case 0x3000: gb->mbc5.rom_bank_high = value; break; + case 0x4000: case 0x5000: + if (gb->cartridge_type->has_rumble) { + if (!!(value & 8) != gb->rumble_state) { + gb->rumble_state = !gb->rumble_state; + if (gb->rumble_callback) { + gb->rumble_callback(gb, gb->rumble_state); + } + } + value &= 7; + } + gb->mbc5.ram_bank = value; + gb->camera_registers_mapped = (value & 0x10) && gb->cartridge_type->mbc_subtype == GB_CAMERA; + break; + } + break; + case GB_HUC1: + switch (addr & 0xF000) { + case 0x0000: case 0x1000: gb->mbc_ram_enable = (value & 0xF) == 0xA; break; + case 0x2000: case 0x3000: gb->huc1.bank_low = value; break; + case 0x4000: case 0x5000: gb->huc1.bank_high = value; break; + case 0x6000: case 0x7000: gb->huc1.mode = value; break; + } + break; + case GB_HUC3: + switch (addr & 0xF000) { + case 0x0000: case 0x1000: gb->mbc_ram_enable = (value & 0xF) == 0xA; break; + case 0x2000: case 0x3000: gb->huc3.rom_bank = value; break; + case 0x4000: case 0x5000: gb->huc3.ram_bank = value; break; + } + break; + } + GB_update_mbc_mappings(gb); +} + +static void write_vram(GB_gameboy_t *gb, uint16_t addr, uint8_t value) +{ + if (gb->vram_write_blocked) { + //GB_log(gb, "Wrote %02x to %04x (VRAM) during mode 3\n", value, addr); + return; + } + gb->vram[(addr & 0x1FFF) + (uint16_t) gb->cgb_vram_bank * 0x2000] = value; +} + +static void write_mbc_ram(GB_gameboy_t *gb, uint16_t addr, uint8_t value) +{ + if (gb->camera_registers_mapped) { + GB_camera_write_register(gb, addr, value); + return; + } + + if (!gb->mbc_ram_enable || !gb->mbc_ram_size) return; + + if (gb->cartridge_type->has_rtc && gb->mbc_ram_bank >= 8 && gb->mbc_ram_bank <= 0xC) { + /* RTC read */ + gb->rtc_latched.data[gb->mbc_ram_bank - 8] = gb->rtc_real.data[gb->mbc_ram_bank - 8] = value; /* Todo: does it really write both? */ + } + + if (!gb->mbc_ram) { + return; + } + + gb->mbc_ram[((addr & 0x1FFF) + gb->mbc_ram_bank * 0x2000) & (gb->mbc_ram_size - 1)] = value; +} + +static void write_ram(GB_gameboy_t *gb, uint16_t addr, uint8_t value) +{ + gb->ram[addr & 0x0FFF] = value; +} + +static void write_banked_ram(GB_gameboy_t *gb, uint16_t addr, uint8_t value) +{ + gb->ram[(addr & 0x0FFF) + gb->cgb_ram_bank * 0x1000] = value; +} + +static void write_high_memory(GB_gameboy_t *gb, uint16_t addr, uint8_t value) +{ + if (addr < 0xFE00) { + GB_log(gb, "Wrote %02x to %04x (RAM Mirror)\n", value, addr); + gb->ram[addr & 0x0FFF] = value; + return; + } + + if (addr < 0xFEA0) { + if (gb->oam_write_blocked|| (gb->dma_steps_left && (gb->dma_cycles > 0 || gb->is_dma_restarting))) { + return; + } + gb->oam[addr & 0xFF] = value; + return; + } + + if (addr < 0xFF00) { + GB_log(gb, "Wrote %02x to %04x (Unused)\n", value, addr); + return; + } + + if (addr < 0xFF80) { + if (addr == 0xff00 && gb->is_sgb) + { + sgb_write_ff00(value, gb->cycles_since_epoch); + return; + } + + /* Hardware registers */ + switch (addr & 0xFF) { + + case GB_IO_SCX: + case GB_IO_IF: + case GB_IO_SCY: + case GB_IO_LYC: + case GB_IO_BGP: + case GB_IO_OBP0: + case GB_IO_OBP1: + case GB_IO_WY: + case GB_IO_WX: + case GB_IO_SB: + case GB_IO_DMG_EMULATION_INDICATION: + case GB_IO_UNKNOWN2: + case GB_IO_UNKNOWN3: + case GB_IO_UNKNOWN4: + case GB_IO_UNKNOWN5: + gb->io_registers[addr & 0xFF] = value; + return; + + case GB_IO_TIMA: + if (gb->tima_reload_state != GB_TIMA_RELOADED) { + gb->io_registers[GB_IO_TIMA] = value; + } + return; + + case GB_IO_TMA: + gb->io_registers[GB_IO_TMA] = value; + if (gb->tima_reload_state != GB_TIMA_RUNNING) { + gb->io_registers[GB_IO_TIMA] = value; + } + return; + + case GB_IO_TAC: + GB_emulate_timer_glitch(gb, gb->io_registers[GB_IO_TAC], value); + gb->io_registers[GB_IO_TAC] = value; + return; + + + case GB_IO_LCDC: + if ((value & 0x80) && !(gb->io_registers[GB_IO_LCDC] & 0x80)) { + /* It appears that there's a slight delay after enabling the screen? */ + /* Todo: verify this. */ + gb->display_cycles = 0; + gb->first_scanline = true; + if (gb->frame_skip_state == GB_FRAMESKIP_SECOND_FRAME_RENDERED) { + gb->frame_skip_state = GB_FRAMESKIP_LCD_TURNED_ON; + } + } + gb->io_registers[GB_IO_LCDC] = value; + return; + + case GB_IO_STAT: + /* A DMG bug: http://www.devrs.com/gb/files/faqs.html#GBBugs */ + if (!gb->is_cgb && !gb->stat_interrupt_line && + (gb->io_registers[GB_IO_STAT] & 0x3) < 2 && (gb->io_registers[GB_IO_LCDC] & 0x80)) { + gb->io_registers[GB_IO_IF] |= 2; + } + /* Delete previous R/W bits */ + gb->io_registers[GB_IO_STAT] &= 7; + /* Set them by value */ + gb->io_registers[GB_IO_STAT] |= value & ~7; + /* Set unused bit to 1 */ + gb->io_registers[GB_IO_STAT] |= 0x80; + return; + + case GB_IO_DIV: + GB_set_internal_div_counter(gb, 0); + return; + + case GB_IO_JOYP: + gb->io_registers[GB_IO_JOYP] &= 0x0F; + gb->io_registers[GB_IO_JOYP] |= value & 0xF0; + GB_update_joyp(gb); + return; + + case GB_IO_BIOS: + gb->boot_rom_finished = true; + return; + + case GB_IO_DMG_EMULATION: + if (gb->is_cgb && !gb->boot_rom_finished) { + gb->cgb_mode = value != 4; /* The real "contents" of this register aren't quite known yet. */ + } + return; + + case GB_IO_DMA: + if (value <= 0xE0) { + if (gb->dma_steps_left) { + /* This is not correct emulation, since we're not really delaying the second DMA. + One write that should have happened in the first DMA will not happen. However, + since that byte will be overwritten by the second DMA before it can actually be + read, it doesn't actually matter. */ + gb->is_dma_restarting = true; + } + gb->dma_cycles = -7; + gb->dma_current_dest = 0; + gb->dma_current_src = value << 8; + gb->dma_steps_left = 0xa0; + } + /* else { what? } */ + + return; + case GB_IO_SVBK: + if (!gb->cgb_mode) { + return; + } + gb->cgb_ram_bank = value & 0x7; + if (!gb->cgb_ram_bank) { + gb->cgb_ram_bank++; + } + return; + case GB_IO_VBK: + if (!gb->cgb_mode) { + return; + } + gb->cgb_vram_bank = value & 0x1; + return; + + case GB_IO_BGPI: + case GB_IO_OBPI: + if (!gb->is_cgb) { + return; + } + gb->io_registers[addr & 0xFF] = value; + return; + case GB_IO_BGPD: + case GB_IO_OBPD: + if (!gb->cgb_mode && gb->boot_rom_finished) { + /* Todo: Due to the behavior of a broken Game & Watch Gallery 2 ROM on a real CGB. A proper test ROM + is required. */ + return; + } + uint8_t index_reg = (addr & 0xFF) - 1; + ((addr & 0xFF) == GB_IO_BGPD? + gb->background_palettes_data : + gb->sprite_palettes_data)[gb->io_registers[index_reg] & 0x3F] = value; + GB_palette_changed(gb, (addr & 0xFF) == GB_IO_BGPD, gb->io_registers[index_reg] & 0x3F); + if (gb->io_registers[index_reg] & 0x80) { + gb->io_registers[index_reg]++; + gb->io_registers[index_reg] |= 0x80; + } + return; + case GB_IO_KEY1: + if (!gb->is_cgb) { + return; + } + gb->io_registers[GB_IO_KEY1] = value; + return; + case GB_IO_HDMA1: + if (gb->cgb_mode) { + gb->hdma_current_src &= 0xF0; + gb->hdma_current_src |= value << 8; + } + return; + case GB_IO_HDMA2: + if (gb->cgb_mode) { + gb->hdma_current_src &= 0xFF00; + gb->hdma_current_src |= value & 0xF0; + } + return; + case GB_IO_HDMA3: + if (gb->cgb_mode) { + gb->hdma_current_dest &= 0xF0; + gb->hdma_current_dest |= value << 8; + } + return; + case GB_IO_HDMA4: + if (gb->cgb_mode) { + gb->hdma_current_dest &= 0x1F00; + gb->hdma_current_dest |= value & 0xF0; + } + return; + case GB_IO_HDMA5: + if (!gb->cgb_mode) return; + if ((value & 0x80) == 0 && gb->hdma_on_hblank) { + gb->hdma_on_hblank = false; + return; + } + gb->hdma_on = (value & 0x80) == 0; + gb->hdma_on_hblank = (value & 0x80) != 0; + if (gb->hdma_on_hblank && (gb->io_registers[GB_IO_STAT] & 3) == 0) { + gb->hdma_on = true; + gb->hdma_cycles = 0; + } + gb->io_registers[GB_IO_HDMA5] = value; + gb->hdma_steps_left = (gb->io_registers[GB_IO_HDMA5] & 0x7F) + 1; + /* Todo: Verify this. Gambatte's DMA tests require this. */ + if (gb->hdma_current_dest + (gb->hdma_steps_left << 4) > 0xFFFF) { + gb->hdma_steps_left = (0x10000 - gb->hdma_current_dest) >> 4; + } + gb->hdma_cycles = 0; + return; + + /* Todo: what happens when starting a transfer during a transfer? + What happens when starting a transfer during external clock? + */ + case GB_IO_SC: + if (!gb->cgb_mode) { + value |= 2; + } + gb->io_registers[GB_IO_SC] = value | (~0x83); + if ((value & 0x80) && (value & 0x1) ) { + gb->serial_length = gb->cgb_mode && (value & 2)? 128 : 4096; + /* Todo: This is probably incorrect for CGB's faster clock mode. */ + gb->serial_cycles &= 0xFF; + if (gb->serial_transfer_start_callback) { + gb->serial_transfer_start_callback(gb, gb->io_registers[GB_IO_SB]); + } + } + else { + gb->serial_length = 0; + } + return; + + case GB_IO_RP: { + if (!gb->is_cgb) { + return; + } + if ((value & 1) != (gb->io_registers[GB_IO_RP] & 1)) { + if (gb->infrared_callback) { + gb->infrared_callback(gb, value & 1, gb->cycles_since_ir_change); + gb->cycles_since_ir_change = 0; + } + } + gb->io_registers[GB_IO_RP] = value; + return; + } + + default: + if ((addr & 0xFF) >= GB_IO_NR10 && (addr & 0xFF) <= GB_IO_WAV_END) { + GB_apu_write(gb, addr & 0xFF, value); + return; + } + GB_log(gb, "Wrote %02x to %04x (HW Register)\n", value, addr); + return; + } + } + + if (addr == 0xFFFF) { + /* Interrupt mask */ + gb->interrupt_enable = value; + return; + } + + /* HRAM */ + gb->hram[addr - 0xFF80] = value; +} + + + +static GB_write_function_t * const write_map[] = +{ + write_mbc, write_mbc, write_mbc, write_mbc, /* 0XXX, 1XXX, 2XXX, 3XXX */ + write_mbc, write_mbc, write_mbc, write_mbc, /* 4XXX, 5XXX, 6XXX, 7XXX */ + write_vram, write_vram, /* 8XXX, 9XXX */ + write_mbc_ram, write_mbc_ram, /* AXXX, BXXX */ + write_ram, write_banked_ram, /* CXXX, DXXX */ + write_high_memory, write_high_memory, /* EXXX FXXX */ +}; + +void GB_write_memory(GB_gameboy_t *gb, uint16_t addr, uint8_t value) +{ + if (is_addr_in_dma_use(gb, addr)) { + /* Todo: What should happen? Will this affect DMA? Will data be written? What and where? */ + return; + } + write_map[addr >> 12](gb, addr, value); +} + +void GB_dma_run(GB_gameboy_t *gb) +{ + while (gb->dma_cycles >= 4 && gb->dma_steps_left) { + /* Todo: measure this value */ + gb->dma_cycles -= 4; + gb->dma_steps_left--; + gb->oam[gb->dma_current_dest++] = GB_read_memory(gb, gb->dma_current_src); + /* dma_current_src must be the correct value during GB_read_memory */ + gb->dma_current_src++; + if (!gb->dma_steps_left) { + gb->is_dma_restarting = false; + } + } +} + +void GB_hdma_run(GB_gameboy_t *gb) +{ + if (!gb->hdma_on) return; + while (gb->hdma_cycles >= 8) { + gb->hdma_cycles -= 8; + + for (uint8_t i = 0; i < 0x10; i++) { + GB_write_memory(gb, 0x8000 | (gb->hdma_current_dest++ & 0x1FFF), GB_read_memory(gb, (gb->hdma_current_src++))); + } + + if(--gb->hdma_steps_left == 0){ + gb->hdma_on = false; + gb->hdma_on_hblank = false; + gb->io_registers[GB_IO_HDMA5] &= 0x7F; + break; + } + if (gb->hdma_on_hblank) { + gb->hdma_on = false; + break; + } + } +} diff --git a/waterbox/sameboy/memory.h b/waterbox/sameboy/memory.h new file mode 100644 index 0000000000..16b3b9220f --- /dev/null +++ b/waterbox/sameboy/memory.h @@ -0,0 +1,12 @@ +#ifndef memory_h +#define memory_h +#include "gb.h" + +uint8_t GB_read_memory(GB_gameboy_t *gb, uint16_t addr); +void GB_write_memory(GB_gameboy_t *gb, uint16_t addr, uint8_t value); +#ifdef GB_INTERNAL +void GB_dma_run(GB_gameboy_t *gb); +void GB_hdma_run(GB_gameboy_t *gb); +#endif + +#endif /* memory_h */ diff --git a/waterbox/sameboy/printer.c b/waterbox/sameboy/printer.c new file mode 100644 index 0000000000..bc1d45ab47 --- /dev/null +++ b/waterbox/sameboy/printer.c @@ -0,0 +1,201 @@ +#include "gb.h" + +/* TODO: Emulation is VERY basic and assumes the ROM correctly uses the printer's interface. + Incorrect usage is not correctly emulated, as it's not well documented, nor do I + have my own GB Printer to figure it out myself. + + It also does not currently emulate communication timeout, which means that a bug + might prevent the printer operation until the GameBoy is restarted. + + Also, field mask values are assumed. */ + +static void handle_command(GB_gameboy_t *gb) +{ + + switch (gb->printer.command_id) { + case GB_PRINTER_INIT_COMMAND: + gb->printer.status = 0; + gb->printer.image_offset = 0; + break; + + case GB_PRINTER_START_COMMAND: + if (gb->printer.command_length == 4) { + gb->printer.status = 6; /* Printing */ + uint32_t image[gb->printer.image_offset]; + uint8_t palette = gb->printer.command_data[2]; + uint32_t colors[4] = {gb->rgb_encode_callback(gb, 0xff, 0xff, 0xff), + gb->rgb_encode_callback(gb, 0xaa, 0xaa, 0xaa), + gb->rgb_encode_callback(gb, 0x55, 0x55, 0x55), + gb->rgb_encode_callback(gb, 0x00, 0x00, 0x00)}; + for (unsigned i = 0; i < gb->printer.image_offset; i++) { + image[i] = colors[(palette >> (gb->printer.image[i] * 2)) & 3]; + } + + if (gb->printer.callback) { + gb->printer.callback(gb, image, gb->printer.image_offset / 160, + gb->printer.command_data[1] >> 4, gb->printer.command_data[1] & 7, + gb->printer.command_data[3] & 0x7F); + } + + gb->printer.image_offset = 0; + } + break; + + case GB_PRINTER_DATA_COMMAND: + if (gb->printer.command_length == GB_PRINTER_DATA_SIZE) { + gb->printer.image_offset %= sizeof(gb->printer.image); + gb->printer.status = 8; /* Received 0x280 bytes */ + + uint8_t *byte = gb->printer.command_data; + + for (unsigned row = 2; row--; ) { + for (unsigned tile_x = 0; tile_x < 160 / 8; tile_x++) { + for (unsigned y = 0; y < 8; y++, byte += 2) { + for (unsigned x_pixel = 0; x_pixel < 8; x_pixel++) { + gb->printer.image[gb->printer.image_offset + tile_x * 8 + x_pixel + y * 160] = + ((*byte) >> 7) | (((*(byte + 1)) >> 7) << 1); + (*byte) <<= 1; + (*(byte + 1)) <<= 1; + } + } + } + + gb->printer.image_offset += 8 * 160; + } + } + + case GB_PRINTER_NOP_COMMAND: + default: + break; + } +} + +static void serial_start(GB_gameboy_t *gb, uint8_t byte_received) +{ + gb->printer.byte_to_send = 0; + switch (gb->printer.command_state) { + case GB_PRINTER_COMMAND_MAGIC1: + if (byte_received != 0x88) { + return; + } + gb->printer.status &= ~1; + gb->printer.command_length = 0; + gb->printer.checksum = 0; + break; + + case GB_PRINTER_COMMAND_MAGIC2: + if (byte_received != 0x33) { + if (byte_received != 0x88) { + gb->printer.command_state = GB_PRINTER_COMMAND_MAGIC1; + } + return; + } + break; + + case GB_PRINTER_COMMAND_ID: + gb->printer.command_id = byte_received & 0xF; + break; + + case GB_PRINTER_COMMAND_COMPRESSION: + gb->printer.compression = byte_received & 1; + break; + + case GB_PRINTER_COMMAND_LENGTH_LOW: + gb->printer.length_left = byte_received; + break; + + case GB_PRINTER_COMMAND_LENGTH_HIGH: + gb->printer.length_left |= (byte_received & 3) << 8; + break; + + case GB_PRINTER_COMMAND_DATA: + if (gb->printer.command_length != GB_PRINTER_MAX_COMMAND_LENGTH) { + if (gb->printer.compression) { + if (!gb->printer.compression_run_lenth) { + gb->printer.compression_run_is_compressed = byte_received & 0x80; + gb->printer.compression_run_lenth = (byte_received & 0x7F) + 1 + gb->printer.compression_run_is_compressed; + } + else if (gb->printer.compression_run_is_compressed) { + while (gb->printer.compression_run_lenth) { + gb->printer.command_data[gb->printer.command_length++] = byte_received; + gb->printer.compression_run_lenth--; + if (gb->printer.command_length == GB_PRINTER_MAX_COMMAND_LENGTH) { + gb->printer.compression_run_lenth = 0; + } + } + } + else { + gb->printer.command_data[gb->printer.command_length++] = byte_received; + gb->printer.compression_run_lenth--; + } + } + else { + gb->printer.command_data[gb->printer.command_length++] = byte_received; + } + } + gb->printer.length_left--; + break; + + case GB_PRINTER_COMMAND_CHECKSUM_LOW: + gb->printer.checksum ^= byte_received; + break; + + case GB_PRINTER_COMMAND_CHECKSUM_HIGH: + gb->printer.checksum ^= byte_received << 8; + if (gb->printer.checksum) { + gb->printer.status |= 1; /* Checksum error*/ + gb->printer.command_state = GB_PRINTER_COMMAND_MAGIC1; + return; + } + break; + case GB_PRINTER_COMMAND_ACTIVE: + gb->printer.byte_to_send = 0x81; + break; + case GB_PRINTER_COMMAND_STATUS: + + if ((gb->printer.command_id & 0xF) == GB_PRINTER_INIT_COMMAND) { + /* Games expect INIT commands to return 0? */ + gb->printer.byte_to_send = 0; + } + else { + gb->printer.byte_to_send = gb->printer.status; + } + + /* Printing is done instantly, but let the game recieve a 6 (Printing) status at least once, for compatibility */ + if (gb->printer.status == 6) { + gb->printer.status = 4; /* Done */ + } + + gb->printer.command_state = GB_PRINTER_COMMAND_MAGIC1; + handle_command(gb); + return; + } + + if (gb->printer.command_state >= GB_PRINTER_COMMAND_ID && gb->printer.command_state < GB_PRINTER_COMMAND_CHECKSUM_LOW) { + gb->printer.checksum += byte_received; + } + + if (gb->printer.command_state != GB_PRINTER_COMMAND_DATA) { + gb->printer.command_state++; + } + + if (gb->printer.command_state == GB_PRINTER_COMMAND_DATA) { + if (gb->printer.length_left == 0) { + gb->printer.command_state++; + } + } + +} + +static uint8_t serial_end(GB_gameboy_t *gb) +{ + return gb->printer.byte_to_send; +} + +void GB_connect_printer(GB_gameboy_t *gb, GB_print_image_callback_t callback) +{ + memset(&gb->printer, 0, sizeof(gb->printer)); + GB_set_serial_transfer_start_callback(gb, serial_start); + GB_set_serial_transfer_end_callback(gb, serial_end); + gb->printer.callback = callback; +} \ No newline at end of file diff --git a/waterbox/sameboy/printer.h b/waterbox/sameboy/printer.h new file mode 100644 index 0000000000..e5d9036a08 --- /dev/null +++ b/waterbox/sameboy/printer.h @@ -0,0 +1,59 @@ +#ifndef printer_h +#define printer_h +#include +#include +#include "gb_struct_def.h" +#define GB_PRINTER_MAX_COMMAND_LENGTH 0x280 +#define GB_PRINTER_DATA_SIZE 0x280 + +typedef void (*GB_print_image_callback_t)(GB_gameboy_t *gb, + uint32_t *image, + uint8_t height, + uint8_t top_margin, + uint8_t bottom_margin, + uint8_t exposure); + + +typedef struct +{ + /* Communication state machine */ + + enum { + GB_PRINTER_COMMAND_MAGIC1, + GB_PRINTER_COMMAND_MAGIC2, + GB_PRINTER_COMMAND_ID, + GB_PRINTER_COMMAND_COMPRESSION, + GB_PRINTER_COMMAND_LENGTH_LOW, + GB_PRINTER_COMMAND_LENGTH_HIGH, + GB_PRINTER_COMMAND_DATA, + GB_PRINTER_COMMAND_CHECKSUM_LOW, + GB_PRINTER_COMMAND_CHECKSUM_HIGH, + GB_PRINTER_COMMAND_ACTIVE, + GB_PRINTER_COMMAND_STATUS, + } command_state : 8; + enum { + GB_PRINTER_INIT_COMMAND = 1, + GB_PRINTER_START_COMMAND = 2, + GB_PRINTER_DATA_COMMAND = 4, + GB_PRINTER_NOP_COMMAND = 0xF, + } command_id : 8; + bool compression; + uint16_t length_left; + uint8_t command_data[GB_PRINTER_MAX_COMMAND_LENGTH]; + uint16_t command_length; + uint16_t checksum; + uint8_t status; + uint8_t byte_to_send; + + uint8_t image[160 * 200]; + uint16_t image_offset; + + GB_print_image_callback_t callback; + + uint8_t compression_run_lenth; + bool compression_run_is_compressed; +} GB_printer_t; + + +void GB_connect_printer(GB_gameboy_t *gb, GB_print_image_callback_t callback); +#endif diff --git a/waterbox/pizza/lib/sgb.c b/waterbox/sameboy/sgb.c similarity index 88% rename from waterbox/pizza/lib/sgb.c rename to waterbox/sameboy/sgb.c index 68b516babc..f4fb6af834 100644 --- a/waterbox/pizza/lib/sgb.c +++ b/waterbox/sameboy/sgb.c @@ -1,9 +1,11 @@ #include "sgb.h" -#include "utils.h" #include #include +#include #include "snes_spc/spc.h" +#define utils_log printf + const uint8_t iplrom[64] = { /*ffc0*/ 0xcd, 0xef, //mov x,#$ef /*ffc2*/ 0xbd, //mov sp,x @@ -330,7 +332,7 @@ static void cmd_attr_chr() return; } int npacket = (n + 87) / 64; - if ((sgb.command[0] & 7) != npacket) + if ((sgb.command[0] & 7) < npacket) { utils_log("SGB: cmd_attr_chr bad length\n"); return; @@ -341,9 +343,9 @@ static void cmd_attr_chr() if (y > 17) y = 17; int vertical = sgb.command[5]; - for (int i = 0; i < 360; i++) + for (int i = 0; i < n; i++) { - uint8_t v = i / 4 + 6; + uint8_t v = sgb.command[i / 4 + 6]; int a = v >> (2 * (3 - (i & 3))) & 3; dst[y * 20 + x] = a; if (vertical) @@ -620,6 +622,16 @@ int sgb_init(const uint8_t *spc, int length) utils_log("SGB: Failed to load SPC\n"); return 0; } + + // the combination of the sameboy bootrom plus the built in SPC file we use means + // that the SPC doesn't finish its init fast enough for donkey kong, which starts poking + // data too early. it's just a combination of various HLE concerns not meshing... + int16_t sound_buffer[4096]; + spc_set_output(sgb.spc, sound_buffer, sizeof(sound_buffer) / sizeof(sound_buffer[0])); + for (int i = 0; i < 240; i++) + { + spc_end_frame(sgb.spc, 35104); + } return 1; } @@ -731,22 +743,38 @@ void sgb_set_controller_data(const uint8_t *buttons) static void trn_sound(const uint8_t* data) { - int len = data[0] | data[1] << 8; - int addr = data[2] | data[3] << 8; - utils_log("TRN_SOUND %04x %04x\n", addr, len); - uint8_t* dst = spc_get_ram(sgb.spc); + const uint8_t* const dataend = data + 0x10000; + uint8_t* const dst = spc_get_ram(sgb.spc); - if (len > 0xffc) + while (1) { - utils_log("TRN_SOUND src overflow\n"); - return; + if (data + 4 > dataend) + { + utils_log("TRN_SOUND header overflow\n"); + break; + } + int len = data[0] | data[1] << 8; + int addr = data[2] | data[3] << 8; + if (!len) + { + utils_log("TRN_SOUND END %04x\n", addr); + break; + } + data += 4; + if (data + len > dataend) + { + utils_log("TRN_SOUND src overflow\n"); + break; + } + if (addr + len >= 0x10000) + { + utils_log("TRN_SOUND dst overflow\n"); + return; + } + utils_log("TRN_SOUND addr %04x len %04x\n", addr, len); + memcpy(dst + addr, data, len); + data += len; } - if (len + addr >= 0x10000) - { - utils_log("TRN_SOUND dst overflow\n"); - return; - } - memcpy(dst + addr, data + 4, len); } static void trn_pal(const uint8_t *data) @@ -971,19 +999,31 @@ void sgb_render_audio(uint64_t time, void (*callback)(int16_t l, int16_t r, uint uint32_t new_remainder = diff % refclocks_per_spc_sample; spc_set_output(sgb.spc, sound_buffer, sizeof(sound_buffer) / sizeof(sound_buffer[0])); - int p; - for (p = 0; p < 4; p++) + int matched = 1; + for (int p = 0; p < 4; p++) { if (spc_read_port(sgb.spc, 0, p) != sgb.sound_control[p]) - break; + matched = 0; } - if (p == 4) // recived + if (matched) // recived { sgb.sound_control[0] = 0; sgb.sound_control[1] = 0; sgb.sound_control[2] = 0; } - for (p = 0; p < 4; p++) + else + { + utils_log("SPC: %02x %02x %02x %02x => %02x %02x %02x %02x\n", + spc_read_port(sgb.spc, 0, 0), + spc_read_port(sgb.spc, 0, 1), + spc_read_port(sgb.spc, 0, 2), + spc_read_port(sgb.spc, 0, 3), + sgb.sound_control[0], + sgb.sound_control[1], + sgb.sound_control[2], + sgb.sound_control[3]); + } + for (int p = 0; p < 4; p++) { spc_write_port(sgb.spc, 0, p, sgb.sound_control[p]); } diff --git a/waterbox/pizza/lib/sgb.h b/waterbox/sameboy/sgb.h similarity index 100% rename from waterbox/pizza/lib/sgb.h rename to waterbox/sameboy/sgb.h diff --git a/waterbox/pizza/lib/snes_spc/SNES_SPC.cpp b/waterbox/sameboy/snes_spc/SNES_SPC.cpp similarity index 100% rename from waterbox/pizza/lib/snes_spc/SNES_SPC.cpp rename to waterbox/sameboy/snes_spc/SNES_SPC.cpp diff --git a/waterbox/pizza/lib/snes_spc/SNES_SPC.h b/waterbox/sameboy/snes_spc/SNES_SPC.h similarity index 100% rename from waterbox/pizza/lib/snes_spc/SNES_SPC.h rename to waterbox/sameboy/snes_spc/SNES_SPC.h diff --git a/waterbox/pizza/lib/snes_spc/SNES_SPC_misc.cpp b/waterbox/sameboy/snes_spc/SNES_SPC_misc.cpp similarity index 100% rename from waterbox/pizza/lib/snes_spc/SNES_SPC_misc.cpp rename to waterbox/sameboy/snes_spc/SNES_SPC_misc.cpp diff --git a/waterbox/pizza/lib/snes_spc/SNES_SPC_state.cpp b/waterbox/sameboy/snes_spc/SNES_SPC_state.cpp similarity index 100% rename from waterbox/pizza/lib/snes_spc/SNES_SPC_state.cpp rename to waterbox/sameboy/snes_spc/SNES_SPC_state.cpp diff --git a/waterbox/pizza/lib/snes_spc/SPC_CPU.h b/waterbox/sameboy/snes_spc/SPC_CPU.h similarity index 100% rename from waterbox/pizza/lib/snes_spc/SPC_CPU.h rename to waterbox/sameboy/snes_spc/SPC_CPU.h diff --git a/waterbox/pizza/lib/snes_spc/SPC_DSP.cpp b/waterbox/sameboy/snes_spc/SPC_DSP.cpp similarity index 100% rename from waterbox/pizza/lib/snes_spc/SPC_DSP.cpp rename to waterbox/sameboy/snes_spc/SPC_DSP.cpp diff --git a/waterbox/pizza/lib/snes_spc/SPC_DSP.h b/waterbox/sameboy/snes_spc/SPC_DSP.h similarity index 100% rename from waterbox/pizza/lib/snes_spc/SPC_DSP.h rename to waterbox/sameboy/snes_spc/SPC_DSP.h diff --git a/waterbox/pizza/lib/snes_spc/SPC_Filter.cpp b/waterbox/sameboy/snes_spc/SPC_Filter.cpp similarity index 100% rename from waterbox/pizza/lib/snes_spc/SPC_Filter.cpp rename to waterbox/sameboy/snes_spc/SPC_Filter.cpp diff --git a/waterbox/pizza/lib/snes_spc/SPC_Filter.h b/waterbox/sameboy/snes_spc/SPC_Filter.h similarity index 100% rename from waterbox/pizza/lib/snes_spc/SPC_Filter.h rename to waterbox/sameboy/snes_spc/SPC_Filter.h diff --git a/waterbox/pizza/lib/snes_spc/blargg_common.h b/waterbox/sameboy/snes_spc/blargg_common.h similarity index 100% rename from waterbox/pizza/lib/snes_spc/blargg_common.h rename to waterbox/sameboy/snes_spc/blargg_common.h diff --git a/waterbox/pizza/lib/snes_spc/blargg_config.h b/waterbox/sameboy/snes_spc/blargg_config.h similarity index 100% rename from waterbox/pizza/lib/snes_spc/blargg_config.h rename to waterbox/sameboy/snes_spc/blargg_config.h diff --git a/waterbox/pizza/lib/snes_spc/blargg_endian.h b/waterbox/sameboy/snes_spc/blargg_endian.h similarity index 100% rename from waterbox/pizza/lib/snes_spc/blargg_endian.h rename to waterbox/sameboy/snes_spc/blargg_endian.h diff --git a/waterbox/pizza/lib/snes_spc/blargg_source.h b/waterbox/sameboy/snes_spc/blargg_source.h similarity index 100% rename from waterbox/pizza/lib/snes_spc/blargg_source.h rename to waterbox/sameboy/snes_spc/blargg_source.h diff --git a/waterbox/pizza/lib/snes_spc/changes.txt b/waterbox/sameboy/snes_spc/changes.txt similarity index 100% rename from waterbox/pizza/lib/snes_spc/changes.txt rename to waterbox/sameboy/snes_spc/changes.txt diff --git a/waterbox/pizza/lib/snes_spc/dsp.cpp b/waterbox/sameboy/snes_spc/dsp.cpp similarity index 100% rename from waterbox/pizza/lib/snes_spc/dsp.cpp rename to waterbox/sameboy/snes_spc/dsp.cpp diff --git a/waterbox/pizza/lib/snes_spc/dsp.h b/waterbox/sameboy/snes_spc/dsp.h similarity index 100% rename from waterbox/pizza/lib/snes_spc/dsp.h rename to waterbox/sameboy/snes_spc/dsp.h diff --git a/waterbox/pizza/lib/snes_spc/license.txt b/waterbox/sameboy/snes_spc/license.txt similarity index 100% rename from waterbox/pizza/lib/snes_spc/license.txt rename to waterbox/sameboy/snes_spc/license.txt diff --git a/waterbox/pizza/lib/snes_spc/readme.txt b/waterbox/sameboy/snes_spc/readme.txt similarity index 100% rename from waterbox/pizza/lib/snes_spc/readme.txt rename to waterbox/sameboy/snes_spc/readme.txt diff --git a/waterbox/pizza/lib/snes_spc/snes_spc.txt b/waterbox/sameboy/snes_spc/snes_spc.txt similarity index 100% rename from waterbox/pizza/lib/snes_spc/snes_spc.txt rename to waterbox/sameboy/snes_spc/snes_spc.txt diff --git a/waterbox/pizza/lib/snes_spc/spc.cpp b/waterbox/sameboy/snes_spc/spc.cpp similarity index 100% rename from waterbox/pizza/lib/snes_spc/spc.cpp rename to waterbox/sameboy/snes_spc/spc.cpp diff --git a/waterbox/pizza/lib/snes_spc/spc.h b/waterbox/sameboy/snes_spc/spc.h similarity index 100% rename from waterbox/pizza/lib/snes_spc/spc.h rename to waterbox/sameboy/snes_spc/spc.h diff --git a/waterbox/sameboy/timing.c b/waterbox/sameboy/timing.c new file mode 100644 index 0000000000..bb2501b31a --- /dev/null +++ b/waterbox/sameboy/timing.c @@ -0,0 +1,161 @@ +#include "gb.h" +#ifdef _WIN32 +#define _WIN32_WINNT 0x0500 +#include +#else +#include +#endif + +static void GB_ir_run(GB_gameboy_t *gb) +{ + if (gb->ir_queue_length == 0) return; + if (gb->cycles_since_input_ir_change >= gb->ir_queue[0].delay) { + gb->cycles_since_input_ir_change -= gb->ir_queue[0].delay; + gb->infrared_input = gb->ir_queue[0].state; + gb->ir_queue_length--; + memmove(&gb->ir_queue[0], &gb->ir_queue[1], sizeof(gb->ir_queue[0]) * (gb->ir_queue_length)); + } +} + +static void advance_tima_state_machine(GB_gameboy_t *gb) +{ + if (gb->tima_reload_state == GB_TIMA_RELOADED) { + gb->tima_reload_state = GB_TIMA_RUNNING; + } + else if (gb->tima_reload_state == GB_TIMA_RELOADING) { + gb->tima_reload_state = GB_TIMA_RELOADED; + } +} + +void GB_advance_cycles(GB_gameboy_t *gb, uint8_t cycles) +{ + // Affected by speed boost + gb->dma_cycles += cycles; + + advance_tima_state_machine(gb); + for (int i = 0; i < cycles; i += 4) { + GB_set_internal_div_counter(gb, gb->div_cycles + 4); + } + + if (cycles > 4) { + advance_tima_state_machine(gb); + if (cycles > 8) { + advance_tima_state_machine(gb); + } + } + + uint16_t previous_serial_cycles = gb->serial_cycles; + gb->serial_cycles += cycles; + if (gb->serial_length) { + if ((gb->serial_cycles & gb->serial_length) != (previous_serial_cycles & gb->serial_length)) { + gb->serial_length = 0; + gb->io_registers[GB_IO_SC] &= ~0x80; + /* TODO: Does SB "update" bit by bit? */ + if (gb->serial_transfer_end_callback) { + gb->io_registers[GB_IO_SB] = gb->serial_transfer_end_callback(gb); + } + else { + gb->io_registers[GB_IO_SB] = 0xFF; + } + + gb->io_registers[GB_IO_IF] |= 8; + } + } + + if (gb->cgb_double_speed) { + cycles >>=1; + } + + // Not affected by speed boost + gb->hdma_cycles += cycles; + gb->apu.apu_cycles += cycles; + gb->cycles_since_ir_change += cycles; + gb->cycles_since_input_ir_change += cycles; + gb->cycles_since_epoch += cycles >> 1; + GB_dma_run(gb); + GB_hdma_run(gb); + GB_apu_run(gb); + GB_display_run(gb, cycles); + GB_ir_run(gb); +} + +/* Standard Timers */ +static const unsigned int GB_TAC_RATIOS[] = {1024, 16, 64, 256}; + +static void increase_tima(GB_gameboy_t *gb) +{ + gb->io_registers[GB_IO_TIMA]++; + if (gb->io_registers[GB_IO_TIMA] == 0) { + gb->io_registers[GB_IO_TIMA] = gb->io_registers[GB_IO_TMA]; + gb->io_registers[GB_IO_IF] |= 4; + gb->tima_reload_state = GB_TIMA_RELOADING; + } +} + +static bool counter_overflow_check(uint32_t old, uint32_t new, uint32_t max) +{ + return (old & (max >> 1)) && !(new & (max >> 1)); +} + +void GB_set_internal_div_counter(GB_gameboy_t *gb, uint32_t value) +{ + /* TIMA increases when a specific high-bit becomes a low-bit. */ + value &= INTERNAL_DIV_CYCLES - 1; + if ((gb->io_registers[GB_IO_TAC] & 4) && + counter_overflow_check(gb->div_cycles, value, GB_TAC_RATIOS[gb->io_registers[GB_IO_TAC] & 3])) { + increase_tima(gb); + } + gb->div_cycles = value; +} + +/* + This glitch is based on the expected results of mooneye-gb rapid_toggle test. + This glitch happens because how TIMA is increased, see GB_set_internal_div_counter. + According to GiiBiiAdvance, GBC's behavior is different, but this was not tested or implemented. +*/ +void GB_emulate_timer_glitch(GB_gameboy_t *gb, uint8_t old_tac, uint8_t new_tac) +{ + /* Glitch only happens when old_tac is enabled. */ + if (!(old_tac & 4)) return; + + unsigned int old_clocks = GB_TAC_RATIOS[old_tac & 3]; + unsigned int new_clocks = GB_TAC_RATIOS[new_tac & 3]; + + /* The bit used for overflow testing must have been 1 */ + if (gb->div_cycles & (old_clocks >> 1)) { + /* And now either the timer must be disabled, or the new bit used for overflow testing be 0. */ + if (!(new_tac & 4) || gb->div_cycles & (new_clocks >> 1)) { + increase_tima(gb); + } + } +} + +void GB_rtc_run(GB_gameboy_t *gb) +{ + if ((gb->rtc_real.high & 0x40) == 0) { /* is timer running? */ + time_t current_time = gb->frontend_rtc_time; + while (gb->last_rtc_second < current_time) { + gb->last_rtc_second++; + if (++gb->rtc_real.seconds == 60) + { + gb->rtc_real.seconds = 0; + if (++gb->rtc_real.minutes == 60) + { + gb->rtc_real.minutes = 0; + if (++gb->rtc_real.hours == 24) + { + gb->rtc_real.hours = 0; + if (++gb->rtc_real.days == 0) + { + if (gb->rtc_real.high & 1) /* Bit 8 of days*/ + { + gb->rtc_real.high |= 0x80; /* Overflow bit */ + } + gb->rtc_real.high ^= 1; + } + } + } + } + } + } +} diff --git a/waterbox/sameboy/timing.h b/waterbox/sameboy/timing.h new file mode 100644 index 0000000000..bd3b2f2732 --- /dev/null +++ b/waterbox/sameboy/timing.h @@ -0,0 +1,18 @@ +#ifndef timing_h +#define timing_h +#include "gb.h" + +#ifdef GB_INTERNAL +void GB_advance_cycles(GB_gameboy_t *gb, uint8_t cycles); +void GB_set_internal_div_counter(GB_gameboy_t *gb, uint32_t value); +void GB_rtc_run(GB_gameboy_t *gb); +void GB_emulate_timer_glitch(GB_gameboy_t *gb, uint8_t old_tac, uint8_t new_tac); + +enum { + GB_TIMA_RUNNING = 0, + GB_TIMA_RELOADING = 1, + GB_TIMA_RELOADED = 2 +}; +#endif + +#endif /* timing_h */ diff --git a/waterbox/sameboy/z80_cpu.c b/waterbox/sameboy/z80_cpu.c new file mode 100644 index 0000000000..9558765263 --- /dev/null +++ b/waterbox/sameboy/z80_cpu.c @@ -0,0 +1,1375 @@ +#include +#include +#include "gb.h" + + +typedef void GB_opcode_t(GB_gameboy_t *gb, uint8_t opcode); + +static void ill(GB_gameboy_t *gb, uint8_t opcode) +{ + GB_log(gb, "Illegal Opcode. Halting.\n"); + gb->interrupt_enable = 0; + gb->halted = true; +} + +static void nop(GB_gameboy_t *gb, uint8_t opcode) +{ + GB_advance_cycles(gb, 4); +} + +static void stop(GB_gameboy_t *gb, uint8_t opcode) +{ + GB_advance_cycles(gb, 4); + if (gb->io_registers[GB_IO_KEY1] & 0x1) { + /* Make sure we don't leave display_cycles not divisble by 4 in single speed mode */ + if (gb->display_cycles % 4 == 2) { + GB_advance_cycles(gb, 4); + } + + /* Todo: the switch is not instant. We should emulate this. */ + gb->cgb_double_speed ^= true; + gb->io_registers[GB_IO_KEY1] = 0; + } + else { + gb->stopped = true; + } + gb->pc++; +} + +/* Operand naming conventions for functions: + r = 8-bit register + lr = low 8-bit register + hr = high 8-bit register + rr = 16-bit register + d8 = 8-bit imm + d16 = 16-bit imm + d.. = [..] + cc = condition code (z, nz, c, nc) + */ + +static void ld_rr_d16(GB_gameboy_t *gb, uint8_t opcode) +{ + uint8_t register_id; + uint16_t value; + GB_advance_cycles(gb, 4); + register_id = (opcode >> 4) + 1; + value = GB_read_memory(gb, gb->pc++); + GB_advance_cycles(gb, 4); + value |= GB_read_memory(gb, gb->pc++) << 8; + GB_advance_cycles(gb, 4); + gb->registers[register_id] = value; +} + +static void ld_drr_a(GB_gameboy_t *gb, uint8_t opcode) +{ + uint8_t register_id; + GB_advance_cycles(gb, 4); + register_id = (opcode >> 4) + 1; + GB_write_memory(gb, gb->registers[register_id], gb->registers[GB_REGISTER_AF] >> 8); + GB_advance_cycles(gb, 4); +} + +static void inc_rr(GB_gameboy_t *gb, uint8_t opcode) +{ + uint8_t register_id; + GB_advance_cycles(gb, 8); + register_id = (opcode >> 4) + 1; + gb->registers[register_id]++; +} + +static void inc_hr(GB_gameboy_t *gb, uint8_t opcode) +{ + uint8_t register_id; + GB_advance_cycles(gb, 4); + register_id = ((opcode >> 4) + 1) & 0x03; + gb->registers[register_id] += 0x100; + gb->registers[GB_REGISTER_AF] &= ~(GB_SUBSTRACT_FLAG | GB_ZERO_FLAG | GB_HALF_CARRY_FLAG); + + if ((gb->registers[register_id] & 0x0F00) == 0) { + gb->registers[GB_REGISTER_AF] |= GB_HALF_CARRY_FLAG; + } + + if ((gb->registers[register_id] & 0xFF00) == 0) { + gb->registers[GB_REGISTER_AF] |= GB_ZERO_FLAG; + } +} +static void dec_hr(GB_gameboy_t *gb, uint8_t opcode) +{ + uint8_t register_id; + GB_advance_cycles(gb, 4); + register_id = ((opcode >> 4) + 1) & 0x03; + gb->registers[register_id] -= 0x100; + gb->registers[GB_REGISTER_AF] &= ~(GB_ZERO_FLAG | GB_HALF_CARRY_FLAG); + gb->registers[GB_REGISTER_AF] |= GB_SUBSTRACT_FLAG; + + if ((gb->registers[register_id] & 0x0F00) == 0xF00) { + gb->registers[GB_REGISTER_AF] |= GB_HALF_CARRY_FLAG; + } + + if ((gb->registers[register_id] & 0xFF00) == 0) { + gb->registers[GB_REGISTER_AF] |= GB_ZERO_FLAG; + } +} + +static void ld_hr_d8(GB_gameboy_t *gb, uint8_t opcode) +{ + uint8_t register_id; + GB_advance_cycles(gb, 4); + register_id = ((opcode >> 4) + 1) & 0x03; + gb->registers[register_id] &= 0xFF; + gb->registers[register_id] |= GB_read_memory(gb, gb->pc++) << 8; + GB_advance_cycles(gb, 4); +} + +static void rlca(GB_gameboy_t *gb, uint8_t opcode) +{ + bool carry = (gb->registers[GB_REGISTER_AF] & 0x8000) != 0; + + GB_advance_cycles(gb, 4); + gb->registers[GB_REGISTER_AF] = (gb->registers[GB_REGISTER_AF] & 0xFF00) << 1; + if (carry) { + gb->registers[GB_REGISTER_AF] |= GB_CARRY_FLAG | 0x0100; + } +} + +static void rla(GB_gameboy_t *gb, uint8_t opcode) +{ + bool bit7 = (gb->registers[GB_REGISTER_AF] & 0x8000) != 0; + bool carry = (gb->registers[GB_REGISTER_AF] & GB_CARRY_FLAG) != 0; + + GB_advance_cycles(gb, 4); + gb->registers[GB_REGISTER_AF] = (gb->registers[GB_REGISTER_AF] & 0xFF00) << 1; + if (carry) { + gb->registers[GB_REGISTER_AF] |= 0x0100; + } + if (bit7) { + gb->registers[GB_REGISTER_AF] |= GB_CARRY_FLAG; + } +} + +static void ld_da16_sp(GB_gameboy_t *gb, uint8_t opcode) +{ + /* Todo: Verify order is correct */ + uint16_t addr; + GB_advance_cycles(gb, 4); + addr = GB_read_memory(gb, gb->pc++); + GB_advance_cycles(gb, 4); + addr |= GB_read_memory(gb, gb->pc++) << 8; + GB_advance_cycles(gb, 4); + GB_write_memory(gb, addr, gb->registers[GB_REGISTER_SP] & 0xFF); + GB_advance_cycles(gb, 4); + GB_write_memory(gb, addr+1, gb->registers[GB_REGISTER_SP] >> 8); + GB_advance_cycles(gb, 4); +} + +static void add_hl_rr(GB_gameboy_t *gb, uint8_t opcode) +{ + uint16_t hl = gb->registers[GB_REGISTER_HL]; + uint16_t rr; + uint8_t register_id; + GB_advance_cycles(gb, 8); + register_id = (opcode >> 4) + 1; + rr = gb->registers[register_id]; + gb->registers[GB_REGISTER_HL] = hl + rr; + gb->registers[GB_REGISTER_AF] &= ~(GB_SUBSTRACT_FLAG | GB_CARRY_FLAG | GB_HALF_CARRY_FLAG); + + /* The meaning of the Half Carry flag is really hard to track -_- */ + if (((hl & 0xFFF) + (rr & 0xFFF)) & 0x1000) { + gb->registers[GB_REGISTER_AF] |= GB_HALF_CARRY_FLAG; + } + + if ( ((unsigned long) hl) + ((unsigned long) rr) & 0x10000) { + gb->registers[GB_REGISTER_AF] |= GB_CARRY_FLAG; + } +} + +static void ld_a_drr(GB_gameboy_t *gb, uint8_t opcode) +{ + uint8_t register_id; + register_id = (opcode >> 4) + 1; + GB_advance_cycles(gb, 4); + gb->registers[GB_REGISTER_AF] &= 0xFF; + gb->registers[GB_REGISTER_AF] |= GB_read_memory(gb, gb->registers[register_id]) << 8; + GB_advance_cycles(gb, 4); +} + +static void dec_rr(GB_gameboy_t *gb, uint8_t opcode) +{ + uint8_t register_id; + GB_advance_cycles(gb, 8); + register_id = (opcode >> 4) + 1; + gb->registers[register_id]--; +} + +static void inc_lr(GB_gameboy_t *gb, uint8_t opcode) +{ + uint8_t register_id; + uint8_t value; + GB_advance_cycles(gb, 4); + register_id = (opcode >> 4) + 1; + + value = (gb->registers[register_id] & 0xFF) + 1; + gb->registers[register_id] = (gb->registers[register_id] & 0xFF00) | value; + + gb->registers[GB_REGISTER_AF] &= ~(GB_SUBSTRACT_FLAG | GB_ZERO_FLAG | GB_HALF_CARRY_FLAG); + + if ((gb->registers[register_id] & 0x0F) == 0) { + gb->registers[GB_REGISTER_AF] |= GB_HALF_CARRY_FLAG; + } + + if ((gb->registers[register_id] & 0xFF) == 0) { + gb->registers[GB_REGISTER_AF] |= GB_ZERO_FLAG; + } +} +static void dec_lr(GB_gameboy_t *gb, uint8_t opcode) +{ + uint8_t register_id; + uint8_t value; + GB_advance_cycles(gb, 4); + register_id = (opcode >> 4) + 1; + + value = (gb->registers[register_id] & 0xFF) - 1; + gb->registers[register_id] = (gb->registers[register_id] & 0xFF00) | value; + + gb->registers[GB_REGISTER_AF] &= ~(GB_ZERO_FLAG | GB_HALF_CARRY_FLAG); + gb->registers[GB_REGISTER_AF] |= GB_SUBSTRACT_FLAG; + + if ((gb->registers[register_id] & 0x0F) == 0xF) { + gb->registers[GB_REGISTER_AF] |= GB_HALF_CARRY_FLAG; + } + + if ((gb->registers[register_id] & 0xFF) == 0) { + gb->registers[GB_REGISTER_AF] |= GB_ZERO_FLAG; + } +} + +static void ld_lr_d8(GB_gameboy_t *gb, uint8_t opcode) +{ + uint8_t register_id; + GB_advance_cycles(gb, 4); + register_id = (opcode >> 4) + 1; + gb->registers[register_id] &= 0xFF00; + gb->registers[register_id] |= GB_read_memory(gb, gb->pc++); + GB_advance_cycles(gb, 4); +} + +static void rrca(GB_gameboy_t *gb, uint8_t opcode) +{ + bool carry = (gb->registers[GB_REGISTER_AF] & 0x100) != 0; + + GB_advance_cycles(gb, 4); + gb->registers[GB_REGISTER_AF] = (gb->registers[GB_REGISTER_AF] >> 1) & 0xFF00; + if (carry) { + gb->registers[GB_REGISTER_AF] |= GB_CARRY_FLAG | 0x8000; + } +} + +static void rra(GB_gameboy_t *gb, uint8_t opcode) +{ + bool bit1 = (gb->registers[GB_REGISTER_AF] & 0x0100) != 0; + bool carry = (gb->registers[GB_REGISTER_AF] & GB_CARRY_FLAG) != 0; + + GB_advance_cycles(gb, 4); + gb->registers[GB_REGISTER_AF] = (gb->registers[GB_REGISTER_AF] >> 1) & 0xFF00; + if (carry) { + gb->registers[GB_REGISTER_AF] |= 0x8000; + } + if (bit1) { + gb->registers[GB_REGISTER_AF] |= GB_CARRY_FLAG; + } +} + +static void jr_r8(GB_gameboy_t *gb, uint8_t opcode) +{ + /* Todo: Verify cycles are not 8 and 4 instead */ + GB_advance_cycles(gb, 4); + gb->pc += (int8_t)GB_read_memory(gb, gb->pc) + 1; + GB_advance_cycles(gb, 8); +} + +static bool condition_code(GB_gameboy_t *gb, uint8_t opcode) +{ + switch ((opcode >> 3) & 0x3) { + case 0: + return !(gb->registers[GB_REGISTER_AF] & GB_ZERO_FLAG); + case 1: + return (gb->registers[GB_REGISTER_AF] & GB_ZERO_FLAG); + case 2: + return !(gb->registers[GB_REGISTER_AF] & GB_CARRY_FLAG); + case 3: + return (gb->registers[GB_REGISTER_AF] & GB_CARRY_FLAG); + } + + return false; +} + +static void jr_cc_r8(GB_gameboy_t *gb, uint8_t opcode) +{ + if (condition_code(gb, opcode)) { + GB_advance_cycles(gb, 4); + gb->pc += (int8_t)GB_read_memory(gb, gb->pc) + 1; + GB_advance_cycles(gb, 8); + } + else { + GB_advance_cycles(gb, 8); + gb->pc += 1; + } +} + +static void daa(GB_gameboy_t *gb, uint8_t opcode) +{ + /* This function is UGLY and UNREADABLE! But it passes Blargg's daa test! */ + GB_advance_cycles(gb, 4); + gb->registers[GB_REGISTER_AF] &= ~GB_ZERO_FLAG; + if (gb->registers[GB_REGISTER_AF] & GB_SUBSTRACT_FLAG) { + if (gb->registers[GB_REGISTER_AF] & GB_HALF_CARRY_FLAG) { + gb->registers[GB_REGISTER_AF] &= ~GB_HALF_CARRY_FLAG; + if (gb->registers[GB_REGISTER_AF] & GB_CARRY_FLAG) { + gb->registers[GB_REGISTER_AF] += 0x9A00; + } + else { + gb->registers[GB_REGISTER_AF] += 0xFA00; + } + } + else if(gb->registers[GB_REGISTER_AF] & GB_CARRY_FLAG) { + gb->registers[GB_REGISTER_AF] += 0xA000; + } + } + else { + if (gb->registers[GB_REGISTER_AF] & GB_HALF_CARRY_FLAG) { + uint16_t number = gb->registers[GB_REGISTER_AF] >> 8; + if (gb->registers[GB_REGISTER_AF] & GB_CARRY_FLAG) { + number += 0x100; + } + gb->registers[GB_REGISTER_AF] = 0; + number += 0x06; + if (number >= 0xa0) { + number -= 0xa0; + gb->registers[GB_REGISTER_AF] |= GB_CARRY_FLAG; + } + gb->registers[GB_REGISTER_AF] |= number << 8; + } + else { + uint16_t number = gb->registers[GB_REGISTER_AF] >> 8; + if (gb->registers[GB_REGISTER_AF] & GB_CARRY_FLAG) { + number += 0x100; + } + if (number > 0x99) { + number += 0x60; + } + number = (number & 0x0F) + ((number & 0x0F) > 9 ? 6 : 0) + (number & 0xFF0); + gb->registers[GB_REGISTER_AF] = number << 8; + if (number & 0xFF00) { + gb->registers[GB_REGISTER_AF] |= GB_CARRY_FLAG; + } + } + } + if ((gb->registers[GB_REGISTER_AF] & 0xFF00) == 0) { + gb->registers[GB_REGISTER_AF] |= GB_ZERO_FLAG; + } +} + +static void cpl(GB_gameboy_t *gb, uint8_t opcode) +{ + GB_advance_cycles(gb, 4); + gb->registers[GB_REGISTER_AF] ^= 0xFF00; + gb->registers[GB_REGISTER_AF] |= GB_HALF_CARRY_FLAG | GB_SUBSTRACT_FLAG; +} + +static void scf(GB_gameboy_t *gb, uint8_t opcode) +{ + GB_advance_cycles(gb, 4); + gb->registers[GB_REGISTER_AF] |= GB_CARRY_FLAG; + gb->registers[GB_REGISTER_AF] &= ~(GB_HALF_CARRY_FLAG | GB_SUBSTRACT_FLAG); +} + +static void ccf(GB_gameboy_t *gb, uint8_t opcode) +{ + GB_advance_cycles(gb, 4); + gb->registers[GB_REGISTER_AF] ^= GB_CARRY_FLAG; + gb->registers[GB_REGISTER_AF] &= ~(GB_HALF_CARRY_FLAG | GB_SUBSTRACT_FLAG); +} + +static void ld_dhli_a(GB_gameboy_t *gb, uint8_t opcode) +{ + GB_advance_cycles(gb, 4); + GB_write_memory(gb, gb->registers[GB_REGISTER_HL]++, gb->registers[GB_REGISTER_AF] >> 8); + GB_advance_cycles(gb, 4); +} + +static void ld_dhld_a(GB_gameboy_t *gb, uint8_t opcode) +{ + GB_advance_cycles(gb, 4); + GB_write_memory(gb, gb->registers[GB_REGISTER_HL]--, gb->registers[GB_REGISTER_AF] >> 8); + GB_advance_cycles(gb, 4); +} + +static void ld_a_dhli(GB_gameboy_t *gb, uint8_t opcode) +{ + GB_advance_cycles(gb, 4); + gb->registers[GB_REGISTER_AF] &= 0xFF; + gb->registers[GB_REGISTER_AF] |= GB_read_memory(gb, gb->registers[GB_REGISTER_HL]++) << 8; + GB_advance_cycles(gb, 4); +} + +static void ld_a_dhld(GB_gameboy_t *gb, uint8_t opcode) +{ + GB_advance_cycles(gb, 4); + gb->registers[GB_REGISTER_AF] &= 0xFF; + gb->registers[GB_REGISTER_AF] |= GB_read_memory(gb, gb->registers[GB_REGISTER_HL]--) << 8; + GB_advance_cycles(gb, 4); +} + +static void inc_dhl(GB_gameboy_t *gb, uint8_t opcode) +{ + uint8_t value; + GB_advance_cycles(gb, 4); + value = GB_read_memory(gb, gb->registers[GB_REGISTER_HL]) + 1; + GB_advance_cycles(gb, 4); + GB_write_memory(gb, gb->registers[GB_REGISTER_HL], value); + GB_advance_cycles(gb, 4); + + gb->registers[GB_REGISTER_AF] &= ~(GB_SUBSTRACT_FLAG | GB_ZERO_FLAG | GB_HALF_CARRY_FLAG); + if ((value & 0x0F) == 0) { + gb->registers[GB_REGISTER_AF] |= GB_HALF_CARRY_FLAG; + } + + if ((value & 0xFF) == 0) { + gb->registers[GB_REGISTER_AF] |= GB_ZERO_FLAG; + } +} + +static void dec_dhl(GB_gameboy_t *gb, uint8_t opcode) +{ + uint8_t value; + GB_advance_cycles(gb, 4); + value = GB_read_memory(gb, gb->registers[GB_REGISTER_HL]) - 1; + GB_advance_cycles(gb, 4); + GB_write_memory(gb, gb->registers[GB_REGISTER_HL], value); + GB_advance_cycles(gb, 4); + + gb->registers[GB_REGISTER_AF] &= ~( GB_ZERO_FLAG | GB_HALF_CARRY_FLAG); + gb->registers[GB_REGISTER_AF] |= GB_SUBSTRACT_FLAG; + if ((value & 0x0F) == 0x0F) { + gb->registers[GB_REGISTER_AF] |= GB_HALF_CARRY_FLAG; + } + + if ((value & 0xFF) == 0) { + gb->registers[GB_REGISTER_AF] |= GB_ZERO_FLAG; + } +} + +static void ld_dhl_d8(GB_gameboy_t *gb, uint8_t opcode) +{ + GB_advance_cycles(gb, 4); + uint8_t data = GB_read_memory(gb, gb->pc++); + GB_advance_cycles(gb, 4); + GB_write_memory(gb, gb->registers[GB_REGISTER_HL], data); + GB_advance_cycles(gb, 4); +} + +uint8_t get_src_value(GB_gameboy_t *gb, uint8_t opcode) +{ + uint8_t src_register_id; + uint8_t src_low; + src_register_id = ((opcode >> 1) + 1) & 3; + src_low = opcode & 1; + if (src_register_id == GB_REGISTER_AF) { + if (src_low) { + return gb->registers[GB_REGISTER_AF] >> 8; + } + uint8_t ret = GB_read_memory(gb, gb->registers[GB_REGISTER_HL]); + GB_advance_cycles(gb, 4); + return ret; + } + if (src_low) { + return gb->registers[src_register_id] & 0xFF; + } + return gb->registers[src_register_id] >> 8; +} + +static void set_src_value(GB_gameboy_t *gb, uint8_t opcode, uint8_t value) +{ + uint8_t src_register_id; + uint8_t src_low; + src_register_id = ((opcode >> 1) + 1) & 3; + src_low = opcode & 1; + + if (src_register_id == GB_REGISTER_AF) { + if (src_low) { + gb->registers[GB_REGISTER_AF] &= 0xFF; + gb->registers[GB_REGISTER_AF] |= value << 8; + } + else { + GB_write_memory(gb, gb->registers[GB_REGISTER_HL], value); + GB_advance_cycles(gb, 4); + } + } + else { + if (src_low) { + gb->registers[src_register_id] &= 0xFF00; + gb->registers[src_register_id] |= value; + } + else { + gb->registers[src_register_id] &= 0xFF; + gb->registers[src_register_id] |= value << 8; + } + } +} + +/* The LD r,r instruction is extremely common and extremely simple. Decoding this opcode at runtime is a significent + performance hit, so we generate functions for every ld x,y couple (including [hl]) at compile time using macros. */ + +/* Todo: It's probably wise to do the same to all opcodes. */ + +#define LD_X_Y(x, y) \ +static void ld_##x##_##y(GB_gameboy_t *gb, uint8_t opcode) \ +{ \ + GB_advance_cycles(gb, 4); \ + gb->x = gb->y;\ +} + +#define LD_X_DHL(x) \ +static void ld_##x##_##dhl(GB_gameboy_t *gb, uint8_t opcode) \ +{ \ +GB_advance_cycles(gb, 4); \ +gb->x = GB_read_memory(gb, gb->registers[GB_REGISTER_HL]); \ +GB_advance_cycles(gb, 4);\ +} + +#define LD_DHL_Y(y) \ +static void ld_##dhl##_##y(GB_gameboy_t *gb, uint8_t opcode) \ +{ \ +GB_advance_cycles(gb, 4); \ +GB_write_memory(gb, gb->registers[GB_REGISTER_HL], gb->y); \ +GB_advance_cycles(gb, 4);\ +} + +LD_X_Y(b,c) LD_X_Y(b,d) LD_X_Y(b,e) LD_X_Y(b,h) LD_X_Y(b,l) LD_X_DHL(b) LD_X_Y(b,a) +LD_X_Y(c,b) LD_X_Y(c,d) LD_X_Y(c,e) LD_X_Y(c,h) LD_X_Y(c,l) LD_X_DHL(c) LD_X_Y(c,a) +LD_X_Y(d,b) LD_X_Y(d,c) LD_X_Y(d,e) LD_X_Y(d,h) LD_X_Y(d,l) LD_X_DHL(d) LD_X_Y(d,a) +LD_X_Y(e,b) LD_X_Y(e,c) LD_X_Y(e,d) LD_X_Y(e,h) LD_X_Y(e,l) LD_X_DHL(e) LD_X_Y(e,a) +LD_X_Y(h,b) LD_X_Y(h,c) LD_X_Y(h,d) LD_X_Y(h,e) LD_X_Y(h,l) LD_X_DHL(h) LD_X_Y(h,a) +LD_X_Y(l,b) LD_X_Y(l,c) LD_X_Y(l,d) LD_X_Y(l,e) LD_X_Y(l,h) LD_X_DHL(l) LD_X_Y(l,a) +LD_DHL_Y(b) LD_DHL_Y(c) LD_DHL_Y(d) LD_DHL_Y(e) LD_DHL_Y(h) LD_DHL_Y(l) LD_DHL_Y(a) +LD_X_Y(a,b) LD_X_Y(a,c) LD_X_Y(a,d) LD_X_Y(a,e) LD_X_Y(a,h) LD_X_Y(a,l) LD_X_DHL(a) + + +static void add_a_r(GB_gameboy_t *gb, uint8_t opcode) +{ + uint8_t value, a; + GB_advance_cycles(gb, 4); + value = get_src_value(gb, opcode); + a = gb->registers[GB_REGISTER_AF] >> 8; + gb->registers[GB_REGISTER_AF] = (a + value) << 8; + if ((uint8_t)(a + value) == 0) { + gb->registers[GB_REGISTER_AF] |= GB_ZERO_FLAG; + } + if ((a & 0xF) + (value & 0xF) > 0x0F) { + gb->registers[GB_REGISTER_AF] |= GB_HALF_CARRY_FLAG; + } + if (((unsigned long) a) + ((unsigned long) value) > 0xFF) { + gb->registers[GB_REGISTER_AF] |= GB_CARRY_FLAG; + } +} + +static void adc_a_r(GB_gameboy_t *gb, uint8_t opcode) +{ + uint8_t value, a, carry; + GB_advance_cycles(gb, 4); + value = get_src_value(gb, opcode); + a = gb->registers[GB_REGISTER_AF] >> 8; + carry = (gb->registers[GB_REGISTER_AF] & GB_CARRY_FLAG) != 0; + gb->registers[GB_REGISTER_AF] = (a + value + carry) << 8; + + if ((uint8_t)(a + value + carry) == 0) { + gb->registers[GB_REGISTER_AF] |= GB_ZERO_FLAG; + } + if ((a & 0xF) + (value & 0xF) + carry > 0x0F) { + gb->registers[GB_REGISTER_AF] |= GB_HALF_CARRY_FLAG; + } + if (((unsigned long) a) + ((unsigned long) value) + carry > 0xFF) { + gb->registers[GB_REGISTER_AF] |= GB_CARRY_FLAG; + } +} + +static void sub_a_r(GB_gameboy_t *gb, uint8_t opcode) +{ + uint8_t value, a; + GB_advance_cycles(gb, 4); + value = get_src_value(gb, opcode); + a = gb->registers[GB_REGISTER_AF] >> 8; + gb->registers[GB_REGISTER_AF] = ((a - value) << 8) | GB_SUBSTRACT_FLAG; + if (a == value) { + gb->registers[GB_REGISTER_AF] |= GB_ZERO_FLAG; + } + if ((a & 0xF) < (value & 0xF)) { + gb->registers[GB_REGISTER_AF] |= GB_HALF_CARRY_FLAG; + } + if (a < value) { + gb->registers[GB_REGISTER_AF] |= GB_CARRY_FLAG; + } +} + +static void sbc_a_r(GB_gameboy_t *gb, uint8_t opcode) +{ + uint8_t value, a, carry; + GB_advance_cycles(gb, 4); + value = get_src_value(gb, opcode); + a = gb->registers[GB_REGISTER_AF] >> 8; + carry = (gb->registers[GB_REGISTER_AF] & GB_CARRY_FLAG) != 0; + gb->registers[GB_REGISTER_AF] = ((a - value - carry) << 8) | GB_SUBSTRACT_FLAG; + + if ((uint8_t) (a - value - carry) == 0) { + gb->registers[GB_REGISTER_AF] |= GB_ZERO_FLAG; + } + if ((a & 0xF) < (value & 0xF) + carry) { + gb->registers[GB_REGISTER_AF] |= GB_HALF_CARRY_FLAG; + } + if (((unsigned long) a) - ((unsigned long) value) - carry > 0xFF) { + gb->registers[GB_REGISTER_AF] |= GB_CARRY_FLAG; + } +} + +static void and_a_r(GB_gameboy_t *gb, uint8_t opcode) +{ + uint8_t value, a; + GB_advance_cycles(gb, 4); + value = get_src_value(gb, opcode); + a = gb->registers[GB_REGISTER_AF] >> 8; + gb->registers[GB_REGISTER_AF] = ((a & value) << 8) | GB_HALF_CARRY_FLAG; + if ((a & value) == 0) { + gb->registers[GB_REGISTER_AF] |= GB_ZERO_FLAG; + } +} + +static void xor_a_r(GB_gameboy_t *gb, uint8_t opcode) +{ + uint8_t value, a; + GB_advance_cycles(gb, 4); + value = get_src_value(gb, opcode); + a = gb->registers[GB_REGISTER_AF] >> 8; + gb->registers[GB_REGISTER_AF] = (a ^ value) << 8; + if ((a ^ value) == 0) { + gb->registers[GB_REGISTER_AF] |= GB_ZERO_FLAG; + } +} + +static void or_a_r(GB_gameboy_t *gb, uint8_t opcode) +{ + uint8_t value, a; + GB_advance_cycles(gb, 4); + value = get_src_value(gb, opcode); + a = gb->registers[GB_REGISTER_AF] >> 8; + gb->registers[GB_REGISTER_AF] = (a | value) << 8; + if ((a | value) == 0) { + gb->registers[GB_REGISTER_AF] |= GB_ZERO_FLAG; + } +} + +static void cp_a_r(GB_gameboy_t *gb, uint8_t opcode) +{ + uint8_t value, a; + GB_advance_cycles(gb, 4); + value = get_src_value(gb, opcode); + a = gb->registers[GB_REGISTER_AF] >> 8; + gb->registers[GB_REGISTER_AF] &= 0xFF00; + gb->registers[GB_REGISTER_AF] |= GB_SUBSTRACT_FLAG; + if (a == value) { + gb->registers[GB_REGISTER_AF] |= GB_ZERO_FLAG; + } + if ((a & 0xF) < (value & 0xF)) { + gb->registers[GB_REGISTER_AF] |= GB_HALF_CARRY_FLAG; + } + if (a < value) { + gb->registers[GB_REGISTER_AF] |= GB_CARRY_FLAG; + } +} + +static void halt(GB_gameboy_t *gb, uint8_t opcode) +{ + GB_advance_cycles(gb, 4); + gb->halted = true; + /* Despite what some online documentations say, the HALT bug also happens on a CGB, in both CGB and DMG modes. */ + if (!gb->ime && (gb->interrupt_enable & gb->io_registers[GB_IO_IF] & 0x1F) != 0) { + gb->halted = false; + gb->halt_bug = true; + } +} + +static void ret_cc(GB_gameboy_t *gb, uint8_t opcode) +{ + /* Todo: Verify timing */ + if (condition_code(gb, opcode)) { + GB_advance_cycles(gb, 8); + gb->pc = GB_read_memory(gb, gb->registers[GB_REGISTER_SP]); + GB_advance_cycles(gb, 4); + gb->pc |= GB_read_memory(gb, gb->registers[GB_REGISTER_SP] + 1) << 8; + GB_advance_cycles(gb, 8); + gb->registers[GB_REGISTER_SP] += 2; + } + else { + GB_advance_cycles(gb, 8); + } +} + +static void pop_rr(GB_gameboy_t *gb, uint8_t opcode) +{ + uint8_t register_id; + GB_advance_cycles(gb, 4); + register_id = ((opcode >> 4) + 1) & 3; + gb->registers[register_id] = GB_read_memory(gb, gb->registers[GB_REGISTER_SP]); + GB_advance_cycles(gb, 4); + gb->registers[register_id] |= GB_read_memory(gb, gb->registers[GB_REGISTER_SP] + 1) << 8; + GB_advance_cycles(gb, 4); + gb->registers[GB_REGISTER_AF] &= 0xFFF0; // Make sure we don't set impossible flags on F! See Blargg's PUSH AF test. + gb->registers[GB_REGISTER_SP] += 2; +} + +static void jp_cc_a16(GB_gameboy_t *gb, uint8_t opcode) +{ + if (condition_code(gb, opcode)) { + GB_advance_cycles(gb, 4); + uint16_t addr = GB_read_memory(gb, gb->pc); + GB_advance_cycles(gb, 4); + addr |= (GB_read_memory(gb, gb->pc + 1) << 8); + GB_advance_cycles(gb, 8); + gb->pc = addr; + + } + else { + GB_advance_cycles(gb, 12); + gb->pc += 2; + } +} + +static void jp_a16(GB_gameboy_t *gb, uint8_t opcode) +{ + GB_advance_cycles(gb, 4); + uint16_t addr = GB_read_memory(gb, gb->pc); + GB_advance_cycles(gb, 4); + addr |= (GB_read_memory(gb, gb->pc + 1) << 8); + GB_advance_cycles(gb, 8); + gb->pc = addr;} + +static void call_cc_a16(GB_gameboy_t *gb, uint8_t opcode) +{ + uint16_t call_addr = gb->pc - 1; + if (condition_code(gb, opcode)) { + GB_advance_cycles(gb, 4); + gb->registers[GB_REGISTER_SP] -= 2; + uint16_t addr = GB_read_memory(gb, gb->pc++); + GB_advance_cycles(gb, 4); + addr |= (GB_read_memory(gb, gb->pc++) << 8); + GB_advance_cycles(gb, 8); + GB_write_memory(gb, gb->registers[GB_REGISTER_SP] + 1, (gb->pc) >> 8); + GB_advance_cycles(gb, 4); + GB_write_memory(gb, gb->registers[GB_REGISTER_SP], (gb->pc) & 0xFF); + GB_advance_cycles(gb, 4); + gb->pc = addr; + } + else { + GB_advance_cycles(gb, 12); + gb->pc += 2; + } +} + +static void push_rr(GB_gameboy_t *gb, uint8_t opcode) +{ + uint8_t register_id; + GB_advance_cycles(gb, 8); + register_id = ((opcode >> 4) + 1) & 3; + gb->registers[GB_REGISTER_SP] -= 2; + GB_write_memory(gb, gb->registers[GB_REGISTER_SP] + 1, (gb->registers[register_id]) >> 8); + GB_advance_cycles(gb, 4); + GB_write_memory(gb, gb->registers[GB_REGISTER_SP], (gb->registers[register_id]) & 0xFF); + GB_advance_cycles(gb, 4); +} + +static void add_a_d8(GB_gameboy_t *gb, uint8_t opcode) +{ + uint8_t value, a; + GB_advance_cycles(gb, 4); + value = GB_read_memory(gb, gb->pc++); + GB_advance_cycles(gb, 4); + a = gb->registers[GB_REGISTER_AF] >> 8; + gb->registers[GB_REGISTER_AF] = (a + value) << 8; + if ((uint8_t) (a + value) == 0) { + gb->registers[GB_REGISTER_AF] |= GB_ZERO_FLAG; + } + if ((a & 0xF) + (value & 0xF) > 0x0F) { + gb->registers[GB_REGISTER_AF] |= GB_HALF_CARRY_FLAG; + } + if (((unsigned long) a) + ((unsigned long) value) > 0xFF) { + gb->registers[GB_REGISTER_AF] |= GB_CARRY_FLAG; + } +} + +static void adc_a_d8(GB_gameboy_t *gb, uint8_t opcode) +{ + uint8_t value, a, carry; + GB_advance_cycles(gb, 4); + value = GB_read_memory(gb, gb->pc++); + GB_advance_cycles(gb, 4); + a = gb->registers[GB_REGISTER_AF] >> 8; + carry = (gb->registers[GB_REGISTER_AF] & GB_CARRY_FLAG) != 0; + gb->registers[GB_REGISTER_AF] = (a + value + carry) << 8; + + if (gb->registers[GB_REGISTER_AF] == 0) { + gb->registers[GB_REGISTER_AF] |= GB_ZERO_FLAG; + } + if ((a & 0xF) + (value & 0xF) + carry > 0x0F) { + gb->registers[GB_REGISTER_AF] |= GB_HALF_CARRY_FLAG; + } + if (((unsigned long) a) + ((unsigned long) value) + carry > 0xFF) { + gb->registers[GB_REGISTER_AF] |= GB_CARRY_FLAG; + } +} + +static void sub_a_d8(GB_gameboy_t *gb, uint8_t opcode) +{ + uint8_t value, a; + GB_advance_cycles(gb, 4); + value = GB_read_memory(gb, gb->pc++); + GB_advance_cycles(gb, 4); + a = gb->registers[GB_REGISTER_AF] >> 8; + gb->registers[GB_REGISTER_AF] = ((a - value) << 8) | GB_SUBSTRACT_FLAG; + if (a == value) { + gb->registers[GB_REGISTER_AF] |= GB_ZERO_FLAG; + } + if ((a & 0xF) < (value & 0xF)) { + gb->registers[GB_REGISTER_AF] |= GB_HALF_CARRY_FLAG; + } + if (a < value) { + gb->registers[GB_REGISTER_AF] |= GB_CARRY_FLAG; + } +} + +static void sbc_a_d8(GB_gameboy_t *gb, uint8_t opcode) +{ + uint8_t value, a, carry; + GB_advance_cycles(gb, 4); + value = GB_read_memory(gb, gb->pc++); + GB_advance_cycles(gb, 4); + a = gb->registers[GB_REGISTER_AF] >> 8; + carry = (gb->registers[GB_REGISTER_AF] & GB_CARRY_FLAG) != 0; + gb->registers[GB_REGISTER_AF] = ((a - value - carry) << 8) | GB_SUBSTRACT_FLAG; + + if ((uint8_t) (a - value - carry) == 0) { + gb->registers[GB_REGISTER_AF] |= GB_ZERO_FLAG; + } + if ((a & 0xF) < (value & 0xF) + carry) { + gb->registers[GB_REGISTER_AF] |= GB_HALF_CARRY_FLAG; + } + if (((unsigned long) a) - ((unsigned long) value) - carry > 0xFF) { + gb->registers[GB_REGISTER_AF] |= GB_CARRY_FLAG; + } +} + +static void and_a_d8(GB_gameboy_t *gb, uint8_t opcode) +{ + uint8_t value, a; + GB_advance_cycles(gb, 4); + value = GB_read_memory(gb, gb->pc++); + GB_advance_cycles(gb, 4); + a = gb->registers[GB_REGISTER_AF] >> 8; + gb->registers[GB_REGISTER_AF] = ((a & value) << 8) | GB_HALF_CARRY_FLAG; + if ((a & value) == 0) { + gb->registers[GB_REGISTER_AF] |= GB_ZERO_FLAG; + } +} + +static void xor_a_d8(GB_gameboy_t *gb, uint8_t opcode) +{ + uint8_t value, a; + GB_advance_cycles(gb, 4); + value = GB_read_memory(gb, gb->pc++); + GB_advance_cycles(gb, 4); + a = gb->registers[GB_REGISTER_AF] >> 8; + gb->registers[GB_REGISTER_AF] = (a ^ value) << 8; + if ((a ^ value) == 0) { + gb->registers[GB_REGISTER_AF] |= GB_ZERO_FLAG; + } +} + +static void or_a_d8(GB_gameboy_t *gb, uint8_t opcode) +{ + uint8_t value, a; + GB_advance_cycles(gb, 4); + value = GB_read_memory(gb, gb->pc++); + GB_advance_cycles(gb, 4); + a = gb->registers[GB_REGISTER_AF] >> 8; + gb->registers[GB_REGISTER_AF] = (a | value) << 8; + if ((a | value) == 0) { + gb->registers[GB_REGISTER_AF] |= GB_ZERO_FLAG; + } +} + +static void cp_a_d8(GB_gameboy_t *gb, uint8_t opcode) +{ + uint8_t value, a; + GB_advance_cycles(gb, 4); + value = GB_read_memory(gb, gb->pc++); + GB_advance_cycles(gb, 4); + a = gb->registers[GB_REGISTER_AF] >> 8; + gb->registers[GB_REGISTER_AF] &= 0xFF00; + gb->registers[GB_REGISTER_AF] |= GB_SUBSTRACT_FLAG; + if (a == value) { + gb->registers[GB_REGISTER_AF] |= GB_ZERO_FLAG; + } + if ((a & 0xF) < (value & 0xF)) { + gb->registers[GB_REGISTER_AF] |= GB_HALF_CARRY_FLAG; + } + if (a < value) { + gb->registers[GB_REGISTER_AF] |= GB_CARRY_FLAG; + } +} + +static void rst(GB_gameboy_t *gb, uint8_t opcode) +{ + uint16_t call_addr = gb->pc - 1; + GB_advance_cycles(gb, 8); + gb->registers[GB_REGISTER_SP] -= 2; + GB_write_memory(gb, gb->registers[GB_REGISTER_SP] + 1, (gb->pc) >> 8); + GB_advance_cycles(gb, 4); + GB_write_memory(gb, gb->registers[GB_REGISTER_SP], (gb->pc) & 0xFF); + GB_advance_cycles(gb, 4); + gb->pc = opcode ^ 0xC7; +} + +static void ret(GB_gameboy_t *gb, uint8_t opcode) +{ + GB_advance_cycles(gb, 4); + gb->pc = GB_read_memory(gb, gb->registers[GB_REGISTER_SP]); + GB_advance_cycles(gb, 4); + gb->pc |= GB_read_memory(gb, gb->registers[GB_REGISTER_SP] + 1) << 8; + GB_advance_cycles(gb, 8); + gb->registers[GB_REGISTER_SP] += 2; +} + +static void reti(GB_gameboy_t *gb, uint8_t opcode) +{ + ret(gb, opcode); + gb->ime = true; +} + +static void call_a16(GB_gameboy_t *gb, uint8_t opcode) +{ + uint16_t call_addr = gb->pc - 1; + GB_advance_cycles(gb, 4); + gb->registers[GB_REGISTER_SP] -= 2; + uint16_t addr = GB_read_memory(gb, gb->pc++); + GB_advance_cycles(gb, 4); + addr |= (GB_read_memory(gb, gb->pc++) << 8); + GB_advance_cycles(gb, 8); + GB_write_memory(gb, gb->registers[GB_REGISTER_SP] + 1, (gb->pc) >> 8); + GB_advance_cycles(gb, 4); + GB_write_memory(gb, gb->registers[GB_REGISTER_SP], (gb->pc) & 0xFF); + GB_advance_cycles(gb, 4); + gb->pc = addr; +} + +static void ld_da8_a(GB_gameboy_t *gb, uint8_t opcode) +{ + GB_advance_cycles(gb, 4); + uint8_t temp = GB_read_memory(gb, gb->pc++); + GB_advance_cycles(gb, 4); + GB_write_memory(gb, 0xFF00 + temp, gb->registers[GB_REGISTER_AF] >> 8); + GB_advance_cycles(gb, 4); +} + +static void ld_a_da8(GB_gameboy_t *gb, uint8_t opcode) +{ + GB_advance_cycles(gb, 4); + gb->registers[GB_REGISTER_AF] &= 0xFF; + uint8_t temp = GB_read_memory(gb, gb->pc++); + GB_advance_cycles(gb, 4); + gb->registers[GB_REGISTER_AF] |= GB_read_memory(gb, 0xFF00 + temp) << 8; + GB_advance_cycles(gb, 4); +} + +static void ld_dc_a(GB_gameboy_t *gb, uint8_t opcode) +{ + GB_advance_cycles(gb, 4); + GB_write_memory(gb, 0xFF00 + (gb->registers[GB_REGISTER_BC] & 0xFF), gb->registers[GB_REGISTER_AF] >> 8); + GB_advance_cycles(gb, 4); +} + +static void ld_a_dc(GB_gameboy_t *gb, uint8_t opcode) +{ + GB_advance_cycles(gb, 4); + gb->registers[GB_REGISTER_AF] &= 0xFF; + gb->registers[GB_REGISTER_AF] |= GB_read_memory(gb, 0xFF00 + (gb->registers[GB_REGISTER_BC] & 0xFF)) << 8; + GB_advance_cycles(gb, 4); +} + +static void add_sp_r8(GB_gameboy_t *gb, uint8_t opcode) +{ + int16_t offset; + uint16_t sp = gb->registers[GB_REGISTER_SP]; + GB_advance_cycles(gb, 4); + offset = (int8_t) GB_read_memory(gb, gb->pc++); + GB_advance_cycles(gb, 12); + gb->registers[GB_REGISTER_SP] += offset; + + gb->registers[GB_REGISTER_AF] &= 0xFF00; + + /* A new instruction, a new meaning for Half Carry! */ + if ((sp & 0xF) + (offset & 0xF) > 0xF) { + gb->registers[GB_REGISTER_AF] |= GB_HALF_CARRY_FLAG; + } + + if ((sp & 0xFF) + (offset & 0xFF) > 0xFF) { + gb->registers[GB_REGISTER_AF] |= GB_CARRY_FLAG; + } +} + +static void jp_hl(GB_gameboy_t *gb, uint8_t opcode) +{ + GB_advance_cycles(gb, 4); + gb->pc = gb->registers[GB_REGISTER_HL]; +} + +static void ld_da16_a(GB_gameboy_t *gb, uint8_t opcode) +{ + uint16_t addr; + GB_advance_cycles(gb, 4); + addr = GB_read_memory(gb, gb->pc++); + GB_advance_cycles(gb, 4); + addr |= GB_read_memory(gb, gb->pc++) << 8; + GB_advance_cycles(gb, 4); + GB_write_memory(gb, addr, gb->registers[GB_REGISTER_AF] >> 8); + GB_advance_cycles(gb, 4); +} + +static void ld_a_da16(GB_gameboy_t *gb, uint8_t opcode) +{ + uint16_t addr; + GB_advance_cycles(gb, 4); + gb->registers[GB_REGISTER_AF] &= 0xFF; + addr = GB_read_memory(gb, gb->pc++); + GB_advance_cycles(gb, 4); + addr |= GB_read_memory(gb, gb->pc++) << 8 ; + GB_advance_cycles(gb, 4); + gb->registers[GB_REGISTER_AF] |= GB_read_memory(gb, addr) << 8; + GB_advance_cycles(gb, 4); +} + +static void di(GB_gameboy_t *gb, uint8_t opcode) +{ + /* DI is NOT delayed, not even on a CGB. Mooneye's di_timing-GS test fails on a CGB + for different reasons.*/ + GB_advance_cycles(gb, 4); + gb->ime = false; +} + +static void ei(GB_gameboy_t *gb, uint8_t opcode) +{ + /* ei is actually "disable interrupts for one instruction, then enable them". */ + GB_advance_cycles(gb, 4); + gb->ime = false; + gb->ime_toggle = true; +} + +static void ld_hl_sp_r8(GB_gameboy_t *gb, uint8_t opcode) +{ + int16_t offset; + GB_advance_cycles(gb, 4); + gb->registers[GB_REGISTER_AF] &= 0xFF00; + offset = (int8_t) GB_read_memory(gb, gb->pc++); + GB_advance_cycles(gb, 8); + gb->registers[GB_REGISTER_HL] = gb->registers[GB_REGISTER_SP] + offset; + + if ((gb->registers[GB_REGISTER_SP] & 0xF) + (offset & 0xF) > 0xF) { + gb->registers[GB_REGISTER_AF] |= GB_HALF_CARRY_FLAG; + } + + if ((gb->registers[GB_REGISTER_SP] & 0xFF) + (offset & 0xFF) > 0xFF) { + gb->registers[GB_REGISTER_AF] |= GB_CARRY_FLAG; + } +} + +static void ld_sp_hl(GB_gameboy_t *gb, uint8_t opcode) +{ + GB_advance_cycles(gb, 8); + gb->registers[GB_REGISTER_SP] = gb->registers[GB_REGISTER_HL]; +} + +static void rlc_r(GB_gameboy_t *gb, uint8_t opcode) +{ + bool carry; + uint8_t value; + GB_advance_cycles(gb, 4); + value = get_src_value(gb, opcode); + carry = (value & 0x80) != 0; + gb->registers[GB_REGISTER_AF] &= 0xFF00; + set_src_value(gb, opcode, (value << 1) | carry); + if (carry) { + gb->registers[GB_REGISTER_AF] |= GB_CARRY_FLAG; + } + if (!(value << 1)) { + gb->registers[GB_REGISTER_AF] |= GB_ZERO_FLAG; + } +} + +static void rrc_r(GB_gameboy_t *gb, uint8_t opcode) +{ + bool carry; + uint8_t value; + GB_advance_cycles(gb, 4); + value = get_src_value(gb, opcode); + carry = (value & 0x01) != 0; + gb->registers[GB_REGISTER_AF] &= 0xFF00; + value = (value >> 1) | (carry << 7); + set_src_value(gb, opcode, value); + if (carry) { + gb->registers[GB_REGISTER_AF] |= GB_CARRY_FLAG; + } + if (value == 0) { + gb->registers[GB_REGISTER_AF] |= GB_ZERO_FLAG; + } +} + +static void rl_r(GB_gameboy_t *gb, uint8_t opcode) +{ + bool carry; + uint8_t value; + bool bit7; + GB_advance_cycles(gb, 4); + value = get_src_value(gb, opcode); + carry = (gb->registers[GB_REGISTER_AF] & GB_CARRY_FLAG) != 0; + bit7 = (value & 0x80) != 0; + + gb->registers[GB_REGISTER_AF] &= 0xFF00; + value = (value << 1) | carry; + set_src_value(gb, opcode, value); + if (bit7) { + gb->registers[GB_REGISTER_AF] |= GB_CARRY_FLAG; + } + if (value == 0) { + gb->registers[GB_REGISTER_AF] |= GB_ZERO_FLAG; + } +} + +static void rr_r(GB_gameboy_t *gb, uint8_t opcode) +{ + bool carry; + uint8_t value; + bool bit1; + + GB_advance_cycles(gb, 4); + value = get_src_value(gb, opcode); + carry = (gb->registers[GB_REGISTER_AF] & GB_CARRY_FLAG) != 0; + bit1 = (value & 0x1) != 0; + + gb->registers[GB_REGISTER_AF] &= 0xFF00; + value = (value >> 1) | (carry << 7); + set_src_value(gb, opcode, value); + if (bit1) { + gb->registers[GB_REGISTER_AF] |= GB_CARRY_FLAG; + } + if (value == 0) { + gb->registers[GB_REGISTER_AF] |= GB_ZERO_FLAG; + } +} + +static void sla_r(GB_gameboy_t *gb, uint8_t opcode) +{ + uint8_t value; + bool carry; + GB_advance_cycles(gb, 4); + value = get_src_value(gb, opcode); + carry = (value & 0x80) != 0; + gb->registers[GB_REGISTER_AF] &= 0xFF00; + set_src_value(gb, opcode, (value << 1)); + if (carry) { + gb->registers[GB_REGISTER_AF] |= GB_CARRY_FLAG; + } + if ((value & 0x7F) == 0) { + gb->registers[GB_REGISTER_AF] |= GB_ZERO_FLAG; + } +} + +static void sra_r(GB_gameboy_t *gb, uint8_t opcode) +{ + uint8_t bit7; + uint8_t value; + GB_advance_cycles(gb, 4); + value = get_src_value(gb, opcode); + bit7 = value & 0x80; + gb->registers[GB_REGISTER_AF] &= 0xFF00; + if (value & 1) { + gb->registers[GB_REGISTER_AF] |= GB_CARRY_FLAG; + } + value = (value >> 1) | bit7; + set_src_value(gb, opcode, value); + if (value == 0) { + gb->registers[GB_REGISTER_AF] |= GB_ZERO_FLAG; + } +} + +static void srl_r(GB_gameboy_t *gb, uint8_t opcode) +{ + uint8_t value; + GB_advance_cycles(gb, 4); + value = get_src_value(gb, opcode); + gb->registers[GB_REGISTER_AF] &= 0xFF00; + set_src_value(gb, opcode, (value >> 1)); + if (value & 1) { + gb->registers[GB_REGISTER_AF] |= GB_CARRY_FLAG; + } + if (!(value >> 1)) { + gb->registers[GB_REGISTER_AF] |= GB_ZERO_FLAG; + } +} + +static void swap_r(GB_gameboy_t *gb, uint8_t opcode) +{ + uint8_t value; + GB_advance_cycles(gb, 4); + value = get_src_value(gb, opcode); + gb->registers[GB_REGISTER_AF] &= 0xFF00; + set_src_value(gb, opcode, (value >> 4) | (value << 4)); + if (!value) { + gb->registers[GB_REGISTER_AF] |= GB_ZERO_FLAG; + } +} + +static void bit_r(GB_gameboy_t *gb, uint8_t opcode) +{ + uint8_t value; + uint8_t bit; + GB_advance_cycles(gb, 4); + value = get_src_value(gb, opcode); + bit = 1 << ((opcode >> 3) & 7); + if ((opcode & 0xC0) == 0x40) { /* Bit */ + gb->registers[GB_REGISTER_AF] &= 0xFF00 | GB_CARRY_FLAG; + gb->registers[GB_REGISTER_AF] |= GB_HALF_CARRY_FLAG; + if (!(bit & value)) { + gb->registers[GB_REGISTER_AF] |= GB_ZERO_FLAG; + } + } + else if ((opcode & 0xC0) == 0x80) { /* res */ + set_src_value(gb, opcode, value & ~bit) ; + } + else if ((opcode & 0xC0) == 0xC0) { /* set */ + set_src_value(gb, opcode, value | bit) ; + } +} + +static void cb_prefix(GB_gameboy_t *gb, uint8_t opcode) +{ + GB_advance_cycles(gb, 4); + opcode = GB_read_memory(gb, gb->pc++); + switch (opcode >> 3) { + case 0: + rlc_r(gb, opcode); + break; + case 1: + rrc_r(gb, opcode); + break; + case 2: + rl_r(gb, opcode); + break; + case 3: + rr_r(gb, opcode); + break; + case 4: + sla_r(gb, opcode); + break; + case 5: + sra_r(gb, opcode); + break; + case 6: + swap_r(gb, opcode); + break; + case 7: + srl_r(gb, opcode); + break; + default: + bit_r(gb, opcode); + break; + } +} + +static GB_opcode_t *opcodes[256] = { + /* X0 X1 X2 X3 X4 X5 X6 X7 */ + /* X8 X9 Xa Xb Xc Xd Xe Xf */ + nop, ld_rr_d16, ld_drr_a, inc_rr, inc_hr, dec_hr, ld_hr_d8, rlca, /* 0X */ + ld_da16_sp, add_hl_rr, ld_a_drr, dec_rr, inc_lr, dec_lr, ld_lr_d8, rrca, + stop, ld_rr_d16, ld_drr_a, inc_rr, inc_hr, dec_hr, ld_hr_d8, rla, /* 1X */ + jr_r8, add_hl_rr, ld_a_drr, dec_rr, inc_lr, dec_lr, ld_lr_d8, rra, + jr_cc_r8, ld_rr_d16, ld_dhli_a, inc_rr, inc_hr, dec_hr, ld_hr_d8, daa, /* 2X */ + jr_cc_r8, add_hl_rr, ld_a_dhli, dec_rr, inc_lr, dec_lr, ld_lr_d8, cpl, + jr_cc_r8, ld_rr_d16, ld_dhld_a, inc_rr, inc_dhl, dec_dhl, ld_dhl_d8, scf, /* 3X */ + jr_cc_r8, add_hl_rr, ld_a_dhld, dec_rr, inc_hr, dec_hr, ld_hr_d8, ccf, + nop, ld_b_c, ld_b_d, ld_b_e, ld_b_h, ld_b_l, ld_b_dhl, ld_b_a, /* 4X */ + ld_c_b, nop, ld_c_d, ld_c_e, ld_c_h, ld_c_l, ld_c_dhl, ld_c_a, + ld_d_b, ld_d_c, nop, ld_d_e, ld_d_h, ld_d_l, ld_d_dhl, ld_d_a, /* 5X */ + ld_e_b, ld_e_c, ld_e_d, nop, ld_e_h, ld_e_l, ld_e_dhl, ld_e_a, + ld_h_b, ld_h_c, ld_h_d, ld_h_e, nop, ld_h_l, ld_h_dhl, ld_h_a, /* 6X */ + ld_l_b, ld_l_c, ld_l_d, ld_l_e, ld_l_h, nop, ld_l_dhl, ld_l_a, + ld_dhl_b, ld_dhl_c, ld_dhl_d, ld_dhl_e, ld_dhl_h, ld_dhl_l, halt, ld_dhl_a, /* 7X */ + ld_a_b, ld_a_c, ld_a_d, ld_a_e, ld_a_h, ld_a_l, ld_a_dhl, nop, + add_a_r, add_a_r, add_a_r, add_a_r, add_a_r, add_a_r, add_a_r, add_a_r, /* 8X */ + adc_a_r, adc_a_r, adc_a_r, adc_a_r, adc_a_r, adc_a_r, adc_a_r, adc_a_r, + sub_a_r, sub_a_r, sub_a_r, sub_a_r, sub_a_r, sub_a_r, sub_a_r, sub_a_r, /* 9X */ + sbc_a_r, sbc_a_r, sbc_a_r, sbc_a_r, sbc_a_r, sbc_a_r, sbc_a_r, sbc_a_r, + and_a_r, and_a_r, and_a_r, and_a_r, and_a_r, and_a_r, and_a_r, and_a_r, /* aX */ + xor_a_r, xor_a_r, xor_a_r, xor_a_r, xor_a_r, xor_a_r, xor_a_r, xor_a_r, + or_a_r, or_a_r, or_a_r, or_a_r, or_a_r, or_a_r, or_a_r, or_a_r, /* bX */ + cp_a_r, cp_a_r, cp_a_r, cp_a_r, cp_a_r, cp_a_r, cp_a_r, cp_a_r, + ret_cc, pop_rr, jp_cc_a16, jp_a16, call_cc_a16,push_rr, add_a_d8, rst, /* cX */ + ret_cc, ret, jp_cc_a16, cb_prefix, call_cc_a16,call_a16, adc_a_d8, rst, + ret_cc, pop_rr, jp_cc_a16, ill, call_cc_a16,push_rr, sub_a_d8, rst, /* dX */ + ret_cc, reti, jp_cc_a16, ill, call_cc_a16,ill, sbc_a_d8, rst, + ld_da8_a, pop_rr, ld_dc_a, ill, ill, push_rr, and_a_d8, rst, /* eX */ + add_sp_r8, jp_hl, ld_da16_a, ill, ill, ill, xor_a_d8, rst, + ld_a_da8, pop_rr, ld_a_dc, di, ill, push_rr, or_a_d8, rst, /* fX */ + ld_hl_sp_r8,ld_sp_hl, ld_a_da16, ei, ill, ill, cp_a_d8, rst, +}; +void GB_cpu_run(GB_gameboy_t *gb) +{ + gb->vblank_just_occured = false; + bool interrupt = gb->interrupt_enable & gb->io_registers[GB_IO_IF] & 0x1F; + + if (interrupt) { + gb->halted = false; + } + + if (gb->hdma_on) { + GB_advance_cycles(gb, 4); + return; + } + + bool effecitve_ime = gb->ime; + if (gb->ime_toggle) { + gb->ime = !gb->ime; + gb->ime_toggle = false; + } + + if (effecitve_ime && interrupt) { + uint8_t interrupt_bit = 0; + uint8_t interrupt_queue = gb->interrupt_enable & gb->io_registers[GB_IO_IF] & 0x1F; + while (!(interrupt_queue & 1)) { + interrupt_queue >>= 1; + interrupt_bit++; + } + gb->io_registers[GB_IO_IF] &= ~(1 << interrupt_bit); + gb->ime = false; + nop(gb, 0); + /* Run pseudo instructions rst 40-60*/ + rst(gb, 0x87 + interrupt_bit * 8); + } + else if(!gb->halted && !gb->stopped) { + uint8_t opcode = GB_read_memory(gb, gb->pc++); + if (gb->halt_bug) { + gb->pc--; + gb->halt_bug = false; + } + opcodes[opcode](gb, opcode); + } + else { + GB_advance_cycles(gb, 4); + } +} diff --git a/waterbox/sameboy/z80_cpu.h b/waterbox/sameboy/z80_cpu.h new file mode 100644 index 0000000000..1434ed7b96 --- /dev/null +++ b/waterbox/sameboy/z80_cpu.h @@ -0,0 +1,10 @@ +#ifndef z80_cpu_h +#define z80_cpu_h +#include "gb.h" + +void GB_cpu_disassemble(GB_gameboy_t *gb, uint16_t pc, uint16_t count); +#ifdef GB_INTERNAL +void GB_cpu_run(GB_gameboy_t *gb); +#endif + +#endif /* z80_cpu_h */ diff --git a/waterbox/vb/vb.cpp b/waterbox/vb/vb.cpp index 9087ea46dd..b70042ae89 100644 --- a/waterbox/vb/vb.cpp +++ b/waterbox/vb/vb.cpp @@ -26,10 +26,13 @@ namespace MDFN_IEN_VB { -struct NativeSettings +struct NativeSyncSettings { int InstantReadHack; int DisableParallax; +}; +struct NativeSettings +{ int ThreeDeeMode; int SwapViews; int AnaglyphPreset; @@ -56,14 +59,14 @@ enum }; static const uint32 AnaglyphPreset_Colors[][2] = -{ - {0, 0}, - {0xFF0000, 0x0000FF}, - {0xFF0000, 0x00B7EB}, - {0xFF0000, 0x00FFFF}, - {0xFF0000, 0x00FF00}, - {0x00FF00, 0xFF00FF}, - {0xFFFF00, 0x0000FF}, + { + {0, 0}, + {0xFF0000, 0x0000FF}, + {0xFF0000, 0x00B7EB}, + {0xFF0000, 0x00FFFF}, + {0xFF0000, 0x00FF00}, + {0x00FF00, 0xFF00FF}, + {0xFFFF00, 0x0000FF}, }; static uint32 VB3DMode; @@ -501,7 +504,6 @@ void VB_ExitLoop(void) VB_V810->Exit(); } - /*MDFNGI EmulatedVB = { @@ -552,7 +554,7 @@ void VB_ExitLoop(void) using namespace MDFN_IEN_VB; -EXPORT int Load(const uint8 *rom, int length, const NativeSettings* settings) +EXPORT int Load(const uint8 *rom, int length, const NativeSyncSettings *syncSettings) { const uint64 rom_size = length; V810_Emu_Mode cpu_mode = V810_EMU_MODE_ACCURATE; @@ -660,20 +662,20 @@ EXPORT int Load(const uint8 *rom, int length, const NativeSettings* settings) VB_VSU = new VSU(); VBINPUT_Init(); - VB3DMode = settings->ThreeDeeMode; - uint32 prescale = settings->InterlacePrescale; - uint32 sbs_separation = settings->SideBySideSeparation; - bool reverse = settings->SwapViews; + VB3DMode = 0; + uint32 prescale = 1; + uint32 sbs_separation = 0; + bool reverse = false; VIP_Set3DMode(VB3DMode, reverse, prescale, sbs_separation); - VIP_SetParallaxDisable(settings->DisableParallax); + VIP_SetParallaxDisable(syncSettings->DisableParallax); { - auto presetColor = settings->AnaglyphPreset; + auto presetColor = 1; - uint32 lcolor = settings->AnaglyphCustomLeftColor; - uint32 rcolor = settings->AnaglyphCustomRightColor; + uint32 lcolor = 0xff0000; + uint32 rcolor = 0x00ff00; if (presetColor != ANAGLYPH_PRESET_DISABLED) { @@ -681,12 +683,12 @@ EXPORT int Load(const uint8 *rom, int length, const NativeSettings* settings) rcolor = AnaglyphPreset_Colors[presetColor][1]; } VIP_SetAnaglyphColors(lcolor, rcolor); - VIP_SetDefaultColor(settings->NonAnaglyphColor); + VIP_SetDefaultColor(0xffffff); } - VBINPUT_SetInstantReadHack(settings->InstantReadHack); + VBINPUT_SetInstantReadHack(syncSettings->InstantReadHack); - VIP_SetLEDOnScale(settings->LedOnScale / 1000.0); + VIP_SetLEDOnScale(1750 / 1000.0); VB_Power(); @@ -731,7 +733,34 @@ EXPORT int Load(const uint8 *rom, int length, const NativeSettings* settings) return 1; } -EXPORT void GetMemoryAreas(MemoryArea* m) +EXPORT void SetSettings(const NativeSettings *settings) +{ + VB3DMode = settings->ThreeDeeMode; + uint32 prescale = settings->InterlacePrescale; + uint32 sbs_separation = settings->SideBySideSeparation; + bool reverse = settings->SwapViews; + + VIP_Set3DMode(VB3DMode, reverse, prescale, sbs_separation); + + { + auto presetColor = settings->AnaglyphPreset; + + uint32 lcolor = settings->AnaglyphCustomLeftColor; + uint32 rcolor = settings->AnaglyphCustomRightColor; + + if (presetColor != ANAGLYPH_PRESET_DISABLED) + { + lcolor = AnaglyphPreset_Colors[presetColor][0]; + rcolor = AnaglyphPreset_Colors[presetColor][1]; + } + VIP_SetAnaglyphColors(lcolor, rcolor); + VIP_SetDefaultColor(settings->NonAnaglyphColor); + } + + VIP_SetLEDOnScale(settings->LedOnScale / 1000.0); +} + +EXPORT void GetMemoryAreas(MemoryArea *m) { m[0].Data = WRAM; m[0].Name = "WRAM"; @@ -749,7 +778,7 @@ EXPORT void GetMemoryAreas(MemoryArea* m) m[2].Flags = MEMORYAREA_FLAGS_WORDSIZE4; } -EXPORT void FrameAdvance(MyFrameInfo* frame) +EXPORT void FrameAdvance(MyFrameInfo *frame) { v810_timestamp_t v810_timestamp; lagged = true; @@ -779,7 +808,7 @@ EXPORT void FrameAdvance(MyFrameInfo* frame) VB_V810->ResetTS(0); } -EXPORT void PredictFrameSize(MyFrameInfo* frame) +EXPORT void PredictFrameSize(MyFrameInfo *frame) { VIP_CalcFrameSize(frame); } diff --git a/waterbox/vb/vip.cpp b/waterbox/vb/vip.cpp index abb7635b53..9810130362 100644 --- a/waterbox/vb/vip.cpp +++ b/waterbox/vb/vip.cpp @@ -21,6 +21,7 @@ #include "vb.h" #include +#include "../emulibc/emulibc.h" #define VIP_DBGMSG(format, ...) \ { \ @@ -67,8 +68,8 @@ static uint32 ColorLUT[2][256]; static int32 BrightnessCache[4]; static uint32 BrightCLUT[2][4]; -static float ColorLUTNoGC[2][256][3]; -static uint32 AnaSlowColorLUT[256][256]; +static float ECL_INVISIBLE ColorLUTNoGC[2][256][3]; +static uint32 ECL_INVISIBLE AnaSlowColorLUT[256][256]; static bool VidSettingsDirty; static bool ParallaxDisabled;