Skip to content

Commit

Permalink
Ported joystick autofire code from vAmiga
Browse files Browse the repository at this point in the history
  • Loading branch information
dirkwhoffmann committed Aug 31, 2024
1 parent b1eb0db commit c385d55
Show file tree
Hide file tree
Showing 6 changed files with 126 additions and 74 deletions.
6 changes: 3 additions & 3 deletions Emulator/Components/C64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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, " ");
}
Expand Down Expand Up @@ -1152,12 +1150,14 @@ C64::processEvents(Cycle cycle)
if (isDue<SLOT_RXD>(cycle)) {
userPort.rs232.processRxdEvent();
}
/*
if (isDue<SLOT_AFI1>(cycle)) {
port1.joystick.processEvent();
}
if (isDue<SLOT_AFI2>(cycle)) {
port2.joystick.processEvent();
}
*/
if (isDue<SLOT_MOT>(cycle)) {
datasette.processMotEvent(eventid[SLOT_MOT]);
}
Expand Down
5 changes: 3 additions & 2 deletions Emulator/Components/Ports/ControlPort.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
114 changes: 71 additions & 43 deletions Emulator/Peripherals/Joystick/Joystick.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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<SLOT_AFI1>() : c64.cancel<SLOT_AFI2>();
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<SLOT_AFI1>() : c64.isPending<SLOT_AFI2>();
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 <SLOT_AFI1> (bullets) : reload <SLOT_AFI2> (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 <EventSlot Slot> void
Joystick::reload(isize bullets)
void
Joystick::stopAutofire()
{
if (bullets > 0 && config.autofire) {
trace(JOY_DEBUG, "stopAutofire()\n");

if (c64.isPending<Slot>()) {
// 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<Slot>(cycle, AFI_FIRE, bullets);
}
reload(config.autofireBursts ? config.autofireBullets : INT_MAX);

} else {

// Release the fire button and cancel any pending event
c64.cancel<Slot>();
button = false;
reload(0);
}
}

void
Joystick::reload(isize bullets)
{
bulletCounter = bullets;
}

}
63 changes: 43 additions & 20 deletions Emulator/Peripherals/Joystick/Joystick.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,13 @@ class Joystick final : public SubComponent, public Inspectable<JoystickInfo> {
// 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
Expand All @@ -69,11 +76,14 @@ class Joystick final : public SubComponent, public Inspectable<JoystickInfo> {

Joystick& operator= (const Joystick& other) {

CLONE(config)

CLONE(button)
CLONE(axisX)
CLONE(axisY)

CLONE(config)
CLONE(bulletCounter)
CLONE(nextAutofireFrame)
CLONE(nextAutofireReleaseFrame)

return *this;
}
Expand All @@ -87,14 +97,28 @@ class Joystick final : public SubComponent, public Inspectable<JoystickInfo> {

template <class T> 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); }
Expand Down Expand Up @@ -150,25 +174,24 @@ class Joystick final : public SubComponent, public Inspectable<JoystickInfo> {
// 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 <EventSlot Slot> void reload(isize bullets);
};

}
2 changes: 1 addition & 1 deletion Emulator/config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
10 changes: 5 additions & 5 deletions GUI/XIB files/Configuration.xib
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@
<windowStyleMask key="styleMask" titled="YES" resizable="YES"/>
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
<rect key="contentRect" x="196" y="240" width="646" height="486"/>
<rect key="screenRect" x="0.0" y="0.0" width="1728" height="1079"/>
<rect key="screenRect" x="0.0" y="0.0" width="1496" height="933"/>
<value key="minSize" type="size" width="646" height="486"/>
<value key="maxSize" type="size" width="646" height="486"/>
<view key="contentView" wantsLayer="YES" id="EiT-Mj-1SZ">
Expand Down Expand Up @@ -1496,18 +1496,18 @@ Gw
</connections>
</slider>
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="ZNc-01-koq">
<rect key="frame" x="566" y="131" width="26" height="14"/>
<rect key="frame" x="564" y="131" width="29" height="14"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Fast" id="uod-jl-p8I">
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Slow" id="uod-jl-p8I">
<font key="font" metaFont="menu" size="11"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="1dt-2Z-WSU">
<rect key="frame" x="438" y="131" width="29" height="14"/>
<rect key="frame" x="438" y="131" width="26" height="14"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Slow" id="SbM-3v-tQ2">
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Fast" id="SbM-3v-tQ2">
<font key="font" metaFont="menu" size="11"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
Expand Down

0 comments on commit c385d55

Please sign in to comment.