ControlPad Library Version 1.0 Copyright ©1995 by Randall Richards and Joseph Carlson. March 11, 1995 The 'ControlPad.Library' and all files in this archive are Copyright ©1995 by Joseph Carlson and Randall Richards, but are freely distributable as a whole archive if left unmodified. The file 'ControlPad.library' may be included with freely distributable games if we are notified by email AND credit is given to Joseph Carlson and Randall Richards. (Just using the function cpShowLogo() qualifies as credit.) Requirements: Any Amiga with AmigaDOS 2.0 or higher. Recommended: CP-1 ControlPad Adapter required for accessing all of the buttons on a Sega ControlPad. Installation: Copy 'ControlPad.Library' to your LIBS: directory. Programmers should copy 'ControlPad.h' to the appropriate includes directory (for SAS/C this is 'include:libraries'.) Description: This library allows programmers to effortlessly include support for joysticks and Sega Genesis(TM) compatible ControlPads (including the extra buttons that can't be found on conventional joysticks for the Amiga.) Files included in this archive: controlpad.doc - what you're reading... controlpad.h - an include file for use with your own code. controlpad.library - the library itself. cp-1.doc - info on the CP-1 adapter. cpTest - a program for testing ControlPads and Adapters cpTest.doc - docs for cpTest. cpTest.lbm - picture file used by cpTest. cp_example - an ugly example program. cp_example.c - source for example showing how easy it is to use the library. -- Introduction ----------------------- This library allows programs to read Sega Genesis(TM) type ControlPads that are plugged into the Amiga via the CP-1 ControlPad Adapter. Standard joysticks are also supported with or without the adapter. Library functions include the ability to allocate and read either or both game ports on the Amiga, disable the mouse, test for adapters, check for controller type, as well as a nice title graphics that fade in and out (AGA/ECS aware). All this in a little 14k library (which includes the graphics data). Further information on the CP-1 ControlPad Adapter is in the file 'CP-1.doc'. -- Library Functions ------------------ The library functions contain references of the following: 'CPHANDLE' is a type definition (typedef void * CPHANDLE). It is a handle used by the library to keep track of what program has what allocated. 'unit' contains flags for defining what ports are being used. See the 'CPU_...' defines described in 'controlpad.h'. The function cpGet() returns a bit-packed UWORD which fully describes the condition of the port. See the 'CPF_...' defines in the h file for the meaning of all 16 bits. Here are the library functions: CPHANDLE cpAlloc(UBYTE unit); Purpose: Allocates one or both ports for use. Needs: unit - must be one of the following: CPU_MOUSEPORT, CPU_JOYPORT, or CPU_BOTHPORTS. Returns: a CPHANDLE pointer if successful, or NULL if allocation failed. Comments: If 'unit' includes the mouseport, then the gameport.device Vertical Blank Routine is temporarily removed (This disables polling of the the mouse.) void cpFree(CPHANDLE cph); Purpose: Frees memory associated with the handle. Re-installs the "gameport.device" vertical blank interrupt if the mouseport is no longer being used by the library. Needs: cph - the CPHANDLE allocated with cpAlloc() or cpReAlloc(). Comments: cph is now invalid and can no longer be used by any function (Bad things will happen if you try...). UWORD cpGet(CPHANDLE cph, UBYTE unit); Purpose: Reads the ControlPad in the specified port(s). Needs: cph - an allocated CPHANDLE. unit - the port to read. Returns: a packed UWORD with 16 bits of information about 'unit'. Bits include direction, all buttons, type of controller, etc. See below and CPB_xxx defines in 'controlpad.h'. Comments: This function does not queue up events in any way. It only returns real-time information. If CPU_BOTHPORTS is specified, result is both ControlPads OR'd together (useful for waiting for the START button on either controller). The combination of CPF_UP, CPF_DOWN, CPF_LEFT, and CPF_RIGHT bits bits that are set (1) indicate current direction being pressed on the joystick or controlpad. The CPF_A, CPF_B, CPF_C, and CPF_START bits that are set (1) indicate the buttons that are currently being pressed on the controlpad. If a joystick is being used, CPF_B returns the joystick fire button. When set, the CPF_3BUTTON bit indicates the presence of a controlpad. When clear (0), this bit indicates a joystick or other controller is attached. CPF_INUSE indicates wether the port has been allocated (1) or not (0). CPF_ERROR indicates the library detected an error when reading the port. The error could mean there is a mouse plugged in or a hardware problem. The bits returned by cpGet() should only be considered valid if CPF_INUSE is set and CPF_ERROR is clear. The CPF_X,_Y,_Z, and _MODE may be supported in future versions if I can figure out how to read those buttons. (Please contact me if you have any information on how they are read in...) CPHANDLE cpReAlloc(CPHANDLE cph, UBYTE unit); Purpose: This is used when you want to change what units are allocated by the handle. This function actually calls cpFree() followed by a cpAllocate(). Needs: cph - the CPHANDLE allocated with cpAlloc() or cpReAlloc(). unit - the new port(s) to be allocated for use. Returns: A new CPHANDLE with the specified ports allocated or NULL if allocation failed. Comments: 'cph' is now invalid and should not be freed. The returned CPHANDLE should be used for further function calls and must be freed before program termination. A suggested use is: cph = cpRealloc(cph, unit); This redefines cph so it is valid again and avoids need for extra variables. UBYTE cpLock(CPHANDLE cph, UBYTE unit); Purpose: To lock a port from being allocated by another program. Needs: cph - a valid CPHANDLE. unit - the unit to lock (must not be in use by any program) Returns: the 'unit' successfully locked. See CPU_xxx defines. Comments: Really only useful for keeping other programs that use this library from disabling the mouse. UBYTE cpUnLock(CPHANDLE cph, UBYTE unit); Purpose: To unlock a port that was locked with cpLock(). Needs: cph - the CPHANDLE used to lock the port. unit - the unit to unlock. Returns: the 'unit' successfully unlocked. See CPU_xxx defines. UBYTE cpUnit(CPHANDLE cph); Purpose: Tells you what ports are allocated by the CPHANDLE. Needs: cph - an allocated CPHANDLE. Returns: the 'unit' currently allocated by cph. See CPU_xxx defines in 'controlpad.h' UBYTE cpTest(); Purpose: To test for CP-1 ControlPad Adapters. Returns: the 'unit's that currently have a ControlPad Adapter installed. Comments: This does not test what type of controller is in the port. cpGet() will tell you controller type. This is useful if you want a 'CP-1 Adapter Detected' type message. void cpShowLogo(int time); Purpose: Fades in and out a nice hires logo stating 'CP-1 ControlPad Adapter supported' message. Needs: time - the number of ticks (50 or 60ths of a second) to keep the logo on screen between fade in and fade out. A value of at least 120 is recommended. Comments: The current View is saved before the controlpad logo screen is displayed, and restored upon completion. This means you can open your own screen with Intuition or your own custom View (system unfriendly way) and it will still be put back up in front for you when the function completes. This display even utilizes an AGA mode (with Intuition) if available! Please, please, please show this off in your programs! -- Sample Code ------------------------ The file 'cp_example.c' shows an example of how to incorporate this library into your own code. To also help, here is some more sample code: #include // Contains all defines and function pragmas void piece_of_code () { struct Library *ControlPadBase; // Must be 'ControlPadBase' CPHANDLE cph = NULL; UWORD cpad, cpad2; int x, y; // Try to Open the Library... if (ControlPadBase = OpenLibrary(ControlPadName, 0)) { // Display fancy logo screen... cpShowLogo(120); // Allocate both ports... if (cph = cpAlloc(CPU_BOTHPORTS)) { do // Wait for either Start button... { WaitTOF(); cpad = cpGet(cph, CPU_BOTHPORTS); } while (!(cpad & CPF_START)); do // get both ports separately and { // do something with them... cpad = cpGet(cph, CPU_MOUSEPORT); cpad2 = cpGet(cph, CPU_JOYPORT); done = doSomething(cpad, cpad2); // loop until done or 'A' button is // pressed on joyport controlpad... } while (!done || !(cpad2 & CPF_A)); // free only the mouseport and // save our new cpHandle... if (cph = cpReAlloc(cph, CPU_JOYPORT)) { // Lock the mouseport... if (cpLock(cph, CPU_MOUSEPORT) != CPU_MOUSEPORT) printf("cpLock() failed!\n"); do // get just joyport controlpad info { // and work with it... cpad = cpGet(cph, CPU_JOYPORT); // calculate delta x and y from cpad. x = ((cpad & CPF_RIGHT) != 0) - ((cpad & CPF_LEFT) != 0); y = ((cpad & CPF_DOWN) != 0) - ((cpad & CPF_UP) != 0); done = doSomethingElse1(x, y); } while (!done); // UnLock the mouseport... if (cpUnLock(cph, CPU_MOUSEPORT) != CPU_MOUSEPORT) printf("cpUnLock() failed!\n"); } else printf("cpReAlloc() failed.\n"); // Free our handle... cpFree(cph); } else printf("cpAlloc() failed.\n"); // Close Library... CloseLibrary(ControlPadBase); } else printf("Could not open controlpad.library!\n); } ----- 'Sega' and 'Genesis' are trademarks of SEGA. 'Amiga' is nobody's trademark. :^(