in cores/snes/controls.cpp [2034:2713]
void S9xApplyCommand (s9xcommand_t cmd, int16 data1, int16 data2)
{
int i;
switch (cmd.type)
{
case S9xNoMapping:
return;
case S9xButtonJoypad:
if (cmd.button.joypad.toggle)
{
if (!data1)
return;
uint16 r = cmd.button.joypad.buttons;
if (cmd.button.joypad.turbo) joypad[cmd.button.joypad.idx].toggleturbo ^= r;
if (cmd.button.joypad.sticky) joypad[cmd.button.joypad.idx].togglestick ^= r;
}
else
{
uint16 r, s, t, st;
s = t = st = 0;
r = cmd.button.joypad.buttons;
st = r & joypad[cmd.button.joypad.idx].togglestick & joypad[cmd.button.joypad.idx].toggleturbo;
r ^= st;
t = r & joypad[cmd.button.joypad.idx].toggleturbo;
r ^= t;
s = r & joypad[cmd.button.joypad.idx].togglestick;
r ^= s;
if (cmd.button.joypad.turbo && cmd.button.joypad.sticky)
{
uint16 x = r; r = st; st = x;
x = s; s = t; t = x;
}
else
if (cmd.button.joypad.turbo)
{
uint16 x = r; r = t; t = x;
x = s; s = st; st = x;
}
else
if (cmd.button.joypad.sticky)
{
uint16 x = r; r = s; s = x;
x = t; t = st; st = x;
}
if (data1)
{
if (!Settings.UpAndDown) // if up+down isn't allowed,
{
if (cmd.button.joypad.buttons & (SNES_LEFT_MASK | SNES_RIGHT_MASK))
{
// if we're pressing left or right, then unpress and unturbo them both first
// so we don't end up hittnig left AND right accidentally.
// Note though that the user can still do it on purpose, if Settings.UpAndDown = true.
// This is a feature, look up glitches in tLoZ:aLttP to find out why.
joypad[cmd.button.joypad.idx].buttons &= ~(SNES_LEFT_MASK | SNES_RIGHT_MASK);
joypad[cmd.button.joypad.idx].turbos &= ~(SNES_LEFT_MASK | SNES_RIGHT_MASK);
}
if (cmd.button.joypad.buttons & (SNES_UP_MASK | SNES_DOWN_MASK))
{
// and ditto for up/down
joypad[cmd.button.joypad.idx].buttons &= ~(SNES_UP_MASK | SNES_DOWN_MASK);
joypad[cmd.button.joypad.idx].turbos &= ~(SNES_UP_MASK | SNES_DOWN_MASK);
}
}
joypad[cmd.button.joypad.idx].buttons |= r;
joypad[cmd.button.joypad.idx].turbos |= t;
joypad[cmd.button.joypad.idx].buttons ^= s;
joypad[cmd.button.joypad.idx].buttons &= ~(joypad[cmd.button.joypad.idx].turbos & st);
joypad[cmd.button.joypad.idx].turbos ^= st;
}
else
{
joypad[cmd.button.joypad.idx].buttons &= ~r;
joypad[cmd.button.joypad.idx].buttons &= ~(joypad[cmd.button.joypad.idx].turbos & t);
joypad[cmd.button.joypad.idx].turbos &= ~t;
}
}
return;
case S9xButtonMouse:
i = 0;
if (cmd.button.mouse.left ) i |= 0x40;
if (cmd.button.mouse.right) i |= 0x80;
if (data1)
mouse[cmd.button.mouse.idx].buttons |= i;
else
mouse[cmd.button.mouse.idx].buttons &= ~i;
return;
case S9xButtonSuperscope:
i = 0;
if (cmd.button.scope.fire ) i |= SUPERSCOPE_FIRE;
if (cmd.button.scope.cursor ) i |= SUPERSCOPE_CURSOR;
if (cmd.button.scope.pause ) i |= SUPERSCOPE_PAUSE;
if (cmd.button.scope.aim_offscreen) i |= SUPERSCOPE_OFFSCREEN;
if (data1)
{
superscope.phys_buttons |= i;
if (cmd.button.scope.turbo)
{
superscope.phys_buttons ^= SUPERSCOPE_TURBO;
if (superscope.phys_buttons & SUPERSCOPE_TURBO)
superscope.next_buttons |= superscope.phys_buttons & (SUPERSCOPE_FIRE | SUPERSCOPE_CURSOR);
else
superscope.next_buttons &= ~(SUPERSCOPE_FIRE | SUPERSCOPE_CURSOR);
}
superscope.next_buttons |= i & (SUPERSCOPE_FIRE | SUPERSCOPE_CURSOR | SUPERSCOPE_PAUSE);
if ((superscope.next_buttons & (SUPERSCOPE_FIRE | SUPERSCOPE_CURSOR)) && curcontrollers[1] == SUPERSCOPE && !(superscope.phys_buttons & SUPERSCOPE_OFFSCREEN))
DoGunLatch(superscope.x, superscope.y);
}
else
{
superscope.phys_buttons &= ~i;
superscope.next_buttons &= SUPERSCOPE_OFFSCREEN | ~i;
}
return;
case S9xButtonJustifier:
i = 0;
if (cmd.button.justifier.trigger) i |= JUSTIFIER_TRIGGER;
if (cmd.button.justifier.start ) i |= JUSTIFIER_START;
if (cmd.button.justifier.aim_offscreen) justifier.offscreen[cmd.button.justifier.idx] = data1 ? 1 : 0;
i >>= cmd.button.justifier.idx;
if (data1)
justifier.buttons |= i;
else
justifier.buttons &= ~i;
return;
case S9xButtonCommand:
if (((enum command_numbers) cmd.button.command) >= LAST_COMMAND)
{
fprintf(stderr, "Unknown command %04x\n", cmd.button.command);
return;
}
if (!data1)
{
switch (i = cmd.button.command)
{
case EmuTurbo:
Settings.TurboMode = FALSE;
break;
}
}
else
{
switch ((enum command_numbers) (i = cmd.button.command))
{
case ExitEmu:
S9xExit();
break;
case Reset:
S9xReset();
break;
case SoftReset:
S9xSoftReset();
break;
case EmuTurbo:
Settings.TurboMode = TRUE;
break;
case ToggleEmuTurbo:
Settings.TurboMode = !Settings.TurboMode;
DisplayStateChange("Turbo mode", Settings.TurboMode);
break;
case ClipWindows:
Settings.DisableGraphicWindows = !Settings.DisableGraphicWindows;
DisplayStateChange("Graphic clip windows", !Settings.DisableGraphicWindows);
break;
case Debugger:
#ifdef DEBUGGER
CPU.Flags |= DEBUG_MODE_FLAG;
#endif
break;
case IncFrameRate:
if (Settings.SkipFrames == AUTO_FRAMERATE)
Settings.SkipFrames = 1;
else
if (Settings.SkipFrames < 10)
Settings.SkipFrames++;
if (Settings.SkipFrames == AUTO_FRAMERATE)
S9xSetInfoString("Auto frame skip");
else
{
sprintf(buf, "Frame skip: %d", Settings.SkipFrames - 1);
S9xSetInfoString(buf);
}
break;
case DecFrameRate:
if (Settings.SkipFrames <= 1)
Settings.SkipFrames = AUTO_FRAMERATE;
else
if (Settings.SkipFrames != AUTO_FRAMERATE)
Settings.SkipFrames--;
if (Settings.SkipFrames == AUTO_FRAMERATE)
S9xSetInfoString("Auto frame skip");
else
{
sprintf(buf, "Frame skip: %d", Settings.SkipFrames - 1);
S9xSetInfoString(buf);
}
break;
case IncEmuTurbo:
if (Settings.TurboSkipFrames < 20)
Settings.TurboSkipFrames += 1;
else
if (Settings.TurboSkipFrames < 200)
Settings.TurboSkipFrames += 5;
sprintf(buf, "Turbo frame skip: %d", Settings.TurboSkipFrames);
S9xSetInfoString(buf);
break;
case DecEmuTurbo:
if (Settings.TurboSkipFrames > 20)
Settings.TurboSkipFrames -= 5;
else
if (Settings.TurboSkipFrames > 0)
Settings.TurboSkipFrames -= 1;
sprintf(buf, "Turbo frame skip: %d", Settings.TurboSkipFrames);
S9xSetInfoString(buf);
break;
case IncFrameTime: // Increase emulated frame time by 1ms
Settings.FrameTime += 1000;
sprintf(buf, "Emulated frame time: %dms", Settings.FrameTime / 1000);
S9xSetInfoString(buf);
break;
case DecFrameTime: // Decrease emulated frame time by 1ms
if (Settings.FrameTime >= 1000)
Settings.FrameTime -= 1000;
sprintf(buf, "Emulated frame time: %dms", Settings.FrameTime / 1000);
S9xSetInfoString(buf);
break;
case IncTurboSpeed:
if (turbo_time >= 120)
break;
turbo_time++;
sprintf(buf, "Turbo speed: %d", turbo_time);
S9xSetInfoString(buf);
break;
case DecTurboSpeed:
if (turbo_time <= 1)
break;
turbo_time--;
sprintf(buf, "Turbo speed: %d", turbo_time);
S9xSetInfoString(buf);
break;
case LoadFreezeFile:
S9xUnfreezeGame(S9xChooseFilename(TRUE));
break;
case SaveFreezeFile:
S9xFreezeGame(S9xChooseFilename(FALSE));
break;
case LoadOopsFile:
{
char filename[PATH_MAX + 1];
char drive[_MAX_DRIVE + 1], dir[_MAX_DIR + 1], def[_MAX_FNAME + 1], ext[_MAX_EXT + 1];
_splitpath(Memory.ROMFilename, drive, dir, def, ext);
snprintf(filename, PATH_MAX + 1, "%s%s%s.%.*s", S9xGetDirectory(SNAPSHOT_DIR), SLASH_STR, def, _MAX_EXT - 1, "oops");
if (S9xUnfreezeGame(filename))
{
sprintf(buf, "%s.%.*s loaded", def, _MAX_EXT - 1, "oops");
S9xSetInfoString (buf);
}
else
S9xMessage(S9X_ERROR, S9X_FREEZE_FILE_NOT_FOUND, "Oops file not found");
break;
}
case Pause:
Settings.Paused = !Settings.Paused;
DisplayStateChange("Pause", Settings.Paused);
#if defined(NETPLAY_SUPPORT) && !defined(__WIN32__)
S9xNPSendPause(Settings.Paused);
#endif
break;
case QuickLoad000:
case QuickLoad001:
case QuickLoad002:
case QuickLoad003:
case QuickLoad004:
case QuickLoad005:
case QuickLoad006:
case QuickLoad007:
case QuickLoad008:
case QuickLoad009:
case QuickLoad010:
{
char filename[PATH_MAX + 1];
char drive[_MAX_DRIVE + 1], dir[_MAX_DIR + 1], def[_MAX_FNAME + 1], ext[_MAX_EXT + 1];
_splitpath(Memory.ROMFilename, drive, dir, def, ext);
snprintf(filename, PATH_MAX + 1, "%s%s%s.%03d", S9xGetDirectory(SNAPSHOT_DIR), SLASH_STR, def, i - QuickLoad000);
if (S9xUnfreezeGame(filename))
{
sprintf(buf, "%s.%03d loaded", def, i - QuickLoad000);
S9xSetInfoString(buf);
}
else
S9xMessage(S9X_ERROR, S9X_FREEZE_FILE_NOT_FOUND, "Freeze file not found");
break;
}
case QuickSave000:
case QuickSave001:
case QuickSave002:
case QuickSave003:
case QuickSave004:
case QuickSave005:
case QuickSave006:
case QuickSave007:
case QuickSave008:
case QuickSave009:
case QuickSave010:
{
char filename[PATH_MAX + 1];
char drive[_MAX_DRIVE + 1], dir[_MAX_DIR + 1], def[_MAX_FNAME + 1], ext[_MAX_EXT + 1];
_splitpath(Memory.ROMFilename, drive, dir, def, ext);
snprintf(filename, PATH_MAX + 1, "%s%s%s.%03d", S9xGetDirectory(SNAPSHOT_DIR), SLASH_STR, def, i - QuickSave000);
sprintf(buf, "%s.%03d saved", def, i - QuickSave000);
S9xSetInfoString(buf);
S9xFreezeGame(filename);
break;
}
case SaveSPC:
S9xDumpSPCSnapshot();
break;
case SoundChannel0:
case SoundChannel1:
case SoundChannel2:
case SoundChannel3:
case SoundChannel4:
case SoundChannel5:
case SoundChannel6:
case SoundChannel7:
S9xToggleSoundChannel(i - SoundChannel0);
sprintf(buf, "Sound channel %d toggled", i - SoundChannel0);
S9xSetInfoString(buf);
break;
case SoundChannelsOn:
S9xToggleSoundChannel(8);
S9xSetInfoString("All sound channels on");
break;
case ToggleBG0:
Settings.BG_Forced ^= 1;
DisplayStateChange("BG#0", !(Settings.BG_Forced & 1));
break;
case ToggleBG1:
Settings.BG_Forced ^= 2;
DisplayStateChange("BG#1", !(Settings.BG_Forced & 2));
break;
case ToggleBG2:
Settings.BG_Forced ^= 4;
DisplayStateChange("BG#2", !(Settings.BG_Forced & 4));
break;
case ToggleBG3:
Settings.BG_Forced ^= 8;
DisplayStateChange("BG#3", !(Settings.BG_Forced & 8));
break;
case ToggleSprites:
Settings.BG_Forced ^= 16;
DisplayStateChange("Sprites", !(Settings.BG_Forced & 16));
break;
case ToggleTransparency:
Settings.Transparency = !Settings.Transparency;
DisplayStateChange("Transparency effects", Settings.Transparency);
break;
case SwapJoypads:
if ((curcontrollers[0] != NONE && !(curcontrollers[0] >= JOYPAD0 && curcontrollers[0] <= JOYPAD7)))
{
S9xSetInfoString("Cannot swap pads: port 1 is not a joypad");
break;
}
if ((curcontrollers[1] != NONE && !(curcontrollers[1] >= JOYPAD0 && curcontrollers[1] <= JOYPAD7)))
{
S9xSetInfoString("Cannot swap pads: port 2 is not a joypad");
break;
}
newcontrollers[1] = curcontrollers[0];
newcontrollers[0] = curcontrollers[1];
strcpy(buf, "Swap pads: P1=");
i = 14;
if (newcontrollers[0] == NONE)
{
strcpy(buf + i, "<none>");
i += 6;
}
else
{
sprintf(buf + i, "Joypad%d", newcontrollers[0] - JOYPAD0 + 1);
i += 7;
}
strcpy(buf + i, " P2=");
i += 4;
if (newcontrollers[1] == NONE)
strcpy(buf + i, "<none>");
else
sprintf(buf + i, "Joypad%d", newcontrollers[1] - JOYPAD0 + 1);
S9xSetInfoString(buf);
break;
case SeekToFrame:
break;
case LAST_COMMAND:
break;
}
}
return;
case S9xPointer:
if (cmd.pointer.aim_mouse0)
{
mouse[0].cur_x = data1;
mouse[0].cur_y = data2;
}
if (cmd.pointer.aim_mouse1)
{
mouse[1].cur_x = data1;
mouse[1].cur_y = data2;
}
if (cmd.pointer.aim_scope)
{
superscope.x = data1;
superscope.y = data2;
}
if (cmd.pointer.aim_justifier0)
{
justifier.x[0] = data1;
justifier.y[0] = data2;
}
if (cmd.pointer.aim_justifier1)
{
justifier.x[1] = data1;
justifier.y[1] = data2;
}
return;
case S9xButtonPseudopointer:
if (data1)
{
if (cmd.button.pointer.UD)
{
if (!pseudopointer[cmd.button.pointer.idx].V_adj)
pseudopointer[cmd.button.pointer.idx].V_adj = cmd.button.pointer.UD * ptrspeeds[cmd.button.pointer.speed_type];
pseudopointer[cmd.button.pointer.idx].V_var = (cmd.button.pointer.speed_type == 0);
}
if (cmd.button.pointer.LR)
{
if (!pseudopointer[cmd.button.pointer.idx].H_adj)
pseudopointer[cmd.button.pointer.idx].H_adj = cmd.button.pointer.LR * ptrspeeds[cmd.button.pointer.speed_type];
pseudopointer[cmd.button.pointer.idx].H_var = (cmd.button.pointer.speed_type == 0);
}
}
else
{
if (cmd.button.pointer.UD)
{
pseudopointer[cmd.button.pointer.idx].V_adj = 0;
pseudopointer[cmd.button.pointer.idx].V_var = false;
}
if (cmd.button.pointer.LR)
{
pseudopointer[cmd.button.pointer.idx].H_adj = 0;
pseudopointer[cmd.button.pointer.idx].H_var = false;
}
}
return;
case S9xAxisJoypad:
{
uint16 pos, neg;
switch (cmd.axis.joypad.axis)
{
case 0: neg = SNES_LEFT_MASK; pos = SNES_RIGHT_MASK; break;
case 1: neg = SNES_UP_MASK; pos = SNES_DOWN_MASK; break;
case 2: neg = SNES_Y_MASK; pos = SNES_A_MASK; break;
case 3: neg = SNES_X_MASK; pos = SNES_B_MASK; break;
case 4: neg = SNES_TL_MASK; pos = SNES_TR_MASK; break;
default: return;
}
if (cmd.axis.joypad.invert)
data1 = -data1;
uint16 p, r;
p = r = 0;
if (data1 > ((cmd.axis.joypad.threshold + 1) * 127))
p |= pos;
else
r |= pos;
if (data1 <= ((cmd.axis.joypad.threshold + 1) * -127))
p |= neg;
else
r |= neg;
joypad[cmd.axis.joypad.idx].buttons |= p;
joypad[cmd.axis.joypad.idx].buttons &= ~r;
joypad[cmd.axis.joypad.idx].turbos &= ~(p | r);
return;
}
case S9xAxisPseudopointer:
if (data1 == 0)
{
if (cmd.axis.pointer.HV)
{
pseudopointer[cmd.axis.pointer.idx].V_adj = 0;
pseudopointer[cmd.axis.pointer.idx].V_var = false;
}
else
{
pseudopointer[cmd.axis.pointer.idx].H_adj = 0;
pseudopointer[cmd.axis.pointer.idx].H_var = false;
}
}
else
{
if (cmd.axis.pointer.invert)
data1 = -data1;
if (cmd.axis.pointer.HV)
{
if (!pseudopointer[cmd.axis.pointer.idx].V_adj)
pseudopointer[cmd.axis.pointer.idx].V_adj = (int16) ((int32) data1 * ptrspeeds[cmd.axis.pointer.speed_type] / 32767);
pseudopointer[cmd.axis.pointer.idx].V_var = (cmd.axis.pointer.speed_type == 0);
}
else
{
if (!pseudopointer[cmd.axis.pointer.idx].H_adj)
pseudopointer[cmd.axis.pointer.idx].H_adj = (int16) ((int32) data1 * ptrspeeds[cmd.axis.pointer.speed_type] / 32767);
pseudopointer[cmd.axis.pointer.idx].H_var = (cmd.axis.pointer.speed_type == 0);
}
}
return;
case S9xAxisPseudobuttons:
if (data1 > ((cmd.axis.button.threshold + 1) * 127))
{
if (!pseudobuttons[cmd.axis.button.posbutton])
{
pseudobuttons[cmd.axis.button.posbutton] = 1;
S9xReportButton(PseudoButtonBase + cmd.axis.button.posbutton, true);
}
}
else
{
if (pseudobuttons[cmd.axis.button.posbutton])
{
pseudobuttons[cmd.axis.button.posbutton] = 0;
S9xReportButton(PseudoButtonBase + cmd.axis.button.posbutton, false);
}
}
if (data1 <= ((cmd.axis.button.threshold + 1) * -127))
{
if (!pseudobuttons[cmd.axis.button.negbutton])
{
pseudobuttons[cmd.axis.button.negbutton] = 1;
S9xReportButton(PseudoButtonBase + cmd.axis.button.negbutton, true);
}
}
else
{
if (pseudobuttons[cmd.axis.button.negbutton])
{
pseudobuttons[cmd.axis.button.negbutton] = 0;
S9xReportButton(PseudoButtonBase + cmd.axis.button.negbutton, false);
}
}
return;
case S9xButtonPort:
case S9xAxisPort:
case S9xPointerPort:
S9xHandlePortCommand(cmd, data1, data2);
return;
case S9xButtonMulti:
if (cmd.button.multi_idx >= (int) multis.size())
return;
if (multis[cmd.button.multi_idx]->multi_press && !data1)
return;
i = ApplyMulti(multis[cmd.button.multi_idx], 0, data1);
if (i >= 0)
{
struct exemulti *e = new struct exemulti;
e->pos = i;
e->data1 = data1 != 0;
e->script = multis[cmd.button.multi_idx];
exemultis.insert(e);
}
return;
default:
fprintf(stderr, "WARNING: Unknown command type %d\n", cmd.type);
return;
}
}