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 CARTRIDGE3E_HXX
19#define CARTRIDGE3E_HXX
20
21class System;
22
23#include "bspf.hxx"
24#include "Cart.hxx"
25#ifdef DEBUGGER_SUPPORT
26 #include "Cart3EWidget.hxx"
27#endif
28
29/**
30 This is the cartridge class for Tigervision's bankswitched
31 games with RAM (basically, 3F plus up to 32K of RAM). This
32 code is basically Brad's Cart3F code plus 32K RAM support.
33
34 In this bankswitching scheme the 2600's 4K cartridge
35 address space is broken into two 2K segments. The last 2K
36 segment always points to the last 2K of the ROM image.
37
38 The lower 2K of address space maps to either one of the 2K ROM banks
39 (up to 256 of them, though only 240 are supposed to be used for
40 compatibility with the Kroko Cart and Cuttle Cart 2), or else one
41 of the 1K RAM banks (up to 32 of them). Like other carts with RAM,
42 this takes up twice the address space that it should: The lower 1K
43 is the read port, and the upper 1K is the write port (maps to the
44 same memory).
45
46 To map ROM, the desired bank number of the first 2K segment is selected
47 by storing its value into $3F. To map RAM in the first 2K segment
48 instead, store the RAM bank number into $3E.
49
50 This implementation of 3E bankswitching numbers the ROM banks 0 to
51 255, and the RAM banks 256 to 287. This is done because the public
52 bankswitching interface requires us to use one bank number, not one
53 bank number plus the knowledge of whether it's RAM or ROM.
54
55 All 32K of potential RAM is available to a game using this class, even
56 though real cartridges might not have the full 32K: We have no way to
57 tell how much RAM the game expects. This may change in the future (we
58 may add a stella.pro property for this), but for now it shouldn't cause
59 any problems. (Famous last words...)
60
61 @author B. Watson
62*/
63
64class Cartridge3E : public Cartridge
65{
66 friend class Cartridge3EWidget;
67
68 public:
69 /**
70 Create a new cartridge using the specified image and size
71
72 @param image Pointer to the ROM image
73 @param size The size of the ROM image
74 @param md5 The md5sum of the ROM image
75 @param settings A reference to the various settings (read-only)
76 */
77 Cartridge3E(const ByteBuffer& image, size_t size, const string& md5,
78 const Settings& settings);
79 virtual ~Cartridge3E() = default;
80
81 public:
82 /**
83 Reset device to its power-on state
84 */
85 void reset() override;
86
87 /**
88 Install cartridge in the specified system. Invoked by the system
89 when the cartridge is attached to it.
90
91 @param system The system the device should install itself in
92 */
93 void install(System& system) override;
94
95 /**
96 Install pages for the specified bank in the system.
97
98 @param bank The bank that should be installed in the system
99 */
100 bool bank(uInt16 bank) override;
101
102 /**
103 Get the current bank.
104
105 @param address The address to use when querying the bank
106 */
107 uInt16 getBank(uInt16 address = 0) const override;
108
109 /**
110 Query the number of banks supported by the cartridge.
111 */
112 uInt16 bankCount() const override;
113
114 /**
115 Patch the cartridge ROM.
116
117 @param address The ROM address to patch
118 @param value The value to place into the address
119 @return Success or failure of the patch operation
120 */
121 bool patch(uInt16 address, uInt8 value) override;
122
123 /**
124 Access the internal ROM image for this cartridge.
125
126 @param size Set to the size of the internal ROM image data
127 @return A pointer to the internal ROM image data
128 */
129 const uInt8* getImage(size_t& size) const override;
130
131 /**
132 Save the current state of this cart to the given Serializer.
133
134 @param out The Serializer object to use
135 @return False on any errors, else true
136 */
137 bool save(Serializer& out) const override;
138
139 /**
140 Load the current state of this cart from the given Serializer.
141
142 @param in The Serializer object to use
143 @return False on any errors, else true
144 */
145 bool load(Serializer& in) override;
146
147 /**
148 Get a descriptor for the device name (used in error checking).
149
150 @return The name of the object
151 */
152 string name() const override { return "Cartridge3E"; }
153
154 #ifdef DEBUGGER_SUPPORT
155 /**
156 Get debugger widget responsible for accessing the inner workings
157 of the cart.
158 */
159 CartDebugWidget* debugWidget(GuiObject* boss, const GUI::Font& lfont,
160 const GUI::Font& nfont, int x, int y, int w, int h) override
161 {
162 return new Cartridge3EWidget(boss, lfont, nfont, x, y, w, h, *this);
163 }
164 #endif
165
166 public:
167 /**
168 Get the byte at the specified address
169
170 @return The byte at the specified address
171 */
172 uInt8 peek(uInt16 address) override;
173
174 /**
175 Change the byte at the specified address to the given value
176
177 @param address The address where the value should be stored
178 @param value The value to be stored at the address
179 @return True if the poke changed the device address space, else false
180 */
181 bool poke(uInt16 address, uInt8 value) override;
182
183 private:
184 // Pointer to a dynamically allocated ROM image of the cartridge
185 ByteBuffer myImage;
186
187 // RAM contents. For now every ROM gets all 32K of potential RAM
188 std::array<uInt8, 32_KB> myRAM;
189
190 // Size of the ROM image
191 size_t mySize;
192
193 // Indicates which bank is currently active for the first segment
194 uInt16 myCurrentBank;
195
196 private:
197 // Following constructors and assignment operators not supported
198 Cartridge3E() = delete;
199 Cartridge3E(const Cartridge3E&) = delete;
200 Cartridge3E(Cartridge3E&&) = delete;
201 Cartridge3E& operator=(const Cartridge3E&) = delete;
202 Cartridge3E& operator=(Cartridge3E&&) = delete;
203};
204
205#endif
206