VirtualC64 v5.0 beta
Commodore 64 Emulator
Loading...
Searching...
No Matches
Cartridge.h
1// -----------------------------------------------------------------------------
2// This file is part of VirtualC64
3//
4// Copyright (C) Dirk W. Hoffmann. www.dirkwhoffmann.de
5// This FILE is dual-licensed. You are free to choose between:
6//
7// - The GNU General Public License v3 (or any later version)
8// - The Mozilla Public License v2
9//
10// SPDX-License-Identifier: GPL-3.0-or-later OR MPL-2.0
11// -----------------------------------------------------------------------------
12
13#pragma once
14
15#include "CartridgeTypes.h"
16#include "SubComponent.h"
17#include "CartridgeRom.h"
18#include "CRTFile.h"
19
20namespace vc64 {
21
22class Cartridge : public SubComponent, public Inspectable<CartridgeInfo> {
23
24 Descriptions descriptions = {{
25
26 .name = "Cartridge",
27 .description = "Cartridge"
28 }};
29
30 CartridgeTraits traits = {
31
32 .type = CRT_NORMAL,
33 .title = "Cartridge",
34 };
35
36public:
37
38 virtual const CartridgeTraits &getCartridgeTraits() const { return traits; }
39
40 // Maximum number of chip packets on a single cartridge
41 static const isize MAX_PACKETS = 128;
42
43
44 //
45 // Cartridge configuration
46 //
47
48private:
49
50 /* Initial values of the game and exrom lines. The values are read from the
51 * CRT file and the game line is set to it when the cartridge is plugged
52 * into the expansion port.
53 */
54 bool gameLineInCrtFile = 1;
55 bool exromLineInCrtFile = 1;
56
57
58 //
59 // Rom packets
60 //
61
62protected:
63
64 isize numPackets = 0;
65 CartridgeRom *packet[MAX_PACKETS] = {};
66
67 // Indicates which packets are currently mapped to ROML and ROMH
68 isize chipL = 0;
69 isize chipH = 0;
70
71 /* Number of bytes that are mapped to ROML and ROMH. For most cartridges,
72 * this value is equals packet[romX]->size which means that the ROM is
73 * completely mapped. A value of 0 indicates that no ROM is currently
74 * mapped.
75 */
76 u16 mappedBytesL = 0;
77 u16 mappedBytesH = 0;
78
79 /* Offset into the ROM chip's data array. The first ROMx byte has index
80 * offsetx. The last ROMx byte has index offsetx + mappedBytesx - 1.
81 */
82 u16 offsetL = 0;
83 u16 offsetH = 0;
84
85private:
86
87 //
88 // On-board RAM
89 //
90
91 // Additional RAM
92 u8 *externalRam = nullptr;
93
94 // RAM capacity in bytes
95 isize ramCapacity = 0;
96
97 // Total number of write accesses
98 i64 writes = 0;
99
100
101 //
102 // On-board registers
103 //
104
105protected:
106
107 /* Auxililary control register. Many non-standard cartridges carry an
108 * additional register on board.
109 */
110 u8 control = 0;
111
112
113 //
114 // Hardware switches
115 //
116
117protected:
118
119 /* Current position of the cartridge switch (if any). Only a few cartridges
120 * have a switch such as ISEPIC and EXPERT.
121 */
122 isize switchPos = 0;
123
124 // Status of the cartridge LED (true = on)
125 bool led = false;
126
127
128 //
129 // Class methods
130 //
131
132public:
133
134 // Checks whether this cartridge has a known type indentifier
135 static bool isKnownType(CartridgeType type);
136
137 // Checks whether this cartridge is a supported by the emulator
138 static bool isSupportedType(CartridgeType type);
139
140 // Returns true if addr is located in the ROML or the ROMH address space
141 static bool isROMLaddr(u16 addr);
142 static bool isROMHaddr(u16 addr);
143
144 // Factory methods
145 static Cartridge *makeWithType(C64 &c64, CartridgeType type) throws;
146 static Cartridge *makeWithCRTFile(C64 &c64, const CRTFile &file) throws;
147
148
149 //
150 // Methods
151 //
152
153public:
154
155 Cartridge(C64 &ref);
156 ~Cartridge();
157
158 virtual void init();
159 void dealloc();
160
161public:
162
163 Cartridge& operator= (const Cartridge& other) {
164
165 cloneRomAndRam(other);
166
167 CLONE(chipL)
168 CLONE(chipH)
169 CLONE(mappedBytesL)
170 CLONE(mappedBytesH)
171 CLONE(offsetL)
172 CLONE(offsetH)
173 CLONE(led)
174
175 CLONE(gameLineInCrtFile)
176 CLONE(exromLineInCrtFile)
177 CLONE(numPackets)
178 CLONE(ramCapacity)
179 CLONE(writes)
180 CLONE(control)
181 CLONE(switchPos)
182
183 return *this;
184 }
185 void cloneRomAndRam(const Cartridge& other);
186 virtual void clone(const Cartridge &other) { *this = other; }
187
188
189 //
190 // Methods from Serializable
191 //
192
193public:
194
195 template <class T>
196 void serialize(T& worker)
197 {
198 worker
199
200 << chipL
201 << chipH
202 << mappedBytesL
203 << mappedBytesH
204 << offsetL
205 << offsetH
206 << led;
207
208 if (isResetter(worker)) return;
209
210 worker
211
212 << gameLineInCrtFile
213 << exromLineInCrtFile
214 << numPackets
215 << ramCapacity
216 << writes
217 << control
218 << switchPos;
219 }
220
221public:
222
223 void operator << (SerResetter &worker) override;
224 void operator << (SerChecker &worker) override { serialize(worker); }
225 void operator << (SerCounter &worker) override;
226 void operator << (SerReader &worker) override;
227 void operator << (SerWriter &worker) override;
228
229
230 //
231 // Methods from CoreComponent
232 //
233
234public:
235
236 const Descriptions &getDescriptions() const override { return descriptions; }
237
238protected:
239
240 const char *objectName() const override { return getCartridgeTraits().title; }
241 void _dump(Category category, std::ostream& os) const override;
242
243
244 //
245 // Methods from Inspectable
246 //
247
248public:
249
250 void cacheInfo(CartridgeInfo &result) const override;
251
252
253 //
254 // Analyzing
255 //
256
257public:
258
259 // CartridgeInfo getInfo() const;
260 CartridgeRomInfo getRomInfo(isize nr) const;
261
262 // Returns the cartridge type
263 virtual CartridgeType getCartridgeType() const { return getCartridgeTraits().type; }
264
265 // Checks whether this cartridge is supported by the emulator yet
266 bool isSupported() const { return isSupportedType(getCartridgeType()); }
267
268
269 //
270 // Accessing
271 //
272
273public:
274
275 // Returns the initial value of the Game or the Exrom line
276 virtual bool getGameLineInCrtFile() const { return gameLineInCrtFile; }
277 virtual bool getExromLineInCrtFile() const { return exromLineInCrtFile; }
278
279 /* Resets the Game and the Exrom line. The default implementation resets
280 * the values to ones found in the CRT file. A few custom cartridges need
281 * other start configurations and overwrite this function.
282 */
283 virtual void resetCartConfig();
284
285
286 //
287 // Handling ROM packets
288 //
289
290public:
291
292 // Reads in a chip packet from a CRT file
293 virtual void loadChip(isize nr, const CRTFile &c);
294
295 // Banks in a rom chip into the ROML or the ROMH space
296 void bankInROML(isize nr, u16 size, u16 offset);
297 void bankInROMH(isize nr, u16 size, u16 offset);
298
299 /* Banks in a rom chip. This function calls bankInROML or bankInROMH with
300 * the default parameters for this chip as provided in the CRT file.
301 */
302 virtual void bankIn(isize nr);
303
304 // Banks out a chip (RAM will be visible again)
305 void bankOut(isize nr);
306
307
308 //
309 // Accessing cartridge memory
310 //
311
312 /* Fallthroughs for the cartridge memory
313 *
314 * ROML range: 0x8000 - 0x9FFF
315 * ROMH range: 0xA000 - 0xBFFF and 0xE000 - 0xFFFF
316 */
317 virtual u8 peek(u16 addr);
318 virtual u8 peekRomL(u16 addr);
319 virtual u8 peekRomH(u16 addr);
320
321 virtual u8 spypeek(u16 addr) const;
322 virtual u8 spypeekRomL(u16 addr) const;
323 virtual u8 spypeekRomH(u16 addr) const;
324
325 virtual void poke(u16 addr, u8 value);
326 virtual void pokeRomL(u16 addr, u8 value) { return; }
327 virtual void pokeRomH(u16 addr, u8 value) { return; }
328
329 // Fallthroughs for the I/O spaces
330 virtual u8 peekIO1(u16 addr) { return 0; }
331 virtual u8 peekIO2(u16 addr) { return 0; }
332
333 virtual u8 spypeekIO1(u16 addr) const { return 0; }
334 virtual u8 spypeekIO2(u16 addr) const { return 0; }
335
336 virtual void pokeIO1(u16 addr, u8 value) { }
337 virtual void pokeIO2(u16 addr, u8 value) { }
338
339
340 //
341 // Managing on-board RAM
342 //
343
344 // Returns the size of the on-board RAM in bytes
345 isize getRamCapacity() const { return getCartridgeTraits().memory; }
346
347 /* Assigns external RAM to this cartridge. This functions frees any
348 * previously assigned RAM and allocates memory of the specified size. The
349 * size is stored in variable ramCapacity.
350 */
351 void setRamCapacity(isize size);
352
353 // Reads or write RAM cells
354 u8 peekRAM(u32 addr) const;
355 void pokeRAM(u32 addr, u8 value);
356 void eraseRAM(u8 value);
357
358
359 //
360 // Operating buttons
361 //
362
363 // Returns the number of available cartridge buttons
364 virtual isize numButtons() const { return 0; }
365
366 /* Returns a textual description for a button or nullptr, if there is no
367 * button with the specified number.
368 */
369 virtual const char *getButtonTitle(isize nr) const { return ""; }
370
371 // Presses a button (make sure to call releaseButton() afterwards)
372 virtual void pressButton(isize nr) { }
373
374 // Releases a button (make sure to call pressButton() before)
375 virtual void releaseButton(isize nr) { }
376
377
378 //
379 // Operating switches
380 //
381
382 // Returns the current switch position
383 virtual isize getSwitch() const { return switchPos; }
384 bool switchIsNeutral() const { return getSwitch() == 0; }
385 bool switchIsLeft() const { return getSwitch() < 0; }
386 bool switchIsRight() const { return getSwitch() > 0; }
387
388 /* Returns a textual description for a switch position or nullptr if the
389 * switch cannot be positioned this way.
390 */
391 virtual const char *getSwitchDescription(isize pos) const { return ""; }
392 const char *getSwitchDescription() const { return getSwitchDescription(getSwitch()); }
393 bool validSwitchPosition(isize pos) const { return getSwitchDescription(pos) != nullptr; }
394
395 // Puts the switch in a certain position
396 virtual void setSwitch(isize pos);
397
398
399 //
400 // Operating LEDs
401 //
402
403 // Returns true if the cartridge has a LED
404 // bool hasLED() const { return traits.led; }
405
406 // Switches the LED on or off
407 virtual void setLED(bool value) { led = value; }
408
409
410 //
411 // Handling delegation calls
412 //
413
414 /* Emulator thread callback. This function is invoked by the expansion port.
415 * Only a few cartridges such as EpyxFastLoader will do some action here.
416 */
417 virtual void execute() { };
418
419 // Modifies the memory source lookup tables if required
420 virtual void updatePeekPokeLookupTables() { };
421
422 // Called when the C64 CPU is about to trigger an NMI
423 virtual void nmiWillTrigger() { }
424
425 // Called after the C64 CPU has processed the NMI instruction
426 virtual void nmiDidTrigger() { }
427};
428
429}
VirtualC64 project namespace.
Definition CmdQueue.cpp:16