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 | |
21 | class 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 | |
64 | class 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 | |