1 //============================================================================
2 //
3 //   SSSS    tt          lll  lll
4 //  SS  SS   tt           ll   ll
5 //  SS     tttttt  eeee   ll   ll   aaaa
6 //   SSSS    tt   ee  ee  ll   ll      aa
7 //      SS   tt   eeeeee  ll   ll   aaaaa  --  "An Atari 2600 VCS Emulator"
8 //  SS  SS   tt   ee      ll   ll  aa  aa
9 //   SSSS     ttt  eeeee llll llll  aaaaa
10 //
11 // Copyright (c) 1995-2021 by Bradford W. Mott, Stephen Anthony
12 // and the Stella Team
13 //
14 // See the file "License.txt" for information on usage and redistribution of
15 // this file, and for a DISCLAIMER OF ALL WARRANTIES.
16 //============================================================================
17 
18 #ifndef COMPUMATE_HXX
19 #define COMPUMATE_HXX
20 
21 class Console;
22 class Event;
23 class System;
24 
25 #include "bspf.hxx"
26 #include "Control.hxx"
27 
28 /**
29   Handler for SpectraVideo CompuMate bankswitched games.
30 
31   The specifics of the CompuMate format can be found in both the Cart side
32   (CartCM) and the Controller side (CMControl).  The CompuMate device is
33   unique for the 2600 in that it requires close co-operation between the
34   cartridge and the left and right controllers.
35 
36   This class acts as a 'parent' for cartridge and both the left and right
37   CMControl's, taking care of their creation and communication between them.
38   It also allows to enable/disable the users actual keyboard when required.
39 
40   @author  Stephen Anthony
41 */
42 class CompuMate
43 {
44   public:
45     /**
46       Create a new CompuMate handler for both left and right ports.
47       Note that this class creates CMControl controllers for both ports,
48       but does not take responsibility for their deletion.
49 
50       @param console  The console that owns the controller
51       @param event    The event object to use for events
52       @param system   The system using this controller
53     */
54     CompuMate(const Console& console, const Event& event, const System& system);
55 
56     /**
57       Return the left and right CompuMate controllers
58     */
leftController()59     unique_ptr<Controller>& leftController()  { return myLeftController;  }
rightController()60     unique_ptr<Controller>& rightController() { return myRightController; }
61 
62 
63     /** Needed for communication with CartCM class */
column()64     uInt8& column() { return myColumn; }
65 
66   private:
67     /**
68       Called by the controller(s) when all pins have been written
69       This method keeps track of consecutive calls, and only updates once
70     */
71     void update();
72 
73     // The actual CompuMate controller
74     // More information about these scheme can be found in CartCM.hxx
75     class CMControl : public Controller
76     {
77       public:
78         /**
79           Create a new CMControl controller plugged into the specified jack
80 
81           @param handler  Class which coordinates between left & right controllers
82           @param jack     The jack the controller is plugged into
83           @param event    The event object to use for events
84           @param system   The system using this controller
85         */
CMControl(class CompuMate & handler,Controller::Jack jack,const Event & event,const System & system)86         CMControl(class CompuMate& handler, Controller::Jack jack, const Event& event,
87                   const System& system)
88           : Controller(jack, event, system, Controller::Type::CompuMate),
89             myHandler{handler} { }
90         ~CMControl() override = default;
91 
92       public:
93         /**
94           Called after *all* digital pins have been written on Port A.
95           Only update on the left controller; the right controller will
96           happen at the same cycle and is redundant.
97         */
controlWrite(uInt8)98         void controlWrite(uInt8) override {
99           if(myJack == Controller::Jack::Left) myHandler.update();
100         }
101 
102         /**
103           Update the entire digital and analog pin state according to the
104           events currently set.
105         */
update()106         void update() override { }
107 
108         /**
109           Returns the name of this controller.
110         */
name() const111         string name() const override { return "CompuMate"; }
112 
113       private:
114         class CompuMate& myHandler;
115 
116         // Following constructors and assignment operators not supported
117         CMControl() = delete;
118         CMControl(const CMControl&) = delete;
119         CMControl(CMControl&&) = delete;
120         CMControl& operator=(const CMControl&) = delete;
121         CMControl& operator=(CMControl&&) = delete;
122     };
123 
124   private:
125     // Console and Event objects
126     const Console& myConsole;
127     const Event& myEvent;
128 
129     // Left and right controllers
130     unique_ptr<Controller> myLeftController, myRightController;
131 
132     // Column currently active
133     uInt8 myColumn{0};
134 
135   private:
136     // Following constructors and assignment operators not supported
137     CompuMate() = delete;
138     CompuMate(const CompuMate&) = delete;
139     CompuMate(CompuMate&&) = delete;
140     CompuMate& operator=(const CompuMate&) = delete;
141     CompuMate& operator=(CompuMate&&) = delete;
142 };
143 
144 #endif
145