23#include "DriveMemory.h"
31#include "RegressionTester.h"
32#include "RetroShell.h"
37#include "ControlPort.h"
39#include "ExpansionPort.h"
40#include "SerialPort.h"
51#include "CustomCartridges.h"
64#include "FileSystem.h"
73static constexpr bool isPrimarySlot(isize s) {
return s <= SLOT_SEC; }
74static constexpr bool isSecondarySlot(isize s) {
return s > SLOT_SEC && s <= SLOT_TER; }
75static constexpr bool isTertiarySlot(isize s) {
return s > SLOT_TER; }
78static constexpr Cycle NEVER = INT64_MAX;
81static constexpr double inspectionInterval = 0.1;
91class C64 final :
public CoreComponent,
public Inspectable<C64Info> {
93 friend class Emulator;
95 Descriptions descriptions = {
98 .description =
"Commodore 64"
101 .name =
"C64[run-ahead]",
102 .description =
"Commodore 64"
106 ConfigOptions options = {
120 C64Config config = {};
123 mutable EventSlotInfo slotInfo[SLOT_COUNT];
133 C64Memory mem = C64Memory(*
this);
134 CPU cpu = CPU(MOS_6510, *
this);
135 CIA1 cia1 = CIA1(*
this);
136 CIA2 cia2 = CIA2(*
this);
137 VICII vic = VICII(*
this);
138 SIDBridge sidBridge = SIDBridge(*
this);
141 AudioPort audioPort = AudioPort(*
this);
142 VideoPort videoPort = VideoPort(*
this);
143 PowerPort supply = PowerPort(*
this);
144 ControlPort port1 = ControlPort(*
this, PORT_1);
145 ControlPort port2 = ControlPort(*
this, PORT_2);
146 ExpansionPort expansionport = ExpansionPort(*
this);
147 SerialPort iec = SerialPort(*
this);
150 Keyboard keyboard = Keyboard(*
this);
151 Drive drive8 = Drive(*
this, 0);
152 Drive drive9 = Drive(*
this, 1);
153 ParCable parCable = ParCable(*
this);
154 Datasette datasette = Datasette(*
this);
155 Monitor monitor = Monitor(*
this);
158 MsgQueue msgQueue = MsgQueue();
161 RetroShell retroShell = RetroShell(*
this);
162 Debugger debugger = Debugger(*
this);
163 RegressionTester regressionTester = RegressionTester(*
this);
164 Recorder recorder = Recorder(*
this);
174 Cycle trigger[SLOT_COUNT] = { };
177 EventID eventid[SLOT_COUNT] = { };
180 i64 data[SLOT_COUNT] = { };
183 Cycle nextTrigger = NEVER;
198 RunLoopFlags flags = 0;
207 Snapshot *autoSnapshot =
nullptr;
208 Snapshot *userSnapshot =
nullptr;
210 typedef struct { Cycle trigger; i64 payload; } Alarm;
211 std::vector<Alarm> alarms;
236 bool ultimax =
false;
242 bool headless =
false;
248 bool isDirty =
false;
251 i64 durationOfOneCycle;
254 std::optional<u16> stepTo = { };
264 static string version();
267 static string build();
270 static const char *eventName(EventSlot slot, EventID
id);
279 C64(
class Emulator& ref, isize
id);
294 static Cycle usec(isize delay) {
return Cycle(delay * 1LL); }
295 static Cycle msec(isize delay) {
return Cycle(delay * 1000LL); }
296 static Cycle sec(
double delay) {
return Cycle(delay * 1000000LL); }
305 C64& operator= (
const C64& other) {
326 CLONE(regressionTester)
338 CLONE(durationOfOneCycle)
351 void serialize(T& worker)
387 if (isResetter(worker))
return;
391 << durationOfOneCycle
396 << config.speedAdjust
398 << config.snapshotDelay
402 void operator << (SerResetter &worker)
override;
403 void operator << (SerChecker &worker)
override { serialize(worker); }
404 void operator << (SerCounter &worker)
override { serialize(worker); }
405 void operator << (SerReader &worker)
override { serialize(worker); }
406 void operator << (SerWriter &worker)
override { serialize(worker); }
415 const Descriptions &getDescriptions()
const override {
return descriptions; }
416 void prefix()
const override;
420 void _dump(Category category, std::ostream& os)
const override;
421 void _reset(
bool hard)
override;
430 virtual void record()
const override;
431 void cacheInfo(C64Info &result)
const override;
433 EventSlotInfo getSlotInfo(isize nr)
const;
437 void inspectSlot(EventSlot nr)
const;
446 const ConfigOptions &getOptions()
const override {
return options; }
447 i64 getOption(
Option opt)
const override;
448 void checkOption(
Option opt, i64 value)
override;
449 void setOption(
Option opt, i64 value)
override;
458 const C64Config &getConfig()
const {
return config; }
461 void updateClockFrequency();
464 void markAsDirty() { isDirty =
true; }
467 bool getHeadless()
const {
return headless; }
468 void setHeadless(
bool value) { headless = value; }
471 void exportConfig(
const fs::path &path)
const;
472 void exportConfig(std::ostream& stream)
const;
481 InspectionTarget getInspectionTarget()
const;
485 void setInspectionTarget(InspectionTarget target);
486 void removeInspectionTarget() { setInspectionTarget(INSPECTION_NONE); }
496 isize load(
const u8 *buffer);
497 isize save(u8 *buffer);
507 void execute(
bool headless);
508 void executeHeadless() { execute(
true); }
509 template <
bool enable8,
bool enable9>
void execute();
510 template <
bool enable8,
bool enable9> alwaysinline
void executeCycle();
511 template <
bool enable8,
bool enable9>
void finishInstruction();
516 void fastForward(isize frames);
525 void _isReady() const throws override;
526 void _powerOn() override;
527 void _powerOff() override;
528 void _run() override;
529 void _pause() override;
530 void _halt() override;
531 void _warpOn() override;
532 void _warpOff() override;
533 void _trackOn() override;
534 void _trackOff() override;
543 bool getUltimax()
const {
return ultimax; }
544 void setUltimax(
bool b) { ultimax = b; }
549 void setFlag(u32 flags);
550 void clearFlag(u32 flags);
553 void signalBreakpoint() { setFlag(RL::BREAKPOINT); }
554 void signalWatchpoint() { setFlag(RL::WATCHPOINT); }
555 void signalJammed() { setFlag(RL::CPU_JAM); }
556 void signalStop() { setFlag(RL::STOP); }
559 void executeOneCycle();
577 void process(
const Cmd &cmd);
580 void processEvents(Cycle cycle);
583 template<EventSlot s>
bool hasEvent()
const {
return this->eventid[s] != (EventID)0; }
586 template<EventSlot s>
bool hasEvent(EventID
id)
const {
return this->eventid[s] == id; }
589 template<EventSlot s>
bool isPending()
const {
return this->trigger[s] != NEVER; }
592 template<EventSlot s>
bool isDue(Cycle cycle)
const {
return cycle >= this->trigger[s]; }
595 template<EventSlot s>
void scheduleAbs(Cycle cycle, EventID
id)
597 this->trigger[s] = cycle;
598 this->eventid[s] = id;
600 if (cycle < nextTrigger) nextTrigger = cycle;
602 if constexpr (isTertiarySlot(s)) {
603 if (cycle < trigger[SLOT_TER]) trigger[SLOT_TER] = cycle;
605 if constexpr (isSecondarySlot(s) || isTertiarySlot(s)) {
606 if (cycle < trigger[SLOT_SEC]) trigger[SLOT_SEC] = cycle;
610 template<EventSlot s>
void scheduleAbs(Cycle cycle, EventID
id, i64 data)
612 scheduleAbs<s>(cycle,
id);
613 this->data[s] = data;
616 template<EventSlot s>
void rescheduleAbs(Cycle cycle)
619 if (cycle < nextTrigger) nextTrigger = cycle;
621 if constexpr (isTertiarySlot(s)) {
622 if (cycle < trigger[SLOT_TER]) trigger[SLOT_TER] = cycle;
624 if constexpr (isSecondarySlot(s) || isTertiarySlot(s)) {
625 if (cycle < trigger[SLOT_SEC]) trigger[SLOT_SEC] = cycle;
629 template<EventSlot s>
void scheduleImm(EventID
id)
631 scheduleAbs<s>(cpu.clock,
id);
634 template<EventSlot s>
void scheduleImm(EventID
id, i64 data)
636 scheduleAbs<s>(cpu.clock,
id);
637 this->data[s] = data;
640 template<EventSlot s>
void scheduleRel(Cycle cycle, EventID
id) {
641 scheduleAbs<s>(cpu.clock + cycle,
id);
644 template<EventSlot s>
void scheduleRel(Cycle cycle, EventID
id, i64 data) {
645 scheduleAbs<s>(cpu.clock + cycle,
id, data);
648 template<EventSlot s>
void rescheduleRel(Cycle cycle) {
649 rescheduleAbs<s>(cpu.clock + cycle);
652 template<EventSlot s>
void scheduleInc(Cycle cycle, EventID
id)
654 scheduleAbs<s>(trigger[s] + cycle,
id);
657 template<EventSlot s>
void scheduleInc(Cycle cycle, EventID
id, i64 data)
659 scheduleAbs<s>(trigger[s] + cycle,
id);
660 this->data[s] = data;
663 template<EventSlot s>
void rescheduleInc(Cycle cycle)
665 rescheduleAbs<s>(trigger[s] + cycle);
668 template<EventSlot s>
void cancel()
670 eventid[s] = (EventID)0;
678 void processINSEvent(EventID
id);
688 MediaFile *takeSnapshot();
691 void loadSnapshot(
const MediaFile &snapshot)
throws;
696 void processSNPEvent(EventID
id);
699 void scheduleNextSNPEvent();
709 static RomTraits getRomTraits(u64 fnv);
710 RomTraits getRomTraits(RomType type)
const;
713 u32 romCRC32(RomType type)
const;
714 u64 romFNV64(RomType type)
const;
717 bool hasRom(RomType type)
const;
718 bool hasMega65Rom(RomType type)
const;
723 const char *mega65BasicRev()
const;
724 const char *mega65KernalRev()
const;
729 void loadRom(
const fs::path &path)
throws;
730 void loadRom(
const MediaFile &file);
733 void deleteRom(RomType type);
736 void saveRom(RomType rom,
const fs::path &path)
throws;
744 void flash(
const MediaFile &file)
throws;
745 void flash(
const MediaFile &file, isize item)
throws;
746 void flash(
const FileSystem &fs, isize item)
throws;
759 void setAlarmAbs(Cycle trigger, i64 payload);
760 void setAlarmRel(Cycle trigger, i64 payload);
763 void processAlarmEvent();
768 void scheduleNextAlarm();
778 static bool getDebugVariable(
DebugFlag flag);
779 static void setDebugVariable(
DebugFlag flag,
bool val);
785 u32 random(u32 seed);
Inspection interface.
Definition Inspectable.h:32
VirtualC64 project namespace.
Definition CmdQueue.cpp:16
DEBUG_FLAG
Definition EmulatorTypes.h:27
OPT
Configuration option.
Definition OptionTypes.h:26
@ OPT_EMU_SNAPSHOTS
Take a snapshots once in a while.
Definition OptionTypes.h:38
@ OPT_EMU_SPEED_ADJUST
Speed adjustment in percent.
Definition OptionTypes.h:37
@ OPT_EMU_WARP_MODE
Warp activation mode.
Definition OptionTypes.h:35
@ OPT_EMU_RUN_AHEAD
Number of run-ahead frames.
Definition OptionTypes.h:40
@ OPT_EMU_WARP_BOOT
Warp-boot time in seconds.
Definition OptionTypes.h:34
@ OPT_EMU_VSYNC
Adapt the frame rate to the VSYNC signal.
Definition OptionTypes.h:36
@ OPT_EMU_SNAPSHOT_DELAY
Delay between two snapshots in seconds.
Definition OptionTypes.h:39