1//============================================================================
2//
3// MM MM 6666 555555 0000 2222
4// MMMM MMMM 66 66 55 00 00 22 22
5// MM MMM MM 66 55 00 00 22
6// MM M MM 66666 55555 00 00 22222 -- "A 6502 Microprocessor Emulator"
7// MM MM 66 66 55 00 00 22
8// MM MM 66 66 55 55 00 00 22
9// MM MM 6666 5555 0000 222222
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 SYSTEM_HXX
19#define SYSTEM_HXX
20
21class Device;
22class M6502;
23class M6532;
24class TIA;
25class NullDevice;
26
27#include "bspf.hxx"
28#include "Device.hxx"
29#include "NullDev.hxx"
30#include "Random.hxx"
31#include "Serializable.hxx"
32
33/**
34 This class represents a system consisting of a 6502 microprocessor
35 and a set of devices. The devices are mapped into an addressing
36 space of 2^n bytes (1 <= n <= 16). The addressing space is broken
37 into 2^m byte pages (1 <= m <= n), where a page is the smallest unit
38 a device can use when installing itself in the system.
39
40 In general the addressing space will be 8192 (2^13) bytes for a
41 6507 based system and 65536 (2^16) bytes for a 6502 based system.
42
43 @author Bradford W. Mott
44*/
45class System : public Serializable
46{
47 public:
48 /**
49 Create a new system with an addressing space of 2^13 bytes and
50 pages of 2^6 bytes.
51 */
52 System(Random& random, M6502& m6502, M6532& m6532,
53 TIA& mTIA, Cartridge& mCart);
54 virtual ~System() = default;
55
56 // Mask to apply to an address before accessing memory
57 static constexpr uInt16 ADDRESS_MASK = (1 << 13) - 1;
58
59 // Amount to shift an address by to determine what page it's on
60 static constexpr uInt16 PAGE_SHIFT = 6;
61
62 // Size of a page
63 static constexpr uInt16 PAGE_SIZE = (1 << PAGE_SHIFT);
64
65 // Mask to apply to an address to obtain its page offset
66 static constexpr uInt16 PAGE_MASK = PAGE_SIZE - 1;
67
68 // Number of pages in the system
69 static constexpr uInt16 NUM_PAGES = 1 << (13 - PAGE_SHIFT);
70
71 public:
72 /**
73 Initialize system and all attached devices to known state.
74 */
75 void initialize();
76
77 /**
78 Reset the system cycle counter, the attached devices, and the
79 attached processor of the system.
80
81 @param autodetect A hint to devices that the system is currently
82 in autodetect mode. That is, the system is being
83 run to autodetect certain device settings before
84 actual emulation will begin. Certain devices may
85 use this hint to act differently under those
86 circumstances.
87 */
88 void reset(bool autodetect = false);
89
90 public:
91 /**
92 Answer the 6502 microprocessor attached to the system. If a
93 processor has not been attached calling this function will fail.
94
95 @return The attached 6502 microprocessor
96 */
97 M6502& m6502() const { return myM6502; }
98
99 /**
100 Answer the 6532 processor attached to the system. If a
101 processor has not been attached calling this function will fail.
102
103 @return The attached 6532 microprocessor
104 */
105 M6532& m6532() const { return myM6532; }
106
107 /**
108 Answer the TIA device attached to the system.
109
110 @return The attached TIA device
111 */
112 TIA& tia() const { return myTIA; }
113
114 /**
115 Answer the Cart attached to the system.
116
117 @return The attached cartridge
118 */
119 Cartridge& cart() const { return myCart; }
120
121 /**
122 Answer the random generator attached to the system.
123
124 @return The random generator
125 */
126 Random& randGenerator() const { return myRandom; }
127
128 /**
129 Get the null device associated with the system. Every system
130 has a null device associated with it that's used by pages which
131 aren't mapped to "real" devices.
132
133 @return The null device associated with the system
134 */
135 const NullDevice& nullDevice() const { return myNullDevice; }
136
137 public:
138 /**
139 Get the number of system cycles which have passed since the
140 system was created.
141
142 @return The number of system cycles which have passed
143 */
144 uInt64 cycles() const { return myCycles; }
145
146 /**
147 Increment the system cycles by the specified number of cycles.
148
149 @param amount The amount to add to the system cycles counter
150 */
151 void incrementCycles(uInt32 amount) { myCycles += amount; }
152
153 /**
154 Informs all attached devices that the console type has changed.
155 */
156 void consoleChanged(ConsoleTiming timing);
157
158 /**
159 Answers whether the system is currently in device autodetect mode.
160 */
161 bool autodetectMode() const { return mySystemInAutodetect; }
162
163 public:
164 /**
165 Get the current state of the data bus in the system. The current
166 state is the last data that was accessed by the system.
167
168 @return The data bus state
169 */
170 uInt8 getDataBusState() const { return myDataBusState; }
171
172 /**
173 Get the current state of the data bus in the system, taking into
174 account that certain bits are in Z-state (undriven). In those
175 cases, the bits are floating, but will usually be the same as the
176 last data bus value (the 'usually' is emulated by randomly driving
177 certain bits high).
178
179 However, some CMOS EPROM chips always drive Z-state bits high.
180 This is emulated by hmask, which specifies to push a specific
181 Z-state bit high.
182
183 @param zmask The bits which are in Z-state
184 @param hmask The bits which should always be driven high
185 @return The data bus state
186 */
187 uInt8 getDataBusState(uInt8 zmask, uInt8 hmask = 0x00) const
188 {
189 // For the pins that are floating, randomly decide which are high or low
190 // Otherwise, they're specifically driven high
191 return (myDataBusState | (randGenerator().next() | hmask)) & zmask;
192 }
193
194 /**
195 Get the byte at the specified address. No masking of the
196 address occurs before it's sent to the device mapped at
197 the address.
198
199 @param address The address from which the value should be loaded
200 @param flags Indicates that this address has the given flags
201 for type of access (CODE, DATA, GFX, etc)
202
203 @return The byte at the specified address
204 */
205 uInt8 peek(uInt16 address, uInt8 flags = 0);
206
207 /**
208 Change the byte at the specified address to the given value.
209 No masking of the address occurs before it's sent to the device
210 mapped at the address.
211
212 This method sets the 'page dirty' if the write succeeds. In the
213 case of direct-access pokes, the write always succeeds. Otherwise,
214 if the device is handling the poke, we depend on its return value
215 for this information.
216
217 @param address The address where the value should be stored
218 @param value The value to be stored at the address
219 */
220 void poke(uInt16 address, uInt8 value, uInt8 flags = 0);
221
222 /**
223 Lock/unlock the data bus. When the bus is locked, peek() and
224 poke() don't update the bus state. The bus should be unlocked
225 while the CPU is running (normal emulation, or when the debugger
226 is stepping/advancing). It should be locked while the debugger
227 is active but not running the CPU. This is so the debugger can
228 use System.peek() to examine memory/registers without changing
229 the state of the system.
230 */
231 void lockDataBus() { myDataBusLocked = true; }
232 void unlockDataBus() { myDataBusLocked = false; }
233
234 /**
235 Access and modify the disassembly type flags for the given
236 address. Note that while any flag can be used, the disassembly
237 only really acts on CODE/GFX/PGFX/DATA/ROW.
238 */
239 uInt8 getAccessFlags(uInt16 address) const;
240 void setAccessFlags(uInt16 address, uInt8 flags);
241
242 public:
243 /**
244 Describes how a page can be accessed
245 */
246 enum class PageAccessType : uInt8 {
247 READ = 1 << 0,
248 WRITE = 1 << 1,
249 READWRITE = READ | WRITE
250 };
251
252 /**
253 Structure used to specify access methods for a page
254 */
255 struct PageAccess
256 {
257 /**
258 Pointer to a block of memory or the null pointer. The null pointer
259 indicates that the device's peek method should be invoked for reads
260 to this page, while other values are the base address of an array
261 to directly access for reads to this page.
262 */
263 uInt8* directPeekBase;
264
265 /**
266 Pointer to a block of memory or the null pointer. The null pointer
267 indicates that the device's poke method should be invoked for writes
268 to this page, while other values are the base address of an array
269 to directly access for pokes to this page.
270 */
271 uInt8* directPokeBase;
272
273 /**
274 Pointer to a lookup table for marking an address as CODE. A CODE
275 section is defined as any address that appears in the program
276 counter. Currently, this is used by the debugger/disassembler to
277 conclusively determine if a section of address space is CODE, even
278 if the disassembler failed to mark it as such.
279 */
280 uInt8* codeAccessBase;
281
282 /**
283 Pointer to the device associated with this page or to the system's
284 null device if the page hasn't been mapped to a device.
285 */
286 Device* device;
287
288 /**
289 The manner in which the pages are accessed by the system
290 (READ, WRITE, READWRITE)
291 */
292 PageAccessType type;
293
294 // Constructors
295 PageAccess()
296 : directPeekBase(nullptr),
297 directPokeBase(nullptr),
298 codeAccessBase(nullptr),
299 device(nullptr),
300 type(System::PageAccessType::READ) { }
301
302 PageAccess(Device* dev, PageAccessType access)
303 : directPeekBase(nullptr),
304 directPokeBase(nullptr),
305 codeAccessBase(nullptr),
306 device(dev),
307 type(access) { }
308 };
309
310 /**
311 Set the page accessing method for the specified address.
312
313 @param addr The address/page accessing methods should be set for
314 @param access The accessing methods to be used by the page
315 */
316 void setPageAccess(uInt16 addr, const PageAccess& access) {
317 myPageAccessTable[(addr & ADDRESS_MASK) >> PAGE_SHIFT] = access;
318 }
319
320 /**
321 Get the page accessing method for the specified address.
322
323 @param addr The address/page to get accessing methods for
324 @return The accessing methods used by the page
325 */
326 const PageAccess& getPageAccess(uInt16 addr) const {
327 return myPageAccessTable[(addr & ADDRESS_MASK) >> PAGE_SHIFT];
328 }
329
330 /**
331 Get the page type for the given address.
332
333 @param addr The address contained in the page in questions
334 @return The type of page that contains the given address
335 */
336 System::PageAccessType getPageAccessType(uInt16 addr) const {
337 return myPageAccessTable[(addr & ADDRESS_MASK) >> PAGE_SHIFT].type;
338 }
339
340 /**
341 Mark the page containing this address as being dirty.
342
343 @param addr Determines the page that is dirty
344 */
345 void setDirtyPage(uInt16 addr) {
346 myPageIsDirtyTable[(addr & ADDRESS_MASK) >> PAGE_SHIFT] = true;
347 }
348
349 /**
350 Answer whether any pages in given range of addresses have been
351 marked as dirty.
352
353 @param start_addr The start address; determines the start page
354 @param end_addr The end address; determines the end page
355 */
356 bool isPageDirty(uInt16 start_addr, uInt16 end_addr) const;
357
358 /**
359 Mark all pages as clean (ie, turn off the dirty flag).
360 */
361 void clearDirtyPages();
362
363 /**
364 Save the current state of this system to the given Serializer.
365
366 @param out The Serializer object to use
367 @return False on any errors, else true
368 */
369 bool save(Serializer& out) const override;
370
371 /**
372 Load the current state of this system from the given Serializer.
373
374 @param in The Serializer object to use
375 @return False on any errors, else true
376 */
377 bool load(Serializer& in) override;
378
379 private:
380 // The system RNG
381 Random& myRandom;
382
383 // 6502 processor attached to the system
384 M6502& myM6502;
385
386 // 6532 processor attached to the system
387 M6532& myM6532;
388
389 // TIA device attached to the system
390 TIA& myTIA;
391
392 // Cartridge device attached to the system
393 Cartridge& myCart;
394
395 // Number of system cycles executed since last reset
396 uInt64 myCycles;
397
398 // Null device to use for page which are not installed
399 NullDevice myNullDevice;
400
401 // The list of PageAccess structures
402 std::array<PageAccess, NUM_PAGES> myPageAccessTable;
403
404 // The list of dirty pages
405 std::array<bool, NUM_PAGES> myPageIsDirtyTable;
406
407 // The current state of the Data Bus
408 uInt8 myDataBusState;
409
410 // Whether or not peek() updates the data bus state. This
411 // is true during normal emulation, and false when the
412 // debugger is active.
413 bool myDataBusLocked;
414
415 // Whether autodetection is currently running (ie, the emulation
416 // core is attempting to autodetect display settings, cart modes, etc)
417 // Some parts of the codebase need to act differently in such a case
418 bool mySystemInAutodetect;
419
420 private:
421 // Following constructors and assignment operators not supported
422 System() = delete;
423 System(const System&) = delete;
424 System(System&&) = delete;
425 System& operator=(const System&) = delete;
426 System& operator=(System&&) = delete;
427};
428
429#endif
430