WIP games are booting in Qt now
This commit is contained in:
parent
1e01001af4
commit
084628acc2
|
@ -50,25 +50,25 @@ jobs:
|
|||
detail: " nopch"
|
||||
secrets: inherit
|
||||
|
||||
# build_linux_qt_sse4:
|
||||
# name: "AppImage"
|
||||
# uses: ./.github/workflows/linux_build_qt.yml
|
||||
# with:
|
||||
# jobName: "Qt SSE4"
|
||||
# compiler: clang
|
||||
# cmakeflags: ""
|
||||
# simd: "SSE4"
|
||||
# buildAppImage: true
|
||||
# secrets: inherit
|
||||
build_linux_qt_sse4:
|
||||
name: "AppImage"
|
||||
uses: ./.github/workflows/linux_build_qt.yml
|
||||
with:
|
||||
jobName: "Qt SSE4"
|
||||
compiler: clang
|
||||
cmakeflags: ""
|
||||
simd: "SSE4"
|
||||
buildAppImage: true
|
||||
secrets: inherit
|
||||
|
||||
# build_linux_qt_avx2:
|
||||
# name: "AppImage"
|
||||
# uses: ./.github/workflows/linux_build_qt.yml
|
||||
# with:
|
||||
# jobName: "Qt AVX2"
|
||||
# detail: ""
|
||||
# compiler: clang
|
||||
# cmakeflags: "-DARCH_FLAG=-march=haswell"
|
||||
# simd: "AVX2"
|
||||
# buildAppImage: true
|
||||
# secrets: inherit
|
||||
build_linux_qt_avx2:
|
||||
name: "AppImage"
|
||||
uses: ./.github/workflows/linux_build_qt.yml
|
||||
with:
|
||||
jobName: "Qt AVX2"
|
||||
detail: ""
|
||||
compiler: clang
|
||||
cmakeflags: "-DARCH_FLAG=-march=haswell"
|
||||
simd: "AVX2"
|
||||
buildAppImage: true
|
||||
secrets: inherit
|
||||
|
|
|
@ -8,18 +8,18 @@ on:
|
|||
branches:
|
||||
- master
|
||||
|
||||
# jobs:
|
||||
# build_macos_wx:
|
||||
# name: "Defaults"
|
||||
# uses: ./.github/workflows/macos_build.yml
|
||||
# with:
|
||||
# jobName: "wxWidgets"
|
||||
# gui: "wxWidgets"
|
||||
# secrets: inherit
|
||||
# build_macos_qt:
|
||||
# name: "Defaults"
|
||||
# uses: ./.github/workflows/macos_build.yml
|
||||
# with:
|
||||
# jobName: "Qt"
|
||||
# gui: "Qt"
|
||||
# secrets: inherit
|
||||
jobs:
|
||||
# build_macos_wx:
|
||||
# name: "Defaults"
|
||||
# uses: ./.github/workflows/macos_build.yml
|
||||
# with:
|
||||
# jobName: "wxWidgets"
|
||||
# gui: "wxWidgets"
|
||||
# secrets: inherit
|
||||
build_macos_qt:
|
||||
name: "Defaults"
|
||||
uses: ./.github/workflows/macos_build.yml
|
||||
with:
|
||||
jobName: "Qt"
|
||||
gui: "Qt"
|
||||
secrets: inherit
|
||||
|
|
|
@ -49,6 +49,7 @@ declare -a PCSX2_PACKAGES=(
|
|||
"libsamplerate0-dev"
|
||||
"libsoundtouch-dev"
|
||||
"libudev-dev"
|
||||
"libusb-1.0-0-dev"
|
||||
"libx11-xcb-dev"
|
||||
"pkg-config"
|
||||
"zlib1g-dev"
|
||||
|
|
|
@ -26,8 +26,8 @@ declare -a PCSX2_PACKAGES=(
|
|||
"librsvg2-dev"
|
||||
"libsamplerate0-dev"
|
||||
"libsoundtouch-dev"
|
||||
"libusb-1.0-0-dev"
|
||||
"libudev-dev"
|
||||
"libusb-1.0-0-dev"
|
||||
"libwxgtk3.0-gtk3-dev"
|
||||
"libx11-xcb-dev"
|
||||
"pkg-config"
|
||||
|
|
|
@ -15,6 +15,7 @@ JPG=9e
|
|||
SAMPLERATE=libsamplerate-0.1.9
|
||||
PORTAUDIO=pa_stable_v190700_20210406
|
||||
SOUNDTOUCH=soundtouch-2.3.1
|
||||
LIBUSB=1.0.26
|
||||
WXWIDGETS=3.1.6
|
||||
QT=6.3.1
|
||||
|
||||
|
@ -38,6 +39,7 @@ fe7cbf3127882e3fc7259a75a0cb585620272c51745d3852ab9dd87960697f2e $SDL.tar.gz
|
|||
7b19f418e6f7b8e23344082dd04440aacf5da23c5a73980ba22ae4eba4f87df7 qtsvg-everywhere-src-$QT.tar.xz
|
||||
c412750f2aa3beb93fce5f30517c607f55daaeb7d0407af206a8adf917e126c1 qttools-everywhere-src-$QT.tar.xz
|
||||
d7bdd55e2908ded901dcc262157100af2a490bf04d31e32995f6d91d78dfdb97 qttranslations-everywhere-src-$QT.tar.xz
|
||||
12ce7a61fc9854d1d2a1ffe095f7b5fac19ddba095c259e6067a46500381b5a5 libusb-$LIBUSB.tar.bz2
|
||||
EOF
|
||||
|
||||
curl -L \
|
||||
|
@ -52,6 +54,7 @@ curl -L \
|
|||
-O "https://download.qt.io/official_releases/qt/${QT%.*}/$QT/submodules/qtsvg-everywhere-src-$QT.tar.xz" \
|
||||
-O "https://download.qt.io/official_releases/qt/${QT%.*}/$QT/submodules/qttools-everywhere-src-$QT.tar.xz" \
|
||||
-O "https://download.qt.io/official_releases/qt/${QT%.*}/$QT/submodules/qttranslations-everywhere-src-$QT.tar.xz" \
|
||||
-O "https://github.com/libusb/libusb/releases/download/v$LIBUSB/libusb-$LIBUSB.tar.bz2" \
|
||||
|
||||
shasum -a 256 --check SHASUMS
|
||||
|
||||
|
@ -104,6 +107,14 @@ make -C build "-j$NPROCS"
|
|||
make -C build install
|
||||
cd ..
|
||||
|
||||
echo "Installing libusb..."
|
||||
tar xf "libusb-$LIBUSB.tar.bz2"
|
||||
cd "libusb-$LIBUSB"
|
||||
./configure --prefix "$INSTALLDIR" --enable-mac-universal=no
|
||||
make "-j$NPROCS"
|
||||
make install
|
||||
cd ..
|
||||
|
||||
if [ "$GUI" == "wxWidgets" ]; then
|
||||
echo "Installing wx..."
|
||||
tar xf "wxWidgets-$WXWIDGETS.tar.bz2"
|
||||
|
|
|
@ -38,24 +38,24 @@ jobs:
|
|||
configuration: Release AVX2
|
||||
secrets: inherit
|
||||
|
||||
# build_qt_sse4:
|
||||
# needs: lint_vs_proj_files
|
||||
# name: "SSE4"
|
||||
# uses: ./.github/workflows/windows_build_qt.yml
|
||||
# with:
|
||||
# jobName: Qt
|
||||
# configuration: Release
|
||||
# simd: "SSE4"
|
||||
# secrets: inherit
|
||||
build_qt_sse4:
|
||||
needs: lint_vs_proj_files
|
||||
name: "SSE4"
|
||||
uses: ./.github/workflows/windows_build_qt.yml
|
||||
with:
|
||||
jobName: Qt
|
||||
configuration: Release
|
||||
simd: "SSE4"
|
||||
secrets: inherit
|
||||
|
||||
# build_qt_avx2:
|
||||
# needs: lint_vs_proj_files
|
||||
# name: "AVX2"
|
||||
# uses: ./.github/workflows/windows_build_qt.yml
|
||||
# with:
|
||||
# jobName: Qt
|
||||
# configuration: Release AVX2
|
||||
# secrets: inherit
|
||||
build_qt_avx2:
|
||||
needs: lint_vs_proj_files
|
||||
name: "AVX2"
|
||||
uses: ./.github/workflows/windows_build_qt.yml
|
||||
with:
|
||||
jobName: Qt
|
||||
configuration: Release AVX2
|
||||
secrets: inherit
|
||||
|
||||
# CMAKE
|
||||
# build_wx_avx2_cmake:
|
||||
|
|
|
@ -39,3 +39,6 @@
|
|||
[submodule "3rdparty/zstd/zstd"]
|
||||
path = 3rdparty/zstd/zstd
|
||||
url = https://github.com/facebook/zstd.git
|
||||
[submodule "3rdparty/libusb/libusb"]
|
||||
path = 3rdparty/libusb/libusb
|
||||
url = https://github.com/libusb/libusb.git
|
||||
|
|
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -1,61 +0,0 @@
|
|||
libusb 1.0 Windows binary snapshot - README
|
||||
|
||||
*********************************************************************
|
||||
* The latest version of this snapshot can always be downloaded at: *
|
||||
* https://sourceforge.net/projects/libusb/files/ *
|
||||
*********************************************************************
|
||||
|
||||
o Visual Studio:
|
||||
- Open existing or create a new project for your application
|
||||
- Copy libusb.h, from the include\libusb-1.0\ directory, into your project and
|
||||
make sure that the location where the file reside appears in the 'Additional
|
||||
Include Directories' section (Configuration Properties -> C/C++ -> General).
|
||||
- Copy the relevant .lib file from MS32\ or MS64\ and add 'libusb-1.0.lib' to
|
||||
your 'Additional Dependencies' (Configuration Properties -> Linker -> Input)
|
||||
Also make sure that the directory where libusb-1.0.lib resides is added to
|
||||
'Additional Library Directories' (Configuration Properties -> Linker
|
||||
-> General)
|
||||
- If you use the static version of the libusb library, make sure that
|
||||
'Runtime Library' is set to 'Multi-threaded DLL (/MD)' (Configuration
|
||||
Properties -> C/C++ -> Code Generation).
|
||||
NB: If your application requires /MT (Multi-threaded/libCMT), you need to
|
||||
recompile a static libusb 1.0 library from source.
|
||||
- Compile and run your application. If you use the DLL version of libusb-1.0,
|
||||
remember that you need to have a copy of the DLL either in the runtime
|
||||
directory or in system32
|
||||
|
||||
o WDK/DDK:
|
||||
- The following is an example of a sources files that you can use to compile
|
||||
a libusb 1.0 based console application. In this sample ..\libusb\ is the
|
||||
directory where you would have copied libusb.h as well as the relevant
|
||||
libusb-1.0.lib
|
||||
|
||||
TARGETNAME=your_app
|
||||
TARGETTYPE=PROGRAM
|
||||
USE_MSVCRT=1
|
||||
UMTYPE=console
|
||||
INCLUDES=..\libusb;$(DDK_INC_PATH)
|
||||
TARGETLIBS=..\libusb\libusb-1.0.lib
|
||||
SOURCES=your_app.c
|
||||
|
||||
- Note that if you plan to use libCMT instead of MSVCRT (USE_LIBCMT=1 instead
|
||||
of USE_MSVCRT=1), you will need to recompile libusb to use libCMT. This can
|
||||
easily be achieved, in the DDK environment, by running 'ddk_build /MT'
|
||||
|
||||
o MinGW/cygwin
|
||||
- Copy libusb.h, from include/libusb-1.0/ to your default include directory,
|
||||
and copy the MinGW32/ or MinGW64/ .a files to your default library directory.
|
||||
Or, if you don't want to use the default locations, make sure that you feed
|
||||
the relevant -I and -L options to the compiler.
|
||||
- Add the '-lusb-1.0' linker option when compiling.
|
||||
|
||||
o Additional information:
|
||||
- The libusb 1.0 API documentation can be accessed at:
|
||||
http://api.libusb.info
|
||||
- For some libusb samples (including source), please have a look in examples/
|
||||
- For additional information on the libusb 1.0 Windows backend please visit:
|
||||
http://windows.libusb.info
|
||||
- The MinGW and MS generated DLLs are fully interchangeable, provided that you
|
||||
use the import libs provided or generate one from the .def also provided.
|
||||
- If you find any issue, please visit http://libusb.info/ and check the
|
||||
Support section
|
|
@ -1,831 +0,0 @@
|
|||
/*
|
||||
* Copyright © 2001 Stephen Williams (steve@icarus.com)
|
||||
* Copyright © 2001-2002 David Brownell (dbrownell@users.sourceforge.net)
|
||||
* Copyright © 2008 Roger Williams (rawqux@users.sourceforge.net)
|
||||
* Copyright © 2012 Pete Batard (pete@akeo.ie)
|
||||
* Copyright © 2013 Federico Manzan (f.manzan@gmail.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "libusb.h"
|
||||
#include "ezusb.h"
|
||||
|
||||
extern void logerror(const char *format, ...)
|
||||
__attribute__ ((format(printf, 1, 2)));
|
||||
|
||||
/*
|
||||
* This file contains functions for uploading firmware into Cypress
|
||||
* EZ-USB microcontrollers. These chips use control endpoint 0 and vendor
|
||||
* specific commands to support writing into the on-chip SRAM. They also
|
||||
* support writing into the CPUCS register, which is how we reset the
|
||||
* processor after loading firmware (including the reset vector).
|
||||
*
|
||||
* These Cypress devices are 8-bit 8051 based microcontrollers with
|
||||
* special support for USB I/O. They come in several packages, and
|
||||
* some can be set up with external memory when device costs allow.
|
||||
* Note that the design was originally by AnchorChips, so you may find
|
||||
* references to that vendor (which was later merged into Cypress).
|
||||
* The Cypress FX parts are largely compatible with the Anchorhip ones.
|
||||
*/
|
||||
|
||||
int verbose = 1;
|
||||
|
||||
/*
|
||||
* return true if [addr,addr+len] includes external RAM
|
||||
* for Anchorchips EZ-USB or Cypress EZ-USB FX
|
||||
*/
|
||||
static bool fx_is_external(uint32_t addr, size_t len)
|
||||
{
|
||||
/* with 8KB RAM, 0x0000-0x1b3f can be written
|
||||
* we can't tell if it's a 4KB device here
|
||||
*/
|
||||
if (addr <= 0x1b3f)
|
||||
return ((addr + len) > 0x1b40);
|
||||
|
||||
/* there may be more RAM; unclear if we can write it.
|
||||
* some bulk buffers may be unused, 0x1b3f-0x1f3f
|
||||
* firmware can set ISODISAB for 2KB at 0x2000-0x27ff
|
||||
*/
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* return true if [addr,addr+len] includes external RAM
|
||||
* for Cypress EZ-USB FX2
|
||||
*/
|
||||
static bool fx2_is_external(uint32_t addr, size_t len)
|
||||
{
|
||||
/* 1st 8KB for data/code, 0x0000-0x1fff */
|
||||
if (addr <= 0x1fff)
|
||||
return ((addr + len) > 0x2000);
|
||||
|
||||
/* and 512 for data, 0xe000-0xe1ff */
|
||||
else if (addr >= 0xe000 && addr <= 0xe1ff)
|
||||
return ((addr + len) > 0xe200);
|
||||
|
||||
/* otherwise, it's certainly external */
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* return true if [addr,addr+len] includes external RAM
|
||||
* for Cypress EZ-USB FX2LP
|
||||
*/
|
||||
static bool fx2lp_is_external(uint32_t addr, size_t len)
|
||||
{
|
||||
/* 1st 16KB for data/code, 0x0000-0x3fff */
|
||||
if (addr <= 0x3fff)
|
||||
return ((addr + len) > 0x4000);
|
||||
|
||||
/* and 512 for data, 0xe000-0xe1ff */
|
||||
else if (addr >= 0xe000 && addr <= 0xe1ff)
|
||||
return ((addr + len) > 0xe200);
|
||||
|
||||
/* otherwise, it's certainly external */
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/*
|
||||
* These are the requests (bRequest) that the bootstrap loader is expected
|
||||
* to recognize. The codes are reserved by Cypress, and these values match
|
||||
* what EZ-USB hardware, or "Vend_Ax" firmware (2nd stage loader) uses.
|
||||
* Cypress' "a3load" is nice because it supports both FX and FX2, although
|
||||
* it doesn't have the EEPROM support (subset of "Vend_Ax").
|
||||
*/
|
||||
#define RW_INTERNAL 0xA0 /* hardware implements this one */
|
||||
#define RW_MEMORY 0xA3
|
||||
|
||||
/*
|
||||
* Issues the specified vendor-specific write request.
|
||||
*/
|
||||
static int ezusb_write(libusb_device_handle *device, const char *label,
|
||||
uint8_t opcode, uint32_t addr, const unsigned char *data, size_t len)
|
||||
{
|
||||
int status;
|
||||
|
||||
if (verbose > 1)
|
||||
logerror("%s, addr 0x%08x len %4u (0x%04x)\n", label, addr, (unsigned)len, (unsigned)len);
|
||||
status = libusb_control_transfer(device,
|
||||
LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE,
|
||||
opcode, addr & 0xFFFF, addr >> 16,
|
||||
(unsigned char*)data, (uint16_t)len, 1000);
|
||||
if (status != (signed)len) {
|
||||
if (status < 0)
|
||||
logerror("%s: %s\n", label, libusb_error_name(status));
|
||||
else
|
||||
logerror("%s ==> %d\n", label, status);
|
||||
}
|
||||
return (status < 0) ? -EIO : 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Issues the specified vendor-specific read request.
|
||||
*/
|
||||
static int ezusb_read(libusb_device_handle *device, const char *label,
|
||||
uint8_t opcode, uint32_t addr, const unsigned char *data, size_t len)
|
||||
{
|
||||
int status;
|
||||
|
||||
if (verbose > 1)
|
||||
logerror("%s, addr 0x%08x len %4u (0x%04x)\n", label, addr, (unsigned)len, (unsigned)len);
|
||||
status = libusb_control_transfer(device,
|
||||
LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE,
|
||||
opcode, addr & 0xFFFF, addr >> 16,
|
||||
(unsigned char*)data, (uint16_t)len, 1000);
|
||||
if (status != (signed)len) {
|
||||
if (status < 0)
|
||||
logerror("%s: %s\n", label, libusb_error_name(status));
|
||||
else
|
||||
logerror("%s ==> %d\n", label, status);
|
||||
}
|
||||
return (status < 0) ? -EIO : 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Modifies the CPUCS register to stop or reset the CPU.
|
||||
* Returns false on error.
|
||||
*/
|
||||
static bool ezusb_cpucs(libusb_device_handle *device, uint32_t addr, bool doRun)
|
||||
{
|
||||
int status;
|
||||
uint8_t data = doRun ? 0x00 : 0x01;
|
||||
|
||||
if (verbose)
|
||||
logerror("%s\n", data ? "stop CPU" : "reset CPU");
|
||||
status = libusb_control_transfer(device,
|
||||
LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE,
|
||||
RW_INTERNAL, addr & 0xFFFF, addr >> 16,
|
||||
&data, 1, 1000);
|
||||
if ((status != 1) &&
|
||||
/* We may get an I/O error from libusb as the device disappears */
|
||||
((!doRun) || (status != LIBUSB_ERROR_IO)))
|
||||
{
|
||||
const char *mesg = "can't modify CPUCS";
|
||||
if (status < 0)
|
||||
logerror("%s: %s\n", mesg, libusb_error_name(status));
|
||||
else
|
||||
logerror("%s\n", mesg);
|
||||
return false;
|
||||
} else
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Send an FX3 jumpt to address command
|
||||
* Returns false on error.
|
||||
*/
|
||||
static bool ezusb_fx3_jump(libusb_device_handle *device, uint32_t addr)
|
||||
{
|
||||
int status;
|
||||
|
||||
if (verbose)
|
||||
logerror("transfer execution to Program Entry at 0x%08x\n", addr);
|
||||
status = libusb_control_transfer(device,
|
||||
LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE,
|
||||
RW_INTERNAL, addr & 0xFFFF, addr >> 16,
|
||||
NULL, 0, 1000);
|
||||
/* We may get an I/O error from libusb as the device disappears */
|
||||
if ((status != 0) && (status != LIBUSB_ERROR_IO))
|
||||
{
|
||||
const char *mesg = "failed to send jump command";
|
||||
if (status < 0)
|
||||
logerror("%s: %s\n", mesg, libusb_error_name(status));
|
||||
else
|
||||
logerror("%s\n", mesg);
|
||||
return false;
|
||||
} else
|
||||
return true;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/*
|
||||
* Parse an Intel HEX image file and invoke the poke() function on the
|
||||
* various segments to implement policies such as writing to RAM (with
|
||||
* a one or two stage loader setup, depending on the firmware) or to
|
||||
* EEPROM (two stages required).
|
||||
*
|
||||
* image - the hex image file
|
||||
* context - for use by poke()
|
||||
* is_external - if non-null, used to check which segments go into
|
||||
* external memory (writable only by software loader)
|
||||
* poke - called with each memory segment; errors indicated
|
||||
* by returning negative values.
|
||||
*
|
||||
* Caller is responsible for halting CPU as needed, such as when
|
||||
* overwriting a second stage loader.
|
||||
*/
|
||||
static int parse_ihex(FILE *image, void *context,
|
||||
bool (*is_external)(uint32_t addr, size_t len),
|
||||
int (*poke) (void *context, uint32_t addr, bool external,
|
||||
const unsigned char *data, size_t len))
|
||||
{
|
||||
unsigned char data[1023];
|
||||
uint32_t data_addr = 0;
|
||||
size_t data_len = 0;
|
||||
int rc;
|
||||
int first_line = 1;
|
||||
bool external = false;
|
||||
|
||||
/* Read the input file as an IHEX file, and report the memory segments
|
||||
* as we go. Each line holds a max of 16 bytes, but uploading is
|
||||
* faster (and EEPROM space smaller) if we merge those lines into larger
|
||||
* chunks. Most hex files keep memory segments together, which makes
|
||||
* such merging all but free. (But it may still be worth sorting the
|
||||
* hex files to make up for undesirable behavior from tools.)
|
||||
*
|
||||
* Note that EEPROM segments max out at 1023 bytes; the upload protocol
|
||||
* allows segments of up to 64 KBytes (more than a loader could handle).
|
||||
*/
|
||||
for (;;) {
|
||||
char buf[512], *cp;
|
||||
char tmp, type;
|
||||
size_t len;
|
||||
unsigned idx, off;
|
||||
|
||||
cp = fgets(buf, sizeof(buf), image);
|
||||
if (cp == NULL) {
|
||||
logerror("EOF without EOF record!\n");
|
||||
break;
|
||||
}
|
||||
|
||||
/* EXTENSION: "# comment-till-end-of-line", for copyrights etc */
|
||||
if (buf[0] == '#')
|
||||
continue;
|
||||
|
||||
if (buf[0] != ':') {
|
||||
logerror("not an ihex record: %s", buf);
|
||||
return -2;
|
||||
}
|
||||
|
||||
/* ignore any newline */
|
||||
cp = strchr(buf, '\n');
|
||||
if (cp)
|
||||
*cp = 0;
|
||||
|
||||
if (verbose >= 3)
|
||||
logerror("** LINE: %s\n", buf);
|
||||
|
||||
/* Read the length field (up to 16 bytes) */
|
||||
tmp = buf[3];
|
||||
buf[3] = 0;
|
||||
len = strtoul(buf+1, NULL, 16);
|
||||
buf[3] = tmp;
|
||||
|
||||
/* Read the target offset (address up to 64KB) */
|
||||
tmp = buf[7];
|
||||
buf[7] = 0;
|
||||
off = (unsigned int)strtoul(buf+3, NULL, 16);
|
||||
buf[7] = tmp;
|
||||
|
||||
/* Initialize data_addr */
|
||||
if (first_line) {
|
||||
data_addr = off;
|
||||
first_line = 0;
|
||||
}
|
||||
|
||||
/* Read the record type */
|
||||
tmp = buf[9];
|
||||
buf[9] = 0;
|
||||
type = (char)strtoul(buf+7, NULL, 16);
|
||||
buf[9] = tmp;
|
||||
|
||||
/* If this is an EOF record, then make it so. */
|
||||
if (type == 1) {
|
||||
if (verbose >= 2)
|
||||
logerror("EOF on hexfile\n");
|
||||
break;
|
||||
}
|
||||
|
||||
if (type != 0) {
|
||||
logerror("unsupported record type: %u\n", type);
|
||||
return -3;
|
||||
}
|
||||
|
||||
if ((len * 2) + 11 > strlen(buf)) {
|
||||
logerror("record too short?\n");
|
||||
return -4;
|
||||
}
|
||||
|
||||
/* FIXME check for _physically_ contiguous not just virtually
|
||||
* e.g. on FX2 0x1f00-0x2100 includes both on-chip and external
|
||||
* memory so it's not really contiguous */
|
||||
|
||||
/* flush the saved data if it's not contiguous,
|
||||
* or when we've buffered as much as we can.
|
||||
*/
|
||||
if (data_len != 0
|
||||
&& (off != (data_addr + data_len)
|
||||
/* || !merge */
|
||||
|| (data_len + len) > sizeof(data))) {
|
||||
if (is_external)
|
||||
external = is_external(data_addr, data_len);
|
||||
rc = poke(context, data_addr, external, data, data_len);
|
||||
if (rc < 0)
|
||||
return -1;
|
||||
data_addr = off;
|
||||
data_len = 0;
|
||||
}
|
||||
|
||||
/* append to saved data, flush later */
|
||||
for (idx = 0, cp = buf+9 ; idx < len ; idx += 1, cp += 2) {
|
||||
tmp = cp[2];
|
||||
cp[2] = 0;
|
||||
data[data_len + idx] = (uint8_t)strtoul(cp, NULL, 16);
|
||||
cp[2] = tmp;
|
||||
}
|
||||
data_len += len;
|
||||
}
|
||||
|
||||
|
||||
/* flush any data remaining */
|
||||
if (data_len != 0) {
|
||||
if (is_external)
|
||||
external = is_external(data_addr, data_len);
|
||||
rc = poke(context, data_addr, external, data, data_len);
|
||||
if (rc < 0)
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse a binary image file and write it as is to the target.
|
||||
* Applies to Cypress BIX images for RAM or Cypress IIC images
|
||||
* for EEPROM.
|
||||
*
|
||||
* image - the BIX image file
|
||||
* context - for use by poke()
|
||||
* is_external - if non-null, used to check which segments go into
|
||||
* external memory (writable only by software loader)
|
||||
* poke - called with each memory segment; errors indicated
|
||||
* by returning negative values.
|
||||
*
|
||||
* Caller is responsible for halting CPU as needed, such as when
|
||||
* overwriting a second stage loader.
|
||||
*/
|
||||
static int parse_bin(FILE *image, void *context,
|
||||
bool (*is_external)(uint32_t addr, size_t len), int (*poke)(void *context,
|
||||
uint32_t addr, bool external, const unsigned char *data, size_t len))
|
||||
{
|
||||
unsigned char data[4096];
|
||||
uint32_t data_addr = 0;
|
||||
size_t data_len = 0;
|
||||
int rc;
|
||||
bool external = false;
|
||||
|
||||
for (;;) {
|
||||
data_len = fread(data, 1, 4096, image);
|
||||
if (data_len == 0)
|
||||
break;
|
||||
if (is_external)
|
||||
external = is_external(data_addr, data_len);
|
||||
rc = poke(context, data_addr, external, data, data_len);
|
||||
if (rc < 0)
|
||||
return -1;
|
||||
data_addr += (uint32_t)data_len;
|
||||
}
|
||||
return feof(image)?0:-1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse a Cypress IIC image file and invoke the poke() function on the
|
||||
* various segments for writing to RAM
|
||||
*
|
||||
* image - the IIC image file
|
||||
* context - for use by poke()
|
||||
* is_external - if non-null, used to check which segments go into
|
||||
* external memory (writable only by software loader)
|
||||
* poke - called with each memory segment; errors indicated
|
||||
* by returning negative values.
|
||||
*
|
||||
* Caller is responsible for halting CPU as needed, such as when
|
||||
* overwriting a second stage loader.
|
||||
*/
|
||||
static int parse_iic(FILE *image, void *context,
|
||||
bool (*is_external)(uint32_t addr, size_t len),
|
||||
int (*poke)(void *context, uint32_t addr, bool external, const unsigned char *data, size_t len))
|
||||
{
|
||||
unsigned char data[4096];
|
||||
uint32_t data_addr = 0;
|
||||
size_t data_len = 0, read_len;
|
||||
uint8_t block_header[4];
|
||||
int rc;
|
||||
bool external = false;
|
||||
long file_size, initial_pos;
|
||||
|
||||
initial_pos = ftell(image);
|
||||
if (initial_pos < 0)
|
||||
return -1;
|
||||
|
||||
if (fseek(image, 0L, SEEK_END) != 0)
|
||||
return -1;
|
||||
file_size = ftell(image);
|
||||
if (fseek(image, initial_pos, SEEK_SET) != 0)
|
||||
return -1;
|
||||
for (;;) {
|
||||
/* Ignore the trailing reset IIC data (5 bytes) */
|
||||
if (ftell(image) >= (file_size - 5))
|
||||
break;
|
||||
if (fread(&block_header, 1, sizeof(block_header), image) != 4) {
|
||||
logerror("unable to read IIC block header\n");
|
||||
return -1;
|
||||
}
|
||||
data_len = (block_header[0] << 8) + block_header[1];
|
||||
data_addr = (block_header[2] << 8) + block_header[3];
|
||||
if (data_len > sizeof(data)) {
|
||||
/* If this is ever reported as an error, switch to using malloc/realloc */
|
||||
logerror("IIC data block too small - please report this error to libusb.info\n");
|
||||
return -1;
|
||||
}
|
||||
read_len = fread(data, 1, data_len, image);
|
||||
if (read_len != data_len) {
|
||||
logerror("read error\n");
|
||||
return -1;
|
||||
}
|
||||
if (is_external)
|
||||
external = is_external(data_addr, data_len);
|
||||
rc = poke(context, data_addr, external, data, data_len);
|
||||
if (rc < 0)
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* the parse call will be selected according to the image type */
|
||||
static int (*parse[IMG_TYPE_MAX])(FILE *image, void *context, bool (*is_external)(uint32_t addr, size_t len),
|
||||
int (*poke)(void *context, uint32_t addr, bool external, const unsigned char *data, size_t len))
|
||||
= { parse_ihex, parse_iic, parse_bin };
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/*
|
||||
* For writing to RAM using a first (hardware) or second (software)
|
||||
* stage loader and 0xA0 or 0xA3 vendor requests
|
||||
*/
|
||||
typedef enum {
|
||||
_undef = 0,
|
||||
internal_only, /* hardware first-stage loader */
|
||||
skip_internal, /* first phase, second-stage loader */
|
||||
skip_external /* second phase, second-stage loader */
|
||||
} ram_mode;
|
||||
|
||||
struct ram_poke_context {
|
||||
libusb_device_handle *device;
|
||||
ram_mode mode;
|
||||
size_t total, count;
|
||||
};
|
||||
|
||||
#define RETRY_LIMIT 5
|
||||
|
||||
static int ram_poke(void *context, uint32_t addr, bool external,
|
||||
const unsigned char *data, size_t len)
|
||||
{
|
||||
struct ram_poke_context *ctx = (struct ram_poke_context*)context;
|
||||
int rc;
|
||||
unsigned retry = 0;
|
||||
|
||||
switch (ctx->mode) {
|
||||
case internal_only: /* CPU should be stopped */
|
||||
if (external) {
|
||||
logerror("can't write %u bytes external memory at 0x%08x\n",
|
||||
(unsigned)len, addr);
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
case skip_internal: /* CPU must be running */
|
||||
if (!external) {
|
||||
if (verbose >= 2) {
|
||||
logerror("SKIP on-chip RAM, %u bytes at 0x%08x\n",
|
||||
(unsigned)len, addr);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case skip_external: /* CPU should be stopped */
|
||||
if (external) {
|
||||
if (verbose >= 2) {
|
||||
logerror("SKIP external RAM, %u bytes at 0x%08x\n",
|
||||
(unsigned)len, addr);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case _undef:
|
||||
default:
|
||||
logerror("bug\n");
|
||||
return -EDOM;
|
||||
}
|
||||
|
||||
ctx->total += len;
|
||||
ctx->count++;
|
||||
|
||||
/* Retry this till we get a real error. Control messages are not
|
||||
* NAKed (just dropped) so time out means is a real problem.
|
||||
*/
|
||||
while ((rc = ezusb_write(ctx->device,
|
||||
external ? "write external" : "write on-chip",
|
||||
external ? RW_MEMORY : RW_INTERNAL,
|
||||
addr, data, len)) < 0
|
||||
&& retry < RETRY_LIMIT) {
|
||||
if (rc != LIBUSB_ERROR_TIMEOUT)
|
||||
break;
|
||||
retry += 1;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* Load a Cypress Image file into target RAM.
|
||||
* See http://www.cypress.com/?docID=41351 (AN76405 PDF) for more info.
|
||||
*/
|
||||
static int fx3_load_ram(libusb_device_handle *device, const char *path)
|
||||
{
|
||||
uint32_t dCheckSum, dExpectedCheckSum, dAddress, i, dLen, dLength;
|
||||
uint32_t* dImageBuf;
|
||||
unsigned char *bBuf, hBuf[4], blBuf[4], rBuf[4096];
|
||||
FILE *image;
|
||||
int ret = 0;
|
||||
|
||||
image = fopen(path, "rb");
|
||||
if (image == NULL) {
|
||||
logerror("unable to open '%s' for input\n", path);
|
||||
return -2;
|
||||
} else if (verbose)
|
||||
logerror("open firmware image %s for RAM upload\n", path);
|
||||
|
||||
// Read header
|
||||
if (fread(hBuf, sizeof(char), sizeof(hBuf), image) != sizeof(hBuf)) {
|
||||
logerror("could not read image header");
|
||||
ret = -3;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
// check "CY" signature byte and format
|
||||
if ((hBuf[0] != 'C') || (hBuf[1] != 'Y')) {
|
||||
logerror("image doesn't have a CYpress signature\n");
|
||||
ret = -3;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
// Check bImageType
|
||||
switch(hBuf[3]) {
|
||||
case 0xB0:
|
||||
if (verbose)
|
||||
logerror("normal FW binary %s image with checksum\n", (hBuf[2]&0x01)?"data":"executable");
|
||||
break;
|
||||
case 0xB1:
|
||||
logerror("security binary image is not currently supported\n");
|
||||
ret = -3;
|
||||
goto exit;
|
||||
case 0xB2:
|
||||
logerror("VID:PID image is not currently supported\n");
|
||||
ret = -3;
|
||||
goto exit;
|
||||
default:
|
||||
logerror("invalid image type 0x%02X\n", hBuf[3]);
|
||||
ret = -3;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
// Read the bootloader version
|
||||
if (verbose) {
|
||||
if ((ezusb_read(device, "read bootloader version", RW_INTERNAL, 0xFFFF0020, blBuf, 4) < 0)) {
|
||||
logerror("Could not read bootloader version\n");
|
||||
ret = -8;
|
||||
goto exit;
|
||||
}
|
||||
logerror("FX3 bootloader version: 0x%02X%02X%02X%02X\n", blBuf[3], blBuf[2], blBuf[1], blBuf[0]);
|
||||
}
|
||||
|
||||
dCheckSum = 0;
|
||||
if (verbose)
|
||||
logerror("writing image...\n");
|
||||
while (1) {
|
||||
if ((fread(&dLength, sizeof(uint32_t), 1, image) != 1) || // read dLength
|
||||
(fread(&dAddress, sizeof(uint32_t), 1, image) != 1)) { // read dAddress
|
||||
logerror("could not read image");
|
||||
ret = -3;
|
||||
goto exit;
|
||||
}
|
||||
if (dLength == 0)
|
||||
break; // done
|
||||
|
||||
// coverity[tainted_data]
|
||||
dImageBuf = (uint32_t*)calloc(dLength, sizeof(uint32_t));
|
||||
if (dImageBuf == NULL) {
|
||||
logerror("could not allocate buffer for image chunk\n");
|
||||
ret = -4;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
// read sections
|
||||
if (fread(dImageBuf, sizeof(uint32_t), dLength, image) != dLength) {
|
||||
logerror("could not read image");
|
||||
free(dImageBuf);
|
||||
ret = -3;
|
||||
goto exit;
|
||||
}
|
||||
for (i = 0; i < dLength; i++)
|
||||
dCheckSum += dImageBuf[i];
|
||||
dLength <<= 2; // convert to Byte length
|
||||
bBuf = (unsigned char*) dImageBuf;
|
||||
|
||||
while (dLength > 0) {
|
||||
dLen = 4096; // 4K max
|
||||
if (dLen > dLength)
|
||||
dLen = dLength;
|
||||
if ((ezusb_write(device, "write firmware", RW_INTERNAL, dAddress, bBuf, dLen) < 0) ||
|
||||
(ezusb_read(device, "read firmware", RW_INTERNAL, dAddress, rBuf, dLen) < 0)) {
|
||||
logerror("R/W error\n");
|
||||
free(dImageBuf);
|
||||
ret = -5;
|
||||
goto exit;
|
||||
}
|
||||
// Verify data: rBuf with bBuf
|
||||
for (i = 0; i < dLen; i++) {
|
||||
if (rBuf[i] != bBuf[i]) {
|
||||
logerror("verify error");
|
||||
free(dImageBuf);
|
||||
ret = -6;
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
dLength -= dLen;
|
||||
bBuf += dLen;
|
||||
dAddress += dLen;
|
||||
}
|
||||
free(dImageBuf);
|
||||
}
|
||||
|
||||
// read pre-computed checksum data
|
||||
if ((fread(&dExpectedCheckSum, sizeof(uint32_t), 1, image) != 1) ||
|
||||
(dCheckSum != dExpectedCheckSum)) {
|
||||
logerror("checksum error\n");
|
||||
ret = -7;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
// transfer execution to Program Entry
|
||||
if (!ezusb_fx3_jump(device, dAddress)) {
|
||||
ret = -6;
|
||||
}
|
||||
|
||||
exit:
|
||||
fclose(image);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Load a firmware file into target RAM. device is the open libusb
|
||||
* device, and the path is the name of the source file. Open the file,
|
||||
* parse the bytes, and write them in one or two phases.
|
||||
*
|
||||
* If stage == 0, this uses the first stage loader, built into EZ-USB
|
||||
* hardware but limited to writing on-chip memory or CPUCS. Everything
|
||||
* is written during one stage, unless there's an error such as the image
|
||||
* holding data that needs to be written to external memory.
|
||||
*
|
||||
* Otherwise, things are written in two stages. First the external
|
||||
* memory is written, expecting a second stage loader to have already
|
||||
* been loaded. Then file is re-parsed and on-chip memory is written.
|
||||
*/
|
||||
int ezusb_load_ram(libusb_device_handle *device, const char *path, int fx_type, int img_type, int stage)
|
||||
{
|
||||
FILE *image;
|
||||
uint32_t cpucs_addr;
|
||||
bool (*is_external)(uint32_t off, size_t len);
|
||||
struct ram_poke_context ctx;
|
||||
int status;
|
||||
uint8_t iic_header[8] = { 0 };
|
||||
int ret = 0;
|
||||
|
||||
if (fx_type == FX_TYPE_FX3)
|
||||
return fx3_load_ram(device, path);
|
||||
|
||||
image = fopen(path, "rb");
|
||||
if (image == NULL) {
|
||||
logerror("%s: unable to open for input.\n", path);
|
||||
return -2;
|
||||
} else if (verbose > 1)
|
||||
logerror("open firmware image %s for RAM upload\n", path);
|
||||
|
||||
if (img_type == IMG_TYPE_IIC) {
|
||||
if ( (fread(iic_header, 1, sizeof(iic_header), image) != sizeof(iic_header))
|
||||
|| (((fx_type == FX_TYPE_FX2LP) || (fx_type == FX_TYPE_FX2)) && (iic_header[0] != 0xC2))
|
||||
|| ((fx_type == FX_TYPE_AN21) && (iic_header[0] != 0xB2))
|
||||
|| ((fx_type == FX_TYPE_FX1) && (iic_header[0] != 0xB6)) ) {
|
||||
logerror("IIC image does not contain executable code - cannot load to RAM.\n");
|
||||
ret = -1;
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
/* EZ-USB original/FX and FX2 devices differ, apart from the 8051 core */
|
||||
switch(fx_type) {
|
||||
case FX_TYPE_FX2LP:
|
||||
cpucs_addr = 0xe600;
|
||||
is_external = fx2lp_is_external;
|
||||
break;
|
||||
case FX_TYPE_FX2:
|
||||
cpucs_addr = 0xe600;
|
||||
is_external = fx2_is_external;
|
||||
break;
|
||||
default:
|
||||
cpucs_addr = 0x7f92;
|
||||
is_external = fx_is_external;
|
||||
break;
|
||||
}
|
||||
|
||||
/* use only first stage loader? */
|
||||
if (stage == 0) {
|
||||
ctx.mode = internal_only;
|
||||
|
||||
/* if required, halt the CPU while we overwrite its code/data */
|
||||
if (cpucs_addr && !ezusb_cpucs(device, cpucs_addr, false))
|
||||
{
|
||||
ret = -1;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* 2nd stage, first part? loader was already uploaded */
|
||||
} else {
|
||||
ctx.mode = skip_internal;
|
||||
|
||||
/* let CPU run; overwrite the 2nd stage loader later */
|
||||
if (verbose)
|
||||
logerror("2nd stage: write external memory\n");
|
||||
}
|
||||
|
||||
/* scan the image, first (maybe only) time */
|
||||
ctx.device = device;
|
||||
ctx.total = ctx.count = 0;
|
||||
status = parse[img_type](image, &ctx, is_external, ram_poke);
|
||||
if (status < 0) {
|
||||
logerror("unable to upload %s\n", path);
|
||||
ret = status;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* second part of 2nd stage: rescan */
|
||||
// TODO: what should we do for non HEX images there?
|
||||
if (stage) {
|
||||
ctx.mode = skip_external;
|
||||
|
||||
/* if needed, halt the CPU while we overwrite the 1st stage loader */
|
||||
if (cpucs_addr && !ezusb_cpucs(device, cpucs_addr, false))
|
||||
{
|
||||
ret = -1;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* at least write the interrupt vectors (at 0x0000) for reset! */
|
||||
rewind(image);
|
||||
if (verbose)
|
||||
logerror("2nd stage: write on-chip memory\n");
|
||||
status = parse_ihex(image, &ctx, is_external, ram_poke);
|
||||
if (status < 0) {
|
||||
logerror("unable to completely upload %s\n", path);
|
||||
ret = status;
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
if (verbose && (ctx.count != 0)) {
|
||||
logerror("... WROTE: %d bytes, %d segments, avg %d\n",
|
||||
(int)ctx.total, (int)ctx.count, (int)(ctx.total/ctx.count));
|
||||
}
|
||||
|
||||
/* if required, reset the CPU so it runs what we just uploaded */
|
||||
if (cpucs_addr && !ezusb_cpucs(device, cpucs_addr, true))
|
||||
ret = -1;
|
||||
|
||||
exit:
|
||||
fclose(image);
|
||||
return ret;
|
||||
}
|
|
@ -1,120 +0,0 @@
|
|||
#ifndef ezusb_H
|
||||
#define ezusb_H
|
||||
/*
|
||||
* Copyright © 2001 Stephen Williams (steve@icarus.com)
|
||||
* Copyright © 2002 David Brownell (dbrownell@users.sourceforge.net)
|
||||
* Copyright © 2013 Federico Manzan (f.manzan@gmail.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(_MSC_VER)
|
||||
#include <stdbool.h>
|
||||
#else
|
||||
#define __attribute__(x)
|
||||
#if !defined(bool)
|
||||
#define bool int
|
||||
#endif
|
||||
#if !defined(true)
|
||||
#define true (1 == 1)
|
||||
#endif
|
||||
#if !defined(false)
|
||||
#define false (!true)
|
||||
#endif
|
||||
#if defined(_PREFAST_)
|
||||
#pragma warning(disable:28193)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define FX_TYPE_UNDEFINED -1
|
||||
#define FX_TYPE_AN21 0 /* Original AnchorChips parts */
|
||||
#define FX_TYPE_FX1 1 /* Updated Cypress versions */
|
||||
#define FX_TYPE_FX2 2 /* USB 2.0 versions */
|
||||
#define FX_TYPE_FX2LP 3 /* Updated FX2 */
|
||||
#define FX_TYPE_FX3 4 /* USB 3.0 versions */
|
||||
#define FX_TYPE_MAX 5
|
||||
#define FX_TYPE_NAMES { "an21", "fx", "fx2", "fx2lp", "fx3" }
|
||||
|
||||
#define IMG_TYPE_UNDEFINED -1
|
||||
#define IMG_TYPE_HEX 0 /* Intel HEX */
|
||||
#define IMG_TYPE_IIC 1 /* Cypress 8051 IIC */
|
||||
#define IMG_TYPE_BIX 2 /* Cypress 8051 BIX */
|
||||
#define IMG_TYPE_IMG 3 /* Cypress IMG format */
|
||||
#define IMG_TYPE_MAX 4
|
||||
#define IMG_TYPE_NAMES { "Intel HEX", "Cypress 8051 IIC", "Cypress 8051 BIX", "Cypress IMG format" }
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Automatically identified devices (VID, PID, type, designation).
|
||||
* TODO: Could use some validation. Also where's the FX2?
|
||||
*/
|
||||
typedef struct {
|
||||
uint16_t vid;
|
||||
uint16_t pid;
|
||||
int type;
|
||||
const char* designation;
|
||||
} fx_known_device;
|
||||
|
||||
#define FX_KNOWN_DEVICES { \
|
||||
{ 0x0547, 0x2122, FX_TYPE_AN21, "Cypress EZ-USB (2122S)" },\
|
||||
{ 0x0547, 0x2125, FX_TYPE_AN21, "Cypress EZ-USB (2121S/2125S)" },\
|
||||
{ 0x0547, 0x2126, FX_TYPE_AN21, "Cypress EZ-USB (2126S)" },\
|
||||
{ 0x0547, 0x2131, FX_TYPE_AN21, "Cypress EZ-USB (2131Q/2131S/2135S)" },\
|
||||
{ 0x0547, 0x2136, FX_TYPE_AN21, "Cypress EZ-USB (2136S)" },\
|
||||
{ 0x0547, 0x2225, FX_TYPE_AN21, "Cypress EZ-USB (2225)" },\
|
||||
{ 0x0547, 0x2226, FX_TYPE_AN21, "Cypress EZ-USB (2226)" },\
|
||||
{ 0x0547, 0x2235, FX_TYPE_AN21, "Cypress EZ-USB (2235)" },\
|
||||
{ 0x0547, 0x2236, FX_TYPE_AN21, "Cypress EZ-USB (2236)" },\
|
||||
{ 0x04b4, 0x6473, FX_TYPE_FX1, "Cypress EZ-USB FX1" },\
|
||||
{ 0x04b4, 0x8613, FX_TYPE_FX2LP, "Cypress EZ-USB FX2LP (68013A/68014A/68015A/68016A)" }, \
|
||||
{ 0x04b4, 0x00f3, FX_TYPE_FX3, "Cypress FX3" },\
|
||||
}
|
||||
|
||||
/*
|
||||
* This function uploads the firmware from the given file into RAM.
|
||||
* Stage == 0 means this is a single stage load (or the first of
|
||||
* two stages). Otherwise it's the second of two stages; the
|
||||
* caller having preloaded the second stage loader.
|
||||
*
|
||||
* The target processor is reset at the end of this upload.
|
||||
*/
|
||||
extern int ezusb_load_ram(libusb_device_handle *device,
|
||||
const char *path, int fx_type, int img_type, int stage);
|
||||
|
||||
/*
|
||||
* This function uploads the firmware from the given file into EEPROM.
|
||||
* This uses the right CPUCS address to terminate the EEPROM load with
|
||||
* a reset command where FX parts behave differently than FX2 ones.
|
||||
* The configuration byte is as provided here (zero for an21xx parts)
|
||||
* and the EEPROM type is set so that the microcontroller will boot
|
||||
* from it.
|
||||
*
|
||||
* The caller must have preloaded a second stage loader that knows
|
||||
* how to respond to the EEPROM write request.
|
||||
*/
|
||||
extern int ezusb_load_eeprom(libusb_device_handle *device,
|
||||
const char *path, int fx_type, int img_type, int config);
|
||||
|
||||
/* Verbosity level (default 1). Can be increased or decreased with options v/q */
|
||||
extern int verbose;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -1,309 +0,0 @@
|
|||
/*
|
||||
* Copyright © 2001 Stephen Williams (steve@icarus.com)
|
||||
* Copyright © 2001-2002 David Brownell (dbrownell@users.sourceforge.net)
|
||||
* Copyright © 2008 Roger Williams (rawqux@users.sourceforge.net)
|
||||
* Copyright © 2012 Pete Batard (pete@akeo.ie)
|
||||
* Copyright © 2013 Federico Manzan (f.manzan@gmail.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <stdarg.h>
|
||||
#include <sys/types.h>
|
||||
#include <getopt.h>
|
||||
|
||||
#include "libusb.h"
|
||||
#include "ezusb.h"
|
||||
|
||||
#if !defined(_WIN32) || defined(__CYGWIN__ )
|
||||
#include <syslog.h>
|
||||
static bool dosyslog = false;
|
||||
#include <strings.h>
|
||||
#define _stricmp strcasecmp
|
||||
#endif
|
||||
|
||||
#ifndef FXLOAD_VERSION
|
||||
#define FXLOAD_VERSION (__DATE__ " (libusb)")
|
||||
#endif
|
||||
|
||||
#ifndef ARRAYSIZE
|
||||
#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
|
||||
#endif
|
||||
|
||||
void logerror(const char *format, ...)
|
||||
__attribute__ ((format (__printf__, 1, 2)));
|
||||
|
||||
void logerror(const char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, format);
|
||||
|
||||
#if !defined(_WIN32) || defined(__CYGWIN__ )
|
||||
if (dosyslog)
|
||||
vsyslog(LOG_ERR, format, ap);
|
||||
else
|
||||
#endif
|
||||
vfprintf(stderr, format, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
static int print_usage(int error_code) {
|
||||
fprintf(stderr, "\nUsage: fxload [-v] [-V] [-t type] [-d vid:pid] [-p bus,addr] [-s loader] -i firmware\n");
|
||||
fprintf(stderr, " -i <path> -- Firmware to upload\n");
|
||||
fprintf(stderr, " -s <path> -- Second stage loader\n");
|
||||
fprintf(stderr, " -t <type> -- Target type: an21, fx, fx2, fx2lp, fx3\n");
|
||||
fprintf(stderr, " -d <vid:pid> -- Target device, as an USB VID:PID\n");
|
||||
fprintf(stderr, " -p <bus,addr> -- Target device, as a libusb bus number and device address path\n");
|
||||
fprintf(stderr, " -v -- Increase verbosity\n");
|
||||
fprintf(stderr, " -q -- Decrease verbosity (silent mode)\n");
|
||||
fprintf(stderr, " -V -- Print program version\n");
|
||||
return error_code;
|
||||
}
|
||||
|
||||
#define FIRMWARE 0
|
||||
#define LOADER 1
|
||||
int main(int argc, char*argv[])
|
||||
{
|
||||
fx_known_device known_device[] = FX_KNOWN_DEVICES;
|
||||
const char *path[] = { NULL, NULL };
|
||||
const char *device_id = NULL;
|
||||
const char *device_path = getenv("DEVICE");
|
||||
const char *type = NULL;
|
||||
const char *fx_name[FX_TYPE_MAX] = FX_TYPE_NAMES;
|
||||
const char *ext, *img_name[] = IMG_TYPE_NAMES;
|
||||
int fx_type = FX_TYPE_UNDEFINED, img_type[ARRAYSIZE(path)];
|
||||
int opt, status;
|
||||
unsigned int i, j;
|
||||
unsigned vid = 0, pid = 0;
|
||||
unsigned busnum = 0, devaddr = 0, _busnum, _devaddr;
|
||||
libusb_device *dev, **devs;
|
||||
libusb_device_handle *device = NULL;
|
||||
struct libusb_device_descriptor desc;
|
||||
|
||||
while ((opt = getopt(argc, argv, "qvV?hd:p:i:I:s:S:t:")) != EOF)
|
||||
switch (opt) {
|
||||
|
||||
case 'd':
|
||||
device_id = optarg;
|
||||
if (sscanf(device_id, "%x:%x" , &vid, &pid) != 2 ) {
|
||||
fputs ("please specify VID & PID as \"vid:pid\" in hexadecimal format\n", stderr);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
device_path = optarg;
|
||||
if (sscanf(device_path, "%u,%u", &busnum, &devaddr) != 2 ) {
|
||||
fputs ("please specify bus number & device number as \"bus,dev\" in decimal format\n", stderr);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'i':
|
||||
case 'I':
|
||||
path[FIRMWARE] = optarg;
|
||||
break;
|
||||
|
||||
case 's':
|
||||
case 'S':
|
||||
path[LOADER] = optarg;
|
||||
break;
|
||||
|
||||
case 'V':
|
||||
puts(FXLOAD_VERSION);
|
||||
return 0;
|
||||
|
||||
case 't':
|
||||
type = optarg;
|
||||
break;
|
||||
|
||||
case 'v':
|
||||
verbose++;
|
||||
break;
|
||||
|
||||
case 'q':
|
||||
verbose--;
|
||||
break;
|
||||
|
||||
case '?':
|
||||
case 'h':
|
||||
default:
|
||||
return print_usage(-1);
|
||||
|
||||
}
|
||||
|
||||
if (path[FIRMWARE] == NULL) {
|
||||
logerror("no firmware specified!\n");
|
||||
return print_usage(-1);
|
||||
}
|
||||
if ((device_id != NULL) && (device_path != NULL)) {
|
||||
logerror("only one of -d or -p can be specified\n");
|
||||
return print_usage(-1);
|
||||
}
|
||||
|
||||
/* determine the target type */
|
||||
if (type != NULL) {
|
||||
for (i=0; i<FX_TYPE_MAX; i++) {
|
||||
if (strcmp(type, fx_name[i]) == 0) {
|
||||
fx_type = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i >= FX_TYPE_MAX) {
|
||||
logerror("illegal microcontroller type: %s\n", type);
|
||||
return print_usage(-1);
|
||||
}
|
||||
}
|
||||
|
||||
/* open the device using libusb */
|
||||
status = libusb_init(NULL);
|
||||
if (status < 0) {
|
||||
logerror("libusb_init() failed: %s\n", libusb_error_name(status));
|
||||
return -1;
|
||||
}
|
||||
libusb_set_option(NULL, LIBUSB_OPTION_LOG_LEVEL, verbose);
|
||||
|
||||
/* try to pick up missing parameters from known devices */
|
||||
if ((type == NULL) || (device_id == NULL) || (device_path != NULL)) {
|
||||
if (libusb_get_device_list(NULL, &devs) < 0) {
|
||||
logerror("libusb_get_device_list() failed: %s\n", libusb_error_name(status));
|
||||
goto err;
|
||||
}
|
||||
for (i=0; (dev=devs[i]) != NULL; i++) {
|
||||
_busnum = libusb_get_bus_number(dev);
|
||||
_devaddr = libusb_get_device_address(dev);
|
||||
if ((type != NULL) && (device_path != NULL)) {
|
||||
// if both a type and bus,addr were specified, we just need to find our match
|
||||
if ((libusb_get_bus_number(dev) == busnum) && (libusb_get_device_address(dev) == devaddr))
|
||||
break;
|
||||
} else {
|
||||
status = libusb_get_device_descriptor(dev, &desc);
|
||||
if (status >= 0) {
|
||||
if (verbose >= 3) {
|
||||
logerror("examining %04x:%04x (%d,%d)\n",
|
||||
desc.idVendor, desc.idProduct, _busnum, _devaddr);
|
||||
}
|
||||
for (j=0; j<ARRAYSIZE(known_device); j++) {
|
||||
if ((desc.idVendor == known_device[j].vid)
|
||||
&& (desc.idProduct == known_device[j].pid)) {
|
||||
if (// nothing was specified
|
||||
((type == NULL) && (device_id == NULL) && (device_path == NULL)) ||
|
||||
// vid:pid was specified and we have a match
|
||||
((type == NULL) && (device_id != NULL) && (vid == desc.idVendor) && (pid == desc.idProduct)) ||
|
||||
// bus,addr was specified and we have a match
|
||||
((type == NULL) && (device_path != NULL) && (busnum == _busnum) && (devaddr == _devaddr)) ||
|
||||
// type was specified and we have a match
|
||||
((type != NULL) && (device_id == NULL) && (device_path == NULL) && (fx_type == known_device[j].type)) ) {
|
||||
fx_type = known_device[j].type;
|
||||
vid = desc.idVendor;
|
||||
pid = desc.idProduct;
|
||||
busnum = _busnum;
|
||||
devaddr = _devaddr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (j < ARRAYSIZE(known_device)) {
|
||||
if (verbose)
|
||||
logerror("found device '%s' [%04x:%04x] (%d,%d)\n",
|
||||
known_device[j].designation, vid, pid, busnum, devaddr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (dev == NULL) {
|
||||
libusb_free_device_list(devs, 1);
|
||||
libusb_exit(NULL);
|
||||
logerror("could not find a known device - please specify type and/or vid:pid and/or bus,dev\n");
|
||||
return print_usage(-1);
|
||||
}
|
||||
status = libusb_open(dev, &device);
|
||||
libusb_free_device_list(devs, 1);
|
||||
if (status < 0) {
|
||||
logerror("libusb_open() failed: %s\n", libusb_error_name(status));
|
||||
goto err;
|
||||
}
|
||||
} else if (device_id != NULL) {
|
||||
device = libusb_open_device_with_vid_pid(NULL, (uint16_t)vid, (uint16_t)pid);
|
||||
if (device == NULL) {
|
||||
logerror("libusb_open() failed\n");
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
/* We need to claim the first interface */
|
||||
libusb_set_auto_detach_kernel_driver(device, 1);
|
||||
status = libusb_claim_interface(device, 0);
|
||||
if (status != LIBUSB_SUCCESS) {
|
||||
libusb_close(device);
|
||||
logerror("libusb_claim_interface failed: %s\n", libusb_error_name(status));
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (verbose)
|
||||
logerror("microcontroller type: %s\n", fx_name[fx_type]);
|
||||
|
||||
for (i=0; i<ARRAYSIZE(path); i++) {
|
||||
if (path[i] != NULL) {
|
||||
ext = path[i] + strlen(path[i]) - 4;
|
||||
if ((_stricmp(ext, ".hex") == 0) || (strcmp(ext, ".ihx") == 0))
|
||||
img_type[i] = IMG_TYPE_HEX;
|
||||
else if (_stricmp(ext, ".iic") == 0)
|
||||
img_type[i] = IMG_TYPE_IIC;
|
||||
else if (_stricmp(ext, ".bix") == 0)
|
||||
img_type[i] = IMG_TYPE_BIX;
|
||||
else if (_stricmp(ext, ".img") == 0)
|
||||
img_type[i] = IMG_TYPE_IMG;
|
||||
else {
|
||||
logerror("%s is not a recognized image type\n", path[i]);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
if (verbose && path[i] != NULL)
|
||||
logerror("%s: type %s\n", path[i], img_name[img_type[i]]);
|
||||
}
|
||||
|
||||
if (path[LOADER] == NULL) {
|
||||
/* single stage, put into internal memory */
|
||||
if (verbose > 1)
|
||||
logerror("single stage: load on-chip memory\n");
|
||||
status = ezusb_load_ram(device, path[FIRMWARE], fx_type, img_type[FIRMWARE], 0);
|
||||
} else {
|
||||
/* two-stage, put loader into internal memory */
|
||||
if (verbose > 1)
|
||||
logerror("1st stage: load 2nd stage loader\n");
|
||||
status = ezusb_load_ram(device, path[LOADER], fx_type, img_type[LOADER], 0);
|
||||
if (status == 0) {
|
||||
/* two-stage, put firmware into internal memory */
|
||||
if (verbose > 1)
|
||||
logerror("2nd state: load on-chip memory\n");
|
||||
status = ezusb_load_ram(device, path[FIRMWARE], fx_type, img_type[FIRMWARE], 1);
|
||||
}
|
||||
}
|
||||
|
||||
libusb_release_interface(device, 0);
|
||||
libusb_close(device);
|
||||
libusb_exit(NULL);
|
||||
return status;
|
||||
err:
|
||||
libusb_exit(NULL);
|
||||
return -1;
|
||||
}
|
|
@ -1,73 +0,0 @@
|
|||
/*
|
||||
* libusb example program to list devices on the bus
|
||||
* Copyright © 2007 Daniel Drake <dsd@gentoo.org>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "libusb.h"
|
||||
|
||||
static void print_devs(libusb_device **devs)
|
||||
{
|
||||
libusb_device *dev;
|
||||
int i = 0, j = 0;
|
||||
uint8_t path[8];
|
||||
|
||||
while ((dev = devs[i++]) != NULL) {
|
||||
struct libusb_device_descriptor desc;
|
||||
int r = libusb_get_device_descriptor(dev, &desc);
|
||||
if (r < 0) {
|
||||
fprintf(stderr, "failed to get device descriptor");
|
||||
return;
|
||||
}
|
||||
|
||||
printf("%04x:%04x (bus %d, device %d)",
|
||||
desc.idVendor, desc.idProduct,
|
||||
libusb_get_bus_number(dev), libusb_get_device_address(dev));
|
||||
|
||||
r = libusb_get_port_numbers(dev, path, sizeof(path));
|
||||
if (r > 0) {
|
||||
printf(" path: %d", path[0]);
|
||||
for (j = 1; j < r; j++)
|
||||
printf(".%d", path[j]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
libusb_device **devs;
|
||||
int r;
|
||||
ssize_t cnt;
|
||||
|
||||
r = libusb_init(NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
cnt = libusb_get_device_list(NULL, &devs);
|
||||
if (cnt < 0){
|
||||
libusb_exit(NULL);
|
||||
return (int) cnt;
|
||||
}
|
||||
|
||||
print_devs(devs);
|
||||
libusb_free_device_list(devs, 1);
|
||||
|
||||
libusb_exit(NULL);
|
||||
return 0;
|
||||
}
|
|
@ -1,256 +0,0 @@
|
|||
/**
|
||||
* This file has no copyright assigned and is placed in the Public Domain.
|
||||
* This file was originally part of the w64 mingw-runtime package.
|
||||
*/
|
||||
|
||||
/* ISO C9x 7.18 Integer types <stdint.h>
|
||||
* Based on ISO/IEC SC22/WG14 9899 Committee draft (SC22 N2794)
|
||||
*
|
||||
* THIS SOFTWARE IS NOT COPYRIGHTED
|
||||
*
|
||||
* Contributor: Danny Smith <danny_r_smith_2001@yahoo.co.nz>
|
||||
* Modified for libusb/MSVC: Pete Batard <pbatard@gmail.com>
|
||||
*
|
||||
* This source code is offered for use in the public domain. You may
|
||||
* use, modify or distribute it freely.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful but
|
||||
* WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY
|
||||
* DISCLAIMED. This includes but is not limited to warranties of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* Date: 2010-04-02
|
||||
*/
|
||||
|
||||
#ifndef _MSC_VER
|
||||
#error This header should only be used with Microsoft compilers
|
||||
#endif
|
||||
|
||||
#ifndef _STDINT_H
|
||||
#define _STDINT_H
|
||||
|
||||
#ifndef _INTPTR_T_DEFINED
|
||||
#define _INTPTR_T_DEFINED
|
||||
#ifndef __intptr_t_defined
|
||||
#define __intptr_t_defined
|
||||
#undef intptr_t
|
||||
#ifdef _WIN64
|
||||
typedef __int64 intptr_t;
|
||||
#else
|
||||
typedef int intptr_t;
|
||||
#endif /* _WIN64 */
|
||||
#endif /* __intptr_t_defined */
|
||||
#endif /* _INTPTR_T_DEFINED */
|
||||
|
||||
#ifndef _UINTPTR_T_DEFINED
|
||||
#define _UINTPTR_T_DEFINED
|
||||
#ifndef __uintptr_t_defined
|
||||
#define __uintptr_t_defined
|
||||
#undef uintptr_t
|
||||
#ifdef _WIN64
|
||||
typedef unsigned __int64 uintptr_t;
|
||||
#else
|
||||
typedef unsigned int uintptr_t;
|
||||
#endif /* _WIN64 */
|
||||
#endif /* __uintptr_t_defined */
|
||||
#endif /* _UINTPTR_T_DEFINED */
|
||||
|
||||
#ifndef _PTRDIFF_T_DEFINED
|
||||
#define _PTRDIFF_T_DEFINED
|
||||
#ifndef _PTRDIFF_T_
|
||||
#define _PTRDIFF_T_
|
||||
#undef ptrdiff_t
|
||||
#ifdef _WIN64
|
||||
typedef __int64 ptrdiff_t;
|
||||
#else
|
||||
typedef int ptrdiff_t;
|
||||
#endif /* _WIN64 */
|
||||
#endif /* _PTRDIFF_T_ */
|
||||
#endif /* _PTRDIFF_T_DEFINED */
|
||||
|
||||
#ifndef _WCHAR_T_DEFINED
|
||||
#define _WCHAR_T_DEFINED
|
||||
#ifndef __cplusplus
|
||||
typedef unsigned short wchar_t;
|
||||
#endif /* C++ */
|
||||
#endif /* _WCHAR_T_DEFINED */
|
||||
|
||||
#ifndef _WCTYPE_T_DEFINED
|
||||
#define _WCTYPE_T_DEFINED
|
||||
#ifndef _WINT_T
|
||||
#define _WINT_T
|
||||
typedef unsigned short wint_t;
|
||||
typedef unsigned short wctype_t;
|
||||
#endif /* _WINT_T */
|
||||
#endif /* _WCTYPE_T_DEFINED */
|
||||
|
||||
/* 7.18.1.1 Exact-width integer types */
|
||||
typedef __int8 int8_t;
|
||||
typedef unsigned __int8 uint8_t;
|
||||
typedef __int16 int16_t;
|
||||
typedef unsigned __int16 uint16_t;
|
||||
typedef __int32 int32_t;
|
||||
typedef unsigned __int32 uint32_t;
|
||||
typedef __int64 int64_t;
|
||||
typedef unsigned __int64 uint64_t;
|
||||
|
||||
/* 7.18.1.2 Minimum-width integer types */
|
||||
typedef signed char int_least8_t;
|
||||
typedef unsigned char uint_least8_t;
|
||||
typedef short int_least16_t;
|
||||
typedef unsigned short uint_least16_t;
|
||||
typedef int int_least32_t;
|
||||
typedef unsigned uint_least32_t;
|
||||
typedef __int64 int_least64_t;
|
||||
typedef unsigned __int64 uint_least64_t;
|
||||
|
||||
/* 7.18.1.3 Fastest minimum-width integer types
|
||||
* Not actually guaranteed to be fastest for all purposes
|
||||
* Here we use the exact-width types for 8 and 16-bit ints.
|
||||
*/
|
||||
typedef __int8 int_fast8_t;
|
||||
typedef unsigned __int8 uint_fast8_t;
|
||||
typedef __int16 int_fast16_t;
|
||||
typedef unsigned __int16 uint_fast16_t;
|
||||
typedef __int32 int_fast32_t;
|
||||
typedef unsigned __int32 uint_fast32_t;
|
||||
typedef __int64 int_fast64_t;
|
||||
typedef unsigned __int64 uint_fast64_t;
|
||||
|
||||
/* 7.18.1.5 Greatest-width integer types */
|
||||
typedef __int64 intmax_t;
|
||||
typedef unsigned __int64 uintmax_t;
|
||||
|
||||
/* 7.18.2 Limits of specified-width integer types */
|
||||
|
||||
/* 7.18.2.1 Limits of exact-width integer types */
|
||||
#define INT8_MIN (-128)
|
||||
#define INT16_MIN (-32768)
|
||||
#define INT32_MIN (-2147483647 - 1)
|
||||
#define INT64_MIN (-9223372036854775807LL - 1)
|
||||
|
||||
#define INT8_MAX 127
|
||||
#define INT16_MAX 32767
|
||||
#define INT32_MAX 2147483647
|
||||
#define INT64_MAX 9223372036854775807LL
|
||||
|
||||
#define UINT8_MAX 255
|
||||
#define UINT16_MAX 65535
|
||||
#define UINT32_MAX 0xffffffffU /* 4294967295U */
|
||||
#define UINT64_MAX 0xffffffffffffffffULL /* 18446744073709551615ULL */
|
||||
|
||||
/* 7.18.2.2 Limits of minimum-width integer types */
|
||||
#define INT_LEAST8_MIN INT8_MIN
|
||||
#define INT_LEAST16_MIN INT16_MIN
|
||||
#define INT_LEAST32_MIN INT32_MIN
|
||||
#define INT_LEAST64_MIN INT64_MIN
|
||||
|
||||
#define INT_LEAST8_MAX INT8_MAX
|
||||
#define INT_LEAST16_MAX INT16_MAX
|
||||
#define INT_LEAST32_MAX INT32_MAX
|
||||
#define INT_LEAST64_MAX INT64_MAX
|
||||
|
||||
#define UINT_LEAST8_MAX UINT8_MAX
|
||||
#define UINT_LEAST16_MAX UINT16_MAX
|
||||
#define UINT_LEAST32_MAX UINT32_MAX
|
||||
#define UINT_LEAST64_MAX UINT64_MAX
|
||||
|
||||
/* 7.18.2.3 Limits of fastest minimum-width integer types */
|
||||
#define INT_FAST8_MIN INT8_MIN
|
||||
#define INT_FAST16_MIN INT16_MIN
|
||||
#define INT_FAST32_MIN INT32_MIN
|
||||
#define INT_FAST64_MIN INT64_MIN
|
||||
|
||||
#define INT_FAST8_MAX INT8_MAX
|
||||
#define INT_FAST16_MAX INT16_MAX
|
||||
#define INT_FAST32_MAX INT32_MAX
|
||||
#define INT_FAST64_MAX INT64_MAX
|
||||
|
||||
#define UINT_FAST8_MAX UINT8_MAX
|
||||
#define UINT_FAST16_MAX UINT16_MAX
|
||||
#define UINT_FAST32_MAX UINT32_MAX
|
||||
#define UINT_FAST64_MAX UINT64_MAX
|
||||
|
||||
/* 7.18.2.4 Limits of integer types capable of holding
|
||||
object pointers */
|
||||
#ifdef _WIN64
|
||||
#define INTPTR_MIN INT64_MIN
|
||||
#define INTPTR_MAX INT64_MAX
|
||||
#define UINTPTR_MAX UINT64_MAX
|
||||
#else
|
||||
#define INTPTR_MIN INT32_MIN
|
||||
#define INTPTR_MAX INT32_MAX
|
||||
#define UINTPTR_MAX UINT32_MAX
|
||||
#endif
|
||||
|
||||
/* 7.18.2.5 Limits of greatest-width integer types */
|
||||
#define INTMAX_MIN INT64_MIN
|
||||
#define INTMAX_MAX INT64_MAX
|
||||
#define UINTMAX_MAX UINT64_MAX
|
||||
|
||||
/* 7.18.3 Limits of other integer types */
|
||||
#ifdef _WIN64
|
||||
#define PTRDIFF_MIN INT64_MIN
|
||||
#define PTRDIFF_MAX INT64_MAX
|
||||
#else
|
||||
#define PTRDIFF_MIN INT32_MIN
|
||||
#define PTRDIFF_MAX INT32_MAX
|
||||
#endif
|
||||
|
||||
#define SIG_ATOMIC_MIN INT32_MIN
|
||||
#define SIG_ATOMIC_MAX INT32_MAX
|
||||
|
||||
#ifndef SIZE_MAX
|
||||
#ifdef _WIN64
|
||||
#define SIZE_MAX UINT64_MAX
|
||||
#else
|
||||
#define SIZE_MAX UINT32_MAX
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef WCHAR_MIN /* also in wchar.h */
|
||||
#define WCHAR_MIN 0U
|
||||
#define WCHAR_MAX 0xffffU
|
||||
#endif
|
||||
|
||||
/*
|
||||
* wint_t is unsigned short for compatibility with MS runtime
|
||||
*/
|
||||
#define WINT_MIN 0U
|
||||
#define WINT_MAX 0xffffU
|
||||
|
||||
|
||||
/* 7.18.4 Macros for integer constants */
|
||||
|
||||
/* 7.18.4.1 Macros for minimum-width integer constants
|
||||
|
||||
Accoding to Douglas Gwyn <gwyn@arl.mil>:
|
||||
"This spec was changed in ISO/IEC 9899:1999 TC1; in ISO/IEC
|
||||
9899:1999 as initially published, the expansion was required
|
||||
to be an integer constant of precisely matching type, which
|
||||
is impossible to accomplish for the shorter types on most
|
||||
platforms, because C99 provides no standard way to designate
|
||||
an integer constant with width less than that of type int.
|
||||
TC1 changed this to require just an integer constant
|
||||
*expression* with *promoted* type."
|
||||
|
||||
The trick used here is from Clive D W Feather.
|
||||
*/
|
||||
|
||||
#define INT8_C(val) (INT_LEAST8_MAX-INT_LEAST8_MAX+(val))
|
||||
#define INT16_C(val) (INT_LEAST16_MAX-INT_LEAST16_MAX+(val))
|
||||
#define INT32_C(val) (INT_LEAST32_MAX-INT_LEAST32_MAX+(val))
|
||||
/* The 'trick' doesn't work in C89 for long long because, without
|
||||
suffix, (val) will be evaluated as int, not intmax_t */
|
||||
#define INT64_C(val) val##i64
|
||||
|
||||
#define UINT8_C(val) (val)
|
||||
#define UINT16_C(val) (val)
|
||||
#define UINT32_C(val) (val##i32)
|
||||
#define UINT64_C(val) val##ui64
|
||||
|
||||
/* 7.18.4.2 Macros for greatest-width integer constants */
|
||||
#define INTMAX_C(val) val##i64
|
||||
#define UINTMAX_C(val) val##ui64
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1 @@
|
|||
Subproject commit ff8fe9397d4c61f072d209703f854c9f62ed17e3
|
|
@ -1,178 +0,0 @@
|
|||
LIBRARY "libusb-1.0.dll"
|
||||
EXPORTS
|
||||
libusb_alloc_streams
|
||||
libusb_alloc_streams@16 = libusb_alloc_streams
|
||||
libusb_alloc_transfer
|
||||
libusb_alloc_transfer@4 = libusb_alloc_transfer
|
||||
libusb_attach_kernel_driver
|
||||
libusb_attach_kernel_driver@8 = libusb_attach_kernel_driver
|
||||
libusb_bulk_transfer
|
||||
libusb_bulk_transfer@24 = libusb_bulk_transfer
|
||||
libusb_cancel_transfer
|
||||
libusb_cancel_transfer@4 = libusb_cancel_transfer
|
||||
libusb_claim_interface
|
||||
libusb_claim_interface@8 = libusb_claim_interface
|
||||
libusb_clear_halt
|
||||
libusb_clear_halt@8 = libusb_clear_halt
|
||||
libusb_close
|
||||
libusb_close@4 = libusb_close
|
||||
libusb_control_transfer
|
||||
libusb_control_transfer@32 = libusb_control_transfer
|
||||
libusb_detach_kernel_driver
|
||||
libusb_detach_kernel_driver@8 = libusb_detach_kernel_driver
|
||||
libusb_dev_mem_alloc
|
||||
libusb_dev_mem_alloc@8 = libusb_dev_mem_alloc
|
||||
libusb_dev_mem_free
|
||||
libusb_dev_mem_free@12 = libusb_dev_mem_free
|
||||
libusb_error_name
|
||||
libusb_error_name@4 = libusb_error_name
|
||||
libusb_event_handler_active
|
||||
libusb_event_handler_active@4 = libusb_event_handler_active
|
||||
libusb_event_handling_ok
|
||||
libusb_event_handling_ok@4 = libusb_event_handling_ok
|
||||
libusb_exit
|
||||
libusb_exit@4 = libusb_exit
|
||||
libusb_free_bos_descriptor
|
||||
libusb_free_bos_descriptor@4 = libusb_free_bos_descriptor
|
||||
libusb_free_config_descriptor
|
||||
libusb_free_config_descriptor@4 = libusb_free_config_descriptor
|
||||
libusb_free_container_id_descriptor
|
||||
libusb_free_container_id_descriptor@4 = libusb_free_container_id_descriptor
|
||||
libusb_free_device_list
|
||||
libusb_free_device_list@8 = libusb_free_device_list
|
||||
libusb_free_pollfds
|
||||
libusb_free_pollfds@4 = libusb_free_pollfds
|
||||
libusb_free_ss_endpoint_companion_descriptor
|
||||
libusb_free_ss_endpoint_companion_descriptor@4 = libusb_free_ss_endpoint_companion_descriptor
|
||||
libusb_free_ss_usb_device_capability_descriptor
|
||||
libusb_free_ss_usb_device_capability_descriptor@4 = libusb_free_ss_usb_device_capability_descriptor
|
||||
libusb_free_streams
|
||||
libusb_free_streams@12 = libusb_free_streams
|
||||
libusb_free_transfer
|
||||
libusb_free_transfer@4 = libusb_free_transfer
|
||||
libusb_free_usb_2_0_extension_descriptor
|
||||
libusb_free_usb_2_0_extension_descriptor@4 = libusb_free_usb_2_0_extension_descriptor
|
||||
libusb_get_active_config_descriptor
|
||||
libusb_get_active_config_descriptor@8 = libusb_get_active_config_descriptor
|
||||
libusb_get_bos_descriptor
|
||||
libusb_get_bos_descriptor@8 = libusb_get_bos_descriptor
|
||||
libusb_get_bus_number
|
||||
libusb_get_bus_number@4 = libusb_get_bus_number
|
||||
libusb_get_config_descriptor
|
||||
libusb_get_config_descriptor@12 = libusb_get_config_descriptor
|
||||
libusb_get_config_descriptor_by_value
|
||||
libusb_get_config_descriptor_by_value@12 = libusb_get_config_descriptor_by_value
|
||||
libusb_get_configuration
|
||||
libusb_get_configuration@8 = libusb_get_configuration
|
||||
libusb_get_container_id_descriptor
|
||||
libusb_get_container_id_descriptor@12 = libusb_get_container_id_descriptor
|
||||
libusb_get_device
|
||||
libusb_get_device@4 = libusb_get_device
|
||||
libusb_get_device_address
|
||||
libusb_get_device_address@4 = libusb_get_device_address
|
||||
libusb_get_device_descriptor
|
||||
libusb_get_device_descriptor@8 = libusb_get_device_descriptor
|
||||
libusb_get_device_list
|
||||
libusb_get_device_list@8 = libusb_get_device_list
|
||||
libusb_get_device_speed
|
||||
libusb_get_device_speed@4 = libusb_get_device_speed
|
||||
libusb_get_max_iso_packet_size
|
||||
libusb_get_max_iso_packet_size@8 = libusb_get_max_iso_packet_size
|
||||
libusb_get_max_packet_size
|
||||
libusb_get_max_packet_size@8 = libusb_get_max_packet_size
|
||||
libusb_get_next_timeout
|
||||
libusb_get_next_timeout@8 = libusb_get_next_timeout
|
||||
libusb_get_parent
|
||||
libusb_get_parent@4 = libusb_get_parent
|
||||
libusb_get_pollfds
|
||||
libusb_get_pollfds@4 = libusb_get_pollfds
|
||||
libusb_get_port_number
|
||||
libusb_get_port_number@4 = libusb_get_port_number
|
||||
libusb_get_port_numbers
|
||||
libusb_get_port_numbers@12 = libusb_get_port_numbers
|
||||
libusb_get_port_path
|
||||
libusb_get_port_path@16 = libusb_get_port_path
|
||||
libusb_get_ss_endpoint_companion_descriptor
|
||||
libusb_get_ss_endpoint_companion_descriptor@12 = libusb_get_ss_endpoint_companion_descriptor
|
||||
libusb_get_ss_usb_device_capability_descriptor
|
||||
libusb_get_ss_usb_device_capability_descriptor@12 = libusb_get_ss_usb_device_capability_descriptor
|
||||
libusb_get_string_descriptor_ascii
|
||||
libusb_get_string_descriptor_ascii@16 = libusb_get_string_descriptor_ascii
|
||||
libusb_get_usb_2_0_extension_descriptor
|
||||
libusb_get_usb_2_0_extension_descriptor@12 = libusb_get_usb_2_0_extension_descriptor
|
||||
libusb_get_version
|
||||
libusb_get_version@0 = libusb_get_version
|
||||
libusb_handle_events
|
||||
libusb_handle_events@4 = libusb_handle_events
|
||||
libusb_handle_events_completed
|
||||
libusb_handle_events_completed@8 = libusb_handle_events_completed
|
||||
libusb_handle_events_locked
|
||||
libusb_handle_events_locked@8 = libusb_handle_events_locked
|
||||
libusb_handle_events_timeout
|
||||
libusb_handle_events_timeout@8 = libusb_handle_events_timeout
|
||||
libusb_handle_events_timeout_completed
|
||||
libusb_handle_events_timeout_completed@12 = libusb_handle_events_timeout_completed
|
||||
libusb_has_capability
|
||||
libusb_has_capability@4 = libusb_has_capability
|
||||
libusb_hotplug_deregister_callback
|
||||
libusb_hotplug_deregister_callback@8 = libusb_hotplug_deregister_callback
|
||||
libusb_hotplug_register_callback
|
||||
libusb_hotplug_register_callback@36 = libusb_hotplug_register_callback
|
||||
libusb_init
|
||||
libusb_init@4 = libusb_init
|
||||
libusb_interrupt_event_handler
|
||||
libusb_interrupt_event_handler@4 = libusb_interrupt_event_handler
|
||||
libusb_interrupt_transfer
|
||||
libusb_interrupt_transfer@24 = libusb_interrupt_transfer
|
||||
libusb_kernel_driver_active
|
||||
libusb_kernel_driver_active@8 = libusb_kernel_driver_active
|
||||
libusb_lock_event_waiters
|
||||
libusb_lock_event_waiters@4 = libusb_lock_event_waiters
|
||||
libusb_lock_events
|
||||
libusb_lock_events@4 = libusb_lock_events
|
||||
libusb_open
|
||||
libusb_open@8 = libusb_open
|
||||
libusb_open_device_with_vid_pid
|
||||
libusb_open_device_with_vid_pid@12 = libusb_open_device_with_vid_pid
|
||||
libusb_pollfds_handle_timeouts
|
||||
libusb_pollfds_handle_timeouts@4 = libusb_pollfds_handle_timeouts
|
||||
libusb_ref_device
|
||||
libusb_ref_device@4 = libusb_ref_device
|
||||
libusb_release_interface
|
||||
libusb_release_interface@8 = libusb_release_interface
|
||||
libusb_reset_device
|
||||
libusb_reset_device@4 = libusb_reset_device
|
||||
libusb_set_auto_detach_kernel_driver
|
||||
libusb_set_auto_detach_kernel_driver@8 = libusb_set_auto_detach_kernel_driver
|
||||
libusb_set_configuration
|
||||
libusb_set_configuration@8 = libusb_set_configuration
|
||||
libusb_set_debug
|
||||
libusb_set_debug@8 = libusb_set_debug
|
||||
libusb_set_log_cb
|
||||
libusb_set_log_cb@12 = libusb_set_log_cb
|
||||
libusb_set_interface_alt_setting
|
||||
libusb_set_interface_alt_setting@12 = libusb_set_interface_alt_setting
|
||||
libusb_set_option
|
||||
_libusb_set_option = libusb_set_option
|
||||
libusb_set_pollfd_notifiers
|
||||
libusb_set_pollfd_notifiers@16 = libusb_set_pollfd_notifiers
|
||||
libusb_setlocale
|
||||
libusb_setlocale@4 = libusb_setlocale
|
||||
libusb_strerror
|
||||
libusb_strerror@4 = libusb_strerror
|
||||
libusb_submit_transfer
|
||||
libusb_submit_transfer@4 = libusb_submit_transfer
|
||||
libusb_transfer_get_stream_id
|
||||
libusb_transfer_get_stream_id@4 = libusb_transfer_get_stream_id
|
||||
libusb_transfer_set_stream_id
|
||||
libusb_transfer_set_stream_id@8 = libusb_transfer_set_stream_id
|
||||
libusb_try_lock_events
|
||||
libusb_try_lock_events@4 = libusb_try_lock_events
|
||||
libusb_unlock_event_waiters
|
||||
libusb_unlock_event_waiters@4 = libusb_unlock_event_waiters
|
||||
libusb_unlock_events
|
||||
libusb_unlock_events@4 = libusb_unlock_events
|
||||
libusb_unref_device
|
||||
libusb_unref_device@4 = libusb_unref_device
|
||||
libusb_wait_for_event
|
||||
libusb_wait_for_event@8 = libusb_wait_for_event
|
|
@ -0,0 +1,65 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(SolutionDir)common\vsprops\BaseProjectConfig.props" />
|
||||
<Import Project="$(SolutionDir)common\vsprops\WinSDK.props" />
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{349EE8F9-7D25-4909-AAF5-FF3FADE72187}</ProjectGuid>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<WholeProgramOptimization Condition="$(Configuration.Contains(Release))">true</WholeProgramOptimization>
|
||||
<UseDebugLibraries Condition="$(Configuration.Contains(Debug))">true</UseDebugLibraries>
|
||||
<UseDebugLibraries Condition="!$(Configuration.Contains(Debug))">false</UseDebugLibraries>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings" />
|
||||
<ImportGroup Label="PropertySheets">
|
||||
<Import Project="..\DefaultProjectRootDir.props" />
|
||||
<Import Project="..\3rdparty.props" />
|
||||
<Import Condition="$(Configuration.Contains(Debug))" Project="..\..\common\vsprops\CodeGen_Debug.props" />
|
||||
<Import Condition="$(Configuration.Contains(Devel))" Project="..\..\common\vsprops\CodeGen_Devel.props" />
|
||||
<Import Condition="$(Configuration.Contains(Release))" Project="..\..\common\vsprops\CodeGen_Release.props" />
|
||||
<Import Condition="!$(Configuration.Contains(Release))" Project="..\..\common\vsprops\IncrementalLinking.props" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup>
|
||||
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="libusb\libusb\core.c" />
|
||||
<ClCompile Include="libusb\libusb\descriptor.c" />
|
||||
<ClCompile Include="libusb\libusb\os\events_windows.c" />
|
||||
<ClCompile Include="libusb\libusb\hotplug.c" />
|
||||
<ClCompile Include="libusb\libusb\io.c" />
|
||||
<ClCompile Include="libusb\libusb\strerror.c" />
|
||||
<ClCompile Include="libusb\libusb\sync.c" />
|
||||
<ClCompile Include="libusb\libusb\os\threads_windows.c" />
|
||||
<ClCompile Include="libusb\libusb\os\windows_common.c" />
|
||||
<ClCompile Include="libusb\libusb\os\windows_usbdk.c" />
|
||||
<ClCompile Include="libusb\libusb\os\windows_winusb.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="libusb\msvc\config.h" />
|
||||
<ClInclude Include="libusb\libusb\os\events_windows.h" />
|
||||
<ClInclude Include="libusb\libusb\libusb.h" />
|
||||
<ClInclude Include="libusb\libusb\libusbi.h" />
|
||||
<ClInclude Include="libusb\libusb\os\threads_windows.h" />
|
||||
<ClInclude Include="libusb\libusb\version.h" />
|
||||
<ClInclude Include="libusb\libusb\version_nano.h" />
|
||||
<ClInclude Include="libusb\libusb\os\windows_common.h" />
|
||||
<ClInclude Include="libusb\libusb\os\windows_usbdk.h" />
|
||||
<ClInclude Include="libusb\libusb\os\windows_winusb.h" />
|
||||
</ItemGroup>
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<WarningLevel>TurnOffAllWarnings</WarningLevel>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)3rdparty\libusb\libusb\libusb;$(SolutionDir)3rdparty\libusb\libusb\msvc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets" />
|
||||
</Project>
|
16
PCSX2_qt.sln
16
PCSX2_qt.sln
|
@ -59,6 +59,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "updater", "updater\updater.
|
|||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cpuinfo", "3rdparty\cpuinfo\cpuinfo.vcxproj", "{7E183337-A7E9-460C-9D3D-568BC9F9BCC1}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libusb", "3rdparty\libusb\libusb.vcxproj", "{349EE8F9-7D25-4909-AAF5-FF3FADE72187}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug AVX2|x64 = Debug AVX2|x64
|
||||
|
@ -393,6 +395,18 @@ Global
|
|||
{7E183337-A7E9-460C-9D3D-568BC9F9BCC1}.Release AVX2|x64.Build.0 = Release|x64
|
||||
{7E183337-A7E9-460C-9D3D-568BC9F9BCC1}.Release|x64.ActiveCfg = Release|x64
|
||||
{7E183337-A7E9-460C-9D3D-568BC9F9BCC1}.Release|x64.Build.0 = Release|x64
|
||||
{349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Debug AVX2|x64.ActiveCfg = Debug|x64
|
||||
{349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Debug AVX2|x64.Build.0 = Debug|x64
|
||||
{349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Debug|x64.Build.0 = Debug|x64
|
||||
{349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Devel AVX2|x64.ActiveCfg = Debug|x64
|
||||
{349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Devel AVX2|x64.Build.0 = Debug|x64
|
||||
{349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Devel|x64.ActiveCfg = Devel|x64
|
||||
{349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Devel|x64.Build.0 = Devel|x64
|
||||
{349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Release AVX2|x64.ActiveCfg = Release|x64
|
||||
{349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Release AVX2|x64.Build.0 = Release|x64
|
||||
{349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Release|x64.ActiveCfg = Release|x64
|
||||
{349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Release|x64.Build.0 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
@ -408,7 +422,6 @@ Global
|
|||
{47AFDBEF-F15F-4BC0-B436-5BE443C3F80F} = {78EBE642-7A4D-4EA7-86BE-5639C6646C38}
|
||||
{EB12076D-4CEF-4D9D-8F34-5D0043798051} = {78EBE642-7A4D-4EA7-86BE-5639C6646C38}
|
||||
{A0D2B3AD-1F72-4EE3-8B5C-F2C358DA35F0} = {78EBE642-7A4D-4EA7-86BE-5639C6646C38}
|
||||
{EB12076D-4CEF-4D9D-8F34-5D0043798051} = {78EBE642-7A4D-4EA7-86BE-5639C6646C38}
|
||||
{ED2F21FD-0A36-4A8F-9B90-E7D92A2ACB63} = {78EBE642-7A4D-4EA7-86BE-5639C6646C38}
|
||||
{C0293B32-5ACF-40F0-AA6C-E6DA6F3BF33A} = {78EBE642-7A4D-4EA7-86BE-5639C6646C38}
|
||||
{88FB34EC-845E-4F21-A552-F1573B9ED167} = {78EBE642-7A4D-4EA7-86BE-5639C6646C38}
|
||||
|
@ -422,6 +435,7 @@ Global
|
|||
{D45CEC7A-3171-40DD-975D-E1544CF16139} = {78EBE642-7A4D-4EA7-86BE-5639C6646C38}
|
||||
{A4323327-3F2B-4271-83D9-7F9A3C66B6B2} = {78EBE642-7A4D-4EA7-86BE-5639C6646C38}
|
||||
{7E183337-A7E9-460C-9D3D-568BC9F9BCC1} = {78EBE642-7A4D-4EA7-86BE-5639C6646C38}
|
||||
{349EE8F9-7D25-4909-AAF5-FF3FADE72187} = {78EBE642-7A4D-4EA7-86BE-5639C6646C38}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {0BC474EA-3628-45D3-9DBC-E22D0B7E0F77}
|
||||
|
|
|
@ -72,6 +72,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "d3d12memalloc", "3rdparty\d
|
|||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "lzma", "3rdparty\lzma\lzma.vcxproj", "{A4323327-3F2B-4271-83D9-7F9A3C66B6B2}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libusb", "3rdparty\libusb\libusb.vcxproj", "{349EE8F9-7D25-4909-AAF5-FF3FADE72187}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug AVX2|x64 = Debug AVX2|x64
|
||||
|
@ -430,6 +432,18 @@ Global
|
|||
{A4323327-3F2B-4271-83D9-7F9A3C66B6B2}.Release AVX2|x64.Build.0 = Release|x64
|
||||
{A4323327-3F2B-4271-83D9-7F9A3C66B6B2}.Release|x64.ActiveCfg = Release|x64
|
||||
{A4323327-3F2B-4271-83D9-7F9A3C66B6B2}.Release|x64.Build.0 = Release|x64
|
||||
{349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Debug AVX2|x64.ActiveCfg = Debug|x64
|
||||
{349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Debug AVX2|x64.Build.0 = Debug|x64
|
||||
{349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Debug|x64.Build.0 = Debug|x64
|
||||
{349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Devel AVX2|x64.ActiveCfg = Debug|x64
|
||||
{349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Devel AVX2|x64.Build.0 = Debug|x64
|
||||
{349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Devel|x64.ActiveCfg = Devel|x64
|
||||
{349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Devel|x64.Build.0 = Devel|x64
|
||||
{349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Release AVX2|x64.ActiveCfg = Release|x64
|
||||
{349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Release AVX2|x64.Build.0 = Release|x64
|
||||
{349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Release|x64.ActiveCfg = Release|x64
|
||||
{349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Release|x64.Build.0 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
|
|
@ -104,6 +104,12 @@ target_sources(pcsx2-qt PRIVATE
|
|||
Settings/DEV9UiCommon.h
|
||||
Settings/HddCreateQt.cpp
|
||||
Settings/HddCreateQt.h
|
||||
Settings/Python2BindingWidget.ui
|
||||
Settings/Python2BindingWidget.cpp
|
||||
Settings/Python2BindingWidget.h
|
||||
Settings/Python2SettingsWidget.cpp
|
||||
Settings/Python2SettingsWidget.h
|
||||
Settings/Python2SettingsWidget.ui
|
||||
Settings/SettingsDialog.cpp
|
||||
Settings/SettingsDialog.h
|
||||
Settings/SettingsDialog.ui
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "Settings/ControllerGlobalSettingsWidget.h"
|
||||
#include "Settings/ControllerBindingWidgets.h"
|
||||
#include "Settings/HotkeySettingsWidget.h"
|
||||
#include "Settings/Python2BindingWidget.h"
|
||||
|
||||
#include "pcsx2/Frontend/INISettingsInterface.h"
|
||||
#include "pcsx2/PAD/Host/PAD.h"
|
||||
|
@ -393,6 +394,15 @@ void ControllerSettingsDialog::createWidgets()
|
|||
m_ui.settingsContainer->addWidget(m_hotkey_settings);
|
||||
}
|
||||
|
||||
{
|
||||
QListWidgetItem* item = new QListWidgetItem();
|
||||
item->setText(tr("Python 2"));
|
||||
item->setIcon(QIcon::fromTheme("gamepad-line"));
|
||||
m_ui.settingsCategory->addItem(item);
|
||||
m_python2_settings = new Python2BindingWidget(m_ui.settingsContainer, this);
|
||||
m_ui.settingsContainer->addWidget(m_python2_settings);
|
||||
}
|
||||
|
||||
m_ui.loadProfile->setEnabled(isEditingProfile());
|
||||
m_ui.deleteProfile->setEnabled(isEditingProfile());
|
||||
m_ui.restoreDefaults->setEnabled(isEditingGlobalSettings());
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
class ControllerGlobalSettingsWidget;
|
||||
class ControllerBindingWidget;
|
||||
class HotkeySettingsWidget;
|
||||
class Python2BindingWidget;
|
||||
|
||||
class SettingsInterface;
|
||||
|
||||
|
@ -101,6 +102,7 @@ private:
|
|||
ControllerGlobalSettingsWidget* m_global_settings = nullptr;
|
||||
std::array<ControllerBindingWidget*, MAX_PORTS> m_port_bindings{};
|
||||
HotkeySettingsWidget* m_hotkey_settings = nullptr;
|
||||
Python2BindingWidget* m_python2_settings = nullptr;
|
||||
|
||||
QList<QPair<QString, QString>> m_device_list;
|
||||
QStringList m_vibration_motors;
|
||||
|
|
|
@ -0,0 +1,770 @@
|
|||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2022 PCSX2 Dev Team, 987123879113
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "PrecompiledHeader.h"
|
||||
|
||||
#include <QtCore/QTimer>
|
||||
#include <QtGui/QKeyEvent>
|
||||
#include <QtGui/QMouseEvent>
|
||||
#include <QtGui/QWheelEvent>
|
||||
#include <QtWidgets/QInputDialog>
|
||||
#include <QtWidgets/QMenu>
|
||||
#include <QtWidgets/QMessageBox>
|
||||
#include <algorithm>
|
||||
|
||||
#include "Settings/Python2BindingWidget.h"
|
||||
#include "Settings/ControllerSettingsDialog.h"
|
||||
#include "Settings/ControllerSettingWidgetBinder.h"
|
||||
#include "Settings/InputBindingWidget.h"
|
||||
#include "Settings/SettingsDialog.h"
|
||||
#include "EmuThread.h"
|
||||
#include "QtUtils.h"
|
||||
#include "SettingWidgetBinder.h"
|
||||
|
||||
#include "common/StringUtil.h"
|
||||
#include "pcsx2/HostSettings.h"
|
||||
#include "pcsx2/PAD/Host/PAD.h"
|
||||
|
||||
#include "pcsx2/GS/GSIntrin.h" // _BitScanForward
|
||||
|
||||
#include "pcsx2/USB/usb-python2/inputs/Python2QtInputManager.h"
|
||||
|
||||
|
||||
Python2BindingWidget::Python2BindingWidget(QWidget* parent, ControllerSettingsDialog* dialog)
|
||||
: QWidget(parent)
|
||||
, m_dialog(dialog)
|
||||
{
|
||||
m_ui.setupUi(this);
|
||||
Python2QtInputManager::LoadMapping();
|
||||
|
||||
connect(m_ui.gameTypeFilter, &QComboBox::currentIndexChanged, this, [this](int index) {
|
||||
m_ui.inputList->clear();
|
||||
|
||||
if (s_python2_system_info[index].bindings == nullptr)
|
||||
{
|
||||
for (auto system_entry : s_python2_system_info)
|
||||
{
|
||||
if (system_entry.bindings == nullptr)
|
||||
continue;
|
||||
|
||||
for (u32 i = 0; i < system_entry.num_bindings; i++)
|
||||
{
|
||||
auto entry = system_entry.bindings[i];
|
||||
|
||||
if (entry.type != PAD::ControllerBindingType::Button)
|
||||
continue;
|
||||
|
||||
QListWidgetItem* item = new QListWidgetItem();
|
||||
item->setText(tr("%1 - %2").arg(QString::fromStdString(system_entry.name)).arg(QString::fromStdString(entry.display_name)));
|
||||
item->setData(Qt::UserRole, QString::fromStdString(entry.name));
|
||||
m_ui.inputList->addItem(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (u32 i = 0; i < s_python2_system_info[index].num_bindings; i++)
|
||||
{
|
||||
auto entry = s_python2_system_info[index].bindings[i];
|
||||
|
||||
if (entry.type != PAD::ControllerBindingType::Button)
|
||||
continue;
|
||||
|
||||
QListWidgetItem* item = new QListWidgetItem();
|
||||
item->setText(QString::fromStdString(entry.display_name));
|
||||
item->setText(tr("%1 - %2").arg(QString::fromStdString(s_python2_system_info[index].name)).arg(QString::fromStdString(entry.display_name)));
|
||||
item->setData(Qt::UserRole, QString::fromStdString(entry.name));
|
||||
m_ui.inputList->addItem(item);
|
||||
}
|
||||
}
|
||||
|
||||
m_ui.inputList->setCurrentRow(0);
|
||||
});
|
||||
|
||||
// Inputs tab
|
||||
connect(m_ui.bindKey, &QPushButton::clicked, this, [this]() { startListeningForInput(TIMEOUT_FOR_SINGLE_BINDING, false); });
|
||||
connect(m_ui.unbindKey, &QPushButton::clicked, this, [this]() { unbindKeyClicked(m_ui.keybindList); });
|
||||
|
||||
for (std::size_t i = 0; i < std::size(s_python2_system_info); i++)
|
||||
{
|
||||
auto input_entry = s_python2_system_info[i];
|
||||
m_ui.gameTypeFilter->addItem(QString::fromStdString(input_entry.name), (int)i);
|
||||
}
|
||||
m_ui.gameTypeFilter->setCurrentIndex(0);
|
||||
|
||||
// Analog Inputs tab
|
||||
connect(m_ui.bindKeyAnalog, &QPushButton::clicked, this, [this]() { startListeningForInput(TIMEOUT_FOR_SINGLE_BINDING, true); });
|
||||
connect(m_ui.unbindKeyAnalog, &QPushButton::clicked, this, [this]() { unbindKeyClicked(m_ui.keybindListAnalogs); });
|
||||
connect(m_ui.inputListAnalogs, &QListWidget::itemClicked, this, [this](QListWidgetItem* item) {
|
||||
// Disable motor scale slider
|
||||
m_ui.Deadzone->setDisabled(true);
|
||||
m_ui.AxisScale->setDisabled(true);
|
||||
|
||||
m_ui.Deadzone->blockSignals(true);
|
||||
m_ui.Deadzone->setValue(m_ui.Deadzone->minimum());
|
||||
m_ui.Deadzone->blockSignals(false);
|
||||
|
||||
m_ui.AxisScale->blockSignals(true);
|
||||
m_ui.AxisScale->setValue(m_ui.AxisScale->minimum());
|
||||
m_ui.AxisScale->blockSignals(false);
|
||||
});
|
||||
connect(m_ui.keybindListAnalogs, &QTableWidget::itemClicked, this, [this](QTableWidgetItem* item) {
|
||||
// Enable motor scale slider
|
||||
auto currentRow = m_ui.keybindListAnalogs->currentRow();
|
||||
|
||||
if (currentRow == -1)
|
||||
return;
|
||||
|
||||
auto deadzoneItem = m_ui.keybindListAnalogs->item(currentRow, 1);
|
||||
auto axisScaleItem = m_ui.keybindListAnalogs->item(currentRow, 2);
|
||||
|
||||
m_ui.Deadzone->blockSignals(true);
|
||||
m_ui.Deadzone->setValue(deadzoneItem->data(Qt::UserRole).toDouble() * static_cast<double>(m_ui.Deadzone->maximum()));
|
||||
m_ui.Deadzone->blockSignals(false);
|
||||
|
||||
m_ui.AxisScale->blockSignals(true);
|
||||
m_ui.AxisScale->setValue(axisScaleItem->data(Qt::UserRole).toDouble() * static_cast<double>(m_ui.AxisScale->maximum()));
|
||||
m_ui.AxisScale->blockSignals(false);
|
||||
|
||||
m_ui.Deadzone->setDisabled(false);
|
||||
m_ui.AxisScale->setDisabled(false);
|
||||
});
|
||||
connect(m_ui.Deadzone, &QSlider::valueChanged, this, [this](int value) {
|
||||
auto currentRow = m_ui.keybindListAnalogs->currentRow();
|
||||
|
||||
if (currentRow == -1)
|
||||
return;
|
||||
|
||||
auto selectedItem = m_ui.keybindListAnalogs->item(currentRow, 0);
|
||||
uint uniqueId = selectedItem->data(Qt::UserRole).toUInt();
|
||||
auto val = static_cast<double>(value) / static_cast<double>(m_ui.Deadzone->maximum());
|
||||
|
||||
for (auto &bind : Python2QtInputManager::GetCurrentMappings()) {
|
||||
if (bind.uniqueId == uniqueId) {
|
||||
bind.analogDeadzone = val;
|
||||
}
|
||||
}
|
||||
|
||||
saveAndRefresh();
|
||||
|
||||
m_ui.keybindListAnalogs->setCurrentItem(
|
||||
m_ui.keybindListAnalogs->item(currentRow, 0)
|
||||
);
|
||||
});
|
||||
connect(m_ui.AxisScale, &QSlider::valueChanged, this, [this](int value) {
|
||||
auto currentRow = m_ui.keybindListAnalogs->currentRow();
|
||||
|
||||
if (currentRow == -1)
|
||||
return;
|
||||
|
||||
auto selectedItem = m_ui.keybindListAnalogs->item(currentRow, 0);
|
||||
uint uniqueId = selectedItem->data(Qt::UserRole).toUInt();
|
||||
auto val = static_cast<double>(value) / static_cast<double>(m_ui.AxisScale->maximum());
|
||||
|
||||
for (auto &bind : Python2QtInputManager::GetCurrentMappings()) {
|
||||
if (bind.uniqueId == uniqueId) {
|
||||
bind.analogSensitivity = val;
|
||||
}
|
||||
}
|
||||
|
||||
saveAndRefresh();
|
||||
|
||||
m_ui.keybindListAnalogs->setCurrentItem(
|
||||
m_ui.keybindListAnalogs->item(currentRow, 0)
|
||||
);
|
||||
});
|
||||
|
||||
for (auto system_entry : s_python2_system_info)
|
||||
{
|
||||
if (system_entry.bindings == nullptr)
|
||||
continue;
|
||||
|
||||
for (u32 i = 0; i < system_entry.num_bindings; i++)
|
||||
{
|
||||
auto entry = system_entry.bindings[i];
|
||||
|
||||
if (entry.type != PAD::ControllerBindingType::Axis && entry.type != PAD::ControllerBindingType::HalfAxis)
|
||||
continue;
|
||||
|
||||
QListWidgetItem* item = new QListWidgetItem();
|
||||
item->setText(tr("%1 - %2").arg(QString::fromStdString(system_entry.name)).arg(QString::fromStdString(entry.display_name)));
|
||||
item->setData(Qt::UserRole, QString::fromStdString(entry.name));
|
||||
m_ui.inputListAnalogs->addItem(item);
|
||||
}
|
||||
}
|
||||
m_ui.inputListAnalogs->setCurrentRow(0);
|
||||
m_ui.Deadzone->setDisabled(true);
|
||||
m_ui.AxisScale->setDisabled(true);
|
||||
|
||||
// Motors tab
|
||||
connect(m_ui.bindKeyMotor, &QPushButton::clicked, this, &Python2BindingWidget::onBindKeyMotorClicked);
|
||||
connect(m_ui.unbindKeyMotor, &QPushButton::clicked, this, [this]() { unbindKeyClicked(m_ui.keybindListMotors); });
|
||||
connect(m_ui.motorList, &QListWidget::itemClicked, this, [this](QListWidgetItem* item) {
|
||||
// Disable motor scale slider
|
||||
m_ui.MotorScale->setDisabled(true);
|
||||
|
||||
m_ui.MotorScale->blockSignals(true);
|
||||
m_ui.MotorScale->setValue(m_ui.MotorScale->minimum());
|
||||
m_ui.MotorScale->blockSignals(false);
|
||||
});
|
||||
connect(m_ui.keybindListMotors, &QTableWidget::itemClicked, this, [this](QTableWidgetItem* item) {
|
||||
// Enable motor scale slider
|
||||
auto currentRow = m_ui.keybindListMotors->currentRow();
|
||||
|
||||
if (currentRow == -1)
|
||||
return;
|
||||
|
||||
auto motorScaleItem = m_ui.keybindListMotors->item(currentRow, 1);
|
||||
|
||||
m_ui.MotorScale->blockSignals(true);
|
||||
m_ui.MotorScale->setValue(motorScaleItem->data(Qt::UserRole).toDouble() * static_cast<double>(m_ui.MotorScale->maximum()));
|
||||
m_ui.MotorScale->blockSignals(false);
|
||||
|
||||
m_ui.MotorScale->setDisabled(false);
|
||||
});
|
||||
connect(m_ui.MotorScale, &QSlider::valueChanged, this, [this](int value) {
|
||||
auto currentRow = m_ui.keybindListMotors->currentRow();
|
||||
|
||||
if (currentRow == -1)
|
||||
return;
|
||||
|
||||
auto selectedItem = m_ui.keybindListMotors->item(currentRow, 0);
|
||||
uint uniqueId = selectedItem->data(Qt::UserRole).toUInt();
|
||||
auto val = static_cast<double>(value) / static_cast<double>(m_ui.MotorScale->maximum());
|
||||
|
||||
for (auto &bind : Python2QtInputManager::GetCurrentMappings()) {
|
||||
if (bind.uniqueId == uniqueId) {
|
||||
bind.motorScale = val;
|
||||
}
|
||||
}
|
||||
|
||||
saveAndRefresh();
|
||||
|
||||
m_ui.keybindListMotors->setCurrentItem(
|
||||
m_ui.keybindListMotors->item(currentRow, 0)
|
||||
);
|
||||
});
|
||||
|
||||
for (auto system_entry : s_python2_system_info)
|
||||
{
|
||||
if (system_entry.bindings == nullptr)
|
||||
continue;
|
||||
|
||||
for (u32 i = 0; i < system_entry.num_bindings; i++)
|
||||
{
|
||||
auto entry = system_entry.bindings[i];
|
||||
|
||||
if (entry.type != PAD::ControllerBindingType::Motor)
|
||||
continue;
|
||||
|
||||
QListWidgetItem* item = new QListWidgetItem();
|
||||
item->setText(tr("%1 - %2").arg(QString::fromStdString(system_entry.name)).arg(QString::fromStdString(entry.display_name)));
|
||||
item->setData(Qt::UserRole, QString::fromStdString(entry.name));
|
||||
m_ui.motorList->addItem(item);
|
||||
}
|
||||
}
|
||||
m_ui.motorList->setCurrentRow(0);
|
||||
m_ui.MotorScale->setDisabled(true);
|
||||
|
||||
refreshUi();
|
||||
}
|
||||
|
||||
Python2BindingWidget::~Python2BindingWidget() = default;
|
||||
|
||||
QIcon Python2BindingWidget::getIcon() const
|
||||
{
|
||||
return QIcon::fromTheme("artboard-2-line");
|
||||
}
|
||||
|
||||
void Python2BindingWidget::unbindKeyClicked(QTableWidget* tableWidget)
|
||||
{
|
||||
auto currentSelectionRow = tableWidget->currentRow();
|
||||
auto currentSelectionCol = tableWidget->currentColumn();
|
||||
|
||||
if (currentSelectionRow == -1)
|
||||
return;
|
||||
|
||||
for (int i = 0; i < tableWidget->rowCount(); i++)
|
||||
{
|
||||
auto selectedItem = tableWidget->item(i, 0);
|
||||
|
||||
if (!selectedItem->isSelected())
|
||||
continue;
|
||||
|
||||
uint uniqueId = selectedItem->data(Qt::UserRole).toUInt();
|
||||
|
||||
Python2QtInputManager::RemoveMappingByUniqueId(uniqueId);
|
||||
}
|
||||
|
||||
if (currentSelectionRow - 1 >= 0 && currentSelectionRow - 1 < tableWidget->rowCount())
|
||||
tableWidget->setCurrentCell(currentSelectionRow - 1, currentSelectionCol);
|
||||
else if (tableWidget->rowCount() > 0)
|
||||
tableWidget->setCurrentCell(0, currentSelectionCol);
|
||||
|
||||
saveAndRefresh();
|
||||
}
|
||||
|
||||
void Python2BindingWidget::onBindKeyMotorClicked()
|
||||
{
|
||||
auto full_key = m_ui.motorList->currentItem()->data(Qt::UserRole).toString();
|
||||
|
||||
QInputDialog dialog(QtUtils::GetRootWidget(this));
|
||||
|
||||
QStringList input_options(m_dialog->getVibrationMotors());
|
||||
if (input_options.isEmpty())
|
||||
{
|
||||
QMessageBox::critical(QtUtils::GetRootWidget(this), tr("Error"), tr("No devices with vibration motors were detected."));
|
||||
return;
|
||||
}
|
||||
|
||||
QInputDialog input_dialog(this);
|
||||
input_dialog.setWindowTitle(full_key);
|
||||
input_dialog.setLabelText(tr("Select vibration motor for %1.").arg(full_key));
|
||||
input_dialog.setInputMode(QInputDialog::TextInput);
|
||||
input_dialog.setOptions(QInputDialog::UseListViewForComboBoxItems);
|
||||
input_dialog.setComboBoxEditable(false);
|
||||
input_dialog.setComboBoxItems(std::move(input_options));
|
||||
input_dialog.setTextValue(QString::fromStdString("Test Value"));
|
||||
if (input_dialog.exec() == 0)
|
||||
return;
|
||||
|
||||
auto new_binding = input_dialog.textValue().toStdString();
|
||||
double motorScale = 0;
|
||||
if (QSlider* widget = findChild<QSlider*>(QStringLiteral("MotorScale")); widget)
|
||||
{
|
||||
motorScale = static_cast<float>(widget->value()) / static_cast<float>(widget->maximum());
|
||||
}
|
||||
|
||||
if (Python2QtInputManager::AddNewBinding(full_key.toStdString(), new_binding, 0, 0, motorScale)) {
|
||||
saveAndRefresh();
|
||||
}
|
||||
}
|
||||
|
||||
void Python2BindingWidget::refreshUi()
|
||||
{
|
||||
refreshInputBindingList();
|
||||
refreshInputAnalogBindingList();
|
||||
refreshOutputMotorBindingList();
|
||||
}
|
||||
|
||||
void Python2BindingWidget::saveAndRefresh()
|
||||
{
|
||||
saveMapping();
|
||||
refreshUi();
|
||||
}
|
||||
|
||||
std::string Python2BindingWidget::getKeybindDisplayName(std::string keybind)
|
||||
{
|
||||
for (auto system_entry : s_python2_system_info)
|
||||
{
|
||||
if (system_entry.bindings == nullptr)
|
||||
continue;
|
||||
|
||||
for (u32 i = 0; i < system_entry.num_bindings; i++)
|
||||
{
|
||||
if (std::string(system_entry.bindings[i].name) == keybind)
|
||||
return (tr("%1 - %2").arg(system_entry.name).arg(system_entry.bindings[i].display_name)).toStdString();
|
||||
}
|
||||
}
|
||||
|
||||
return keybind;
|
||||
}
|
||||
|
||||
void Python2BindingWidget::refreshInputBindingList()
|
||||
{
|
||||
m_ui.keybindList->clearContents();
|
||||
m_ui.keybindList->setSelectionBehavior(QAbstractItemView::SelectRows);
|
||||
m_ui.keybindList->setAlternatingRowColors(true);
|
||||
m_ui.keybindList->setShowGrid(false);
|
||||
m_ui.keybindList->verticalHeader()->hide();
|
||||
m_ui.keybindList->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch);
|
||||
m_ui.keybindList->horizontalHeader()->setSectionResizeMode(1, QHeaderView::ResizeToContents);
|
||||
m_ui.keybindList->horizontalHeader()->setStretchLastSection(true);
|
||||
m_ui.keybindList->setRowCount(0);
|
||||
|
||||
for (auto &entry : Python2QtInputManager::GetCurrentMappings())
|
||||
{
|
||||
if (entry.input_type != PAD::ControllerBindingType::Button)
|
||||
continue;
|
||||
|
||||
const int row = m_ui.keybindList->rowCount();
|
||||
m_ui.keybindList->insertRow(row);
|
||||
|
||||
QTableWidgetItem* item = new QTableWidgetItem();
|
||||
item->setText(QString::fromStdString(getKeybindDisplayName(entry.keybind)));
|
||||
item->setFlags(item->flags() & ~(Qt::ItemIsEditable));
|
||||
item->setData(Qt::UserRole, entry.uniqueId);
|
||||
m_ui.keybindList->setItem(row, 0, item);
|
||||
|
||||
QCheckBox* cb = new QCheckBox(m_ui.keybindList);
|
||||
cb->setChecked(entry.isOneshot);
|
||||
connect(cb, &QCheckBox::stateChanged, this, [this, &entry](int state) {
|
||||
entry.isOneshot = state == Qt::Checked;
|
||||
saveMapping();
|
||||
});
|
||||
|
||||
QWidget* cbw = new QWidget();
|
||||
QHBoxLayout* hbox = new QHBoxLayout(cbw);
|
||||
hbox->addWidget(cb);
|
||||
hbox->setAlignment(Qt::AlignCenter);
|
||||
hbox->setContentsMargins(0, 0, 0, 0);
|
||||
|
||||
m_ui.keybindList->setCellWidget(row, 1, cbw);
|
||||
|
||||
QTableWidgetItem* item2 = new QTableWidgetItem();
|
||||
item2->setText(QString::fromStdString(entry.inputKey));
|
||||
item2->setFlags(item->flags() & ~(Qt::ItemIsEditable));
|
||||
m_ui.keybindList->setItem(row, 2, item2);
|
||||
}
|
||||
}
|
||||
|
||||
void Python2BindingWidget::refreshInputAnalogBindingList()
|
||||
{
|
||||
m_ui.keybindListAnalogs->clearContents();
|
||||
m_ui.keybindListAnalogs->setSelectionBehavior(QAbstractItemView::SelectRows);
|
||||
m_ui.keybindListAnalogs->setAlternatingRowColors(true);
|
||||
m_ui.keybindListAnalogs->setShowGrid(false);
|
||||
m_ui.keybindListAnalogs->verticalHeader()->hide();
|
||||
m_ui.keybindListAnalogs->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch);
|
||||
m_ui.keybindListAnalogs->horizontalHeader()->setSectionResizeMode(1, QHeaderView::ResizeToContents);
|
||||
m_ui.keybindListAnalogs->horizontalHeader()->setSectionResizeMode(2, QHeaderView::ResizeToContents);
|
||||
m_ui.keybindListAnalogs->horizontalHeader()->setStretchLastSection(true);
|
||||
m_ui.keybindListAnalogs->setRowCount(0);
|
||||
|
||||
for (auto entry : Python2QtInputManager::GetCurrentMappings())
|
||||
{
|
||||
if (entry.input_type != PAD::ControllerBindingType::Axis && entry.input_type != PAD::ControllerBindingType::HalfAxis)
|
||||
continue;
|
||||
|
||||
const int row = m_ui.keybindListAnalogs->rowCount();
|
||||
m_ui.keybindListAnalogs->insertRow(row);
|
||||
|
||||
QTableWidgetItem* item = new QTableWidgetItem();
|
||||
item->setText(QString::fromStdString(getKeybindDisplayName(entry.keybind)));
|
||||
item->setFlags(item->flags() & ~(Qt::ItemIsEditable));
|
||||
item->setData(Qt::UserRole, entry.uniqueId);
|
||||
m_ui.keybindListAnalogs->setItem(row, 0, item);
|
||||
|
||||
QTableWidgetItem* item2 = new QTableWidgetItem();
|
||||
item2->setText(tr("%1%").arg(entry.analogDeadzone * 100));
|
||||
item2->setData(Qt::UserRole, entry.analogDeadzone);
|
||||
item2->setFlags(item->flags() & ~(Qt::ItemIsEditable));
|
||||
m_ui.keybindListAnalogs->setItem(row, 1, item2);
|
||||
|
||||
QTableWidgetItem* item3 = new QTableWidgetItem();
|
||||
item3->setText(tr("%1%").arg(entry.analogSensitivity * 100));
|
||||
item3->setData(Qt::UserRole, entry.analogSensitivity);
|
||||
item3->setFlags(item->flags() & ~(Qt::ItemIsEditable));
|
||||
m_ui.keybindListAnalogs->setItem(row, 2, item3);
|
||||
|
||||
QTableWidgetItem* item4 = new QTableWidgetItem();
|
||||
item4->setText(QString::fromStdString(entry.inputKey));
|
||||
item4->setFlags(item->flags() & ~(Qt::ItemIsEditable));
|
||||
m_ui.keybindListAnalogs->setItem(row, 3, item4);
|
||||
}
|
||||
}
|
||||
|
||||
void Python2BindingWidget::refreshOutputMotorBindingList()
|
||||
{
|
||||
m_ui.keybindListMotors->clearContents();
|
||||
m_ui.keybindListMotors->setSelectionBehavior(QAbstractItemView::SelectRows);
|
||||
m_ui.keybindListMotors->setAlternatingRowColors(true);
|
||||
m_ui.keybindListMotors->setShowGrid(false);
|
||||
m_ui.keybindListMotors->verticalHeader()->hide();
|
||||
m_ui.keybindListMotors->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch);
|
||||
m_ui.keybindListMotors->horizontalHeader()->setSectionResizeMode(1, QHeaderView::ResizeToContents);
|
||||
m_ui.keybindListMotors->horizontalHeader()->setStretchLastSection(true);
|
||||
m_ui.keybindListMotors->setRowCount(0);
|
||||
|
||||
for (auto entry : Python2QtInputManager::GetCurrentMappings())
|
||||
{
|
||||
if (entry.input_type != PAD::ControllerBindingType::Motor)
|
||||
continue;
|
||||
|
||||
const int row = m_ui.keybindListMotors->rowCount();
|
||||
m_ui.keybindListMotors->insertRow(row);
|
||||
|
||||
QTableWidgetItem* item = new QTableWidgetItem();
|
||||
item->setText(QString::fromStdString(getKeybindDisplayName(entry.keybind)));
|
||||
item->setFlags(item->flags() & ~(Qt::ItemIsEditable));
|
||||
item->setData(Qt::UserRole, entry.uniqueId);
|
||||
m_ui.keybindListMotors->setItem(row, 0, item);
|
||||
|
||||
QTableWidgetItem* item2 = new QTableWidgetItem();
|
||||
item2->setText(tr("%1%").arg(entry.motorScale * 100));
|
||||
item2->setData(Qt::UserRole, entry.motorScale);
|
||||
item2->setFlags(item->flags() & ~(Qt::ItemIsEditable));
|
||||
m_ui.keybindListMotors->setItem(row, 1, item2);
|
||||
|
||||
QTableWidgetItem* item3 = new QTableWidgetItem();
|
||||
item3->setText(QString::fromStdString(entry.inputKey));
|
||||
item3->setFlags(item->flags() & ~(Qt::ItemIsEditable));
|
||||
m_ui.keybindListMotors->setItem(row, 2, item3);
|
||||
}
|
||||
}
|
||||
|
||||
void Python2BindingWidget::onInputListenTimerTimeout()
|
||||
{
|
||||
m_input_listen_remaining_seconds--;
|
||||
if (m_input_listen_remaining_seconds == 0)
|
||||
{
|
||||
stopListeningForInput();
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_input_listen_analog)
|
||||
{
|
||||
m_ui.bindKeyAnalog->setText(tr("Press axis button... [%1]").arg(m_input_listen_remaining_seconds));
|
||||
}
|
||||
else
|
||||
{
|
||||
m_ui.bindKey->setText(tr("Press button... [%1]").arg(m_input_listen_remaining_seconds));
|
||||
}
|
||||
}
|
||||
|
||||
void Python2BindingWidget::startListeningForInput(u32 timeout_in_seconds, bool isAnalog)
|
||||
{
|
||||
if (isListeningForInput())
|
||||
stopListeningForInput();
|
||||
|
||||
m_new_bindings.clear();
|
||||
|
||||
m_input_listen_analog = isAnalog;
|
||||
m_input_listen_timer = new QTimer(this);
|
||||
m_input_listen_timer->setSingleShot(false);
|
||||
m_input_listen_timer->start(1000);
|
||||
m_input_listen_timer->connect(m_input_listen_timer, &QTimer::timeout, this, &Python2BindingWidget::onInputListenTimerTimeout);
|
||||
|
||||
m_input_listen_remaining_seconds = timeout_in_seconds;
|
||||
|
||||
if (m_input_listen_analog)
|
||||
{
|
||||
m_ui.bindKeyAnalog->setText(tr("Press axis button... [%1]").arg(m_input_listen_remaining_seconds));
|
||||
}
|
||||
else
|
||||
{
|
||||
m_ui.bindKey->setText(tr("Press button... [%1]").arg(m_input_listen_remaining_seconds));
|
||||
}
|
||||
|
||||
installEventFilter(this);
|
||||
grabKeyboard();
|
||||
grabMouse();
|
||||
setMouseTracking(true);
|
||||
hookInputManager();
|
||||
}
|
||||
|
||||
void Python2BindingWidget::stopListeningForInput()
|
||||
{
|
||||
delete m_input_listen_timer;
|
||||
m_input_listen_timer = nullptr;
|
||||
|
||||
std::vector<InputBindingKey>().swap(m_new_bindings);
|
||||
|
||||
unhookInputManager();
|
||||
setMouseTracking(false);
|
||||
releaseMouse();
|
||||
releaseKeyboard();
|
||||
removeEventFilter(this);
|
||||
|
||||
if (m_input_listen_analog)
|
||||
{
|
||||
m_ui.bindKeyAnalog->setText(tr("Bind"));
|
||||
}
|
||||
else
|
||||
{
|
||||
m_ui.bindKey->setText(tr("Bind"));
|
||||
}
|
||||
}
|
||||
|
||||
void Python2BindingWidget::inputManagerHookCallback(InputBindingKey key, float value)
|
||||
{
|
||||
const float abs_value = std::abs(value);
|
||||
|
||||
if (m_input_listen_analog && key.source_subtype != InputSubclass::PointerAxis && key.source_subtype != InputSubclass::ControllerAxis)
|
||||
return;
|
||||
|
||||
for (InputBindingKey other_key : m_new_bindings)
|
||||
{
|
||||
if (other_key.MaskDirection() == key.MaskDirection())
|
||||
{
|
||||
if (abs_value < 0.5f)
|
||||
{
|
||||
// if this key is in our new binding list, it's a "release", and we're done
|
||||
setNewInputBinding();
|
||||
stopListeningForInput();
|
||||
return;
|
||||
}
|
||||
|
||||
// otherwise, keep waiting
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// new binding, add it to the list, but wait for a decent distance first, and then wait for release
|
||||
if (abs_value >= 0.5f)
|
||||
{
|
||||
InputBindingKey key_to_add = key;
|
||||
m_new_bindings.push_back(key_to_add);
|
||||
}
|
||||
}
|
||||
|
||||
void Python2BindingWidget::hookInputManager()
|
||||
{
|
||||
InputManager::SetHook([this](InputBindingKey key, float value) {
|
||||
QMetaObject::invokeMethod(this, "inputManagerHookCallback", Qt::QueuedConnection, Q_ARG(InputBindingKey, key),
|
||||
Q_ARG(float, value));
|
||||
return InputInterceptHook::CallbackResult::StopProcessingEvent;
|
||||
});
|
||||
}
|
||||
|
||||
void Python2BindingWidget::unhookInputManager()
|
||||
{
|
||||
InputManager::RemoveHook();
|
||||
}
|
||||
|
||||
bool Python2BindingWidget::eventFilter(QObject* watched, QEvent* event)
|
||||
{
|
||||
if (m_input_listen_analog)
|
||||
return false;
|
||||
|
||||
const QEvent::Type event_type = event->type();
|
||||
|
||||
// if the key is being released, set the input
|
||||
if (event_type == QEvent::KeyRelease || event_type == QEvent::MouseButtonRelease)
|
||||
{
|
||||
setNewInputBinding();
|
||||
stopListeningForInput();
|
||||
return true;
|
||||
}
|
||||
else if (event_type == QEvent::KeyPress)
|
||||
{
|
||||
const QKeyEvent* key_event = static_cast<const QKeyEvent*>(event);
|
||||
m_new_bindings.push_back(InputManager::MakeHostKeyboardKey(QtUtils::KeyEventToCode(key_event)));
|
||||
return true;
|
||||
}
|
||||
else if (event_type == QEvent::MouseButtonPress || event_type == QEvent::MouseButtonDblClick)
|
||||
{
|
||||
// double clicks get triggered if we click bind, then click again quickly.
|
||||
unsigned long button_index;
|
||||
if (_BitScanForward(&button_index, static_cast<u32>(static_cast<const QMouseEvent*>(event)->button())))
|
||||
m_new_bindings.push_back(InputManager::MakePointerButtonKey(0, button_index));
|
||||
return true;
|
||||
}
|
||||
else if (event_type == QEvent::Wheel)
|
||||
{
|
||||
const QPoint delta_angle(static_cast<QWheelEvent*>(event)->angleDelta());
|
||||
const float dx = std::clamp(static_cast<float>(delta_angle.x()) / QtUtils::MOUSE_WHEEL_DELTA, -1.0f, 1.0f);
|
||||
if (dx != 0.0f)
|
||||
{
|
||||
InputBindingKey key(InputManager::MakePointerAxisKey(0, InputPointerAxis::WheelX));
|
||||
key.negative = (dx < 0.0f);
|
||||
m_new_bindings.push_back(key);
|
||||
}
|
||||
|
||||
const float dy = std::clamp(static_cast<float>(delta_angle.y()) / QtUtils::MOUSE_WHEEL_DELTA, -1.0f, 1.0f);
|
||||
if (dy != 0.0f)
|
||||
{
|
||||
InputBindingKey key(InputManager::MakePointerAxisKey(0, InputPointerAxis::WheelY));
|
||||
key.negative = (dy < 0.0f);
|
||||
m_new_bindings.push_back(key);
|
||||
}
|
||||
|
||||
if (dx != 0.0f || dy != 0.0f)
|
||||
{
|
||||
setNewInputBinding();
|
||||
stopListeningForInput();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void Python2BindingWidget::setNewInputBinding()
|
||||
{
|
||||
if (m_new_bindings.empty())
|
||||
return;
|
||||
|
||||
const std::string new_binding(InputManager::ConvertInputBindingKeysToString(m_new_bindings.data(), m_new_bindings.size()));
|
||||
|
||||
std::string full_key;
|
||||
float analogDeadzone = 0;
|
||||
float analogSensitivity = 0;
|
||||
|
||||
if (m_input_listen_analog)
|
||||
{
|
||||
full_key = m_ui.inputListAnalogs->currentItem()->data(Qt::UserRole).toString().toStdString();
|
||||
|
||||
if (QSlider* widget = findChild<QSlider*>(QStringLiteral("Deadzone")); widget)
|
||||
{
|
||||
analogDeadzone = static_cast<float>(widget->value()) / static_cast<float>(widget->maximum());
|
||||
}
|
||||
|
||||
if (QSlider* widget = findChild<QSlider*>(QStringLiteral("AxisScale")); widget)
|
||||
{
|
||||
analogSensitivity = static_cast<float>(widget->value()) / static_cast<float>(widget->maximum());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
full_key = m_ui.inputList->currentItem()->data(Qt::UserRole).toString().toStdString();
|
||||
}
|
||||
|
||||
if (Python2QtInputManager::AddNewBinding(full_key, new_binding, analogDeadzone, analogSensitivity, 0)) {
|
||||
saveAndRefresh();
|
||||
}
|
||||
}
|
||||
|
||||
void Python2BindingWidget::saveMapping()
|
||||
{
|
||||
auto lock = Host::GetSettingsLock();
|
||||
SettingsInterface* si = Host::Internal::GetBaseSettingsLayer();
|
||||
const std::string section = "Python2";
|
||||
|
||||
// Clear all keybinds in Python2 section
|
||||
si->ClearSection(section.c_str());
|
||||
|
||||
// Recreate Python2 section
|
||||
for (auto entry : Python2QtInputManager::GetCurrentMappings())
|
||||
{
|
||||
if (entry.input_type == PAD::ControllerBindingType::Button)
|
||||
{
|
||||
si->AddToStringList(
|
||||
section.c_str(),
|
||||
entry.keybind.c_str(),
|
||||
StringUtil::StdStringFromFormat("%s|%d", entry.inputKey.c_str(), entry.isOneshot).c_str()
|
||||
);
|
||||
}
|
||||
else if (entry.input_type == PAD::ControllerBindingType::Axis || entry.input_type == PAD::ControllerBindingType::HalfAxis)
|
||||
{
|
||||
si->AddToStringList(
|
||||
section.c_str(),
|
||||
entry.keybind.c_str(),
|
||||
StringUtil::StdStringFromFormat("%s|%lf|%lf", entry.inputKey.c_str(), entry.analogDeadzone, entry.analogSensitivity).c_str()
|
||||
);
|
||||
}
|
||||
else if (entry.input_type == PAD::ControllerBindingType::Motor)
|
||||
{
|
||||
si->AddToStringList(
|
||||
section.c_str(),
|
||||
entry.keybind.c_str(),
|
||||
StringUtil::StdStringFromFormat("%s|%lf", entry.inputKey.c_str(), entry.motorScale).c_str()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
QtHost::QueueSettingsSave();
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2022 PCSX2 Dev Team, 987123879113
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QtWidgets/QWidget>
|
||||
|
||||
#include "ui_Python2BindingWidget.h"
|
||||
|
||||
#include "pcsx2/Frontend/InputManager.h"
|
||||
|
||||
class InputBindingWidget;
|
||||
class ControllerSettingsDialog;
|
||||
|
||||
struct Python2KeyMapping;
|
||||
|
||||
class Python2BindingWidget final : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
Python2BindingWidget(QWidget* parent, ControllerSettingsDialog* dialog);
|
||||
~Python2BindingWidget();
|
||||
|
||||
QIcon getIcon() const;
|
||||
|
||||
__fi ControllerSettingsDialog* getDialog() const { return m_dialog; }
|
||||
|
||||
private Q_SLOTS:
|
||||
void unbindKeyClicked(QTableWidget *tableWidget);
|
||||
|
||||
void onBindKeyMotorClicked();
|
||||
|
||||
void onInputListenTimerTimeout();
|
||||
void inputManagerHookCallback(InputBindingKey key, float value);
|
||||
|
||||
protected:
|
||||
enum : u32
|
||||
{
|
||||
TIMEOUT_FOR_SINGLE_BINDING = 5
|
||||
};
|
||||
|
||||
void refreshUi();
|
||||
void saveAndRefresh();
|
||||
|
||||
void refreshInputBindingList();
|
||||
void refreshInputAnalogBindingList();
|
||||
void refreshOutputMotorBindingList();
|
||||
|
||||
virtual bool eventFilter(QObject* watched, QEvent* event) override;
|
||||
|
||||
virtual void startListeningForInput(u32 timeout_in_seconds, bool isAnalog);
|
||||
virtual void stopListeningForInput();
|
||||
|
||||
bool isListeningForInput() const { return m_input_listen_timer != nullptr; }
|
||||
void setNewInputBinding();
|
||||
|
||||
void hookInputManager();
|
||||
void unhookInputManager();
|
||||
|
||||
void saveMapping();
|
||||
|
||||
std::string getKeybindDisplayName(std::string keybind);
|
||||
|
||||
Ui::Python2BindingWidget m_ui;
|
||||
|
||||
ControllerSettingsDialog* m_dialog;
|
||||
|
||||
std::vector<std::string> m_bindings;
|
||||
std::vector<InputBindingKey> m_new_bindings;
|
||||
QTimer* m_input_listen_timer = nullptr;
|
||||
u32 m_input_listen_remaining_seconds = 0;
|
||||
bool m_input_listen_analog = false;
|
||||
};
|
|
@ -0,0 +1,346 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>Python2BindingWidget</class>
|
||||
<widget class="QWidget" name="Python2BindingWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>833</width>
|
||||
<height>560</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout" stretch="0">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
|
||||
<item>
|
||||
<widget class="QTabWidget" name="inputsTabWidget">
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="documentMode">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<widget class="QWidget" name="tabInputs">
|
||||
<attribute name="title">
|
||||
<string>Inputs</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout2">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox3">
|
||||
<property name="title">
|
||||
<string>Game Type Filter</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout2">
|
||||
<item>
|
||||
<widget class="QComboBox" name="gameTypeFilter" />
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item row="0" column="0" rowspan="6">
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>Available Inputs</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0" colspan="2">
|
||||
<widget class="QListWidget" name="inputList" />
|
||||
</item>
|
||||
<item row="1" column="0" colspan="2">
|
||||
<widget class="QPushButton" name="bindKey">
|
||||
<property name="text">
|
||||
<string>Bind</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="6" rowspan="6">
|
||||
<widget class="QGroupBox" name="groupBox2">
|
||||
<property name="title">
|
||||
<string>Existing Keybinds</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout2">
|
||||
<item row="0" column="0" colspan="2">
|
||||
<widget class="QTableWidget" name="keybindList">
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Keybind</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Oneshot</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Device</string>
|
||||
</property>
|
||||
</column>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="2">
|
||||
<widget class="QPushButton" name="unbindKey">
|
||||
<property name="text">
|
||||
<string>Unbind</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
|
||||
<widget class="QWidget" name="tabAnalogInputs">
|
||||
<attribute name="title">
|
||||
<string>Analog Inputs</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout4">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout3">
|
||||
<item row="0" column="0" rowspan="6">
|
||||
<widget class="QGroupBox" name="groupBox4">
|
||||
<property name="title">
|
||||
<string>Available Analog Inputs</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout3">
|
||||
<item row="0" column="0" colspan="2">
|
||||
<widget class="QListWidget" name="inputListAnalogs" />
|
||||
</item>
|
||||
<item row="1" column="0" colspan="2">
|
||||
<widget class="QPushButton" name="bindKeyAnalog">
|
||||
<property name="text">
|
||||
<string>Bind</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="6" rowspan="6">
|
||||
<widget class="QGroupBox" name="groupBox5">
|
||||
<property name="title">
|
||||
<string>Existing Keybinds</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout4">
|
||||
<item row="0" column="0" colspan="2">
|
||||
<widget class="QTableWidget" name="keybindListAnalogs">
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Keybind</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Deadzone</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Sensitivity</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Device</string>
|
||||
</property>
|
||||
</column>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="2">
|
||||
<widget class="QPushButton" name="unbindKeyAnalog">
|
||||
<property name="text">
|
||||
<string>Unbind</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout5">
|
||||
<item row="0" column="0" colspan="2">
|
||||
<widget class="QGroupBox" name="groupBox_33">
|
||||
<property name="title">
|
||||
<string>Analog Deadzone</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item>
|
||||
<widget class="QSlider" name="Deadzone">
|
||||
<property name="maximum">
|
||||
<number>100</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="DeadzoneLabel">
|
||||
<property name="text">
|
||||
<string>0%</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
|
||||
<item row="0" column="2" colspan="2">
|
||||
<widget class="QGroupBox" name="groupBox_30">
|
||||
<property name="title">
|
||||
<string>Analog Sensitivity</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QSlider" name="AxisScale">
|
||||
<property name="maximum">
|
||||
<number>200</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="AxisScaleLabel">
|
||||
<property name="text">
|
||||
<string>100%</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
|
||||
<widget class="QWidget" name="tabMotors">
|
||||
<attribute name="title">
|
||||
<string>Motors</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout3">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout4">
|
||||
<item row="0" column="0" rowspan="6">
|
||||
<widget class="QGroupBox" name="groupBox6">
|
||||
<property name="title">
|
||||
<string>Available Motor Outputs</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout5">
|
||||
<item row="0" column="0" colspan="2">
|
||||
<widget class="QListWidget" name="motorList" />
|
||||
</item>
|
||||
<item row="1" column="0" colspan="2">
|
||||
<widget class="QPushButton" name="bindKeyMotor">
|
||||
<property name="text">
|
||||
<string>Bind</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="6" rowspan="6">
|
||||
<widget class="QGroupBox" name="groupBox7">
|
||||
<property name="title">
|
||||
<string>Existing Keybinds</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout6">
|
||||
<item row="0" column="0" colspan="2">
|
||||
<widget class="QTableWidget" name="keybindListMotors">
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Keybind</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Scale</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Device</string>
|
||||
</property>
|
||||
</column>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="2">
|
||||
<widget class="QPushButton" name="unbindKeyMotor">
|
||||
<property name="text">
|
||||
<string>Unbind</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_31">
|
||||
<property name="title">
|
||||
<string>Motor Scale</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||
<item>
|
||||
<widget class="QSlider" name="MotorScale">
|
||||
<property name="maximum">
|
||||
<number>100</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="MotorScaleLabel">
|
||||
<property name="text">
|
||||
<string>100%</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources>
|
||||
<include location="../resources/resources.qrc" />
|
||||
</resources>
|
||||
<connections />
|
||||
</ui>
|
|
@ -0,0 +1,192 @@
|
|||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2022 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "PrecompiledHeader.h"
|
||||
|
||||
#include "common/StringUtil.h"
|
||||
|
||||
#include "Frontend/GameList.h"
|
||||
#include "PAD/Host/PAD.h"
|
||||
|
||||
#include "Python2SettingsWidget.h"
|
||||
#include "SettingWidgetBinder.h"
|
||||
#include "SettingsDialog.h"
|
||||
#include "QtHost.h"
|
||||
|
||||
Python2SettingsWidget::Python2SettingsWidget(const GameList::Entry* entry, SettingsDialog* dialog, QWidget* parent)
|
||||
: m_dialog(dialog)
|
||||
{
|
||||
SettingsInterface* sif = dialog->getSettingsInterface();
|
||||
|
||||
m_ui.setupUi(this);
|
||||
|
||||
const int gameTypeId = m_dialog->getIntValue("Python2/Game", "GameType", 0).value();
|
||||
connect(m_ui.gameType, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &Python2SettingsWidget::onGameTypeChanged);
|
||||
m_ui.gameType->setCurrentIndex(gameTypeId);
|
||||
|
||||
SettingWidgetBinder::BindWidgetToStringSetting(sif, m_ui.hddIdPath, "DEV9/Hdd", "HddIdFile", "HDD_ID.bin");
|
||||
m_ui.hddIdPath->setEnabled(true);
|
||||
connect(m_ui.hddIdBrowse, &QPushButton::clicked, this, &Python2SettingsWidget::onHddIdBrowseClicked);
|
||||
|
||||
SettingWidgetBinder::BindWidgetToStringSetting(sif, m_ui.ilinkIdPath, "Python2/System", "IlinkIdFile", "ILINK_ID.bin");
|
||||
m_ui.ilinkIdPath->setEnabled(true);
|
||||
connect(m_ui.ilinkIdBrowse, &QPushButton::clicked, this, &Python2SettingsWidget::onIlinkIdBrowseClicked);
|
||||
|
||||
SettingWidgetBinder::BindWidgetToStringSetting(sif, m_ui.dongleBlackPath, "Python2/Game", "DongleBlackFile", "dongle_black.bin");
|
||||
m_ui.dongleBlackPath->setEnabled(true);
|
||||
connect(m_ui.dongleBlackBrowse, &QPushButton::clicked, this, &Python2SettingsWidget::onDongleBlackBrowseClicked);
|
||||
|
||||
SettingWidgetBinder::BindWidgetToStringSetting(sif, m_ui.dongleWhitePath, "Python2/Game", "DongleWhiteFile", "dongle_white.bin");
|
||||
m_ui.dongleWhitePath->setEnabled(true);
|
||||
connect(m_ui.dongleWhiteBrowse, &QPushButton::clicked, this, &Python2SettingsWidget::onDongleWhiteBrowseClicked);
|
||||
|
||||
SettingWidgetBinder::BindWidgetToStringSetting(sif, m_ui.player1CardPath, "Python2/Game", "Player1CardFile", "card1.txt");
|
||||
m_ui.player1CardPath->setEnabled(true);
|
||||
connect(m_ui.player1CardBrowse, &QPushButton::clicked, this, &Python2SettingsWidget::onPlayer1CardBrowseClicked);
|
||||
|
||||
SettingWidgetBinder::BindWidgetToStringSetting(sif, m_ui.player2CardPath, "Python2/Game", "Player2CardFile", "card2.txt");
|
||||
m_ui.player2CardPath->setEnabled(true);
|
||||
connect(m_ui.player2CardBrowse, &QPushButton::clicked, this, &Python2SettingsWidget::onPlayer2CardBrowseClicked);
|
||||
|
||||
// Nullable bools are weird so don't use BindWidgetToBoolSetting
|
||||
const bool dipsw1Value = m_dialog->getBoolValue("Python2/Game", "DIPSW1", false).value();
|
||||
connect(m_ui.dipsw1, QOverload<int>::of(&QCheckBox::stateChanged), this, [&](int state) { m_dialog->setBoolSettingValue("Python2/Game", "DIPSW1", state); });
|
||||
m_ui.dipsw1->setCheckState(dipsw1Value ? Qt::CheckState::Checked : Qt::CheckState::Unchecked);
|
||||
|
||||
const bool dipsw2Value = m_dialog->getBoolValue("Python2/Game", "DIPSW2", false).value();
|
||||
connect(m_ui.dipsw2, QOverload<int>::of(&QCheckBox::stateChanged), this, [&](int state) { m_dialog->setBoolSettingValue("Python2/Game", "DIPSW2", state); });
|
||||
m_ui.dipsw2->setCheckState(dipsw2Value ? Qt::CheckState::Checked : Qt::CheckState::Unchecked);
|
||||
|
||||
const bool dipsw3Value = m_dialog->getBoolValue("Python2/Game", "DIPSW3", false).value();
|
||||
connect(m_ui.dipsw3, QOverload<int>::of(&QCheckBox::stateChanged), this, [&](int state) { m_dialog->setBoolSettingValue("Python2/Game", "DIPSW3", state); });
|
||||
m_ui.dipsw3->setCheckState(dipsw3Value ? Qt::CheckState::Checked : Qt::CheckState::Unchecked);
|
||||
|
||||
const bool dipsw4Value = m_dialog->getBoolValue("Python2/Game", "DIPSW4", false).value();
|
||||
connect(m_ui.dipsw4, QOverload<int>::of(&QCheckBox::stateChanged), this, [&](int state) { m_dialog->setBoolSettingValue("Python2/Game", "DIPSW4", state); });
|
||||
m_ui.dipsw4->setCheckState(dipsw4Value ? Qt::CheckState::Checked : Qt::CheckState::Unchecked);
|
||||
|
||||
const bool force31kHzValue = m_dialog->getBoolValue("Python2/Game", "Force31kHz", false).value();
|
||||
connect(m_ui.force31khz, QOverload<int>::of(&QCheckBox::stateChanged), this, [&](int state) { m_dialog->setBoolSettingValue("Python2/Game", "Force31kHz", state); });
|
||||
m_ui.force31khz->setCheckState(force31kHzValue ? Qt::CheckState::Checked : Qt::CheckState::Unchecked);
|
||||
|
||||
SettingWidgetBinder::BindWidgetToStringSetting(sif, m_ui.patchFilePath, "Python2/Game", "PatchFile", "patches.pnach");
|
||||
m_ui.patchFilePath->setEnabled(true);
|
||||
connect(m_ui.patchFileBrowse, &QPushButton::clicked, this, &Python2SettingsWidget::onPatchFileBrowseClicked);
|
||||
}
|
||||
|
||||
void Python2SettingsWidget::onGameTypeChanged(int index)
|
||||
{
|
||||
m_dialog->setIntSettingValue("Python2/Game", "GameType", index);
|
||||
}
|
||||
|
||||
void Python2SettingsWidget::onHddIdBrowseClicked()
|
||||
{
|
||||
QString path =
|
||||
QDir::toNativeSeparators(QFileDialog::getOpenFileName(QtUtils::GetRootWidget(this), tr("HDD ID File"),
|
||||
!m_ui.hddIdPath->text().isEmpty() ? m_ui.hddIdPath->text() : "HDD_ID.bin", tr("BIN (*.bin)"), nullptr,
|
||||
QFileDialog::DontConfirmOverwrite));
|
||||
|
||||
if (path.isEmpty())
|
||||
return;
|
||||
|
||||
m_ui.hddIdPath->setText(path);
|
||||
m_ui.hddIdPath->editingFinished();
|
||||
}
|
||||
|
||||
void Python2SettingsWidget::onIlinkIdBrowseClicked()
|
||||
{
|
||||
QString path =
|
||||
QDir::toNativeSeparators(QFileDialog::getOpenFileName(QtUtils::GetRootWidget(this), tr("ILINK ID File"),
|
||||
!m_ui.ilinkIdPath->text().isEmpty() ? m_ui.ilinkIdPath->text() : "ILINK_ID.bin", tr("BIN (*.bin)"), nullptr,
|
||||
QFileDialog::DontConfirmOverwrite));
|
||||
|
||||
if (path.isEmpty())
|
||||
return;
|
||||
|
||||
m_ui.ilinkIdPath->setText(path);
|
||||
m_ui.ilinkIdPath->editingFinished();
|
||||
}
|
||||
|
||||
void Python2SettingsWidget::onDongleBlackBrowseClicked()
|
||||
{
|
||||
QString path =
|
||||
QDir::toNativeSeparators(QFileDialog::getOpenFileName(QtUtils::GetRootWidget(this), tr("Dongle File"),
|
||||
!m_ui.dongleBlackPath->text().isEmpty() ? m_ui.dongleBlackPath->text() : "dongle_black.bin", tr("BIN (*.bin)"), nullptr,
|
||||
QFileDialog::DontConfirmOverwrite));
|
||||
|
||||
if (path.isEmpty())
|
||||
return;
|
||||
|
||||
m_ui.dongleBlackPath->setText(path);
|
||||
m_ui.dongleBlackPath->editingFinished();
|
||||
}
|
||||
|
||||
void Python2SettingsWidget::onDongleWhiteBrowseClicked()
|
||||
{
|
||||
QString path =
|
||||
QDir::toNativeSeparators(QFileDialog::getOpenFileName(QtUtils::GetRootWidget(this), tr("Dongle File"),
|
||||
!m_ui.dongleWhitePath->text().isEmpty() ? m_ui.dongleWhitePath->text() : "dongle_white.bin", tr("BIN (*.bin)"), nullptr,
|
||||
QFileDialog::DontConfirmOverwrite));
|
||||
|
||||
if (path.isEmpty())
|
||||
return;
|
||||
|
||||
m_ui.dongleWhitePath->setText(path);
|
||||
m_ui.dongleWhitePath->editingFinished();
|
||||
}
|
||||
|
||||
void Python2SettingsWidget::onPatchFileBrowseClicked()
|
||||
{
|
||||
QString path =
|
||||
QDir::toNativeSeparators(QFileDialog::getOpenFileName(QtUtils::GetRootWidget(this), tr("Patch File"),
|
||||
!m_ui.patchFilePath->text().isEmpty() ? m_ui.patchFilePath->text() : "patches.pnach", tr("Patch (*.pnach)"), nullptr,
|
||||
QFileDialog::DontConfirmOverwrite));
|
||||
|
||||
if (path.isEmpty())
|
||||
return;
|
||||
|
||||
m_ui.patchFilePath->setText(path);
|
||||
m_ui.patchFilePath->editingFinished();
|
||||
}
|
||||
|
||||
void Python2SettingsWidget::onPlayer1CardBrowseClicked()
|
||||
{
|
||||
QString path =
|
||||
QDir::toNativeSeparators(QFileDialog::getOpenFileName(QtUtils::GetRootWidget(this), tr("Card File"),
|
||||
!m_ui.player1CardPath->text().isEmpty() ? m_ui.player1CardPath->text() : "card1.txt", nullptr, nullptr,
|
||||
QFileDialog::DontConfirmOverwrite));
|
||||
|
||||
if (path.isEmpty())
|
||||
return;
|
||||
|
||||
m_ui.player1CardPath->setText(path);
|
||||
m_ui.player1CardPath->editingFinished();
|
||||
}
|
||||
|
||||
void Python2SettingsWidget::onPlayer2CardBrowseClicked()
|
||||
{
|
||||
QString path =
|
||||
QDir::toNativeSeparators(QFileDialog::getOpenFileName(QtUtils::GetRootWidget(this), tr("Card File"),
|
||||
!m_ui.player2CardPath->text().isEmpty() ? m_ui.player2CardPath->text() : "card2.txt", nullptr, nullptr,
|
||||
QFileDialog::DontConfirmOverwrite));
|
||||
|
||||
if (path.isEmpty())
|
||||
return;
|
||||
|
||||
m_ui.player2CardPath->setText(path);
|
||||
m_ui.player2CardPath->editingFinished();
|
||||
}
|
||||
|
||||
Python2SettingsWidget::~Python2SettingsWidget() = default;
|
|
@ -0,0 +1,50 @@
|
|||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2022 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QtWidgets/QWidget>
|
||||
|
||||
#include "ui_Python2SettingsWidget.h"
|
||||
|
||||
namespace GameList
|
||||
{
|
||||
struct Entry;
|
||||
}
|
||||
|
||||
class SettingsDialog;
|
||||
|
||||
class Python2SettingsWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private Q_SLOTS:
|
||||
void onGameTypeChanged(int index);
|
||||
void onHddIdBrowseClicked();
|
||||
void onIlinkIdBrowseClicked();
|
||||
void onDongleBlackBrowseClicked();
|
||||
void onDongleWhiteBrowseClicked();
|
||||
void onPatchFileBrowseClicked();
|
||||
void onPlayer1CardBrowseClicked();
|
||||
void onPlayer2CardBrowseClicked();
|
||||
|
||||
public:
|
||||
Python2SettingsWidget(const GameList::Entry* entry, SettingsDialog* dialog, QWidget* parent);
|
||||
~Python2SettingsWidget();
|
||||
|
||||
private:
|
||||
Ui::Python2SettingsWidget m_ui;
|
||||
SettingsDialog* m_dialog;
|
||||
};
|
|
@ -0,0 +1,281 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>Python2SettingsWidget</class>
|
||||
<widget class="QWidget" name="Python2SettingsWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>692</width>
|
||||
<height>562</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<property name="fieldGrowthPolicy">
|
||||
<enum>QFormLayout::ExpandingFieldsGrow</enum>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_1">
|
||||
<property name="text">
|
||||
<string>Game Type:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="gameType">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="editable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Drummania</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Guitar Freaks</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Dance Dance Revolution</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Toy's March</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Thrill Drive 3</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Dance 86.4</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="3">
|
||||
<layout class="QGridLayout" name="gridLayout_3_1">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>HDD ID Path:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="hddIdPath" />
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QPushButton" name="hddIdBrowse">
|
||||
<property name="text">
|
||||
<string>Browse</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="3">
|
||||
<layout class="QGridLayout" name="gridLayout_3_2">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>ILINK ID Path:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="ilinkIdPath" />
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QPushButton" name="ilinkIdBrowse">
|
||||
<property name="text">
|
||||
<string>Browse</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="3" column="0" colspan="3">
|
||||
<layout class="QGridLayout" name="gridLayout_3_3">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Black Dongle Path:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="dongleBlackPath" />
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QPushButton" name="dongleBlackBrowse">
|
||||
<property name="text">
|
||||
<string>Browse</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="4" column="0" colspan="3">
|
||||
<layout class="QGridLayout" name="gridLayout_3_4">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>White Dongle Path:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="dongleWhitePath" />
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QPushButton" name="dongleWhiteBrowse">
|
||||
<property name="text">
|
||||
<string>Browse</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>Dipswitches:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1" colspan="4">
|
||||
<layout class="QGridLayout" name="gridLayout_4">
|
||||
<item row="0" column="0">
|
||||
<widget class="QCheckBox" name="dipsw1">
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QCheckBox" name="dipsw2">
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QCheckBox" name="dipsw3">
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="3">
|
||||
<widget class="QCheckBox" name="dipsw4">
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="text">
|
||||
<string>Force 31kHz:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="QCheckBox" name="force31khz" />
|
||||
</item>
|
||||
<item row="7" column="0" colspan="3">
|
||||
<layout class="QGridLayout" name="gridLayout_3_5">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_8">
|
||||
<property name="text">
|
||||
<string>Patch File:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="patchFilePath" />
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QPushButton" name="patchFileBrowse">
|
||||
<property name="text">
|
||||
<string>Browse</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="8" column="0" colspan="3">
|
||||
<layout class="QGridLayout" name="gridLayout_3_6">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_9">
|
||||
<property name="text">
|
||||
<string>P1 Card Path:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="player1CardPath" />
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QPushButton" name="player1CardBrowse">
|
||||
<property name="text">
|
||||
<string>Browse</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="9" column="0" colspan="3">
|
||||
<layout class="QGridLayout" name="gridLayout_3_7">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_10">
|
||||
<property name="text">
|
||||
<string>P2 Card Path:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="player2CardPath" />
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QPushButton" name="player2CardBrowse">
|
||||
<property name="text">
|
||||
<string>Browse</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources>
|
||||
<include location="../resources/resources.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
|
@ -43,6 +43,7 @@
|
|||
#include "InterfaceSettingsWidget.h"
|
||||
#include "MemoryCardSettingsWidget.h"
|
||||
#include "SystemSettingsWidget.h"
|
||||
#include "Python2SettingsWidget.h"
|
||||
|
||||
#include <QtWidgets/QMessageBox>
|
||||
#include <QtWidgets/QTextEdit>
|
||||
|
@ -128,7 +129,7 @@ void SettingsDialog::setupUi(const GameList::Entry* game)
|
|||
addWidget(m_memory_card_settings = new MemoryCardSettingsWidget(this, m_ui.settingsContainer), tr("Memory Cards"),
|
||||
QStringLiteral("sd-card-line"), tr("<strong>Memory Card Settings</strong><hr>Create and configure Memory Cards here.<br><br>Mouse over an option for additional information."));
|
||||
}
|
||||
|
||||
|
||||
addWidget(m_dev9_settings = new DEV9SettingsWidget(this, m_ui.settingsContainer), tr("Network & HDD"), QStringLiteral("dashboard-line"),
|
||||
tr("<strong>Network & HDD Settings</strong><hr>These options control the network connectivity and internal HDD storage of the console.<br><br>"
|
||||
"Mouse over an option for additional information."));
|
||||
|
@ -139,6 +140,11 @@ void SettingsDialog::setupUi(const GameList::Entry* game)
|
|||
tr("<strong>Folder Settings</strong><hr>These options control where PCSX2 will save runtime data files."));
|
||||
}
|
||||
|
||||
if (isPerGameSettings() && game->type == GameList::EntryType::Python2) {
|
||||
addWidget(m_python2_settings = new Python2SettingsWidget(game, this, m_ui.settingsContainer), tr("Python 2"), QStringLiteral("dashboard-line"),
|
||||
tr("<strong>Python 2 Settings</strong><hr>These options control the settings specific to Python 2 games."));
|
||||
}
|
||||
|
||||
m_ui.settingsCategory->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
|
||||
m_ui.settingsCategory->setCurrentRow(0);
|
||||
m_ui.settingsContainer->setCurrentIndex(0);
|
||||
|
|
|
@ -41,6 +41,7 @@ class AudioSettingsWidget;
|
|||
class MemoryCardSettingsWidget;
|
||||
class FolderSettingsWidget;
|
||||
class DEV9SettingsWidget;
|
||||
class Python2SettingsWidget;
|
||||
|
||||
class SettingsDialog final : public QDialog
|
||||
{
|
||||
|
@ -68,6 +69,7 @@ public:
|
|||
__fi MemoryCardSettingsWidget* getMemoryCardSettingsWidget() const { return m_memory_card_settings; }
|
||||
__fi FolderSettingsWidget* getFolderSettingsWidget() const { return m_folder_settings; }
|
||||
__fi DEV9SettingsWidget* getDEV9SettingsWidget() const { return m_dev9_settings; }
|
||||
__fi Python2SettingsWidget* getPython2SettingsWidget() const { return m_python2_settings; }
|
||||
|
||||
void registerWidgetHelp(QObject* object, QString title, QString recommended_value, QString text);
|
||||
bool eventFilter(QObject* object, QEvent* event) override;
|
||||
|
@ -126,6 +128,7 @@ private:
|
|||
MemoryCardSettingsWidget* m_memory_card_settings = nullptr;
|
||||
FolderSettingsWidget* m_folder_settings = nullptr;
|
||||
DEV9SettingsWidget* m_dev9_settings = nullptr;
|
||||
Python2SettingsWidget* m_python2_settings = nullptr;
|
||||
|
||||
std::array<QString, MAX_SETTINGS_WIDGETS> m_category_help_text;
|
||||
|
||||
|
|
|
@ -129,6 +129,9 @@
|
|||
<ProjectReference Include="..\3rdparty\lzma\lzma.vcxproj">
|
||||
<Project>{a4323327-3f2b-4271-83d9-7f9a3c66b6b2}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\3rdparty\libusb\libusb.vcxproj">
|
||||
<Project>{349ee8f9-7d25-4909-aaf5-ff3fade72187}</Project>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Manifest Include="..\pcsx2\windows\PCSX2.manifest" />
|
||||
|
@ -160,6 +163,8 @@
|
|||
<ClCompile Include="Settings\DEV9UiCommon.cpp" />
|
||||
<ClCompile Include="Settings\HddCreateQt.cpp" />
|
||||
<ClCompile Include="Settings\GameSummaryWidget.cpp" />
|
||||
<ClCompile Include="Settings\Python2BindingWidget.cpp" />
|
||||
<ClCompile Include="Settings\Python2SettingsWidget.cpp" />
|
||||
<ClCompile Include="GameList\GameListModel.cpp" />
|
||||
<ClCompile Include="GameList\GameListRefreshThread.cpp" />
|
||||
<ClCompile Include="GameList\GameListWidget.cpp" />
|
||||
|
@ -199,6 +204,8 @@
|
|||
<ClInclude Include="Settings\HddCreateQt.h" />
|
||||
<QtMoc Include="Settings\GameSummaryWidget.h" />
|
||||
<QtMoc Include="Settings\CreateMemoryCardDialog.h" />
|
||||
<QtMoc Include="Settings\Python2BindingWidget.h" />
|
||||
<QtMoc Include="Settings\Python2SettingsWidget.h" />
|
||||
<QtMoc Include="GameList\GameListModel.h" />
|
||||
<QtMoc Include="GameList\GameListWidget.h" />
|
||||
<QtMoc Include="GameList\GameListRefreshThread.h" />
|
||||
|
@ -244,6 +251,8 @@
|
|||
<ClCompile Include="$(IntDir)Settings\moc_DEV9SettingsWidget.cpp" />
|
||||
<ClCompile Include="$(IntDir)Settings\moc_DEV9UiCommon.cpp" />
|
||||
<ClCompile Include="$(IntDir)Settings\moc_GameSummaryWidget.cpp" />
|
||||
<ClCompile Include="$(IntDir)Settings\moc_Python2BindingWidget.cpp" />
|
||||
<ClCompile Include="$(IntDir)Settings\moc_Python2SettingsWidget.cpp" />
|
||||
<ClCompile Include="$(IntDir)GameList\moc_GameListModel.cpp" />
|
||||
<ClCompile Include="$(IntDir)GameList\moc_GameListRefreshThread.cpp" />
|
||||
<ClCompile Include="$(IntDir)GameList\moc_GameListWidget.cpp" />
|
||||
|
@ -327,6 +336,12 @@
|
|||
<QtUi Include="Settings\GameSummaryWidget.ui">
|
||||
<FileType>Document</FileType>
|
||||
</QtUi>
|
||||
<QtUi Include="Settings\Python2BindingWidget.ui">
|
||||
<FileType>Document</FileType>
|
||||
</QtUi>
|
||||
<QtUi Include="Settings\Python2SettingsWidget.ui">
|
||||
<FileType>Document</FileType>
|
||||
</QtUi>
|
||||
<QtUi Include="AutoUpdaterDialog.ui">
|
||||
<FileType>Document</FileType>
|
||||
</QtUi>
|
||||
|
|
|
@ -205,6 +205,12 @@
|
|||
<ClCompile Include="Settings\HddCreateQt.cpp">
|
||||
<Filter>Settings</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Settings\Python2SettingsWidget.cpp">
|
||||
<Filter>Settings</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Settings\Python2BindingWidget.cpp">
|
||||
<Filter>Settings</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="AutoUpdaterDialog.cpp" />
|
||||
<ClCompile Include="$(IntDir)moc_AutoUpdaterDialog.cpp">
|
||||
<Filter>moc</Filter>
|
||||
|
@ -236,6 +242,12 @@
|
|||
<ClInclude Include="Settings\HddCreateQt.h">
|
||||
<Filter>Settings</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Settings\Python2SettingsWidget.h">
|
||||
<Filter>Settings</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Settings\Python2BindingWidget.h">
|
||||
<Filter>Settings</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Settings\ControllerSettingWidgetBinder.h">
|
||||
<Filter>Settings</Filter>
|
||||
</ClInclude>
|
||||
|
@ -395,6 +407,12 @@
|
|||
<QtUi Include="Settings\DEV9SettingsWidget.ui">
|
||||
<Filter>Settings</Filter>
|
||||
</QtUi>
|
||||
<QtUi Include="Settings\Python2SettingsWidget.ui">
|
||||
<Filter>Settings</Filter>
|
||||
</QtUi>
|
||||
<QtUi Include="Settings\Python2BindingWidget.ui">
|
||||
<Filter>Settings</Filter>
|
||||
</QtUi>
|
||||
<QtUi Include="GameList\EmptyGameListWidget.ui">
|
||||
<Filter>GameList</Filter>
|
||||
</QtUi>
|
||||
|
|
|
@ -484,13 +484,44 @@ set(pcsx2USBSources
|
|||
USB/usb-python2/devices/thrilldrive_belt.cpp
|
||||
USB/usb-python2/devices/thrilldrive_handle.cpp
|
||||
USB/usb-python2/devices/toysmarch_drumpad.cpp
|
||||
USB/usb-python2/passthrough/python2-config-passthrough.cpp
|
||||
USB/usb-python2/passthrough/usb-python2-passthrough.cpp
|
||||
USB/usb-python2/inputs/passthrough/python2-config-passthrough.cpp
|
||||
USB/usb-python2/inputs/passthrough/usb-python2-passthrough.cpp
|
||||
USB/usb-python2/patches.cpp
|
||||
USB/usb-python2/api_init_linux.cpp
|
||||
USB/usb-printer/usb-printer.cpp
|
||||
)
|
||||
|
||||
set(pcsx2USBSourcesQt
|
||||
USB/USB.cpp
|
||||
USB/deviceproxy.cpp
|
||||
USB/device_init.cpp
|
||||
USB/qemu-usb/glib.cpp
|
||||
USB/qemu-usb/vl.cpp
|
||||
USB/qemu-usb/iov.cpp
|
||||
USB/qemu-usb/desc.cpp
|
||||
USB/qemu-usb/core.cpp
|
||||
USB/qemu-usb/bus.cpp
|
||||
USB/qemu-usb/usb-ohci.cpp
|
||||
USB/qemu-usb/hid.cpp
|
||||
USB/qemu-usb/input-keymap-qcode-to-qnum.cpp
|
||||
USB/usb-hid/usb-hid.cpp
|
||||
USB/shared/shared_usb.cpp
|
||||
USB/shared/inifile_usb.cpp
|
||||
USB/shared/ringbuffer.cpp
|
||||
USB/usb-python2/usb-python2.cpp
|
||||
USB/usb-python2/devices/acio.cpp
|
||||
USB/usb-python2/devices/ddr_extio.cpp
|
||||
USB/usb-python2/devices/icca.cpp
|
||||
USB/usb-python2/devices/thrilldrive_belt.cpp
|
||||
USB/usb-python2/devices/thrilldrive_handle.cpp
|
||||
USB/usb-python2/devices/toysmarch_drumpad.cpp
|
||||
USB/usb-python2/inputs/Python2QtInputManager.cpp
|
||||
USB/usb-python2/inputs/passthrough/usb-python2-passthrough.cpp
|
||||
USB/usb-python2/inputs/native/usb-python2-native.cpp
|
||||
USB/usb-python2/patches.cpp
|
||||
USB/usb-python2/api_init_linux.cpp
|
||||
)
|
||||
|
||||
# USB headers
|
||||
set(pcsx2USBHeaders
|
||||
USB/USB.h
|
||||
|
@ -541,11 +572,48 @@ set(pcsx2USBHeaders
|
|||
USB/usb-python2/devices/thrilldrive_belt.h
|
||||
USB/usb-python2/devices/thrilldrive_handle.h
|
||||
USB/usb-python2/devices/toysmarch_drumpad.h
|
||||
USB/usb-python2/passthrough/usb-python2-passthrough.h
|
||||
USB/usb-python2/inputs/passthrough/usb-python2-passthrough.h
|
||||
USB/usb-python2/patches.h
|
||||
USB/usb-printer/usb-printer.h
|
||||
)
|
||||
|
||||
set(pcsx2USBHeadersQt
|
||||
USB/USB.h
|
||||
USB/proxybase.h
|
||||
USB/deviceproxy.h
|
||||
USB/platcompat.h
|
||||
USB/helpers.h
|
||||
USB/readerwriterqueue/readerwriterqueue.h
|
||||
USB/readerwriterqueue/atomicops.h
|
||||
USB/qemu-usb/glib.h
|
||||
USB/qemu-usb/vl.h
|
||||
USB/qemu-usb/qusb.h
|
||||
USB/qemu-usb/USBinternal.h
|
||||
USB/qemu-usb/desc.h
|
||||
USB/qemu-usb/iov.h
|
||||
USB/qemu-usb/queue.h
|
||||
USB/qemu-usb/hid.h
|
||||
USB/qemu-usb/input-keymap.h
|
||||
USB/usb-hid/hidproxy.h
|
||||
USB/usb-hid/usb-hid.h
|
||||
USB/usb-hid/noop.h
|
||||
USB/shared/shared_usb.h
|
||||
USB/shared/inifile_usb.h
|
||||
USB/shared/ringbuffer.h
|
||||
USB/usb-python2/noop.h
|
||||
USB/usb-python2/devices/acio.h
|
||||
USB/usb-python2/devices/ddr_extio.h
|
||||
USB/usb-python2/devices/icca.h
|
||||
USB/usb-python2/devices/input_device.h
|
||||
USB/usb-python2/devices/thrilldrive_belt.h
|
||||
USB/usb-python2/devices/thrilldrive_handle.h
|
||||
USB/usb-python2/devices/toysmarch_drumpad.h
|
||||
USB/usb-python2/inputs/Python2QtInputManager.h
|
||||
USB/usb-python2/inputs/passthrough/usb-python2-passthrough.h
|
||||
USB/usb-python2/inputs/native/usb-python2-native.h
|
||||
USB/usb-python2/patches.h
|
||||
)
|
||||
|
||||
if(TARGET PulseAudio::PulseAudio)
|
||||
list(APPEND pcsx2USBSources USB/usb-mic/audiodev-pulse.cpp)
|
||||
list(APPEND pcsx2USBHeaders USB/usb-mic/audiodev-pulse.h)
|
||||
|
@ -1605,8 +1673,8 @@ if(UNIX AND NOT Linux)
|
|||
target_sources(PCSX2 PRIVATE
|
||||
${pcsx2OSXSources}
|
||||
${pcsx2LinuxHeaders}
|
||||
${pcsx2USBNullSources}
|
||||
${pcsx2USBNullHeaders})
|
||||
${pcsx2USBSourcesQt}
|
||||
${pcsx2USBHeadersQt})
|
||||
else()
|
||||
if(NOT PCSX2_CORE)
|
||||
target_sources(PCSX2 PRIVATE
|
||||
|
@ -1614,8 +1682,8 @@ else()
|
|||
${pcsx2USBHeaders})
|
||||
else()
|
||||
target_sources(PCSX2 PRIVATE
|
||||
${pcsx2USBNullSources}
|
||||
${pcsx2USBNullHeaders})
|
||||
${pcsx2USBSourcesQt}
|
||||
${pcsx2USBHeadersQt})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
|
|
@ -75,12 +75,9 @@ void ATA::SCE_IDENTIFY_DRIVE()
|
|||
hddId[0x4f] = 0x01;
|
||||
// 0x50 - 0x80 is a unique block of data
|
||||
|
||||
#ifndef PCSX2_CORE
|
||||
// TODO: Rewrite this in a way to not use g_Conf for future Qt support
|
||||
auto fp = FileSystem::OpenManagedCFile(EmuConfig.DEV9.HddIdFile.c_str(), "rb");
|
||||
if (fp && FileSystem::FSize64(fp.get()) >= 128)
|
||||
std::fread(hddId, 1, 128, fp.get());
|
||||
#endif
|
||||
|
||||
pioDRQEndTransferFunc = nullptr;
|
||||
DRQCmdPIODataToHost(hddId, 128, 0, 128, true);
|
||||
|
|
|
@ -36,6 +36,8 @@
|
|||
#include "Elfheader.h"
|
||||
#include "VMManager.h"
|
||||
|
||||
#include "Frontend/INISettingsInterface.h"
|
||||
|
||||
enum : u32
|
||||
{
|
||||
GAME_LIST_CACHE_SIGNATURE = 0x45434C47,
|
||||
|
@ -50,6 +52,7 @@ namespace GameList
|
|||
|
||||
static bool GetElfListEntry(const std::string& path, GameList::Entry* entry);
|
||||
static bool GetIsoListEntry(const std::string& path, GameList::Entry* entry);
|
||||
static bool GetPython2ListEntry(const std::string& path, GameList::Entry* entry);
|
||||
|
||||
static bool GetGameListEntryFromCache(const std::string& path, GameList::Entry* entry);
|
||||
static void ScanDirectory(
|
||||
|
@ -81,13 +84,13 @@ bool GameList::IsGameListLoaded()
|
|||
|
||||
const char* GameList::EntryTypeToString(EntryType type)
|
||||
{
|
||||
static std::array<const char*, static_cast<int>(EntryType::Count)> names = {{"PS2Disc", "PS1Disc", "ELF", "Playlist"}};
|
||||
static std::array<const char*, static_cast<int>(EntryType::Count)> names = {{"PS2Disc", "PS1Disc", "ELF", "Playlist", "Python 2"}};
|
||||
return names[static_cast<int>(type)];
|
||||
}
|
||||
|
||||
const char* GameList::EntryTypeToDisplayString(EntryType type)
|
||||
{
|
||||
static std::array<const char*, static_cast<int>(EntryType::Count)> names = {{"PS2 Disc", "PS1 Disc", "ELF", "Playlist"}};
|
||||
static std::array<const char*, static_cast<int>(EntryType::Count)> names = {{"PS2 Disc", "PS1 Disc", "ELF", "Playlist", "Python 2"}};
|
||||
return names[static_cast<int>(type)];
|
||||
}
|
||||
|
||||
|
@ -119,7 +122,7 @@ const char* GameList::EntryCompatibilityRatingToString(CompatibilityRating ratin
|
|||
|
||||
bool GameList::IsScannableFilename(const std::string_view& path)
|
||||
{
|
||||
static const char* extensions[] = {".iso", ".mdf", ".nrg", ".bin", ".img", ".gz", ".cso", ".chd", ".elf", ".irx"};
|
||||
static const char* extensions[] = {".iso", ".mdf", ".nrg", ".bin", ".img", ".gz", ".cso", ".chd", ".elf", ".irx", ".py2"};
|
||||
|
||||
for (const char* test_extension : extensions)
|
||||
{
|
||||
|
@ -144,6 +147,16 @@ void GameList::FillBootParametersForEntry(VMBootParameters* params, const Entry*
|
|||
params->source_type = CDVD_SourceType::NoDisc;
|
||||
params->elf_override = entry->path;
|
||||
}
|
||||
else if (entry->type == GameList::EntryType::Python2)
|
||||
{
|
||||
params->filename.clear();
|
||||
params->source_type = CDVD_SourceType::NoDisc;
|
||||
params->elf_override.clear();
|
||||
|
||||
params->is_python2 = true;
|
||||
params->python2_crc = entry->crc;
|
||||
params->python2_serial = entry->serial;
|
||||
}
|
||||
else
|
||||
{
|
||||
params->filename.clear();
|
||||
|
@ -303,10 +316,218 @@ bool GameList::GetIsoListEntry(const std::string& path, GameList::Entry* entry)
|
|||
return true;
|
||||
}
|
||||
// clang-format off
|
||||
bool GameList::GetPython2ListEntry(const std::string& path, GameList::Entry* entry)
|
||||
{
|
||||
// TODO: Parse a .py2 entry file to read target image filename, HDD ID, ILINK ID, and other configurations
|
||||
std::unique_ptr<INISettingsInterface> new_interface = std::make_unique<INISettingsInterface>(std::move(path));
|
||||
if (!new_interface->Load())
|
||||
{
|
||||
Console.Error("Failed to parse Python 2 game entry ini '%s'", new_interface->GetFileName().c_str());
|
||||
new_interface.reset();
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string game_title;
|
||||
new_interface->GetStringValue("Game", "Title", &game_title);
|
||||
|
||||
std::string hdd_id_path;
|
||||
new_interface->GetStringValue("Game", "HddId", &hdd_id_path);
|
||||
|
||||
if (!hdd_id_path.empty() && !Path::IsAbsolute(hdd_id_path)) {
|
||||
hdd_id_path = std::string(Path::Combine(Path::GetDirectory(path), hdd_id_path));
|
||||
}
|
||||
|
||||
std::string ilink_id_path;
|
||||
new_interface->GetStringValue("Game", "IlinkId", &ilink_id_path);
|
||||
|
||||
if (!ilink_id_path.empty() && !Path::IsAbsolute(ilink_id_path)) {
|
||||
ilink_id_path = std::string(Path::Combine(Path::GetDirectory(path), ilink_id_path));
|
||||
}
|
||||
|
||||
std::string hdd_image_path;
|
||||
new_interface->GetStringValue("Game", "HddImage", &hdd_image_path);
|
||||
|
||||
if (!hdd_image_path.empty() && !Path::IsAbsolute(hdd_image_path)) {
|
||||
hdd_image_path = std::string(Path::Combine(Path::GetDirectory(path), hdd_image_path));
|
||||
}
|
||||
|
||||
std::string region;
|
||||
new_interface->GetStringValue("Game", "Region", ®ion);
|
||||
|
||||
printf("game_title: %s\n", game_title.c_str());
|
||||
printf("hdd_id_path: %s\n", hdd_id_path.c_str());
|
||||
printf("ilink_id_path: %s\n", ilink_id_path.c_str());
|
||||
printf("hdd_image_path: %s\n", hdd_image_path.c_str());
|
||||
printf("region: %s\n", region.c_str());
|
||||
|
||||
entry->path = path;
|
||||
entry->serial = "KNAC00001";
|
||||
entry->crc = rand(); // There should be a better way to determine this but there's no reliable way without parsing the files on the HDD directly
|
||||
entry->title = game_title;
|
||||
entry->type = EntryType::Python2;
|
||||
entry->compatibility_rating = CompatibilityRating::Unknown;
|
||||
|
||||
////// NTSC //////
|
||||
//////////////////
|
||||
if (StringUtil::StartsWith(region, "NTSC-B"))
|
||||
entry->region = Region::NTSC_B;
|
||||
else if (StringUtil::StartsWith(region, "NTSC-C"))
|
||||
entry->region = Region::NTSC_C;
|
||||
else if (StringUtil::StartsWith(region, "NTSC-HK"))
|
||||
entry->region = Region::NTSC_HK;
|
||||
else if (StringUtil::StartsWith(region, "NTSC-J"))
|
||||
entry->region = Region::NTSC_J;
|
||||
else if (StringUtil::StartsWith(region, "NTSC-K"))
|
||||
entry->region = Region::NTSC_K;
|
||||
else if (StringUtil::StartsWith(region, "NTSC-T"))
|
||||
entry->region = Region::NTSC_T;
|
||||
else if (StringUtil::StartsWith(region, "NTSC-U"))
|
||||
entry->region = Region::NTSC_U;
|
||||
////// PAL //////
|
||||
//////////////////
|
||||
else if (StringUtil::StartsWith(region, "PAL-AF"))
|
||||
entry->region = Region::PAL_AF;
|
||||
else if (StringUtil::StartsWith(region, "PAL-AU"))
|
||||
entry->region = Region::PAL_AU;
|
||||
else if (StringUtil::StartsWith(region, "PAL-A"))
|
||||
entry->region = Region::PAL_A;
|
||||
else if (StringUtil::StartsWith(region, "PAL-BE"))
|
||||
entry->region = Region::PAL_BE;
|
||||
else if (StringUtil::StartsWith(region, "PAL-E"))
|
||||
entry->region = Region::PAL_E;
|
||||
else if (StringUtil::StartsWith(region, "PAL-FI"))
|
||||
entry->region = Region::PAL_FI;
|
||||
else if (StringUtil::StartsWith(region, "PAL-F"))
|
||||
entry->region = Region::PAL_F;
|
||||
else if (StringUtil::StartsWith(region, "PAL-GR"))
|
||||
entry->region = Region::PAL_GR;
|
||||
else if (StringUtil::StartsWith(region, "PAL-G"))
|
||||
entry->region = Region::PAL_G;
|
||||
else if (StringUtil::StartsWith(region, "PAL-IN"))
|
||||
entry->region = Region::PAL_IN;
|
||||
else if (StringUtil::StartsWith(region, "PAL-I"))
|
||||
entry->region = Region::PAL_I;
|
||||
else if (StringUtil::StartsWith(region, "PAL-M"))
|
||||
entry->region = Region::PAL_M;
|
||||
else if (StringUtil::StartsWith(region, "PAL-NL"))
|
||||
entry->region = Region::PAL_NL;
|
||||
else if (StringUtil::StartsWith(region, "PAL-NO"))
|
||||
entry->region = Region::PAL_NO;
|
||||
else if (StringUtil::StartsWith(region, "PAL-P"))
|
||||
entry->region = Region::PAL_P;
|
||||
else if (StringUtil::StartsWith(region, "PAL-R"))
|
||||
entry->region = Region::PAL_R;
|
||||
else if (StringUtil::StartsWith(region, "PAL-SC"))
|
||||
entry->region = Region::PAL_SC;
|
||||
else if (StringUtil::StartsWith(region, "PAL-SWI"))
|
||||
entry->region = Region::PAL_SWI;
|
||||
else if (StringUtil::StartsWith(region, "PAL-SW"))
|
||||
entry->region = Region::PAL_SW;
|
||||
else if (StringUtil::StartsWith(region, "PAL-S"))
|
||||
entry->region = Region::PAL_S;
|
||||
else if (StringUtil::StartsWith(region, "PAL-UK"))
|
||||
entry->region = Region::PAL_UK;
|
||||
else
|
||||
entry->region = Region::Other;
|
||||
|
||||
std::string filename(VMManager::GetGameSettingsPath(entry->serial, entry->crc));
|
||||
std::unique_ptr<INISettingsInterface> sif = std::make_unique<INISettingsInterface>(std::move(filename));
|
||||
if (FileSystem::FileExists(sif->GetFileName().c_str()))
|
||||
sif->Load();
|
||||
|
||||
sif->SetBoolValue("DEV9/Hdd", "HddEnable", true);
|
||||
sif->SetStringValue("DEV9/Hdd", "HddFile", hdd_image_path.c_str());
|
||||
sif->SetStringValue("DEV9/Hdd", "HddIdFile", hdd_id_path.c_str());
|
||||
sif->SetStringValue("DEV9/Hdd", "IlinkIdPath", ilink_id_path.c_str()); // TODO: Find better place
|
||||
sif->SetBoolValue("DEV9/Eth", "EthEnable", true);
|
||||
sif->SetBoolValue("EmuCore/Gamefixes", "OPHFlagHack", true);
|
||||
|
||||
if (!sif->ContainsValue("Python2/Game", "DongleBlackFile")) {
|
||||
std::string dongleBlackFile;
|
||||
new_interface->GetStringValue("Game", "DongleBlackFile", &dongleBlackFile);
|
||||
|
||||
if (!dongleBlackFile.empty() && !Path::IsAbsolute(dongleBlackFile)) {
|
||||
dongleBlackFile = std::string(Path::Combine(Path::GetDirectory(path), dongleBlackFile));
|
||||
}
|
||||
|
||||
if (!dongleBlackFile.empty())
|
||||
sif->SetStringValue("Python2/Game", "DongleBlackFile", dongleBlackFile.c_str());
|
||||
}
|
||||
|
||||
if (!sif->ContainsValue("Python2/Game", "DongleWhiteFile")) {
|
||||
std::string dongleWhiteFile;
|
||||
new_interface->GetStringValue("Game", "DongleWhiteFile", &dongleWhiteFile);
|
||||
|
||||
if (!dongleWhiteFile.empty() && !Path::IsAbsolute(dongleWhiteFile)) {
|
||||
dongleWhiteFile = std::string(Path::Combine(Path::GetDirectory(path), dongleWhiteFile));
|
||||
}
|
||||
|
||||
if (!dongleWhiteFile.empty())
|
||||
sif->SetStringValue("Python2/Game", "DongleWhiteFile", dongleWhiteFile.c_str());
|
||||
}
|
||||
|
||||
if (!sif->ContainsValue("Python2/Game", "Player1CardFile")) {
|
||||
std::string player1CardFile;
|
||||
new_interface->GetStringValue("Game", "Player1CardFile", &player1CardFile);
|
||||
|
||||
if (!player1CardFile.empty() && !Path::IsAbsolute(player1CardFile)) {
|
||||
player1CardFile = std::string(Path::Combine(Path::GetDirectory(path), player1CardFile));
|
||||
}
|
||||
|
||||
if (!player1CardFile.empty())
|
||||
sif->SetStringValue("Python2/Game", "Player1CardFile", player1CardFile.c_str());
|
||||
}
|
||||
|
||||
if (!sif->ContainsValue("Python2/Game", "Player2CardFile")) {
|
||||
std::string player2CardFile;
|
||||
new_interface->GetStringValue("Game", "Player2CardFile", &player2CardFile);
|
||||
|
||||
if (!player2CardFile.empty() && !Path::IsAbsolute(player2CardFile)) {
|
||||
player2CardFile = std::string(Path::Combine(Path::GetDirectory(path), player2CardFile));
|
||||
}
|
||||
|
||||
if (!player2CardFile.empty())
|
||||
sif->SetStringValue("Python2/Game", "Player2CardFile", player2CardFile.c_str());
|
||||
}
|
||||
|
||||
|
||||
if (!sif->ContainsValue("Python2/Game", "PatchFile")) {
|
||||
std::string patchFile;
|
||||
new_interface->GetStringValue("Game", "PatchFile", &patchFile);
|
||||
|
||||
if (!patchFile.empty() && !Path::IsAbsolute(patchFile)) {
|
||||
patchFile = std::string(Path::Combine(Path::GetDirectory(path), patchFile));
|
||||
}
|
||||
if (!patchFile.empty())
|
||||
sif->SetStringValue("Python2/Game", "PatchFile", patchFile.c_str());
|
||||
}
|
||||
|
||||
if (!sif->ContainsValue("Python2/Game", "DIPSW1"))
|
||||
sif->SetBoolValue("Python2/Game", "DIPSW1", new_interface->GetBoolValue("Game", "DIPSW1", false));
|
||||
|
||||
if (!sif->ContainsValue("Python2/Game", "DIPSW2"))
|
||||
sif->SetBoolValue("Python2/Game", "DIPSW2", new_interface->GetBoolValue("Game", "DIPSW2", false));
|
||||
|
||||
if (!sif->ContainsValue("Python2/Game", "DIPSW3"))
|
||||
sif->SetBoolValue("Python2/Game", "DIPSW3", new_interface->GetBoolValue("Game", "DIPSW3", false));
|
||||
|
||||
if (!sif->ContainsValue("Python2/Game", "DIPSW4"))
|
||||
sif->SetBoolValue("Python2/Game", "DIPSW4", new_interface->GetBoolValue("Game", "DIPSW4", false));
|
||||
|
||||
if (!sif->ContainsValue("Python2/Game", "Force31kHz"))
|
||||
sif->SetBoolValue("Python2/Game", "Force31kHz", new_interface->GetBoolValue("Game", "Force31kHz", false));
|
||||
|
||||
sif->Save();
|
||||
|
||||
return true;
|
||||
}
|
||||
// clang-format off
|
||||
bool GameList::PopulateEntryFromPath(const std::string& path, GameList::Entry* entry)
|
||||
{
|
||||
if (VMManager::IsElfFileName(path.c_str()))
|
||||
return GetElfListEntry(path, entry);
|
||||
else if (StringUtil::EndsWithNoCase(path.c_str(), ".py2"))
|
||||
return GetPython2ListEntry(path, entry);
|
||||
else
|
||||
return GetIsoListEntry(path, entry);
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@ namespace GameList
|
|||
PS1Disc,
|
||||
ELF,
|
||||
Playlist,
|
||||
Python2,
|
||||
Count
|
||||
};
|
||||
|
||||
|
|
|
@ -26,7 +26,10 @@
|
|||
#include "qemu-usb/desc.h"
|
||||
#include "shared/shared_usb.h"
|
||||
#include "deviceproxy.h"
|
||||
|
||||
#ifndef PCSX2_CORE
|
||||
#include "configuration.h"
|
||||
#endif
|
||||
|
||||
#define PSXCLK 36864000 /* 36.864 Mhz */
|
||||
|
||||
|
@ -70,12 +73,19 @@ s64 remaining = 0;
|
|||
#if defined(_WIN32)
|
||||
HWND gsWnd = nullptr;
|
||||
#elif defined(__linux__)
|
||||
|
||||
#ifndef PCSX2_CORE
|
||||
#include "gtk.h"
|
||||
#include <gdk/gdkx.h>
|
||||
#endif
|
||||
|
||||
#include <X11/X.h>
|
||||
|
||||
#ifndef PCSX2_CORE
|
||||
Display* g_GSdsp = nullptr;
|
||||
Window g_GSwin;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
Config::Config()
|
||||
: Log(0)
|
||||
|
@ -198,17 +208,24 @@ void CreateDevices()
|
|||
|
||||
s32 USBinit()
|
||||
{
|
||||
#ifndef PCSX2_CORE
|
||||
USBsetSettingsDir();
|
||||
#endif
|
||||
|
||||
RegisterDevice::Register();
|
||||
|
||||
#ifndef PCSX2_CORE
|
||||
LoadConfig();
|
||||
#endif
|
||||
|
||||
if (conf.Log && !usbLog)
|
||||
{
|
||||
#ifndef PCSX2_CORE
|
||||
#ifdef _WIN32
|
||||
usbLog = wfopen(LogDir.c_str(), L"wb"); // L"wb,ccs=UNICODE");
|
||||
#else
|
||||
usbLog = wfopen(LogDir.c_str(), "wb"); // L"wb,ccs=UNICODE");
|
||||
#endif
|
||||
#endif
|
||||
//if(usbLog) setvbuf(usbLog, NULL, _IONBF, 0);
|
||||
}
|
||||
|
@ -245,6 +262,9 @@ void USBshutdown()
|
|||
|
||||
s32 USBopen(const WindowInfo& wi)
|
||||
{
|
||||
#ifdef PCSX2_CORE
|
||||
conf.Port[0] = "python2io";
|
||||
#endif
|
||||
|
||||
if (conf.Log && !usbLog)
|
||||
{
|
||||
|
@ -262,9 +282,11 @@ s32 USBopen(const WindowInfo& wi)
|
|||
#elif defined(__linux__)
|
||||
if (wi.type == WindowInfo::Type::X11)
|
||||
{
|
||||
#ifndef PCSX2_CORE
|
||||
g_GSdsp = static_cast<Display*>(wi.display_connection);
|
||||
g_GSwin = reinterpret_cast<Window>(wi.window_handle);
|
||||
window_handle_for_init = reinterpret_cast<void*>(g_GSwin);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -297,9 +319,12 @@ void USBclose()
|
|||
#if defined(_WIN32)
|
||||
gsWnd = {};
|
||||
#elif defined(__linux__)
|
||||
g_GSdsp = nullptr;
|
||||
|
||||
#ifndef PCSX2_CORE
|
||||
g_GSdsp = nullptr;
|
||||
g_GSwin = {};
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
u8 USBread8(u32 addr)
|
||||
|
|
|
@ -16,7 +16,11 @@
|
|||
#pragma once
|
||||
|
||||
#include "platcompat.h"
|
||||
|
||||
#ifndef PCSX2_CORE
|
||||
#include <wx/string.h>
|
||||
#endif
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
|
|
@ -29,6 +29,8 @@ void RegisterDevice::Register()
|
|||
auto& inst = RegisterDevice::instance();
|
||||
if (inst.Map().size()) // FIXME Don't clear proxies, singstar keeps a copy to uninit audio
|
||||
return;
|
||||
|
||||
#ifndef PCSX2_CORE
|
||||
inst.Add(DEVTYPE_PAD, new DeviceProxy<usb_pad::PadDevice>());
|
||||
inst.Add(DEVTYPE_MSD, new DeviceProxy<usb_msd::MsdDevice>());
|
||||
inst.Add(DEVTYPE_SINGSTAR, new DeviceProxy<usb_mic::SingstarDevice>());
|
||||
|
@ -47,6 +49,8 @@ void RegisterDevice::Register()
|
|||
inst.Add(DEVTYPE_SEGA_SEAMIC, new DeviceProxy<usb_pad::SeamicDevice>());
|
||||
inst.Add(DEVTYPE_PRINTER, new DeviceProxy<usb_printer::PrinterDevice>());
|
||||
inst.Add(DEVTYPE_KEYBOARDMANIA, new DeviceProxy<usb_pad::KeyboardmaniaDevice>());
|
||||
#endif
|
||||
|
||||
inst.Add(DEVTYPE_PYTHON2, new DeviceProxy<usb_python2::Python2Device>());
|
||||
|
||||
RegisterAPIs();
|
||||
|
|
|
@ -15,28 +15,38 @@
|
|||
|
||||
#include "PrecompiledHeader.h"
|
||||
#include "deviceproxy.h"
|
||||
|
||||
#ifndef PCSX2_CORE
|
||||
#include "usb-pad/padproxy.h"
|
||||
#include "usb-mic/audiodeviceproxy.h"
|
||||
#include "usb-hid/hidproxy.h"
|
||||
#include "usb-eyetoy/videodeviceproxy.h"
|
||||
#endif
|
||||
|
||||
#include "usb-python2/python2proxy.h"
|
||||
|
||||
RegisterDevice* RegisterDevice::registerDevice = nullptr;
|
||||
|
||||
void RegisterAPIs()
|
||||
{
|
||||
#ifndef PCSX2_CORE
|
||||
usb_pad::RegisterPad::Register();
|
||||
usb_mic::RegisterAudioDevice::Register();
|
||||
usb_hid::RegisterUsbHID::Register();
|
||||
usb_eyetoy::RegisterVideoDevice::Register();
|
||||
#endif
|
||||
|
||||
usb_python2::RegisterUsbPython2::Register();
|
||||
}
|
||||
|
||||
void UnregisterAPIs()
|
||||
{
|
||||
#ifndef PCSX2_CORE
|
||||
usb_pad::RegisterPad::instance().Clear();
|
||||
usb_mic::RegisterAudioDevice::instance().Clear();
|
||||
usb_hid::RegisterUsbHID::instance().Clear();
|
||||
usb_eyetoy::RegisterVideoDevice::instance().Clear();
|
||||
#endif
|
||||
|
||||
usb_python2::RegisterUsbPython2::instance().Clear();
|
||||
}
|
||||
|
|
|
@ -15,6 +15,13 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#include <basetsd.h>
|
||||
#ifndef HAVE_SSIZE_T
|
||||
typedef SSIZE_T ssize_t;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Annoying defines
|
||||
// ---------------------------------------------------------------------
|
||||
// make sure __POSIX__ is defined for all systems where we assume POSIX
|
||||
|
@ -36,26 +43,40 @@
|
|||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#if defined(_WIN32)
|
||||
#ifndef NOMINMAX
|
||||
#define NOMINMAX
|
||||
#endif
|
||||
#include <windows.h>
|
||||
|
||||
#ifdef PCSX2_CORE
|
||||
#define wfopen _wfopen
|
||||
#define fseeko64 _fseeki64
|
||||
#define ftello64 _ftelli64
|
||||
#define TSTDSTRING std::string
|
||||
#define TSTDSTRINGSTREAM std::stringstream
|
||||
#define TSTDTOSTRING std::to_string
|
||||
#define P2TEXT(x) x
|
||||
|
||||
void SysMessage(const char* fmt, ...);
|
||||
#else
|
||||
#define wfopen _wfopen
|
||||
#define fseeko64 _fseeki64
|
||||
#define ftello64 _ftelli64
|
||||
#define TSTDSTRING std::wstring
|
||||
#define TSTDSTRINGSTREAM std::wstringstream
|
||||
#define TSTDTOSTRING std::to_wstring
|
||||
#define P2TEXT(x) L##x
|
||||
|
||||
void SysMessageW(const wchar_t* fmt, ...);
|
||||
#define SysMessage SysMessageW
|
||||
#endif
|
||||
|
||||
//FIXME narrow string fmt
|
||||
#define SFMTs "S"
|
||||
|
||||
#define __builtin_constant_p(p) false
|
||||
|
||||
void SysMessageW(const wchar_t* fmt, ...);
|
||||
#define SysMessage SysMessageW
|
||||
|
||||
#else //_WIN32
|
||||
|
||||
#define MAX_PATH PATH_MAX
|
||||
|
@ -67,6 +88,7 @@ void SysMessageW(const wchar_t* fmt, ...);
|
|||
//FIXME narrow string fmt
|
||||
#define SFMTs "s"
|
||||
#define TEXT(val) val
|
||||
#define P2TEXT(val) val
|
||||
#define TCHAR char
|
||||
#define wfopen fopen
|
||||
#define TSTDSTRING std::string
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
#include "shared_usb.h"
|
||||
#include <stdexcept>
|
||||
|
||||
#ifdef _WIN32
|
||||
#if defined(_WIN32) && !defined(PCSX2_CORE)
|
||||
#include "rawinput_usb.h"
|
||||
#endif
|
||||
|
||||
|
@ -26,7 +26,7 @@ namespace shared
|
|||
|
||||
void Initialize(void* ptr)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
#if defined(_WIN32) && !defined(PCSX2_CORE)
|
||||
if (!shared::rawinput::Initialize(ptr))
|
||||
throw std::runtime_error("Failed to initialize raw input!");
|
||||
#endif
|
||||
|
@ -34,7 +34,7 @@ namespace shared
|
|||
|
||||
void Uninitialize(/*void *ptr*/)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
#if defined(_WIN32) && !defined(PCSX2_CORE)
|
||||
shared::rawinput::Uninitialize(/*ptr*/);
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -1,10 +1,18 @@
|
|||
#include "python2proxy.h"
|
||||
#include "noop.h"
|
||||
#include "passthrough/usb-python2-passthrough.h"
|
||||
#include "inputs/passthrough/usb-python2-passthrough.h"
|
||||
|
||||
#ifdef PCSX2_CORE
|
||||
#include "inputs/native/usb-python2-native.h"
|
||||
#endif
|
||||
|
||||
void usb_python2::RegisterUsbPython2::Register()
|
||||
{
|
||||
auto& inst = RegisterUsbPython2::instance();
|
||||
inst.Add(usb_python2::passthrough::APINAME, new UsbPython2Proxy<usb_python2::passthrough::PassthroughInput>());
|
||||
#ifdef PCSX2_CORE
|
||||
inst.Add(usb_python2::native::APINAME, new UsbPython2Proxy<usb_python2::native::NativeInput>());
|
||||
#else
|
||||
inst.Add(usb_python2::noop::APINAME, new UsbPython2Proxy<usb_python2::noop::NOOP>());
|
||||
}
|
||||
#endif
|
||||
inst.Add(usb_python2::passthrough::APINAME, new UsbPython2Proxy<usb_python2::passthrough::PassthroughInput>());
|
||||
}
|
|
@ -1,16 +1,28 @@
|
|||
#include "PrecompiledHeader.h"
|
||||
#include "python2proxy.h"
|
||||
#include "raw/usb-python2-raw.h"
|
||||
#include "passthrough/usb-python2-passthrough.h"
|
||||
#include "btools/usb-python2-btools.h"
|
||||
|
||||
#ifdef PCSX2_CORE
|
||||
#include "inputs/native/usb-python2-native.h"
|
||||
#else
|
||||
#include "inputs/raw/usb-python2-raw.h"
|
||||
#include "inputs/btools/usb-python2-btools.h"
|
||||
#endif
|
||||
|
||||
#include "inputs/passthrough/usb-python2-passthrough.h"
|
||||
|
||||
void usb_python2::RegisterUsbPython2::Register()
|
||||
{
|
||||
auto& inst = RegisterUsbPython2::instance();
|
||||
|
||||
#ifdef PCSX2_CORE
|
||||
inst.Add(usb_python2::native::APINAME, new UsbPython2Proxy<usb_python2::native::NativeInput>());
|
||||
#else
|
||||
inst.Add(usb_python2::APINAME, new UsbPython2Proxy<usb_python2::raw::RawInputPad>());
|
||||
#endif
|
||||
|
||||
inst.Add(usb_python2::passthrough::APINAME, new UsbPython2Proxy<usb_python2::passthrough::PassthroughInput>());
|
||||
|
||||
#ifdef INCLUDE_BTOOLS
|
||||
#if defined(INCLUDE_BTOOLS) && !defined(PCSX2_CORE)
|
||||
inst.Add(usb_python2::btools::APINAME, new UsbPython2Proxy<usb_python2::btools::BToolsInput>());
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -21,31 +21,31 @@ namespace usb_python2
|
|||
uint8_t cardId[8] = {0};
|
||||
std::string cardFilename = "";
|
||||
|
||||
std::wstring keypadIdsByDeviceId[2][12] = {
|
||||
{L"KeypadP1_0",
|
||||
L"KeypadP1_1",
|
||||
L"KeypadP1_2",
|
||||
L"KeypadP1_3",
|
||||
L"KeypadP1_4",
|
||||
L"KeypadP1_5",
|
||||
L"KeypadP1_6",
|
||||
L"KeypadP1_7",
|
||||
L"KeypadP1_8",
|
||||
L"KeypadP1_9",
|
||||
L"KeypadP1_00",
|
||||
L"KeypadP1InsertEject"},
|
||||
{L"KeypadP2_0",
|
||||
L"KeypadP2_1",
|
||||
L"KeypadP2_2",
|
||||
L"KeypadP2_3",
|
||||
L"KeypadP2_4",
|
||||
L"KeypadP2_5",
|
||||
L"KeypadP2_6",
|
||||
L"KeypadP2_7",
|
||||
L"KeypadP2_8",
|
||||
L"KeypadP2_9",
|
||||
L"KeypadP2_00",
|
||||
L"KeypadP2InsertEject"},
|
||||
TSTDSTRING keypadIdsByDeviceId[2][12] = {
|
||||
{P2TEXT("KeypadP1_0"),
|
||||
P2TEXT("KeypadP1_1"),
|
||||
P2TEXT("KeypadP1_2"),
|
||||
P2TEXT("KeypadP1_3"),
|
||||
P2TEXT("KeypadP1_4"),
|
||||
P2TEXT("KeypadP1_5"),
|
||||
P2TEXT("KeypadP1_6"),
|
||||
P2TEXT("KeypadP1_7"),
|
||||
P2TEXT("KeypadP1_8"),
|
||||
P2TEXT("KeypadP1_9"),
|
||||
P2TEXT("KeypadP1_00"),
|
||||
P2TEXT("KeypadP1InsertEject")},
|
||||
{P2TEXT("KeypadP2_0"),
|
||||
P2TEXT("KeypadP2_1"),
|
||||
P2TEXT("KeypadP2_2"),
|
||||
P2TEXT("KeypadP2_3"),
|
||||
P2TEXT("KeypadP2_4"),
|
||||
P2TEXT("KeypadP2_5"),
|
||||
P2TEXT("KeypadP2_6"),
|
||||
P2TEXT("KeypadP2_7"),
|
||||
P2TEXT("KeypadP2_8"),
|
||||
P2TEXT("KeypadP2_9"),
|
||||
P2TEXT("KeypadP2_00"),
|
||||
P2TEXT("KeypadP2InsertEject")},
|
||||
};
|
||||
|
||||
void write(std::vector<uint8_t>& packet) {}
|
||||
|
|
|
@ -7,7 +7,7 @@ namespace usb_python2
|
|||
const auto header = (ACIO_PACKET_HEADER*)packet.data();
|
||||
const auto code = BigEndian16(header->code);
|
||||
|
||||
if (p2dev->GetKeyState(L"ThrillDriveSeatbelt") != 0)
|
||||
if (p2dev->GetKeyState(P2TEXT("ThrillDriveSeatbelt")) != 0)
|
||||
{
|
||||
if (!seatBeltButtonPressed)
|
||||
seatBeltStatus = !seatBeltStatus;
|
||||
|
|
|
@ -15,13 +15,13 @@ namespace usb_python2
|
|||
// If this packet can't be read then the game will throw a drum I/O error
|
||||
uint8_t state[9] = {
|
||||
stateIdx,
|
||||
uint8_t(p2dev->GetKeyStateOneShot(L"ToysMarchP1Cymbal") * 128),
|
||||
uint8_t(p2dev->GetKeyStateOneShot(L"ToysMarchP1DrumL") * 128),
|
||||
uint8_t(p2dev->GetKeyStateOneShot(L"ToysMarchP1DrumR") * 128),
|
||||
uint8_t(p2dev->GetKeyStateOneShot(P2TEXT("ToysMarchP1Cymbal")) * 128),
|
||||
uint8_t(p2dev->GetKeyStateOneShot(P2TEXT("ToysMarchP1DrumL")) * 128),
|
||||
uint8_t(p2dev->GetKeyStateOneShot(P2TEXT("ToysMarchP1DrumR")) * 128),
|
||||
0,
|
||||
uint8_t(p2dev->GetKeyStateOneShot(L"ToysMarchP2Cymbal") * 128),
|
||||
uint8_t(p2dev->GetKeyStateOneShot(L"ToysMarchP2DrumL") * 128),
|
||||
uint8_t(p2dev->GetKeyStateOneShot(L"ToysMarchP2DrumR") * 128),
|
||||
uint8_t(p2dev->GetKeyStateOneShot(P2TEXT("ToysMarchP2Cymbal")) * 128),
|
||||
uint8_t(p2dev->GetKeyStateOneShot(P2TEXT("ToysMarchP2DrumL")) * 128),
|
||||
uint8_t(p2dev->GetKeyStateOneShot(P2TEXT("ToysMarchP2DrumR")) * 128),
|
||||
0
|
||||
};
|
||||
stateIdx = (stateIdx + 1) % 8;
|
||||
|
|
|
@ -0,0 +1,161 @@
|
|||
#include "Python2QtInputManager.h"
|
||||
|
||||
#include <map>
|
||||
|
||||
#include "pcsx2/HostSettings.h"
|
||||
#include "common/SettingsInterface.h"
|
||||
#include "common/StringUtil.h"
|
||||
|
||||
|
||||
static std::vector<Python2KeyMapping> s_python2_current_mappings;
|
||||
static std::map<std::string, std::vector<Python2KeyMapping>> mappingsByInputKey;
|
||||
|
||||
std::vector<Python2KeyMapping> Python2QtInputManager::GetCurrentMappings()
|
||||
{
|
||||
return s_python2_current_mappings;
|
||||
}
|
||||
|
||||
std::vector<Python2KeyMapping> Python2QtInputManager::GetMappingsByInputKey(std::string keyBindStr)
|
||||
{
|
||||
if (mappingsByInputKey.find(keyBindStr) != mappingsByInputKey.end())
|
||||
return mappingsByInputKey[keyBindStr];
|
||||
|
||||
return std::vector<Python2KeyMapping>();
|
||||
}
|
||||
|
||||
bool Python2QtInputManager::AddNewBinding(std::string full_key, std::string new_binding, double analogDeadzone, double analogSensitivity, double motorScale)
|
||||
{
|
||||
uint32_t nextUniqueId = 0;
|
||||
for (auto mapping : s_python2_current_mappings)
|
||||
{
|
||||
if (mapping.uniqueId + 1 > nextUniqueId)
|
||||
nextUniqueId = mapping.uniqueId + 1;
|
||||
}
|
||||
|
||||
for (auto system_entry : s_python2_system_info)
|
||||
{
|
||||
if (system_entry.bindings == nullptr)
|
||||
continue;
|
||||
|
||||
for (u32 i = 0; i < system_entry.num_bindings; i++)
|
||||
{
|
||||
auto entry = system_entry.bindings[i];
|
||||
|
||||
if (std::string(entry.name) != full_key)
|
||||
continue;
|
||||
|
||||
Python2KeyMapping keybindMapping = {
|
||||
nextUniqueId,
|
||||
new_binding,
|
||||
entry.name,
|
||||
entry.type,
|
||||
analogDeadzone,
|
||||
analogSensitivity,
|
||||
motorScale,
|
||||
entry.is_oneshot,
|
||||
};
|
||||
|
||||
s_python2_current_mappings.push_back(keybindMapping);
|
||||
|
||||
mappingsByInputKey[new_binding].push_back(keybindMapping);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void Python2QtInputManager::RemoveMappingByUniqueId(uint32_t uniqueId)
|
||||
{
|
||||
s_python2_current_mappings.erase(
|
||||
std::remove_if(
|
||||
s_python2_current_mappings.begin(),
|
||||
s_python2_current_mappings.end(),
|
||||
[uniqueId](const Python2KeyMapping& x) { return x.uniqueId == uniqueId; }),
|
||||
s_python2_current_mappings.end());
|
||||
|
||||
for (auto x : mappingsByInputKey) {
|
||||
x.second.erase(
|
||||
std::remove_if(
|
||||
x.second.begin(),
|
||||
x.second.end(),
|
||||
[uniqueId](const Python2KeyMapping& x) { return x.uniqueId == uniqueId; }),
|
||||
x.second.end());
|
||||
}
|
||||
}
|
||||
|
||||
void Python2QtInputManager::LoadMapping()
|
||||
{
|
||||
SettingsInterface* si = Host::GetSettingsInterfaceForBindings();
|
||||
const std::string section = "Python2";
|
||||
uint32_t uniqueKeybindIdx = 0;
|
||||
|
||||
s_python2_current_mappings.clear();
|
||||
|
||||
for (auto system_entry : s_python2_system_info)
|
||||
{
|
||||
if (system_entry.bindings == nullptr)
|
||||
continue;
|
||||
|
||||
for (u32 i = 0; i < system_entry.num_bindings; i++)
|
||||
{
|
||||
auto entry = system_entry.bindings[i];
|
||||
const std::vector<std::string> bindings(si->GetStringList(section.c_str(), entry.name));
|
||||
|
||||
printf("button: %s\n", entry.name);
|
||||
|
||||
for (auto bind : bindings)
|
||||
{
|
||||
int isOneshot = 0;
|
||||
double analogDeadzone = 0;
|
||||
double analogSensitivity = 0;
|
||||
double motorScale = 0;
|
||||
|
||||
auto idx = bind.find_first_of(L'|');
|
||||
if (idx != std::string::npos)
|
||||
{
|
||||
auto substr = std::string(bind.begin() + idx + 1, bind.end());
|
||||
|
||||
if (entry.type == PAD::ControllerBindingType::Button)
|
||||
{
|
||||
isOneshot = std::stoi(substr);
|
||||
}
|
||||
else if (entry.type == PAD::ControllerBindingType::Axis || entry.type == PAD::ControllerBindingType::HalfAxis)
|
||||
{
|
||||
analogDeadzone = std::stod(substr);
|
||||
analogSensitivity = std::stod(substr.substr(substr.find_first_of('|') + 1));
|
||||
}
|
||||
else if (entry.type == PAD::ControllerBindingType::Motor)
|
||||
{
|
||||
motorScale = std::stod(substr);
|
||||
}
|
||||
}
|
||||
|
||||
auto input_key = std::string(bind.begin(), bind.begin() + idx);
|
||||
|
||||
Python2KeyMapping keybindMapping = {
|
||||
uniqueKeybindIdx++,
|
||||
input_key,
|
||||
std::string(entry.name),
|
||||
entry.type,
|
||||
analogDeadzone,
|
||||
analogSensitivity,
|
||||
motorScale,
|
||||
isOneshot == 1,
|
||||
};
|
||||
|
||||
s_python2_current_mappings.push_back(keybindMapping);
|
||||
|
||||
mappingsByInputKey[input_key].push_back(keybindMapping);
|
||||
|
||||
if (entry.type == PAD::ControllerBindingType::Button)
|
||||
printf("\tbind: %s, oneshot = %d\n", input_key.c_str(), isOneshot);
|
||||
else if (entry.type == PAD::ControllerBindingType::Axis || entry.type == PAD::ControllerBindingType::HalfAxis)
|
||||
printf("\tbind: %s, deadzone = %lf, sensitivity = %lf\n", input_key.c_str(), analogDeadzone, analogSensitivity);
|
||||
else if (entry.type == PAD::ControllerBindingType::Motor)
|
||||
printf("\tbind: %s, motor scale = %lf\n", input_key.c_str(), motorScale);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,189 @@
|
|||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "pcsx2/PAD/Host/PAD.h"
|
||||
|
||||
struct Python2KeyMapping
|
||||
{
|
||||
uint32_t uniqueId;
|
||||
std::string inputKey;
|
||||
std::string keybind;
|
||||
PAD::ControllerBindingType input_type;
|
||||
double analogDeadzone;
|
||||
double analogSensitivity;
|
||||
double motorScale;
|
||||
bool isOneshot; // Immediately trigger an off after on
|
||||
};
|
||||
|
||||
struct Python2BindingInfo
|
||||
{
|
||||
const char* name;
|
||||
const char* display_name;
|
||||
PAD::ControllerBindingType type;
|
||||
bool is_oneshot;
|
||||
};
|
||||
|
||||
struct Python2SystemInfo
|
||||
{
|
||||
const char* name;
|
||||
const Python2BindingInfo* bindings;
|
||||
u32 num_bindings;
|
||||
};
|
||||
|
||||
static const Python2BindingInfo s_python2_system_binds[] = {
|
||||
{"Test", "Test", PAD::ControllerBindingType::Button, false},
|
||||
{"Service", "Service", PAD::ControllerBindingType::Button, false},
|
||||
{"Coin1", "Coin 1", PAD::ControllerBindingType::Button, false},
|
||||
{"Coin2", "Coin 2", PAD::ControllerBindingType::Button, false},
|
||||
};
|
||||
|
||||
static const Python2BindingInfo s_python2_guitarfreaks_binds[] = {
|
||||
{"GfP1Start", "P1 Start", PAD::ControllerBindingType::Button, false},
|
||||
{"GfP1Pick", "P1 Pick", PAD::ControllerBindingType::Button, true},
|
||||
{"GfP1Wail", "P1 Wail", PAD::ControllerBindingType::Button, false},
|
||||
{"GfP1EffectInc", "P1 Effect+", PAD::ControllerBindingType::Button, false},
|
||||
{"GfP1EffectDec", "P1 Effect-", PAD::ControllerBindingType::Button, false},
|
||||
{"GfP1NeckR", "P1 Neck R", PAD::ControllerBindingType::Button, false},
|
||||
{"GfP1NeckG", "P1 Neck G", PAD::ControllerBindingType::Button, false},
|
||||
{"GfP1NeckB", "P1 Neck B", PAD::ControllerBindingType::Button, false},
|
||||
|
||||
{"GfP2Start", "P2 Start", PAD::ControllerBindingType::Button, false},
|
||||
{"GfP2Pick", "P2 Pick", PAD::ControllerBindingType::Button, true},
|
||||
{"GfP2Wail", "P2 Wail", PAD::ControllerBindingType::Button, false},
|
||||
{"GfP2EffectInc", "P2 Effect+", PAD::ControllerBindingType::Button, false},
|
||||
{"GfP2EffectDec", "P2 Effect-", PAD::ControllerBindingType::Button, false},
|
||||
{"GfP2NeckR", "P2 Neck R", PAD::ControllerBindingType::Button, false},
|
||||
{"GfP2NeckG", "P2 Neck G", PAD::ControllerBindingType::Button, false},
|
||||
{"GfP2NeckB", "P2 Neck B", PAD::ControllerBindingType::Button, false},
|
||||
};
|
||||
|
||||
static const Python2BindingInfo s_python2_drummania_binds[] = {
|
||||
{"DmStart", "Start", PAD::ControllerBindingType::Button, false},
|
||||
{"DmSelectL", "Select L", PAD::ControllerBindingType::Button, false},
|
||||
{"DmSelectR", "Select R", PAD::ControllerBindingType::Button, false},
|
||||
{"DmHihat", "Hihat", PAD::ControllerBindingType::Button, true},
|
||||
{"DmSnare", "Snare", PAD::ControllerBindingType::Button, true},
|
||||
{"DmHighTom", "High Tom", PAD::ControllerBindingType::Button, true},
|
||||
{"DmLowTom", "Low Tom", PAD::ControllerBindingType::Button, true},
|
||||
{"DmCymbal", "Cymbal", PAD::ControllerBindingType::Button, true},
|
||||
{"DmBassDrum", "Bass Drum", PAD::ControllerBindingType::Button, true},
|
||||
};
|
||||
|
||||
static const Python2BindingInfo s_python2_ddr_binds[] = {
|
||||
{"DdrP1Start", "P1 Start", PAD::ControllerBindingType::Button, false},
|
||||
{"DdrP1SelectL", "P1 Select L", PAD::ControllerBindingType::Button, false},
|
||||
{"DdrP1SelectR", "P1 Select R", PAD::ControllerBindingType::Button, false},
|
||||
{"DdrP1FootLeft", "P1 Left", PAD::ControllerBindingType::Button, false},
|
||||
{"DdrP1FootDown", "P1 Down", PAD::ControllerBindingType::Button, false},
|
||||
{"DdrP1FootUp", "P1 Up", PAD::ControllerBindingType::Button, false},
|
||||
{"DdrP1FootRight", "P1 Right", PAD::ControllerBindingType::Button, false},
|
||||
|
||||
{"DdrP2Start", "P2 Start", PAD::ControllerBindingType::Button, false},
|
||||
{"DdrP2SelectL", "P2 Select L", PAD::ControllerBindingType::Button, false},
|
||||
{"DdrP2SelectR", "P2 Select R", PAD::ControllerBindingType::Button, false},
|
||||
{"DdrP2FootLeft", "P2 Left", PAD::ControllerBindingType::Button, false},
|
||||
{"DdrP2FootDown", "P2 Down", PAD::ControllerBindingType::Button, false},
|
||||
{"DdrP2FootUp", "P2 Up", PAD::ControllerBindingType::Button, false},
|
||||
{"DdrP2FootRight", "P2 Right", PAD::ControllerBindingType::Button, false},
|
||||
};
|
||||
|
||||
static const Python2BindingInfo s_python2_thrilldrive_binds[] = {
|
||||
{"ThrillDriveStart", "Start", PAD::ControllerBindingType::Button, false},
|
||||
{"ThrillDriveGearUp", "Gear Up", PAD::ControllerBindingType::Button, false},
|
||||
{"ThrillDriveGearDown", "Gear Down", PAD::ControllerBindingType::Button, false},
|
||||
{"ThrillDriveWheelAnalog", "Wheel", PAD::ControllerBindingType::Axis, false},
|
||||
{"ThrillDriveWheelLeft", "Wheel Left", PAD::ControllerBindingType::Button, false},
|
||||
{"ThrillDriveWheelRight", "Wheel Right", PAD::ControllerBindingType::Button, false},
|
||||
{"ThrillDriveAccelAnalog", "Acceleration", PAD::ControllerBindingType::HalfAxis, false},
|
||||
{"ThrillDriveAccel", "Acceleration", PAD::ControllerBindingType::Button, false},
|
||||
{"ThrillDriveBrake", "Brake", PAD::ControllerBindingType::Button, false},
|
||||
{"ThrillDriveBrakeAnalog", "Brake", PAD::ControllerBindingType::HalfAxis, false},
|
||||
{"ThrillDriveSeatbelt", "Seatbelt", PAD::ControllerBindingType::Button, false},
|
||||
{"ThrillDriveSeatbeltMotor", "Seatbelt", PAD::ControllerBindingType::Motor, false},
|
||||
{"ThrillDriveWheelMotor", "Wheel", PAD::ControllerBindingType::Motor, false},
|
||||
};
|
||||
|
||||
static const Python2BindingInfo s_python2_dance864_binds[] = {
|
||||
{"Dance864P1Start", "P1 Start", PAD::ControllerBindingType::Button, false},
|
||||
{"Dance864P1Left", "P1 Select L", PAD::ControllerBindingType::Button, false},
|
||||
{"Dance864P1Right", "P1 Select R", PAD::ControllerBindingType::Button, false},
|
||||
{"Dance864P1PadLeft", "P1 Left", PAD::ControllerBindingType::Button, false},
|
||||
{"Dance864P1PadCenter", "P1 Center", PAD::ControllerBindingType::Button, false},
|
||||
{"Dance864P1PadRight", "P1 Right", PAD::ControllerBindingType::Button, false},
|
||||
|
||||
{"Dance864P2Start", "P2 Start", PAD::ControllerBindingType::Button, false},
|
||||
{"Dance864P2Left", "P2 Select L", PAD::ControllerBindingType::Button, false},
|
||||
{"Dance864P2Right", "P2 Select R", PAD::ControllerBindingType::Button, false},
|
||||
{"Dance864P2PadLeft", "P2 Left", PAD::ControllerBindingType::Button, false},
|
||||
{"Dance864P2PadCenter", "P2 Center", PAD::ControllerBindingType::Button, false},
|
||||
{"Dance864P2PadRight", "P2 Right", PAD::ControllerBindingType::Button, false},
|
||||
};
|
||||
|
||||
static const Python2BindingInfo s_python2_toysmarch_binds[] = {
|
||||
{"ToysMarchP1Start", "P1 Start", PAD::ControllerBindingType::Button, false},
|
||||
{"ToysMarchP1SelectL", "P1 Select L", PAD::ControllerBindingType::Button, false},
|
||||
{"ToysMarchP1SelectR", "P1 Select R", PAD::ControllerBindingType::Button, false},
|
||||
{"ToysMarchP1DrumL", "P1 Drum L", PAD::ControllerBindingType::Button, false},
|
||||
{"ToysMarchP1DrumR", "P1 Drum R", PAD::ControllerBindingType::Button, false},
|
||||
{"ToysMarchP1Cymbal", "P1 Cymbal", PAD::ControllerBindingType::Button, false},
|
||||
|
||||
{"ToysMarchP2Start", "P2 Start", PAD::ControllerBindingType::Button, false},
|
||||
{"ToysMarchP2SelectL", "P2 Select L", PAD::ControllerBindingType::Button, false},
|
||||
{"ToysMarchP2SelectR", "P2 Select R", PAD::ControllerBindingType::Button, false},
|
||||
{"ToysMarchP2DrumL", "P2 Drum L", PAD::ControllerBindingType::Button, false},
|
||||
{"ToysMarchP2DrumR", "P2 Drum R", PAD::ControllerBindingType::Button, false},
|
||||
{"ToysMarchP2Cymbal", "P2 Cymbal", PAD::ControllerBindingType::Button, false},
|
||||
};
|
||||
|
||||
static const Python2BindingInfo s_python2_icca_binds[] = {
|
||||
{"KeypadP1_0", "P1 Keypad 0", PAD::ControllerBindingType::Button, false},
|
||||
{"KeypadP1_1", "P1 Keypad 1", PAD::ControllerBindingType::Button, false},
|
||||
{"KeypadP1_2", "P1 Keypad 2", PAD::ControllerBindingType::Button, false},
|
||||
{"KeypadP1_3", "P1 Keypad 3", PAD::ControllerBindingType::Button, false},
|
||||
{"KeypadP1_4", "P1 Keypad 4", PAD::ControllerBindingType::Button, false},
|
||||
{"KeypadP1_5", "P1 Keypad 5", PAD::ControllerBindingType::Button, false},
|
||||
{"KeypadP1_6", "P1 Keypad 6", PAD::ControllerBindingType::Button, false},
|
||||
{"KeypadP1_7", "P1 Keypad 7", PAD::ControllerBindingType::Button, false},
|
||||
{"KeypadP1_8", "P1 Keypad 8", PAD::ControllerBindingType::Button, false},
|
||||
{"KeypadP1_9", "P1 Keypad 9", PAD::ControllerBindingType::Button, false},
|
||||
{"KeypadP1_00", "P1 Keypad 00", PAD::ControllerBindingType::Button, false},
|
||||
{"KeypadP1InsertEject", "P1 Insert/Eject Card", PAD::ControllerBindingType::Button, false},
|
||||
|
||||
{"KeypadP2_0", "P2 Keypad 0", PAD::ControllerBindingType::Button, false},
|
||||
{"KeypadP2_1", "P2 Keypad 1", PAD::ControllerBindingType::Button, false},
|
||||
{"KeypadP2_2", "P2 Keypad 2", PAD::ControllerBindingType::Button, false},
|
||||
{"KeypadP2_3", "P2 Keypad 3", PAD::ControllerBindingType::Button, false},
|
||||
{"KeypadP2_4", "P2 Keypad 4", PAD::ControllerBindingType::Button, false},
|
||||
{"KeypadP2_5", "P2 Keypad 5", PAD::ControllerBindingType::Button, false},
|
||||
{"KeypadP2_6", "P2 Keypad 6", PAD::ControllerBindingType::Button, false},
|
||||
{"KeypadP2_7", "P2 Keypad 7", PAD::ControllerBindingType::Button, false},
|
||||
{"KeypadP2_8", "P2 Keypad 8", PAD::ControllerBindingType::Button, false},
|
||||
{"KeypadP2_9", "P2 Keypad 9", PAD::ControllerBindingType::Button, false},
|
||||
{"KeypadP2_00", "P2 Keypad 00", PAD::ControllerBindingType::Button, false},
|
||||
{"KeypadP2InsertEject", "P2 Insert/Eject Card", PAD::ControllerBindingType::Button, false},
|
||||
};
|
||||
|
||||
static const Python2SystemInfo s_python2_system_info[] = {
|
||||
{"All", nullptr, 0},
|
||||
{"System", s_python2_system_binds, std::size(s_python2_system_binds)},
|
||||
{"Dance 86.4", s_python2_dance864_binds, std::size(s_python2_dance864_binds)},
|
||||
{"Dance Dance Revolution", s_python2_ddr_binds, std::size(s_python2_ddr_binds)},
|
||||
{"Drummania", s_python2_drummania_binds, std::size(s_python2_drummania_binds)},
|
||||
{"Guitar Freaks", s_python2_guitarfreaks_binds, std::size(s_python2_guitarfreaks_binds)},
|
||||
{"Thrill Drive", s_python2_thrilldrive_binds, std::size(s_python2_thrilldrive_binds)},
|
||||
{"Toy's March", s_python2_toysmarch_binds, std::size(s_python2_toysmarch_binds)},
|
||||
{"Card Reader", s_python2_icca_binds, std::size(s_python2_icca_binds)},
|
||||
};
|
||||
|
||||
|
||||
namespace Python2QtInputManager
|
||||
{
|
||||
std::vector<Python2KeyMapping> GetCurrentMappings();
|
||||
std::vector<Python2KeyMapping> GetMappingsByInputKey(std::string keyBindStr);
|
||||
|
||||
bool AddNewBinding(std::string full_key, std::string new_binding, double analogDeadzone, double analogSensitivity, double motorScale);
|
||||
void RemoveMappingByUniqueId(uint32_t uniqueId);
|
||||
|
||||
void LoadMapping();
|
||||
}
|
|
@ -1,18 +1,3 @@
|
|||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2020 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "PrecompiledHeader.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
@ -105,13 +90,8 @@ namespace usb_python2
|
|||
{
|
||||
const auto selectedIdx = dialog.GetSelectedGame();
|
||||
|
||||
#ifdef _WIN32
|
||||
std::wstring selectedGameEntry = config.devListGroups[selectedIdx].ToStdWstring();
|
||||
SaveSetting<std::wstring>(Python2Device::TypeName(), config.port, "python2", N_DEVICE, selectedGameEntry);
|
||||
#else
|
||||
std::string selectedGameEntry = config.devListGroups[selectedIdx].ToStdString();
|
||||
SaveSetting<std::string>(Python2Device::TypeName(), config.port, "python2", N_DEVICE, selectedGameEntry);
|
||||
#endif
|
||||
SaveSetting(Python2Device::TypeName(), config.port, "python2", N_DEVICE, selectedGameEntry);
|
||||
}
|
||||
|
||||
paused_core.AllowResume();
|
|
@ -2,10 +2,12 @@
|
|||
#include "USB/USB.h"
|
||||
#include "usb-python2-btools.h"
|
||||
|
||||
#ifndef PCSX2_CORE
|
||||
#include <wx/fileconf.h>
|
||||
#include "gui/AppConfig.h"
|
||||
#include "gui/StringHelpers.h"
|
||||
#include "USB/shared/inifile_usb.h"
|
||||
#endif
|
||||
|
||||
#include <algorithm>
|
||||
#include <chrono>
|
||||
|
@ -131,53 +133,57 @@ namespace usb_python2
|
|||
return 0;
|
||||
}
|
||||
|
||||
bool BToolsInput::GetKeyState(std::wstring keybind)
|
||||
bool BToolsInput::GetKeyState(TSTDSTRING keybind)
|
||||
{
|
||||
if (keybind == L"Test")
|
||||
if (keybind == "Test")
|
||||
return ddrioState & (1 << DDR_TEST);
|
||||
if (keybind == L"Service")
|
||||
if (keybind == "Service")
|
||||
return ddrioState & (1 << DDR_SERVICE);
|
||||
if (keybind == L"Coin1")
|
||||
if (keybind == "Coin1")
|
||||
return ddrioState & (1 << DDR_COIN);
|
||||
|
||||
if (keybind == L"DdrP1Start")
|
||||
if (keybind == "DdrP1Start")
|
||||
return ddrioState & (1 << DDR_P1_START);
|
||||
if (keybind == L"DdrP1SelectL")
|
||||
if (keybind == "DdrP1Select")
|
||||
return ddrioState & (1 << DDR_P1_MENU_LEFT);
|
||||
if (keybind == L"DdrP1SelectR")
|
||||
if (keybind == "DdrP1SelectR")
|
||||
return ddrioState & (1 << DDR_P1_MENU_RIGHT);
|
||||
|
||||
if (keybind == L"DdrP1FootUp")
|
||||
if (keybind == "DdrP1FootUp")
|
||||
return ddrioState & (1 << DDR_P1_UP);
|
||||
if (keybind == L"DdrP1FootDown")
|
||||
if (keybind == "DdrP1FootDown")
|
||||
return ddrioState & (1 << DDR_P1_DOWN);
|
||||
if (keybind == L"DdrP1FootLeft")
|
||||
if (keybind == "DdrP1FootLeft")
|
||||
return ddrioState & (1 << DDR_P1_LEFT);
|
||||
if (keybind == L"DdrP1FootRight")
|
||||
if (keybind == "DdrP1FootRight")
|
||||
return ddrioState & (1 << DDR_P1_RIGHT);
|
||||
|
||||
if (keybind == L"DdrP2Start")
|
||||
if (keybind == "DdrP2Start")
|
||||
return ddrioState & (1 << DDR_P2_START);
|
||||
if (keybind == L"DdrP2SelectL")
|
||||
if (keybind == "DdrP2Select")
|
||||
return ddrioState & (1 << DDR_P2_MENU_LEFT);
|
||||
if (keybind == L"DdrP2SelectR")
|
||||
if (keybind == "DdrP2SelectR")
|
||||
return ddrioState & (1 << DDR_P2_MENU_RIGHT);
|
||||
|
||||
if (keybind == L"DdrP2FootUp")
|
||||
if (keybind == "DdrP2FootUp")
|
||||
return ddrioState & (1 << DDR_P2_UP);
|
||||
if (keybind == L"DdrP2FootDown")
|
||||
if (keybind == "DdrP2FootDown")
|
||||
return ddrioState & (1 << DDR_P2_DOWN);
|
||||
if (keybind == L"DdrP2FootLeft")
|
||||
if (keybind == "DdrP2FootLeft")
|
||||
return ddrioState & (1 << DDR_P2_LEFT);
|
||||
if (keybind == L"DdrP2FootRight")
|
||||
if (keybind == "DdrP2FootRight")
|
||||
return ddrioState & (1 << DDR_P2_RIGHT);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifndef PCSX2_CORE
|
||||
void ConfigurePython2Btools(Python2DlgConfig& config);
|
||||
#endif
|
||||
|
||||
int BToolsInput::Configure(int port, const char* dev_type, void* data)
|
||||
{
|
||||
#ifndef PCSX2_CORE
|
||||
std::vector<wxString> devList;
|
||||
std::vector<wxString> devListGroups;
|
||||
|
||||
|
@ -191,11 +197,11 @@ namespace usb_python2
|
|||
for (auto itr = sections.begin(); itr != sections.end(); itr++)
|
||||
{
|
||||
auto groupName = (*itr)->GetSectionName();
|
||||
if (groupName.find(L"GameEntry ") == 0)
|
||||
if (groupName.find(TEXT("GameEntry ")) == 0)
|
||||
{
|
||||
devListGroups.push_back(wxString(groupName));
|
||||
|
||||
auto gameName = (*itr)->GetKeyValue(L"Name");
|
||||
auto gameName = (*itr)->GetKeyValue(TEXT("Name"));
|
||||
if (!gameName.empty())
|
||||
devList.push_back(wxString(gameName));
|
||||
}
|
||||
|
@ -203,6 +209,7 @@ namespace usb_python2
|
|||
|
||||
Python2DlgConfig config(port, dev_type, devList, devListGroups);
|
||||
ConfigurePython2Btools(config);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -14,6 +14,7 @@ namespace usb_python2
|
|||
{
|
||||
static const char* APINAME = "btools";
|
||||
|
||||
#ifndef PCSX2_CORE
|
||||
struct Python2DlgConfig
|
||||
{
|
||||
int port;
|
||||
|
@ -30,6 +31,7 @@ namespace usb_python2
|
|||
{
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
class BToolsInput : public Python2Input
|
||||
{
|
||||
|
@ -58,12 +60,11 @@ namespace usb_python2
|
|||
|
||||
bool isPassthrough() override { return false; }
|
||||
|
||||
void UpdateKeyStates(std::wstring keybind) override {}
|
||||
bool GetKeyState(std::wstring keybind);
|
||||
bool GetKeyStateOneShot(std::wstring keybind) override { return false; }
|
||||
double GetKeyStateAnalog(std::wstring keybind) override { return 0; }
|
||||
bool IsKeybindAvailable(std::wstring keybind) override { return false; }
|
||||
bool IsAnalogKeybindAvailable(std::wstring keybind) override { return false; }
|
||||
void UpdateKeyStates(TSTDSTRING keybind) override {}
|
||||
bool GetKeyState(TSTDSTRING keybind);
|
||||
bool GetKeyStateOneShot(TSTDSTRING keybind) override { return false; }
|
||||
double GetKeyStateAnalog(TSTDSTRING keybind) override { return 0; }
|
||||
bool IsAnalogKeybindAvailable(TSTDSTRING keybind) override { return false; }
|
||||
|
||||
bool set_p3io_lights(uint8_t stateFromGame);
|
||||
|
|
@ -0,0 +1,195 @@
|
|||
#include "PrecompiledHeader.h"
|
||||
#include "USB/USB.h"
|
||||
#include "usb-python2-native.h"
|
||||
|
||||
#include "pcsx2/HostSettings.h"
|
||||
#include "common/SettingsInterface.h"
|
||||
|
||||
#include "common/StringUtil.h"
|
||||
#include "PAD/Host/PAD.h"
|
||||
|
||||
#include "USB/usb-python2/inputs/Python2QtInputManager.h"
|
||||
|
||||
namespace usb_python2
|
||||
{
|
||||
namespace native
|
||||
{
|
||||
InputInterceptHook::CallbackResult NativeInput::ParseInput(InputBindingKey key, float value)
|
||||
{
|
||||
// TODO: Fix sticky input issue. Hold button, tab out, then tab back in. The button will be held until it's pressed again.
|
||||
|
||||
std::map<std::string, int> updatedInputState;
|
||||
auto keyBindStr = InputManager::ConvertInputBindingKeyToString(key);
|
||||
|
||||
if (key.source_subtype != InputSubclass::PointerAxis && key.source_subtype != InputSubclass::ControllerAxis)
|
||||
printf("Pressed button! %d %f %s\n", key.data, value, keyBindStr.c_str());
|
||||
|
||||
for (auto mappedKey : Python2QtInputManager::GetMappingsByInputKey(keyBindStr))
|
||||
{
|
||||
printf("\t%s %d\n", mappedKey.keybind.c_str(), mappedKey.isOneshot);
|
||||
|
||||
if (key.source_type == InputSourceType::Keyboard)
|
||||
{
|
||||
if (value == 0)
|
||||
{
|
||||
if (updatedInputState.find(mappedKey.keybind) == updatedInputState.end() || updatedInputState[mappedKey.keybind] == 0) // Only reset value if it wasn't set by a button already
|
||||
updatedInputState[mappedKey.keybind] = keyboardButtonIsPressed[keyBindStr] ? 2 : 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!keyboardButtonIsPressed[keyBindStr])
|
||||
updatedInputState[mappedKey.keybind] = 1 | (mappedKey.isOneshot ? 0x80 : 0);
|
||||
}
|
||||
}
|
||||
else if (key.source_subtype == InputSubclass::ControllerAxis || key.source_subtype == InputSubclass::PointerAxis)
|
||||
{
|
||||
currentInputStateAnalog[mappedKey.keybind] = value;
|
||||
}
|
||||
else if (key.source_subtype == InputSubclass::ControllerButton || key.source_subtype == InputSubclass::PointerButton)
|
||||
{
|
||||
if (value == 0)
|
||||
{
|
||||
if (updatedInputState.find(mappedKey.keybind) == updatedInputState.end() || updatedInputState[mappedKey.keybind] == 0) // Only reset value if it wasn't set by a button already
|
||||
updatedInputState[mappedKey.keybind] = gamepadButtonIsPressed[key.data | ((int)key.source_subtype << 28)] ? 2 : 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!gamepadButtonIsPressed[key.data | ((int)key.source_subtype << 28)])
|
||||
updatedInputState[mappedKey.keybind] = 1 | (mappedKey.isOneshot ? 0x80 : 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (key.source_type == InputSourceType::Keyboard)
|
||||
{
|
||||
keyboardButtonIsPressed[keyBindStr] = value != 0;
|
||||
}
|
||||
else if (key.source_subtype == InputSubclass::ControllerButton || key.source_subtype == InputSubclass::PointerButton)
|
||||
{
|
||||
gamepadButtonIsPressed[key.data | ((int)key.source_subtype << 28)] = value != 0;
|
||||
}
|
||||
|
||||
for (auto& k : updatedInputState)
|
||||
{
|
||||
currentInputStatePad[k.first] = k.second;
|
||||
|
||||
if ((k.second & 3) == 1)
|
||||
{
|
||||
keyStateUpdates[k.first].push_back({std::chrono::steady_clock::now(), true});
|
||||
|
||||
if (k.second & 0x80)
|
||||
{
|
||||
// Oneshot
|
||||
keyStateUpdates[k.first].push_back({std::chrono::steady_clock::now(), false});
|
||||
}
|
||||
}
|
||||
else if ((k.second & 3) == 2)
|
||||
{
|
||||
keyStateUpdates[k.first].push_back({std::chrono::steady_clock::now(), false});
|
||||
}
|
||||
}
|
||||
|
||||
return InputInterceptHook::CallbackResult::ContinueProcessingEvent;
|
||||
}
|
||||
|
||||
int NativeInput::Open()
|
||||
{
|
||||
Reset();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int NativeInput::Close()
|
||||
{
|
||||
InputManager::RemoveHook();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int NativeInput::Reset()
|
||||
{
|
||||
Close();
|
||||
|
||||
currentInputStateAnalog.clear();
|
||||
currentKeyStates.clear();
|
||||
keyStateUpdates.clear();
|
||||
|
||||
keyboardButtonIsPressed.clear();
|
||||
gamepadButtonIsPressed.clear();
|
||||
|
||||
Python2QtInputManager::LoadMapping();
|
||||
|
||||
InputManager::SetHook([this](InputBindingKey key, float value) {
|
||||
return this->ParseInput(key, value);
|
||||
});
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void NativeInput::UpdateKeyStates(TSTDSTRING keybind)
|
||||
{
|
||||
if (!InputManager::HasHook()) {
|
||||
// Input configuration menu also uses hooks so the I/O gets overwritten.
|
||||
// If ParseInput is ever called while there is no hook set, it most likely means that the user just changed keybinds.
|
||||
Reset();
|
||||
}
|
||||
|
||||
const auto currentTimestamp = std::chrono::steady_clock::now();
|
||||
while (keyStateUpdates[keybind].size() > 0)
|
||||
{
|
||||
auto curState = keyStateUpdates[keybind].front();
|
||||
keyStateUpdates[keybind].pop_front();
|
||||
|
||||
// Remove stale inputs that occur during times where the game can't query for inputs.
|
||||
// The timeout value is based on what felt ok to me so just adjust as needed.
|
||||
const std::chrono::duration<double, std::milli> timestampDiff = currentTimestamp - curState.timestamp;
|
||||
if (timestampDiff.count() > 50)
|
||||
{
|
||||
Console.WriteLn("Dropping delayed input... %s %ld ms late", keybind.c_str(), timestampDiff.count());
|
||||
continue;
|
||||
}
|
||||
|
||||
Console.WriteLn("Keystate update %s %d", keybind.c_str(), curState.state);
|
||||
currentKeyStates[keybind] = curState.state;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool NativeInput::GetKeyState(TSTDSTRING keybind)
|
||||
{
|
||||
UpdateKeyStates(keybind);
|
||||
|
||||
auto it = currentKeyStates.find(keybind);
|
||||
if (it != currentKeyStates.end())
|
||||
return it->second;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NativeInput::GetKeyStateOneShot(TSTDSTRING keybind)
|
||||
{
|
||||
UpdateKeyStates(keybind);
|
||||
|
||||
auto isPressed = false;
|
||||
auto it = currentKeyStates.find(keybind);
|
||||
if (it != currentKeyStates.end())
|
||||
{
|
||||
isPressed = it->second;
|
||||
it->second = false;
|
||||
}
|
||||
|
||||
return isPressed;
|
||||
}
|
||||
|
||||
double NativeInput::GetKeyStateAnalog(TSTDSTRING keybind)
|
||||
{
|
||||
const auto it = currentInputStateAnalog.find(keybind);
|
||||
if (it == currentInputStateAnalog.end())
|
||||
return 0;
|
||||
return it->second;
|
||||
}
|
||||
|
||||
bool NativeInput::IsAnalogKeybindAvailable(TSTDSTRING keybind)
|
||||
{
|
||||
return currentInputStateAnalog.find(keybind) != currentInputStateAnalog.end();
|
||||
}
|
||||
} // namespace native
|
||||
} // namespace usb_python2
|
|
@ -0,0 +1,93 @@
|
|||
#ifndef USBPYTHON2NATIVE_H
|
||||
#define USBPYTHON2NATIVE_H
|
||||
#include <thread>
|
||||
#include <array>
|
||||
#include <atomic>
|
||||
#include <chrono>
|
||||
#include "Frontend/InputManager.h"
|
||||
#include "USB/usb-python2/python2proxy.h"
|
||||
#include "USB/usb-python2/usb-python2.h"
|
||||
|
||||
namespace usb_python2
|
||||
{
|
||||
namespace native
|
||||
{
|
||||
static const char* APINAME = "native";
|
||||
|
||||
struct InputStateUpdate
|
||||
{
|
||||
std::chrono::steady_clock::time_point timestamp;
|
||||
bool state;
|
||||
};
|
||||
|
||||
class NativeInput : public Python2Input
|
||||
{
|
||||
public:
|
||||
NativeInput(int port, const char* dev_type)
|
||||
: Python2Input(port, dev_type)
|
||||
{
|
||||
}
|
||||
~NativeInput()
|
||||
{
|
||||
Close();
|
||||
}
|
||||
int Open() override;
|
||||
int Close() override;
|
||||
int ReadPacket(std::vector<uint8_t>& data) override { return 0; }
|
||||
int WritePacket(const std::vector<uint8_t>& data) override { return 0; }
|
||||
void ReadIo(std::vector<uint8_t>& data) override {}
|
||||
int Reset() override;
|
||||
|
||||
bool isPassthrough() override { return false; }
|
||||
|
||||
InputInterceptHook::CallbackResult ParseInput(InputBindingKey key, float value);
|
||||
|
||||
static const TCHAR* Name()
|
||||
{
|
||||
return TEXT("Raw Input");
|
||||
}
|
||||
|
||||
void UpdateKeyStates(TSTDSTRING keybind) override;
|
||||
bool GetKeyState(TSTDSTRING keybind) override;
|
||||
bool GetKeyStateOneShot(TSTDSTRING keybind) override;
|
||||
double GetKeyStateAnalog(TSTDSTRING keybind) override;
|
||||
bool IsAnalogKeybindAvailable(TSTDSTRING keybind) override;
|
||||
|
||||
static int Configure(int port, const char* dev_type, void* data) { return 0; }
|
||||
|
||||
protected:
|
||||
private:
|
||||
};
|
||||
|
||||
enum KeybindType
|
||||
{
|
||||
KeybindType_Button = 0,
|
||||
KeybindType_Axis,
|
||||
KeybindType_Hat,
|
||||
KeybindType_Keyboard,
|
||||
KeybindType_Motor,
|
||||
};
|
||||
|
||||
struct KeyMapping
|
||||
{
|
||||
TSTDSTRING inputKey;
|
||||
TSTDSTRING keybind;
|
||||
double analogDeadzone;
|
||||
double analogSensitivity;
|
||||
double motorScale;
|
||||
bool isOneshot; // Immediately trigger an off after on
|
||||
};
|
||||
|
||||
static std::map<TSTDSTRING, std::deque<InputStateUpdate>> keyStateUpdates;
|
||||
static std::map<TSTDSTRING, bool> isOneshotState;
|
||||
static std::map<TSTDSTRING, bool> currentKeyStates;
|
||||
static std::map<TSTDSTRING, int> currentInputStateKeyboard;
|
||||
static std::map<TSTDSTRING, int> currentInputStatePad;
|
||||
static std::map<TSTDSTRING, double> currentInputStateAnalog;
|
||||
|
||||
static std::map<TSTDSTRING, bool> keyboardButtonIsPressed;
|
||||
static std::map<uint32_t, bool> gamepadButtonIsPressed;
|
||||
|
||||
} // namespace native
|
||||
} // namespace usb_python2
|
||||
#endif
|
|
@ -2,10 +2,12 @@
|
|||
#include "USB/USB.h"
|
||||
#include "usb-python2-passthrough.h"
|
||||
|
||||
#ifndef PCSX2_CORE
|
||||
#include <wx/fileconf.h>
|
||||
#include "gui/AppConfig.h"
|
||||
#include "gui/StringHelpers.h"
|
||||
#include "USB/shared/inifile_usb.h"
|
||||
#endif
|
||||
|
||||
#include <algorithm>
|
||||
#include <chrono>
|
||||
|
@ -102,34 +104,39 @@ namespace usb_python2
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifndef PCSX2_CORE
|
||||
void ConfigurePython2Passthrough(Python2DlgConfig& config);
|
||||
#endif
|
||||
|
||||
int PassthroughInput::Configure(int port, const char* dev_type, void* data)
|
||||
{
|
||||
#ifndef PCSX2_CORE
|
||||
std::vector<wxString> devList;
|
||||
std::vector<wxString> devListGroups;
|
||||
|
||||
const wxString iniPath = StringUtil::UTF8StringToWxString(Path::Combine(EmuFolders::Settings, "Python2.ini"));
|
||||
CIniFile ciniFile;
|
||||
CIniFileA ciniFile;
|
||||
|
||||
if (!ciniFile.Load(iniPath.ToStdWstring()))
|
||||
if (!ciniFile.Load(iniPath.ToStdString()))
|
||||
return 0;
|
||||
|
||||
auto sections = ciniFile.GetSections();
|
||||
for (auto itr = sections.begin(); itr != sections.end(); itr++)
|
||||
{
|
||||
auto groupName = (*itr)->GetSectionName();
|
||||
if (groupName.find(L"GameEntry ") == 0)
|
||||
if (groupName.find("GameEntry ") == 0)
|
||||
{
|
||||
devListGroups.push_back(wxString(groupName));
|
||||
devListGroups.push_back(StringUtil::UTF8StringToWxString(groupName));
|
||||
|
||||
auto gameName = (*itr)->GetKeyValue(L"Name");
|
||||
auto gameName = (*itr)->GetKeyValue("Name");
|
||||
if (!gameName.empty())
|
||||
devList.push_back(wxString(gameName));
|
||||
devList.push_back(StringUtil::UTF8StringToWxString(gameName));
|
||||
}
|
||||
}
|
||||
|
||||
Python2DlgConfig config(port, dev_type, devList, devListGroups);
|
||||
ConfigurePython2Passthrough(config);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -5,9 +5,8 @@
|
|||
#include <atomic>
|
||||
#include "USB/usb-python2/python2proxy.h"
|
||||
#include "USB/usb-python2/usb-python2.h"
|
||||
#include "USB/readerwriterqueue/readerwriterqueue.h"
|
||||
|
||||
#include "libusb-1.0/libusb.h"
|
||||
#include <libusb.h>
|
||||
|
||||
|
||||
namespace usb_python2
|
||||
|
@ -16,6 +15,7 @@ namespace usb_python2
|
|||
{
|
||||
static const char* APINAME = "passthrough";
|
||||
|
||||
#ifndef PCSX2_CORE
|
||||
struct Python2DlgConfig
|
||||
{
|
||||
int port;
|
||||
|
@ -32,6 +32,7 @@ namespace usb_python2
|
|||
{
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
class PassthroughInput : public Python2Input
|
||||
{
|
||||
|
@ -58,12 +59,11 @@ namespace usb_python2
|
|||
|
||||
bool isPassthrough() override { return true; }
|
||||
|
||||
void UpdateKeyStates(std::wstring keybind) override {}
|
||||
bool GetKeyState(std::wstring keybind) override { return false; }
|
||||
bool GetKeyStateOneShot(std::wstring keybind) override { return false; }
|
||||
double GetKeyStateAnalog(std::wstring keybind) override { return 0; }
|
||||
bool IsKeybindAvailable(std::wstring keybind) override { return false; }
|
||||
bool IsAnalogKeybindAvailable(std::wstring keybind) override { return false; }
|
||||
void UpdateKeyStates(TSTDSTRING keybind) override {}
|
||||
bool GetKeyState(TSTDSTRING keybind) override { return false; }
|
||||
bool GetKeyStateOneShot(TSTDSTRING keybind) override { return false; }
|
||||
double GetKeyStateAnalog(TSTDSTRING keybind) override { return 0; }
|
||||
bool IsAnalogKeybindAvailable(TSTDSTRING keybind) override { return false; }
|
||||
|
||||
static const TCHAR* Name()
|
||||
{
|
|
@ -1,20 +1,3 @@
|
|||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2020 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// Used OBS as example
|
||||
|
||||
#include "PrecompiledHeader.h"
|
||||
#include <windows.h>
|
||||
|
||||
|
@ -31,7 +14,7 @@
|
|||
|
||||
#include <windowsx.h>
|
||||
|
||||
#define MSG_PRESS_ESC(wnd) SendDlgItemMessageW(wnd, IDC_STATIC_CAP, WM_SETTEXT, 0, (LPARAM)L"Capturing, press ESC to cancel")
|
||||
#define MSG_PRESS_ESC(wnd) SendDlgItemMessageW(wnd, IDC_STATIC_CAP, WM_SETTEXT, 0, (LPARAM)TEXT("Capturing, press ESC to cancel"))
|
||||
|
||||
namespace usb_python2
|
||||
{
|
||||
|
@ -58,7 +41,7 @@ namespace usb_python2
|
|||
return std::wstring(tmp);
|
||||
}
|
||||
|
||||
inline bool MapExists(const MapVector& maps, const std::wstring& hid)
|
||||
inline bool MapExists(const MapVector& maps, const TSTDSTRING& hid)
|
||||
{
|
||||
for (auto& it : maps)
|
||||
if (!it.hidPath.compare(hid))
|
||||
|
@ -76,7 +59,7 @@ namespace usb_python2
|
|||
int v = 0;
|
||||
for (int j = 0; j < 25; j++)
|
||||
{
|
||||
std::wstring hid, tmp;
|
||||
TSTDSTRING hid, tmp;
|
||||
|
||||
if (LoadSetting(dev_type, j, "RAW DEVICE", TEXT("HID"), hid) && !hid.empty() && !MapExists(maps, hid))
|
||||
{
|
||||
|
@ -96,15 +79,15 @@ namespace usb_python2
|
|||
{
|
||||
auto idx = tmp.find_first_of(L',');
|
||||
|
||||
if (idx == std::wstring::npos)
|
||||
if (idx == std::string::npos)
|
||||
idx = tmp.size();
|
||||
|
||||
auto substr = std::wstring(tmp.begin(), tmp.begin() + idx);
|
||||
auto substr = std::string(tmp.begin(), tmp.begin() + idx);
|
||||
|
||||
uint32_t buttonType = 0;
|
||||
uint32_t value = 0;
|
||||
int isOneshot = 0;
|
||||
swscanf_s(substr.c_str(), L"%02X|%08X|%d", &buttonType, &value, &isOneshot);
|
||||
sscanf_s(substr.c_str(), "%02X|%08X|%d", &buttonType, &value, &isOneshot);
|
||||
|
||||
KeyMapping keybindMapping = {
|
||||
uniqueKeybindIdx++,
|
||||
|
@ -139,7 +122,7 @@ namespace usb_python2
|
|||
{
|
||||
if (it.mappings.size() > 0)
|
||||
{
|
||||
SaveSetting<std::wstring>(dev_type, numDevice, "RAW DEVICE", TEXT("HID"), it.hidPath);
|
||||
SaveSetting(dev_type, numDevice, "RAW DEVICE", TEXT("HID"), it.hidPath);
|
||||
|
||||
std::map<int, std::vector<KeyMapping>> mapByKeybind;
|
||||
|
||||
|
@ -148,20 +131,20 @@ namespace usb_python2
|
|||
|
||||
for (auto& bindIt : mapByKeybind)
|
||||
{
|
||||
std::wstring val;
|
||||
TSTDSTRING val;
|
||||
|
||||
for (auto& keymap : bindIt.second)
|
||||
{
|
||||
WCHAR tmp[255] = {0};
|
||||
swprintf_s(tmp, 255, L"%02X|%08X|%d", keymap.bindType, keymap.value, keymap.isOneshot);
|
||||
TCHAR tmp[255] = {0};
|
||||
swprintf_s(tmp, 255, TEXT("%02X|%08X|%d"), keymap.bindType, keymap.value, keymap.isOneshot);
|
||||
|
||||
if (val.size() > 0)
|
||||
val.append(L",");
|
||||
val.append(TEXT(","));
|
||||
|
||||
val.append(std::wstring(tmp));
|
||||
val.append(TSTDSTRING(tmp));
|
||||
}
|
||||
|
||||
SaveSetting<std::wstring>(dev_type, numDevice, "RAW DEVICE", buttonLabelList[bindIt.first], val.c_str());
|
||||
SaveSetting(dev_type, numDevice, "RAW DEVICE", buttonLabelList[bindIt.first], val.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -285,7 +268,7 @@ namespace usb_python2
|
|||
UINT nameSize = 1024;
|
||||
UINT pSize;
|
||||
RID_DEVICE_INFO devInfo;
|
||||
std::wstring devName;
|
||||
TSTDSTRING devName;
|
||||
//DevInfo_t mapDevInfo;
|
||||
Mappings* mapping = NULL;
|
||||
TCHAR buf[256];
|
||||
|
@ -534,7 +517,7 @@ namespace usb_python2
|
|||
LoadMappings(Python2Device::TypeName(), mapVector);
|
||||
|
||||
SendDlgItemMessage(hW, IDC_COMBO1, CB_RESETCONTENT, 0, 0);
|
||||
std::wstring selectedDevice;
|
||||
TSTDSTRING selectedDevice;
|
||||
LoadSetting(Python2Device::TypeName(), cfg->port, APINAME, N_DEVICE, selectedDevice);
|
||||
for (auto i = 0; i != cfg->devList.size(); i++)
|
||||
{
|
||||
|
@ -565,7 +548,7 @@ namespace usb_python2
|
|||
|
||||
// Save machine configuration selection
|
||||
auto deviceIdx = ComboBox_GetCurSel(GetDlgItem(hW, IDC_COMBO1));
|
||||
if (!SaveSetting<std::wstring>(Python2Device::TypeName(), cfg->port, APINAME, N_DEVICE, cfg->devListGroups[deviceIdx]))
|
||||
if (!SaveSetting(Python2Device::TypeName(), cfg->port, APINAME, N_DEVICE, cfg->devListGroups[deviceIdx]))
|
||||
res = RESULT_FAILED;
|
||||
|
||||
SaveMappings(Python2Device::TypeName(), mapVector);
|
|
@ -1,35 +1,20 @@
|
|||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2020 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "PrecompiledHeader.h"
|
||||
#include "USB/USB.h"
|
||||
#include "USB/Win32/Config_usb.h"
|
||||
#include "usb-python2-raw.h"
|
||||
|
||||
#ifndef PCSX2_CORE
|
||||
#include <wx/fileconf.h>
|
||||
#include "gui/AppConfig.h"
|
||||
#include "gui/StringHelpers.h"
|
||||
#include "USB/shared/inifile_usb.h"
|
||||
|
||||
#include "DEV9/DEV9.h"
|
||||
#endif
|
||||
|
||||
namespace usb_python2
|
||||
{
|
||||
namespace raw
|
||||
{
|
||||
std::wstring getKeyLabel(const KeyMapping key);
|
||||
TSTDSTRING getKeyLabel(const KeyMapping key);
|
||||
|
||||
uint32_t axisDiff2[32]; //previous axes values
|
||||
bool axisPass22 = false;
|
||||
|
@ -47,14 +32,14 @@ namespace usb_python2
|
|||
TCHAR name[1024] = {0};
|
||||
UINT nameSize = 1024;
|
||||
RID_DEVICE_INFO devInfo = {0};
|
||||
std::wstring devName;
|
||||
TSTDSTRING devName;
|
||||
USHORT capsLength = 0;
|
||||
USAGE usage[32] = {0};
|
||||
Mappings* mapping = NULL;
|
||||
|
||||
std::vector<uint32_t> usageCountButtons(countof(usage));
|
||||
std::vector<uint32_t> usageCountHats(8);
|
||||
std::map<wchar_t*, int> updatedInputState;
|
||||
std::map<TCHAR*, int> updatedInputState;
|
||||
|
||||
auto iter = mappings.find(pRawInput->header.hDevice);
|
||||
if (iter != mappings.end())
|
||||
|
@ -197,8 +182,6 @@ namespace usb_python2
|
|||
|
||||
for (auto& k : updatedInputState)
|
||||
{
|
||||
currentInputStatePad[k.first] = k.second;
|
||||
|
||||
if ((k.second & 3) == 1)
|
||||
{
|
||||
keyStateUpdates[k.first].push_back({wxDateTime::UNow(), true});
|
||||
|
@ -275,8 +258,6 @@ namespace usb_python2
|
|||
Close();
|
||||
|
||||
mappings.clear();
|
||||
currentInputStateKeyboard.clear();
|
||||
currentInputStatePad.clear();
|
||||
currentInputStateAnalog.clear();
|
||||
currentKeyStates.clear();
|
||||
keyStateUpdates.clear();
|
||||
|
@ -286,7 +267,7 @@ namespace usb_python2
|
|||
|
||||
LoadMappings(mDevType, mapVector);
|
||||
|
||||
std::wstring selectedDevice;
|
||||
TSTDSTRING selectedDevice;
|
||||
LoadSetting(Python2Device::TypeName(), mPort, APINAME, N_DEVICE, selectedDevice);
|
||||
|
||||
shared::rawinput::RegisterCallback(this);
|
||||
|
@ -299,7 +280,7 @@ namespace usb_python2
|
|||
return 0;
|
||||
}
|
||||
|
||||
void RawInputPad::UpdateKeyStates(std::wstring keybind)
|
||||
void RawInputPad::UpdateKeyStates(TSTDSTRING keybind)
|
||||
{
|
||||
const auto currentTimestamp = wxDateTime::UNow();
|
||||
while (keyStateUpdates[keybind].size() > 0)
|
||||
|
@ -312,11 +293,11 @@ namespace usb_python2
|
|||
const auto timestampDiff = currentTimestamp - curState.timestamp;
|
||||
if (timestampDiff.GetMilliseconds() > 150)
|
||||
{
|
||||
//Console.WriteLn(L"Dropping delayed input... %s %ld ms late", keybind, timestampDiff);
|
||||
//Console.WriteLn("Dropping delayed input... %s %ld ms late", keybind, timestampDiff);
|
||||
continue;
|
||||
}
|
||||
|
||||
//Console.WriteLn(L"Keystate update %s %d", keybind, curState.state);
|
||||
//Console.WriteLn("Keystate update %s %d", keybind, curState.state);
|
||||
|
||||
currentKeyStates[keybind] = curState.state;
|
||||
|
||||
|
@ -324,7 +305,7 @@ namespace usb_python2
|
|||
}
|
||||
}
|
||||
|
||||
bool RawInputPad::GetKeyState(std::wstring keybind)
|
||||
bool RawInputPad::GetKeyState(TSTDSTRING keybind)
|
||||
{
|
||||
UpdateKeyStates(keybind);
|
||||
|
||||
|
@ -335,7 +316,7 @@ namespace usb_python2
|
|||
return false;
|
||||
}
|
||||
|
||||
bool RawInputPad::GetKeyStateOneShot(std::wstring keybind)
|
||||
bool RawInputPad::GetKeyStateOneShot(TSTDSTRING keybind)
|
||||
{
|
||||
UpdateKeyStates(keybind);
|
||||
|
||||
|
@ -350,7 +331,7 @@ namespace usb_python2
|
|||
return isPressed;
|
||||
}
|
||||
|
||||
double RawInputPad::GetKeyStateAnalog(std::wstring keybind)
|
||||
double RawInputPad::GetKeyStateAnalog(TSTDSTRING keybind)
|
||||
{
|
||||
const auto it = currentInputStateAnalog.find(keybind);
|
||||
if (it == currentInputStateAnalog.end())
|
||||
|
@ -358,28 +339,27 @@ namespace usb_python2
|
|||
return it->second;
|
||||
}
|
||||
|
||||
bool RawInputPad::IsKeybindAvailable(std::wstring keybind)
|
||||
{
|
||||
return currentInputStateKeyboard.find(keybind) != currentInputStateKeyboard.end() || currentInputStatePad.find(keybind) != currentInputStatePad.end();
|
||||
}
|
||||
|
||||
bool RawInputPad::IsAnalogKeybindAvailable(std::wstring keybind)
|
||||
bool RawInputPad::IsAnalogKeybindAvailable(TSTDSTRING keybind)
|
||||
{
|
||||
return currentInputStateAnalog.find(keybind) != currentInputStateAnalog.end();
|
||||
}
|
||||
|
||||
// ---------
|
||||
#ifndef PCSX2_CORE
|
||||
#include "python2-config-raw-res.h"
|
||||
|
||||
INT_PTR CALLBACK ConfigurePython2DlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||
#endif
|
||||
|
||||
int RawInputPad::Configure(int port, const char* dev_type, void* data)
|
||||
{
|
||||
#ifndef PCSX2_CORE
|
||||
Win32Handles* h = (Win32Handles*)data;
|
||||
INT_PTR res = RESULT_FAILED;
|
||||
if (shared::rawinput::Initialize(h->hWnd))
|
||||
{
|
||||
std::vector<std::wstring> devList;
|
||||
std::vector<std::wstring> devListGroups;
|
||||
std::vector<TSTDSTRING> devList;
|
||||
std::vector<TSTDSTRING> devListGroups;
|
||||
|
||||
const wxString iniPath = StringUtil::UTF8StringToWxString(Path::Combine(EmuFolders::Settings, "Python2.ini"));
|
||||
CIniFile ciniFile;
|
||||
|
@ -391,11 +371,11 @@ namespace usb_python2
|
|||
for (auto itr = sections.begin(); itr != sections.end(); itr++)
|
||||
{
|
||||
auto groupName = (*itr)->GetSectionName();
|
||||
if (groupName.find(L"GameEntry ") == 0)
|
||||
if (groupName.find(TEXT("GameEntry ")) == 0)
|
||||
{
|
||||
devListGroups.push_back(groupName);
|
||||
|
||||
auto gameName = (*itr)->GetKeyValue(L"Name");
|
||||
auto gameName = (*itr)->GetKeyValue(TEXT("Name"));
|
||||
if (!gameName.empty())
|
||||
devList.push_back(gameName);
|
||||
}
|
||||
|
@ -406,7 +386,10 @@ namespace usb_python2
|
|||
shared::rawinput::Uninitialize();
|
||||
}
|
||||
return (int)res;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace raw
|
||||
} // namespace usb_pad
|
||||
} // namespace usb_python2
|
|
@ -0,0 +1,282 @@
|
|||
#ifndef USBPYTHON2RAW_H
|
||||
#define USBPYTHON2RAW_H
|
||||
#include <thread>
|
||||
#include <array>
|
||||
#include <atomic>
|
||||
#include "USB/usb-python2/python2proxy.h"
|
||||
#include "USB/usb-python2/usb-python2.h"
|
||||
#include "USB/shared/rawinput_usb.h"
|
||||
|
||||
namespace usb_python2
|
||||
{
|
||||
#define CHECK(exp) \
|
||||
do \
|
||||
{ \
|
||||
if (!(exp)) \
|
||||
goto Error; \
|
||||
} while (0)
|
||||
#define SAFE_FREE(p) \
|
||||
do \
|
||||
{ \
|
||||
if (p) \
|
||||
{ \
|
||||
free(p); \
|
||||
(p) = NULL; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
namespace raw
|
||||
{
|
||||
struct InputStateUpdate
|
||||
{
|
||||
wxDateTime timestamp;
|
||||
bool state;
|
||||
};
|
||||
|
||||
const std::vector<TCHAR*> axisLabelList = {
|
||||
TEXT("X"),
|
||||
TEXT("Y"),
|
||||
TEXT("Z"),
|
||||
TEXT("RX"),
|
||||
TEXT("RY"),
|
||||
TEXT("RZ")};
|
||||
|
||||
const std::vector<TCHAR*> buttonDefaultOneshotList = {
|
||||
TEXT("DmHihat"),
|
||||
TEXT("DmSnare"),
|
||||
TEXT("DmHighTom"),
|
||||
TEXT("DmLowTom"),
|
||||
TEXT("DmCymbal"),
|
||||
TEXT("DmBassDrum"),
|
||||
|
||||
TEXT("GfP1Pick"),
|
||||
TEXT("GfP2Pick")};
|
||||
|
||||
const std::vector<TCHAR*> buttonLabelList = {
|
||||
// Machine
|
||||
TEXT("Test"),
|
||||
TEXT("Service"),
|
||||
TEXT("Coin1"),
|
||||
TEXT("Coin2"),
|
||||
|
||||
// Guitar Freaks
|
||||
TEXT("GfP1Start"),
|
||||
TEXT("GfP1Pick"),
|
||||
TEXT("GfP1Wail"),
|
||||
TEXT("GfP1EffectInc"),
|
||||
TEXT("GfP1EffectDec"),
|
||||
TEXT("GfP1NeckR"),
|
||||
TEXT("GfP1NeckG"),
|
||||
TEXT("GfP1NeckB"),
|
||||
|
||||
TEXT("GfP2Start"),
|
||||
TEXT("GfP2Pick"),
|
||||
TEXT("GfP2Wail"),
|
||||
TEXT("GfP2EffectInc"),
|
||||
TEXT("GfP2EffectDec"),
|
||||
TEXT("GfP2NeckR"),
|
||||
TEXT("GfP2NeckG"),
|
||||
TEXT("GfP2NeckB"),
|
||||
|
||||
// Drummania
|
||||
TEXT("DmStart"),
|
||||
TEXT("DmSelectL"),
|
||||
TEXT("DmSelectR"),
|
||||
TEXT("DmHihat"),
|
||||
TEXT("DmSnare"),
|
||||
TEXT("DmHighTom"),
|
||||
TEXT("DmLowTom"),
|
||||
TEXT("DmCymbal"),
|
||||
TEXT("DmBassDrum"),
|
||||
|
||||
// DDR
|
||||
TEXT("DdrP1Start"),
|
||||
TEXT("DdrP1SelectL"),
|
||||
TEXT("DdrP1SelectR"),
|
||||
TEXT("DdrP1FootLeft"),
|
||||
TEXT("DdrP1FootDown"),
|
||||
TEXT("DdrP1FootUp"),
|
||||
TEXT("DdrP1FootRight"),
|
||||
|
||||
TEXT("DdrP2Start"),
|
||||
TEXT("DdrP2SelectL"),
|
||||
TEXT("DdrP2SelectR"),
|
||||
TEXT("DdrP2FootLeft"),
|
||||
TEXT("DdrP2FootDown"),
|
||||
TEXT("DdrP2FootUp"),
|
||||
TEXT("DdrP2FootRight"),
|
||||
|
||||
// Thrill Drive
|
||||
TEXT("ThrillDriveStart"),
|
||||
TEXT("ThrillDriveGearUp"),
|
||||
TEXT("ThrillDriveGearDown"),
|
||||
TEXT("ThrillDriveWheelAnalog"),
|
||||
TEXT("ThrillDriveWheelLeft"),
|
||||
TEXT("ThrillDriveWheelRight"),
|
||||
TEXT("ThrillDriveAccelAnalog"),
|
||||
TEXT("ThrillDriveAccel"),
|
||||
TEXT("ThrillDriveBrake"),
|
||||
TEXT("ThrillDriveBrakeAnalog"),
|
||||
TEXT("ThrillDriveSeatbelt"),
|
||||
|
||||
// Toy's March
|
||||
TEXT("ToysMarchP1Start"),
|
||||
TEXT("ToysMarchP1SelectL"),
|
||||
TEXT("ToysMarchP1SelectR"),
|
||||
TEXT("ToysMarchP1DrumL"),
|
||||
TEXT("ToysMarchP1DrumR"),
|
||||
TEXT("ToysMarchP1Cymbal"),
|
||||
|
||||
TEXT("ToysMarchP2Start"),
|
||||
TEXT("ToysMarchP2SelectL"),
|
||||
TEXT("ToysMarchP2SelectR"),
|
||||
TEXT("ToysMarchP2DrumL"),
|
||||
TEXT("ToysMarchP2DrumR"),
|
||||
TEXT("ToysMarchP2Cymbal"),
|
||||
|
||||
// Dance 86.4
|
||||
TEXT("Dance864P1Start"),
|
||||
TEXT("Dance864P1Left"),
|
||||
TEXT("Dance864P1Right"),
|
||||
TEXT("Dance864P1PadLeft"),
|
||||
TEXT("Dance864P1PadCenter"),
|
||||
TEXT("Dance864P1PadRight"),
|
||||
|
||||
TEXT("Dance864P2Start"),
|
||||
TEXT("Dance864P2Left"),
|
||||
TEXT("Dance864P2Right"),
|
||||
TEXT("Dance864P2PadLeft"),
|
||||
TEXT("Dance864P2PadCenter"),
|
||||
TEXT("Dance864P2PadRight"),
|
||||
|
||||
// ICCA Card Reader
|
||||
TEXT("KeypadP1_0"),
|
||||
TEXT("KeypadP1_1"),
|
||||
TEXT("KeypadP1_2"),
|
||||
TEXT("KeypadP1_3"),
|
||||
TEXT("KeypadP1_4"),
|
||||
TEXT("KeypadP1_5"),
|
||||
TEXT("KeypadP1_6"),
|
||||
TEXT("KeypadP1_7"),
|
||||
TEXT("KeypadP1_8"),
|
||||
TEXT("KeypadP1_9"),
|
||||
TEXT("KeypadP1_00"),
|
||||
TEXT("KeypadP1InsertEject"),
|
||||
TEXT("KeypadP2_0"),
|
||||
TEXT("KeypadP2_1"),
|
||||
TEXT("KeypadP2_2"),
|
||||
TEXT("KeypadP2_3"),
|
||||
TEXT("KeypadP2_4"),
|
||||
TEXT("KeypadP2_5"),
|
||||
TEXT("KeypadP2_6"),
|
||||
TEXT("KeypadP2_7"),
|
||||
TEXT("KeypadP2_8"),
|
||||
TEXT("KeypadP2_9"),
|
||||
TEXT("KeypadP2_00"),
|
||||
TEXT("KeypadP2InsertEject"),
|
||||
};
|
||||
|
||||
class RawInputPad : public Python2Input, shared::rawinput::ParseRawInputCB
|
||||
{
|
||||
public:
|
||||
RawInputPad(int port, const char* dev_type)
|
||||
: Python2Input(port, dev_type)
|
||||
{
|
||||
if (!InitHid())
|
||||
throw UsbPython2Error("InitHid() failed!");
|
||||
}
|
||||
~RawInputPad()
|
||||
{
|
||||
Close();
|
||||
}
|
||||
int Open() override;
|
||||
int Close() override;
|
||||
int ReadPacket(std::vector<uint8_t>& data) override { return 0; };
|
||||
int WritePacket(const std::vector<uint8_t>& data) override { return 0; };
|
||||
void ReadIo(std::vector<uint8_t>& data) override {}
|
||||
int Reset() override { return 0; }
|
||||
void ParseRawInput(PRAWINPUT pRawInput);
|
||||
|
||||
bool isPassthrough() override { return false; }
|
||||
|
||||
static const TCHAR* Name()
|
||||
{
|
||||
return TEXT("Raw Input");
|
||||
}
|
||||
|
||||
void UpdateKeyStates(TSTDSTRING keybind) override;
|
||||
bool GetKeyState(TSTDSTRING keybind) override;
|
||||
bool GetKeyStateOneShot(TSTDSTRING keybind) override;
|
||||
double GetKeyStateAnalog(TSTDSTRING keybind) override;
|
||||
bool IsAnalogKeybindAvailable(TSTDSTRING keybind) override;
|
||||
|
||||
static int Configure(int port, const char* dev_type, void* data);
|
||||
|
||||
protected:
|
||||
private:
|
||||
};
|
||||
|
||||
enum KeybindType
|
||||
{
|
||||
KeybindType_Button = 0,
|
||||
KeybindType_Axis,
|
||||
KeybindType_Hat,
|
||||
KeybindType_Keyboard
|
||||
};
|
||||
|
||||
struct KeyMapping
|
||||
{
|
||||
uint32_t uniqueId;
|
||||
uint32_t keybindId;
|
||||
uint32_t bindType; // 0 = button, 1 = axis, 2 = hat, 3 = keyboard
|
||||
uint32_t value;
|
||||
bool isOneshot; // Immediately trigger an off after on
|
||||
};
|
||||
|
||||
struct Mappings
|
||||
{
|
||||
std::vector<KeyMapping> mappings;
|
||||
|
||||
TSTDSTRING devName;
|
||||
#if _WIN32
|
||||
TSTDSTRING hidPath;
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifndef PCSX2_CORE
|
||||
struct Python2DlgConfig
|
||||
{
|
||||
int port;
|
||||
const char* dev_type;
|
||||
|
||||
const std::vector<TSTDSTRING> devList;
|
||||
const std::vector<TSTDSTRING> devListGroups;
|
||||
|
||||
Python2DlgConfig(int p, const char* dev_type_, const std::vector<TSTDSTRING>& devList, const std::vector<TSTDSTRING>& devListGroups)
|
||||
: port(p)
|
||||
, dev_type(dev_type_)
|
||||
, devList(devList)
|
||||
, devListGroups(devListGroups)
|
||||
{
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
typedef std::vector<Mappings> MapVector;
|
||||
static MapVector mapVector;
|
||||
static std::map<HANDLE, Mappings*> mappings;
|
||||
|
||||
static std::map<TSTDSTRING, std::deque<InputStateUpdate>> keyStateUpdates;
|
||||
static std::map<TSTDSTRING, bool> isOneshotState;
|
||||
static std::map<TSTDSTRING, bool> currentKeyStates;
|
||||
static std::map<TSTDSTRING, double> currentInputStateAnalog;
|
||||
|
||||
static std::map<uint16_t, bool> keyboardButtonIsPressed;
|
||||
static std::map<TSTDSTRING, std::map<uint32_t, bool>> gamepadButtonIsPressed;
|
||||
|
||||
void LoadMappings(const char* dev_type, MapVector& maps);
|
||||
void SaveMappings(const char* dev_type, MapVector& maps);
|
||||
|
||||
} // namespace raw
|
||||
} // namespace usb_python2
|
||||
#endif
|
|
@ -1,18 +1,3 @@
|
|||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2020 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "usb-python2.h"
|
||||
#include "python2proxy.h"
|
||||
|
||||
|
@ -40,12 +25,11 @@ namespace usb_python2
|
|||
int Reset() { return 0; }
|
||||
bool isPassthrough() { return false; }
|
||||
|
||||
void UpdateKeyStates(std::wstring keybind) {};
|
||||
bool GetKeyState(std::wstring keybind) { return false; };
|
||||
bool GetKeyStateOneShot(std::wstring keybind) { return false; };
|
||||
double GetKeyStateAnalog(std::wstring keybind) { return 0; };
|
||||
bool IsKeybindAvailable(std::wstring keybind) { return false; };
|
||||
bool IsAnalogKeybindAvailable(std::wstring keybind) { return false; };
|
||||
void UpdateKeyStates(std::string keybind) {};
|
||||
bool GetKeyState(std::string keybind) { return false; };
|
||||
bool GetKeyStateOneShot(std::string keybind) { return false; };
|
||||
double GetKeyStateAnalog(std::string keybind) { return 0; };
|
||||
bool IsAnalogKeybindAvailable(std::string keybind) { return false; };
|
||||
|
||||
static const TCHAR* Name()
|
||||
{
|
||||
|
@ -59,4 +43,4 @@ namespace usb_python2
|
|||
};
|
||||
|
||||
} // namespace noop
|
||||
} // namespace usb_hid
|
||||
} // namespace usb_python2
|
||||
|
|
|
@ -11,21 +11,20 @@
|
|||
#include "IopMem.h"
|
||||
#include "Patch.h"
|
||||
|
||||
#include <wx/ffile.h>
|
||||
#include <wx/fileconf.h>
|
||||
|
||||
namespace usb_python2
|
||||
{
|
||||
std::thread mPatchSpdifAudioThread;
|
||||
std::atomic<bool> mPatchSpdifAudioThreadIsRunning;
|
||||
uint32_t mTargetWriteCmd = 0;
|
||||
uint32_t mTargetPatchAddr = 0;
|
||||
uint32_t mTargetIgnoreAddr = 0;
|
||||
|
||||
void Python2Patch::PatchSpdifAudioThread(void* ptr)
|
||||
{
|
||||
mPatchSpdifAudioThreadIsRunning = true;
|
||||
mTargetWriteCmd = 0;
|
||||
mTargetPatchAddr = 0;
|
||||
mTargetIgnoreAddr = 0;
|
||||
|
||||
ForgetLoadedPatches();
|
||||
|
||||
|
@ -37,7 +36,7 @@ namespace usb_python2
|
|||
#ifndef PCSX2_CORE
|
||||
!GetCoreThread().IsOpen() || GetCoreThread().IsPaused()
|
||||
#else
|
||||
VMManager::GetState() != Running /* Untested */
|
||||
VMManager::GetState() != VMState::Running
|
||||
#endif
|
||||
|| psxMemRLUT == NULL || psxMemWLUT == NULL)
|
||||
continue;
|
||||
|
@ -47,13 +46,14 @@ namespace usb_python2
|
|||
|
||||
// The GF games I looked all had the required code in this range, but it's possible there exists
|
||||
// code in other places.
|
||||
for (int i = 0x100000; i < 0x120000; i += 4)
|
||||
|
||||
for (uint32_t i = 0x100000; i < 0x120000; i += 4)
|
||||
{
|
||||
if (
|
||||
#ifndef PCSX2_CORE
|
||||
!GetCoreThread().IsOpen() || GetCoreThread().IsPaused()
|
||||
#else
|
||||
VMManager::GetState() != Running /* Untested */
|
||||
VMManager::GetState() != VMState::Running
|
||||
#endif
|
||||
|| psxMemRLUT == NULL || psxMemWLUT == NULL)
|
||||
break;
|
||||
|
@ -64,17 +64,19 @@ namespace usb_python2
|
|||
{
|
||||
Console.WriteLn("Patching write @ %08x...", i);
|
||||
|
||||
// Patch write
|
||||
IniPatch iPatch = {0};
|
||||
iPatch.placetopatch = PPT_CONTINUOUSLY;
|
||||
iPatch.cpu = CPU_IOP;
|
||||
iPatch.addr = i;
|
||||
iPatch.type = WORD_T;
|
||||
iPatch.data = 0;
|
||||
iPatch.oldData = iopMemRead32(iPatch.addr);
|
||||
iPatch.hasOldData = true;
|
||||
iPatch.enabled = 1;
|
||||
LoadPatchFromMemory(iPatch);
|
||||
if (i != mTargetIgnoreAddr) {
|
||||
// Patch write
|
||||
IniPatch iPatch = {0};
|
||||
iPatch.placetopatch = PPT_CONTINUOUSLY;
|
||||
iPatch.cpu = CPU_IOP;
|
||||
iPatch.addr = i;
|
||||
iPatch.type = WORD_T;
|
||||
iPatch.data = 0;
|
||||
iPatch.oldData = iopMemRead32(iPatch.addr);
|
||||
iPatch.hasOldData = true;
|
||||
iPatch.enabled = 1;
|
||||
LoadPatchFromMemory(iPatch);
|
||||
}
|
||||
}
|
||||
else if (
|
||||
x == 0x00000000 &&
|
||||
|
@ -82,7 +84,7 @@ namespace usb_python2
|
|||
iopMemRead32(i + 12) == 0x24020001 &&
|
||||
(iopMemRead32(i + 16) & 0xffffff00) == 0x3c010000 &&
|
||||
(iopMemRead32(i + 20) & 0xffff0000) == 0xac220000 &&
|
||||
(iopMemRead32(i + 24) & 0xffff0000) == 0x08040000 &&
|
||||
(iopMemRead32(i + 24) & 0xff000000) == 0x08000000 &&
|
||||
iopMemRead32(i + 28) == 0x00000000 &&
|
||||
(iopMemRead32(i + 32) & 0xffffff00) == 0x3c010000)
|
||||
{
|
||||
|
@ -96,11 +98,9 @@ namespace usb_python2
|
|||
|
||||
mTargetWriteCmd = writeCmd;
|
||||
mTargetPatchAddr = addr;
|
||||
mTargetIgnoreAddr = i + 20;
|
||||
|
||||
// Find other writes along the way and patch those out
|
||||
i += 28;
|
||||
|
||||
// Patch jump
|
||||
// Patch jump so that we'll always write analog (1) into the variable at least once
|
||||
IniPatch iPatch = {0};
|
||||
iPatch.placetopatch = PPT_CONTINUOUSLY;
|
||||
iPatch.cpu = CPU_IOP;
|
||||
|
@ -124,6 +124,9 @@ namespace usb_python2
|
|||
iPatch.enabled = 1;
|
||||
LoadPatchFromMemory(iPatch);
|
||||
|
||||
// Find other writes along the way and patch those out
|
||||
i += 28;
|
||||
|
||||
lastLoop = true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,18 +1,3 @@
|
|||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2020 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef USBPYTHON2PROXY_H
|
||||
#define USBPYTHON2PROXY_H
|
||||
#include <string>
|
||||
|
|
|
@ -1,299 +0,0 @@
|
|||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2020 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef USBPYTHON2RAW_H
|
||||
#define USBPYTHON2RAW_H
|
||||
#include <thread>
|
||||
#include <array>
|
||||
#include <atomic>
|
||||
#include "USB/usb-python2/python2proxy.h"
|
||||
#include "USB/usb-python2/usb-python2.h"
|
||||
#include "USB/shared/rawinput_usb.h"
|
||||
#include "USB/readerwriterqueue/readerwriterqueue.h"
|
||||
|
||||
namespace usb_python2
|
||||
{
|
||||
#define CHECK(exp) \
|
||||
do \
|
||||
{ \
|
||||
if (!(exp)) \
|
||||
goto Error; \
|
||||
} while (0)
|
||||
#define SAFE_FREE(p) \
|
||||
do \
|
||||
{ \
|
||||
if (p) \
|
||||
{ \
|
||||
free(p); \
|
||||
(p) = NULL; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
namespace raw
|
||||
{
|
||||
struct InputStateUpdate
|
||||
{
|
||||
wxDateTime timestamp;
|
||||
bool state;
|
||||
};
|
||||
|
||||
const std::vector<wchar_t*> axisLabelList = {
|
||||
L"X",
|
||||
L"Y",
|
||||
L"Z",
|
||||
L"RX",
|
||||
L"RY",
|
||||
L"RZ"};
|
||||
|
||||
const std::vector<wchar_t*> buttonDefaultOneshotList = {
|
||||
L"DmHihat",
|
||||
L"DmSnare",
|
||||
L"DmHighTom",
|
||||
L"DmLowTom",
|
||||
L"DmCymbal",
|
||||
L"DmBassDrum",
|
||||
|
||||
L"GfP1Pick",
|
||||
L"GfP2Pick"};
|
||||
|
||||
const std::vector<wchar_t*> buttonLabelList = {
|
||||
// Machine
|
||||
L"Test",
|
||||
L"Service",
|
||||
L"Coin1",
|
||||
L"Coin2",
|
||||
|
||||
// Guitar Freaks
|
||||
L"GfP1Start",
|
||||
L"GfP1Pick",
|
||||
L"GfP1Wail",
|
||||
L"GfP1EffectInc",
|
||||
L"GfP1EffectDec",
|
||||
L"GfP1NeckR",
|
||||
L"GfP1NeckG",
|
||||
L"GfP1NeckB",
|
||||
|
||||
L"GfP2Start",
|
||||
L"GfP2Pick",
|
||||
L"GfP2Wail",
|
||||
L"GfP2EffectInc",
|
||||
L"GfP2EffectDec",
|
||||
L"GfP2NeckR",
|
||||
L"GfP2NeckG",
|
||||
L"GfP2NeckB",
|
||||
|
||||
// Drummania
|
||||
L"DmStart",
|
||||
L"DmSelectL",
|
||||
L"DmSelectR",
|
||||
L"DmHihat",
|
||||
L"DmSnare",
|
||||
L"DmHighTom",
|
||||
L"DmLowTom",
|
||||
L"DmCymbal",
|
||||
L"DmBassDrum",
|
||||
|
||||
// DDR
|
||||
L"DdrP1Start",
|
||||
L"DdrP1SelectL",
|
||||
L"DdrP1SelectR",
|
||||
L"DdrP1FootLeft",
|
||||
L"DdrP1FootDown",
|
||||
L"DdrP1FootUp",
|
||||
L"DdrP1FootRight",
|
||||
|
||||
L"DdrP2Start",
|
||||
L"DdrP2SelectL",
|
||||
L"DdrP2SelectR",
|
||||
L"DdrP2FootLeft",
|
||||
L"DdrP2FootDown",
|
||||
L"DdrP2FootUp",
|
||||
L"DdrP2FootRight",
|
||||
|
||||
// Thrill Drive
|
||||
L"ThrillDriveStart",
|
||||
L"ThrillDriveGearUp",
|
||||
L"ThrillDriveGearDown",
|
||||
L"ThrillDriveWheelAnalog",
|
||||
L"ThrillDriveWheelLeft",
|
||||
L"ThrillDriveWheelRight",
|
||||
L"ThrillDriveAccelAnalog",
|
||||
L"ThrillDriveAccel",
|
||||
L"ThrillDriveBrake",
|
||||
L"ThrillDriveBrakeAnalog",
|
||||
L"ThrillDriveSeatbelt",
|
||||
|
||||
// Toy's March
|
||||
L"ToysMarchP1Start",
|
||||
L"ToysMarchP1SelectL",
|
||||
L"ToysMarchP1SelectR",
|
||||
L"ToysMarchP1DrumL",
|
||||
L"ToysMarchP1DrumR",
|
||||
L"ToysMarchP1Cymbal",
|
||||
|
||||
L"ToysMarchP2Start",
|
||||
L"ToysMarchP2SelectL",
|
||||
L"ToysMarchP2SelectR",
|
||||
L"ToysMarchP2DrumL",
|
||||
L"ToysMarchP2DrumR",
|
||||
L"ToysMarchP2Cymbal",
|
||||
|
||||
// Dance 86.4
|
||||
L"Dance864P1Start",
|
||||
L"Dance864P1Left",
|
||||
L"Dance864P1Right",
|
||||
L"Dance864P1PadLeft",
|
||||
L"Dance864P1PadCenter",
|
||||
L"Dance864P1PadRight",
|
||||
|
||||
L"Dance864P2Start",
|
||||
L"Dance864P2Left",
|
||||
L"Dance864P2Right",
|
||||
L"Dance864P2PadLeft",
|
||||
L"Dance864P2PadCenter",
|
||||
L"Dance864P2PadRight",
|
||||
|
||||
// ICCA Card Reader
|
||||
L"KeypadP1_0",
|
||||
L"KeypadP1_1",
|
||||
L"KeypadP1_2",
|
||||
L"KeypadP1_3",
|
||||
L"KeypadP1_4",
|
||||
L"KeypadP1_5",
|
||||
L"KeypadP1_6",
|
||||
L"KeypadP1_7",
|
||||
L"KeypadP1_8",
|
||||
L"KeypadP1_9",
|
||||
L"KeypadP1_00",
|
||||
L"KeypadP1InsertEject",
|
||||
L"KeypadP2_0",
|
||||
L"KeypadP2_1",
|
||||
L"KeypadP2_2",
|
||||
L"KeypadP2_3",
|
||||
L"KeypadP2_4",
|
||||
L"KeypadP2_5",
|
||||
L"KeypadP2_6",
|
||||
L"KeypadP2_7",
|
||||
L"KeypadP2_8",
|
||||
L"KeypadP2_9",
|
||||
L"KeypadP2_00",
|
||||
L"KeypadP2InsertEject",
|
||||
};
|
||||
|
||||
class RawInputPad : public Python2Input, shared::rawinput::ParseRawInputCB
|
||||
{
|
||||
public:
|
||||
RawInputPad(int port, const char* dev_type)
|
||||
: Python2Input(port, dev_type)
|
||||
{
|
||||
if (!InitHid())
|
||||
throw UsbPython2Error("InitHid() failed!");
|
||||
}
|
||||
~RawInputPad()
|
||||
{
|
||||
Close();
|
||||
}
|
||||
int Open() override;
|
||||
int Close() override;
|
||||
int ReadPacket(std::vector<uint8_t>& data) override { return 0; };
|
||||
int WritePacket(const std::vector<uint8_t>& data) override { return 0; };
|
||||
void ReadIo(std::vector<uint8_t>& data) override {}
|
||||
int Reset() override { return 0; }
|
||||
void ParseRawInput(PRAWINPUT pRawInput);
|
||||
|
||||
bool isPassthrough() override { return false; }
|
||||
|
||||
static const TCHAR* Name()
|
||||
{
|
||||
return TEXT("Raw Input");
|
||||
}
|
||||
|
||||
void UpdateKeyStates(std::wstring keybind) override;
|
||||
bool GetKeyState(std::wstring keybind) override;
|
||||
bool GetKeyStateOneShot(std::wstring keybind) override;
|
||||
double GetKeyStateAnalog(std::wstring keybind) override;
|
||||
bool IsKeybindAvailable(std::wstring keybind) override;
|
||||
bool IsAnalogKeybindAvailable(std::wstring keybind) override;
|
||||
|
||||
static int Configure(int port, const char* dev_type, void* data);
|
||||
|
||||
protected:
|
||||
private:
|
||||
};
|
||||
|
||||
enum KeybindType
|
||||
{
|
||||
KeybindType_Button = 0,
|
||||
KeybindType_Axis,
|
||||
KeybindType_Hat,
|
||||
KeybindType_Keyboard
|
||||
};
|
||||
|
||||
struct KeyMapping
|
||||
{
|
||||
uint32_t uniqueId;
|
||||
uint32_t keybindId;
|
||||
uint32_t bindType; // 0 = button, 1 = axis, 2 = hat, 3 = keyboard
|
||||
uint32_t value;
|
||||
bool isOneshot; // Immediately trigger an off after on
|
||||
};
|
||||
|
||||
struct Mappings
|
||||
{
|
||||
std::vector<KeyMapping> mappings;
|
||||
|
||||
std::wstring devName;
|
||||
#if _WIN32
|
||||
std::wstring hidPath;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct Python2DlgConfig
|
||||
{
|
||||
int port;
|
||||
const char* dev_type;
|
||||
|
||||
const std::vector<std::wstring> devList;
|
||||
const std::vector<std::wstring> devListGroups;
|
||||
|
||||
Python2DlgConfig(int p, const char* dev_type_, const std::vector<std::wstring>& devList, const std::vector<std::wstring>& devListGroups)
|
||||
: port(p)
|
||||
, dev_type(dev_type_)
|
||||
, devList(devList)
|
||||
, devListGroups(devListGroups)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
typedef std::vector<Mappings> MapVector;
|
||||
static MapVector mapVector;
|
||||
static std::map<HANDLE, Mappings*> mappings;
|
||||
|
||||
static std::map<std::wstring, std::deque<InputStateUpdate>> keyStateUpdates;
|
||||
static std::map<std::wstring, bool> isOneshotState;
|
||||
static std::map<std::wstring, bool> currentKeyStates;
|
||||
static std::map<std::wstring, int> currentInputStateKeyboard;
|
||||
static std::map<std::wstring, int> currentInputStatePad;
|
||||
static std::map<std::wstring, double> currentInputStateAnalog;
|
||||
|
||||
static std::map<USHORT, bool> keyboardButtonIsPressed;
|
||||
static std::map<std::wstring, std::map<uint32_t, bool>> gamepadButtonIsPressed;
|
||||
|
||||
void LoadMappings(const char* dev_type, MapVector& maps);
|
||||
void SaveMappings(const char* dev_type, MapVector& maps);
|
||||
|
||||
} // namespace raw
|
||||
} // namespace usb_python2
|
||||
#endif
|
|
@ -1,40 +1,22 @@
|
|||
/*
|
||||
* QEMU USB HID devices
|
||||
*
|
||||
* Copyright (c) 2005 Fabrice Bellard
|
||||
* Copyright (c) 2007 OpenMoko, Inc. (andrew@openedhand.com)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "PrecompiledHeader.h"
|
||||
#include <algorithm>
|
||||
#include <numeric>
|
||||
#include <queue>
|
||||
|
||||
#include "common/FileSystem.h"
|
||||
#include "common/Path.h"
|
||||
|
||||
#include "Config.h"
|
||||
|
||||
#ifndef PCSX2_CORE
|
||||
#include "gui/AppConfig.h"
|
||||
#include "gui/StringHelpers.h"
|
||||
#include "gui/AppConfig.h"
|
||||
#endif
|
||||
|
||||
#ifdef PCSX2_CORE
|
||||
#include "pcsx2/HostSettings.h"
|
||||
#include "common/SettingsInterface.h"
|
||||
#include "Frontend/InputManager.h"
|
||||
#endif
|
||||
|
||||
#include "USB/deviceproxy.h"
|
||||
|
@ -50,9 +32,7 @@
|
|||
#include "USB/usb-python2/devices/toysmarch_drumpad.h"
|
||||
#include "USB/usb-python2/devices/icca.h"
|
||||
|
||||
#ifndef PCSX2_CORE
|
||||
#include "patches.h"
|
||||
#endif
|
||||
|
||||
#ifdef INCLUDE_MINIMAID
|
||||
#include <mmmagic.h>
|
||||
|
@ -60,7 +40,7 @@
|
|||
|
||||
#ifdef INCLUDE_BTOOLS
|
||||
#include <bemanitools/ddrio.h>
|
||||
#include <pcsx2/USB/usb-python2/btools/usb-python2-btools.h>
|
||||
#include "USB/usb-python2/inputs/btools/usb-python2-btools.h"
|
||||
|
||||
HINSTANCE hDDRIO = nullptr;
|
||||
|
||||
|
@ -324,9 +304,78 @@ namespace usb_python2
|
|||
|
||||
void load_configuration(USBDevice* dev)
|
||||
{
|
||||
#ifndef PCSX2_CORE
|
||||
auto s = reinterpret_cast<UsbPython2State*>(dev);
|
||||
|
||||
#ifdef PCSX2_CORE
|
||||
SettingsInterface* si = Host::GetSettingsInterface(); // TODO: Fix this to load the appropriate config file
|
||||
|
||||
s->f.dipSwitch[0] = si->GetBoolValue("Python2/Game", "DIPSW1", false) ? '1' : '0';
|
||||
s->f.dipSwitch[1] = si->GetBoolValue("Python2/Game", "DIPSW2", false) ? '1' : '0';
|
||||
s->f.dipSwitch[2] = si->GetBoolValue("Python2/Game", "DIPSW3", false) ? '1' : '0';
|
||||
s->f.dipSwitch[3] = si->GetBoolValue("Python2/Game", "DIPSW4", false) ? '1' : '0';
|
||||
s->f.force31khz = si->GetBoolValue("Python2/Game", "Force31kHz", false);
|
||||
|
||||
Console.WriteLn("dipswitches: %c %c %c %c\n", s->f.dipSwitch[0], s->f.dipSwitch[1], s->f.dipSwitch[2], s->f.dipSwitch[3]);
|
||||
Console.WriteLn("force31khz: %d\n", s->f.force31khz);
|
||||
|
||||
IlinkIdPath = si->GetStringValue("Python2/System", "IlinkIdFile", "");
|
||||
Console.WriteLn("IlinkIdPath: %s", IlinkIdPath.c_str());
|
||||
|
||||
// PatchFileOverridePath = si->GetStringValue("Python2/Game", "PatchFile", "");
|
||||
// Console.WriteLn("PatchFileOverridePath: %s", PatchFileOverridePath.c_str());
|
||||
|
||||
s->f.cardFilenames[0] = si->GetStringValue("Python2/Game", "Player1CardFile", "card1.txt");
|
||||
Console.WriteLn("Player 1 card filename: %s", s->f.cardFilenames[0].c_str());
|
||||
|
||||
s->f.cardFilenames[1] = si->GetStringValue("Python2/Game", "Player2CardFile", "card2.txt");
|
||||
Console.WriteLn("Player 2 card filename: %s", s->f.cardFilenames[0].c_str());
|
||||
|
||||
|
||||
s->f.gameType = si->GetIntValue("Python2/Game", "GameType", 0);
|
||||
Console.WriteLn("GameType: %d", s->f.gameType);
|
||||
|
||||
const std::string hddIdPath = si->GetStringValue("DEV9/Hdd", "HddIdFile", "");
|
||||
Console.WriteLn("HddIdPath: %s", hddIdPath.c_str());
|
||||
if (!hddIdPath.empty())
|
||||
{
|
||||
if (FileSystem::FileExists(hddIdPath.c_str()))
|
||||
EmuConfig.DEV9.HddIdFile = hddIdPath;
|
||||
}
|
||||
|
||||
auto dongleBlackPath = si->GetStringValue("Python2/Game", "DongleBlackFile", "");
|
||||
Console.WriteLn("DongleBlackPath: %s", dongleBlackPath.c_str());
|
||||
if (!dongleBlackPath.empty())
|
||||
{
|
||||
auto dongleFile = FileSystem::OpenManagedCFile(dongleBlackPath.c_str(), "rb");
|
||||
if (dongleFile && FileSystem::FSize64(dongleFile.get()) >= 40)
|
||||
{
|
||||
std::fread(&s->f.dongleSlotPayload[0][0], 1, 40, dongleFile.get());
|
||||
s->f.isDongleSlotLoaded[0] = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::fill(std::begin(s->f.dongleSlotPayload[0]), std::end(s->f.dongleSlotPayload[0]), 0);
|
||||
s->f.isDongleSlotLoaded[0] = false;
|
||||
}
|
||||
}
|
||||
|
||||
auto dongleWhitePath = si->GetStringValue("Python2/Game", "DongleWhiteFile", "");
|
||||
Console.WriteLn("DongleWhitePath: %s", dongleWhitePath.c_str());
|
||||
if (!dongleWhitePath.empty())
|
||||
{
|
||||
auto dongleFile = FileSystem::OpenManagedCFile(dongleWhitePath.c_str(), "rb");
|
||||
if (dongleFile && FileSystem::FSize64(dongleFile.get()) >= 40)
|
||||
{
|
||||
std::fread(&s->f.dongleSlotPayload[1][0], 1, 40, dongleFile.get());
|
||||
s->f.isDongleSlotLoaded[1] = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::fill(std::begin(s->f.dongleSlotPayload[1]), std::end(s->f.dongleSlotPayload[1]), 0);
|
||||
s->f.isDongleSlotLoaded[1] = false;
|
||||
}
|
||||
}
|
||||
#else
|
||||
// Called when the device is initialized so just load settings here
|
||||
const wxString iniPath = StringUtil::UTF8StringToWxString(Path::Combine(EmuFolders::Settings, "Python2.ini"));
|
||||
CIniFile ciniFile;
|
||||
|
@ -343,10 +392,10 @@ namespace usb_python2
|
|||
#endif
|
||||
|
||||
{
|
||||
s->f.cardFilenames[0] = wstr_to_str(ciniFile.GetKeyValue(L"CardReader", L"Player1Card"));
|
||||
s->f.cardFilenames[0] = wxString(ciniFile.GetKeyValue(L"CardReader", L"Player1Card")).ToStdString();
|
||||
Console.WriteLn("Player 1 card filename: %s", s->f.cardFilenames[0].c_str());
|
||||
|
||||
s->f.cardFilenames[1] = wstr_to_str(ciniFile.GetKeyValue(L"CardReader", L"Player2Card"));
|
||||
s->f.cardFilenames[1] = wxString(ciniFile.GetKeyValue(L"CardReader", L"Player2Card")).ToStdString();
|
||||
Console.WriteLn("Player 2 card filename: %s", s->f.cardFilenames[1].c_str());
|
||||
}
|
||||
|
||||
|
@ -354,10 +403,10 @@ namespace usb_python2
|
|||
auto section = ciniFile.GetSection(selectedDevice);
|
||||
if (section)
|
||||
{
|
||||
auto gameName = wstr_to_str(section->GetKeyValue(L"Name"));
|
||||
auto gameName = wxString(section->GetKeyValue(L"Name")).ToStdString();
|
||||
Console.WriteLn("Game Name: %s", gameName.c_str());
|
||||
|
||||
auto dongleBlackPath = wstr_to_str(section->GetKeyValue(L"DongleBlackPath"));
|
||||
auto dongleBlackPath = wxString(section->GetKeyValue(L"DongleBlackPath")).ToStdString();
|
||||
Console.WriteLn("DongleBlackPath: %s", dongleBlackPath.c_str());
|
||||
if (!dongleBlackPath.empty())
|
||||
{
|
||||
|
@ -374,7 +423,7 @@ namespace usb_python2
|
|||
}
|
||||
}
|
||||
|
||||
auto dongleWhitePath = wstr_to_str(section->GetKeyValue(L"DongleWhitePath"));
|
||||
auto dongleWhitePath = wxString(section->GetKeyValue(L"DongleWhitePath")).ToStdString();
|
||||
Console.WriteLn("DongleWhitePath: %s", dongleWhitePath.c_str());
|
||||
if (!dongleWhitePath.empty())
|
||||
{
|
||||
|
@ -391,19 +440,19 @@ namespace usb_python2
|
|||
}
|
||||
}
|
||||
|
||||
auto inputType = wstr_to_str(section->GetKeyValue(L"InputType"));
|
||||
auto inputType = wxString(section->GetKeyValue(L"InputType")).ToStdString();
|
||||
Console.WriteLn("InputType: %s", inputType.c_str());
|
||||
s->f.gameType = 0;
|
||||
if (!inputType.empty())
|
||||
s->f.gameType = atoi(inputType.c_str());
|
||||
|
||||
auto dipSwitch = wstr_to_str(section->GetKeyValue(L"DipSwitch"));
|
||||
auto dipSwitch = wxString(section->GetKeyValue(L"DipSwitch")).ToStdString();
|
||||
Console.WriteLn("DipSwitch: %s", dipSwitch.c_str());
|
||||
std::fill(std::begin(s->f.dipSwitch), std::end(s->f.dipSwitch), 0);
|
||||
for (size_t j = 0; j < 4 && j < dipSwitch.size(); j++)
|
||||
s->f.dipSwitch[j] = dipSwitch[j];
|
||||
|
||||
auto hddImagePath = wstr_to_str(section->GetKeyValue(L"HddImagePath"));
|
||||
auto hddImagePath = wxString(section->GetKeyValue(L"HddImagePath")).ToStdString();
|
||||
Console.WriteLn("HddImagePath: %s", hddImagePath.c_str());
|
||||
EmuConfig.DEV9.HddFile = "";
|
||||
if (!hddImagePath.empty())
|
||||
|
@ -412,7 +461,7 @@ namespace usb_python2
|
|||
EmuConfig.DEV9.HddFile = hddImagePath;
|
||||
}
|
||||
|
||||
auto hddIdPath = wstr_to_str(section->GetKeyValue(L"HddIdPath"));
|
||||
auto hddIdPath = wxString(section->GetKeyValue(L"HddIdPath")).ToStdString();
|
||||
Console.WriteLn("HddIdPath: %s", hddIdPath.c_str());
|
||||
EmuConfig.DEV9.HddIdFile = "";
|
||||
if (!hddIdPath.empty())
|
||||
|
@ -421,15 +470,15 @@ namespace usb_python2
|
|||
EmuConfig.DEV9.HddIdFile = hddIdPath;
|
||||
}
|
||||
|
||||
auto ilinkIdPath = wstr_to_str(section->GetKeyValue(L"IlinkIdPath"));
|
||||
auto ilinkIdPath = wxString(section->GetKeyValue(L"IlinkIdPath")).ToStdString();
|
||||
Console.WriteLn("IlinkIdPath: %s", ilinkIdPath.c_str());
|
||||
IlinkIdPath = ilinkIdPath;
|
||||
|
||||
auto force31kHz = wstr_to_str(section->GetKeyValue(L"Force31kHz"));
|
||||
auto force31kHz = wxString(section->GetKeyValue(L"Force31kHz")).ToStdString();
|
||||
Console.WriteLn("Force31kHz: %s", force31kHz.c_str());
|
||||
s->f.force31khz = force31kHz == "1";
|
||||
|
||||
auto patchFile = wstr_to_str(section->GetKeyValue(L"PatchFile"));
|
||||
auto patchFile = wxString(section->GetKeyValue(L"PatchFile")).ToStdString();
|
||||
Console.WriteLn("PatchFile: %s", patchFile.c_str());
|
||||
PatchFileOverridePath = patchFile;
|
||||
}
|
||||
|
@ -471,7 +520,7 @@ namespace usb_python2
|
|||
const uint8_t resp[] = {
|
||||
'D', '4', '4', '\0', // product code
|
||||
1, // major
|
||||
6, // minor
|
||||
6, // minor
|
||||
4 // revision
|
||||
};
|
||||
data.insert(data.end(), std::begin(resp), std::end(resp));
|
||||
|
@ -529,7 +578,7 @@ namespace usb_python2
|
|||
|
||||
else if (header->cmd == P2IO_CMD_COIN_STOCK)
|
||||
{
|
||||
Python2ConVerbose.WriteLn("P2IO_CMD_COIN_STOCK");
|
||||
// Python2ConVerbose.WriteLn("P2IO_CMD_COIN_STOCK");
|
||||
|
||||
const uint8_t resp[] = {
|
||||
0, // If this is non-zero then the following 4 bytes are not processed
|
||||
|
@ -823,7 +872,7 @@ namespace usb_python2
|
|||
|
||||
#define CheckKeyState(key, val) \
|
||||
{ \
|
||||
if (s->p2dev->GetKeyState((key))) \
|
||||
if (s->p2dev->GetKeyState(P2TEXT(key))) \
|
||||
s->f.jammaIoStatus &= ~(val); \
|
||||
else \
|
||||
s->f.jammaIoStatus |= (val); \
|
||||
|
@ -831,7 +880,7 @@ namespace usb_python2
|
|||
|
||||
#define CheckKeyStateOneShot(key, val) \
|
||||
{ \
|
||||
if (s->p2dev->GetKeyStateOneShot((key))) \
|
||||
if (s->p2dev->GetKeyStateOneShot(P2TEXT(key))) \
|
||||
s->f.jammaIoStatus &= ~(val); \
|
||||
else \
|
||||
s->f.jammaIoStatus |= (val); \
|
||||
|
@ -839,13 +888,13 @@ namespace usb_python2
|
|||
|
||||
#define KnobStateInc(key, val, playerId) \
|
||||
{ \
|
||||
if (s->p2dev->GetKeyStateOneShot((key))) \
|
||||
if (s->p2dev->GetKeyStateOneShot(P2TEXT(key))) \
|
||||
s->f.knobs[(playerId)] = (s->f.knobs[(playerId)] + 1) % 4; \
|
||||
}
|
||||
|
||||
#define KnobStateDec(key, val, playerId) \
|
||||
{ \
|
||||
if (s->p2dev->GetKeyStateOneShot((key))) \
|
||||
if (s->p2dev->GetKeyStateOneShot(P2TEXT(key))) \
|
||||
s->f.knobs[(playerId)] = (s->f.knobs[(playerId)] - 1) < 0 ? 3 : (s->f.knobs[(playerId)] - 1); \
|
||||
}
|
||||
|
||||
|
@ -866,10 +915,10 @@ namespace usb_python2
|
|||
}
|
||||
|
||||
// Handle inputs that shouldn't be oneshots typically on every update
|
||||
CheckKeyState(L"Test", P2IO_JAMMA_IO_TEST);
|
||||
CheckKeyState(L"Service", P2IO_JAMMA_IO_SERVICE);
|
||||
CheckKeyState(L"Coin1", P2IO_JAMMA_IO_COIN1);
|
||||
CheckKeyState(L"Coin2", P2IO_JAMMA_IO_COIN2);
|
||||
CheckKeyState("Test", P2IO_JAMMA_IO_TEST);
|
||||
CheckKeyState("Service", P2IO_JAMMA_IO_SERVICE);
|
||||
CheckKeyState("Coin1", P2IO_JAMMA_IO_COIN1);
|
||||
CheckKeyState("Coin2", P2IO_JAMMA_IO_COIN2);
|
||||
|
||||
// Python 2 games only accept coins via the P2IO directly, even though the game sees the JAMMA coin buttons returned here(?)
|
||||
CoinInc(P2IO_JAMMA_IO_COIN1, 0);
|
||||
|
@ -877,52 +926,52 @@ namespace usb_python2
|
|||
|
||||
if (s->f.gameType == GAMETYPE_DDR)
|
||||
{
|
||||
CheckKeyState(L"DdrP1Start", P2IO_JAMMA_DDR_P1_START);
|
||||
CheckKeyState(L"DdrP1SelectL", P2IO_JAMMA_DDR_P1_LEFT);
|
||||
CheckKeyState(L"DdrP1SelectR", P2IO_JAMMA_DDR_P1_RIGHT);
|
||||
CheckKeyState(L"DdrP1FootLeft", P2IO_JAMMA_DDR_P1_FOOT_LEFT);
|
||||
CheckKeyState(L"DdrP1FootDown", P2IO_JAMMA_DDR_P1_FOOT_DOWN);
|
||||
CheckKeyState(L"DdrP1FootUp", P2IO_JAMMA_DDR_P1_FOOT_UP);
|
||||
CheckKeyState(L"DdrP1FootRight", P2IO_JAMMA_DDR_P1_FOOT_RIGHT);
|
||||
CheckKeyState("DdrP1Start", P2IO_JAMMA_DDR_P1_START);
|
||||
CheckKeyState("DdrP1SelectL", P2IO_JAMMA_DDR_P1_LEFT);
|
||||
CheckKeyState("DdrP1SelectR", P2IO_JAMMA_DDR_P1_RIGHT);
|
||||
CheckKeyState("DdrP1FootLeft", P2IO_JAMMA_DDR_P1_FOOT_LEFT);
|
||||
CheckKeyState("DdrP1FootDown", P2IO_JAMMA_DDR_P1_FOOT_DOWN);
|
||||
CheckKeyState("DdrP1FootUp", P2IO_JAMMA_DDR_P1_FOOT_UP);
|
||||
CheckKeyState("DdrP1FootRight", P2IO_JAMMA_DDR_P1_FOOT_RIGHT);
|
||||
|
||||
CheckKeyState(L"DdrP2Start", P2IO_JAMMA_DDR_P2_START);
|
||||
CheckKeyState(L"DdrP2SelectL", P2IO_JAMMA_DDR_P2_LEFT);
|
||||
CheckKeyState(L"DdrP2SelectR", P2IO_JAMMA_DDR_P2_RIGHT);
|
||||
CheckKeyState(L"DdrP2FootLeft", P2IO_JAMMA_DDR_P2_FOOT_LEFT);
|
||||
CheckKeyState(L"DdrP2FootDown", P2IO_JAMMA_DDR_P2_FOOT_DOWN);
|
||||
CheckKeyState(L"DdrP2FootUp", P2IO_JAMMA_DDR_P2_FOOT_UP);
|
||||
CheckKeyState(L"DdrP2FootRight", P2IO_JAMMA_DDR_P2_FOOT_RIGHT);
|
||||
CheckKeyState("DdrP2Start", P2IO_JAMMA_DDR_P2_START);
|
||||
CheckKeyState("DdrP2SelectL", P2IO_JAMMA_DDR_P2_LEFT);
|
||||
CheckKeyState("DdrP2SelectR", P2IO_JAMMA_DDR_P2_RIGHT);
|
||||
CheckKeyState("DdrP2FootLeft", P2IO_JAMMA_DDR_P2_FOOT_LEFT);
|
||||
CheckKeyState("DdrP2FootDown", P2IO_JAMMA_DDR_P2_FOOT_DOWN);
|
||||
CheckKeyState("DdrP2FootUp", P2IO_JAMMA_DDR_P2_FOOT_UP);
|
||||
CheckKeyState("DdrP2FootRight", P2IO_JAMMA_DDR_P2_FOOT_RIGHT);
|
||||
}
|
||||
else if (s->f.gameType == GAMETYPE_THRILLDRIVE)
|
||||
{
|
||||
CheckKeyState(L"ThrillDriveStart", P2IO_JAMMA_THRILLDRIVE_START);
|
||||
CheckKeyState("ThrillDriveStart", P2IO_JAMMA_THRILLDRIVE_START);
|
||||
|
||||
CheckKeyState(L"ThrillDriveGearUp", P2IO_JAMMA_THRILLDRIVE_GEARSHIFT_UP);
|
||||
CheckKeyState(L"ThrillDriveGearDown", P2IO_JAMMA_THRILLDRIVE_GEARSHIFT_DOWN);
|
||||
CheckKeyState("ThrillDriveGearUp", P2IO_JAMMA_THRILLDRIVE_GEARSHIFT_UP);
|
||||
CheckKeyState("ThrillDriveGearDown", P2IO_JAMMA_THRILLDRIVE_GEARSHIFT_DOWN);
|
||||
|
||||
const auto isBrakePressed = s->p2dev->GetKeyState(L"ThrillDriveBrake");
|
||||
const auto isBrakePressed = s->p2dev->GetKeyState(P2TEXT("ThrillDriveBrake"));
|
||||
if (isBrakePressed)
|
||||
s->f.brake = 0xffff;
|
||||
else
|
||||
s->f.brake = s->p2dev->GetKeyStateAnalog(L"ThrillDriveBrakeAnalog");
|
||||
s->f.brake = s->p2dev->GetKeyStateAnalog(P2TEXT("ThrillDriveBrakeAnalog"));
|
||||
|
||||
const auto isAccelerationPressed = s->p2dev->GetKeyState(L"ThrillDriveAccel");
|
||||
const auto isAccelerationPressed = s->p2dev->GetKeyState(P2TEXT("ThrillDriveAccel"));
|
||||
if (isAccelerationPressed)
|
||||
{
|
||||
if (!isBrakePressed)
|
||||
s->f.accel = 0xffff;
|
||||
}
|
||||
else
|
||||
s->f.accel = s->p2dev->GetKeyStateAnalog(L"ThrillDriveAccelAnalog");
|
||||
s->f.accel = s->p2dev->GetKeyStateAnalog(P2TEXT("ThrillDriveAccelAnalog"));
|
||||
|
||||
const auto isLeftWheelTurned = s->p2dev->GetKeyState(L"ThrillDriveWheelLeft");
|
||||
const auto isRightWheelTurned = s->p2dev->GetKeyState(L"ThrillDriveWheelRight");
|
||||
const auto isLeftWheelTurned = s->p2dev->GetKeyState(P2TEXT("ThrillDriveWheelLeft"));
|
||||
const auto isRightWheelTurned = s->p2dev->GetKeyState(P2TEXT("ThrillDriveWheelRight"));
|
||||
if (isLeftWheelTurned)
|
||||
s->f.wheel = 0xffff;
|
||||
else if (isRightWheelTurned)
|
||||
s->f.wheel = 0;
|
||||
else if (s->p2dev->IsAnalogKeybindAvailable(L"ThrillDriveWheelAnalog"))
|
||||
s->f.wheel = uint16_t(0xffff - (0xffff * s->p2dev->GetKeyStateAnalog(L"ThrillDriveWheelAnalog")));
|
||||
else if (s->p2dev->IsAnalogKeybindAvailable(P2TEXT("ThrillDriveWheelAnalog")))
|
||||
s->f.wheel = uint16_t(0xffff - (0xffff * s->p2dev->GetKeyStateAnalog(P2TEXT("ThrillDriveWheelAnalog"))));
|
||||
else
|
||||
s->f.wheel = s->wheelCenter;
|
||||
|
||||
|
@ -944,51 +993,51 @@ namespace usb_python2
|
|||
}
|
||||
else if (s->f.gameType == GAMETYPE_DM)
|
||||
{
|
||||
CheckKeyState(L"DmSelectL", P2IO_JAMMA_DM_SELECT_L);
|
||||
CheckKeyState(L"DmSelectR", P2IO_JAMMA_DM_SELECT_R);
|
||||
CheckKeyState(L"DmStart", P2IO_JAMMA_DM_START);
|
||||
CheckKeyState("DmSelectL", P2IO_JAMMA_DM_SELECT_L);
|
||||
CheckKeyState("DmSelectR", P2IO_JAMMA_DM_SELECT_R);
|
||||
CheckKeyState("DmStart", P2IO_JAMMA_DM_START);
|
||||
}
|
||||
else if (s->f.gameType == GAMETYPE_GF)
|
||||
{
|
||||
CheckKeyState(L"GfP1Start", P2IO_JAMMA_GF_P1_START);
|
||||
CheckKeyState(L"GfP1NeckR", P2IO_JAMMA_GF_P1_R);
|
||||
CheckKeyState(L"GfP1NeckG", P2IO_JAMMA_GF_P1_G);
|
||||
CheckKeyState(L"GfP1NeckB", P2IO_JAMMA_GF_P1_B);
|
||||
CheckKeyState(L"GfP1Wail", P2IO_JAMMA_GF_P1_WAILING);
|
||||
CheckKeyState("GfP1Start", P2IO_JAMMA_GF_P1_START);
|
||||
CheckKeyState("GfP1NeckR", P2IO_JAMMA_GF_P1_R);
|
||||
CheckKeyState("GfP1NeckG", P2IO_JAMMA_GF_P1_G);
|
||||
CheckKeyState("GfP1NeckB", P2IO_JAMMA_GF_P1_B);
|
||||
CheckKeyState("GfP1Wail", P2IO_JAMMA_GF_P1_WAILING);
|
||||
|
||||
CheckKeyState(L"GfP2Start", P2IO_JAMMA_GF_P2_START);
|
||||
CheckKeyState(L"GfP2NeckR", P2IO_JAMMA_GF_P2_R);
|
||||
CheckKeyState(L"GfP2NeckG", P2IO_JAMMA_GF_P2_G);
|
||||
CheckKeyState(L"GfP2NeckB", P2IO_JAMMA_GF_P2_B);
|
||||
CheckKeyState(L"GfP2Wail", P2IO_JAMMA_GF_P2_WAILING);
|
||||
CheckKeyState("GfP2Start", P2IO_JAMMA_GF_P2_START);
|
||||
CheckKeyState("GfP2NeckR", P2IO_JAMMA_GF_P2_R);
|
||||
CheckKeyState("GfP2NeckG", P2IO_JAMMA_GF_P2_G);
|
||||
CheckKeyState("GfP2NeckB", P2IO_JAMMA_GF_P2_B);
|
||||
CheckKeyState("GfP2Wail", P2IO_JAMMA_GF_P2_WAILING);
|
||||
}
|
||||
else if (s->f.gameType == GAMETYPE_TOYSMARCH)
|
||||
{
|
||||
CheckKeyState(L"ToysMarchP1Start", P2IO_JAMMA_TOYSMARCH_P1_START);
|
||||
CheckKeyState(L"ToysMarchP1SelectL", P2IO_JAMMA_TOYSMARCH_P1_LEFT);
|
||||
CheckKeyState(L"ToysMarchP1SelectR", P2IO_JAMMA_TOYSMARCH_P1_RIGHT);
|
||||
CheckKeyState(L"ToysMarchP2Start", P2IO_JAMMA_TOYSMARCH_P2_START);
|
||||
CheckKeyState(L"ToysMarchP2SelectL", P2IO_JAMMA_TOYSMARCH_P2_LEFT);
|
||||
CheckKeyState(L"ToysMarchP2SelectR", P2IO_JAMMA_TOYSMARCH_P2_RIGHT);
|
||||
CheckKeyState("ToysMarchP1Start", P2IO_JAMMA_TOYSMARCH_P1_START);
|
||||
CheckKeyState("ToysMarchP1SelectL", P2IO_JAMMA_TOYSMARCH_P1_LEFT);
|
||||
CheckKeyState("ToysMarchP1SelectR", P2IO_JAMMA_TOYSMARCH_P1_RIGHT);
|
||||
CheckKeyState("ToysMarchP2Start", P2IO_JAMMA_TOYSMARCH_P2_START);
|
||||
CheckKeyState("ToysMarchP2SelectL", P2IO_JAMMA_TOYSMARCH_P2_LEFT);
|
||||
CheckKeyState("ToysMarchP2SelectR", P2IO_JAMMA_TOYSMARCH_P2_RIGHT);
|
||||
}
|
||||
else if (s->f.gameType == GAMETYPE_DANCE864)
|
||||
{
|
||||
CheckKeyState(L"Dance864P1Start", P2IO_JAMMA_DANCE864_P1_START);
|
||||
CheckKeyState(L"Dance864P1Left", P2IO_JAMMA_DANCE864_P1_LEFT);
|
||||
CheckKeyState(L"Dance864P1Right", P2IO_JAMMA_DANCE864_P1_RIGHT);
|
||||
CheckKeyState(L"Dance864P2Start", P2IO_JAMMA_DANCE864_P2_START);
|
||||
CheckKeyState(L"Dance864P2Left", P2IO_JAMMA_DANCE864_P2_LEFT);
|
||||
CheckKeyState(L"Dance864P2Right", P2IO_JAMMA_DANCE864_P2_RIGHT);
|
||||
CheckKeyState("Dance864P1Start", P2IO_JAMMA_DANCE864_P1_START);
|
||||
CheckKeyState("Dance864P1Left", P2IO_JAMMA_DANCE864_P1_LEFT);
|
||||
CheckKeyState("Dance864P1Right", P2IO_JAMMA_DANCE864_P1_RIGHT);
|
||||
CheckKeyState("Dance864P2Start", P2IO_JAMMA_DANCE864_P2_START);
|
||||
CheckKeyState("Dance864P2Left", P2IO_JAMMA_DANCE864_P2_LEFT);
|
||||
CheckKeyState("Dance864P2Right", P2IO_JAMMA_DANCE864_P2_RIGHT);
|
||||
|
||||
if (s->f.footPanelIoCheckHack < 0)
|
||||
{
|
||||
CheckKeyState(L"Dance864P1PadLeft", P2IO_JAMMA_DANCE864_P1_PAD_LEFT);
|
||||
CheckKeyState(L"Dance864P1PadCenter", P2IO_JAMMA_DANCE864_P1_PAD_CENTER);
|
||||
CheckKeyState(L"Dance864P1PadRight", P2IO_JAMMA_DANCE864_P1_PAD_RIGHT);
|
||||
CheckKeyState("Dance864P1PadLeft", P2IO_JAMMA_DANCE864_P1_PAD_LEFT);
|
||||
CheckKeyState("Dance864P1PadCenter", P2IO_JAMMA_DANCE864_P1_PAD_CENTER);
|
||||
CheckKeyState("Dance864P1PadRight", P2IO_JAMMA_DANCE864_P1_PAD_RIGHT);
|
||||
|
||||
CheckKeyState(L"Dance864P2PadLeft", P2IO_JAMMA_DANCE864_P2_PAD_LEFT);
|
||||
CheckKeyState(L"Dance864P2PadCenter", P2IO_JAMMA_DANCE864_P2_PAD_CENTER);
|
||||
CheckKeyState(L"Dance864P2PadRight", P2IO_JAMMA_DANCE864_P2_PAD_RIGHT);
|
||||
CheckKeyState("Dance864P2PadLeft", P2IO_JAMMA_DANCE864_P2_PAD_LEFT);
|
||||
CheckKeyState("Dance864P2PadCenter", P2IO_JAMMA_DANCE864_P2_PAD_CENTER);
|
||||
CheckKeyState("Dance864P2PadRight", P2IO_JAMMA_DANCE864_P2_PAD_RIGHT);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1000,25 +1049,25 @@ namespace usb_python2
|
|||
{
|
||||
if (s->f.gameType == GAMETYPE_DM)
|
||||
{
|
||||
CheckKeyStateOneShot(L"DmHihat", P2IO_JAMMA_DM_HIHAT);
|
||||
CheckKeyStateOneShot(L"DmSnare", P2IO_JAMMA_DM_SNARE);
|
||||
CheckKeyStateOneShot(L"DmHighTom", P2IO_JAMMA_DM_HIGH_TOM);
|
||||
CheckKeyStateOneShot(L"DmLowTom", P2IO_JAMMA_DM_LOW_TOM);
|
||||
CheckKeyStateOneShot(L"DmCymbal", P2IO_JAMMA_DM_CYMBAL);
|
||||
CheckKeyStateOneShot("DmHihat", P2IO_JAMMA_DM_HIHAT);
|
||||
CheckKeyStateOneShot("DmSnare", P2IO_JAMMA_DM_SNARE);
|
||||
CheckKeyStateOneShot("DmHighTom", P2IO_JAMMA_DM_HIGH_TOM);
|
||||
CheckKeyStateOneShot("DmLowTom", P2IO_JAMMA_DM_LOW_TOM);
|
||||
CheckKeyStateOneShot("DmCymbal", P2IO_JAMMA_DM_CYMBAL);
|
||||
|
||||
// Bass pedal is not a one shot and can be held techically
|
||||
CheckKeyStateOneShot(L"DmBassDrum", P2IO_JAMMA_DM_BASS_DRUM);
|
||||
CheckKeyStateOneShot("DmBassDrum", P2IO_JAMMA_DM_BASS_DRUM);
|
||||
}
|
||||
else if (s->f.gameType == GAMETYPE_GF)
|
||||
{
|
||||
CheckKeyState(L"GfP1Pick", P2IO_JAMMA_GF_P1_PICK);
|
||||
CheckKeyState(L"GfP2Pick", P2IO_JAMMA_GF_P2_PICK);
|
||||
CheckKeyState("GfP1Pick", P2IO_JAMMA_GF_P1_PICK);
|
||||
CheckKeyState("GfP2Pick", P2IO_JAMMA_GF_P2_PICK);
|
||||
|
||||
KnobStateInc(L"GfP1EffectInc", P2IO_JAMMA_GF_P1_EFFECT1, 0);
|
||||
KnobStateDec(L"GfP1EffectDec", P2IO_JAMMA_GF_P1_EFFECT2, 0);
|
||||
KnobStateInc("GfP1EffectInc", P2IO_JAMMA_GF_P1_EFFECT1, 0);
|
||||
KnobStateDec("GfP1EffectDec", P2IO_JAMMA_GF_P1_EFFECT2, 0);
|
||||
|
||||
KnobStateInc(L"GfP2EffectInc", P2IO_JAMMA_GF_P2_EFFECT1, 1);
|
||||
KnobStateDec(L"GfP2EffectDec", P2IO_JAMMA_GF_P2_EFFECT2, 1);
|
||||
KnobStateInc("GfP2EffectInc", P2IO_JAMMA_GF_P2_EFFECT1, 1);
|
||||
KnobStateDec("GfP2EffectDec", P2IO_JAMMA_GF_P2_EFFECT2, 1);
|
||||
|
||||
s->f.jammaIoStatus |= P2IO_JAMMA_GF_P1_EFFECT3;
|
||||
if (s->f.knobs[0] == 1)
|
||||
|
@ -1150,7 +1199,6 @@ namespace usb_python2
|
|||
|
||||
if (s)
|
||||
{
|
||||
#ifndef PCSX2_CORE
|
||||
// Load the configuration and start SPDIF patcher thread every time a game is started
|
||||
load_configuration(dev);
|
||||
|
||||
|
@ -1160,7 +1208,6 @@ namespace usb_python2
|
|||
mPatchSpdifAudioThread.join();
|
||||
mPatchSpdifAudioThread = std::thread(Python2Patch::PatchSpdifAudioThread, s->p2dev);
|
||||
}
|
||||
#endif
|
||||
|
||||
initialize_device(dev);
|
||||
|
||||
|
@ -1182,7 +1229,10 @@ namespace usb_python2
|
|||
DevCon.WriteLn("%s\n", __func__);
|
||||
|
||||
std::string varApi;
|
||||
#ifndef PCSX2_CORE
|
||||
|
||||
#ifdef PCSX2_CORE
|
||||
varApi = "native";
|
||||
#else
|
||||
#ifdef _WIN32
|
||||
std::wstring tmp;
|
||||
LoadSetting(nullptr, port, TypeName(), N_DEVICE_API, tmp);
|
||||
|
@ -1190,8 +1240,6 @@ namespace usb_python2
|
|||
#else
|
||||
LoadSetting(nullptr, port, TypeName(), N_DEVICE_API, varApi);
|
||||
#endif
|
||||
#else
|
||||
varApi = "noop";
|
||||
#endif
|
||||
|
||||
const UsbPython2ProxyBase* proxy = RegisterUsbPython2::instance().Proxy(varApi);
|
||||
|
|
|
@ -1,18 +1,3 @@
|
|||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2020 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <thread>
|
||||
#include <atomic>
|
||||
|
@ -180,12 +165,11 @@ namespace usb_python2
|
|||
virtual int Port() { return mPort; }
|
||||
virtual void Port(int port) { mPort = port; }
|
||||
|
||||
virtual void UpdateKeyStates(std::wstring keybind) = 0;
|
||||
virtual bool GetKeyState(std::wstring keybind) = 0;
|
||||
virtual bool GetKeyStateOneShot(std::wstring keybind) = 0;
|
||||
virtual double GetKeyStateAnalog(std::wstring keybind) = 0;
|
||||
virtual bool IsKeybindAvailable(std::wstring keybind) = 0;
|
||||
virtual bool IsAnalogKeybindAvailable(std::wstring keybind) = 0;
|
||||
virtual void UpdateKeyStates(TSTDSTRING keybind) = 0;
|
||||
virtual bool GetKeyState(TSTDSTRING keybind) = 0;
|
||||
virtual bool GetKeyStateOneShot(TSTDSTRING keybind) = 0;
|
||||
virtual double GetKeyStateAnalog(TSTDSTRING keybind) = 0;
|
||||
virtual bool IsAnalogKeybindAvailable(TSTDSTRING keybind) = 0;
|
||||
|
||||
protected:
|
||||
int mPort;
|
||||
|
|
|
@ -137,6 +137,10 @@ static u32 s_frame_advance_count = 0;
|
|||
static u32 s_mxcsr_saved;
|
||||
static std::optional<LimiterModeType> s_limiter_mode_prior_to_hold_interaction;
|
||||
|
||||
static bool s_is_python2 = false;
|
||||
static u32 s_python2_crc = 0;
|
||||
static std::string s_python2_serial;
|
||||
|
||||
bool VMManager::PerformEarlyHardwareChecks(const char** error)
|
||||
{
|
||||
#define COMMON_DOWNLOAD_MESSAGE \
|
||||
|
@ -630,6 +634,11 @@ void VMManager::UpdateRunningGame(bool resetting, bool game_starting)
|
|||
new_serial = GSDumpReplayer::GetDumpSerial();
|
||||
}
|
||||
|
||||
if (s_is_python2) {
|
||||
new_crc = ElfCRC = s_python2_crc;
|
||||
new_serial = s_python2_serial;
|
||||
}
|
||||
|
||||
if (!resetting && s_game_crc == new_crc && s_game_serial == new_serial)
|
||||
return;
|
||||
|
||||
|
@ -791,6 +800,16 @@ bool VMManager::ApplyBootParameters(const VMBootParameters& params, std::string*
|
|||
EmuConfig.UseBOOT2Injection = true;
|
||||
}
|
||||
|
||||
s_is_python2 = params.is_python2.has_value() && params.is_python2.value();
|
||||
if (s_is_python2) {
|
||||
// Set parameters for Python 2
|
||||
s_python2_crc = params.python2_crc.has_value() ? params.python2_crc.value() : 0;
|
||||
s_python2_serial = params.python2_serial.has_value() ? params.python2_serial.value() : "";
|
||||
} else {
|
||||
s_python2_crc = 0;
|
||||
s_python2_serial = "";
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -839,6 +858,8 @@ bool VMManager::Initialize(const VMBootParameters& boot_params)
|
|||
if (!ApplyBootParameters(boot_params, &state_to_load))
|
||||
return false;
|
||||
|
||||
UpdateRunningGame(true, false); // Add this here so we can get the loaded settings in the Python 2 USB code
|
||||
|
||||
EmuConfig.LimiterMode = GetInitialLimiterMode();
|
||||
|
||||
// early out if we don't have a bios
|
||||
|
@ -889,17 +910,6 @@ bool VMManager::Initialize(const VMBootParameters& boot_params)
|
|||
PADshutdown();
|
||||
};
|
||||
|
||||
Console.WriteLn("Opening DEV9...");
|
||||
if (DEV9init() != 0 || DEV9open() != 0)
|
||||
{
|
||||
Host::ReportErrorAsync("Startup Error", "Failed to initialize DEV9.");
|
||||
return false;
|
||||
}
|
||||
ScopedGuard close_dev9 = []() {
|
||||
DEV9close();
|
||||
DEV9shutdown();
|
||||
};
|
||||
|
||||
Console.WriteLn("Opening USB...");
|
||||
if (USBinit() != 0 || USBopen(Host::GetHostDisplay()->GetWindowInfo()) != 0)
|
||||
{
|
||||
|
@ -911,6 +921,17 @@ bool VMManager::Initialize(const VMBootParameters& boot_params)
|
|||
USBshutdown();
|
||||
};
|
||||
|
||||
Console.WriteLn("Opening DEV9...");
|
||||
if (DEV9init() != 0 || DEV9open() != 0)
|
||||
{
|
||||
Host::ReportErrorAsync("Startup Error", "Failed to initialize DEV9.");
|
||||
return false;
|
||||
}
|
||||
ScopedGuard close_dev9 = []() {
|
||||
DEV9close();
|
||||
DEV9shutdown();
|
||||
};
|
||||
|
||||
Console.WriteLn("Opening FW...");
|
||||
if (FWopen() != 0)
|
||||
{
|
||||
|
|
|
@ -48,6 +48,11 @@ struct VMBootParameters
|
|||
|
||||
std::optional<bool> fast_boot;
|
||||
std::optional<bool> fullscreen;
|
||||
|
||||
// For Python 2
|
||||
std::optional<bool> is_python2;
|
||||
std::optional<u32> python2_crc;
|
||||
std::optional<std::string> python2_serial;
|
||||
};
|
||||
|
||||
namespace VMManager
|
||||
|
|
|
@ -33,52 +33,52 @@
|
|||
<TargetName>$(EXEString)</TargetName>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LibraryPath>$(SolutionDir)3rdparty\libmmmagic\lib\windows-64bit;$(SolutionDir)3rdparty\bemanitools;$(SolutionDir)3rdparty\libusb\MS64\dll;$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64)</LibraryPath>
|
||||
<IncludePath>$(SolutionDir)3rdparty\libmmmagic\include;$(SolutionDir)3rdparty\libusb\include;$(VC_IncludePath);$(WindowsSDK_IncludePath);</IncludePath>
|
||||
<LibraryPath>$(SolutionDir)3rdparty\libmmmagic\lib\windows-64bit;$(SolutionDir)3rdparty\bemanitools;$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64)</LibraryPath>
|
||||
<IncludePath>$(SolutionDir)\3rdparty\libusb\libusb\libusb;$(SolutionDir)3rdparty\libmmmagic\include;$(VC_IncludePath);$(WindowsSDK_IncludePath);</IncludePath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug AVX2|x64'">
|
||||
<LibraryPath>$(SolutionDir)3rdparty\libmmmagic\lib\windows-64bit;$(SolutionDir)3rdparty\bemanitools;$(SolutionDir)3rdparty\libusb\MS64\dll;$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64)</LibraryPath>
|
||||
<IncludePath>$(SolutionDir)3rdparty\libmmmagic\include;$(SolutionDir)3rdparty\libusb\include;$(VC_IncludePath);$(WindowsSDK_IncludePath);</IncludePath>
|
||||
<LibraryPath>$(SolutionDir)3rdparty\libmmmagic\lib\windows-64bit;$(SolutionDir)3rdparty\bemanitools;$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64)</LibraryPath>
|
||||
<IncludePath>$(SolutionDir)\3rdparty\libusb\libusb\libusb;$(SolutionDir)3rdparty\libmmmagic\include;$(VC_IncludePath);$(WindowsSDK_IncludePath);</IncludePath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Devel|x64'">
|
||||
<LibraryPath>$(SolutionDir)3rdparty\libmmmagic\lib\windows-64bit;$(SolutionDir)3rdparty\bemanitools;$(SolutionDir)3rdparty\libusb\MS64\dll;$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64)</LibraryPath>
|
||||
<IncludePath>$(SolutionDir)3rdparty\libmmmagic\include;$(SolutionDir)3rdparty\libusb\include;$(VC_IncludePath);$(WindowsSDK_IncludePath);</IncludePath>
|
||||
<LibraryPath>$(SolutionDir)3rdparty\libmmmagic\lib\windows-64bit;$(SolutionDir)3rdparty\bemanitools;$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64)</LibraryPath>
|
||||
<IncludePath>$(SolutionDir)\3rdparty\libusb\libusb\libusb;$(SolutionDir)3rdparty\libmmmagic\include;$(VC_IncludePath);$(WindowsSDK_IncludePath);</IncludePath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Devel AVX2|x64'">
|
||||
<LibraryPath>$(SolutionDir)3rdparty\libmmmagic\lib\windows-64bit;$(SolutionDir)3rdparty\bemanitools;$(SolutionDir)3rdparty\libusb\MS64\dll;$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64)</LibraryPath>
|
||||
<IncludePath>$(SolutionDir)3rdparty\libmmmagic\include;$(SolutionDir)3rdparty\libusb\include;$(VC_IncludePath);$(WindowsSDK_IncludePath);</IncludePath>
|
||||
<LibraryPath>$(SolutionDir)3rdparty\libmmmagic\lib\windows-64bit;$(SolutionDir)3rdparty\bemanitools;$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64)</LibraryPath>
|
||||
<IncludePath>$(SolutionDir)\3rdparty\libusb\libusb\libusb;$(SolutionDir)3rdparty\libmmmagic\include;$(VC_IncludePath);$(WindowsSDK_IncludePath);</IncludePath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LibraryPath>$(SolutionDir)3rdparty\libmmmagic\lib\windows-64bit;$(SolutionDir)3rdparty\bemanitools;$(SolutionDir)3rdparty\libusb\MS64\dll;$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64)</LibraryPath>
|
||||
<IncludePath>$(SolutionDir)3rdparty\libmmmagic\include;$(SolutionDir)3rdparty\libusb\include;$(VC_IncludePath);$(WindowsSDK_IncludePath);</IncludePath>
|
||||
<LibraryPath>$(SolutionDir)3rdparty\libmmmagic\lib\windows-64bit;$(SolutionDir)3rdparty\bemanitools;$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64)</LibraryPath>
|
||||
<IncludePath>$(SolutionDir)\3rdparty\libusb\libusb\libusb;$(SolutionDir)3rdparty\libmmmagic\include;$(VC_IncludePath);$(WindowsSDK_IncludePath);</IncludePath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release AVX2|x64'">
|
||||
<LibraryPath>$(SolutionDir)3rdparty\libmmmagic\lib\windows-64bit;$(SolutionDir)3rdparty\bemanitools;$(SolutionDir)3rdparty\libusb\MS64\dll;$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64)</LibraryPath>
|
||||
<IncludePath>$(SolutionDir)3rdparty\libmmmagic\include;$(SolutionDir)3rdparty\libusb\include;$(VC_IncludePath);$(WindowsSDK_IncludePath);</IncludePath>
|
||||
<LibraryPath>$(SolutionDir)3rdparty\libmmmagic\lib\windows-64bit;$(SolutionDir)3rdparty\bemanitools;$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64)</LibraryPath>
|
||||
<IncludePath>$(SolutionDir)\3rdparty\libusb\libusb\libusb;$(SolutionDir)3rdparty\libmmmagic\include;$(VC_IncludePath);$(WindowsSDK_IncludePath);</IncludePath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LibraryPath>$(SolutionDir)3rdparty\libmmmagic\lib\windows-32bit;$(SolutionDir)3rdparty\bemanitools;$(SolutionDir)3rdparty\libusb\MS32\dll;$(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86)</LibraryPath>
|
||||
<IncludePath>$(SolutionDir)3rdparty\libmmmagic\include;$(SolutionDir)3rdparty\libusb\include;$(VC_IncludePath);$(WindowsSDK_IncludePath);</IncludePath>
|
||||
<LibraryPath>$(SolutionDir)3rdparty\libmmmagic\lib\windows-32bit;$(SolutionDir)3rdparty\bemanitools;$(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86)</LibraryPath>
|
||||
<IncludePath>$(SolutionDir)3rdparty\libmmmagic\include;$(VC_IncludePath);$(WindowsSDK_IncludePath);</IncludePath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug AVX2|Win32'">
|
||||
<LibraryPath>$(SolutionDir)3rdparty\libmmmagic\lib\windows-32bit;$(SolutionDir)3rdparty\bemanitools;$(SolutionDir)3rdparty\libusb\MS32\dll;$(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86)</LibraryPath>
|
||||
<IncludePath>$(SolutionDir)3rdparty\libmmmagic\include;$(SolutionDir)3rdparty\libusb\include;$(VC_IncludePath);$(WindowsSDK_IncludePath);</IncludePath>
|
||||
<LibraryPath>$(SolutionDir)3rdparty\libmmmagic\lib\windows-32bit;$(SolutionDir)3rdparty\bemanitools;$(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86)</LibraryPath>
|
||||
<IncludePath>$(SolutionDir)3rdparty\libmmmagic\include;$(VC_IncludePath);$(WindowsSDK_IncludePath);</IncludePath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Devel|Win32'">
|
||||
<LibraryPath>$(SolutionDir)3rdparty\libmmmagic\lib\windows-32bit;$(SolutionDir)3rdparty\bemanitools;$(SolutionDir)3rdparty\libusb\MS32\dll;$(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86)</LibraryPath>
|
||||
<IncludePath>$(SolutionDir)3rdparty\libmmmagic\include;$(SolutionDir)3rdparty\libusb\include;$(VC_IncludePath);$(WindowsSDK_IncludePath);</IncludePath>
|
||||
<LibraryPath>$(SolutionDir)3rdparty\libmmmagic\lib\windows-32bit;$(SolutionDir)3rdparty\bemanitools;$(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86)</LibraryPath>
|
||||
<IncludePath>$(SolutionDir)3rdparty\libmmmagic\include;$(VC_IncludePath);$(WindowsSDK_IncludePath);</IncludePath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Devel AVX2|Win32'">
|
||||
<LibraryPath>$(SolutionDir)3rdparty\libmmmagic\lib\windows-32bit;$(SolutionDir)3rdparty\bemanitools;$(SolutionDir)3rdparty\libusb\MS32\dll;$(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86)</LibraryPath>
|
||||
<IncludePath>$(SolutionDir)3rdparty\libmmmagic\include;$(SolutionDir)3rdparty\libusb\include;$(VC_IncludePath);$(WindowsSDK_IncludePath);</IncludePath>
|
||||
<LibraryPath>$(SolutionDir)3rdparty\libmmmagic\lib\windows-32bit;$(SolutionDir)3rdparty\bemanitools;$(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86)</LibraryPath>
|
||||
<IncludePath>$(SolutionDir)3rdparty\libmmmagic\include;$(VC_IncludePath);$(WindowsSDK_IncludePath);</IncludePath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LibraryPath>$(SolutionDir)3rdparty\libmmmagic\lib\windows-32bit;$(SolutionDir)3rdparty\bemanitools;$(SolutionDir)3rdparty\libusb\MS32\dll;$(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86)</LibraryPath>
|
||||
<IncludePath>$(SolutionDir)3rdparty\libmmmagic\include;$(SolutionDir)3rdparty\libusb\include;$(VC_IncludePath);$(WindowsSDK_IncludePath);</IncludePath>
|
||||
<LibraryPath>$(SolutionDir)3rdparty\libmmmagic\lib\windows-32bit;$(SolutionDir)3rdparty\bemanitools;$(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86)</LibraryPath>
|
||||
<IncludePath>$(SolutionDir)3rdparty\libmmmagic\include;$(VC_IncludePath);$(WindowsSDK_IncludePath);</IncludePath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release AVX2|Win32'">
|
||||
<LibraryPath>$(SolutionDir)3rdparty\libmmmagic\lib\windows-32bit;$(SolutionDir)3rdparty\bemanitools;$(SolutionDir)3rdparty\libusb\MS32\dll;$(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86)</LibraryPath>
|
||||
<IncludePath>$(SolutionDir)3rdparty\libmmmagic\include;$(SolutionDir)3rdparty\libusb\include;$(VC_IncludePath);$(WindowsSDK_IncludePath);</IncludePath>
|
||||
<LibraryPath>$(SolutionDir)3rdparty\libmmmagic\lib\windows-32bit;$(SolutionDir)3rdparty\bemanitools;$(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86)</LibraryPath>
|
||||
<IncludePath>$(SolutionDir)3rdparty\libmmmagic\include;$(VC_IncludePath);$(WindowsSDK_IncludePath);</IncludePath>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
|
@ -120,7 +120,7 @@
|
|||
<Link>
|
||||
<LargeAddressAware>Yes</LargeAddressAware>
|
||||
<AdditionalDependencies>comctl32.lib;ws2_32.lib;shlwapi.lib;winmm.lib;rpcrt4.lib;iphlpapi.lib;dsound.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>libmmmagic.a;libusb-1.0.lib;dxguid.lib;dinput8.lib;hid.lib;PowrProf.lib;d3dcompiler.lib;d3d11.lib;dxgi.lib;strmiids.lib;opengl32.lib;comsuppw.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>libmmmagic.a;dxguid.lib;dinput8.lib;hid.lib;PowrProf.lib;d3dcompiler.lib;d3d11.lib;dxgi.lib;strmiids.lib;opengl32.lib;comsuppw.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<ImageHasSafeExceptionHandlers Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</ImageHasSafeExceptionHandlers>
|
||||
<ImageHasSafeExceptionHandlers Condition="'$(Configuration)|$(Platform)'=='Debug AVX2|x64'">false</ImageHasSafeExceptionHandlers>
|
||||
<ImageHasSafeExceptionHandlers Condition="'$(Configuration)|$(Platform)'=='Devel|x64'">false</ImageHasSafeExceptionHandlers>
|
||||
|
@ -134,42 +134,6 @@
|
|||
<ImageHasSafeExceptionHandlers Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</ImageHasSafeExceptionHandlers>
|
||||
<ImageHasSafeExceptionHandlers Condition="'$(Configuration)|$(Platform)'=='Release AVX2|Win32'">false</ImageHasSafeExceptionHandlers>
|
||||
</Link>
|
||||
<PostBuildEvent>
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">xcopy /y $(SolutionDir)3rdparty\libusb\MS64\dll\libusb-1.0.dll $(OutDirFullPath)</Command>
|
||||
</PostBuildEvent>
|
||||
<PostBuildEvent>
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Debug AVX2|x64'">xcopy /y $(SolutionDir)3rdparty\libusb\MS64\dll\libusb-1.0.dll $(OutDirFullPath)</Command>
|
||||
</PostBuildEvent>
|
||||
<PostBuildEvent>
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Devel|x64'">xcopy /y $(SolutionDir)3rdparty\libusb\MS64\dll\libusb-1.0.dll $(OutDirFullPath)</Command>
|
||||
</PostBuildEvent>
|
||||
<PostBuildEvent>
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Devel AVX2|x64'">xcopy /y $(SolutionDir)3rdparty\libusb\MS64\dll\libusb-1.0.dll $(OutDirFullPath)</Command>
|
||||
</PostBuildEvent>
|
||||
<PostBuildEvent>
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">xcopy /y $(SolutionDir)3rdparty\libusb\MS64\dll\libusb-1.0.dll $(OutDirFullPath)</Command>
|
||||
</PostBuildEvent>
|
||||
<PostBuildEvent>
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Release AVX2|x64'">xcopy /y $(SolutionDir)3rdparty\libusb\MS64\dll\libusb-1.0.dll $(OutDirFullPath)</Command>
|
||||
</PostBuildEvent>
|
||||
<PostBuildEvent>
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">xcopy /y $(SolutionDir)3rdparty\libusb\MS32\dll\libusb-1.0.dll $(OutDirFullPath)</Command>
|
||||
</PostBuildEvent>
|
||||
<PostBuildEvent>
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Debug AVX2|Win32'">xcopy /y $(SolutionDir)3rdparty\libusb\MS32\dll\libusb-1.0.dll $(OutDirFullPath)</Command>
|
||||
</PostBuildEvent>
|
||||
<PostBuildEvent>
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Devel|Win32'">xcopy /y $(SolutionDir)3rdparty\libusb\MS32\dll\libusb-1.0.dll $(OutDirFullPath)</Command>
|
||||
</PostBuildEvent>
|
||||
<PostBuildEvent>
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Devel AVX2|Win32'">xcopy /y $(SolutionDir)3rdparty\libusb\MS32\dll\libusb-1.0.dll $(OutDirFullPath)</Command>
|
||||
</PostBuildEvent>
|
||||
<PostBuildEvent>
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">xcopy /y $(SolutionDir)3rdparty\libusb\MS32\dll\libusb-1.0.dll $(OutDirFullPath)</Command>
|
||||
</PostBuildEvent>
|
||||
<PostBuildEvent>
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Release AVX2|Win32'">xcopy /y $(SolutionDir)3rdparty\libusb\MS32\dll\libusb-1.0.dll $(OutDirFullPath)</Command>
|
||||
</PostBuildEvent>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\bin\resources\shaders\vulkan\convert.glsl" />
|
||||
|
@ -595,19 +559,19 @@
|
|||
<ClCompile Include="USB\usb-pad\usb-pad.cpp" />
|
||||
<ClCompile Include="USB\usb-pad\usb-seamic.cpp" />
|
||||
<ClCompile Include="USB\usb-python2\api_init_win32_hid.cpp" />
|
||||
<ClCompile Include="USB\usb-python2\btools\python2-config-btools.cpp" />
|
||||
<ClCompile Include="USB\usb-python2\btools\usb-python2-btools.cpp" />
|
||||
<ClCompile Include="USB\usb-python2\devices\acio.cpp" />
|
||||
<ClCompile Include="USB\usb-python2\devices\ddr_extio.cpp" />
|
||||
<ClCompile Include="USB\usb-python2\devices\icca.cpp" />
|
||||
<ClCompile Include="USB\usb-python2\devices\thrilldrive_belt.cpp" />
|
||||
<ClCompile Include="USB\usb-python2\devices\thrilldrive_handle.cpp" />
|
||||
<ClCompile Include="USB\usb-python2\devices\toysmarch_drumpad.cpp" />
|
||||
<ClCompile Include="USB\usb-python2\passthrough\python2-config-passthrough.cpp" />
|
||||
<ClCompile Include="USB\usb-python2\passthrough\usb-python2-passthrough.cpp" />
|
||||
<ClCompile Include="USB\usb-python2\inputs\btools\python2-config-btools.cpp" />
|
||||
<ClCompile Include="USB\usb-python2\inputs\btools\usb-python2-btools.cpp" />
|
||||
<ClCompile Include="USB\usb-python2\inputs\passthrough\python2-config-passthrough.cpp" />
|
||||
<ClCompile Include="USB\usb-python2\inputs\passthrough\usb-python2-passthrough.cpp" />
|
||||
<ClCompile Include="USB\usb-python2\inputs\raw\python2-config-raw.cpp" />
|
||||
<ClCompile Include="USB\usb-python2\inputs\raw\usb-python2-raw.cpp" />
|
||||
<ClCompile Include="USB\usb-python2\patches.cpp" />
|
||||
<ClCompile Include="USB\usb-python2\raw\python2-config-raw.cpp" />
|
||||
<ClCompile Include="USB\usb-python2\raw\usb-python2-raw.cpp" />
|
||||
<ClCompile Include="USB\usb-python2\usb-python2.cpp" />
|
||||
<ClCompile Include="USB\usb-printer\usb-printer.cpp" />
|
||||
<ClCompile Include="USB\USB.cpp" />
|
||||
|
@ -1125,7 +1089,6 @@
|
|||
<ClInclude Include="USB\usb-pad\raw\raw-config-res.h" />
|
||||
<ClInclude Include="USB\usb-pad\raw\usb-pad-raw.h" />
|
||||
<ClInclude Include="USB\usb-pad\usb-pad.h" />
|
||||
<ClInclude Include="USB\usb-python2\btools\usb-python2-btools.h" />
|
||||
<ClInclude Include="USB\usb-python2\devices\acio.h" />
|
||||
<ClInclude Include="USB\usb-python2\devices\icca.h" />
|
||||
<ClInclude Include="USB\usb-python2\devices\thrilldrive_belt.h" />
|
||||
|
@ -1133,11 +1096,12 @@
|
|||
<ClInclude Include="USB\usb-python2\devices\thrilldrive_handle.h" />
|
||||
<ClInclude Include="USB\usb-python2\devices\input_device.h" />
|
||||
<ClInclude Include="USB\usb-python2\devices\toysmarch_drumpad.h" />
|
||||
<ClInclude Include="USB\usb-python2\passthrough\usb-python2-passthrough.h" />
|
||||
<ClInclude Include="USB\usb-python2\inputs\btools\usb-python2-btools.h" />
|
||||
<ClInclude Include="USB\usb-python2\inputs\passthrough\usb-python2-passthrough.h" />
|
||||
<ClInclude Include="USB\usb-python2\inputs\raw\python2-config-raw-res.h" />
|
||||
<ClInclude Include="USB\usb-python2\inputs\raw\usb-python2-raw.h" />
|
||||
<ClInclude Include="USB\usb-python2\patches.h" />
|
||||
<ClInclude Include="USB\usb-python2\python2proxy.h" />
|
||||
<ClInclude Include="USB\usb-python2\raw\python2-config-raw-res.h" />
|
||||
<ClInclude Include="USB\usb-python2\raw\usb-python2-raw.h" />
|
||||
<ClInclude Include="USB\usb-python2\usb-python2.h" />
|
||||
<ClInclude Include="USB\usb-printer\usb-printer.h" />
|
||||
<ClInclude Include="USB\USB.h" />
|
||||
|
@ -1291,7 +1255,7 @@
|
|||
<ResourceCompile Include="SPU2\Windows\SPU2.rc" />
|
||||
<ResourceCompile Include="USB\usb-pad\dx\versionproxy.rc" />
|
||||
<ResourceCompile Include="USB\usb-pad\raw\raw-config.rc" />
|
||||
<ResourceCompile Include="USB\usb-python2\raw\python2-config-raw.rc" />
|
||||
<ResourceCompile Include="USB\usb-python2\inputs\raw\python2-config-raw.rc" />
|
||||
<ResourceCompile Include="USB\Win32\USBDialog.rc" />
|
||||
<ResourceCompile Include="windows\wxResources.rc" />
|
||||
</ItemGroup>
|
||||
|
@ -1356,6 +1320,9 @@
|
|||
<ProjectReference Include="$(SolutionDir)3rdparty\imgui\imgui.vcxproj">
|
||||
<Project>{88fb34ec-845e-4f21-a552-f1573b9ed167}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\3rdparty\libusb\libusb.vcxproj">
|
||||
<Project>{349ee8f9-7d25-4909-aaf5-ff3fade72187}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\3rdparty\libzip\libzip.vcxproj">
|
||||
<Project>{20b2e9fe-f020-42a0-b324-956f5b06ea68}</Project>
|
||||
</ProjectReference>
|
||||
|
|
|
@ -289,9 +289,6 @@
|
|||
<Filter Include="System\Ps2\USB\usb-python2">
|
||||
<UniqueIdentifier>{bb0f1450-811a-47f7-9224-af7979108bea}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="System\Ps2\USB\usb-python2\raw">
|
||||
<UniqueIdentifier>{6e7cffc4-c6a0-4b63-8672-ad561a0fc19a}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="System\Ps2\USB\usb-python2\devices">
|
||||
<UniqueIdentifier>{bc0b7c38-447a-4cfc-a13d-f135eed7338a}</UniqueIdentifier>
|
||||
</Filter>
|
||||
|
@ -304,12 +301,6 @@
|
|||
<Filter Include="System\Ps2\USB\usb-python2\devices\toysmarch">
|
||||
<UniqueIdentifier>{02363106-af40-450a-9ec4-d28177b58106}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="System\Ps2\USB\usb-python2\passthrough">
|
||||
<UniqueIdentifier>{05dcd9a6-e244-49b2-aa3e-d5b1513cd2ca}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="System\Ps2\USB\usb-python2\btools">
|
||||
<UniqueIdentifier>{5f3a7bab-b96f-4123-8e5c-1c447c0403f4}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="System\Ps2\GS\GIF">
|
||||
<UniqueIdentifier>{78f5077b-255e-435e-9a51-352171dfaee8}</UniqueIdentifier>
|
||||
</Filter>
|
||||
|
@ -1736,9 +1727,6 @@
|
|||
<ClCompile Include="USB\usb-python2\usb-python2.cpp">
|
||||
<Filter>System\Ps2\USB\usb-python2</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="USB\usb-python2\raw\usb-python2-raw.cpp">
|
||||
<Filter>System\Ps2\USB\usb-python2\raw</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="USB\usb-python2\devices\acio.cpp">
|
||||
<Filter>System\Ps2\USB\usb-python2\devices</Filter>
|
||||
</ClCompile>
|
||||
|
@ -1760,15 +1748,6 @@
|
|||
<ClCompile Include="USB\usb-python2\devices\toysmarch_drumpad.cpp">
|
||||
<Filter>System\Ps2\USB\usb-python2\devices\toysmarch</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="USB\usb-python2\passthrough\usb-python2-passthrough.cpp">
|
||||
<Filter>System\Ps2\USB\usb-python2\passthrough</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="USB\usb-python2\raw\python2-config-raw.cpp">
|
||||
<Filter>System\Ps2\USB\usb-python2\raw</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="USB\usb-python2\passthrough\python2-config-passthrough.cpp">
|
||||
<Filter>System\Ps2\USB\usb-python2\passthrough</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="gui\AppHost.cpp">
|
||||
<Filter>AppHost</Filter>
|
||||
</ClCompile>
|
||||
|
@ -1811,12 +1790,6 @@
|
|||
<ClCompile Include="GS\Renderers\HW\GSTextureReplacementLoaders.cpp">
|
||||
<Filter>System\Ps2\GS\Renderers\Hardware</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="USB\usb-python2\btools\python2-config-btools.cpp">
|
||||
<Filter>System\Ps2\USB\usb-python2\btools</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="USB\usb-python2\btools\usb-python2-btools.cpp">
|
||||
<Filter>System\Ps2\USB\usb-python2\btools</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="x86\iR5900Analysis.cpp">
|
||||
<Filter>System\Ps2\EmotionEngine\EE\Dynarec</Filter>
|
||||
</ClCompile>
|
||||
|
@ -1865,6 +1838,12 @@
|
|||
<ClCompile Include="gui\PathUtils.cpp">
|
||||
<Filter>AppHost</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="USB\usb-python2\inputs\btools\python2-config-btools.cpp" />
|
||||
<ClCompile Include="USB\usb-python2\inputs\btools\usb-python2-btools.cpp" />
|
||||
<ClCompile Include="USB\usb-python2\inputs\passthrough\python2-config-passthrough.cpp" />
|
||||
<ClCompile Include="USB\usb-python2\inputs\passthrough\usb-python2-passthrough.cpp" />
|
||||
<ClCompile Include="USB\usb-python2\inputs\raw\python2-config-raw.cpp" />
|
||||
<ClCompile Include="USB\usb-python2\inputs\raw\usb-python2-raw.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Patch.h">
|
||||
|
@ -2995,9 +2974,6 @@
|
|||
<ClInclude Include="USB\usb-python2\usb-python2.h">
|
||||
<Filter>System\Ps2\USB\usb-python2</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="USB\usb-python2\raw\usb-python2-raw.h">
|
||||
<Filter>System\Ps2\USB\usb-python2\raw</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="USB\usb-python2\devices\acio.h">
|
||||
<Filter>System\Ps2\USB\usb-python2\devices</Filter>
|
||||
</ClInclude>
|
||||
|
@ -3022,15 +2998,6 @@
|
|||
<ClInclude Include="USB\usb-python2\devices\toysmarch_drumpad.h">
|
||||
<Filter>System\Ps2\USB\usb-python2\devices\toysmarch</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="USB\usb-python2\btools\usb-python2-btools.h">
|
||||
<Filter>System\Ps2\USB\usb-python2\btools</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="USB\usb-python2\passthrough\usb-python2-passthrough.h">
|
||||
<Filter>System\Ps2\USB\usb-python2\passthrough</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="USB\usb-python2\raw\python2-config-raw-res.h">
|
||||
<Filter>System\Ps2\USB\usb-python2\raw</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="PAD\Gamepad.h">
|
||||
<Filter>System\Ps2\PAD</Filter>
|
||||
</ClInclude>
|
||||
|
@ -3102,6 +3069,10 @@
|
|||
<ClInclude Include="gui\StringHelpers.h">
|
||||
<Filter>AppHost</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="USB\usb-python2\inputs\btools\usb-python2-btools.h" />
|
||||
<ClInclude Include="USB\usb-python2\inputs\passthrough\usb-python2-passthrough.h" />
|
||||
<ClInclude Include="USB\usb-python2\inputs\raw\python2-config-raw-res.h" />
|
||||
<ClInclude Include="USB\usb-python2\inputs\raw\usb-python2-raw.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="windows\wxResources.rc">
|
||||
|
@ -3131,9 +3102,7 @@
|
|||
<ResourceCompile Include="GS\GS.rc">
|
||||
<Filter>System\Ps2\GS</Filter>
|
||||
</ResourceCompile>
|
||||
<ResourceCompile Include="USB\usb-python2\raw\python2-config-raw.rc">
|
||||
<Filter>System\Ps2\USB\usb-python2\raw</Filter>
|
||||
</ResourceCompile>
|
||||
<ResourceCompile Include="USB\usb-python2\inputs\raw\python2-config-raw.rc" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<CustomBuildStep Include="rdebug\deci2.h">
|
||||
|
|
|
@ -46,6 +46,7 @@
|
|||
<AdditionalIncludeDirectories>$(SolutionDir)3rdparty\sdl2\include;$(SolutionDir)3rdparty\sdl2\SDL\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)3rdparty\libzip;$(SolutionDir)3rdparty\libzip\libzip\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)3rdparty\d3d12memalloc\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)3rdparty\libusb\libusb\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SolutionDir)3rdparty\zstd\zstd\lib</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SolutionDir)3rdparty\cpuinfo\include</AdditionalIncludeDirectories>
|
||||
<ExceptionHandling>Async</ExceptionHandling>
|
||||
|
@ -317,7 +318,6 @@
|
|||
<ClCompile Include="GS\Renderers\SW\GSVertexSW.cpp" />
|
||||
<ClCompile Include="GS\Renderers\Common\GSVertexTrace.cpp" />
|
||||
<ClCompile Include="SPU2\Windows\SndOut_XAudio2.cpp" />
|
||||
<ClCompile Include="USB\USBNull.cpp" />
|
||||
<ClCompile Include="Dump.cpp" />
|
||||
<ClCompile Include="VMManager.cpp" />
|
||||
<ClCompile Include="windows\Optimus.cpp" />
|
||||
|
@ -446,6 +446,34 @@
|
|||
<ClCompile Include="CDVD\IsoFS\IsoFile.cpp" />
|
||||
<ClCompile Include="CDVD\IsoFS\IsoFS.cpp" />
|
||||
<ClCompile Include="CDVD\IsoFS\IsoFSCDVD.cpp" />
|
||||
<ClCompile Include="USB\USB.cpp" />
|
||||
<ClCompile Include="USB\deviceproxy.cpp" />
|
||||
<ClCompile Include="USB\device_init.cpp" />
|
||||
<ClCompile Include="USB\qemu-usb\bus.cpp" />
|
||||
<ClCompile Include="USB\qemu-usb\core.cpp" />
|
||||
<ClCompile Include="USB\qemu-usb\desc.cpp" />
|
||||
<ClCompile Include="USB\qemu-usb\glib.cpp" />
|
||||
<ClCompile Include="USB\qemu-usb\hid.cpp" />
|
||||
<ClCompile Include="USB\qemu-usb\input-keymap-qcode-to-qnum.cpp" />
|
||||
<ClCompile Include="USB\qemu-usb\input-keymap-win32-to-qcode.cpp" />
|
||||
<ClCompile Include="USB\qemu-usb\iov.cpp" />
|
||||
<ClCompile Include="USB\qemu-usb\usb-ohci.cpp" />
|
||||
<ClCompile Include="USB\qemu-usb\vl.cpp" />
|
||||
<ClCompile Include="USB\shared\shared_usb.cpp" />
|
||||
<ClCompile Include="USB\shared\inifile_usb.cpp" />
|
||||
<ClCompile Include="USB\shared\ringbuffer.cpp" />
|
||||
<ClCompile Include="USB\usb-python2\usb-python2.cpp" />
|
||||
<ClCompile Include="USB\usb-python2\devices\acio.cpp" />
|
||||
<ClCompile Include="USB\usb-python2\devices\ddr_extio.cpp" />
|
||||
<ClCompile Include="USB\usb-python2\devices\icca.cpp" />
|
||||
<ClCompile Include="USB\usb-python2\devices\thrilldrive_belt.cpp" />
|
||||
<ClCompile Include="USB\usb-python2\devices\thrilldrive_handle.cpp" />
|
||||
<ClCompile Include="USB\usb-python2\devices\toysmarch_drumpad.cpp" />
|
||||
<ClCompile Include="USB\usb-python2\inputs\passthrough\usb-python2-passthrough.cpp" />
|
||||
<ClCompile Include="USB\usb-python2\inputs\native\usb-python2-native.cpp" />
|
||||
<ClCompile Include="USB\usb-python2\inputs\Python2QtInputManager.cpp" />
|
||||
<ClCompile Include="USB\usb-python2\patches.cpp" />
|
||||
<ClCompile Include="USB\usb-python2\api_init_win32_hid.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="AsyncFileReader.h" />
|
||||
|
@ -637,7 +665,6 @@
|
|||
<ClInclude Include="PrecompiledHeader.h" />
|
||||
<ClInclude Include="sio_internal.h" />
|
||||
<ClInclude Include="ps2\pgif.h" />
|
||||
<ClInclude Include="USB\USB.h" />
|
||||
<ClInclude Include="Utilities\AsciiFile.h" />
|
||||
<ClInclude Include="Elfheader.h" />
|
||||
<ClInclude Include="CDVD\IsoFileFormats.h" />
|
||||
|
@ -751,6 +778,39 @@
|
|||
<ClInclude Include="CDVD\IsoFS\IsoFS.h" />
|
||||
<ClInclude Include="CDVD\IsoFS\IsoFSCDVD.h" />
|
||||
<ClInclude Include="CDVD\IsoFS\SectorSource.h" />
|
||||
<ClInclude Include="USB\USB.h" />
|
||||
<ClInclude Include="USB\deviceproxy.h" />
|
||||
<ClInclude Include="USB\helpers.h" />
|
||||
<ClInclude Include="USB\platcompat.h" />
|
||||
<ClInclude Include="USB\proxybase.h" />
|
||||
<ClInclude Include="USB\qemu-usb\desc.h" />
|
||||
<ClInclude Include="USB\qemu-usb\glib.h" />
|
||||
<ClInclude Include="USB\qemu-usb\hid.h" />
|
||||
<ClInclude Include="USB\qemu-usb\input-keymap-win32-to-qcode.h" />
|
||||
<ClInclude Include="USB\qemu-usb\input-keymap.h" />
|
||||
<ClInclude Include="USB\qemu-usb\iov.h" />
|
||||
<ClInclude Include="USB\qemu-usb\queue.h" />
|
||||
<ClInclude Include="USB\qemu-usb\qusb.h" />
|
||||
<ClInclude Include="USB\qemu-usb\USBinternal.h" />
|
||||
<ClInclude Include="USB\qemu-usb\vl.h" />
|
||||
<ClInclude Include="USB\readerwriterqueue\atomicops.h" />
|
||||
<ClInclude Include="USB\readerwriterqueue\readerwriterqueue.h" />
|
||||
<ClInclude Include="USB\shared\inifile_usb.h" />
|
||||
<ClInclude Include="USB\shared\ringbuffer.h" />
|
||||
<ClInclude Include="USB\shared\shared_usb.h" />
|
||||
<ClInclude Include="USB\usb-python2\devices\acio.h" />
|
||||
<ClInclude Include="USB\usb-python2\devices\icca.h" />
|
||||
<ClInclude Include="USB\usb-python2\devices\thrilldrive_belt.h" />
|
||||
<ClInclude Include="USB\usb-python2\devices\ddr_extio.h" />
|
||||
<ClInclude Include="USB\usb-python2\devices\thrilldrive_handle.h" />
|
||||
<ClInclude Include="USB\usb-python2\devices\input_device.h" />
|
||||
<ClInclude Include="USB\usb-python2\devices\toysmarch_drumpad.h" />
|
||||
<ClInclude Include="USB\usb-python2\inputs\passthrough\usb-python2-passthrough.h" />
|
||||
<ClInclude Include="USB\usb-python2\inputs\native\usb-python2-native.h" />
|
||||
<ClInclude Include="USB\usb-python2\inputs\Python2QtInputManager.h" />
|
||||
<ClInclude Include="USB\usb-python2\patches.h" />
|
||||
<ClInclude Include="USB\usb-python2\python2proxy.h" />
|
||||
<ClInclude Include="USB\usb-python2\usb-python2.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="$(SolutionDir)3rdparty\baseclasses\baseclasses.vcxproj">
|
||||
|
@ -796,6 +856,9 @@
|
|||
<ProjectReference Include="$(SolutionDir)3rdparty\imgui\imgui.vcxproj">
|
||||
<Project>{88fb34ec-845e-4f21-a552-f1573b9ed167}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\3rdparty\libusb\libusb.vcxproj">
|
||||
<Project>{349ee8f9-7d25-4909-aaf5-ff3fade72187}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\3rdparty\libzip\libzip.vcxproj">
|
||||
<Project>{20b2e9fe-f020-42a0-b324-956f5b06ea68}</Project>
|
||||
</ProjectReference>
|
||||
|
|
|
@ -238,6 +238,15 @@
|
|||
<Filter Include="Tools\Input Recording">
|
||||
<UniqueIdentifier>{03ba2aa7-2cd9-48cb-93c6-fc93d5bdc938}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="System\Ps2\USB\usb-python2">
|
||||
<UniqueIdentifier>{95d253c7-cb70-49c4-b5ca-25817162d414}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="System\Ps2\USB\usb-python2\devices">
|
||||
<UniqueIdentifier>{32c6df0a-0683-4310-84e8-d2ced8721a0d}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="System\Ps2\USB\usb-python2\inputs">
|
||||
<UniqueIdentifier>{30f8041c-9171-4e12-bef0-2e2a6b5a4103}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Utilities\folderdesc.txt">
|
||||
|
@ -1202,9 +1211,6 @@
|
|||
<ClCompile Include="SPU2\Host\Config.cpp">
|
||||
<Filter>System\Ps2\SPU2</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="USB\USBNull.cpp">
|
||||
<Filter>System\Ps2\USB</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="HostSettings.cpp">
|
||||
<Filter>Host</Filter>
|
||||
</ClCompile>
|
||||
|
@ -1275,6 +1281,58 @@
|
|||
<ClCompile Include="Frontend\LogSink.cpp">
|
||||
<Filter>Host</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="USB\USB.cpp" />
|
||||
<ClCompile Include="USB\deviceproxy.cpp" />
|
||||
<ClCompile Include="USB\device_init.cpp" />
|
||||
<ClCompile Include="USB\qemu-usb\bus.cpp" />
|
||||
<ClCompile Include="USB\qemu-usb\core.cpp" />
|
||||
<ClCompile Include="USB\qemu-usb\desc.cpp" />
|
||||
<ClCompile Include="USB\qemu-usb\glib.cpp" />
|
||||
<ClCompile Include="USB\qemu-usb\hid.cpp" />
|
||||
<ClCompile Include="USB\qemu-usb\input-keymap-qcode-to-qnum.cpp" />
|
||||
<ClCompile Include="USB\qemu-usb\input-keymap-win32-to-qcode.cpp" />
|
||||
<ClCompile Include="USB\qemu-usb\iov.cpp" />
|
||||
<ClCompile Include="USB\qemu-usb\usb-ohci.cpp" />
|
||||
<ClCompile Include="USB\qemu-usb\vl.cpp" />
|
||||
<ClCompile Include="USB\shared\shared_usb.cpp" />
|
||||
<ClCompile Include="USB\shared\inifile_usb.cpp" />
|
||||
<ClCompile Include="USB\shared\ringbuffer.cpp" />
|
||||
<ClCompile Include="USB\usb-python2\devices\ddr_extio.cpp">
|
||||
<Filter>System\Ps2\USB\usb-python2\devices</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="USB\usb-python2\devices\acio.cpp">
|
||||
<Filter>System\Ps2\USB\usb-python2\devices</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="USB\usb-python2\devices\thrilldrive_belt.cpp">
|
||||
<Filter>System\Ps2\USB\usb-python2\devices</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="USB\usb-python2\devices\thrilldrive_handle.cpp">
|
||||
<Filter>System\Ps2\USB\usb-python2\devices</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="USB\usb-python2\devices\toysmarch_drumpad.cpp">
|
||||
<Filter>System\Ps2\USB\usb-python2\devices</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="USB\usb-python2\inputs\native\usb-python2-native.cpp">
|
||||
<Filter>System\Ps2\USB\usb-python2\inputs</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="USB\usb-python2\inputs\passthrough\usb-python2-passthrough.cpp">
|
||||
<Filter>System\Ps2\USB\usb-python2\inputs</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="USB\usb-python2\inputs\Python2QtInputManager.cpp">
|
||||
<Filter>System\Ps2\USB\usb-python2\inputs</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="USB\usb-python2\devices\icca.cpp">
|
||||
<Filter>System\Ps2\USB\usb-python2\devices</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="USB\usb-python2\patches.cpp">
|
||||
<Filter>System\Ps2\USB\usb-python2</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="USB\usb-python2\usb-python2.cpp">
|
||||
<Filter>System\Ps2\USB\usb-python2</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="USB\usb-python2\api_init_win32_hid.cpp">
|
||||
<Filter>System\Ps2\USB\usb-python2</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Patch.h">
|
||||
|
@ -2119,6 +2177,66 @@
|
|||
<ClInclude Include="Frontend\LogSink.h">
|
||||
<Filter>Host</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="USB\deviceproxy.h" />
|
||||
<ClInclude Include="USB\helpers.h" />
|
||||
<ClInclude Include="USB\platcompat.h" />
|
||||
<ClInclude Include="USB\qemu-usb\desc.h" />
|
||||
<ClInclude Include="USB\qemu-usb\glib.h" />
|
||||
<ClInclude Include="USB\qemu-usb\hid.h" />
|
||||
<ClInclude Include="USB\qemu-usb\input-keymap-win32-to-qcode.h" />
|
||||
<ClInclude Include="USB\qemu-usb\input-keymap.h" />
|
||||
<ClInclude Include="USB\qemu-usb\iov.h" />
|
||||
<ClInclude Include="USB\qemu-usb\queue.h" />
|
||||
<ClInclude Include="USB\qemu-usb\qusb.h" />
|
||||
<ClInclude Include="USB\qemu-usb\USBinternal.h" />
|
||||
<ClInclude Include="USB\qemu-usb\vl.h" />
|
||||
<ClInclude Include="USB\readerwriterqueue\atomicops.h" />
|
||||
<ClInclude Include="USB\readerwriterqueue\readerwriterqueue.h" />
|
||||
<ClInclude Include="USB\shared\inifile_usb.h" />
|
||||
<ClInclude Include="USB\shared\ringbuffer.h" />
|
||||
<ClInclude Include="USB\shared\shared_usb.h" />
|
||||
<ClInclude Include="USB\usb-python2\devices\ddr_extio.h">
|
||||
<Filter>System\Ps2\USB\usb-python2\devices</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="USB\usb-python2\devices\acio.h">
|
||||
<Filter>System\Ps2\USB\usb-python2\devices</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="USB\usb-python2\devices\thrilldrive_belt.h">
|
||||
<Filter>System\Ps2\USB\usb-python2\devices</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="USB\usb-python2\devices\thrilldrive_handle.h">
|
||||
<Filter>System\Ps2\USB\usb-python2\devices</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="USB\usb-python2\devices\toysmarch_drumpad.h">
|
||||
<Filter>System\Ps2\USB\usb-python2\devices</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="USB\usb-python2\inputs\passthrough\usb-python2-passthrough.h">
|
||||
<Filter>System\Ps2\USB\usb-python2\inputs</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="USB\usb-python2\inputs\native\usb-python2-native.h">
|
||||
<Filter>System\Ps2\USB\usb-python2\inputs</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="USB\usb-python2\inputs\Python2QtInputManager.h">
|
||||
<Filter>System\Ps2\USB\usb-python2\inputs</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="USB\usb-python2\devices\icca.h">
|
||||
<Filter>System\Ps2\USB\usb-python2\devices</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="USB\usb-python2\patches.h">
|
||||
<Filter>System\Ps2\USB\usb-python2</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="USB\proxybase.h">
|
||||
<Filter>System\Ps2\USB\usb-python2</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="USB\usb-python2\python2proxy.h">
|
||||
<Filter>System\Ps2\USB\usb-python2</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="USB\usb-python2\usb-python2.h">
|
||||
<Filter>System\Ps2\USB\usb-python2</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="USB\usb-python2\devices\input_device.h">
|
||||
<Filter>System\Ps2\USB\usb-python2\devices</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<CustomBuildStep Include="rdebug\deci2.h">
|
||||
|
@ -2143,4 +2261,4 @@
|
|||
<Filter>System\Ps2\Debug\rdebug</Filter>
|
||||
</CustomBuildStep>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
</Project>
|
Loading…
Reference in New Issue