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 CARTRIDGE_DPC_PLUS_HXX
19#define CARTRIDGE_DPC_PLUS_HXX
20
21class System;
22
23#include "Thumbulator.hxx"
24#ifdef DEBUGGER_SUPPORT
25 #include "CartDPCPlusWidget.hxx"
26#endif
27
28#include "bspf.hxx"
29#include "Cart.hxx"
30
31/**
32 Cartridge class used for DPC+, derived from Pitfall II. There are six 4K
33 program banks, a 4K display bank, 1K frequency table and the DPC chip.
34 DPC chip access is mapped to $1000 - $1080 ($1000 - $103F is read port,
35 $1040 - $107F is write port).
36 Program banks are accessible by read/write to $1FF6 - $1FFB.
37
38 FIXME: THIS NEEDS TO BE UPDATED
39
40 For complete details on the DPC chip see David P. Crane's United States
41 Patent Number 4,644,495.
42
43 @authors Darrell Spice Jr, Fred Quimby, Stephen Anthony, Bradford W. Mott
44*/
45class CartridgeDPCPlus : public Cartridge
46{
47 friend class CartridgeDPCPlusWidget;
48 friend class CartridgeRamDPCPlusWidget;
49
50 public:
51 /**
52 Create a new cartridge using the specified image
53
54 @param image Pointer to the ROM image
55 @param size The size of the ROM image
56 @param md5 The md5sum of the ROM image
57 @param settings A reference to the various settings (read-only)
58 */
59 CartridgeDPCPlus(const ByteBuffer& image, size_t size, const string& md5,
60 const Settings& settings);
61 virtual ~CartridgeDPCPlus() = default;
62
63 public:
64 /**
65 Reset device to its power-on state
66 */
67 void reset() override;
68
69 /**
70 Notification method invoked by the system when the console type
71 has changed. We need this to inform the Thumbulator that the
72 timing has changed.
73
74 @param timing Enum representing the new console type
75 */
76 void consoleChanged(ConsoleTiming timing) override;
77
78 /**
79 Install cartridge in the specified system. Invoked by the system
80 when the cartridge is attached to it.
81
82 @param system The system the device should install itself in
83 */
84 void install(System& system) override;
85
86 /**
87 Install pages for the specified bank in the system.
88
89 @param bank The bank that should be installed in the system
90 */
91 bool bank(uInt16 bank) override;
92
93 /**
94 Get the current bank.
95
96 @param address The address to use when querying the bank
97 */
98 uInt16 getBank(uInt16 address = 0) const override;
99
100 /**
101 Query the number of banks supported by the cartridge.
102 */
103 uInt16 bankCount() const override;
104
105 /**
106 Patch the cartridge ROM.
107
108 @param address The ROM address to patch
109 @param value The value to place into the address
110 @return Success or failure of the patch operation
111 */
112 bool patch(uInt16 address, uInt8 value) override;
113
114 /**
115 Access the internal ROM image for this cartridge.
116
117 @param size Set to the size of the internal ROM image data
118 @return A pointer to the internal ROM image data
119 */
120 const uInt8* getImage(size_t& size) const override;
121
122 /**
123 Save the current state of this cart to the given Serializer.
124
125 @param out The Serializer object to use
126 @return False on any errors, else true
127 */
128 bool save(Serializer& out) const override;
129
130 /**
131 Load the current state of this cart from the given Serializer.
132
133 @param in The Serializer object to use
134 @return False on any errors, else true
135 */
136 bool load(Serializer& in) override;
137
138 /**
139 Get a descriptor for the device name (used in error checking).
140
141 @return The name of the object
142 */
143 string name() const override { return "CartridgeDPC+"; }
144
145 #ifdef DEBUGGER_SUPPORT
146 /**
147 Get debugger widget responsible for accessing the inner workings
148 of the cart.
149 */
150 CartDebugWidget* debugWidget(GuiObject* boss, const GUI::Font& lfont,
151 const GUI::Font& nfont, int x, int y, int w, int h) override
152 {
153 return new CartridgeDPCPlusWidget(boss, lfont, nfont, x, y, w, h, *this);
154 }
155 #endif
156
157 public:
158 /**
159 Get the byte at the specified address.
160
161 @return The byte at the specified address
162 */
163 uInt8 peek(uInt16 address) override;
164
165 /**
166 Change the byte at the specified address to the given value
167
168 @param address The address where the value should be stored
169 @param value The value to be stored at the address
170 @return True if the poke changed the device address space, else false
171 */
172 bool poke(uInt16 address, uInt8 value) override;
173
174 private:
175 /**
176 Sets the initial state of the DPC pointers and RAM
177 */
178 void setInitialState();
179
180 /**
181 Clocks the random number generator to move it to its next state
182 */
183 void clockRandomNumberGenerator();
184
185 /**
186 Clocks the random number generator to move it to its prior state
187 */
188 void priorClockRandomNumberGenerator();
189
190 /**
191 Updates any data fetchers in music mode based on the number of
192 CPU cycles which have passed since the last update.
193 */
194 void updateMusicModeDataFetchers();
195
196 /**
197 Call Special Functions
198 */
199 void callFunction(uInt8 value);
200
201 private:
202 // The ROM image and size
203 std::array<uInt8, 32_KB> myImage;
204 size_t mySize;
205
206 // Pointer to the 24K program ROM image of the cartridge
207 uInt8* myProgramImage;
208
209 // Pointer to the 4K display ROM image of the cartridge
210 uInt8* myDisplayImage;
211
212 // The DPC 8k RAM image, used as:
213 // 3K DPC+ driver
214 // 4K Display Data
215 // 1K Frequency Data
216 std::array<uInt8, 8_KB> myDPCRAM;
217
218 // Pointer to the Thumb ARM emulator object
219 unique_ptr<Thumbulator> myThumbEmulator;
220
221 // Pointer to the 1K frequency table
222 uInt8* myFrequencyImage;
223
224 // The top registers for the data fetchers
225 std::array<uInt8, 8> myTops;
226
227 // The bottom registers for the data fetchers
228 std::array<uInt8, 8> myBottoms;
229
230 // The counter registers for the data fetchers
231 std::array<uInt16, 8> myCounters;
232
233 // The counter registers for the fractional data fetchers
234 std::array<uInt32, 8> myFractionalCounters;
235
236 // The fractional increments for the data fetchers
237 std::array<uInt8, 8> myFractionalIncrements;
238
239 // The Fast Fetcher Enabled flag
240 bool myFastFetch;
241
242 // Flags that last byte peeked was A9 (LDA #)
243 bool myLDAimmediate;
244
245 // Parameter for special functions
246 std::array<uInt8, 8> myParameter;
247
248 // Parameter pointer for special functions
249 uInt8 myParameterPointer;
250
251 // The music mode counters
252 std::array<uInt32, 3> myMusicCounters;
253
254 // The music frequency
255 std::array<uInt32, 3> myMusicFrequencies;
256
257 // The music waveforms
258 std::array<uInt16, 3> myMusicWaveforms;
259
260 // The random number generator register
261 uInt32 myRandomNumber;
262
263 // System cycle count from when the last update to music data fetchers occurred
264 uInt64 myAudioCycles;
265
266 // System cycle count when the last Thumbulator::run() occurred
267 uInt64 myARMCycles;
268
269 // Fractional DPC music OSC clocks unused during the last update
270 double myFractionalClocks;
271
272 // Indicates the offset into the ROM image (aligns to current bank)
273 uInt16 myBankOffset;
274
275 // Older DPC+ driver code had different behaviour wrt the mask used
276 // to retrieve 'DFxFRACLOW' (fractional data pointer low byte)
277 // ROMs built with an old DPC+ driver and using the newer mask can
278 // result in 'jittering' in the playfield display
279 // For current versions, this is 0x0F00FF; older versions need 0x0F0000
280 uInt32 myFractionalLowMask;
281
282 private:
283 // Following constructors and assignment operators not supported
284 CartridgeDPCPlus() = delete;
285 CartridgeDPCPlus(const CartridgeDPCPlus&) = delete;
286 CartridgeDPCPlus(CartridgeDPCPlus&&) = delete;
287 CartridgeDPCPlus& operator=(const CartridgeDPCPlus&) = delete;
288 CartridgeDPCPlus& operator=(CartridgeDPCPlus&&) = delete;
289};
290
291#endif
292