#include "plugins.h"
#include "cdriso.h"
+#include "psxcounters.h"
static char IsoFile[MAXPATHLEN] = "";
static s64 cdOpenCaseTime = 0;
GPUupdateLace GPU_updateLace;
GPUinit GPU_init;
GPUshutdown GPU_shutdown;
-GPUconfigure GPU_configure;
-GPUtest GPU_test;
-GPUabout GPU_about;
GPUopen GPU_open;
GPUclose GPU_close;
GPUreadStatus GPU_readStatus;
SPUregisterScheduleCb SPU_registerScheduleCb;
SPUasync SPU_async;
SPUplayCDDAchannel SPU_playCDDAchannel;
+SPUsetCDvol SPU_setCDvol;
PADconfigure PAD1_configure;
PADabout PAD1_about;
#define LoadSym(dest, src, name, checkerr) { \
dest = (src)SysLoadSym(drv, name); \
- if (checkerr) { CheckErr(name); } else SysLibError(); \
+ if (checkerr) { CheckErr(name); } \
}
void *hGPUDriver = NULL;
hGPUDriver = SysLoadLibrary(GPUdll);
if (hGPUDriver == NULL) {
- GPU_configure = NULL;
SysMessage (_("Could not load GPU plugin %s!"), GPUdll); return -1;
}
drv = hGPUDriver;
LoadGpuSym0(showScreenPic, "GPUshowScreenPic");
LoadGpuSym0(vBlank, "GPUvBlank");
LoadGpuSym0(getScreenInfo, "GPUgetScreenInfo");
- LoadGpuSym0(configure, "GPUconfigure");
- LoadGpuSym0(test, "GPUtest");
- LoadGpuSym0(about, "GPUabout");
return 0;
}
static void *hSPUDriver = NULL;\r
static void CALLBACK SPU__registerScheduleCb(void (CALLBACK *cb)(unsigned int)) {}\r
+static void CALLBACK SPU__setCDvol(unsigned char ll, unsigned char lr,
+ unsigned char rl, unsigned char rr, unsigned int cycle) {}
#define LoadSpuSym1(dest, name) \
LoadSym(SPU_##dest, SPU##dest, name, TRUE);
#define LoadSpuSym0(dest, name) \
LoadSym(SPU_##dest, SPU##dest, name, FALSE); \
- if (SPU_##dest == NULL) SPU_##dest = (SPU##dest) SPU__##dest;
+ if (SPU_##dest == NULL) SPU_##dest = SPU__##dest;
#define LoadSpuSymN(dest, name) \
LoadSym(SPU_##dest, SPU##dest, name, FALSE);
LoadSpuSym0(registerScheduleCb, "SPUregisterScheduleCb");
LoadSpuSymN(async, "SPUasync");
LoadSpuSymN(playCDDAchannel, "SPUplayCDDAchannel");
+ LoadSpuSym0(setCDvol, "SPUsetCDvol");
return 0;
}
static void initBufForRequest(int padIndex, char value) {
- if (pads[padIndex].configMode) {
+ if (pads[padIndex].ds.configMode) {
buf[0] = 0xf3; buf[1] = 0x5a;
respSize = 8;
}
return;
}
+ if ((u32)(frame_counter - pads[padIndex].ds.lastUseFrame) > 2*60u
+ && pads[padIndex].ds.configModeUsed
+ && !Config.hacks.dualshock_init_analog)
+ {
+ //SysPrintf("Pad reset\n");
+ pads[padIndex].ds.padMode = 0; // according to nocash
+ pads[padIndex].ds.autoAnalogTried = 0;
+ }
+ else if (pads[padIndex].ds.padMode == 0 && value == CMD_READ_DATA_AND_VIBRATE
+ && pads[padIndex].ds.configModeUsed
+ && !pads[padIndex].ds.configMode
+ && !pads[padIndex].ds.userToggled)
+ {
+ if (pads[padIndex].ds.autoAnalogTried == 16) {
+ // auto-enable for convenience
+ SysPrintf("Auto-enabling dualshock analog mode.\n");
+ pads[padIndex].ds.padMode = 1;
+ pads[padIndex].ds.autoAnalogTried = 255;
+ }
+ else if (pads[padIndex].ds.autoAnalogTried < 16)
+ pads[padIndex].ds.autoAnalogTried++;
+ }
+ pads[padIndex].ds.lastUseFrame = frame_counter;
+
switch (value) {
// keystate already in buffer, set by PADstartPoll_()
//case CMD_READ_DATA_AND_VIBRATE :
// break;
case CMD_CONFIG_MODE :
- if (pads[padIndex].configMode) {
+ if (pads[padIndex].ds.configMode) {
memcpy(buf, resp43, 8);
break;
}
break;
case CMD_QUERY_MODEL_AND_MODE :
memcpy(buf, resp45, 8);
- buf[4] = pads[padIndex].PadMode;
+ buf[4] = pads[padIndex].ds.padMode;
break;
case CMD_QUERY_ACT :
memcpy(buf, resp46_00, 8);
memcpy(buf, resp4C_00, 8);
break;
case CMD_VIBRATION_TOGGLE: // 4d
- memcpy(buf + 2, pads[padIndex].cmd4dConfig, 6);
+ memcpy(buf + 2, pads[padIndex].ds.cmd4dConfig, 6);
break;
case REQ40 :
memcpy(buf, resp40, 8);
case CMD_CONFIG_MODE :
//0x43
if (value == 0) {
- pads[padIndex].configMode = 0;
- } else {
- pads[padIndex].configMode = 1;
+ pads[padIndex].ds.configMode = 0;
+ } else if (value == 1) {
+ pads[padIndex].ds.configMode = 1;
+ pads[padIndex].ds.configModeUsed = 1;
}
break;
case CMD_SET_MODE_AND_LOCK :
//0x01 analog ON
//0x00 analog OFF
if ((value & ~1) == 0)
- pads[padIndex].PadMode = value;
+ pads[padIndex].ds.padMode = value;
break;
case CMD_QUERY_ACT :
//0x46
memcpy(buf, resp4C_01, 8);
}
break;
- case CMD_READ_DATA_AND_VIBRATE:
- //mem the vibration value for small motor;
- pads[padIndex].Vib[0] = value;
- break;
}
}
-static void vibrate(int padIndex) {
+static void ds_update_vibrate(int padIndex) {
PadDataS *pad = &pads[padIndex];
+ if (pad->ds.configModeUsed) {
+ pad->Vib[0] = (pad->Vib[0] == 1) ? 1 : 0;
+ }
+ else {
+ // compat mode
+ pad->Vib[0] = (pad->Vib[0] & 0xc0) == 0x40 && (pad->Vib[1] & 1);
+ pad->Vib[1] = 0;
+ }
if (pad->Vib[0] != pad->VibF[0] || pad->Vib[1] != pad->VibF[1]) {
//value is different update Value and call libretro for vibration
pad->VibF[0] = pad->Vib[0];
pad->VibF[1] = pad->Vib[1];
plat_trigger_vibrate(padIndex, pad->VibF[0], pad->VibF[1]);
- //printf("vibration pad %i\n", padIndex);
+ //printf("vib%i %02x %02x\n", padIndex, pad->VibF[0], pad->VibF[1]);
}
}
#endif
}
+static void adjust_analog(unsigned char *b)
+{
+ // ff8 hates 0x80 for whatever reason (broken in 2d area menus),
+ // or is this caused by something else we do wrong??
+ // Also S.C.A.R.S. treats 0x7f as turning left.
+ if (b[6] == 0x7f || b[6] == 0x80)
+ b[6] = 0x81;
+}
+
// Build response for 0x42 request Pad in port
static void PADstartPoll_(PadDataS *pad) {
switch (pad->controllerType) {
respSize = 4;
break;
case PSE_PAD_TYPE_ANALOGPAD: // scph1150
- if (pad->PadMode == 0)
+ if (pad->ds.padMode == 0)
goto standard;
stdpar[0] = 0x73;
stdpar[1] = 0x5a;
stdpar[5] = pad->rightJoyY;
stdpar[6] = pad->leftJoyX;
stdpar[7] = pad->leftJoyY;
+ adjust_analog(stdpar);
memcpy(buf, stdpar, 8);
respSize = 8;
break;
stdpar[5] = pad->rightJoyY;
stdpar[6] = pad->leftJoyX;
stdpar[7] = pad->leftJoyY;
+ adjust_analog(stdpar);
memcpy(buf, stdpar, 8);
respSize = 8;
break;
case 2:
reqIndex2Treatment(port, value);
break;
- case 3:
- if (pads[port].txData[0] == CMD_READ_DATA_AND_VIBRATE) {
- // vibration value for the Large motor
- pads[port].Vib[1] = value;
-
- vibrate(port);
- }
- break;
case 7:
if (pads[port].txData[0] == CMD_VIBRATION_TOGGLE)
- memcpy(pads[port].cmd4dConfig, pads[port].txData + 2, 6);
+ memcpy(pads[port].ds.cmd4dConfig, pads[port].txData + 2, 6);
break;
}
+
+ if (pads[port].txData[0] == CMD_READ_DATA_AND_VIBRATE
+ && !pads[port].ds.configModeUsed && 2 <= pos && pos < 4)
+ {
+ // "compat" single motor mode
+ pads[port].Vib[pos - 2] = value;
+ }
+ else if (pads[port].txData[0] == CMD_READ_DATA_AND_VIBRATE
+ && 2 <= pos && pos < 8)
+ {
+ // 0 - weak motor, 1 - strong motor
+ int dev = pads[port].ds.cmd4dConfig[pos - 2];
+ if (dev < 2)
+ pads[port].Vib[dev] = value;
+ }
+ if (pos == respSize - 1)
+ ds_update_vibrate(port);
}
static unsigned char PADpoll_(int port, unsigned char value, int pos, int *more_data) {
memset(pads, 0, sizeof(pads));
for (p = 0; p < sizeof(pads) / sizeof(pads[0]); p++) {
- memset(pads[p].cmd4dConfig, 0xff, sizeof(pads[p].cmd4dConfig));
+ memset(pads[p].ds.cmd4dConfig, 0xff, sizeof(pads[p].ds.cmd4dConfig));
}
return 0;
return 0;
}
+int padFreeze(void *f, int Mode) {
+ size_t i;
+
+ for (i = 0; i < sizeof(pads) / sizeof(pads[0]); i++) {
+ pads[i].saveSize = sizeof(pads[i]);
+ gzfreeze(&pads[i], sizeof(pads[i]));
+ if (Mode == 0 && pads[i].saveSize != sizeof(pads[i]))
+ SaveFuncs.seek(f, pads[i].saveSize - sizeof(pads[i]), SEEK_CUR);
+ }
+
+ return 0;
+}
+
+int padToggleAnalog(unsigned int index)
+{
+ int r = -1;
+
+ if (index < sizeof(pads) / sizeof(pads[0])) {
+ r = (pads[index].ds.padMode ^= 1);
+ pads[index].ds.userToggled = 1;
+ }
+ return r;
+}
+
+
void *hNETDriver = NULL;
void CALLBACK NET__setInfo(netInfo *info) {}