1
2//============================================================================
3//
4// SSSS tt lll lll
5// SS SS tt ll ll
6// SS tttttt eeee ll ll aaaa
7// SSSS tt ee ee ll ll aa
8// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
9// SS SS tt ee ll ll aa aa
10// SSSS ttt eeeee llll llll aaaaa
11//
12// Copyright (c) 1995-2019 by Bradford W. Mott, Stephen Anthony
13// and the Stella Team
14//
15// See the file "License.txt" for information on usage and redistribution of
16// this file, and for a DISCLAIMER OF ALL WARRANTIES.
17//============================================================================
18
19#ifndef CARTRIDGE_MNETWORK_HXX
20#define CARTRIDGE_MNETWORK_HXX
21
22#include "System.hxx"
23#include "bspf.hxx"
24#include "Cart.hxx"
25
26/**
27 This is the abstract cartridge class for M-Network
28 bankswitched games.
29 In this bankswitching scheme the 2600's 4K cartridge address
30 space is broken into two 2K segments.
31
32 Kevin Horton describes E7 as follows:
33
34 "Only M-Network used this scheme. This has to be the
35 most complex method used in any cart! :-) It allows
36 for the capability of 2K of RAM; although it doesn't
37 have to be used (in fact, only one cart used it).
38 There are now 8 2K banks, instead of 4. The last 2K
39 in the cart always points to the last 2K of the ROM
40 image, while the first 2K is selectable. You access
41 1FE0 to 1FE6 to select which 2K bank. Note that you
42 cannot select the last 2K of the ROM image into the
43 lower 2K of the cart! Accessing 1FE7 selects 1K of
44 RAM at 1000-17FF instead of ROM! The 2K of RAM is
45 broken up into two 1K sections. One 1K section is
46 mapped in at 1000-17FF if 1FE7 has been accessed.
47 1000-13FF is the write port, while 1400-17FF is the
48 read port. The second 1K of RAM appears at 1800-19FF.
49 1800-18FF is the write port while 1900-19FF is the
50 read port. You select which 256 byte block appears
51 here by accessing 1FE8 to 1FEB.
52
53 This cart reports having 8 banks; 1 for each of the possible 7
54 slices in the lower 2K area, and the last for RAM in the lower
55 2K area."
56
57 There are 8K, 12K and 16K variations, with or without RAM.
58
59 @author Bradford W. Mott, Thomas Jentzsch
60*/
61class CartridgeMNetwork : public Cartridge
62{
63 friend class CartridgeMNetworkWidget;
64 friend class CartridgeE7Widget;
65 friend class CartridgeE78KWidget;
66
67 public:
68 /**
69 Create a new cartridge using the specified image
70
71 @param image Pointer to the ROM image
72 @param size The size of the ROM image
73 @param md5 The md5sum of the ROM image
74 @param settings A reference to the various settings (read-only)
75 */
76 CartridgeMNetwork(const ByteBuffer& image, size_t size, const string& md5,
77 const Settings& settings);
78 virtual ~CartridgeMNetwork() = default;
79
80 public:
81 /**
82 Reset device to its power-on state
83 */
84 void reset() override;
85
86 /**
87 Install cartridge in the specified system. Invoked by the system
88 when the cartridge is attached to it.
89
90 @param system The system the device should install itself in
91 */
92 void install(System& system) override;
93
94 /**
95 Install pages for the specified bank in the system.
96
97 @param bank The bank that should be installed in the system
98 */
99 bool bank(uInt16 bank) override;
100
101 /**
102 Get the current bank.
103
104 @param address The address to use when querying the bank
105 */
106 uInt16 getBank(uInt16 address = 0) const override;
107
108 /**
109 Query the number of banks supported by the cartridge.
110 */
111 uInt16 bankCount() const override;
112
113 /**
114 Patch the cartridge ROM.
115
116 @param address The ROM address to patch
117 @param value The value to place into the address
118 @return Success or failure of the patch operation
119 */
120 bool patch(uInt16 address, uInt8 value) override;
121
122 /**
123 Access the internal ROM image for this cartridge.
124
125 @param size Set to the size of the internal ROM image data
126 @return A pointer to the internal ROM image data
127 */
128 const uInt8* getImage(size_t& size) const override;
129
130 /**
131 Save the current state of this cart to the given Serializer.
132
133 @param out The Serializer object to use
134 @return False on any errors, else true
135 */
136 bool save(Serializer& out) const override;
137
138 /**
139 Load the current state of this cart from the given Serializer.
140
141 @param in The Serializer object to use
142 @return False on any errors, else true
143 */
144 bool load(Serializer& in) override;
145
146 public:
147 /**
148 Get the byte at the specified address.
149
150 @return The byte at the specified address
151 */
152 uInt8 peek(uInt16 address) override;
153
154 /**
155 Change the byte at the specified address to the given value
156
157 @param address The address where the value should be stored
158 @param value The value to be stored at the address
159 @return True if the poke changed the device address space, else false
160 */
161 bool poke(uInt16 address, uInt8 value) override;
162
163 protected:
164 /**
165 Class initialization
166 */
167 void initialize(const ByteBuffer& image, size_t size);
168
169 /**
170 Install pages for the specified 256 byte bank of RAM
171
172 @param bank The bank that should be installed in the system
173 */
174 void bankRAM(uInt16 bank);
175
176 // Size of a ROM or RAM bank
177 static constexpr uInt32 BANK_SIZE = 0x800; // 2K
178
179 private:
180 // Size of RAM in the cart
181 static constexpr uInt32 RAM_SIZE = 0x800; // 1K + 4 * 256B = 2K
182 // Number of slices with 4K address space
183 static constexpr uInt32 NUM_SEGMENTS = 2;
184
185 /**
186 Query the size of the BS type.
187 */
188 uInt16 romSize() const;
189
190 /**
191 Check hotspots and switch bank if triggered.
192 */
193 virtual void checkSwitchBank(uInt16 address) = 0;
194
195 void setAccess(uInt16 addrFrom, uInt16 size, uInt16 directOffset, uInt8* directData,
196 uInt16 codeOffset, System::PageAccessType type, uInt16 addrMask = 0);
197
198 private:
199 // Pointer to a dynamically allocated ROM image of the cartridge
200 ByteBuffer myImage;
201 // The 16K ROM image of the cartridge (works for E78K too)
202 //uInt8 myImage[BANK_SIZE * 8];
203
204 // Size of the ROM image
205 size_t mySize;
206
207 // The 2K of RAM
208 std::array<uInt8, RAM_SIZE> myRAM;
209
210 // Indicates which slice is in the segment
211 std::array<uInt16, NUM_SEGMENTS> myCurrentSlice;
212
213 // Indicates which 256 byte bank of RAM is being used
214 uInt16 myCurrentRAM;
215
216 // The number of the RAM slice (== bankCount() - 1)
217 uInt32 myRAMSlice;
218
219 private:
220 // Following constructors and assignment operators not supported
221 CartridgeMNetwork() = delete;
222 CartridgeMNetwork(const CartridgeMNetwork&) = delete;
223 CartridgeMNetwork(CartridgeMNetwork&&) = delete;
224 CartridgeMNetwork& operator=(const CartridgeMNetwork&) = delete;
225 CartridgeMNetwork& operator=(CartridgeMNetwork&&) = delete;
226};
227
228#endif
229