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 CARTRIDGEWD_HXX
19#define CARTRIDGEWD_HXX
20
21class System;
22
23#include "bspf.hxx"
24#include "Cart.hxx"
25#ifdef DEBUGGER_SUPPORT
26 #include "CartWDWidget.hxx"
27#endif
28
29/**
30 This is the cartridge class for a "Wickstead Design" prototype cart.
31 The ROM has 64 bytes of RAM.
32 In this bankswitching scheme the 2600's 4K cartridge address space
33 is broken into four 1K segments. The desired arrangement of 1K slices
34 is selected by accessing $30 - $3F of TIA address space. The slices
35 are mapped into all 4 segments at once as follows:
36
37 $0030, $0038: 0,0,1,3
38 $0031, $0039: 0,1,2,3
39 $0032, $003A: 4,5,6,7
40 $0033, $003B: 7,4,2,3
41
42 $0034, $003C: 0,0,6,7
43 $0035, $003D: 0,1,7,6
44 $0036, $003E: 2,3,4,5
45 $0037, $003F: 6,0,5,1
46
47
48 In the uppermost (third) segment, the byte at $3FC is overwritten by 0.
49
50 The 64 bytes of RAM are accessible at $1000 - $103F (read port) and
51 $1040 - $107F (write port). Because the RAM takes 128 bytes of address
52 space, the range $1000 - $107F of segment 0 ROM will never be available.
53
54 @author Stephen Anthony
55*/
56class CartridgeWD : public Cartridge
57{
58 friend class CartridgeWDWidget;
59
60 public:
61 /**
62 Create a new cartridge using the specified image
63
64 @param image Pointer to the ROM image
65 @param size The size of the ROM image
66 @param md5 The md5sum of the ROM image
67 @param settings A reference to the various settings (read-only)
68 */
69 CartridgeWD(const ByteBuffer& image, size_t size, const string& md5,
70 const Settings& settings);
71 virtual ~CartridgeWD() = default;
72
73 public:
74 /**
75 Reset device to its power-on state
76 */
77 void reset() override;
78
79 /**
80 Install cartridge in the specified system. Invoked by the system
81 when the cartridge is attached to it.
82
83 @param system The system the device should install itself in
84 */
85 void install(System& system) override;
86
87 /**
88 Install pages for the specified bank in the system.
89
90 @param bank The bank that should be installed in the system
91 */
92 bool bank(uInt16 bank) override;
93
94 /**
95 Get the current bank.
96
97 @param address The address to use when querying the bank
98 */
99 uInt16 getBank(uInt16 address = 0) const override;
100
101 /**
102 Query the number of banks supported by the cartridge.
103 */
104 uInt16 bankCount() const override;
105
106 /**
107 Patch the cartridge ROM.
108
109 @param address The ROM address to patch
110 @param value The value to place into the address
111 @return Success or failure of the patch operation
112 */
113 bool patch(uInt16 address, uInt8 value) override;
114
115 /**
116 Access the internal ROM image for this cartridge.
117
118 @param size Set to the size of the internal ROM image data
119 @return A pointer to the internal ROM image data
120 */
121 const uInt8* getImage(size_t& size) const override;
122
123 /**
124 Save the current state of this cart to the given Serializer.
125
126 @param out The Serializer object to use
127 @return False on any errors, else true
128 */
129 bool save(Serializer& out) const override;
130
131 /**
132 Load the current state of this cart from the given Serializer.
133
134 @param in The Serializer object to use
135 @return False on any errors, else true
136 */
137 bool load(Serializer& in) override;
138
139 /**
140 Get a descriptor for the device name (used in error checking).
141
142 @return The name of the object
143 */
144 string name() const override { return "CartridgeWD"; }
145
146 #ifdef DEBUGGER_SUPPORT
147 /**
148 Get debugger widget responsible for accessing the inner workings
149 of the cart.
150 */
151 CartDebugWidget* debugWidget(GuiObject* boss, const GUI::Font& lfont,
152 const GUI::Font& nfont, int x, int y, int w, int h) override
153 {
154 return new CartridgeWDWidget(boss, lfont, nfont, x, y, w, h, *this);
155 }
156 #endif
157
158 public:
159 /**
160 Get the byte at the specified address.
161
162 @return The byte at the specified address
163 */
164 uInt8 peek(uInt16 address) override;
165
166 /**
167 Change the byte at the specified address to the given value.
168
169 @param address The address where the value should be stored
170 @param value The value to be stored at the address
171 @return True if the poke changed the device address space, else false
172 */
173 bool poke(uInt16 address, uInt8 value) override;
174
175 private:
176 /**
177 Install the specified slice for segment zero.
178
179 @param slice The slice to map into the segment
180 */
181 void segmentZero(uInt8 slice);
182
183 /**
184 Install the specified slice for segment one.
185
186 @param slice The slice to map into the segment
187 */
188 void segmentOne(uInt8 slice);
189
190 /**
191 Install the specified slice for segment two.
192
193 @param slice The slice to map into the segment
194 */
195 void segmentTwo(uInt8 slice);
196
197 /**
198 Install the specified slice for segment three.
199 Note that this method also takes care of setting one byte to 0.
200
201 @param slice The slice to map into the segment
202 */
203 void segmentThree(uInt8 slice);
204
205 private:
206 // The 8K ROM image of the cartridge
207 std::array<uInt8, 8_KB> myImage;
208
209 // Indicates the actual size of the ROM image (either 8K or 8K + 3)
210 size_t mySize;
211
212 // The 64 bytes RAM of the cartridge
213 std::array<uInt8, 64> myRAM;
214
215 // The 1K ROM mirror of segment 3 (sometimes contains extra 3 bytes)
216 std::array<uInt8, 1_KB> mySegment3;
217
218 // Indicates the offset for each of the four segments
219 std::array<uInt16, 4> myOffset;
220
221 // Indicates the cycle at which a bankswitch was initiated
222 uInt64 myCyclesAtBankswitchInit;
223
224 // Indicates the bank we wish to switch to in the future
225 uInt16 myPendingBank;
226
227 // Indicates which bank is currently active
228 uInt16 myCurrentBank;
229
230 // The arrangement of banks to use on each hotspot read
231 struct BankOrg {
232 uInt8 zero, one, two, three;
233 };
234 static BankOrg ourBankOrg[8];
235
236 private:
237 // Following constructors and assignment operators not supported
238 CartridgeWD() = delete;
239 CartridgeWD(const CartridgeWD&) = delete;
240 CartridgeWD(CartridgeWD&&) = delete;
241 CartridgeWD& operator=(const CartridgeWD&) = delete;
242 CartridgeWD& operator=(CartridgeWD&&) = delete;
243};
244
245#endif
246