I accept payment through PayPal!, the #1 online payment service!

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


home