
/***********************************************************\
*                                                           *
*   NAME:                                                   *
*     AUTOPORT                                              *
*                                                           *
*   USAGE:                                                  *
*     in CLI:                                               *
*       type                                                *
*       'AUTOPORT <return>'                                 *
*                                                           *
*       Place it in the startup-sequence !                  *
*       Remove it by typing in some CLI :                   *
*       'AUTOPORT <return>'                                 *
*                                                           *
*     on WorkBench:                                         *
*       DoubleClick on Icon to start or stop it             *
*                                                           *
*   FUNCTION:                                               *
*     I use a trackball plugged into the second mouseport   *
*     and the mouse into the first port. AUTOPORT switches  *
*     the port that is used by the Input.device each time   *
*     one moves either mouse or trackball. So they can be   *
*     used as if they were both plugged in the first port.  *
*     When stopped mouse is activated.                      *
*                                                           *
*   BUGS:                                                   *
*     Don't know what it does when another task needs the   *
*     ports ( games ... )                                   *
*                                                           *
*   AUTHOR:                                                 *
*     Koessi                                                *
*     phone germany 02192 7630                              *
*                                                           *
*   VERSION:                                                *
*     1.1 august 91 - dcc_back added                        *
*     1.0 july   91 - my own fun                            *
*     Runs under DOS  1.3 & 2.0 / A3000                     *
*     It's public domain - have fun !                       *
*                                                           *
*   COMPILING:                                              *
*     Compiled by DICE - Matt Dillon's perfect C-compiler   *
*                           (I do have fun - thanx Matt)    *
*     I used DOS2.0 includes & amiga.lib.                   *
*     Libraries are opened automatically by DICE-startup!   *
*                                                           *
*     Included is dcc_back.o which detaches any DICE        *
*     compiled c-program that is dlinked with it.           *
*     See DmakeFile and dc_back.c for further details!      *
*                                                           *
*                                                           *
\***********************************************************/

#include <devices/inputevent.h>
#include <devices/input.h>
#include <devices/gameport.h>
#include <exec/memory.h>
#include <dos/dos.h>

__regargs void  port_io(struct IOStdReq *, BYTE, UWORD);
__regargs void  wait_msg(struct MsgPort *);

BOOL  open_game(void);
void  close_game(void);
BOOL  open_input(void);
void  close_input(void);
void  chg_mport(void);
void  send_msg(void);
void  write_out(void);

struct  MsgPort   *auto_port  = NULL;
struct  MsgPort   *input_port = NULL;
struct  IOStdReq  *input_req  = NULL;
struct  MsgPort   *game_port  = NULL;
struct  IOStdReq  *game_req   = NULL;

__aligned struct  InputEvent  input_event;

const char  autoport[]  = "autoport";
BYTE  gport_num   = 1;
BYTE  error       = 0;

int wbmain(void *foo)
{
  return(main());
}


/***********************  main  **************************/
int main(void)
{
  if (auto_port = (struct MsgPort *)FindPort(autoport))
    send_msg();               /*  if already there - kill it */
  else
  {
    write_out();                      /*  ON  */
    while (!(error && gport_num))     /*  quit only if port0! */
    {
      chg_mport();                    /*  init port1  */
      if (error)
        break;
                                      /*  toggle port       */
      if (gport_num)
        gport_num = 0;
      else
        gport_num = 1;

      if (open_game())                /*  open the unused port  */
        wait_msg(game_port);          /*  wait for readevents   */

      close_game();                   /*  close gameport    */
    }
    write_out();                      /*  OFF */
  }
  return(0);
}

/***********************  wait_msg  **************************/
__regargs void wait_msg(struct MsgPort *address)
{
  struct  Message *msg = (struct Message *)WaitPort(address);

  if (msg->mn_Node.ln_Name)
    error = 1;                /*  received send_msg call to remove */

  Forbid();
  ReplyMsg(msg);
  Permit();
}

/***********************  write_out  **************************/
const char on_win[] = "RAW:19/11/265/11/ © Koessi - autoport - ON  ";
const char offwin[] = "RAW:19/11/265/11/ © Koessi - autoport - OFF ";

void write_out(void)
{
  struct FileHandle *out;
  if (!error)
    out = (struct FileHandle *)Open(on_win , MODE_NEWFILE);
  else
    out = (struct FileHandle *)Open(offwin , MODE_NEWFILE);
  if (out)
  {
    Delay(80);
    Close(out);
  }
}

/***********************  open_input(void)  **************************/
const char input[] = "input.device";

BOOL open_input(void)                      /*  open input.device */
{
  if (input_port = (struct MsgPort  *)CreatePort( NULL, 0))

  if (input_req  = (struct IOStdReq *)CreateStdIO(input_port))

  if ((OpenDevice(input, 0, input_req, 0)) == 0)
    return(TRUE);

  error = 1;
  return(FALSE);
}

/***********************  close_input(void)  **************************/
void  close_input(void)                      /*  close input.device  */
{
  if (input_req)
  {
    if (input_req->io_Device)
      CloseDevice(input_req);

    DeleteStdIO(input_req);
  }

  if (input_port)
    DeletePort(input_port);
}

/***********************  port_io  **************************/
/*  perform exec/DoIO to deviceport ( data is only one byte ) */

__regargs void  port_io(struct IOStdReq *ioreq,  BYTE data,  UWORD command)
{
  ioreq->io_Data    = (APTR)&data;
  ioreq->io_Length  = (ULONG)1L;
  ioreq->io_Flags   = IOF_QUICK;
  ioreq->io_Command = command;

  Forbid();
  DoIO(ioreq);
  Permit();
}

/***********************  chg_mport(void)  **************************/
void  chg_mport(void)      /*  change mouseport used by input.device */
{
  if (open_input())
    port_io(input_req, gport_num, (UWORD)IND_SETMPORT);

  close_input();
}

/***********************  open_game(void)  **************************/
const char gameport[] = "gameport.device";

BOOL open_game(void)                       /*  open gameport.device */
{                                         /*  unit is gport_num     */
  if (game_port    = (struct MsgPort   *)CreatePort(autoport, 0))

  if (game_req     = (struct IOStdReq  *)CreateStdIO(game_port))

  if ((OpenDevice(gameport, gport_num, game_req, 0L)) == 0)
  {
    port_io(game_req, (BYTE)GPCT_MOUSE, (UWORD)GPD_SETCTYPE);

    game_req->io_Data    = (APTR)&input_event;
    game_req->io_Length  = (ULONG)sizeof(struct InputEvent);
    game_req->io_Command = (UWORD)GPD_READEVENT;

    SendIO(game_req);
    return(TRUE);
  }
  error = 1;
  return(FALSE);
}

/***********************  close_game(void)  **************************/
void  close_game(void)                     /*  close gameport.device */
{
  if (CheckIO(game_req) == 0)              /*  SendIO not done ???   */
    AbortIO(game_req);
                                           /*  free gameport */
  port_io(game_req, (BYTE)GPCT_NOCONTROLLER, (UWORD)GPD_SETCTYPE);

  if (game_req)
  {
    if (game_req->io_Device)
      CloseDevice(game_req);

    DeleteStdIO(game_req);
  }

  if (game_port)
    DeletePort(game_port);
}

/***********************  send_msg(void)  **************************/
void send_msg(void)                      /*  send message to do error  */
{
  __aligned struct Message msg;

  struct  MsgPort *msg_port = NULL;

  if (msg_port = (struct MsgPort *)CreatePort(NULL, 0))
  {
    msg.mn_ReplyPort    = msg_port;
    msg.mn_Node.ln_Name = autoport;  /*  identifier  */
    msg.mn_Node.ln_Type = NT_MESSAGE;

    PutMsg(auto_port,(struct Message *)&msg);

    WaitPort(msg_port);                 /*  wait for reply  */

    DeletePort(msg_port);
  }
}

/***********************   \8-)  **************************/


