diff --git a/Emulator/Components/C64.cpp b/Emulator/Components/C64.cpp index b4a471e78..f515eebe0 100644 --- a/Emulator/Components/C64.cpp +++ b/Emulator/Components/C64.cpp @@ -241,8 +241,6 @@ C64::eventName(EventSlot slot, EventID id) void C64::prefix(isize level, const char *component, isize line) const { - fprintf(stderr, "[%lld] (%3d,%3d) %04X ", frame, scanline, rasterCycle, cpu.getPC0()); - if (level) { if (level >= 2) { @@ -260,7 +258,7 @@ C64::prefix(isize level, const char *component, isize line) const } if (level >= 5) { - fprintf(stderr, " %s%s", (cpu.irqLine ? "*" : "-"), (cpu.nmiLine ? "+" : "-")); + fprintf(stderr, " [%s%s]", (cpu.irqLine ? "*" : "-"), (cpu.nmiLine ? "+" : "-")); } fprintf(stderr, " "); } @@ -1152,12 +1150,14 @@ C64::processEvents(Cycle cycle) if (isDue(cycle)) { userPort.rs232.processRxdEvent(); } + /* if (isDue(cycle)) { port1.joystick.processEvent(); } if (isDue(cycle)) { port2.joystick.processEvent(); } + */ if (isDue(cycle)) { datasette.processMotEvent(eventid[SLOT_MOT]); } diff --git a/Emulator/Components/Ports/ControlPort.cpp b/Emulator/Components/Ports/ControlPort.cpp index f658d6be3..c4868e125 100644 --- a/Emulator/Components/Ports/ControlPort.cpp +++ b/Emulator/Components/Ports/ControlPort.cpp @@ -22,8 +22,9 @@ ControlPort::execute() { switch (device) { - case CPDEVICE_MOUSE: mouse.execute(); break; - + case CPDEVICE_MOUSE: mouse.execute(); break; + case CPDEVICE_JOYSTICK: joystick.eofHandler(); break; + default: break; } diff --git a/Emulator/Peripherals/Joystick/Joystick.cpp b/Emulator/Peripherals/Joystick/Joystick.cpp index ee9159bdc..2cee9e042 100644 --- a/Emulator/Peripherals/Joystick/Joystick.cpp +++ b/Emulator/Peripherals/Joystick/Joystick.cpp @@ -52,15 +52,33 @@ Joystick::trigger(GamePadAction event) case PRESS_FIRE: - button = true; - + // If autofire is enabled... if (config.autofire) { - if (isAutofiring() && !config.autofireBursts) { - reload(0); // Stop shooting + // ...check if we are currently firing. + if (isAutofiring()) { + + // If yes, the required action depends on the autofire mode. + if (config.autofireBursts) { + + // In burst mode, reload the magazine. + reload(config.autofireBullets); + + } else { + + // Otherwise, stop firing. + stopAutofire(); + } + } else { - reload(); // Start or continue shooting + + // We are currently not firing. Initiate the first shot. + startAutofire(); } + + } else { + + button = true; } break; @@ -77,71 +95,81 @@ Joystick::trigger(GamePadAction event) } void -Joystick::processEvent() +Joystick::eofHandler() { - // Get the number of remaining bullets - auto shots = objid == PORT_1 ? (isize)c64.data[SLOT_AFI1] : (isize)c64.data[SLOT_AFI2]; - assert(shots > 0); - - // Cancel the current event - objid == PORT_1 ? c64.cancel() : c64.cancel(); + if (isAutofiring()) { - // Fire and reload - if (button) { + if (i64(c64.frame) == nextAutofireFrame) { - button = false; - reload(shots - 1); + debug(JOY_DEBUG, "Autofire press\n"); + button = true; + nextAutofireReleaseFrame = nextAutofireFrame + config.autofireDelay; + } - } else { + if (i64(c64.frame) == nextAutofireReleaseFrame) { - button = true; - reload(shots); + debug(JOY_DEBUG, "Autofire release\n"); + button = false; + if (--bulletCounter > 0) { + nextAutofireFrame = nextAutofireReleaseFrame + config.autofireDelay; + } else { + stopAutofire(); + } + } } } bool Joystick::isAutofiring() { - return objid == PORT_1 ? c64.isPending() : c64.isPending(); + return bulletCounter > 0; } void -Joystick::reload() +Joystick::startAutofire() { - reload(config.autofireBursts ? config.autofireBullets : LONG_MAX); -} + debug(JOY_DEBUG, "startAutofire()\n"); -void -Joystick::reload(isize bullets) -{ - objid == PORT_1 ? reload (bullets) : reload (bullets); + // Load magazine + reload(config.autofireBursts ? config.autofireBullets : INT_MAX); + + // Fire the first shot + button = true; + + // Schedule the release event + nextAutofireReleaseFrame = c64.frame + config.autofireDelay; } -template void -Joystick::reload(isize bullets) +void +Joystick::stopAutofire() { - if (bullets > 0 && config.autofire) { + trace(JOY_DEBUG, "stopAutofire()\n"); - if (c64.isPending()) { + // Release button and empty the bullet counter + button = false; + bulletCounter = 0; - // Just add bullets (shooting is in progress) - trace(JOY_DEBUG, "Filling up to %ld bullets\n", bullets); - c64.data[Slot] = bullets; + // Clear all events + nextAutofireFrame = nextAutofireReleaseFrame = 0; +} - } else { +void +Joystick::reload() +{ + if (config.autofire) { - // Fire the first shot - auto cycle = config.autofireDelay * vic.getCyclesPerFrame(); - trace(JOY_DEBUG, "Next auto-fire event in %ld cycles\n", cycle); - c64.scheduleRel(cycle, AFI_FIRE, bullets); - } + reload(config.autofireBursts ? config.autofireBullets : INT_MAX); } else { - // Release the fire button and cancel any pending event - c64.cancel(); - button = false; + reload(0); } } +void +Joystick::reload(isize bullets) +{ + bulletCounter = bullets; +} + } diff --git a/Emulator/Peripherals/Joystick/Joystick.h b/Emulator/Peripherals/Joystick/Joystick.h index efa72e3c5..bcb1679b4 100644 --- a/Emulator/Peripherals/Joystick/Joystick.h +++ b/Emulator/Peripherals/Joystick/Joystick.h @@ -58,6 +58,13 @@ class Joystick final : public SubComponent, public Inspectable { // Vertical joystick position (-1 = up, 1 = down, 0 = released) int axisY = 0; + // Bullet counter used in autofire mode + isize bulletCounter = 0; + + // Next frame to auto-press or auto-release the fire button + i64 nextAutofireFrame = 0; + i64 nextAutofireReleaseFrame = 0; + // // Methods @@ -69,11 +76,14 @@ class Joystick final : public SubComponent, public Inspectable { Joystick& operator= (const Joystick& other) { + CLONE(config) + CLONE(button) CLONE(axisX) CLONE(axisY) - - CLONE(config) + CLONE(bulletCounter) + CLONE(nextAutofireFrame) + CLONE(nextAutofireReleaseFrame) return *this; } @@ -87,14 +97,28 @@ class Joystick final : public SubComponent, public Inspectable { template void serialize(T& worker) { - if (isResetter(worker)) return; - - worker - - << config.autofire - << config.autofireBursts - << config.autofireBullets - << config.autofireDelay; + if (isResetter(worker)) { + + worker + + << button + << axisX + << axisY + << bulletCounter + << nextAutofireFrame + << nextAutofireReleaseFrame; + + } else { + + /* + worker + + << config.autofire + << config.autofireBursts + << config.autofireBullets + << config.autofireDelay; + */ + } } void operator << (SerChecker &worker) override { serialize(worker); } void operator << (SerCounter &worker) override { serialize(worker); } @@ -150,25 +174,24 @@ class Joystick final : public SubComponent, public Inspectable { // Triggers a gamepad event void trigger(GamePadAction event); + // To be called after each frame + void eofHandler(); + // // Auto fire // -public: - - // Processes an auto-fire event - void processEvent(); - -private: - - // Indicates if the device is currently auto-firing + // Checks whether autofiring is active bool isAutofiring(); - // Reloads the auto-fire gun + // Starts or stops autofire mode + void startAutofire(); + void stopAutofire(); + + // Reloads the autofire magazine void reload(); void reload(isize bullets); - template void reload(isize bullets); }; } diff --git a/Emulator/config.cpp b/Emulator/config.cpp index d4a401731..ea7b7ab1e 100644 --- a/Emulator/config.cpp +++ b/Emulator/config.cpp @@ -70,7 +70,7 @@ debugflag CRT_DEBUG = 0; debugflag FILE_DEBUG = 0; // Peripherals -debugflag JOY_DEBUG = 0; +debugflag JOY_DEBUG = 1; debugflag DRV_DEBUG = 0; debugflag TAP_DEBUG = 0; debugflag KBD_DEBUG = 0; diff --git a/GUI/XIB files/Configuration.xib b/GUI/XIB files/Configuration.xib index 9f038a2da..2cc24eb0d 100644 --- a/GUI/XIB files/Configuration.xib +++ b/GUI/XIB files/Configuration.xib @@ -152,7 +152,7 @@ - + @@ -1496,18 +1496,18 @@ Gw - + - + - + - +