From e8f67c9e416fe0cbbe8a70e85841c71047fa56af Mon Sep 17 00:00:00 2001 From: jmcmullan Date: Tue, 4 Jun 2013 03:24:57 +0000 Subject: [PATCH] amiga-m68k/lowlevel.library: Add support for ReadJoyPort() Limited to JP_TYPE_JOYSTK for now, until I can find someone to do CD32 joypad testing. CD32 Trolls! is now playable! Signed-off-by: Jason S. McMullan git-svn-id: https://svn.aros.org/svn/aros/trunk/AROS@47505 fb15a70f-31f2-0310-bbcc-cdcc74a49acc --- arch/m68k-amiga/lowlevel/lowlevel_amiga.c | 26 +++ arch/m68k-amiga/lowlevel/mmakefile.src | 15 ++ arch/m68k-amiga/lowlevel/readjoyport.c | 253 ++++++++++++++++++++++++++++ arch/m68k-amiga/lowlevel/setjoyportattrsa.c | 50 ++++++ workbench/libs/lowlevel/lowlevel_intern.h | 4 + 5 files changed, 348 insertions(+) create mode 100644 arch/m68k-amiga/lowlevel/lowlevel_amiga.c create mode 100644 arch/m68k-amiga/lowlevel/mmakefile.src create mode 100644 arch/m68k-amiga/lowlevel/readjoyport.c create mode 100644 arch/m68k-amiga/lowlevel/setjoyportattrsa.c diff --git a/arch/m68k-amiga/lowlevel/lowlevel_amiga.c b/arch/m68k-amiga/lowlevel/lowlevel_amiga.c new file mode 100644 index 0000000000..56a283f348 --- /dev/null +++ b/arch/m68k-amiga/lowlevel/lowlevel_amiga.c @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2013, The AROS Development Team + * All right reserved. + * Author: Jason S. McMullan + * + * Licensed under the AROS PUBLIC LICENSE (APL) Version 1.1 + */ + +#include + +#include + +#include "lowlevel_intern.h" + +static int Lowlevel_amiga_InitLib(struct LowLevelBase *LowLevelBase) +{ + LowLevelBase->ll_PotgoBase = OpenResource("potgo.resource"); + if (LowLevelBase->ll_PotgoBase == NULL) + return 0; + + LowLevelBase->ll_PortType[0] = 0; /* Autosense */ + LowLevelBase->ll_PortType[1] = 0; /* Autosense */ + return 1; +} + +ADD2INITLIB(Lowlevel_amiga_InitLib, 40) diff --git a/arch/m68k-amiga/lowlevel/mmakefile.src b/arch/m68k-amiga/lowlevel/mmakefile.src new file mode 100644 index 0000000000..f37a28c471 --- /dev/null +++ b/arch/m68k-amiga/lowlevel/mmakefile.src @@ -0,0 +1,15 @@ +# $Id: mmakefile.src $ +include $(TOP)/config/make.cfg + +FILES := readjoyport \ + setjoyportattrsa \ + lowlevel_amiga + +USER_INCLUDES += -I$(SRCDIR)/workbench/libs/lowlevel + +%build_archspecific \ + mainmmake=workbench-libs-lowlevel maindir=workbench/libs/lowlevel \ + arch=amiga-m68k \ + files="$(FILES)" + +%common diff --git a/arch/m68k-amiga/lowlevel/readjoyport.c b/arch/m68k-amiga/lowlevel/readjoyport.c new file mode 100644 index 0000000000..3a34bb7465 --- /dev/null +++ b/arch/m68k-amiga/lowlevel/readjoyport.c @@ -0,0 +1,253 @@ +/* + Copyright © 2013, The AROS Development Team. All rights reserved. + $Id$ + + Desc: + Lang: english +*/ + +#include + +#include +#include +#include + +#include + +#include + +#include +#include + +#include "lowlevel_intern.h" + +#define POTGO_GAMEPAD_PORT0 \ + (1 << 11) | (1 << 10) | (1 << 9) | (1 << 8) +#define POTGO_GAMEPAD_PORT1 \ + (1 << 15) | (1 << 14) | (1 << 13) | (1 << 12) + +/* + * ciaapra - (1 << 7) is /FIR1 (port 1, pin 6) + * ciaapra - (1 << 6) is /FIR0 (port 0, pin 6) + * ciaaddra - 0x03 + * JOYnDAT: + * pin 1 (up) = ((JOYnDAT >> 0) ^ (JOYnDAT >> 1)) & 1 + * pin 2 (dn) = ((JOYnDAT >> 8) ^ (JOYnDAT >> 9)) & 1 + * pin 3 (lt) = (JOYnDAT >> 9) & 1 + * pin 4 (rt) = (JOYnDAT >> 1) & 1 + * POTGO/POTINP: + * port 0: pin 9 (1 << 10), pin 5 (1 << 8) + * port 1: pin 9 (1 << 14), pin 5 (1 << 12) + */ +static inline ULONG llPollGameCtrl(int port) +{ + volatile struct Custom *custom = (struct Custom*)0xdff000; + volatile struct CIA *cia = (struct CIA *)0xbfe001; + UWORD pot; + ULONG bits = 0; + UWORD joydat; + int i; + UBYTE cmask = (port == 0) ? (1 << 6) : (1 << 7); + + /* Set Pin 5 as output, shift mode */ + pot = custom->potinp; + pot &= ~((port == 0) ? (3 << 8) : (3 << 12)); + custom->potgo = pot | (port == 0) ? (2 << 8) : (2 << 12); + cia->ciapra &= ~cmask; + cia->ciaddra |= cmask; + + /* Shift in the button values */ + D(bug("Sin: \n")); + for (i = 0; i < 9; i++) { + cia->ciapra |= cmask; + cia->ciapra &= ~cmask; + bits <<= 1; + bits |= ((custom->potinp >> ((port == 0) ? 10 : 14)) & 1) ? 0 : 1; + D(bug(" %d", bits & 1)); + } + D(bug("\n")); + + cia->ciapra &= ~cmask; + custom->potgo = pot; + + if ((bits & 3) != 2) { + /* Stuck bits? Probably not a game controller */ + D(bug("%s: Stuck bits? (0x%04x)\n", __func__, bits)); + /* Revert to autosense */ + return 0; + } + bits &= ~3; + bits <<= 15; + + /* Get the joypad bits */ + joydat = (port == 0) ? custom->joy0dat : custom->joy1dat; + + if ((joydat >> 1) & 1) { + bits |= JPF_JOY_RIGHT; + } + if ((joydat >> 9) & 1) { + bits |= JPF_JOY_LEFT; + } + if (((joydat >> 0) ^ (joydat >> 1)) & 1) { + bits |= JPF_JOY_DOWN; + } + if (((joydat >> 8) ^ (joydat >> 9)) & 1) { + bits |= JPF_JOY_UP; + } + + return JP_TYPE_GAMECTLR | bits; +} + +/* + * ciaapra - (1 << 7) is /FIR1 (port 2, pin 6) + * ciaapra - (1 << 6) is /FIR0 (port 1, pin 6) + * ciaaddra - 0x03 + * JOYnDAT: + * pin 1 (up) = ((JOYnDAT >> 0) ^ (JOYnDAT >> 1)) & 1 + * pin 2 (dn) = ((JOYnDAT >> 8) ^ (JOYnDAT >> 9)) & 1 + * pin 3 (lt) = (JOYnDAT >> 9) & 1 + * pin 4 (rt) = (JOYnDAT >> 1) & 1 + * POTGO/POTINP: + * port 1: pin 9 (1 << 10), pin 5 (1 << 8) + * port 2: pin 9 (1 << 14), pin 5 (1 << 12) + */ +static inline ULONG llPollJoystick(int port) +{ + volatile struct Custom *custom = (struct Custom*)0xdff000; + volatile struct CIA *cia = (struct CIA *)0xbfe001; + ULONG bits = 0; + UWORD joydat; + UBYTE cmask = (port == 0) ? (1 << 6) : (1 << 7); + + /* 'red' - /FIRn on CIA Port A */ + bits |= (cia->ciapra & cmask) ? 0 : JPF_BUTTON_RED; + + /* 'blue' - Pin 9 on POTINP */ + bits |= ((custom->potinp >> ((port == 0) ? 10 : 14)) & 1) ? 0 : JPF_BUTTON_BLUE; + + /* Get the joypad bits */ + joydat = (port == 0) ? custom->joy0dat : custom->joy1dat; + + if ((joydat >> 1) & 1) { + bits |= JPF_JOY_RIGHT; + } + if ((joydat >> 9) & 1) { + bits |= JPF_JOY_LEFT; + } + if (((joydat >> 0) ^ (joydat >> 1)) & 1) { + bits |= JPF_JOY_DOWN; + } + if (((joydat >> 8) ^ (joydat >> 9)) & 1) { + bits |= JPF_JOY_UP; + } + + return JP_TYPE_JOYSTK | bits; +} + + +ULONG llPortOpen(struct LowLevelBase *LowLevelBase, int port, UWORD *bits) +{ + UWORD potbits, potres; + ULONG type = LowLevelBase->ll_PortType[port]; + struct Library *PotgoBase = LowLevelBase->ll_PotgoBase; + volatile struct Custom *custom = (struct Custom*)0xdff000; + + if (type == 0 || type == JP_TYPE_GAMECTLR || type == JP_TYPE_JOYSTK) { + if (port == 0) + potbits = POTGO_GAMEPAD_PORT0; + else + potbits = POTGO_GAMEPAD_PORT1; + potres = AllocPotBits(potbits); + if (potres != potbits) { + D(bug("%s: Can't allocate PotGo bits 0x%04x\n", __func__)); + + FreePotBits(potres); + type = JP_TYPE_NOTAVAIL; + PotgoBase = NULL; + } else { + /* Set Pin 5 as output, load mode */ + UWORD pot; + pot = custom->potinp; + pot &= ~((port == 0) ? (3 << 8) : (3 << 12)); + custom->potgo = pot | ((port == 0) ? (3 << 8) : (3 << 12)); + } + } else { + /* No Potgo bits allocated */ + potbits = 0; + } + + /* Handle autosense */ + if (type == 0) { + type = llPollGameCtrl(port); + if (type == 0) + type = JP_TYPE_JOYSTK; + LowLevelBase->ll_PortType[port] = type & JP_TYPE_MASK; + D(bug("%s: Autosense: 0x%08x\n", __func__, LowLevelBase->ll_PortType[port])); + } + + *bits = potbits; + return type; +} + +static VOID llPortClose(struct LowLevelBase *LowLevelBase, int port, UWORD potbits) +{ + struct Library *PotgoBase = LowLevelBase->ll_PotgoBase; + + if (potbits) { + FreePotBits(potbits); + } +} + +/***************************************************************************** + + NAME */ + + AROS_LH1(ULONG, ReadJoyPort, + +/* SYNOPSIS */ + AROS_LHA(ULONG, port, D0), + +/* LOCATION */ + struct LowLevelBase *, LowLevelBase, 5, LowLevel) + +/* FUNCTION + + INPUTS + + RESULT + + BUGS + + INTERNALS + +*****************************************************************************/ +{ + AROS_LIBFUNC_INIT + +// D(bug("%s: Port %d\n", __func__, port)); + + if (port == 0 || port == 1) { + ULONG state, type; + UWORD potbits; + + type = llPortOpen(LowLevelBase, port, &potbits); + switch (type) { + case JP_TYPE_GAMECTLR: + state = llPollGameCtrl(port); + break; + case JP_TYPE_JOYSTK: + state = llPollJoystick(port); + break; + default: + state = JP_TYPE_UNKNOWN; + break; + } + llPortClose(LowLevelBase, port, potbits); + + return state; + } + + return JP_TYPE_NOTAVAIL; // return failure until implemented + + AROS_LIBFUNC_EXIT +} /* ReadJoyPort */ diff --git a/arch/m68k-amiga/lowlevel/setjoyportattrsa.c b/arch/m68k-amiga/lowlevel/setjoyportattrsa.c new file mode 100644 index 0000000000..502b8e1deb --- /dev/null +++ b/arch/m68k-amiga/lowlevel/setjoyportattrsa.c @@ -0,0 +1,50 @@ +/* + Copyright © 1995-2007, The AROS Development Team. All rights reserved. + $Id$ + + Desc: + Lang: English +*/ + +#include + +#include + +/***************************************************************************** + + NAME */ + + AROS_LH2(BOOL, SetJoyPortAttrsA, + +/* SYNOPSIS */ + AROS_LHA(ULONG, portNumber, D0), + AROS_LHA(struct TagItem *, tagList, A1), + +/* LOCATION */ + struct LowLevelBase *, LowLevelBase, 22, LowLevel) + +/* FUNCTION + + INPUTS + + RESULT + + BUGS + + SEE ALSO + + INTERNALS + +*****************************************************************************/ +{ + AROS_LIBFUNC_INIT + struct TagItem *ti; + + while ((ti = LibNextTagItem(&tagList)) != NULL) { + D(bug("%s: Tag %d = %p\n", __func__, ti->ti_Tag, (APTR)ti->ti_Data)); + } + return FALSE; + + AROS_LIBFUNC_EXIT + +} /* SetJoyPortAttrsA */ diff --git a/workbench/libs/lowlevel/lowlevel_intern.h b/workbench/libs/lowlevel/lowlevel_intern.h index 0cb6bf91a1..37c0c3a920 100644 --- a/workbench/libs/lowlevel/lowlevel_intern.h +++ b/workbench/libs/lowlevel/lowlevel_intern.h @@ -31,6 +31,10 @@ struct LowLevelBase struct SignalSemaphore ll_Lock; struct Interrupt ll_VBlank; BPTR ll_SegList; + + /* Variables used by amiga-m68k */ + ULONG ll_PortType[2]; + struct Library *ll_PotgoBase; }; /* -- 2.11.4.GIT