Copy Link
Add to Bookmark
Report
making dual shock controllers vibrate
- each pad has two actuators (things that make it vibrate)
- actuator 0 for each pad has an on and an off setting equal to 0 or 1 respectivly
- this is the way the vibration in porsche challenge is done
- actuator 1 for each pad has a setting between 0 and 255, where 0 is off, and 255 is most vibration
- this is the way the vibration was done for tekken 3
- (note: you can use both types of vibration at once)
/**
dual shock demo file
*/
#include <sys/types.h>
#include <libetc.h>
#include <libgte.h>
#include <libgpu.h>
#include <libgs.h>
#include <libpad.h>
#include <memory.h>
#include <pad.h>
#define DS_PAD_1 0 //port id for pad 1
#define DS_PAD_2 1 //port id for pad 2
#define OT_LENGTH 10
GsOT myOT[2];
GsOT_TAG myOT_TAG[2][1<<OT_LENGTH];
#define PACKETMAX 1000
PACKET GPUPacketArea[2][PACKETMAX*24];
#define SCREEN_WIDTH 320
#define SCREEN_HEIGHT 240
#define vibBuffLength 8
static u_char padbuff[2][34]; //read buffers for pads
u_char transmissionBuffer[2][vibBuffLength]; //vibration buffers for pads
int activeBuffer;
/************ protoypes ***************/
int main(void);
int InitDSPads(void); //inits dual shock pads
void InitAll(void); //inits system
void DisplayAll(void); //displays OT contents onscreen
u_long DSPadRead(void); //gets button info from pads
void GetStablePad(int); //makes pads stable (specify which pad 0 or 1)
/************ methods ***************/
int main(void) {
int i, currentVibBuff=0;
u_long pad, oldPad;
static u_char align[6]={0,1,0xFF,0xFF,0xFF,0xFF}; //array used to 'align' activators
GsLINE pointer; //line used to point to actuator values onscreen
ResetCallback();
SetVideoMode(MODE_PAL);
InitAll();
InitDSPads(); //init dual shock pads
pointer.y0=pointer.y1=20; //init pointer line for pointing to act. values onscreen
pointer.x0=10; pointer.x1=25;
pointer.r=pointer.g=pointer.b=255;
pointer.attribute=0;
for(i=0; i<vibBuffLength;i++) //this makes sure the transmission buffer is empty (all zeros=no vibration)
transmissionBuffer[DS_PAD_1][i]=0x00;
GetStablePad(DS_PAD_1); //before setting up the transmission buffers pads must be in stable state
PadSetAct(DS_PAD_1, transmissionBuffer[DS_PAD_1], vibBuffLength); //registers transmission buffer (call this once)
// GetStablePad(DS_PAD_2); //before setting up the transmission buffers pads must be in stable state
// PadSetAct(DS_PAD_2, transmissionBuffer[DS_PAD_2], vibBuffLength); //registers transmission buffer (call this once)
GetStablePad(DS_PAD_1); //before 'aligning' transmission buffers, pads must be in stable state
if (!PadSetActAlign(DS_PAD_1, align)) {printf("error aligning pad 1's actuators"); exit(-1);}
GetStablePad(DS_PAD_1); //before getting PadInfoAct, pads must be in stable state
printf("total number of actuators in pad 1 is %d\n",PadInfoAct(DS_PAD_1, -1, 0)); //get info about actuator 1 in pad 1
printf("total number of actuators in pad 2 is %d\n",PadInfoAct(DS_PAD_2, -1, 0)); //get info about actuator 1 in pad 1
GetStablePad(DS_PAD_1); //yep you guessed it :)
printf("pad 1 InfoMode is %d\n",PadInfoMode(DS_PAD_1, 1, 2)); //get info about the mode of pad1
//now, to make pad vibrate just put correct info into transmissionBuffer
while(1) { //this is the main loop
if(pad&Pad1tri) {
//pressing triangle stops pads vibrating by setting trans. buffers to 0
printf("no more vibrations\n");
for(i=0; i<vibBuffLength;i++)
transmissionBuffer[DS_PAD_1][i]=0x00;
}
//the next 2 control the amount of vibration
if(pad&Pad1Up) {if(transmissionBuffer[DS_PAD_1][currentVibBuff]<250) transmissionBuffer[DS_PAD_1][currentVibBuff]+=1;}
if(pad&Pad1Down) {if(transmissionBuffer[DS_PAD_1][currentVibBuff]>0) transmissionBuffer[DS_PAD_1][currentVibBuff]-=1;}
//these control the movement of the onscreen 'pointer'
if(pad&Pad1Left) if ((oldPad!=pad)&&(pointer.x0>30)) {currentVibBuff--; pointer.x0-=24; pointer.x1-=24;}
if(pad&Pad1Right) if ((oldPad!=pad)&&(pointer.x0<10+(vibBuffLength-1)*24)) {currentVibBuff++; pointer.x0+=24; pointer.x1+=24;}
if(pad&Pad1crc) {
//this aligns pads - use it if pads will not vibrate when X is pressed
//(this will occur if pad mode is changed from digital to analogue)
printf("aligning pads\n");
GetStablePad(DS_PAD_1);
PadSetAct(DS_PAD_1, transmissionBuffer[DS_PAD_1], vibBuffLength);
GetStablePad(DS_PAD_1);
if (!PadSetActAlign(DS_PAD_1, align)) {printf("error aligning pad 1's actuators"); exit(-1);}
}
if(pad&Pad1x) {
//this puts max. values in all the positions of the transmission buffer
printf("vibrating pad\n");
for(i=0; i<vibBuffLength;i++)
transmissionBuffer[DS_PAD_1][i]=0xFF;
}
activeBuffer=GsGetActiveBuff();
GsSetWorkBase((PACKET*)GPUPacketArea[activeBuffer]);
GsClearOt(0, 0, &myOT[activeBuffer]);
//print the values of trans. buffer to screen
for (i=0; i<vibBuffLength; i++)
FntPrint("%2x ",transmissionBuffer[DS_PAD_1][i]);
// FntPrint("\n\npad1: act1=%d act2=%d", PadInfoAct(DS_PAD_1, 0, 1), PadInfoAct(DS_PAD_1, 1, 1));
GsSortLine(&pointer, &myOT[activeBuffer], 0);
DisplayAll();
oldPad=pad;
pad=DSPadRead();
}
printf("finished\n");
return(0);
}
int InitDSPads(void) {
printf("about to init DS Pad\n");
PadInitDirect(padbuff[DS_PAD_1], padbuff[DS_PAD_2]); //inits both controllers
//cant use PadInit() as it will not transfer information to padds properly
PadStartCom();
PadEnableCom(3); //enables both controllers
}
void DisplayAll(void) {
DrawSync(0);
VSync(0);
GsSwapDispBuff();
GsSortClear(0,0,0,&myOT[activeBuffer]);
GsDrawOt(&myOT[activeBuffer]);
FntFlush(-1);
}
void InitAll(void) {
GsInitGraph(SCREEN_WIDTH, SCREEN_HEIGHT, GsINTER|GsOFSGPU, 0,0);
GsDefDispBuff(0,0,0,SCREEN_HEIGHT);
myOT[0].length=OT_LENGTH;
myOT[1].length=OT_LENGTH;
myOT[0].org=myOT_TAG[0];
myOT[1].org=myOT_TAG[1];
GsClearOt(0,0,&myOT[0]);
GsClearOt(0,0,&myOT[1]);
FntLoad(960, 256);
FntOpen(10,10,SCREEN_WIDTH-10,SCREEN_HEIGHT-20,0,512);
SetDispMask(1); /* start display */
}
u_long DSPadRead(void) {
return(~(*(*padbuff+3) | *(*padbuff+2) << 8 | *(*padbuff+3) << 16 | *(*padbuff+2) << 24));
}
void GetStablePad(int port) {
//this is just a simple loop that keeps going till both pads are in a stable state
while (PadGetState(port)!=PadStateStable)
;//loop till both pads are in a stable state
}