From 6bf2fd17c393e857d8d77350f13a5d446e9b7c7d Mon Sep 17 00:00:00 2001 From: alyosha-tas Date: Mon, 22 May 2017 11:36:18 -0400 Subject: [PATCH 1/9] add 7800 db entry not linked up yet --- Assets/gamedb/gamedb_a7800.txt | 156 +++++++++++++++++++++++++++++++++ 1 file changed, 156 insertions(+) create mode 100644 Assets/gamedb/gamedb_a7800.txt diff --git a/Assets/gamedb/gamedb_a7800.txt b/Assets/gamedb/gamedb_a7800.txt new file mode 100644 index 0000000000..5515b75bdc --- /dev/null +++ b/Assets/gamedb/gamedb_a7800.txt @@ -0,0 +1,156 @@ +;;NOTE: These hashes were generated using trimmed ROM headers +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: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: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: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: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: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 +md5:408dca9fc40e2b5d805f403fa0509436 Dig Dug A78 PAL=true;board=0 +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: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 +md5:fb8d803b328b2e442548f7799cfa9a4a Galaga A78 NTSC=true;board=0 +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: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: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: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: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: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: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:66ecaafe1b82ae68ffc96267aaf7a4d7 Robotron 2084 A78 NTSC=true;board=0 +md5:ae85689b21bdf85cb9dc57c3b1fec9db Santa Simon A78 NTSC=true;board=A7848 +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:a84c1b2300fbfbf21b1c02387f613dad Space Duel A78 PAL=true;board=0 +md5:771cb4609347657f63e6f0eb26036e35 Space Duel A78 NTSC=true;board=A7832 +md5:6adf79558a3d7f5beca1bb8d34337417 Space Invaders A78 NTSC=true;board=0 +md5:cbb0746192540a13b4c7775c7ce2021f Summer Games A78 NTSC=true;board=A78SGR +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: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: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 From 3a020a1c406236c619fa0ab3b307658864ed0993 Mon Sep 17 00:00:00 2001 From: alyosha-tas Date: Wed, 24 May 2017 19:35:39 -0400 Subject: [PATCH 2/9] Create Readme.txt --- BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/Readme.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/Readme.txt diff --git a/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/Readme.txt b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/Readme.txt new file mode 100644 index 0000000000..84fa199c5f --- /dev/null +++ b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/Readme.txt @@ -0,0 +1 @@ +todo: From b2eecd7bec16a48a377a26490f6bc284493235f7 Mon Sep 17 00:00:00 2001 From: alyosha-tas Date: Wed, 24 May 2017 19:36:34 -0400 Subject: [PATCH 3/9] Add files via upload --- .../Atari/A7800Hawk/A7800Hawk.IDebuggable.cs | 79 ++++ .../Atari/A7800Hawk/A7800Hawk.IEmulator.cs | 51 +++ .../A7800Hawk/A7800Hawk.IInputPollable.cs | 24 + .../A7800Hawk/A7800Hawk.IMemoryDomains.cs | 84 ++++ .../Atari/A7800Hawk/A7800Hawk.ISaveRam.cs | 26 ++ .../Atari/A7800Hawk/A7800Hawk.IStatable.cs | 59 +++ .../Consoles/Atari/A7800Hawk/A7800Hawk.cs | 298 +++++++++++++ .../Atari/A7800Hawk/A7800HawkControl.cs | 409 ++++++++++++++++++ .../Consoles/Atari/A7800Hawk/M6532.cs | 225 ++++++++++ .../Consoles/Atari/A7800Hawk/Maria.cs | 39 ++ 10 files changed, 1294 insertions(+) create mode 100644 BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.IDebuggable.cs create mode 100644 BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.IEmulator.cs create mode 100644 BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.IInputPollable.cs create mode 100644 BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.IMemoryDomains.cs create mode 100644 BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.ISaveRam.cs create mode 100644 BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.IStatable.cs create mode 100644 BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.cs create mode 100644 BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800HawkControl.cs create mode 100644 BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/M6532.cs create mode 100644 BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/Maria.cs diff --git a/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.IDebuggable.cs b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.IDebuggable.cs new file mode 100644 index 0000000000..45809e725e --- /dev/null +++ b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.IDebuggable.cs @@ -0,0 +1,79 @@ +using System; +using System.Collections.Generic; + +using BizHawk.Emulation.Common; + +namespace BizHawk.Emulation.Cores.Atari.A7800Hawk +{ + public partial class A7800Hawk : IDebuggable + { + public IDictionary GetCpuFlagsAndRegisters() + { + return new Dictionary + { + ["A"] = cpu.A, + ["X"] = cpu.X, + ["Y"] = cpu.Y, + ["S"] = cpu.S, + ["PC"] = cpu.PC, + ["Flag C"] = cpu.FlagC, + ["Flag Z"] = cpu.FlagZ, + ["Flag I"] = cpu.FlagI, + ["Flag D"] = cpu.FlagD, + ["Flag B"] = cpu.FlagB, + ["Flag V"] = cpu.FlagV, + ["Flag N"] = cpu.FlagN, + ["Flag T"] = cpu.FlagT + }; + } + + public void SetCpuRegister(string register, int value) + { + switch (register) + { + default: + throw new InvalidOperationException(); + case "A": + cpu.A = (byte)value; + break; + case "X": + cpu.X = (byte)value; + break; + case "Y": + cpu.Y = (byte)value; + break; + case "S": + cpu.S = (byte)value; + break; + case "PC": + cpu.PC = (ushort)value; + break; + case "Flag I": + cpu.FlagI = value > 0; + break; + } + } + + public IMemoryCallbackSystem MemoryCallbacks + { + [FeatureNotImplemented] + get { throw new NotImplementedException(); } + } + + public bool CanStep(StepType type) + { + return false; + } + + [FeatureNotImplemented] + public void Step(StepType type) + { + throw new NotImplementedException(); + } + + public int TotalExecutedCycles + { + get { return cpu.TotalExecutedCycles; } + } + } +} diff --git a/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.IEmulator.cs b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.IEmulator.cs new file mode 100644 index 0000000000..5beafd7006 --- /dev/null +++ b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.IEmulator.cs @@ -0,0 +1,51 @@ +using BizHawk.Emulation.Common; + +namespace BizHawk.Emulation.Cores.Atari.A7800Hawk +{ + public partial class A7800Hawk : IEmulator + { + public IEmulatorServiceProvider ServiceProvider { get; } + + public ControllerDefinition ControllerDefinition { get; private set; } + + public void FrameAdvance(IController controller, bool render, bool rendersound) + { + _frame++; + + if (controller.IsPressed("Power")) + { + // it seems that theMachine.Reset() doesn't clear ram, etc + // this should leave hsram intact but clear most other things + HardReset(); + } + + if (_islag) + { + _lagcount++; + } + + } + + public int Frame => _frame; + + public string SystemId => "A7800"; + + public bool DeterministicEmulation { get; set; } + + public void ResetCounters() + { + _frame = 0; + _lagcount = 0; + _islag = false; + } + + public CoreComm CoreComm { get; } + + public void Dispose() + { + maria = null; + tia = null; + + } + } +} diff --git a/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.IInputPollable.cs b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.IInputPollable.cs new file mode 100644 index 0000000000..f2c5b97360 --- /dev/null +++ b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.IInputPollable.cs @@ -0,0 +1,24 @@ +using BizHawk.Emulation.Common; + +namespace BizHawk.Emulation.Cores.Atari.A7800Hawk +{ + public partial class A7800Hawk : IInputPollable + { + public int LagCount + { + get { return _lagcount; } + set { _lagcount = value; } + } + + public bool IsLagFrame + { + get { return _islag; } + set { _islag = value; } + } + + public IInputCallbackSystem InputCallbacks { get; } = new InputCallbackSystem(); + + private bool _islag = true; + private int _lagcount; + } +} diff --git a/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.IMemoryDomains.cs b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.IMemoryDomains.cs new file mode 100644 index 0000000000..72735171c0 --- /dev/null +++ b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.IMemoryDomains.cs @@ -0,0 +1,84 @@ +using System; +using System.Collections.Generic; + +using BizHawk.Emulation.Common; + +namespace BizHawk.Emulation.Cores.Atari.A7800Hawk +{ + public partial class A7800Hawk + { + private IMemoryDomains MemoryDomains; + + public void SetupMemoryDomains() + { + var domains = new List + { + new MemoryDomainDelegate( + "Main RAM", + RAM.Length, + MemoryDomain.Endian.Little, + addr => RAM[addr], + (addr, value) => RAM[addr] = value, + 1), + new MemoryDomainDelegate( + "TIA Registers", + TIA_regs.Length, + MemoryDomain.Endian.Little, + addr => TIA_regs[addr], + (addr, value) => TIA_regs[addr] = value, + 1), + new MemoryDomainDelegate( + "Maria Registers", + Maria_regs.Length, + MemoryDomain.Endian.Little, + addr => Maria_regs[addr], + (addr, value) => Maria_regs[addr] = value, + 1), + new MemoryDomainDelegate( + "6532 Registers", + regs_6532.Length, + MemoryDomain.Endian.Little, + addr => regs_6532[addr], + (addr, value) => regs_6532[addr] = value, + 1), + new MemoryDomainDelegate( + "Ram Block 0", + 0xB, + MemoryDomain.Endian.Little, + addr => RAM[addr-0x840], + (addr, value) => RAM[addr-0x840] = value, + 1 + ), + new MemoryDomainDelegate( + "Ram Block 1", + 0xB, + MemoryDomain.Endian.Little, + addr => RAM[addr-0x940], + (addr, value) => RAM[addr-0x940] = value, + 1 + ), + new MemoryDomainDelegate( + "System Bus", + 0X10000, + MemoryDomain.Endian.Little, + addr => PeekSystemBus(addr), + (addr, value) => PokeSystemBus(addr, value), + 1 + ) + }; + + MemoryDomains = new MemoryDomainList(domains); + (ServiceProvider as BasicServiceProvider).Register(MemoryDomains); + } + + private byte PeekSystemBus(long addr) + { + return 0; + } + + private void PokeSystemBus(long addr, byte value) + { + + } + } +} diff --git a/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.ISaveRam.cs b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.ISaveRam.cs new file mode 100644 index 0000000000..b3a08cde2b --- /dev/null +++ b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.ISaveRam.cs @@ -0,0 +1,26 @@ +using System; +using BizHawk.Emulation.Common; + +namespace BizHawk.Emulation.Cores.Atari.A7800Hawk +{ + public partial class A7800Hawk : ISaveRam + { + public byte[] CloneSaveRam() + { + return (byte[])_hsram.Clone(); + } + + public void StoreSaveRam(byte[] data) + { + Buffer.BlockCopy(data, 0, _hsram, 0, data.Length); + } + + public bool SaveRamModified + { + get + { + return false; + } + } + } +} diff --git a/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.IStatable.cs b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.IStatable.cs new file mode 100644 index 0000000000..96356abb5b --- /dev/null +++ b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.IStatable.cs @@ -0,0 +1,59 @@ +using System.IO; + +using BizHawk.Common; +using BizHawk.Emulation.Common; + +namespace BizHawk.Emulation.Cores.Atari.A7800Hawk +{ + public partial class A7800Hawk : IStatable + { + public bool BinarySaveStatesPreferred => true; + + public void SaveStateText(TextWriter writer) + { + SyncState(new Serializer(writer)); + } + + public void LoadStateText(TextReader reader) + { + SyncState(new Serializer(reader)); + } + + public void SaveStateBinary(BinaryWriter bw) + { + SyncState(new Serializer(bw)); + } + + public void LoadStateBinary(BinaryReader br) + { + SyncState(new Serializer(br)); + } + + public byte[] SaveStateBinary() + { + MemoryStream ms = new MemoryStream(); + BinaryWriter bw = new BinaryWriter(ms); + SaveStateBinary(bw); + bw.Flush(); + return ms.ToArray(); + } + + private void SyncState(Serializer ser) + { + byte[] core = null; + if (ser.IsWriter) + { + var ms = new MemoryStream(); + ms.Close(); + core = ms.ToArray(); + } + + ser.BeginSection("Atari7800"); + ser.Sync("core", ref core, false); + ser.Sync("Lag", ref _lagcount); + ser.Sync("Frame", ref _frame); + ser.Sync("IsLag", ref _islag); + ser.EndSection(); + } + } +} diff --git a/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.cs b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.cs new file mode 100644 index 0000000000..255f3ea4bd --- /dev/null +++ b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.cs @@ -0,0 +1,298 @@ +using System; + +using BizHawk.Common.BufferExtensions; +using BizHawk.Emulation.Common; +using BizHawk.Emulation.Cores.Components.M6502; + +namespace BizHawk.Emulation.Cores.Atari.A7800Hawk +{ + [CoreAttributes( + "A7800Hawk", + "", + isPorted: false, + isReleased: true)] + [ServiceNotApplicable(typeof(ISettable<,>), typeof(IDriveLight))] + public partial class A7800Hawk : IEmulator, ISaveRam, IDebuggable, IStatable, IInputPollable, IRegionable + { + // memory domains + public byte[] TIA_regs = new byte[0x20]; + public byte[] Maria_regs = new byte[0x20]; + public byte[] RAM = new byte[0x1000]; + public byte[] regs_6532 = new byte[0x80]; + + private readonly byte[] _rom; + private readonly byte[] _hsbios; + private readonly byte[] _bios; + private readonly byte[] _hsram = new byte[2048]; + + private int _frame = 0; + + public MOS6502X cpu; + public Maria maria; + private bool _isPAL; + public M6532 m6532; + public TIA tia; + + public A7800Hawk(CoreComm comm, GameInfo game, byte[] rom, string gameDbFn) + { + var ser = new BasicServiceProvider(this); + ser.Register(maria); + ser.Register(tia); + ServiceProvider = ser; + + CoreComm = comm; + 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."); + + if (rom.Length % 1024 == 128) + { + Console.WriteLine("Trimming 128 byte .a78 header..."); + byte[] newrom = new byte[rom.Length - 128]; + Buffer.BlockCopy(rom, 128, newrom, 0, newrom.Length); + rom = newrom; + } + + _isPAL = false; + + // look up hash in gamedb to see what mapper to use + // if none found default is zero + // also check for PAL region + string hash_md5 = null; + string s_mapper = null; + hash_md5 = "md5:" + rom.HashMD5(0, rom.Length); + + var gi = Database.CheckDatabase(hash_md5); + + if (gi != null) + { + var dict = gi.GetOptionsDict(); + if (!dict.ContainsKey("PAL")) + { + _isPAL = true; + } + if (!dict.ContainsKey("board")) + { + s_mapper = dict["board"]; + } + else + throw new Exception("No Board selected for this mapper"); + } + else + { + throw new Exception("ROM not in gamedb"); + } + + _rom = rom; + _hsbios = highscoreBios; + _bios = _isPAL ? palBios : ntscBios; + + if (_bios == null) + { + throw new MissingFirmwareException("The BIOS corresponding to the region of the game you loaded is required to run Atari 7800 games."); + } + + // set up palette and frame rate + if (_isPAL) + { + maria._frameHz = 50; + maria._palette = PALPalette; + } + else + { + maria._frameHz = 60; + maria._palette = NTSCPalette; + } + + + HardReset(); + } + + public DisplayType Region => _isPAL ? DisplayType.PAL : DisplayType.NTSC; + + public A7800HawkControl ControlAdapter { get; private set; } + + private void HardReset() + { + + + cpu.Reset(); + } + + /* + * MariaTables.cs + * + * Palette tables for the Maria class. + * All derived from Dan Boris' 7800/MAME code. + * + * Copyright © 2004 Mike Murphy + * + */ + + public static readonly int[] NTSCPalette = + { + 0x000000, 0x1c1c1c, 0x393939, 0x595959, // Grey + 0x797979, 0x929292, 0xababab, 0xbcbcbc, + 0xcdcdcd, 0xd9d9d9, 0xe6e6e6, 0xececec, + 0xf2f2f2, 0xf8f8f8, 0xffffff, 0xffffff, + + 0x391701, 0x5e2304, 0x833008, 0xa54716, // Gold + 0xc85f24, 0xe37820, 0xff911d, 0xffab1d, + 0xffc51d, 0xffce34, 0xffd84c, 0xffe651, + 0xfff456, 0xfff977, 0xffff98, 0xffff98, + + 0x451904, 0x721e11, 0x9f241e, 0xb33a20, // Orange + 0xc85122, 0xe36920, 0xff811e, 0xff8c25, + 0xff982c, 0xffae38, 0xffc545, 0xffc559, + 0xffc66d, 0xffd587, 0xffe4a1, 0xffe4a1, + + 0x4a1704, 0x7e1a0d, 0xb21d17, 0xc82119, // Red Orange + 0xdf251c, 0xec3b38, 0xfa5255, 0xfc6161, + 0xff706e, 0xff7f7e, 0xff8f8f, 0xff9d9e, + 0xffabad, 0xffb9bd, 0xffc7ce, 0xffc7ce, + + 0x050568, 0x3b136d, 0x712272, 0x8b2a8c, // Pink + 0xa532a6, 0xb938ba, 0xcd3ecf, 0xdb47dd, + 0xea51eb, 0xf45ff5, 0xfe6dff, 0xfe7afd, + 0xff87fb, 0xff95fd, 0xffa4ff, 0xffa4ff, + + 0x280479, 0x400984, 0x590f90, 0x70249d, // Purple + 0x8839aa, 0xa441c3, 0xc04adc, 0xd054ed, + 0xe05eff, 0xe96dff, 0xf27cff, 0xf88aff, + 0xff98ff, 0xfea1ff, 0xfeabff, 0xfeabff, + + 0x35088a, 0x420aad, 0x500cd0, 0x6428d0, // Purple Blue + 0x7945d0, 0x8d4bd4, 0xa251d9, 0xb058ec, + 0xbe60ff, 0xc56bff, 0xcc77ff, 0xd183ff, + 0xd790ff, 0xdb9dff, 0xdfaaff, 0xdfaaff, + + 0x051e81, 0x0626a5, 0x082fca, 0x263dd4, // Blue1 + 0x444cde, 0x4f5aee, 0x5a68ff, 0x6575ff, + 0x7183ff, 0x8091ff, 0x90a0ff, 0x97a9ff, + 0x9fb2ff, 0xafbeff, 0xc0cbff, 0xc0cbff, + + 0x0c048b, 0x2218a0, 0x382db5, 0x483ec7, // Blue2 + 0x584fda, 0x6159ec, 0x6b64ff, 0x7a74ff, + 0x8a84ff, 0x918eff, 0x9998ff, 0xa5a3ff, + 0xb1aeff, 0xb8b8ff, 0xc0c2ff, 0xc0c2ff, + + 0x1d295a, 0x1d3876, 0x1d4892, 0x1c5cac, // Light Blue + 0x1c71c6, 0x3286cf, 0x489bd9, 0x4ea8ec, + 0x55b6ff, 0x70c7ff, 0x8cd8ff, 0x93dbff, + 0x9bdfff, 0xafe4ff, 0xc3e9ff, 0xc3e9ff, + + 0x2f4302, 0x395202, 0x446103, 0x417a12, // Turquoise + 0x3e9421, 0x4a9f2e, 0x57ab3b, 0x5cbd55, + 0x61d070, 0x69e27a, 0x72f584, 0x7cfa8d, + 0x87ff97, 0x9affa6, 0xadffb6, 0xadffb6, + + 0x0a4108, 0x0d540a, 0x10680d, 0x137d0f, // Green Blue + 0x169212, 0x19a514, 0x1cb917, 0x1ec919, + 0x21d91b, 0x47e42d, 0x6ef040, 0x78f74d, + 0x83ff5b, 0x9aff7a, 0xb2ff9a, 0xb2ff9a, + + 0x04410b, 0x05530e, 0x066611, 0x077714, // Green + 0x088817, 0x099b1a, 0x0baf1d, 0x48c41f, + 0x86d922, 0x8fe924, 0x99f927, 0xa8fc41, + 0xb7ff5b, 0xc9ff6e, 0xdcff81, 0xdcff81, + + 0x02350f, 0x073f15, 0x0c4a1c, 0x2d5f1e, // Yellow Green + 0x4f7420, 0x598324, 0x649228, 0x82a12e, + 0xa1b034, 0xa9c13a, 0xb2d241, 0xc4d945, + 0xd6e149, 0xe4f04e, 0xf2ff53, 0xf2ff53, + + 0x263001, 0x243803, 0x234005, 0x51541b, // Orange Green + 0x806931, 0x978135, 0xaf993a, 0xc2a73e, + 0xd5b543, 0xdbc03d, 0xe1cb38, 0xe2d836, + 0xe3e534, 0xeff258, 0xfbff7d, 0xfbff7d, + + 0x401a02, 0x581f05, 0x702408, 0x8d3a13, // Light Orange + 0xab511f, 0xb56427, 0xbf7730, 0xd0853a, + 0xe19344, 0xeda04e, 0xf9ad58, 0xfcb75c, + 0xffc160, 0xffc671, 0xffcb83, 0xffcb83 + }; + + public static readonly int[] PALPalette = + { + 0x000000, 0x1c1c1c, 0x393939, 0x595959, // Grey + 0x797979, 0x929292, 0xababab, 0xbcbcbc, + 0xcdcdcd, 0xd9d9d9, 0xe6e6e6, 0xececec, + 0xf2f2f2, 0xf8f8f8, 0xffffff, 0xffffff, + + 0x263001, 0x243803, 0x234005, 0x51541b, // Orange Green + 0x806931, 0x978135, 0xaf993a, 0xc2a73e, + 0xd5b543, 0xdbc03d, 0xe1cb38, 0xe2d836, + 0xe3e534, 0xeff258, 0xfbff7d, 0xfbff7d, + + 0x263001, 0x243803, 0x234005, 0x51541b, // Orange Green + 0x806931, 0x978135, 0xaf993a, 0xc2a73e, + 0xd5b543, 0xdbc03d, 0xe1cb38, 0xe2d836, + 0xe3e534, 0xeff258, 0xfbff7d, 0xfbff7d, + + 0x401a02, 0x581f05, 0x702408, 0x8d3a13, // Light Orange + 0xab511f, 0xb56427, 0xbf7730, 0xd0853a, + 0xe19344, 0xeda04e, 0xf9ad58, 0xfcb75c, + 0xffc160, 0xffc671, 0xffcb83, 0xffcb83, + + 0x391701, 0x5e2304, 0x833008, 0xa54716, // Gold + 0xc85f24, 0xe37820, 0xff911d, 0xffab1d, + 0xffc51d, 0xffce34, 0xffd84c, 0xffe651, + 0xfff456, 0xfff977, 0xffff98, 0xffff98, + + 0x451904, 0x721e11, 0x9f241e, 0xb33a20, // Orange + 0xc85122, 0xe36920, 0xff811e, 0xff8c25, + 0xff982c, 0xffae38, 0xffc545, 0xffc559, + 0xffc66d, 0xffd587, 0xffe4a1, 0xffe4a1, + + 0x4a1704, 0x7e1a0d, 0xb21d17, 0xc82119, // Red Orange + 0xdf251c, 0xec3b38, 0xfa5255, 0xfc6161, + 0xff706e, 0xff7f7e, 0xff8f8f, 0xff9d9e, + 0xffabad, 0xffb9bd, 0xffc7ce, 0xffc7ce, + + 0x050568, 0x3b136d, 0x712272, 0x8b2a8c, // Pink + 0xa532a6, 0xb938ba, 0xcd3ecf, 0xdb47dd, + 0xea51eb, 0xf45ff5, 0xfe6dff, 0xfe7afd, + 0xff87fb, 0xff95fd, 0xffa4ff, 0xffa4ff, + + 0x280479, 0x400984, 0x590f90, 0x70249d, // Purple + 0x8839aa, 0xa441c3, 0xc04adc, 0xd054ed, + 0xe05eff, 0xe96dff, 0xf27cff, 0xf88aff, + 0xff98ff, 0xfea1ff, 0xfeabff, 0xfeabff, + + 0x051e81, 0x0626a5, 0x082fca, 0x263dd4, // Blue1 + 0x444cde, 0x4f5aee, 0x5a68ff, 0x6575ff, + 0x7183ff, 0x8091ff, 0x90a0ff, 0x97a9ff, + 0x9fb2ff, 0xafbeff, 0xc0cbff, 0xc0cbff, + + 0x0c048b, 0x2218a0, 0x382db5, 0x483ec7, // Blue2 + 0x584fda, 0x6159ec, 0x6b64ff, 0x7a74ff, + 0x8a84ff, 0x918eff, 0x9998ff, 0xa5a3ff, + 0xb1aeff, 0xb8b8ff, 0xc0c2ff, 0xc0c2ff, + + 0x1d295a, 0x1d3876, 0x1d4892, 0x1c5cac, // Light Blue + 0x1c71c6, 0x3286cf, 0x489bd9, 0x4ea8ec, + 0x55b6ff, 0x70c7ff, 0x8cd8ff, 0x93dbff, + 0x9bdfff, 0xafe4ff, 0xc3e9ff, 0xc3e9ff, + + 0x2f4302, 0x395202, 0x446103, 0x417a12, // Turquoise + 0x3e9421, 0x4a9f2e, 0x57ab3b, 0x5cbd55, + 0x61d070, 0x69e27a, 0x72f584, 0x7cfa8d, + 0x87ff97, 0x9affa6, 0xadffb6, 0xadffb6, + + 0x0a4108, 0x0d540a, 0x10680d, 0x137d0f, // Green Blue + 0x169212, 0x19a514, 0x1cb917, 0x1ec919, + 0x21d91b, 0x47e42d, 0x6ef040, 0x78f74d, + 0x83ff5b, 0x9aff7a, 0xb2ff9a, 0xb2ff9a, + + 0x04410b, 0x05530e, 0x066611, 0x077714, // Green + 0x088817, 0x099b1a, 0x0baf1d, 0x48c41f, + 0x86d922, 0x8fe924, 0x99f927, 0xa8fc41, + 0xb7ff5b, 0xc9ff6e, 0xdcff81, 0xdcff81, + + 0x02350f, 0x073f15, 0x0c4a1c, 0x2d5f1e, // Yellow Green + 0x4f7420, 0x598324, 0x649228, 0x82a12e, + 0xa1b034, 0xa9c13a, 0xb2d241, 0xc4d945, + 0xd6e149, 0xe4f04e, 0xf2ff53, 0xf2ff53 + }; + } +} diff --git a/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800HawkControl.cs b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800HawkControl.cs new file mode 100644 index 0000000000..ddb0815b14 --- /dev/null +++ b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800HawkControl.cs @@ -0,0 +1,409 @@ +using System; + +using EMU7800.Core; +using BizHawk.Emulation.Common; + +namespace BizHawk.Emulation.Cores.Atari.A7800Hawk +{ + public class A7800HawkControl + { + private static readonly ControllerDefinition Joystick = new ControllerDefinition + { + Name = "Atari 7800 Joystick Controller", + BoolButtons = + { + // hard reset, not passed to EMU7800 + "Power", + + // on the console + "Reset", + "Select", + "BW", // should be "Color"?? + "Left Difficulty", // better not put P# on these as they might not correspond to player numbers + "Right Difficulty", + + // ports + "P1 Up", "P1 Down", "P1 Left", "P1 Right", "P1 Trigger", + "P2 Up", "P2 Down", "P2 Left", "P2 Right", "P2 Trigger" + } + }; + + private static readonly ControllerDefinition Paddles = new ControllerDefinition + { + Name = "Atari 7800 Paddle Controller", + BoolButtons = + { + // hard reset, not passed to EMU7800 + "Power", + + // on the console + "Reset", + "Select", + "BW", // should be "Color"?? + "Left Difficulty", // better not put P# on these as they might not correspond to player numbers + "Right Difficulty", + + // ports + "P1 Trigger", + "P2 Trigger", + "P3 Trigger", + "P4 Trigger" + }, + FloatControls = // should be in [0..700000] + { + "P1 Paddle", + "P2 Paddle", + "P3 Paddle", + "P4 Paddle" + }, + FloatRanges = + { + // what is the center point supposed to be here? + new[] { 0.0f, 0.0f, 700000.0f }, + new[] { 0.0f, 0.0f, 700000.0f }, + new[] { 0.0f, 0.0f, 700000.0f }, + new[] { 0.0f, 0.0f, 700000.0f } + } + }; + + private static readonly ControllerDefinition Keypad = new ControllerDefinition + { + Name = "Atari 7800 Keypad Controller", + BoolButtons = + { + // hard reset, not passed to EMU7800 + "Power", + + // on the console + "Reset", + "Select", + "BW", // should be "Color"?? + "Toggle Left Difficulty", // better not put P# on these as they might not correspond to player numbers + "Toggle Right Difficulty", + + // ports + "P1 Keypad1", "P1 Keypad2", "P1 Keypad3", + "P1 Keypad4", "P1 Keypad5", "P1 Keypad6", + "P1 Keypad7", "P1 Keypad8", "P1 Keypad9", + "P1 KeypadA", "P1 Keypad0", "P1 KeypadP", + "P2 Keypad1", "P2 Keypad2", "P2 Keypad3", + "P2 Keypad4", "P2 Keypad5", "P2 Keypad6", + "P2 Keypad7", "P2 Keypad8", "P2 Keypad9", + "P2 KeypadA", "P2 Keypad0", "P2 KeypadP", + "P3 Keypad1", "P3 Keypad2", "P3 Keypad3", + "P3 Keypad4", "P3 Keypad5", "P3 Keypad6", + "P3 Keypad7", "P3 Keypad8", "P3 Keypad9", + "P3 KeypadA", "P3 Keypad0", "P3 KeypadP", + "P4 Keypad1", "P4 Keypad2", "P4 Keypad3", + "P4 Keypad4", "P4 Keypad5", "P4 Keypad6", + "P4 Keypad7", "P4 Keypad8", "P4 Keypad9", + "P4 KeypadA", "P4 Keypad0", "P4 KeypadP" + } + }; + + private static readonly ControllerDefinition Driving = new ControllerDefinition + { + Name = "Atari 7800 Driving Controller", + BoolButtons = + { + // hard reset, not passed to EMU7800 + "Power", + + // on the console + "Reset", + "Select", + "BW", // should be "Color"?? + "Toggle Left Difficulty", // better not put P# on these as they might not correspond to player numbers + "Toggle Right Difficulty", + + // ports + "P1 Trigger", + "P2 Trigger" + }, + FloatControls = // should be in [0..3] + { + "P1 Driving", + "P2 Driving" + }, + FloatRanges = + { + new[] { 0.0f, 0.0f, 3.0f }, + new[] { 0.0f, 0.0f, 3.0f }, + new[] { 0.0f, 0.0f, 3.0f } + } + }; + + private static readonly ControllerDefinition BoosterGrip = new ControllerDefinition + { + Name = "Atari 7800 Booster Grip Controller", + BoolButtons = + { + // hard reset, not passed to EMU7800 + "Power", + + // on the console + "Reset", + "Select", + "BW", // should be "Color"?? + "Toggle Left Difficulty", // better not put P# on these as they might not correspond to player numbers + "Toggle Right Difficulty", + + // ports + // NB: as referenced by the emu, p1t2 = p1t2, p1t3 = p2t2, p2t2 = p3t2, p2t3 = p4t2 + "P1 Up", "P1 Down", "P1 Left", "P1 Right", "P1 Trigger", "P1 Trigger 2", "P1 Trigger 3", + "P2 Up", "P2 Down", "P2 Left", "P2 Right", "P2 Trigger", "P2 Trigger 2", "P2 Trigger 3" + } + }; + + private static readonly ControllerDefinition ProLineJoystick = new ControllerDefinition + { + Name = "Atari 7800 ProLine Joystick Controller", + BoolButtons = + { + // hard reset, not passed to EMU7800 + "Power", + + // on the console + "Reset", + "Select", + "Pause", + "Toggle Left Difficulty", // better not put P# on these as they might not correspond to player numbers + "Toggle Right Difficulty", + + // ports + "P1 Up", "P1 Down", "P1 Left", "P1 Right", "P1 Trigger", "P1 Trigger 2", + "P2 Up", "P2 Down", "P2 Left", "P2 Right", "P2 Trigger", "P2 Trigger 2" + } + }; + + private static readonly ControllerDefinition Lightgun = new ControllerDefinition + { + Name = "Atari 7800 Light Gun Controller", + BoolButtons = + { + // hard reset, not passed to EMU7800 + "Power", + + // on the console + "Reset", + "Select", + "Pause", + "Left Difficulty", // better not put P# on these as they might not correspond to player numbers + "Right Difficulty", + + // ports + "P1 Trigger", + "P2 Trigger" + }, + FloatControls = // vpos should be actual scanline number. hpos should be in [0..319]?? + { + "P1 VPos", "P1 HPos", + "P2 VPos", "P2 HPos" + }, + FloatRanges = + { + // how many scanlines are there again?? + new[] { 0.0f, 0.0f, 240.0f }, + new[] { 0.0f, 0.0f, 319.0f }, + new[] { 0.0f, 0.0f, 240.0f }, + new[] { 0.0f, 0.0f, 319.0f } + } + }; + + private struct ControlAdapter + { + public readonly ControllerDefinition Type; + public readonly Controller Left; + public readonly Controller Right; + public readonly Action Convert; + + public ControlAdapter(ControllerDefinition type, Controller left, Controller right, Action convert) + { + Type = type; + Left = left; + Right = right; + Convert = convert; + } + } + + private static readonly ControlAdapter[] Adapters = + { + new ControlAdapter(Joystick, Controller.Joystick, Controller.Joystick, ConvertJoystick), + new ControlAdapter(Paddles, Controller.Paddles, Controller.Paddles, ConvertPaddles), + new ControlAdapter(Keypad, Controller.Keypad, Controller.Keypad, ConvertKeypad), + new ControlAdapter(Driving, Controller.Driving, Controller.Driving, ConvertDriving), + new ControlAdapter(BoosterGrip, Controller.BoosterGrip, Controller.BoosterGrip, ConvertBoosterGrip), + new ControlAdapter(ProLineJoystick, Controller.ProLineJoystick, Controller.ProLineJoystick, ConvertProLineJoystick), + new ControlAdapter(Lightgun, Controller.Lightgun, Controller.Lightgun, ConvertLightgun), + }; + + private static void ConvertConsoleButtons(IController c, InputState s) + { + s.RaiseInput(0, MachineInput.Reset, c.IsPressed("Reset")); + s.RaiseInput(0, MachineInput.Select, c.IsPressed("Select")); + s.RaiseInput(0, MachineInput.Color, c.IsPressed("BW")); + if (c.IsPressed("Toggle Left Difficulty")) + { + s.RaiseInput(0, MachineInput.LeftDifficulty, c.IsPressed("Toggle Left Difficulty")); + } + + if (c.IsPressed("Toggle Right Difficulty")) + { + s.RaiseInput(0, MachineInput.RightDifficulty, c.IsPressed("Toggle Right Difficulty")); + } + } + + private static void ConvertConsoleButtons7800(IController c, InputState s) + { + s.RaiseInput(0, MachineInput.Reset, c.IsPressed("Reset")); + s.RaiseInput(0, MachineInput.Select, c.IsPressed("Select")); + s.RaiseInput(0, MachineInput.Color, c.IsPressed("Pause")); + if (c.IsPressed("Toggle Left Difficulty")) + { + s.RaiseInput(0, MachineInput.LeftDifficulty, c.IsPressed("Toggle Left Difficulty")); + } + + if (c.IsPressed("Toggle Right Difficulty")) + { + s.RaiseInput(0, MachineInput.RightDifficulty, c.IsPressed("Toggle Right Difficulty")); + } + } + + private static void ConvertDirections(IController c, InputState s, int p) + { + string ps = $"P{p + 1} "; + s.RaiseInput(p, MachineInput.Up, c.IsPressed(ps + "Up")); + s.RaiseInput(p, MachineInput.Down, c.IsPressed(ps + "Down")); + s.RaiseInput(p, MachineInput.Left, c.IsPressed(ps + "Left")); + s.RaiseInput(p, MachineInput.Right, c.IsPressed(ps + "Right")); + } + + private static void ConvertTrigger(IController c, InputState s, int p) + { + string ps = $"P{p + 1} "; + s.RaiseInput(p, MachineInput.Fire, c.IsPressed(ps + "Trigger")); + } + + private static void ConvertJoystick(IController c, InputState s) + { + s.ClearControllerInput(); + ConvertConsoleButtons(c, s); + ConvertDirections(c, s, 0); + ConvertDirections(c, s, 1); + ConvertTrigger(c, s, 0); + ConvertTrigger(c, s, 1); + } + + private static void ConvertPaddles(IController c, InputState s) + { + s.ClearControllerInput(); + ConvertConsoleButtons(c, s); + for (int i = 0; i < 4; i++) + { + string ps = $"P{i + 1} "; + ConvertTrigger(c, s, i); + s.RaisePaddleInput(i, 700000, (int)c.GetFloat(ps + "Trigger")); + } + } + + private static void ConvertKeypad(IController c, InputState s) + { + s.ClearControllerInput(); + ConvertConsoleButtons(c, s); + for (int i = 0; i < 4; i++) + { + string ps = $"P{i + 1} "; + s.RaiseInput(i, MachineInput.NumPad1, c.IsPressed(ps + "Keypad1")); + s.RaiseInput(i, MachineInput.NumPad2, c.IsPressed(ps + "Keypad2")); + s.RaiseInput(i, MachineInput.NumPad3, c.IsPressed(ps + "Keypad3")); + s.RaiseInput(i, MachineInput.NumPad4, c.IsPressed(ps + "Keypad4")); + s.RaiseInput(i, MachineInput.NumPad5, c.IsPressed(ps + "Keypad5")); + s.RaiseInput(i, MachineInput.NumPad6, c.IsPressed(ps + "Keypad6")); + s.RaiseInput(i, MachineInput.NumPad7, c.IsPressed(ps + "Keypad7")); + s.RaiseInput(i, MachineInput.NumPad8, c.IsPressed(ps + "Keypad8")); + s.RaiseInput(i, MachineInput.NumPad9, c.IsPressed(ps + "Keypad9")); + s.RaiseInput(i, MachineInput.NumPadMult, c.IsPressed(ps + "KeypadA")); + s.RaiseInput(i, MachineInput.NumPad0, c.IsPressed(ps + "Keypad0")); + s.RaiseInput(i, MachineInput.NumPadHash, c.IsPressed(ps + "KeypadP")); + } + } + + private static readonly MachineInput[] Drvlut = + { + MachineInput.Driving0, + MachineInput.Driving1, + MachineInput.Driving2, + MachineInput.Driving3 + }; + + private static void ConvertDriving(IController c, InputState s) + { + s.ClearControllerInput(); + ConvertConsoleButtons(c, s); + ConvertTrigger(c, s, 0); + ConvertTrigger(c, s, 1); + s.RaiseInput(0, Drvlut[(int)c.GetFloat("P1 Driving")], true); + s.RaiseInput(1, Drvlut[(int)c.GetFloat("P2 Driving")], true); + } + + private static void ConvertBoosterGrip(IController c, InputState s) + { + s.ClearControllerInput(); + ConvertConsoleButtons(c, s); + ConvertDirections(c, s, 0); + ConvertDirections(c, s, 1); + + // weird mapping is intentional + s.RaiseInput(0, MachineInput.Fire, c.IsPressed("P1 Trigger")); + s.RaiseInput(0, MachineInput.Fire2, c.IsPressed("P1 Trigger 2")); + s.RaiseInput(1, MachineInput.Fire2, c.IsPressed("P1 Trigger 3")); + s.RaiseInput(1, MachineInput.Fire, c.IsPressed("P2 Trigger")); + s.RaiseInput(2, MachineInput.Fire2, c.IsPressed("P2 Trigger 2")); + s.RaiseInput(3, MachineInput.Fire2, c.IsPressed("P2 Trigger 3")); + } + + private static void ConvertProLineJoystick(IController c, InputState s) + { + s.ClearControllerInput(); + ConvertConsoleButtons7800(c, s); + ConvertDirections(c, s, 0); + ConvertDirections(c, s, 1); + s.RaiseInput(0, MachineInput.Fire, c.IsPressed("P1 Trigger")); + s.RaiseInput(0, MachineInput.Fire2, c.IsPressed("P1 Trigger 2")); + s.RaiseInput(1, MachineInput.Fire, c.IsPressed("P2 Trigger")); + s.RaiseInput(1, MachineInput.Fire2, c.IsPressed("P2 Trigger 2")); + } + + private static void ConvertLightgun(IController c, InputState s) + { + s.ClearControllerInput(); + ConvertConsoleButtons7800(c, s); + ConvertTrigger(c, s, 0); + ConvertTrigger(c, s, 1); + s.RaiseLightgunPos(0, (int)c.GetFloat("P1 VPos"), (int)c.GetFloat("P1 HPos")); + s.RaiseLightgunPos(1, (int)c.GetFloat("P2 VPos"), (int)c.GetFloat("P2 HPos")); + } + + public Action Convert { get; private set; } + + public ControllerDefinition ControlType { get; private set; } + + public A7800HawkControl(MachineBase mac) + { + var l = mac.InputState.LeftControllerJack; + var r = mac.InputState.RightControllerJack; + + foreach (var a in Adapters) + { + if (a.Left == l && a.Right == r) + { + Convert = a.Convert; + ControlType = a.Type; + return; + } + } + + throw new Exception($"Couldn't connect Atari 7800 controls \"{l}\" and \"{r}\""); + } + } +} diff --git a/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/M6532.cs b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/M6532.cs new file mode 100644 index 0000000000..58a54af72f --- /dev/null +++ b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/M6532.cs @@ -0,0 +1,225 @@ +using BizHawk.Common; + +namespace BizHawk.Emulation.Cores.Atari.A7800Hawk +{ + // Emulates the M6532 RIOT Chip + public class M6532 + { + private byte _ddRa = 0x00; + private byte _ddRb = 0x00; + private byte _outputA = 0x00; + + public TimerData Timer; + + public M6532() + { + + // arbitrary value to start with. + Timer.Value = 0x73; + Timer.PrescalerShift = 10; + Timer.PrescalerCount = 1 << Timer.PrescalerShift; + } + + public byte ReadMemory(ushort addr, bool peek) + { + if ((addr & 0x0200) == 0) // If not register select, read Ram + { + //return _core.Ram[(ushort)(addr & 0x007f)]; + return 0; + } + + var registerAddr = (ushort)(addr & 0x0007); + if (registerAddr == 0x00) + { + // Read Output reg A + // Combine readings from player 1 and player 2 + // actually depends on setting in SWCHCNTA (aka DDRa) + byte temp = 0;// (byte)(_core.ReadControls1(peek) & 0xF0 | ((_core.ReadControls2(peek) >> 4) & 0x0F)); + temp = (byte)(temp & ~_ddRa); + temp = (byte)(temp + (_outputA & _ddRa)); + return temp; + } + + if (registerAddr == 0x01) + { + // Read DDRA + return _ddRa; + } + + if (registerAddr == 0x02) + { + // Read Output reg B + byte temp = 0;// _core.ReadConsoleSwitches(peek); + temp = (byte)(temp & ~_ddRb); + return temp; + } + + if (registerAddr == 0x03) // Read DDRB + { + return _ddRb; + } + + if ((registerAddr & 0x5) == 0x4) + { + // Bit 0x0080 contains interrupt enable/disable + Timer.InterruptEnabled = (addr & 0x0080) != 0; + + // The interrupt flag will be reset whenever the Timer is access by a read or a write + // However, the reading of the timer at the same time the interrupt occurs will not reset the interrupt flag + // (M6532 Datasheet) + if (!(Timer.PrescalerCount == 0 && Timer.Value == 0)) + { + Timer.InterruptFlag = false; + } + + return Timer.Value; + } + + // TODO: fix this to match real behaviour + // This is an undocumented instruction whose behaviour is more dynamic then indicated here + if ((registerAddr & 0x5) == 0x5) + { + // Read interrupt flag + if (Timer.InterruptFlag) // Timer.InterruptEnabled && ) + { + return 0xC0; + } + + return 0x00; + } + + return 0x3A; + } + + public void WriteMemory(ushort addr, byte value) + { + if ((addr & 0x0200) == 0) // If the RS bit is not set, this is a ram write + { + //_core.Ram[(ushort)(addr & 0x007f)] = value; + } + else + { + // If bit 0x0010 is set, and bit 0x0004 is set, this is a timer write + if ((addr & 0x0014) == 0x0014) + { + var registerAddr = (ushort)(addr & 0x0007); + + // Bit 0x0080 contains interrupt enable/disable + Timer.InterruptEnabled = (addr & 0x0080) != 0; + + // The interrupt flag will be reset whenever the Timer is access by a read or a write + // (M6532 datasheet) + if (registerAddr == 0x04) + { + // Write to Timer/1 + Timer.PrescalerShift = 0; + Timer.Value = value; + Timer.PrescalerCount = 0; // 1 << Timer.PrescalerShift; + Timer.InterruptFlag = false; + } + else if (registerAddr == 0x05) + { + // Write to Timer/8 + Timer.PrescalerShift = 3; + Timer.Value = value; + Timer.PrescalerCount = 0; // 1 << Timer.PrescalerShift; + Timer.InterruptFlag = false; + } + else if (registerAddr == 0x06) + { + // Write to Timer/64 + Timer.PrescalerShift = 6; + Timer.Value = value; + Timer.PrescalerCount = 0; // 1 << Timer.PrescalerShift; + Timer.InterruptFlag = false; + } + else if (registerAddr == 0x07) + { + // Write to Timer/1024 + Timer.PrescalerShift = 10; + Timer.Value = value; + Timer.PrescalerCount = 0; // 1 << Timer.PrescalerShift; + Timer.InterruptFlag = false; + } + } + + // If bit 0x0004 is not set, bit 0x0010 is ignored and + // these are register writes + else if ((addr & 0x0004) == 0) + { + var registerAddr = (ushort)(addr & 0x0007); + + if (registerAddr == 0x00) + { + // Write Output reg A + _outputA = value; + } + else if (registerAddr == 0x01) + { + // Write DDRA + _ddRa = value; + } + else if (registerAddr == 0x02) + { + // Write Output reg B + // But is read only + } + else if (registerAddr == 0x03) + { + // Write DDRB + _ddRb = value; + } + } + } + } + + public void SyncState(Serializer ser) + { + ser.BeginSection("M6532"); + ser.Sync("ddra", ref _ddRa); + ser.Sync("ddrb", ref _ddRb); + ser.Sync("OutputA", ref _outputA); + Timer.SyncState(ser); + ser.EndSection(); + } + + public struct TimerData + { + public int PrescalerCount; + public byte PrescalerShift; + + public byte Value; + + public bool InterruptEnabled; + public bool InterruptFlag; + + public void Tick() + { + if (PrescalerCount == 0) + { + Value--; + PrescalerCount = 1 << PrescalerShift; + } + + PrescalerCount--; + if (PrescalerCount == 0) + { + if (Value == 0) + { + InterruptFlag = true; + PrescalerShift = 0; + } + } + } + + public void SyncState(Serializer ser) + { + ser.Sync("prescalerCount", ref PrescalerCount); + ser.Sync("prescalerShift", ref PrescalerShift); + ser.Sync("value", ref Value); + ser.Sync("interruptEnabled", ref InterruptEnabled); + ser.Sync("interruptFlag", ref InterruptFlag); + } + } + } +} \ No newline at end of file diff --git a/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/Maria.cs b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/Maria.cs new file mode 100644 index 0000000000..41687abf5a --- /dev/null +++ b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/Maria.cs @@ -0,0 +1,39 @@ +using System; + +using BizHawk.Emulation.Common; + +namespace BizHawk.Emulation.Cores.Atari.A7800Hawk +{ + // Emulates the Atari 7800 Maria graphics chip + public class Maria : IVideoProvider + { + public int _frameHz; + + public int[] _vidbuffer; + public int[] _palette; + + public int[] GetVideoBuffer() + { + return _vidbuffer; + } + + public int VirtualWidth => 275; + public int VirtualHeight => BufferHeight; + public int BufferWidth { get; private set; } + public int BufferHeight { get; private set; } + public int BackgroundColor => unchecked((int)0xff000000); + public int VsyncNumerator => _frameHz; + public int VsyncDenominator => 1; + + public void FrameAdvance() + { + + } + + public void Reset() + { + + } + + } +} From f159220bef3cd6577519834dbc87100b638a9a03 Mon Sep 17 00:00:00 2001 From: alyosha-tas Date: Wed, 24 May 2017 19:37:21 -0400 Subject: [PATCH 4/9] Create temp.txt --- .../Consoles/Atari/A7800Hawk/TIA_Sound/temp.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/TIA_Sound/temp.txt diff --git a/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/TIA_Sound/temp.txt b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/TIA_Sound/temp.txt new file mode 100644 index 0000000000..9c595a6fb7 --- /dev/null +++ b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/TIA_Sound/temp.txt @@ -0,0 +1 @@ +temp From a2ab02f9d9051da4770f9eb6c2aa379044e483b8 Mon Sep 17 00:00:00 2001 From: alyosha-tas Date: Wed, 24 May 2017 19:37:44 -0400 Subject: [PATCH 5/9] Add files via upload --- .../Consoles/Atari/A7800Hawk/TIA_Sound/TIA.cs | 334 ++++++++++++++++++ .../Atari/A7800Hawk/TIA_Sound/Tia.Audio.cs | 212 +++++++++++ .../A7800Hawk/TIA_Sound/Tia.ISoundProvider.cs | 65 ++++ .../A7800Hawk/TIA_Sound/Tia.SyncState.cs | 28 ++ 4 files changed, 639 insertions(+) create mode 100644 BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/TIA_Sound/TIA.cs create mode 100644 BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/TIA_Sound/Tia.Audio.cs create mode 100644 BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/TIA_Sound/Tia.ISoundProvider.cs create mode 100644 BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/TIA_Sound/Tia.SyncState.cs diff --git a/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/TIA_Sound/TIA.cs b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/TIA_Sound/TIA.cs new file mode 100644 index 0000000000..4c6ef5f20d --- /dev/null +++ b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/TIA_Sound/TIA.cs @@ -0,0 +1,334 @@ +using System; +using System.Numerics; + +using BizHawk.Emulation.Common; + +namespace BizHawk.Emulation.Cores.Atari.A7800Hawk +{ + // Emulates the TIA + public partial class TIA : ISoundProvider + { + public byte BusState; + + private bool _doTicks; + + private byte _hsyncCnt; + private int _capChargeStart; + private bool _capCharging; + public int AudioClocks; // not savestated + + private readonly Audio[] AUD = { new Audio(), new Audio() }; + + // current audio register state used to sample correct positions in the scanline (clrclk 0 and 114) + ////public byte[] current_audio_register = new byte[6]; + public readonly short[] LocalAudioCycles = new short[2000]; + + public void Reset() + { + _hsyncCnt = 0; + _capChargeStart = 0; + _capCharging = false; + AudioClocks = 0; + + _doTicks = false; + } + + // Execute TIA cycles + public void Execute(int cycles) + { + // do the audio sampling + if (_hsyncCnt == 36 || _hsyncCnt == 148) + { + LocalAudioCycles[AudioClocks] += (short)(AUD[0].Cycle() / 2); + LocalAudioCycles[AudioClocks] += (short)(AUD[1].Cycle() / 2); + AudioClocks++; + } + + } + + public byte ReadMemory(ushort addr, bool peek) + { + var maskedAddr = (ushort)(addr & 0x000F); + byte coll = 0; + int mask = 0; + + if (maskedAddr == 0x00) // CXM0P + { + + } + + if (maskedAddr == 0x01) // CXM1P + { + + } + + if (maskedAddr == 0x02) // CXP0FB + { + + } + + if (maskedAddr == 0x03) // CXP1FB + { + + } + + if (maskedAddr == 0x04) // CXM0FB + { + + } + + if (maskedAddr == 0x05) // CXM1FB + { + + } + + if (maskedAddr == 0x06) // CXBLPF + { + + } + + if (maskedAddr == 0x07) // CXPPMM + { + + } + + // 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 + if (maskedAddr == 0x08) // INPT0 + { + + } + + if (maskedAddr == 0x09) // INPT1 + { + + } + + if (maskedAddr == 0x0A) // INPT2 + { + + } + + if (maskedAddr == 0x0B) // INPT3 + { + + } + + if (maskedAddr == 0x0C) // INPT4 + { + + } + + if (maskedAddr == 0x0D) // INPT5 + { + + } + + // some bits of the databus will be undriven when a read call is made. Our goal here is to sort out what + // happens to the undriven pins. Most of the time, they will be in whatever state they were when previously + // assigned in some other bus access, so let's go with that. + coll += (byte)(mask & BusState); + + if (!peek) + { + BusState = coll; + } + + return coll; + } + + public void WriteMemory(ushort addr, byte value, bool poke) + { + var maskedAddr = (ushort)(addr & 0x3f); + if (!poke) + { + BusState = value; + } + + if (maskedAddr == 0x00) // VSYNC + { + + } + else if (maskedAddr == 0x01) // VBLANK + { + + } + else if (maskedAddr == 0x02) // WSYNC + { + + } + else if (maskedAddr == 0x04) // NUSIZ0 + { + + } + else if (maskedAddr == 0x05) // NUSIZ1 + { + + } + else if (maskedAddr == 0x06) // COLUP0 + { + + } + else if (maskedAddr == 0x07) // COLUP1 + { + + } + else if (maskedAddr == 0x08) // COLUPF + { + + } + else if (maskedAddr == 0x09) // COLUBK + { + + } + else if (maskedAddr == 0x0A) // CTRLPF + { + + } + else if (maskedAddr == 0x0B) // REFP0 + { + + } + else if (maskedAddr == 0x0C) // REFP1 + { + + } + else if (maskedAddr == 0x0D) // PF0 + { + + } + else if (maskedAddr == 0x0E) // PF1 + { + + } + else if (maskedAddr == 0x0F) // PF2 + { + + } + else if (maskedAddr == 0x10) // RESP0 + { + + } + else if (maskedAddr == 0x11) // RESP1 + { + + } + else if (maskedAddr == 0x12) // RESM0 + { + + } + else if (maskedAddr == 0x13) // RESM1 + { + + } + else if (maskedAddr == 0x14) // RESBL + { + + } + else if (maskedAddr == 0x15) // AUDC0 + { + AUD[0].AUDC = (byte)(value & 15); + } + else if (maskedAddr == 0x16) // AUDC1 + { + AUD[1].AUDC = (byte)(value & 15); + } + else if (maskedAddr == 0x17) // AUDF0 + { + AUD[0].AUDF = (byte)((value & 31) + 1); + } + else if (maskedAddr == 0x18) // AUDF1 + { + AUD[1].AUDF = (byte)((value & 31) + 1); + } + else if (maskedAddr == 0x19) // AUDV0 + { + AUD[0].AUDV = (byte)(value & 15); + } + else if (maskedAddr == 0x1A) // AUDV1 + { + AUD[1].AUDV = (byte)(value & 15); + } + else if (maskedAddr == 0x1B) // GRP0 + { + + } + else if (maskedAddr == 0x1C) // GRP1 + { + + } + else if (maskedAddr == 0x1D) // ENAM0 + { + + } + else if (maskedAddr == 0x1E) // ENAM1 + { + + } + else if (maskedAddr == 0x1F) // ENABL + { + + } + else if (maskedAddr == 0x20) // HMP0 + { + + } + else if (maskedAddr == 0x21) // HMP1 + { + + } + else if (maskedAddr == 0x22) // HMM0 + { + + } + else if (maskedAddr == 0x23) // HMM1 + { + + } + else if (maskedAddr == 0x24) // HMBL + { + + } + else if (maskedAddr == 0x25) // VDELP0 + { + + } + else if (maskedAddr == 0x26) // VDELP1 + { + + } + else if (maskedAddr == 0x27) // VDELBL + { + + } + else if (maskedAddr == 0x28) // RESMP0 + { + + } + else if (maskedAddr == 0x29) // RESMP1 + { + + } + else if (maskedAddr == 0x2A) // HMOVE + { + + } + else if (maskedAddr == 0x2B) // HMCLR + { + + } + else if (maskedAddr == 0x2C) // CXCLR + { + + } + } + + private enum AudioRegister : byte + { + AUDC, AUDF, AUDV + } + + private int _frameStartCycles, _frameEndCycles; + } +} \ No newline at end of file diff --git a/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/TIA_Sound/Tia.Audio.cs b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/TIA_Sound/Tia.Audio.cs new file mode 100644 index 0000000000..cf5aa3e0c7 --- /dev/null +++ b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/TIA_Sound/Tia.Audio.cs @@ -0,0 +1,212 @@ +using System; +using BizHawk.Common; + +namespace BizHawk.Emulation.Cores.Atari.A7800Hawk +{ + public partial class TIA + { + public class Audio + { + // noise/division control + public byte AUDC = 0; + + // frequency divider + public byte AUDF = 1; + + // volume + public byte AUDV = 0; + + // 2 state counter + private bool sr1 = true; + + // 4 bit shift register + private int sr4 = 0x0f; + + // 5 bit shift register + private int sr5 = 0x1f; + + // 9 bit shift register + private int sr9 = 0x1ff; + + // 3 state counter + private int sr3 = 2; + + // counter based off AUDF + private byte freqcnt; + + // latched audio value + private bool on = true; + + private bool Run3() + { + sr3++; + if (sr3 == 3) + { + sr3 = 0; + return true; + } + + return false; + } + + private bool Run4() + { + bool ret = (sr4 & 1) != 0; + bool c = ((sr4 & 1) != 0) ^ ((sr4 & 2) != 0); + sr4 = (sr4 >> 1) | (c ? 8 : 0); + return ret; + } + + private bool Run5() + { + bool ret = (sr5 & 1) != 0; + bool c = ((sr5 & 1) != 0) ^ ((sr5 & 4) != 0); + sr5 = (sr5 >> 1) | (c ? 16 : 0); + return ret; + } + + private bool One4() + { + bool ret = (sr4 & 1) != 0; + sr4 = (sr4 >> 1) | 8; + return ret; + } + + private bool One5() + { + bool ret = (sr5 & 1) != 0; + sr5 = (sr5 >> 1) | 16; + return ret; + } + + private bool Run1() + { + sr1 = !sr1; + return !sr1; + } + + private bool Run9() + { + bool ret = (sr9 & 1) != 0; + bool c = ((sr9 & 1) != 0) ^ ((sr9 & 16) != 0); + sr9 = (sr9 >> 1) | (c ? 256 : 0); + return ret; + } + + /// + /// call me approx 31k times a second + /// + /// 16 bit audio sample + public short Cycle() + { + if (++freqcnt >= AUDF) + { + freqcnt = 0; + switch (AUDC) + { + case 0x00: + case 0x0b: + // Both have a 1 s + One5(); + on = One4(); + break; + + case 0x01: + // Both run, but the 5 bit is ignored + on = Run4(); + //Run5(); + break; + case 0x02: + if ((sr5 & 0x0f) == 0 || (sr5 & 0x0f) == 0x0f) + { + on = Run4(); + } + + Run5(); + break; + case 0x03: + if (Run5()) + { + on = Run4(); + } + + break; + + case 0x04: + Run5(); + One4(); + on = Run1(); + break; + + case 0x05: + One5(); + Run4(); + on = Run1(); + break; + + case 0x06: + case 0x0a: + Run5(); + if ((sr5 & 0x0f) == 0) + { + on = false; + } + else if ((sr5 & 0x0f) == 0x0f) + { + on = true; + } + + break; + + case 0x07: + case 0x09: + on = Run5(); + break; + + case 0x08: + on = Run9(); + break; + case 0x0c: + case 0x0d: + if (Run3()) + { + on = Run1(); + } + + break; + case 0x0e: + if (Run3()) + { + goto case 0x06; + } + + break; + case 0x0f: + if (Run3()) + { + goto case 0x07; + } + + break; + } + } + + return (short)(on ? AUDV * 1092 : 0); + } + + public void SyncState(Serializer ser) + { + ser.Sync("AUDC", ref AUDC); + ser.Sync("AUDF", ref AUDF); + ser.Sync("AUDV", ref AUDV); + ser.Sync("sr1", ref sr1); + ser.Sync("sr3", ref sr3); + ser.Sync("sr4", ref sr4); + ser.Sync("sr5", ref sr5); + ser.Sync("sr9", ref sr9); + ser.Sync("freqcnt", ref freqcnt); + ser.Sync("on", ref on); + } + } + } +} 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 new file mode 100644 index 0000000000..3a85b7bbd0 --- /dev/null +++ b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/TIA_Sound/Tia.ISoundProvider.cs @@ -0,0 +1,65 @@ +using System; +using BizHawk.Emulation.Common; + +namespace BizHawk.Emulation.Cores.Atari.A7800Hawk +{ + public partial class TIA : ISoundProvider + { + public bool CanProvideAsync => false; + + public void SetSyncMode(SyncSoundMode mode) + { + if (mode != SyncSoundMode.Sync) + { + throw new InvalidOperationException("Only Sync mode is supported."); + } + } + + public SyncSoundMode SyncMode => SyncSoundMode.Sync; + + public void GetSamplesSync(out short[] samples, out int nsamp) + { + short[] ret = new short[_spf * 2]; + GetSamples(ret); + samples = ret; + nsamp = _spf; + } + + public void GetSamplesAsync(short[] samples) + { + throw new NotSupportedException("Async is not available"); + } + + public void DiscardSamples() + { + 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) + { + if (AudioClocks > 0) + { + var samples31Khz = new short[AudioClocks]; // mono + + for (int i = 0; i < AudioClocks; i++) + { + samples31Khz[i] = LocalAudioCycles[i]; + LocalAudioCycles[i] = 0; + } + + // convert from 31khz to 44khz + for (var i = 0; i < samples.Length / 2; i++) + { + samples[i * 2] = samples31Khz[(int)(((double)samples31Khz.Length / (double)(samples.Length / 2)) * i)]; + samples[(i * 2) + 1] = samples[i * 2]; + } + } + + AudioClocks = 0; + } + } +} 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 new file mode 100644 index 0000000000..100bdf5361 --- /dev/null +++ b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/TIA_Sound/Tia.SyncState.cs @@ -0,0 +1,28 @@ +using BizHawk.Common; + +namespace BizHawk.Emulation.Cores.Atari.A7800Hawk +{ + public partial class TIA + { + public void SyncState(Serializer ser) + { + ser.BeginSection("TIA"); + + ser.Sync("hsyncCnt", ref _hsyncCnt); + + // add everything to the state + ser.Sync("Bus_State", ref BusState); + + ser.Sync("Ticks", ref _doTicks); + + // some of these things weren't in the state because they weren't needed if + // states were always taken at frame boundaries + ser.Sync("capChargeStart", ref _capChargeStart); + ser.Sync("capCharging", ref _capCharging); + ser.Sync("AudioClocks", ref AudioClocks); + ser.Sync("FrameStartCycles", ref _frameStartCycles); + ser.Sync("FrameEndCycles", ref _frameEndCycles); + + } + } +} From 7ce43e143879b1b7d3ad9f6f4eab2b94436b4f1c Mon Sep 17 00:00:00 2001 From: alyosha-tas Date: Wed, 24 May 2017 20:40:02 -0400 Subject: [PATCH 6/9] Add files via upload --- .../Atari/A7800Hawk/A7800Hawk.IEmulator.cs | 4 +- .../Consoles/Atari/A7800Hawk/A7800Hawk.cs | 11 +- .../Consoles/Atari/A7800Hawk/Maria.cs | 5 +- .../Consoles/Atari/A7800Hawk/MemoryMap.cs | 147 ++++++++++++++++++ 4 files changed, 164 insertions(+), 3 deletions(-) create mode 100644 BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/MemoryMap.cs diff --git a/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.IEmulator.cs b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.IEmulator.cs index 5beafd7006..0022c69bed 100644 --- a/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.IEmulator.cs +++ b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.IEmulator.cs @@ -24,6 +24,8 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk _lagcount++; } + maria.FrameAdvance(); + } public int Frame => _frame; @@ -45,7 +47,7 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk { maria = null; tia = null; - + m6532 = null; } } } diff --git a/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.cs b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.cs index 255f3ea4bd..cbef263947 100644 --- a/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.cs +++ b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.cs @@ -14,6 +14,12 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk [ServiceNotApplicable(typeof(ISettable<,>), typeof(IDriveLight))] public partial class A7800Hawk : IEmulator, ISaveRam, IDebuggable, IStatable, IInputPollable, IRegionable { + // this register selects between 2600 and 7800 mode in the A7800 + // however, we already have a 2600 emulator so this core will only be loading A7800 games + // furthermore, the location of the register is in the same place as TIA registers (0x0-0x1F) + // any writes to this location before the register is 'locked' will go to the register and not the TIA + public byte A7800_control_register; + // memory domains public byte[] TIA_regs = new byte[0x20]; public byte[] Maria_regs = new byte[0x20]; @@ -114,9 +120,12 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk private void HardReset() { + A7800_control_register = 0; - + tia.Reset(); cpu.Reset(); + maria.Reset(); + m6532 = new M6532(); } /* diff --git a/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/Maria.cs b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/Maria.cs index 41687abf5a..395fffb671 100644 --- a/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/Maria.cs +++ b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/Maria.cs @@ -25,6 +25,9 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk public int VsyncNumerator => _frameHz; public int VsyncDenominator => 1; + //Maria related variables + public int cycle; + public void FrameAdvance() { @@ -32,7 +35,7 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk public void Reset() { - + cycle = 0; } } diff --git a/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/MemoryMap.cs b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/MemoryMap.cs new file mode 100644 index 0000000000..9bf21bbcb9 --- /dev/null +++ b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/MemoryMap.cs @@ -0,0 +1,147 @@ +using System; + +using BizHawk.Common.BufferExtensions; +using BizHawk.Emulation.Common; +using BizHawk.Emulation.Cores.Components.M6502; + +namespace BizHawk.Emulation.Cores.Atari.A7800Hawk +{ + public partial class A7800Hawk + { + public byte ReadMemory(int addr) + { + addr &= 0xFFFF; + + if (addr < 0x0400) { + if ((addr & 0xFF) < 0x20) + { + // return TIA registers or control register if it is still unlocked + if ((A7800_control_register & 0x1) == 0 && (addr < 0x20)) + { + return 0xFF; // TODO: what to return here? + } + else + { + return TIA_regs[addr]; // TODO: what to return here? + } + } + else if ((addr & 0xFF) < 0x40) + { + return Maria_regs[(addr & 0x3F) - 0x20]; + } + else if (addr < 0x100) + { + // RAM block 0 + return RAM[addr - 0x40 + 0x840]; + } + else if (addr < 0x200) + { + // RAM block 1 + return RAM[addr - 0x140 + 0x940]; + } + else if (addr < 0x300) + { + return regs_6532[addr - 0x240]; + } + else + { + return 0xFF; // what is mapped here? + } + } + else if (addr < 0x480) + { + return 0xFF; // cartridge space available + } + else if (addr < 0x500) + { + // this is where RAM for the 6532 resides for use in 2600 mode + return 0xFF; + } + else if (addr < 0x1800) + { + return 0xFF; // cartridge space available + } + else if (addr < 0x2800) + { + return RAM[addr - 0x1800]; + } + else if (addr < 0x4000) + { + return RAM[addr - 0x2800 + 0x800]; + } + else + { + return 0xFF; // cartridge and other OPSYS + } + } + + public void WriteMemory(int addr, byte value) + { + addr &= 0xFFFF; + + if (addr < 0x0400) + { + if ((addr & 0xFF) < 0x20) + { + // return TIA registers or control register if it is still unlocked + if ((A7800_control_register & 0x1) == 0 && (addr < 0x20)) + { + A7800_control_register = value; // TODO: what to return here? + } + else + { + TIA_regs[addr] = value; // TODO: what to return here? + } + } + else if ((addr & 0xFF) < 0x40) + { + Maria_regs[(addr & 0x3F) - 0x20] = value; + } + else if (addr < 0x100) + { + // RAM block 0 + RAM[addr - 0x40 + 0x840] = value; + } + else if (addr < 0x200) + { + // RAM block 1 + RAM[addr - 0x140 + 0x940] = value; + } + else if (addr < 0x300) + { + regs_6532[addr - 0x240] = value; + } + else + { + // what is mapped here? + } + } + else if (addr < 0x480) + { + // cartridge space available + } + else if (addr < 0x500) + { + // this is where RAM for the 6532 resides for use in 2600 mode + // is it accessible in 7800 mode? + } + else if (addr < 0x1800) + { + // cartridge space available + } + else if (addr < 0x2800) + { + RAM[addr - 0x1800] = value; + } + else if (addr < 0x4000) + { + RAM[addr - 0x2800 + 0x800] = value; + } + else + { + // cartridge and other OPSYS + } + } + + } +} From a1497045ddcfb86913ad10870c27640d3ee5ab02 Mon Sep 17 00:00:00 2001 From: alyosha-tas Date: Wed, 24 May 2017 20:40:38 -0400 Subject: [PATCH 7/9] Add files via upload --- .../BizHawk.Emulation.Cores.csproj | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj b/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj index 8469b45cf4..870f73b4b4 100644 --- a/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj +++ b/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj @@ -354,6 +354,35 @@ + + + A7800Hawk.cs + + + A7800Hawk.cs + + + A7800Hawk.cs + + + A7800Hawk.cs + + + A7800Hawk.cs + + + A7800Hawk.cs + + + A7800Hawk.cs + + + + + + + + Atari7800.cs @@ -1317,6 +1346,7 @@ + From 93c14ce2d132bd79a80784265b0951a577159e55 Mon Sep 17 00:00:00 2001 From: alyosha-tas Date: Thu, 25 May 2017 15:32:38 -0400 Subject: [PATCH 8/9] Add files via upload --- BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj b/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj index 870f73b4b4..7ee8ac2297 100644 --- a/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj +++ b/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj @@ -373,8 +373,8 @@ A7800Hawk.cs - - A7800Hawk.cs + + A7800Hawk.cs @@ -1346,7 +1346,6 @@ - From 827c5848dd53d1ab3fdd3edc20822dbec425a92b Mon Sep 17 00:00:00 2001 From: alyosha-tas Date: Thu, 25 May 2017 15:38:51 -0400 Subject: [PATCH 9/9] Delete temp.txt --- .../Consoles/Atari/A7800Hawk/TIA_Sound/temp.txt | 1 - 1 file changed, 1 deletion(-) delete mode 100644 BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/TIA_Sound/temp.txt diff --git a/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/TIA_Sound/temp.txt b/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/TIA_Sound/temp.txt deleted file mode 100644 index 9c595a6fb7..0000000000 --- a/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/TIA_Sound/temp.txt +++ /dev/null @@ -1 +0,0 @@ -temp