
#include <intuition/intuition.h>
#include <intuition/intuitionbase.h>
#include <exec/exec.h>
#include <devices/gameport.h>
#include <devices/input.h>
#include <proto/intuition.h>
#include <proto/exec.h>

void doinit(),qread(),dojoy(),dodie(),cleanup();
void fakeevent();
ULONG joymask,diemask;
struct MsgPort *joyport,*iport,*diep;
struct IOStdReq *joyreq,*inputreq,*diemsg;
struct InputEvent jevent,fevent;
struct GamePortTrigger jtrig = { GPTF_DOWNKEYS|GPTF_UPKEYS,0,1,1 };
struct IntuitionBase *IntuitionBase;
int error;
int go=1;
BYTE ctype;
BYTE mytype=GPCT_RELJOYSTICK;
ULONG signals;
WORD x,y;
BOOL fast=FALSE;
BOOL down=FALSE;
BOOL mnu=FALSE;
ULONG tick;
WORD step=3;

main(argc,argv)
{
    doinit();
    qread();
    while(go)
    {
        signals=Wait(joymask|diemask);
        if (signals & joymask) dojoy();
        if (signals & diemask) dodie();
    }
    cleanup(50);
}


void dojoy()
{
    UWORD code;
    GetMsg((struct MsgPort *)joyport);
    code=jevent.ie_Code;
    if ((code==IECODE_LBUTTON)&(down==TRUE)) code=IECODE_NOBUTTON;
    x=jevent.ie_X;
    y=jevent.ie_Y;
    if((jevent.ie_TimeStamp.tv_secs/60) < 4000 ) {
        tick++;
        if (tick==10) step=9;
        if (tick==40) step=15;
    }
    else {
        tick=0;
        step=3;
    }
    if ((code==IECODE_LBUTTON) & (IntuitionBase->MouseY<2)) {
        code=IECODE_RBUTTON;
        mnu=TRUE;
    }
    else {
        if (code==IECODE_LBUTTON+IECODE_UP_PREFIX) {
            down=FALSE;
            if (mnu==TRUE) {
                code=IECODE_RBUTTON+IECODE_UP_PREFIX;
                mnu=FALSE;
            }
        }
        else if (code==IECODE_LBUTTON) down=TRUE;
    }
    fakeevent(code,x,y);
    qread();
}


void fakeevent(xcode,xx,xy)
UWORD xcode;
WORD xx,xy;
{
    fevent.ie_Code=xcode;
    fevent.ie_NextEvent=NULL;
    fevent.ie_Class=IECLASS_RAWMOUSE;
    fevent.ie_Qualifier=IEQUALIFIER_RELATIVEMOUSE;
    fevent.ie_X=xx*step;
    fevent.ie_Y=xy*step;
    inputreq->io_Command=IND_WRITEEVENT;
    inputreq->io_Data=(APTR)&fevent;
    inputreq->io_Flags=0;
    inputreq->io_Length=sizeof(struct InputEvent);
    DoIO((struct IORequest *)inputreq);
}

void qread()
{
    joyreq->io_Command=GPD_READEVENT;
    joyreq->io_Data=(APTR)&jevent;
    joyreq->io_Length=sizeof(struct InputEvent);
    SendIO((struct IORequest *)joyreq);
}

void dodie()
{
    struct IOStdReq *msg;
    msg=(struct IORequest *)GetMsg((struct MsgPort *)diep);
    ReplyMsg((struct IORequest  *)msg);
    go=0;
}

void cleanup(level)
int level;
{
    BYTE utype=GPCT_NOCONTROLLER;
    switch(level)
    {
        case 50:
          DeletePort((struct MsgPort *)diep);
          AbortIO((struct IORequest *)joyreq);
          WaitIO((struct IORequest *)joyreq);
          joyreq->io_Command=GPD_SETCTYPE;
          joyreq->io_Data=(APTR)&utype;
          joyreq->io_Length=1;
          DoIO((struct IORequest *)joyreq);
        case 45:
          CloseDevice((struct IORequest *)inputreq);
        case 40:
          CloseDevice((struct IORequest *)joyreq);
        case 35:
          DeleteStdIO(inputreq);
        case 30:
          DeleteStdIO(joyreq);
        case 25:
          DeletePort((struct MsgPort *)iport);
        case 20:
          DeletePort((struct MsgPort *)joyport);
        case 15:
        case 10:
          CloseLibrary((struct Library *)IntuitionBase);
        case 5:
          exit(1);
    }
}

void doinit()
{
    struct MsgPort *p,*mp;
    struct IOStdReq *tmsg;
    if(p=FindPort("pmdjoymouse")) {
        if(mp=(struct MsgPort *)CreatePort("pmdjm",0)) {
            if(tmsg=(struct IOStdReq *)CreateStdIO(mp)) {
                PutMsg(p,tmsg);
                WaitPort((struct MsgPort *)mp);
                DeleteStdIO(tmsg);
            }
            DeletePort((struct MsgPort *)mp);
        }
        cleanup(5);
    }
    else {
        if(!(diep=(struct MsgPort *)CreatePort("pmdjoymouse",0))) cleanup(5);
        diemask=1<<diep->mp_SigBit;
    }
    if(!(IntuitionBase=(struct IntuitionBase *)OpenLibrary("intuition.library",33))) cleanup(5);
    if(!(joyport=(struct MsgPort *)CreatePort(NULL,0))) cleanup(15);
    if(!(iport=(struct MsgPort *)CreatePort(NULL,0))) cleanup(20);
    if(!(joyreq=CreateStdIO(joyport))) cleanup(25);
    if(!(inputreq=CreateStdIO(iport))) cleanup(30);
    if(error=OpenDevice("gameport.device",1,(struct IORequest *)joyreq,0)) cleanup(35);
    if(error=OpenDevice("input.device",0,(struct IORequest *)inputreq,0)) cleanup(40);
    joyreq->io_Command=GPD_ASKCTYPE;
    joyreq->io_Data=(APTR)&ctype;
    joyreq->io_Length=1;
    error=0;
    Forbid();
    DoIO((struct IORequest *)joyreq);
    if (ctype==GPCT_NOCONTROLLER) {
        joyreq->io_Command=GPD_SETCTYPE;
        joyreq->io_Data=(APTR)&mytype;
        joyreq->io_Length=1;
        DoIO((struct IORequest *)joyreq);
    }
    else error=1;
    Permit();
    if (error) cleanup(45);
    joyreq->io_Command=GPD_SETTRIGGER;
    joyreq->io_Data=(APTR)&jtrig;
    joyreq->io_Length=(LONG)sizeof(struct GamePortTrigger);
    DoIO((struct IORequest *)joyreq);
    joyreq->io_Command=CMD_CLEAR;
    DoIO((struct IORequest *)joyreq);
    joymask=1<<joyport->mp_SigBit;
}


