Source Code from Direct Pad Pro 4.5
by Earle F. Philhower III
This source code is for all of the joysticks and joypads supported in Direct Pad Pro 4.5, not just SNES joypads.
/* DirectPad Pro Joystick Scanning Code - V4.5 */
/* (c) Earle F. Philhower, III */
/* See http://www.ziplabel.com/dpadpro for more information */
#define OUTP(a,b) {int aa; for (aa=0; aa<3; aa++) _outp((a), (b));}
#define SNES_PWR (128+64+32+16+8)
#define SNES_CLK 1 // base+0
#define SNES_LAT 2 // base+0
#define SIN (negate?((_inp(base+1)&snes_din)?1:0):((_inp(base+1)&snes_din)?0:1))
#define SNESIT(a) {if (snesdelay==3) {int i; for (i=0; i<3; i++) _outp(base, (a));}
else {int i; for (i=0; i<snesdelay; i++) _outp(base, (a));} }
typedef struct mySNES
{
char dn;
char up;
char lf;
char rt;
char a, b;
char x, y;
char l, r;
char sel, start;
} mySNES;
typedef struct myJAG
{
char dn;
char up;
char lf;
char rt;
char a, b, c, d;
char pause;
char opt;
char kp[12];
} myJAG;
typedef struct {
char dn;
char up;
char lf;
char rt;
char start, select, box, cross, circle, triangle;
char r1, l1, r2, l2, r3, l3;
char lx, ly, rx, ry;
} myPSX;
typedef struct myTGFX
{
char dn;
char up;
char lf;
char rt;
char f1, f2, f3, f4, f5;
} myTGFX;
typedef struct mySATURN
{
char dn;
char up;
char lf;
char rt;
char a, b, c;
char x, y, z;
char start;
char r,l;
} mySATURN;
typedef struct myGENESIS
{
char dn;
char up;
char lf;
char rt;
char a, b, c;
char start;
char x, y, z, md;
} myGENESIS;
typedef struct myATARI
{
char up;
char dn;
char lf;
char rt;
char btn;
char btn2;
} myATARI;
void ScanTGFX( myTGFX *tgfx, int num, int base )
{
int k, l;
OUTP( base+2, 0x04 ); // 4 extra inputs
OUTP( base, 0xff ); // all out high
OUTP( base, 0xff-( 1 << (7-num) ) );
k = _inp( base+1 );
l = _inp( base+2 );
tgfx->up = (k&16)?0:1;
tgfx->dn = (k&32)?0:1;
tgfx->lf = (k&64)?0:1;
tgfx->rt = (k&128)?1:0;
tgfx->f1 = (k&8)?0:1;
tgfx->f2 = (l&2)?1:0;
tgfx->f3 = (l&4)?0:1;
tgfx->f4 = (l&1)?1:0;
tgfx->f5 = (l&8)?1:0;
}
void ScanSaturn(mySATURN *saturn, int id, int base)
{
int s10, s11, s12, s13;
int s20, s21, s22, s23;
if (id!=2) {
OUTP(base, 255-64-(2+1));
//first pad power up, ground=0, select=00, but
2nd pad ground=1
s10=_inp(base+1);
OUTP(base, 255-64-(2+0));
//first pad power up, select=01
s11=_inp(base+1);
OUTP(base, 255-64-(0+1));
//first pad power up,select=10
s12=_inp(base+1);
OUTP(base, 255-64-(0+0));
//first pad power up,select=11
s13=_inp(base+1);
saturn->r = (s10&16)?0:1;
saturn->x = (s10&32)?0:1;
saturn->y = (s10&64)?0:1;
saturn->z = (s10&128)?1:0;
saturn->start = (s11&16)?0:1;
saturn->a = (s11&32)?0:1;
saturn->c = (s11&64)?0:1;
saturn->b = (s11&128)?1:0;
saturn->rt = (s12&16)?0:1;
saturn->lf = (s12&32)?0:1;
saturn->dn = (s12&64)?0:1;
saturn->up = (s12&128)?1:0;
saturn->l = (s13&16)?0:1;
} else {
OUTP(base, 255-128-(32+16));
//2nd pad power up, ground=0, select=00, but first pad ground=1
s20=_inp(base+1);
OUTP(base, 255-128-(32+0));
//2nd pad power up,select=01
s21=_inp(base+1);
OUTP(base, 255-128-(0+16));
//2nd pad power up,select=10
s22=_inp(base+1);
OUTP(base, 255-128-(0+0));
//2nd pad power up,select=11
s23=_inp(base+1);
saturn->r = (s20&16)?0:1;
saturn->x = (s20&32)?0:1;
saturn->y = (s20&64)?0:1;
saturn->z = (s20&128)?1:0;
saturn->start = (s21&16)?0:1;
saturn->a = (s21&32)?0:1;
saturn->c = (s21&64)?0:1;
saturn->b = (s21&128)?1:0;
saturn->rt = (s22&16)?0:1;
saturn->lf = (s22&32)?0:1;
saturn->dn = (s22&64)?0:1;
saturn->up = (s22&128)?1:0;
saturn->l = (s23&16)?0:1;
}
if (!joy[curJoy].power)
OUTP(base,0);
//power down gamepad
}
void ScanGenesis( myGENESIS *genesis, int base )
{
int s0, s1, s2, c, c2;
OUTP(base+2, 0x0c);
OUTP(base, 254); // Power up, select=0
s0 = _inp(base+1);
OUTP(base, 255); // Power up, select=1
s1 = _inp(base+1);
c = _inp(base+2);
if (joy[curJoy].name==GENESIS6)
{
_outp(base, 254); // sel=0;
_outp(base, 254); // sel=0;
_outp(base, 255); // sel=1;
_outp(base, 255); // sel=1;
_outp(base, 254); // sel=0;
_outp(base, 254); // sel=0;
_outp(base, 255); // sel=1;
_outp(base, 255); // sel=1;
s2=_inp(base+1);
c2=_inp(base+2);
}
if (!joy[curJoy].power)
OUTP(base, 0); // Power down joystick
genesis->dn = (c&2)?1:0;
genesis->up = (c&1)?1:0;
genesis->lf = (s1&64)?0:1;
genesis->rt = (s1&128)?1:0;
genesis->a = (s0&32)?0:1;
genesis->b = (s1&32)?0:1;
genesis->c = (s1&16)?0:1;
genesis->start = (s0&16)?0:1;
if (joy[curJoy].name==GENESIS6)
{
genesis->z = (c2&1)?1:0;
genesis->y = (c2&2)?1:0;
genesis->x = (s2&64)?0:1;
genesis->md = (s2&128)?1:0;
}
}
void ScanAtari( myATARI *atari, int base, int two )
{
int c;
// Atari
IBM
//up 1 1
(c0-)
//dn 2 14
(c1-)
//lf 3 16
(c2+)
//rt 4 17
(c3-)
//btn 6 11
(s7-) (connect 11 to 4p7R to 2 (d0), drive d0 1)
//btn2 9 12
(s5+) (connect 12 to 4p7R to 3 (d1), drive d1 1)
//gnd 8 18
OUTP(base+2, 4); //All C's high, disconnected
OUTP(base, 2+1); // Power joy button sensor
c = _inp(base+1);
atari->btn = (c & 128)?1:0;
atari->btn2 = two?((c & 32)?0:1):0;
if (!joy[curJoy].power)
OUTP(base, 0); // Power down joy button sensor
c=_inp(base+2);
atari->up = (c&1)?1:0;
atari->dn = (c&2)?1:0;
atari->lf = (c&4)?0:1;
atari->rt = (c&8)?1:0;
}
void ScanSNES(mySNES *snes, int base, int snes_din, int negate)
{
SNESIT(SNES_PWR+SNES_CLK); // Power up!
SNESIT(SNES_PWR+SNES_LAT+SNES_CLK); // Latch it!
SNESIT(SNES_PWR+SNES_CLK);
SNESIT(SNES_PWR);
snes->b = SIN;
SNESIT(SNES_PWR);
SNESIT(SNES_PWR+SNES_CLK);
SNESIT(SNES_PWR);
if (joy[curJoy].name==NES)
snes->a = SIN;
else
snes->y = SIN;
SNESIT(SNES_PWR);
SNESIT(SNES_PWR+SNES_CLK);
SNESIT(SNES_PWR);
snes->sel = SIN;
SNESIT(SNES_PWR);
SNESIT(SNES_PWR+SNES_CLK);
SNESIT(SNES_PWR);
snes->start = SIN;
SNESIT(SNES_PWR);
SNESIT(SNES_PWR+SNES_CLK);
SNESIT(SNES_PWR);
snes->up = SIN;
SNESIT(SNES_PWR);
SNESIT(SNES_PWR+SNES_CLK);
SNESIT(SNES_PWR);
snes->dn = SIN;
SNESIT(SNES_PWR);
SNESIT(SNES_PWR+SNES_CLK);
SNESIT(SNES_PWR);
snes->lf = SIN;
SNESIT(SNES_PWR);
SNESIT(SNES_PWR+SNES_CLK);
SNESIT(SNES_PWR);
snes->rt = SIN;
if (joy[curJoy].name==SNES)
{
SNESIT(SNES_PWR);
SNESIT(SNES_PWR+SNES_CLK);
SNESIT(SNES_PWR);
snes->a = SIN;
SNESIT(SNES_PWR);
SNESIT(SNES_PWR+SNES_CLK);
SNESIT(SNES_PWR);
snes->x = SIN;
SNESIT(SNES_PWR);
SNESIT(SNES_PWR+SNES_CLK);
SNESIT(SNES_PWR);
snes->l = SIN;
SNESIT(SNES_PWR);
SNESIT(SNES_PWR+SNES_CLK);
SNESIT(SNES_PWR);
snes->r = SIN;
}
if (!joy[curJoy].power)
OUTP(base, 0); // Power it down
}
void ScanJag(myJAG *jag, int base)
{
int r4, r4p, r3, r2, r1;
OUTP(base, 255-8);
OUTP(base+2, 4);
r4 = _inp(base+1);
jag->dn = (r4 & 16)?0:1;
jag->up = (r4 & 8)?0:1;
jag->lf = (r4 & 32)?0:1;
jag->rt = (r4 & 128)?1:0;
jag->a = (r4 & 64)?0:1;
r4p = _inp(base+2);
jag->pause = (r4p&2)?1:0;
OUTP(base, 255-4);
r3 = _inp(base+1);
jag->b = (r3 & 64)?0:1;
jag->kp[1] = (r3 & 128)?1:0;
jag->kp[4] = (r3 & 32)?0:1;
jag->kp[7] = (r3 & 16)?0:1;
jag->kp[10]= (r3 & 8)?0:1;
OUTP(base, 255-2);
r2 = _inp(base+1);
jag->c = (r2 & 64)?0:1;
jag->kp[2] = (r2 & 128)?1:0;
jag->kp[5] = (r2 & 32)?0:1;
jag->kp[8] = (r2 & 16)?0:1;
jag->kp[0] = (r2 & 8)?0:1;
OUTP(base, 255-1);
r1 = _inp(base+1);
jag->opt = (r1 & 64)?0:1;
jag->kp[3] = (r1 & 128)?1:0;
jag->kp[6] = (r1 & 32)?0:1;
jag->kp[9] = (r1 & 16)?0:1;
jag->kp[11]= (r1 & 8)?0:1;
}
// =========================
// | o o o | o o o | o o o | Controller plug
// \_____________________/
// 1 2 3 4 5 6 7 8 9
//
// Controller Parallel
// 1 - Data 10(pad1),13(pad2)
// 2 - Command 2
// 3 - 9V(shock) +9V battery terminal
// 4 - GND 18 , also -9V battery terminal
// 5 - V+ 6,7,8,9 through diodes
// 6 - ATT 3
// 7 - Clock 4
// 9 - ack 12(pad1), 15(pad2)
unsigned char p0 = 0xf8+4+2+1;
void Clk(int i, int base)
{
const clk=0x04; // Bit 3 Base+0 (parallel port)
if (i)
p0 |= clk;
else
p0 &= ~clk;
_outp(base+0, p0);
}
void Sel(int i, int id, int base)
{
const power=0xf8; // Bits 3-7 Base+0 (parallel port)
const att=0x02; // Bit 2 Base+0 (parallel port)
unsigned char attary[] = { 0, 0x02, 0x08, 0x10, 0x20, 0x40 };
unsigned char attval;
if (multitap)
attval = attary[id];
else
attval = att;
p0 |= power;
if (i)
p0 |= attval;
else
p0 &= ~attval;
_outp(base+0, p0);
}
void Cmd(int i, int base)
{
const cmd=0x01; // Bit 1 Base+0 (parallel port)
if (i)
p0 |= cmd;
else
p0 &= ~cmd;
_outp(base+0, p0);
}
int Dat(int id, int base)
{
unsigned char data;
if (multitap)
data = 0x40;
else
{
if (id==1) data = 0x40;
else data = 0x10;
}
if (_inp(base+1)&data)
return 1;
else
return 0;
}
int Ack(int id, int base)
{
unsigned char ack;
if (multitap)
ack = 0x20;
else
{
if (id==1) ack = 0x20;
else ack = 0x08;
}
if (_inp(base+1)&ack)
return 1;
else
return 0;
}
void Slow(int base)
{
int i;
if (psxdelay==3)
{
for (i=0; i<3; i++)
_outp(base+0, p0);
} else
{
for (i=0; i<psxdelay; i++)
_outp(base+0, p0);
}
}
unsigned char SendByte(unsigned char byte, int wait, int id, int base)
{
int i,j,k;
unsigned char data;
data=0;
for (i=0; i<8; i++)
{
Slow(base);
Cmd(byte&(1<<i), base);
Clk(0, base);
Slow(base);
Clk(1, base);
data |= (Dat(id, base)?(1<<i):0);
}
// Wait for ACK;
for(j=0; wait && j<300 && Ack(id, base); j++);
for(k=0; wait && k<300 && !Ack(id, base); k++);
return data;
}
void SendPSXString( int string[], int id, int base )
{
int i;
Sel(1, id, base);
Clk(1, base);
Cmd(1, base);
Slow(base);
Slow(base);
Slow(base);
Slow(base);
Sel(0, id, base);
Slow(base);
Slow(base);
for (i=0; string[i+1]!=-1; i++)
SendByte((unsigned char)string[i],1,id,base);
SendByte((unsigned char)string[i],0,id,base);
Slow(base);
Sel(1, id, base);
Slow(base);
Slow(base);
}
void Shock(long id, long base, long small, long big)
{
int i;
static int ShockString[4][12]= {
{0x01, 0x43, 0x00, 0x01, 0x00, 0x01, -1},
{0x01, 0x4d, 0x00, 0x00, 0x01, 0xff, 0xff,
0xff, 0xff, 0x01, -1},
{0x01, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x01, -1},
{0x01, 0x42, 0x00, 0xff, 0xff, 0x01, -1 } };
ShockString[3][3] = (int)small;
ShockString[3][4] = (int)big;
for (i=0; i<4; i++)
SendPSXString( ShockString[i], id, base );
}
int ScanPSX( myPSX *psx, int base, int id )
{
extern void ForceFeedback( DWORD dwDeviceID, int controller, int base,
int always );
unsigned char data[10];
Sel(1, id, base);
Clk(1,base);
Cmd(1,base);
Slow(base);
Slow(base);
Slow(base);
Slow(base);
Slow(base);
Sel(0, id, base);
Slow(base);
Slow(base);
data[0]=SendByte(0x01,1,id,base);
data[1]=SendByte(0x42,1,id,base);
if (data[1]==0x41) {
data[2]=SendByte(0x00,1,id,base);
data[3]=SendByte(0x00,1,id,base);
data[4]=SendByte(0x00,0,id,base);
} else if (data[1]==0x53) {
data[2]=SendByte(0x00,1,id,base);
data[3]=SendByte(0x00,1,id,base);
data[4]=SendByte(0x00,1,id,base);
data[5]=SendByte(0x00,1,id,base);
data[6]=SendByte(0x00,1,id,base);
data[7]=SendByte(0x00,1,id,base);
data[8]=SendByte(0x00,0,id,base);
} else if (data[1]==0x73 || data[1]==0x23) {
data[2]=SendByte(0x00,1,id,base);
data[3]=SendByte(0x00,1,id,base);
data[4]=SendByte(0x00,1,id,base);
data[5]=SendByte(0x00,1,id,base);
data[6]=SendByte(0x00,1,id,base);
data[7]=SendByte(0x00,1,id,base);
data[8]=SendByte(0x00,1,id,base);
data[9]=SendByte(0x00,0,id,base);
} else {
data[1] = 0;
data[2] = 0;
data[3] = 255;
data[4] = 255;
data[5] = 128;
data[6] = 128;
data[7] = 128;
data[8] = 128;
data[9] = 0;
}
Slow(base);
Slow(base);
Sel(1, id, base);
Cmd(1,base);
Clk(1,base);
Slow(base);
psx->lf = data[3]&0x80?0:1;
psx->dn = data[3]&0x40?0:1;
psx->rt = data[3]&0x20?0:1;
psx->up = data[3]&0x10?0:1;
psx->start = data[3]&0x08?0:1;
psx->select = data[3]&0x01?0:1;
psx->cross = data[4]&0x40?0:1;
psx->circle = data[4]&0x20?0:1;
psx->l2 = data[4]&0x01?0:1;
psx->r3 = data[3]&0x04?0:1;
psx->l3 = data[3]&0x02?0:1;
if (data[1]!=0x41) {
psx->rx = data[5];
psx->ry = data[6];
psx->lx = data[7];
psx->ly = data[8];
} else {
psx->lx = psx->rx =
psx->lf?(MINJOY/256):(psx->rt?(MAXJOY/256):(MIDJOY/256));
psx->ly = psx->ry =
psx->up?(MINJOY/256):(psx->dn?(MAXJOY/256):(MIDJOY/256));
}
switch (data[1]) {
case 0x73: //analog red mode
case 0x53: //analog green mode
psx->l1 =
data[4]&0x04?0:1;
psx->r1 =
data[4]&0x08?0:1;
psx->triangle =
data[4]&0x10?0:1;
psx->r2 =
data[4]&0x02?0:1;
psx->box =
data[4]&0x80?0:1;
break;
default:
psx->box =
data[4]&0x80?0:1;
psx->triangle =
data[4]&0x10?0:1;
psx->r1 =
data[4]&0x08?0:1;
psx->l1 =
data[4]&0x04?0:1;
psx->r2 =
data[4]&0x02?0:1;
break;
}
ForceFeedback( curJoy-1, id, base, 0 );
return data[1];
}
Here is some sample source code
provided by Kerry High
<BEGIN SOURCE FILE>
// SNESpad class
// Version 1.0
// Kerry High
#include <iostream.h>
#include <conio.h>
#include "snespad.h"
#define SNES_PWR (128+64+32+16+8)
#define SNES_CLK 1 // base+0
#define SNES_LAT 2 // base+0
#define SIN (negate?((inp(base+1)&snes_din)?1:0):((inp(base+1)&snes_din)?0:1))
// New snespad, base=LPT1
SNESpad::SNESpad()
{
setlpt(1);
return;
}
// New snespad, set base by lpt#
SNESpad::SNESpad(int lpt_number)
{
setlpt(lpt_number);
return;
}
// Set base by lpt#: 1=0x378 2=0x278 3=0x3BC
void SNESpad::setlpt(int lpt_number)
{
switch(lpt_number)
{
case 1: setbase(0x378); break;
case 2: setbase(0x278); break;
case 3: setbase(0x3bc); break;
default:
cerr << "SNESpad: LPT" << lpt_number << " invalid!"
<< endl;
cerr << "Defaulting to LPT1" << endl;
setbase(0x378);
}
return;
}
// Set to any base
void SNESpad::setbase(int port_number)
{
base=port_number;
return;
}
// Read pad number pad_number
// Pads are numbered from 0 to 4
// Original C code by Earle F. Philhower, III.
void SNESpad::readpad(int pad_number)
{
const int DIN[5] = {64,32,16,8,128};
const int NEGATE[5]={0, 0, 0,0, 1};
int snes_din=DIN[pad_number];
int negate=NEGATE[pad_number];
outp(base, SNES_PWR+SNES_CLK); // Power up!
outp(base, SNES_PWR+SNES_LAT+SNES_CLK); // Latch it!
outp(base, SNES_PWR+SNES_CLK);
snes.b = SIN;
outp(base, SNES_PWR);
outp(base, SNES_PWR+SNES_CLK);
snes.y = SIN;
outp(base, SNES_PWR);
outp(base, SNES_PWR+SNES_CLK);
snes.select = SIN;
outp(base, SNES_PWR);
outp(base, SNES_PWR+SNES_CLK);
snes.start = SIN;
outp(base, SNES_PWR);
outp(base, SNES_PWR+SNES_CLK);
snes.up = SIN;
outp(base, SNES_PWR);
outp(base, SNES_PWR+SNES_CLK);
snes.down = SIN;
outp(base, SNES_PWR);
outp(base, SNES_PWR+SNES_CLK);
snes.left = SIN;
outp(base, SNES_PWR);
outp(base, SNES_PWR+SNES_CLK);
snes.right = SIN;
outp(base, SNES_PWR);
outp(base, SNES_PWR+SNES_CLK);
snes.a = SIN;
outp(base, SNES_PWR);
outp(base, SNES_PWR+SNES_CLK);
snes.x = SIN;
outp(base, SNES_PWR);
outp(base, SNES_PWR+SNES_CLK);
snes.l = SIN;
outp(base, SNES_PWR);
outp(base, SNES_PWR+SNES_CLK);
snes.r = SIN;
outp(base, 0); // Power it down
}
// Return 1 if button pressed at last read, 0 otherwise
int SNESpad::up()
{
return snes.up;
}
int SNESpad::down()
{
return snes.down;
}
int SNESpad::right()
{
return snes.right;
}
int SNESpad::left()
{
return snes.left;
}
int SNESpad::select()
{
return snes.select;
}
int SNESpad::start()
{
return snes.start;
}
int SNESpad::a()
{
return snes.a;
}
int SNESpad::b()
{
return snes.b;
}
int SNESpad::x()
{
return snes.x;
}
int SNESpad::y()
{
return snes.y;
}
int SNESpad::l()
{
return snes.l;
}
int SNESpad::r()
{
return snes.r;
}
<END OF FILE>
This source is included in the SNESTest archive available on the downloads page