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-2019 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 CARTRIDGEMDM_HXX
19#define CARTRIDGEMDM_HXX
20
21#include "bspf.hxx"
22#include "Cart.hxx"
23#include "System.hxx"
24#ifdef DEBUGGER_SUPPORT
25 #include "CartMDMWidget.hxx"
26#endif
27
28/**
29 Cartridge class used for "Menu Driven Megacart" as described at the
30 following link and developed by Edwin Blink:
31
32 http://atariage.com/forums/topic/56073-cheap-2k4k-x-in-1-menu-driven-multicart-for-atari-2600
33
34 Note that this code implements a modified scheme (as designed by E. Blink).
35 In this version, the hotspots are from $800 to $BFF instead of $800 to $FFF.
36
37 The hotspots in this scheme are read/write at addresses $800 to $BFF, where
38 the lower byte determines the actual 4K bank switch to. In the current
39 implementation, only 128 banks are supported, so selecting bank 128+ results
40 in further bankswitching being locked. A reset line is used to reset to
41 bank 0 and re-enable bankswitching.
42
43 Therefore, there are 128 banks / 512K possible in total.
44
45 @author Stephen Anthony, based on 0840 scheme by Fred X. Quimby
46*/
47class CartridgeMDM : public Cartridge
48{
49 friend class CartridgeMDMWidget;
50
51 public:
52 /**
53 Create a new cartridge using the specified image
54
55 @param image Pointer to the ROM image
56 @param size The size of the ROM image
57 @param md5 The md5sum of the ROM image
58 @param settings A reference to the various settings (read-only)
59 */
60 CartridgeMDM(const ByteBuffer& image, size_t size, const string& md5,
61 const Settings& settings);
62 virtual ~CartridgeMDM() = default;
63
64 public:
65 /**
66 Reset device to its power-on state
67 */
68 void reset() override;
69
70 /**
71 Install cartridge in the specified system. Invoked by the system
72 when the cartridge is attached to it.
73
74 @param system The system the device should install itself in
75 */
76 void install(System& system) override;
77
78 /**
79 Install pages for the specified bank in the system.
80
81 @param bank The bank that should be installed in the system
82 */
83 bool bank(uInt16 bank) override;
84
85 /**
86 Get the current bank.
87
88 @param address The address to use when querying the bank
89 */
90 uInt16 getBank(uInt16 address = 0) const override;
91
92 /**
93 Query the number of banks supported by the cartridge.
94 */
95 uInt16 bankCount() const override;
96
97 /**
98 Patch the cartridge ROM.
99
100 @param address The ROM address to patch
101 @param value The value to place into the address
102 @return Success or failure of the patch operation
103 */
104 bool patch(uInt16 address, uInt8 value) override;
105
106 /**
107 Access the internal ROM image for this cartridge.
108
109 @param size Set to the size of the internal ROM image data
110 @return A pointer to the internal ROM image data
111 */
112 const uInt8* getImage(size_t& size) const override;
113
114 /**
115 Save the current state of this cart to the given Serializer.
116
117 @param out The Serializer object to use
118 @return False on any errors, else true
119 */
120 bool save(Serializer& out) const override;
121
122 /**
123 Load the current state of this cart from the given Serializer.
124
125 @param in The Serializer object to use
126 @return False on any errors, else true
127 */
128 bool load(Serializer& in) override;
129
130 /**
131 Get a descriptor for the device name (used in error checking).
132
133 @return The name of the object
134 */
135 string name() const override { return "CartridgeMDM"; }
136
137 #ifdef DEBUGGER_SUPPORT
138 /**
139 Get debugger widget responsible for accessing the inner workings
140 of the cart.
141 */
142 CartDebugWidget* debugWidget(GuiObject* boss, const GUI::Font& lfont,
143 const GUI::Font& nfont, int x, int y, int w, int h) override
144 {
145 return new CartridgeMDMWidget(boss, lfont, nfont, x, y, w, h, *this);
146 }
147 #endif
148
149 public:
150 /**
151 Get the byte at the specified address.
152
153 @return The byte at the specified address
154 */
155 uInt8 peek(uInt16 address) override;
156
157 /**
158 Change the byte at the specified address to the given value
159
160 @param address The address where the value should be stored
161 @param value The value to be stored at the address
162 @return True if the poke changed the device address space, else false
163 */
164 bool poke(uInt16 address, uInt8 value) override;
165
166 private:
167 // Pointer to a dynamically allocated ROM image of the cartridge
168 ByteBuffer myImage;
169
170 // Size of the ROM image
171 size_t mySize;
172
173 // Previous Device's page access
174 std::array<System::PageAccess, 8> myHotSpotPageAccess;
175
176 // Indicates the offset into the ROM image (aligns to current bank)
177 uInt32 myBankOffset;
178
179 // Indicates whether banking has been disabled due to a bankswitch
180 // above bank 127
181 bool myBankingDisabled;
182
183 private:
184 // Following constructors and assignment operators not supported
185 CartridgeMDM() = delete;
186 CartridgeMDM(const CartridgeMDM&) = delete;
187 CartridgeMDM(CartridgeMDM&&) = delete;
188 CartridgeMDM& operator=(const CartridgeMDM&) = delete;
189 CartridgeMDM& operator=(CartridgeMDM&&) = delete;
190};
191
192#endif
193