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_HXX
19#define CARTRIDGE_DPC_HXX
20
21class System;
22
23#include "bspf.hxx"
24#include "Cart.hxx"
25#ifdef DEBUGGER_SUPPORT
26 #include "CartDPCWidget.hxx"
27#endif
28
29/**
30 Cartridge class used for Pitfall II. There are two 4K program banks, a
31 2K display bank, and the DPC chip. The bankswitching itself is the same
32 as F8 scheme (hotspots at $1FF8 and $1FF9). DPC chip access is mapped to
33 $1000 - $1080 ($1000 - $103F is read port, $1040 - $107F is write port).
34
35 For complete details on the DPC chip see David P. Crane's United States
36 Patent Number 4,644,495.
37
38 @author Bradford W. Mott
39*/
40class CartridgeDPC : public Cartridge
41{
42 friend class CartridgeDPCWidget;
43
44 public:
45 /**
46 Create a new cartridge using the specified image
47
48 @param image Pointer to the ROM image
49 @param size The size of the ROM image
50 @param md5 The md5sum of the ROM image
51 @param settings A reference to the various settings (read-only)
52 */
53 CartridgeDPC(const ByteBuffer& image, size_t size, const string& md5,
54 const Settings& settings);
55 virtual ~CartridgeDPC() = default;
56
57 public:
58 /**
59 Reset device to its power-on state
60 */
61 void reset() override;
62
63 /**
64 Install cartridge in the specified system. Invoked by the system
65 when the cartridge is attached to it.
66
67 @param system The system the device should install itself in
68 */
69 void install(System& system) override;
70
71 /**
72 Install pages for the specified bank in the system.
73
74 @param bank The bank that should be installed in the system
75 */
76 bool bank(uInt16 bank) override;
77
78 /**
79 Get the current bank.
80
81 @param address The address to use when querying the bank
82 */
83 uInt16 getBank(uInt16 address = 0) const override;
84
85 /**
86 Query the number of banks supported by the cartridge.
87 */
88 uInt16 bankCount() const override;
89
90 /**
91 Patch the cartridge ROM.
92
93 @param address The ROM address to patch
94 @param value The value to place into the address
95 @return Success or failure of the patch operation
96 */
97 bool patch(uInt16 address, uInt8 value) override;
98
99 /**
100 Access the internal ROM image for this cartridge.
101
102 @param size Set to the size of the internal ROM image data
103 @return A pointer to the internal ROM image data
104 */
105 const uInt8* getImage(size_t& size) const override;
106
107 /**
108 Save the current state of this cart to the given Serializer.
109
110 @param out The Serializer object to use
111 @return False on any errors, else true
112 */
113 bool save(Serializer& out) const override;
114
115 /**
116 Load the current state of this cart from the given Serializer.
117
118 @param in The Serializer object to use
119 @return False on any errors, else true
120 */
121 bool load(Serializer& in) override;
122
123 /**
124 Get a descriptor for the device name (used in error checking).
125
126 @return The name of the object
127 */
128 string name() const override { return "CartridgeDPC"; }
129
130 void setDpcPitch(double pitch) { myDpcPitch = pitch; }
131
132 #ifdef DEBUGGER_SUPPORT
133 /**
134 Get debugger widget responsible for accessing the inner workings
135 of the cart.
136 */
137 CartDebugWidget* debugWidget(GuiObject* boss, const GUI::Font& lfont,
138 const GUI::Font& nfont, int x, int y, int w, int h) override
139 {
140 return new CartridgeDPCWidget(boss, lfont, nfont, x, y, w, h, *this);
141 }
142 #endif
143
144 public:
145 /**
146 Get the byte at the specified address.
147
148 @return The byte at the specified address
149 */
150 uInt8 peek(uInt16 address) override;
151
152 /**
153 Change the byte at the specified address to the given value
154
155 @param address The address where the value should be stored
156 @param value The value to be stored at the address
157 @return True if the poke changed the device address space, else false
158 */
159 bool poke(uInt16 address, uInt8 value) override;
160
161 private:
162 /**
163 Clocks the random number generator to move it to its next state
164 */
165 void clockRandomNumberGenerator();
166
167 /**
168 Updates any data fetchers in music mode based on the number of
169 CPU cycles which have passed since the last update.
170 */
171 void updateMusicModeDataFetchers();
172
173 private:
174 // The ROM image
175 std::array<uInt8, 8_KB + 2_KB + 256> myImage;
176
177 // (Actual) Size of the ROM image
178 size_t mySize;
179
180 // Pointer to the 8K program ROM image of the cartridge
181 uInt8* myProgramImage;
182
183 // Pointer to the 2K display ROM image of the cartridge
184 uInt8* myDisplayImage;
185
186 // The top registers for the data fetchers
187 std::array<uInt8, 8> myTops;
188
189 // The bottom registers for the data fetchers
190 std::array<uInt8, 8> myBottoms;
191
192 // The counter registers for the data fetchers
193 std::array<uInt16, 8> myCounters;
194
195 // The flag registers for the data fetchers
196 std::array<uInt8, 8> myFlags;
197
198 // The music mode DF5, DF6, & DF7 enabled flags
199 std::array<bool, 3> myMusicMode;
200
201 // The random number generator register
202 uInt8 myRandomNumber;
203
204 // System cycle count from when the last update to music data fetchers occurred
205 uInt64 myAudioCycles;
206
207 // Fractional DPC music OSC clocks unused during the last update
208 double myFractionalClocks;
209
210 // Indicates the offset into the ROM image (aligns to current bank)
211 uInt16 myBankOffset;
212
213 // DPC pitch
214 double myDpcPitch;
215
216 private:
217 // Following constructors and assignment operators not supported
218 CartridgeDPC() = delete;
219 CartridgeDPC(const CartridgeDPC&) = delete;
220 CartridgeDPC(CartridgeDPC&&) = delete;
221 CartridgeDPC& operator=(const CartridgeDPC&) = delete;
222 CartridgeDPC& operator=(CartridgeDPC&&) = delete;
223};
224
225#endif
226