mirror of https://github.com/xemu-project/xemu.git
Merge branch 'master' into xblc_gui
This commit is contained in:
commit
a64b6a4337
|
@ -79,7 +79,7 @@ jobs:
|
||||||
artifact_name: xemu-win-aarch64-release
|
artifact_name: xemu-win-aarch64-release
|
||||||
arch: aarch64
|
arch: aarch64
|
||||||
env:
|
env:
|
||||||
DOCKER_IMAGE_NAME: ghcr.io/xemu-project/xemu-win64-toolchain:sha-b6d29d4
|
DOCKER_IMAGE_NAME: ghcr.io/xemu-project/xemu-win64-toolchain:sha-03e3cd0
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Download source package
|
- name: Download source package
|
||||||
|
|
|
@ -21,9 +21,13 @@ general:
|
||||||
|
|
||||||
input:
|
input:
|
||||||
bindings:
|
bindings:
|
||||||
|
port1_driver: string
|
||||||
port1: string
|
port1: string
|
||||||
|
port2_driver: string
|
||||||
port2: string
|
port2: string
|
||||||
|
port3_driver: string
|
||||||
port3: string
|
port3: string
|
||||||
|
port4_driver: string
|
||||||
port4: string
|
port4: string
|
||||||
peripherals:
|
peripherals:
|
||||||
port1:
|
port1:
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 45 KiB |
|
@ -0,0 +1,86 @@
|
||||||
|
<svg viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg">
|
||||||
|
<g class="layer">
|
||||||
|
<title>Controller S</title>
|
||||||
|
|
||||||
|
<!-- Left Thumbstick Head -->
|
||||||
|
<ellipse cx="33.5" cy="397.5" fill="#000000" id="svg_69" rx="26" ry="26" stroke="#ff0000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="null" stroke-width="2"/>
|
||||||
|
<ellipse cx="33.5" cy="397.5" fill="#000000" fill-opacity="null" id="svg_70" rx="18.5" ry="18.5" stroke="#ff0000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="null" stroke-width="2"/>
|
||||||
|
<ellipse cx="33.5" cy="383.5" fill="#ff0000" id="svg_71" rx="1.43" ry="1.6" stroke="#ff0000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="null" stroke-width="0"/>
|
||||||
|
<ellipse cx="33.5" cy="411.5" fill="#ff0000" id="svg_72" rx="1.5" ry="1.5" stroke="#ff0000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="null" stroke-width="0"/>
|
||||||
|
<ellipse cx="19" cy="397.5" fill="#ff0000" id="svg_73" rx="1.43" ry="1.6" stroke="#ff0000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="null" stroke-width="0" transform="matrix(1, 0, 0, 1, 0, 0)"/>
|
||||||
|
<ellipse cx="48" cy="397.5" fill="#ff0000" id="svg_74" rx="1.43" ry="1.6" stroke="#ff0000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="null" stroke-width="0"/>
|
||||||
|
|
||||||
|
<!-- Right Thumbstick Head -->
|
||||||
|
<ellipse cx="33.5" cy="464.5" fill="#000000" id="svg_80" rx="26" ry="26" stroke="#ff0000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="null" stroke-width="2" transform="matrix(1, 0, 0, 1, 0, 0)"/>
|
||||||
|
<ellipse cx="33.5" cy="464.5" fill="#000000" fill-opacity="null" id="svg_79" rx="18.5" ry="18.5" stroke="#ff0000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="null" stroke-width="2" transform="matrix(1, 0, 0, 1, 0, 0)"/>
|
||||||
|
<ellipse cx="33.5" cy="450.67" fill="#ff0000" id="svg_78" rx="1.43" ry="1.6" stroke="#ff0000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="null" stroke-width="0" transform="matrix(1, 0, 0, 1, 0, 0)"/>
|
||||||
|
<ellipse cx="33.5" cy="478.67" fill="#ff0000" id="svg_77" rx="1.5" ry="1.5" stroke="#ff0000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="null" stroke-width="0" transform="matrix(1, 0, 0, 1, 0, 0)"/>
|
||||||
|
<ellipse cx="19" cy="464.5" fill="#ff0000" id="svg_76" rx="1.43" ry="1.6" stroke="#ff0000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="null" stroke-width="0" transform="matrix(1, 0, 0, 1, 0, 0)"/>
|
||||||
|
<ellipse cx="48" cy="464.5" fill="#ff0000" id="svg_75" rx="1.43" ry="1.6" stroke="#ff0000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="null" stroke-width="0" transform="matrix(1, 0, 0, 1, 0, 0)"/>
|
||||||
|
|
||||||
|
<!-- Controller Body -->
|
||||||
|
<path d="m63.5,37.5c0,0 30,-15 41,-18.5c11,-3.5 47,-14 47,-14c0,0 19,13 78,14c59,1 83.5,-15 83.5,-15c0,0 42,12.5 49,15c7,2.5 39,20 39,20c0,0 61.2,116.9 63.1,185.8c1.9,68.9 -6.4,118.3 -27.2,126.5c-20.8,8.2 -46.7,-4.7 -67.3,-30.8c-20.6,-26.1 -22.6,-52.5 -22.6,-52.5c0,0 -33.9,-17.3 -115.3,-17.4c-81.4,-0.1 -112.7,16.9 -112.7,16.9c0,0 -5.7,34.4 -23.6,54.8c-17.9,20.4 -44.4,36.7 -63.9,28.7c-19.5,-8 -32.2,-51.7 -29.7,-123.4c2.5,-71.7 61.7,-190.1 61.7,-190.1z" fill="#000000" id="svg_5" stroke="#ff0000" stroke-width="2" transform="matrix(1, 0, 0, 1, 0, 0)"/>
|
||||||
|
<path d="m53.5,48c0,0 21.5,-10.3 40,-16.6c18.5,-6.3 40,-9.9 40,-9.9c0,0 6.3,12.2 31.8,28.2c25.5,16 37.2,14.8 37.2,14.8c0,0 -11.7,9.4 -17.3,28.9c-5.6,19.5 3,35.8 11.6,45.7c8.6,9.9 23.6,16.2 37.2,15.9c13.6,-0.3 27.9,-6.4 37.5,-17c9.6,-10.6 15.9,-29.6 9.4,-47.6c-6.5,-18 -14.9,-25.9 -14.9,-25.4c0,0.5 12,-0.6 37,-16.6c25,-16 30.5,-26.9 30.5,-26.9c0,0 20,4.9 38.7,10.6c18.7,5.7 40.8,17.4 40.8,17.4c0,0 32.4,44.6 22.4,119.6c-10,75 -88.4,98.9 -88.4,98.9c0,0 -39.3,-52.2 -115.3,-52.2c-76,0 -112.2,51.2 -112.2,51.2c0,0 -78.2,-17.2 -88.2,-94.7c-10,-77.5 22.2,-124.3 22.2,-124.3z" fill="#000000" fill-opacity="null" id="svg_2" stroke="#ff0000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="null" stroke-width="2" transform="matrix(1, 0, 0, 1, 0, 0)"/>
|
||||||
|
|
||||||
|
<!-- Left Thumbstick -->
|
||||||
|
<ellipse cx="97.6" cy="109.6" fill="#000000" fill-opacity="null" id="svg_53" rx="46.8" ry="44.8" stroke="#ff0000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="null" stroke-width="2" transform="matrix(1, 0, 0, 1, 0, 0)"/>
|
||||||
|
<ellipse cx="101.6" cy="110.4" fill="#000000" fill-opacity="null" id="svg_54" rx="33" ry="33" stroke="#ff0000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="null" stroke-width="2" transform="matrix(1, 0, 0, 1, 0, 0)"/>
|
||||||
|
|
||||||
|
<!-- Right Thumbstick -->
|
||||||
|
<path d="m248.8,196.8c0.81,-32.4 27.15,-50 44.57,-51.2c17.42,-1.2 39.31,9.2 45.38,25.2c6.08,16 4.86,42 -10.54,54c-15.4,12 -27.55,20 -53.08,12.4c-25.53,-7.6 -26.34,-40.4 -26.34,-40.4l0.01,0z" fill="#000000" fill-opacity="null" id="svg_55" stroke="#ff0000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="null" stroke-width="2" transform="matrix(1, 0, 0, 1, 0, 0)"/>
|
||||||
|
<ellipse cx="295" cy="188.8" fill="#000000" fill-opacity="null" id="svg_56" rx="33" ry="33" stroke="#ff0000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="null" stroke-width="2" transform="matrix(1, 0, 0, 1, 0, 0)"/>
|
||||||
|
|
||||||
|
<!-- Circle Behind Face Buttons -->
|
||||||
|
<ellipse cx="362.4" cy="111" fill="#000000" id="svg_31" rx="40" ry="40.6" stroke="#ff0000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-width="2" transform="matrix(1, 0, 0, 1, 0, 0)"/>
|
||||||
|
|
||||||
|
<!-- X Button -->
|
||||||
|
<ellipse cx="328" cy="111.6" fill="#0000ff" id="svg_32" rx="17" ry="17" stroke="#ff0000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-width="2"/>
|
||||||
|
<text fill="#ff0000" font-family="Helvetica" font-size="24" font-weight="bold" id="svg_60" letter-spacing="0" stroke="#ff0000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="null" stroke-width="0" text-anchor="middle" x="328" xml:space="preserve" y="120.4">X</text>
|
||||||
|
|
||||||
|
<!-- B Button -->
|
||||||
|
<ellipse cx="398" cy="110.8" fill="#0000ff" id="svg_33" rx="17" ry="17" stroke="#ff0000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-width="2"/>
|
||||||
|
<text fill="#ff0000" font-family="Helvetica" font-size="24" font-weight="bold" id="svg_63" stroke="#ff0000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="null" stroke-width="0" text-anchor="middle" transform="matrix(1, 0, 0, 1, 0, 0)" x="398.8" xml:space="preserve" y="119.6">B</text>
|
||||||
|
|
||||||
|
<!-- A Button -->
|
||||||
|
<ellipse cx="364" cy="146.4" fill="#0000ff" id="svg_35" rx="17" ry="17" stroke="#ff0000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-width="2"/>
|
||||||
|
<text fill="#ff0000" font-family="Helvetica" font-size="24" font-weight="bold" id="svg_64" stroke="#ff0000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="null" stroke-width="0" text-anchor="middle" transform="matrix(1, 0, 0, 1, 0, 0)" x="363.6" xml:space="preserve" y="154.8">A</text>
|
||||||
|
|
||||||
|
<!-- Y Button -->
|
||||||
|
<ellipse cx="364" cy="76.4" fill="#0000ff" id="svg_34" rx="17" ry="17" stroke="#ff0000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-width="2"/>
|
||||||
|
<text fill="#ff0000" font-family="Helvetica" font-size="24" font-weight="bold" id="svg_65" stroke="#ff0000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="null" stroke-width="0" text-anchor="middle" transform="matrix(1, 0, 0, 1, 0, 0)" x="363.6" xml:space="preserve" y="85.6">Y</text>
|
||||||
|
|
||||||
|
<!-- White Button -->
|
||||||
|
<ellipse cx="368.6" cy="204.6" fill="#000000" id="svg_39" rx="18.2" ry="18.2" stroke="#ff0000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="null" stroke-width="2"/>
|
||||||
|
<ellipse cx="368.6" cy="204.6" fill="#0000ff" id="svg_36" rx="14.4" ry="14.6" stroke="#ff0000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-width="2"/>
|
||||||
|
|
||||||
|
<!-- Black Button -->
|
||||||
|
<ellipse cx="404" cy="176" fill="#000000" id="svg_38" rx="18" ry="18" stroke="#ff0000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="null" stroke-width="2" transform="matrix(1, 0, 0, 1, 0, 0)"/>
|
||||||
|
<ellipse cx="404" cy="176" fill="#0000ff" id="svg_37" rx="14.4" ry="14.6" stroke="#ff0000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-width="2"/>
|
||||||
|
|
||||||
|
<!-- Back Button -->
|
||||||
|
<ellipse cx="55.6" cy="160" fill="#000000" fill-opacity="null" id="svg_40" rx="13.6" ry="13.6" stroke="#ff0000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="null" stroke-width="2" transform="matrix(1, 0, 0, 1, 0, 0)"/>
|
||||||
|
<ellipse cx="55.6" cy="160" fill="#0000ff" fill-opacity="null" id="svg_43" rx="10" ry="10" stroke="#ff0000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="null" stroke-width="2"/>
|
||||||
|
<path d="m59.83,155l-0.17,9.33l-10.33,-4.83l10.5,-4.5z" fill="none" fill-opacity="null" id="svg_81" stroke="#ff0000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="null" stroke-width="2"/>
|
||||||
|
|
||||||
|
<!-- Start Button -->
|
||||||
|
<ellipse cx="82" cy="189" fill="#000000" fill-opacity="null" id="svg_41" rx="15.6" ry="16.2" stroke="#ff0000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="null" stroke-width="2" transform="matrix(1, 0, 0, 1, 0, 0)"/>
|
||||||
|
<ellipse cx="82" cy="189" fill="#0000ff" id="svg_42" rx="12" ry="12.4" stroke="#ff0000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="null" stroke-width="2" transform="matrix(1, 0, 0, 1, 0, 0)"/>
|
||||||
|
<path d="m76.17,183.83l0,10.33l11.5,-4.83l-11.5,-5.5z" fill="none" fill-opacity="null" id="svg_82" stroke="#ff0000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="null" stroke-width="2"/>
|
||||||
|
|
||||||
|
<!-- D-Pad -->
|
||||||
|
<ellipse cx="164" cy="189" fill="#000000" fill-opacity="null" id="svg_52" rx="48.2" ry="49.6" stroke="#ff0000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="null" stroke-width="2" transform="matrix(1, 0, 0, 1, 0, 0)"/>
|
||||||
|
<ellipse cx="164" cy="188" fill="#000000" id="svg_50" rx="42.6" ry="42.6" stroke="#ff0000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-width="2" transform="matrix(1, 0, 0, 1, 0, 0)"/>
|
||||||
|
<ellipse cx="164" cy="188" fill="#000000" fill-opacity="null" id="svg_51" rx="37.2" ry="37" stroke="#ff0000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="null" stroke-width="2" transform="matrix(1, 0, 0, 1, 0, 0)"/>
|
||||||
|
<line fill="none" fill-opacity="null" id="svg_1" stroke="#ff0000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="null" stroke-width="2" x1="151" x2="151" y1="153" y2="176"/>
|
||||||
|
<line fill="none" fill-opacity="null" id="svg_3" stroke="#ff0000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="null" stroke-width="2" x1="176" x2="176" y1="153" y2="177"/>
|
||||||
|
<line fill="none" fill-opacity="null" id="svg_4" stroke="#ff0000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="null" stroke-width="2" transform="matrix(1, 0, 0, 1, 0, 0)" x1="151" x2="151" y1="198.29" y2="223"/>
|
||||||
|
<line fill="none" fill-opacity="null" id="svg_6" stroke="#ff0000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="null" stroke-width="2" x1="176" x2="176" y1="199" y2="223"/>
|
||||||
|
<line fill="none" fill-opacity="null" id="svg_7" stroke="#ff0000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="null" stroke-width="2" x1="176" x2="200" y1="176" y2="176"/>
|
||||||
|
<line fill="none" fill-opacity="null" id="svg_8" stroke="#ff0000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="null" stroke-width="2" transform="matrix(1, 0, 0, 1, 0, 0)" x1="175" x2="200" y1="199" y2="199"/>
|
||||||
|
<line fill="none" fill-opacity="null" id="svg_9" stroke="#ff0000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="null" stroke-width="2" transform="matrix(1, 0, 0, 1, 0, 0)" x1="128" x2="152" y1="199" y2="199"/>
|
||||||
|
<line fill="none" fill-opacity="null" id="svg_10" stroke="#ff0000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="null" stroke-width="2" x1="128" x2="152" y1="176" y2="176"/>
|
||||||
|
|
||||||
|
<!-- Jewel -->
|
||||||
|
<ellipse cx="233.19" cy="106.15" fill="#0000ff" id="svg_20" rx="40" ry="40" stroke="#ff0000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-opacity="null" stroke-width="2"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 13 KiB |
|
@ -1,5 +1,6 @@
|
||||||
pfiles = [
|
pfiles = [
|
||||||
'controller_mask.png',
|
'controller_mask.png',
|
||||||
|
'controller_mask_s.png',
|
||||||
'xmu_mask.png',
|
'xmu_mask.png',
|
||||||
'xblc_mask.png',
|
'xblc_mask.png',
|
||||||
'logo_sdf.png',
|
'logo_sdf.png',
|
||||||
|
|
|
@ -16,6 +16,7 @@ specific_ss.add(files(
|
||||||
'xbox_pci.c',
|
'xbox_pci.c',
|
||||||
'xid.c',
|
'xid.c',
|
||||||
'xblc.c',
|
'xblc.c',
|
||||||
|
'xid-gamepad.c',
|
||||||
))
|
))
|
||||||
subdir('nv2a')
|
subdir('nv2a')
|
||||||
subdir('mcpx')
|
subdir('mcpx')
|
||||||
|
|
|
@ -0,0 +1,293 @@
|
||||||
|
/*
|
||||||
|
* QEMU USB XID Devices
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013 espes
|
||||||
|
* Copyright (c) 2017 Jannik Vogel
|
||||||
|
* Copyright (c) 2018-2021 Matt Borgerson
|
||||||
|
*
|
||||||
|
* 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 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "xid.h"
|
||||||
|
|
||||||
|
// #define DEBUG_XID
|
||||||
|
#ifdef DEBUG_XID
|
||||||
|
#define DPRINTF printf
|
||||||
|
#else
|
||||||
|
#define DPRINTF(...)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define USB_VENDOR_MICROSOFT 0x045e
|
||||||
|
|
||||||
|
#define GAMEPAD_IN_ENDPOINT_ID 0x02
|
||||||
|
#define GAMEPAD_OUT_ENDPOINT_ID 0x02
|
||||||
|
|
||||||
|
#define USB_XID(obj) \
|
||||||
|
OBJECT_CHECK(USBXIDGamepadState, (obj), TYPE_USB_XID_GAMEPAD)
|
||||||
|
#define USB_XID_S(obj) \
|
||||||
|
OBJECT_CHECK(USBXIDGamepadState, (obj), TYPE_USB_XID_GAMEPAD_S)
|
||||||
|
|
||||||
|
static const USBDescIface desc_iface_xbox_gamepad = {
|
||||||
|
.bInterfaceNumber = 0,
|
||||||
|
.bNumEndpoints = 2,
|
||||||
|
.bInterfaceClass = USB_CLASS_XID,
|
||||||
|
.bInterfaceSubClass = 0x42,
|
||||||
|
.bInterfaceProtocol = 0x00,
|
||||||
|
.eps =
|
||||||
|
(USBDescEndpoint[]){
|
||||||
|
{
|
||||||
|
.bEndpointAddress = USB_DIR_IN | GAMEPAD_IN_ENDPOINT_ID,
|
||||||
|
.bmAttributes = USB_ENDPOINT_XFER_INT,
|
||||||
|
.wMaxPacketSize = 0x20,
|
||||||
|
.bInterval = 4,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.bEndpointAddress = USB_DIR_OUT | GAMEPAD_OUT_ENDPOINT_ID,
|
||||||
|
.bmAttributes = USB_ENDPOINT_XFER_INT,
|
||||||
|
.wMaxPacketSize = 0x20,
|
||||||
|
.bInterval = 4,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static const USBDescDevice desc_device_xbox_gamepad = {
|
||||||
|
.bcdUSB = 0x0110,
|
||||||
|
.bMaxPacketSize0 = 0x40,
|
||||||
|
.bNumConfigurations = 1,
|
||||||
|
.confs =
|
||||||
|
(USBDescConfig[]){
|
||||||
|
{
|
||||||
|
.bNumInterfaces = 1,
|
||||||
|
.bConfigurationValue = 1,
|
||||||
|
.bmAttributes = USB_CFG_ATT_ONE,
|
||||||
|
.bMaxPower = 50,
|
||||||
|
.nif = 1,
|
||||||
|
.ifs = &desc_iface_xbox_gamepad,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static const USBDesc desc_xbox_gamepad = {
|
||||||
|
.id = {
|
||||||
|
.idVendor = USB_VENDOR_MICROSOFT,
|
||||||
|
.idProduct = 0x0202,
|
||||||
|
.bcdDevice = 0x0100,
|
||||||
|
.iManufacturer = STR_MANUFACTURER,
|
||||||
|
.iProduct = STR_PRODUCT,
|
||||||
|
.iSerialNumber = STR_SERIALNUMBER,
|
||||||
|
},
|
||||||
|
.full = &desc_device_xbox_gamepad,
|
||||||
|
.str = desc_strings,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const USBDesc desc_xbox_gamepad_s = {
|
||||||
|
.id = {
|
||||||
|
.idVendor = USB_VENDOR_MICROSOFT,
|
||||||
|
.idProduct = 0x0289,
|
||||||
|
.bcdDevice = 0x0100,
|
||||||
|
.iManufacturer = STR_MANUFACTURER,
|
||||||
|
.iProduct = STR_PRODUCT,
|
||||||
|
.iSerialNumber = STR_SERIALNUMBER,
|
||||||
|
},
|
||||||
|
.full = &desc_device_xbox_gamepad,
|
||||||
|
.str = desc_strings,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const XIDDesc desc_xid_xbox_gamepad = {
|
||||||
|
.bLength = 0x10,
|
||||||
|
.bDescriptorType = USB_DT_XID,
|
||||||
|
.bcdXid = 0x100,
|
||||||
|
.bType = XID_DEVICETYPE_GAMEPAD,
|
||||||
|
.bSubType = XID_DEVICESUBTYPE_GAMEPAD,
|
||||||
|
.bMaxInputReportSize = 20,
|
||||||
|
.bMaxOutputReportSize = 6,
|
||||||
|
.wAlternateProductIds = { 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF },
|
||||||
|
};
|
||||||
|
|
||||||
|
static const XIDDesc desc_xid_xbox_gamepad_s = {
|
||||||
|
.bLength = 0x10,
|
||||||
|
.bDescriptorType = USB_DT_XID,
|
||||||
|
.bcdXid = 0x100,
|
||||||
|
.bType = XID_DEVICETYPE_GAMEPAD,
|
||||||
|
.bSubType = XID_DEVICESUBTYPE_GAMEPAD_S,
|
||||||
|
.bMaxInputReportSize = 20,
|
||||||
|
.bMaxOutputReportSize = 6,
|
||||||
|
.wAlternateProductIds = { 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF },
|
||||||
|
};
|
||||||
|
|
||||||
|
static void usb_xid_gamepad_handle_data(USBDevice *dev, USBPacket *p)
|
||||||
|
{
|
||||||
|
USBXIDGamepadState *s = DO_UPCAST(USBXIDGamepadState, dev, dev);
|
||||||
|
|
||||||
|
DPRINTF("xid handle_gamepad_data 0x%x %d 0x%zx\n", p->pid, p->ep->nr,
|
||||||
|
p->iov.size);
|
||||||
|
|
||||||
|
switch (p->pid) {
|
||||||
|
case USB_TOKEN_IN:
|
||||||
|
if (p->ep->nr == GAMEPAD_IN_ENDPOINT_ID) {
|
||||||
|
update_input(s);
|
||||||
|
usb_packet_copy(p, &s->in_state, s->in_state.bLength);
|
||||||
|
} else {
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case USB_TOKEN_OUT:
|
||||||
|
if (p->ep->nr == GAMEPAD_OUT_ENDPOINT_ID) {
|
||||||
|
usb_packet_copy(p, &s->out_state, s->out_state.length);
|
||||||
|
update_output(s);
|
||||||
|
} else {
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
p->status = USB_RET_STALL;
|
||||||
|
assert(false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void usb_xid_gamepad_class_initfn(ObjectClass *klass, void *data)
|
||||||
|
{
|
||||||
|
USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
|
||||||
|
|
||||||
|
uc->handle_reset = usb_xid_handle_reset;
|
||||||
|
uc->handle_control = usb_xid_handle_control;
|
||||||
|
uc->handle_data = usb_xid_gamepad_handle_data;
|
||||||
|
// uc->handle_destroy = usb_xid_handle_destroy;
|
||||||
|
uc->handle_attach = usb_desc_attach;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void usb_xbox_gamepad_realize(USBDevice *dev, Error **errp)
|
||||||
|
{
|
||||||
|
USBXIDGamepadState *s = USB_XID(dev);
|
||||||
|
usb_desc_create_serial(dev);
|
||||||
|
usb_desc_init(dev);
|
||||||
|
s->intr = usb_ep_get(dev, USB_TOKEN_IN, 2);
|
||||||
|
|
||||||
|
s->in_state.bLength = sizeof(s->in_state);
|
||||||
|
s->in_state.bReportId = 0;
|
||||||
|
|
||||||
|
s->out_state.length = sizeof(s->out_state);
|
||||||
|
s->out_state.report_id = 0;
|
||||||
|
|
||||||
|
s->xid_desc = &desc_xid_xbox_gamepad;
|
||||||
|
|
||||||
|
memset(&s->in_state_capabilities, 0xFF, sizeof(s->in_state_capabilities));
|
||||||
|
s->in_state_capabilities.bLength = sizeof(s->in_state_capabilities);
|
||||||
|
s->in_state_capabilities.bReportId = 0;
|
||||||
|
|
||||||
|
memset(&s->out_state_capabilities, 0xFF, sizeof(s->out_state_capabilities));
|
||||||
|
s->out_state_capabilities.length = sizeof(s->out_state_capabilities);
|
||||||
|
s->out_state_capabilities.report_id = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void usb_xbox_gamepad_s_realize(USBDevice *dev, Error **errp)
|
||||||
|
{
|
||||||
|
USBXIDGamepadState *s = USB_XID_S(dev);
|
||||||
|
usb_desc_create_serial(dev);
|
||||||
|
usb_desc_init(dev);
|
||||||
|
s->intr = usb_ep_get(dev, USB_TOKEN_IN, 2);
|
||||||
|
|
||||||
|
s->in_state.bLength = sizeof(s->in_state);
|
||||||
|
s->in_state.bReportId = 0;
|
||||||
|
|
||||||
|
s->out_state.length = sizeof(s->out_state);
|
||||||
|
s->out_state.report_id = 0;
|
||||||
|
|
||||||
|
s->xid_desc = &desc_xid_xbox_gamepad_s;
|
||||||
|
|
||||||
|
memset(&s->in_state_capabilities, 0xFF, sizeof(s->in_state_capabilities));
|
||||||
|
s->in_state_capabilities.bLength = sizeof(s->in_state_capabilities);
|
||||||
|
s->in_state_capabilities.bReportId = 0;
|
||||||
|
|
||||||
|
memset(&s->out_state_capabilities, 0xFF, sizeof(s->out_state_capabilities));
|
||||||
|
s->out_state_capabilities.length = sizeof(s->out_state_capabilities);
|
||||||
|
s->out_state_capabilities.report_id = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Property xid_properties[] = {
|
||||||
|
DEFINE_PROP_UINT8("index", USBXIDGamepadState, device_index, 0),
|
||||||
|
DEFINE_PROP_END_OF_LIST(),
|
||||||
|
};
|
||||||
|
|
||||||
|
static const VMStateDescription vmstate_usb_xbox = {
|
||||||
|
.name = TYPE_USB_XID_GAMEPAD,
|
||||||
|
.version_id = 1,
|
||||||
|
.minimum_version_id = 1,
|
||||||
|
.fields = (VMStateField[]){ VMSTATE_USB_DEVICE(dev, USBXIDGamepadState),
|
||||||
|
// FIXME
|
||||||
|
VMSTATE_END_OF_LIST() },
|
||||||
|
};
|
||||||
|
|
||||||
|
static const VMStateDescription vmstate_usb_xbox_s = {
|
||||||
|
.name = TYPE_USB_XID_GAMEPAD_S,
|
||||||
|
.minimum_version_id = 1,
|
||||||
|
.fields = (VMStateField[]){ VMSTATE_USB_DEVICE(dev, USBXIDGamepadState),
|
||||||
|
// FIXME
|
||||||
|
VMSTATE_END_OF_LIST() },
|
||||||
|
};
|
||||||
|
|
||||||
|
static void usb_xbox_gamepad_class_initfn(ObjectClass *klass, void *data)
|
||||||
|
{
|
||||||
|
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||||
|
USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
|
||||||
|
|
||||||
|
uc->product_desc = "Microsoft Xbox Controller";
|
||||||
|
uc->usb_desc = &desc_xbox_gamepad;
|
||||||
|
uc->realize = usb_xbox_gamepad_realize;
|
||||||
|
uc->unrealize = usb_xbox_gamepad_unrealize;
|
||||||
|
usb_xid_gamepad_class_initfn(klass, data);
|
||||||
|
set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
|
||||||
|
dc->vmsd = &vmstate_usb_xbox;
|
||||||
|
device_class_set_props(dc, xid_properties);
|
||||||
|
dc->desc = "Microsoft Xbox Controller";
|
||||||
|
}
|
||||||
|
|
||||||
|
static void usb_xbox_gamepad_s_class_initfn(ObjectClass *klass, void *data)
|
||||||
|
{
|
||||||
|
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||||
|
USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
|
||||||
|
|
||||||
|
uc->product_desc = "Microsoft Xbox Controller S";
|
||||||
|
uc->usb_desc = &desc_xbox_gamepad_s;
|
||||||
|
uc->realize = usb_xbox_gamepad_s_realize;
|
||||||
|
uc->unrealize = usb_xbox_gamepad_unrealize;
|
||||||
|
usb_xid_gamepad_class_initfn(klass, data);
|
||||||
|
set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
|
||||||
|
dc->vmsd = &vmstate_usb_xbox_s;
|
||||||
|
device_class_set_props(dc, xid_properties);
|
||||||
|
dc->desc = "Microsoft Xbox Controller S";
|
||||||
|
}
|
||||||
|
|
||||||
|
static const TypeInfo usb_xbox_gamepad_info = {
|
||||||
|
.name = TYPE_USB_XID_GAMEPAD,
|
||||||
|
.parent = TYPE_USB_DEVICE,
|
||||||
|
.instance_size = sizeof(USBXIDGamepadState),
|
||||||
|
.class_init = usb_xbox_gamepad_class_initfn,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const TypeInfo usb_xbox_gamepad_s_info = {
|
||||||
|
.name = TYPE_USB_XID_GAMEPAD_S,
|
||||||
|
.parent = TYPE_USB_DEVICE,
|
||||||
|
.instance_size = sizeof(USBXIDGamepadState),
|
||||||
|
.class_init = usb_xbox_gamepad_s_class_initfn,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void usb_xid_register_types(void)
|
||||||
|
{
|
||||||
|
type_register_static(&usb_xbox_gamepad_info);
|
||||||
|
type_register_static(&usb_xbox_gamepad_s_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
type_init(usb_xid_register_types)
|
280
hw/xbox/xid.c
280
hw/xbox/xid.c
|
@ -19,22 +19,7 @@
|
||||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "qemu/osdep.h"
|
#include "xid.h"
|
||||||
#include "hw/qdev-properties.h"
|
|
||||||
#include "migration/vmstate.h"
|
|
||||||
#include "sysemu/sysemu.h"
|
|
||||||
#include "hw/hw.h"
|
|
||||||
#include "ui/console.h"
|
|
||||||
#include "hw/usb.h"
|
|
||||||
#include "hw/usb/desc.h"
|
|
||||||
#include "ui/xemu-input.h"
|
|
||||||
|
|
||||||
//#define DEBUG_XID
|
|
||||||
#ifdef DEBUG_XID
|
|
||||||
#define DPRINTF printf
|
|
||||||
#else
|
|
||||||
#define DPRINTF(...)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* http://xbox-linux.cvs.sourceforge.net/viewvc/xbox-linux/kernel-2.6/drivers/usb/input/xpad.c
|
* http://xbox-linux.cvs.sourceforge.net/viewvc/xbox-linux/kernel-2.6/drivers/usb/input/xpad.c
|
||||||
|
@ -42,156 +27,18 @@
|
||||||
* http://euc.jp/periphs/xbox-pad-desc.txt
|
* http://euc.jp/periphs/xbox-pad-desc.txt
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define USB_CLASS_XID 0x58
|
|
||||||
#define USB_DT_XID 0x42
|
|
||||||
|
|
||||||
#define HID_GET_REPORT 0x01
|
|
||||||
#define HID_SET_REPORT 0x09
|
|
||||||
#define XID_GET_CAPABILITIES 0x01
|
|
||||||
|
|
||||||
#define TYPE_USB_XID "usb-xbox-gamepad"
|
|
||||||
#define USB_XID(obj) OBJECT_CHECK(USBXIDState, (obj), TYPE_USB_XID)
|
|
||||||
|
|
||||||
enum {
|
|
||||||
STR_MANUFACTURER = 1,
|
|
||||||
STR_PRODUCT,
|
|
||||||
STR_SERIALNUMBER,
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef enum HapticEmulationMode {
|
typedef enum HapticEmulationMode {
|
||||||
EMU_NONE,
|
EMU_NONE,
|
||||||
EMU_HAPTIC_LEFT_RIGHT
|
EMU_HAPTIC_LEFT_RIGHT
|
||||||
} HapticEmulationMode;
|
} HapticEmulationMode;
|
||||||
|
|
||||||
static const USBDescStrings desc_strings = {
|
const USBDescStrings desc_strings = {
|
||||||
[STR_MANUFACTURER] = "QEMU",
|
[STR_MANUFACTURER] = "QEMU",
|
||||||
[STR_PRODUCT] = "Microsoft Xbox Controller",
|
[STR_PRODUCT] = "Microsoft Xbox Controller",
|
||||||
[STR_SERIALNUMBER] = "1",
|
[STR_SERIALNUMBER] = "1",
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct XIDDesc {
|
void update_output(USBXIDGamepadState *s)
|
||||||
uint8_t bLength;
|
|
||||||
uint8_t bDescriptorType;
|
|
||||||
uint16_t bcdXid;
|
|
||||||
uint8_t bType;
|
|
||||||
uint8_t bSubType;
|
|
||||||
uint8_t bMaxInputReportSize;
|
|
||||||
uint8_t bMaxOutputReportSize;
|
|
||||||
uint16_t wAlternateProductIds[4];
|
|
||||||
} QEMU_PACKED XIDDesc;
|
|
||||||
|
|
||||||
typedef struct XIDGamepadReport {
|
|
||||||
uint8_t bReportId;
|
|
||||||
uint8_t bLength;
|
|
||||||
uint16_t wButtons;
|
|
||||||
uint8_t bAnalogButtons[8];
|
|
||||||
int16_t sThumbLX;
|
|
||||||
int16_t sThumbLY;
|
|
||||||
int16_t sThumbRX;
|
|
||||||
int16_t sThumbRY;
|
|
||||||
} QEMU_PACKED XIDGamepadReport;
|
|
||||||
|
|
||||||
typedef struct XIDGamepadOutputReport {
|
|
||||||
uint8_t report_id; //FIXME: is this correct?
|
|
||||||
uint8_t length;
|
|
||||||
uint16_t left_actuator_strength;
|
|
||||||
uint16_t right_actuator_strength;
|
|
||||||
} QEMU_PACKED XIDGamepadOutputReport;
|
|
||||||
|
|
||||||
typedef struct USBXIDState {
|
|
||||||
USBDevice dev;
|
|
||||||
USBEndpoint *intr;
|
|
||||||
const XIDDesc *xid_desc;
|
|
||||||
XIDGamepadReport in_state;
|
|
||||||
XIDGamepadReport in_state_capabilities;
|
|
||||||
XIDGamepadOutputReport out_state;
|
|
||||||
XIDGamepadOutputReport out_state_capabilities;
|
|
||||||
uint8_t device_index;
|
|
||||||
} USBXIDState;
|
|
||||||
|
|
||||||
static const USBDescIface desc_iface_xbox_gamepad = {
|
|
||||||
.bInterfaceNumber = 0,
|
|
||||||
.bNumEndpoints = 2,
|
|
||||||
.bInterfaceClass = USB_CLASS_XID,
|
|
||||||
.bInterfaceSubClass = 0x42,
|
|
||||||
.bInterfaceProtocol = 0x00,
|
|
||||||
.eps = (USBDescEndpoint[]) {
|
|
||||||
{
|
|
||||||
.bEndpointAddress = USB_DIR_IN | 0x02,
|
|
||||||
.bmAttributes = USB_ENDPOINT_XFER_INT,
|
|
||||||
.wMaxPacketSize = 0x20,
|
|
||||||
.bInterval = 4,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.bEndpointAddress = USB_DIR_OUT | 0x02,
|
|
||||||
.bmAttributes = USB_ENDPOINT_XFER_INT,
|
|
||||||
.wMaxPacketSize = 0x20,
|
|
||||||
.bInterval = 4,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
static const USBDescDevice desc_device_xbox_gamepad = {
|
|
||||||
.bcdUSB = 0x0110,
|
|
||||||
.bMaxPacketSize0 = 0x40,
|
|
||||||
.bNumConfigurations = 1,
|
|
||||||
.confs = (USBDescConfig[]) {
|
|
||||||
{
|
|
||||||
.bNumInterfaces = 1,
|
|
||||||
.bConfigurationValue = 1,
|
|
||||||
.bmAttributes = USB_CFG_ATT_ONE,
|
|
||||||
.bMaxPower = 50,
|
|
||||||
.nif = 1,
|
|
||||||
.ifs = &desc_iface_xbox_gamepad,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
static const USBDesc desc_xbox_gamepad = {
|
|
||||||
.id = {
|
|
||||||
.idVendor = 0x045e,
|
|
||||||
.idProduct = 0x0202,
|
|
||||||
.bcdDevice = 0x0100,
|
|
||||||
.iManufacturer = STR_MANUFACTURER,
|
|
||||||
.iProduct = STR_PRODUCT,
|
|
||||||
.iSerialNumber = STR_SERIALNUMBER,
|
|
||||||
},
|
|
||||||
.full = &desc_device_xbox_gamepad,
|
|
||||||
.str = desc_strings,
|
|
||||||
};
|
|
||||||
|
|
||||||
static const XIDDesc desc_xid_xbox_gamepad = {
|
|
||||||
.bLength = 0x10,
|
|
||||||
.bDescriptorType = USB_DT_XID,
|
|
||||||
.bcdXid = 0x100,
|
|
||||||
.bType = 1,
|
|
||||||
.bSubType = 1,
|
|
||||||
.bMaxInputReportSize = 20,
|
|
||||||
.bMaxOutputReportSize = 6,
|
|
||||||
.wAlternateProductIds = { 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF },
|
|
||||||
};
|
|
||||||
|
|
||||||
#define GAMEPAD_A 0
|
|
||||||
#define GAMEPAD_B 1
|
|
||||||
#define GAMEPAD_X 2
|
|
||||||
#define GAMEPAD_Y 3
|
|
||||||
#define GAMEPAD_BLACK 4
|
|
||||||
#define GAMEPAD_WHITE 5
|
|
||||||
#define GAMEPAD_LEFT_TRIGGER 6
|
|
||||||
#define GAMEPAD_RIGHT_TRIGGER 7
|
|
||||||
|
|
||||||
#define GAMEPAD_DPAD_UP 8
|
|
||||||
#define GAMEPAD_DPAD_DOWN 9
|
|
||||||
#define GAMEPAD_DPAD_LEFT 10
|
|
||||||
#define GAMEPAD_DPAD_RIGHT 11
|
|
||||||
#define GAMEPAD_START 12
|
|
||||||
#define GAMEPAD_BACK 13
|
|
||||||
#define GAMEPAD_LEFT_THUMB 14
|
|
||||||
#define GAMEPAD_RIGHT_THUMB 15
|
|
||||||
|
|
||||||
#define BUTTON_MASK(button) (1 << ((button) - GAMEPAD_DPAD_UP))
|
|
||||||
|
|
||||||
static void update_output(USBXIDState *s)
|
|
||||||
{
|
{
|
||||||
if (xemu_input_get_test_mode()) {
|
if (xemu_input_get_test_mode()) {
|
||||||
// Don't report changes if we are testing the controller while running
|
// Don't report changes if we are testing the controller while running
|
||||||
|
@ -205,7 +52,7 @@ static void update_output(USBXIDState *s)
|
||||||
xemu_input_update_rumble(state);
|
xemu_input_update_rumble(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void update_input(USBXIDState *s)
|
void update_input(USBXIDGamepadState *s)
|
||||||
{
|
{
|
||||||
if (xemu_input_get_test_mode()) {
|
if (xemu_input_get_test_mode()) {
|
||||||
// Don't report changes if we are testing the controller while running
|
// Don't report changes if we are testing the controller while running
|
||||||
|
@ -256,15 +103,15 @@ static void update_input(USBXIDState *s)
|
||||||
s->in_state.sThumbRY = state->axis[CONTROLLER_AXIS_RSTICK_Y];
|
s->in_state.sThumbRY = state->axis[CONTROLLER_AXIS_RSTICK_Y];
|
||||||
}
|
}
|
||||||
|
|
||||||
static void usb_xid_handle_reset(USBDevice *dev)
|
void usb_xid_handle_reset(USBDevice *dev)
|
||||||
{
|
{
|
||||||
DPRINTF("xid reset\n");
|
DPRINTF("xid reset\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void usb_xid_handle_control(USBDevice *dev, USBPacket *p,
|
void usb_xid_handle_control(USBDevice *dev, USBPacket *p,
|
||||||
int request, int value, int index, int length, uint8_t *data)
|
int request, int value, int index, int length, uint8_t *data)
|
||||||
{
|
{
|
||||||
USBXIDState *s = (USBXIDState *)dev;
|
USBXIDGamepadState *s = (USBXIDGamepadState *)dev;
|
||||||
|
|
||||||
DPRINTF("xid handle_control 0x%x 0x%x\n", request, value);
|
DPRINTF("xid handle_control 0x%x 0x%x\n", request, value);
|
||||||
|
|
||||||
|
@ -368,36 +215,6 @@ static void usb_xid_handle_control(USBDevice *dev, USBPacket *p,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void usb_xid_handle_data(USBDevice *dev, USBPacket *p)
|
|
||||||
{
|
|
||||||
USBXIDState *s = DO_UPCAST(USBXIDState, dev, dev);
|
|
||||||
|
|
||||||
DPRINTF("xid handle_data 0x%x %d 0x%zx\n", p->pid, p->ep->nr, p->iov.size);
|
|
||||||
|
|
||||||
switch (p->pid) {
|
|
||||||
case USB_TOKEN_IN:
|
|
||||||
if (p->ep->nr == 2) {
|
|
||||||
update_input(s);
|
|
||||||
usb_packet_copy(p, &s->in_state, s->in_state.bLength);
|
|
||||||
} else {
|
|
||||||
assert(false);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case USB_TOKEN_OUT:
|
|
||||||
if (p->ep->nr == 2) {
|
|
||||||
usb_packet_copy(p, &s->out_state, s->out_state.length);
|
|
||||||
update_output(s);
|
|
||||||
} else {
|
|
||||||
assert(false);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
p->status = USB_RET_STALL;
|
|
||||||
assert(false);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
static void usb_xid_handle_destroy(USBDevice *dev)
|
static void usb_xid_handle_destroy(USBDevice *dev)
|
||||||
{
|
{
|
||||||
|
@ -406,87 +223,6 @@ static void usb_xid_handle_destroy(USBDevice *dev)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void usb_xbox_gamepad_unrealize(USBDevice *dev)
|
void usb_xbox_gamepad_unrealize(USBDevice *dev)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
static void usb_xid_class_initfn(ObjectClass *klass, void *data)
|
|
||||||
{
|
|
||||||
USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
|
|
||||||
|
|
||||||
uc->handle_reset = usb_xid_handle_reset;
|
|
||||||
uc->handle_control = usb_xid_handle_control;
|
|
||||||
uc->handle_data = usb_xid_handle_data;
|
|
||||||
// uc->handle_destroy = usb_xid_handle_destroy;
|
|
||||||
uc->handle_attach = usb_desc_attach;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void usb_xbox_gamepad_realize(USBDevice *dev, Error **errp)
|
|
||||||
{
|
|
||||||
USBXIDState *s = USB_XID(dev);
|
|
||||||
usb_desc_create_serial(dev);
|
|
||||||
usb_desc_init(dev);
|
|
||||||
s->intr = usb_ep_get(dev, USB_TOKEN_IN, 2);
|
|
||||||
|
|
||||||
s->in_state.bLength = sizeof(s->in_state);
|
|
||||||
s->in_state.bReportId = 0;
|
|
||||||
|
|
||||||
s->out_state.length = sizeof(s->out_state);
|
|
||||||
s->out_state.report_id = 0;
|
|
||||||
|
|
||||||
s->xid_desc = &desc_xid_xbox_gamepad;
|
|
||||||
|
|
||||||
memset(&s->in_state_capabilities, 0xFF, sizeof(s->in_state_capabilities));
|
|
||||||
s->in_state_capabilities.bLength = sizeof(s->in_state_capabilities);
|
|
||||||
s->in_state_capabilities.bReportId = 0;
|
|
||||||
|
|
||||||
memset(&s->out_state_capabilities, 0xFF, sizeof(s->out_state_capabilities));
|
|
||||||
s->out_state_capabilities.length = sizeof(s->out_state_capabilities);
|
|
||||||
s->out_state_capabilities.report_id = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static Property xid_properties[] = {
|
|
||||||
DEFINE_PROP_UINT8("index", USBXIDState, device_index, 0),
|
|
||||||
DEFINE_PROP_END_OF_LIST(),
|
|
||||||
};
|
|
||||||
|
|
||||||
static const VMStateDescription vmstate_usb_xbox = {
|
|
||||||
.name = TYPE_USB_XID,
|
|
||||||
.version_id = 1,
|
|
||||||
.minimum_version_id = 1,
|
|
||||||
.fields = (VMStateField[]) {
|
|
||||||
VMSTATE_USB_DEVICE(dev, USBXIDState),
|
|
||||||
// FIXME
|
|
||||||
VMSTATE_END_OF_LIST()
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
static void usb_xbox_gamepad_class_initfn(ObjectClass *klass, void *data)
|
|
||||||
{
|
|
||||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
|
||||||
USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
|
|
||||||
|
|
||||||
uc->product_desc = "Microsoft Xbox Controller";
|
|
||||||
uc->usb_desc = &desc_xbox_gamepad;
|
|
||||||
uc->realize = usb_xbox_gamepad_realize;
|
|
||||||
uc->unrealize = usb_xbox_gamepad_unrealize;
|
|
||||||
usb_xid_class_initfn(klass, data);
|
|
||||||
set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
|
|
||||||
dc->vmsd = &vmstate_usb_xbox;
|
|
||||||
device_class_set_props(dc, xid_properties);
|
|
||||||
dc->desc = "Microsoft Xbox Controller";
|
|
||||||
}
|
|
||||||
|
|
||||||
static const TypeInfo usb_xbox_gamepad_info = {
|
|
||||||
.name = TYPE_USB_XID,
|
|
||||||
.parent = TYPE_USB_DEVICE,
|
|
||||||
.instance_size = sizeof(USBXIDState),
|
|
||||||
.class_init = usb_xbox_gamepad_class_initfn,
|
|
||||||
};
|
|
||||||
|
|
||||||
static void usb_xid_register_types(void)
|
|
||||||
{
|
|
||||||
type_register_static(&usb_xbox_gamepad_info);
|
|
||||||
}
|
|
||||||
|
|
||||||
type_init(usb_xid_register_types)
|
|
||||||
|
|
|
@ -0,0 +1,137 @@
|
||||||
|
#ifndef __XID_H__
|
||||||
|
#define __XID_H__
|
||||||
|
|
||||||
|
/*
|
||||||
|
* QEMU USB XID Devices
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013 espes
|
||||||
|
* Copyright (c) 2017 Jannik Vogel
|
||||||
|
* Copyright (c) 2018-2021 Matt Borgerson
|
||||||
|
* Copyright (c) 2023 Fred Hallock
|
||||||
|
*
|
||||||
|
* 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 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "qemu/osdep.h"
|
||||||
|
#include "hw/hw.h"
|
||||||
|
#include "hw/qdev-properties.h"
|
||||||
|
#include "hw/usb.h"
|
||||||
|
#include "hw/usb/desc.h"
|
||||||
|
#include "migration/vmstate.h"
|
||||||
|
#include "sysemu/sysemu.h"
|
||||||
|
#include "ui/console.h"
|
||||||
|
#include "ui/xemu-input.h"
|
||||||
|
|
||||||
|
// #define DEBUG_XID
|
||||||
|
#ifdef DEBUG_XID
|
||||||
|
#define DPRINTF printf
|
||||||
|
#else
|
||||||
|
#define DPRINTF(...)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define USB_CLASS_XID 0x58
|
||||||
|
#define USB_DT_XID 0x42
|
||||||
|
|
||||||
|
#define HID_GET_REPORT 0x01
|
||||||
|
#define HID_SET_REPORT 0x09
|
||||||
|
#define XID_GET_CAPABILITIES 0x01
|
||||||
|
|
||||||
|
#define XID_DEVICETYPE_GAMEPAD 0x01
|
||||||
|
|
||||||
|
#define XID_DEVICESUBTYPE_GAMEPAD 0x01
|
||||||
|
#define XID_DEVICESUBTYPE_GAMEPAD_S 0x02
|
||||||
|
|
||||||
|
#define TYPE_USB_XID_GAMEPAD "usb-xbox-gamepad"
|
||||||
|
#define TYPE_USB_XID_GAMEPAD_S "usb-xbox-gamepad-s"
|
||||||
|
|
||||||
|
#define GAMEPAD_A 0
|
||||||
|
#define GAMEPAD_B 1
|
||||||
|
#define GAMEPAD_X 2
|
||||||
|
#define GAMEPAD_Y 3
|
||||||
|
#define GAMEPAD_BLACK 4
|
||||||
|
#define GAMEPAD_WHITE 5
|
||||||
|
#define GAMEPAD_LEFT_TRIGGER 6
|
||||||
|
#define GAMEPAD_RIGHT_TRIGGER 7
|
||||||
|
|
||||||
|
#define GAMEPAD_DPAD_UP 8
|
||||||
|
#define GAMEPAD_DPAD_DOWN 9
|
||||||
|
#define GAMEPAD_DPAD_LEFT 10
|
||||||
|
#define GAMEPAD_DPAD_RIGHT 11
|
||||||
|
#define GAMEPAD_START 12
|
||||||
|
#define GAMEPAD_BACK 13
|
||||||
|
#define GAMEPAD_LEFT_THUMB 14
|
||||||
|
#define GAMEPAD_RIGHT_THUMB 15
|
||||||
|
|
||||||
|
#define BUTTON_MASK(button) (1 << ((button) - GAMEPAD_DPAD_UP))
|
||||||
|
|
||||||
|
enum {
|
||||||
|
STR_MANUFACTURER = 1,
|
||||||
|
STR_PRODUCT,
|
||||||
|
STR_SERIALNUMBER,
|
||||||
|
};
|
||||||
|
|
||||||
|
extern const USBDescStrings desc_strings;
|
||||||
|
|
||||||
|
typedef struct XIDDesc {
|
||||||
|
uint8_t bLength;
|
||||||
|
uint8_t bDescriptorType;
|
||||||
|
uint16_t bcdXid;
|
||||||
|
uint8_t bType;
|
||||||
|
uint8_t bSubType;
|
||||||
|
uint8_t bMaxInputReportSize;
|
||||||
|
uint8_t bMaxOutputReportSize;
|
||||||
|
uint16_t wAlternateProductIds[4];
|
||||||
|
} QEMU_PACKED XIDDesc;
|
||||||
|
|
||||||
|
typedef struct XIDGamepadReport {
|
||||||
|
uint8_t bReportId;
|
||||||
|
uint8_t bLength;
|
||||||
|
uint16_t wButtons;
|
||||||
|
uint8_t bAnalogButtons[8];
|
||||||
|
int16_t sThumbLX;
|
||||||
|
int16_t sThumbLY;
|
||||||
|
int16_t sThumbRX;
|
||||||
|
int16_t sThumbRY;
|
||||||
|
} QEMU_PACKED XIDGamepadReport;
|
||||||
|
|
||||||
|
typedef struct XIDGamepadOutputReport {
|
||||||
|
uint8_t report_id; // FIXME: is this correct?
|
||||||
|
uint8_t length;
|
||||||
|
uint16_t left_actuator_strength;
|
||||||
|
uint16_t right_actuator_strength;
|
||||||
|
} QEMU_PACKED XIDGamepadOutputReport;
|
||||||
|
|
||||||
|
typedef struct USBXIDGamepadState {
|
||||||
|
USBDevice dev;
|
||||||
|
USBEndpoint *intr;
|
||||||
|
const XIDDesc *xid_desc;
|
||||||
|
XIDGamepadReport in_state;
|
||||||
|
XIDGamepadReport in_state_capabilities;
|
||||||
|
XIDGamepadOutputReport out_state;
|
||||||
|
XIDGamepadOutputReport out_state_capabilities;
|
||||||
|
uint8_t device_index;
|
||||||
|
} USBXIDGamepadState;
|
||||||
|
|
||||||
|
void update_input(USBXIDGamepadState *s);
|
||||||
|
void update_output(USBXIDGamepadState *s);
|
||||||
|
void usb_xid_handle_reset(USBDevice *dev);
|
||||||
|
void usb_xid_handle_control(USBDevice *dev, USBPacket *p, int request,
|
||||||
|
int value, int index, int length, uint8_t *data);
|
||||||
|
void usb_xbox_gamepad_unrealize(USBDevice *dev);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
void usb_xid_handle_destroy(USBDevice *dev);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
|
@ -2292,14 +2292,6 @@ libglslang = not_found
|
||||||
|
|
||||||
if host_os == 'windows'
|
if host_os == 'windows'
|
||||||
vulkan = declare_dependency(compile_args: ['-DVK_USE_PLATFORM_WIN32_KHR'])
|
vulkan = declare_dependency(compile_args: ['-DVK_USE_PLATFORM_WIN32_KHR'])
|
||||||
libglslang = declare_dependency(link_args: [
|
|
||||||
'-lglslang',
|
|
||||||
'-lMachineIndependent',
|
|
||||||
'-lGenericCodeGen',
|
|
||||||
'-lSPIRV',
|
|
||||||
'-lSPIRV-Tools',
|
|
||||||
'-lSPIRV-Tools-opt'
|
|
||||||
])
|
|
||||||
elif host_os == 'linux'
|
elif host_os == 'linux'
|
||||||
vulkan = dependency('vulkan')
|
vulkan = dependency('vulkan')
|
||||||
endif
|
endif
|
||||||
|
|
|
@ -261,6 +261,12 @@ Lib('SPIRV-Reflect', 'https://github.com/KhronosGroup/SPIRV-Reflect',
|
||||||
submodule=Submodule('subprojects/SPIRV-Reflect.wrap')
|
submodule=Submodule('subprojects/SPIRV-Reflect.wrap')
|
||||||
),
|
),
|
||||||
|
|
||||||
|
Lib('glslang', 'https://github.com/KhronosGroup/glslang',
|
||||||
|
bsd_3clause, 'https://raw.githubusercontent.com/KhronosGroup/glslang/main/LICENSE.txt',
|
||||||
|
ships_static=all_platforms,
|
||||||
|
submodule=Submodule('subprojects/glslang.wrap')
|
||||||
|
),
|
||||||
|
|
||||||
#
|
#
|
||||||
# Data files included with xemu
|
# Data files included with xemu
|
||||||
#
|
#
|
||||||
|
@ -374,18 +380,6 @@ Lib('miniz', 'https://github.com/richgel999/miniz',
|
||||||
ships_static={windows}, platform={windows},
|
ships_static={windows}, platform={windows},
|
||||||
version='2.1.0'
|
version='2.1.0'
|
||||||
),
|
),
|
||||||
|
|
||||||
Lib('glslang', 'https://github.com/KhronosGroup/glslang',
|
|
||||||
bsd_3clause, 'https://raw.githubusercontent.com/KhronosGroup/glslang/main/LICENSE.txt',
|
|
||||||
ships_static={windows}, platform={windows},
|
|
||||||
version='14.3.0'
|
|
||||||
),
|
|
||||||
|
|
||||||
Lib('SPIRV-Tools', 'https://github.com/KhronosGroup/SPIRV-Tools',
|
|
||||||
apache2, 'https://raw.githubusercontent.com/KhronosGroup/SPIRV-Tools/main/LICENSE',
|
|
||||||
ships_static={windows}, platform={windows},
|
|
||||||
pkgconfig=PkgConfig('SPIRV-Tools')
|
|
||||||
),
|
|
||||||
]
|
]
|
||||||
|
|
||||||
def gen_license():
|
def gen_license():
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
[wrap-git]
|
[wrap-git]
|
||||||
url=https://github.com/KhronosGroup/SPIRV-Reflect
|
url=https://github.com/KhronosGroup/SPIRV-Reflect
|
||||||
revision=vulkan-sdk-1.3.296.0
|
revision=vulkan-sdk-1.4.304.0
|
||||||
depth=1
|
depth=1
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
[wrap-git]
|
[wrap-git]
|
||||||
url=https://github.com/KhronosGroup/glslang
|
url=https://github.com/KhronosGroup/glslang
|
||||||
revision=vulkan-sdk-1.3.296.0
|
revision=vulkan-sdk-1.4.304.0
|
||||||
depth=1
|
depth=1
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
[wrap-git]
|
[wrap-git]
|
||||||
url=https://github.com/zeux/volk
|
url=https://github.com/zeux/volk
|
||||||
revision=1.3.295
|
revision=1.4.304
|
||||||
depth=1
|
depth=1
|
||||||
|
|
|
@ -6,10 +6,10 @@ FROM ubuntu:24.04
|
||||||
|
|
||||||
ENV MXE_PATH=/opt/mxe
|
ENV MXE_PATH=/opt/mxe
|
||||||
ENV MXE_REPO=https://github.com/mxe/mxe.git
|
ENV MXE_REPO=https://github.com/mxe/mxe.git
|
||||||
ENV MXE_VERSION=ab676e8ce5ba921daaa80a123ff2e415aac4524a
|
ENV MXE_VERSION=7f054f14930d109412d2d61d019c12fa80816b8c
|
||||||
|
|
||||||
ENV MXE_LLVM_MINGW_REPO=https://github.com/libvips/build-win64-mxe
|
ENV MXE_LLVM_MINGW_REPO=https://github.com/libvips/build-win64-mxe
|
||||||
ENV MXE_LLVM_MINGW_VERSION=21e02f87c282fcfe17c8376217b0a4f44f14d01b
|
ENV MXE_LLVM_MINGW_VERSION=8a4e0ab8a3b574287378459356f6bdaecc727de2
|
||||||
ENV MXE_LLVM_MINGW_PATH=/opt/build-win64-mxe
|
ENV MXE_LLVM_MINGW_PATH=/opt/build-win64-mxe
|
||||||
|
|
||||||
ARG PLUGIN_DIRS="${MXE_LLVM_MINGW_PATH} ${MXE_LLVM_MINGW_PATH}/build/plugins/llvm-mingw"
|
ARG PLUGIN_DIRS="${MXE_LLVM_MINGW_PATH} ${MXE_LLVM_MINGW_PATH}/build/plugins/llvm-mingw"
|
||||||
|
@ -78,9 +78,6 @@ RUN make \
|
||||||
|
|
||||||
RUN rm ${MXE_PATH}/src/sdl2*.patch
|
RUN rm ${MXE_PATH}/src/sdl2*.patch
|
||||||
COPY vulkan-headers.mk \
|
COPY vulkan-headers.mk \
|
||||||
spirv-headers.mk \
|
|
||||||
spirv-tools.mk \
|
|
||||||
glslang.mk \
|
|
||||||
glib.mk \
|
glib.mk \
|
||||||
sdl2.mk \
|
sdl2.mk \
|
||||||
libsamplerate.mk \
|
libsamplerate.mk \
|
||||||
|
@ -101,10 +98,7 @@ RUN make \
|
||||||
cmake \
|
cmake \
|
||||||
libslirp \
|
libslirp \
|
||||||
sdl2 \
|
sdl2 \
|
||||||
vulkan-headers \
|
vulkan-headers
|
||||||
spirv-headers \
|
|
||||||
spirv-tools \
|
|
||||||
glslang
|
|
||||||
|
|
||||||
RUN find ${MXE_PATH}/usr -executable -type f -exec chmod a+x {} \;
|
RUN find ${MXE_PATH}/usr -executable -type f -exec chmod a+x {} \;
|
||||||
|
|
||||||
|
|
|
@ -1,25 +0,0 @@
|
||||||
PKG := glslang
|
|
||||||
$(PKG)_WEBSITE := https://github.com/KhronosGroup/glslang
|
|
||||||
$(PKG)_DESCR := glslang
|
|
||||||
$(PKG)_IGNORE :=
|
|
||||||
$(PKG)_VERSION := 15.0.0
|
|
||||||
$(PKG)_SUBDIR := glslang-$($(PKG)_VERSION)
|
|
||||||
$(PKG)_FILE := glslang-$($(PKG)_VERSION).tar.gz
|
|
||||||
$(PKG)_CHECKSUM := c31c8c2e89af907507c0631273989526ee7d5cdf7df95ececd628fd7b811e064
|
|
||||||
$(PKG)_URL := https://github.com/KhronosGroup/glslang/archive/refs/tags/$($(PKG)_VERSION).tar.gz
|
|
||||||
$(PKG)_DEPS := cc spirv-tools
|
|
||||||
|
|
||||||
define $(PKG)_BUILD
|
|
||||||
$(TARGET)-cmake -B'$(BUILD_DIR)' -S'$(SOURCE_DIR)' \
|
|
||||||
-G"Ninja" \
|
|
||||||
-DBUILD_SHARED_LIBS=$(CMAKE_SHARED_BOOL) \
|
|
||||||
-DENABLE_GLSLANG_BINARIES=OFF \
|
|
||||||
-DGLSLANG_TESTS=OFF \
|
|
||||||
-DBUILD_EXTERNAL=OFF \
|
|
||||||
-DALLOW_EXTERNAL_SPIRV_TOOLS=ON \
|
|
||||||
-DVERBOSE=1
|
|
||||||
$(TARGET)-cmake --build '$(BUILD_DIR)'
|
|
||||||
$(TARGET)-cmake --install '$(BUILD_DIR)'
|
|
||||||
endef
|
|
||||||
|
|
||||||
# FIXME: Shared libs
|
|
|
@ -1,16 +0,0 @@
|
||||||
PKG := spirv-headers
|
|
||||||
$(PKG)_WEBSITE := https://github.com/KhronosGroup/SPIRV-Headers
|
|
||||||
$(PKG)_DESCR := SPIRV-Headers
|
|
||||||
$(PKG)_IGNORE :=
|
|
||||||
$(PKG)_VERSION := vulkan-sdk-1.3.296.0
|
|
||||||
$(PKG)_SUBDIR := SPIRV-Headers-$($(PKG)_VERSION)
|
|
||||||
$(PKG)_FILE := spirv-headers-$($(PKG)_VERSION).tar.gz
|
|
||||||
$(PKG)_CHECKSUM := 1423d58a1171611d5aba2bf6f8c69c72ef9c38a0aca12c3493e4fda64c9b2dc6
|
|
||||||
$(PKG)_URL := https://github.com/KhronosGroup/SPIRV-Headers/archive/refs/tags/$($(PKG)_VERSION).tar.gz
|
|
||||||
$(PKG)_DEPS := cc
|
|
||||||
|
|
||||||
define $(PKG)_BUILD
|
|
||||||
$(TARGET)-cmake -B'$(BUILD_DIR)' -S'$(SOURCE_DIR)'
|
|
||||||
$(TARGET)-cmake --build '$(BUILD_DIR)'
|
|
||||||
$(TARGET)-cmake --install '$(BUILD_DIR)'
|
|
||||||
endef
|
|
|
@ -1,27 +0,0 @@
|
||||||
PKG := spirv-tools
|
|
||||||
$(PKG)_WEBSITE := https://github.com/KhronosGroup/SPIRV-Tools
|
|
||||||
$(PKG)_DESCR := SPIRV-Tools
|
|
||||||
$(PKG)_IGNORE :=
|
|
||||||
$(PKG)_VERSION := vulkan-sdk-1.3.296.0
|
|
||||||
$(PKG)_SUBDIR := SPIRV-Tools-$($(PKG)_VERSION)
|
|
||||||
$(PKG)_FILE := spirv-tools-$($(PKG)_VERSION).tar.gz
|
|
||||||
$(PKG)_CHECKSUM := 75aafdf7e731b4b6bfb36a590ddfbb38ebc605d80487f38254da24fe0cb95837
|
|
||||||
$(PKG)_URL := https://github.com/KhronosGroup/SPIRV-Tools/archive/refs/tags/$($(PKG)_VERSION).tar.gz
|
|
||||||
$(PKG)_DEPS := cc spirv-headers
|
|
||||||
|
|
||||||
define $(PKG)_BUILD
|
|
||||||
$(TARGET)-cmake -B'$(BUILD_DIR)' -S'$(SOURCE_DIR)' \
|
|
||||||
-G"Ninja" \
|
|
||||||
-DBUILD_SHARED_LIBS=$(CMAKE_SHARED_BOOL) \
|
|
||||||
-DSPIRV-Headers_SOURCE_DIR=$(PREFIX)/$(TARGET) \
|
|
||||||
-DSPIRV_WERROR=OFF \
|
|
||||||
-DBUILD_SHARED_LIBS=OFF \
|
|
||||||
-DSPIRV_TOOLS_BUILD_STATIC=ON \
|
|
||||||
-DSPIRV_SKIP_EXECUTABLES=ON \
|
|
||||||
-DSPIRV_SKIP_TESTS=ON \
|
|
||||||
-DVERBOSE=1
|
|
||||||
$(TARGET)-cmake --build '$(BUILD_DIR)'
|
|
||||||
$(TARGET)-cmake --install '$(BUILD_DIR)'
|
|
||||||
endef
|
|
||||||
|
|
||||||
# FIXME: Shared libs
|
|
|
@ -2,10 +2,10 @@ PKG := vulkan-headers
|
||||||
$(PKG)_WEBSITE := https://github.com/KhronosGroup/Vulkan-Headers
|
$(PKG)_WEBSITE := https://github.com/KhronosGroup/Vulkan-Headers
|
||||||
$(PKG)_DESCR := Vulkan-Headers
|
$(PKG)_DESCR := Vulkan-Headers
|
||||||
$(PKG)_IGNORE :=
|
$(PKG)_IGNORE :=
|
||||||
$(PKG)_VERSION := vulkan-sdk-1.3.296.0
|
$(PKG)_VERSION := vulkan-sdk-1.4.304.0
|
||||||
$(PKG)_SUBDIR := Vulkan-Headers-$($(PKG)_VERSION)
|
$(PKG)_SUBDIR := Vulkan-Headers-$($(PKG)_VERSION)
|
||||||
$(PKG)_FILE := vulkan-headers-$($(PKG)_VERSION).tar.gz
|
$(PKG)_FILE := vulkan-headers-$($(PKG)_VERSION).tar.gz
|
||||||
$(PKG)_CHECKSUM := 1e872a0be3890784bbe68dcd89b7e017fed77ba95820841848718c98bda6dc33
|
$(PKG)_CHECKSUM := 46f8f5b6384a36c688e0c40d28d534df41d22de406493dfb5c9b7bcc29672613
|
||||||
$(PKG)_URL := https://github.com/KhronosGroup/Vulkan-Headers/archive/refs/tags/$($(PKG)_VERSION).tar.gz
|
$(PKG)_URL := https://github.com/KhronosGroup/Vulkan-Headers/archive/refs/tags/$($(PKG)_VERSION).tar.gz
|
||||||
$(PKG)_DEPS := cc
|
$(PKG)_DEPS := cc
|
||||||
|
|
||||||
|
|
|
@ -87,6 +87,8 @@ static void xemu_input_print_controller_state(ControllerState *state)
|
||||||
ControllerStateList available_controllers =
|
ControllerStateList available_controllers =
|
||||||
QTAILQ_HEAD_INITIALIZER(available_controllers);
|
QTAILQ_HEAD_INITIALIZER(available_controllers);
|
||||||
ControllerState *bound_controllers[4] = { NULL, NULL, NULL, NULL };
|
ControllerState *bound_controllers[4] = { NULL, NULL, NULL, NULL };
|
||||||
|
const char *bound_drivers[4] = { DRIVER_DUKE, DRIVER_DUKE, DRIVER_DUKE,
|
||||||
|
DRIVER_DUKE };
|
||||||
int test_mode;
|
int test_mode;
|
||||||
|
|
||||||
static const char **port_index_to_settings_key_map[] = {
|
static const char **port_index_to_settings_key_map[] = {
|
||||||
|
@ -96,6 +98,13 @@ static const char **port_index_to_settings_key_map[] = {
|
||||||
&g_config.input.bindings.port4,
|
&g_config.input.bindings.port4,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const char **port_index_to_driver_settings_key_map[] = {
|
||||||
|
&g_config.input.bindings.port1_driver,
|
||||||
|
&g_config.input.bindings.port2_driver,
|
||||||
|
&g_config.input.bindings.port3_driver,
|
||||||
|
&g_config.input.bindings.port4_driver
|
||||||
|
};
|
||||||
|
|
||||||
static int *peripheral_types_settings_map[4][2] = {
|
static int *peripheral_types_settings_map[4][2] = {
|
||||||
{ &g_config.input.peripherals.port1.peripheral_type_0,
|
{ &g_config.input.peripherals.port1.peripheral_type_0,
|
||||||
&g_config.input.peripherals.port1.peripheral_type_1 },
|
&g_config.input.peripherals.port1.peripheral_type_1 },
|
||||||
|
@ -120,6 +129,25 @@ static const char **peripheral_params_settings_map[4][2] = {
|
||||||
|
|
||||||
static int sdl_kbd_scancode_map[25];
|
static int sdl_kbd_scancode_map[25];
|
||||||
|
|
||||||
|
static const char *get_bound_driver(int port)
|
||||||
|
{
|
||||||
|
assert(port >= 0 && port <= 3);
|
||||||
|
const char *driver = *port_index_to_driver_settings_key_map[port];
|
||||||
|
|
||||||
|
// If the driver in the config is NULL, empty, or unrecognized
|
||||||
|
// then default to DRIVER_DUKE
|
||||||
|
if (driver == NULL)
|
||||||
|
return DRIVER_DUKE;
|
||||||
|
if (strlen(driver) == 0)
|
||||||
|
return DRIVER_DUKE;
|
||||||
|
if (strcmp(driver, DRIVER_DUKE) == 0)
|
||||||
|
return DRIVER_DUKE;
|
||||||
|
if (strcmp(driver, DRIVER_S) == 0)
|
||||||
|
return DRIVER_S;
|
||||||
|
|
||||||
|
return DRIVER_DUKE;
|
||||||
|
}
|
||||||
|
|
||||||
static const int port_map[4] = { 3, 4, 1, 2 };
|
static const int port_map[4] = { 3, 4, 1, 2 };
|
||||||
|
|
||||||
const char *peripheral_type_names[3] = {
|
const char *peripheral_type_names[3] = {
|
||||||
|
@ -184,6 +212,11 @@ void xemu_input_init(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bound_drivers[0] = get_bound_driver(0);
|
||||||
|
bound_drivers[1] = get_bound_driver(1);
|
||||||
|
bound_drivers[2] = get_bound_driver(2);
|
||||||
|
bound_drivers[3] = get_bound_driver(3);
|
||||||
|
|
||||||
// Check to see if we should auto-bind the keyboard
|
// Check to see if we should auto-bind the keyboard
|
||||||
int port = xemu_input_get_controller_default_bind_port(new_con, 0);
|
int port = xemu_input_get_controller_default_bind_port(new_con, 0);
|
||||||
if (port >= 0) {
|
if (port >= 0) {
|
||||||
|
@ -615,6 +648,8 @@ void xemu_input_bind(int index, ControllerState *state, int save)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
xemu_settings_set_string(port_index_to_settings_key_map[index], guid_buf);
|
xemu_settings_set_string(port_index_to_settings_key_map[index], guid_buf);
|
||||||
|
xemu_settings_set_string(port_index_to_driver_settings_key_map[index],
|
||||||
|
bound_drivers[index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bind new controller
|
// Bind new controller
|
||||||
|
@ -643,7 +678,7 @@ void xemu_input_bind(int index, ControllerState *state, int save)
|
||||||
QDict *qdict = qdict_new();
|
QDict *qdict = qdict_new();
|
||||||
|
|
||||||
// Specify device driver
|
// Specify device driver
|
||||||
qdict_put_str(qdict, "driver", "usb-xbox-gamepad");
|
qdict_put_str(qdict, "driver", bound_drivers[index]);
|
||||||
|
|
||||||
// Specify device identifier
|
// Specify device identifier
|
||||||
static int id_counter = 0;
|
static int id_counter = 0;
|
||||||
|
|
|
@ -30,6 +30,12 @@
|
||||||
|
|
||||||
#include "qemu/queue.h"
|
#include "qemu/queue.h"
|
||||||
|
|
||||||
|
#define DRIVER_DUKE "usb-xbox-gamepad"
|
||||||
|
#define DRIVER_S "usb-xbox-gamepad-s"
|
||||||
|
|
||||||
|
#define DRIVER_DUKE_DISPLAY_NAME "Xbox Controller"
|
||||||
|
#define DRIVER_S_DISPLAY_NAME "Xbox Controller S"
|
||||||
|
|
||||||
enum controller_state_buttons_mask {
|
enum controller_state_buttons_mask {
|
||||||
CONTROLLER_BUTTON_A = (1 << 0),
|
CONTROLLER_BUTTON_A = (1 << 0),
|
||||||
CONTROLLER_BUTTON_B = (1 << 1),
|
CONTROLLER_BUTTON_B = (1 << 1),
|
||||||
|
@ -116,6 +122,7 @@ typedef struct ControllerState {
|
||||||
typedef QTAILQ_HEAD(, ControllerState) ControllerStateList;
|
typedef QTAILQ_HEAD(, ControllerState) ControllerStateList;
|
||||||
extern ControllerStateList available_controllers;
|
extern ControllerStateList available_controllers;
|
||||||
extern ControllerState *bound_controllers[4];
|
extern ControllerState *bound_controllers[4];
|
||||||
|
extern const char *bound_drivers[4];
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include "gl-helpers.hh"
|
#include "gl-helpers.hh"
|
||||||
#include "common.hh"
|
#include "common.hh"
|
||||||
#include "data/controller_mask.png.h"
|
#include "data/controller_mask.png.h"
|
||||||
|
#include "data/controller_mask_s.png.h"
|
||||||
#include "data/logo_sdf.png.h"
|
#include "data/logo_sdf.png.h"
|
||||||
#include "data/xemu_64x64.png.h"
|
#include "data/xemu_64x64.png.h"
|
||||||
#include "data/xmu_mask.png.h"
|
#include "data/xmu_mask.png.h"
|
||||||
|
@ -36,6 +37,8 @@
|
||||||
|
|
||||||
Fbo *controller_fbo, *xmu_fbo, *xblc_fbo, *logo_fbo;
|
Fbo *controller_fbo, *xmu_fbo, *xblc_fbo, *logo_fbo;
|
||||||
GLuint g_controller_tex, g_logo_tex, g_icon_tex, g_xmu_tex, g_xblc_tex;
|
GLuint g_controller_tex, g_logo_tex, g_icon_tex, g_xmu_tex, g_xblc_tex;
|
||||||
|
GLuint g_controller_duke_tex, g_controller_s_tex,
|
||||||
|
g_logo_tex, g_icon_tex, g_xmu_tex, g_xblc_tex;
|
||||||
|
|
||||||
enum class ShaderType {
|
enum class ShaderType {
|
||||||
Blit,
|
Blit,
|
||||||
|
@ -443,8 +446,10 @@ enum tex_item_names {
|
||||||
void InitCustomRendering(void)
|
void InitCustomRendering(void)
|
||||||
{
|
{
|
||||||
glActiveTexture(GL_TEXTURE0);
|
glActiveTexture(GL_TEXTURE0);
|
||||||
g_controller_tex =
|
g_controller_duke_tex =
|
||||||
LoadTextureFromMemory(controller_mask_data, controller_mask_size);
|
LoadTextureFromMemory(controller_mask_data, controller_mask_size);
|
||||||
|
g_controller_s_tex =
|
||||||
|
LoadTextureFromMemory(controller_mask_s_data, controller_mask_s_size);
|
||||||
g_decal_shader = NewDecalShader(ShaderType::Mask);
|
g_decal_shader = NewDecalShader(ShaderType::Mask);
|
||||||
controller_fbo = new Fbo(512, 512);
|
controller_fbo = new Fbo(512, 512);
|
||||||
|
|
||||||
|
@ -471,7 +476,7 @@ static void RenderMeter(DecalShader *s, float x, float y, float width,
|
||||||
RenderDecal(s, x, y, width * p, height, 0, 0, 1, 1, 0, 0, color_fg);
|
RenderDecal(s, x, y, width * p, height, 0, 0, 1, 1, 0, 0, color_fg);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderController(float frame_x, float frame_y, uint32_t primary_color,
|
static void RenderDukeController(float frame_x, float frame_y, uint32_t primary_color,
|
||||||
uint32_t secondary_color, ControllerState *state)
|
uint32_t secondary_color, ControllerState *state)
|
||||||
{
|
{
|
||||||
// Location within the controller texture of masked button locations,
|
// Location within the controller texture of masked button locations,
|
||||||
|
@ -501,7 +506,7 @@ void RenderController(float frame_x, float frame_y, uint32_t primary_color,
|
||||||
glUseProgram(g_decal_shader->prog);
|
glUseProgram(g_decal_shader->prog);
|
||||||
glBindVertexArray(g_decal_shader->vao);
|
glBindVertexArray(g_decal_shader->vao);
|
||||||
glActiveTexture(GL_TEXTURE0);
|
glActiveTexture(GL_TEXTURE0);
|
||||||
glBindTexture(GL_TEXTURE_2D, g_controller_tex);
|
glBindTexture(GL_TEXTURE_2D, g_controller_duke_tex);
|
||||||
|
|
||||||
// Add a 5 pixel space around the controller so we can wiggle the controller
|
// Add a 5 pixel space around the controller so we can wiggle the controller
|
||||||
// around to visualize rumble in action
|
// around to visualize rumble in action
|
||||||
|
@ -630,13 +635,191 @@ void RenderController(float frame_x, float frame_y, uint32_t primary_color,
|
||||||
glUseProgram(0);
|
glUseProgram(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void RenderControllerS(float frame_x, float frame_y, uint32_t primary_color,
|
||||||
|
uint32_t secondary_color, ControllerState *state)
|
||||||
|
{
|
||||||
|
// Location within the controller texture of masked button locations,
|
||||||
|
// relative to the origin of the controller
|
||||||
|
const struct rect jewel = { 194, 213, 84, 84 };
|
||||||
|
const struct rect lstick_ctr = { 103, 254, 0, 0 };
|
||||||
|
const struct rect rstick_ctr = { 295, 176, 0, 0 };
|
||||||
|
const struct rect buttons[12] = {
|
||||||
|
{ 347, 200, 34, 34 }, // A
|
||||||
|
{ 381, 235, 34, 34 }, // B
|
||||||
|
{ 313, 235, 34, 34 }, // X
|
||||||
|
{ 347, 270, 34, 34 }, // Y
|
||||||
|
{ 123, 165, 31, 26 }, // D-Left
|
||||||
|
{ 150, 187, 26, 31 }, // D-Up
|
||||||
|
{ 173, 165, 31, 26 }, // D-Right
|
||||||
|
{ 150, 135, 26, 31 }, // D-Down
|
||||||
|
{ 45, 195, 20, 24 }, // Back
|
||||||
|
{ 70, 163, 26, 26 }, // Start
|
||||||
|
{ 352, 145, 30, 30 }, // White
|
||||||
|
{ 388, 172, 30, 30 }, // Black
|
||||||
|
};
|
||||||
|
|
||||||
|
uint8_t alpha = 0;
|
||||||
|
uint32_t now = SDL_GetTicks();
|
||||||
|
float t;
|
||||||
|
|
||||||
|
glUseProgram(g_decal_shader->prog);
|
||||||
|
glBindVertexArray(g_decal_shader->vao);
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, g_controller_s_tex);
|
||||||
|
|
||||||
|
// Add a 5 pixel space around the controller so we can wiggle the controller
|
||||||
|
// around to visualize rumble in action
|
||||||
|
frame_x += 5;
|
||||||
|
frame_y += 5;
|
||||||
|
float original_frame_x = frame_x;
|
||||||
|
float original_frame_y = frame_y;
|
||||||
|
|
||||||
|
// Floating point versions that will get scaled
|
||||||
|
float rumble_l = 0;
|
||||||
|
float rumble_r = 0;
|
||||||
|
|
||||||
|
glBlendEquation(GL_FUNC_ADD);
|
||||||
|
glBlendFunc(GL_ONE, GL_ZERO);
|
||||||
|
|
||||||
|
uint32_t jewel_color = secondary_color;
|
||||||
|
|
||||||
|
// Check to see if the guide button is pressed
|
||||||
|
const uint32_t animate_guide_button_duration = 2000;
|
||||||
|
if (state->buttons & CONTROLLER_BUTTON_GUIDE) {
|
||||||
|
state->animate_guide_button_end =
|
||||||
|
now + animate_guide_button_duration;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (now < state->animate_guide_button_end) {
|
||||||
|
t = 1.0f - (float)(state->animate_guide_button_end - now) /
|
||||||
|
(float)animate_guide_button_duration;
|
||||||
|
float sin_wav = (1 - sin(M_PI * t / 2.0f));
|
||||||
|
|
||||||
|
// Animate guide button by highlighting logo jewel and fading out over
|
||||||
|
// time
|
||||||
|
alpha = sin_wav * 255.0f;
|
||||||
|
jewel_color = primary_color + alpha;
|
||||||
|
|
||||||
|
// Add a little extra flare: wiggle the frame around while we rumble
|
||||||
|
frame_x += ((float)(rand() % 5) - 2.5) * (1 - t);
|
||||||
|
frame_y += ((float)(rand() % 5) - 2.5) * (1 - t);
|
||||||
|
rumble_l = rumble_r = sin_wav;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Render controller texture
|
||||||
|
RenderDecal(g_decal_shader, frame_x + 0, frame_y + 0,
|
||||||
|
tex_items[obj_controller].w, tex_items[obj_controller].h,
|
||||||
|
tex_items[obj_controller].x, tex_items[obj_controller].y,
|
||||||
|
tex_items[obj_controller].w, tex_items[obj_controller].h,
|
||||||
|
primary_color, secondary_color, 0);
|
||||||
|
|
||||||
|
glBlendFunc(GL_ONE_MINUS_DST_ALPHA,
|
||||||
|
GL_ONE); // Blend with controller cutouts
|
||||||
|
RenderDecal(g_decal_shader, frame_x + jewel.x, frame_y + jewel.y, jewel.w,
|
||||||
|
jewel.h, 0, 0, 1, 1, 0, 0, jewel_color);
|
||||||
|
|
||||||
|
// The controller has alpha cutouts where the buttons are. Draw a surface
|
||||||
|
// behind the buttons if they are activated
|
||||||
|
for (int i = 0; i < 12; i++) {
|
||||||
|
if (state->buttons & (1 << i)) {
|
||||||
|
RenderDecal(g_decal_shader, frame_x + buttons[i].x,
|
||||||
|
frame_y + buttons[i].y, buttons[i].w, buttons[i].h, 0,
|
||||||
|
0, 1, 1, 0, 0, primary_color + 0xff);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // Blend with controller
|
||||||
|
|
||||||
|
// Render left thumbstick
|
||||||
|
float w = tex_items[obj_lstick].w;
|
||||||
|
float h = tex_items[obj_lstick].h;
|
||||||
|
float c_x = frame_x + lstick_ctr.x;
|
||||||
|
float c_y = frame_y + lstick_ctr.y;
|
||||||
|
float lstick_x = (float)state->axis[CONTROLLER_AXIS_LSTICK_X] / 32768.0;
|
||||||
|
float lstick_y = (float)state->axis[CONTROLLER_AXIS_LSTICK_Y] / 32768.0;
|
||||||
|
RenderDecal(
|
||||||
|
g_decal_shader, (int)(c_x - w / 2.0f + 10.0f * lstick_x),
|
||||||
|
(int)(c_y - h / 2.0f + 10.0f * lstick_y), w, h, tex_items[obj_lstick].x,
|
||||||
|
tex_items[obj_lstick].y, w, h,
|
||||||
|
(state->buttons & CONTROLLER_BUTTON_LSTICK) ? secondary_color :
|
||||||
|
primary_color,
|
||||||
|
(state->buttons & CONTROLLER_BUTTON_LSTICK) ? primary_color :
|
||||||
|
secondary_color,
|
||||||
|
0);
|
||||||
|
|
||||||
|
// Render right thumbstick
|
||||||
|
w = tex_items[obj_rstick].w;
|
||||||
|
h = tex_items[obj_rstick].h;
|
||||||
|
c_x = frame_x + rstick_ctr.x;
|
||||||
|
c_y = frame_y + rstick_ctr.y;
|
||||||
|
float rstick_x = (float)state->axis[CONTROLLER_AXIS_RSTICK_X] / 32768.0;
|
||||||
|
float rstick_y = (float)state->axis[CONTROLLER_AXIS_RSTICK_Y] / 32768.0;
|
||||||
|
RenderDecal(
|
||||||
|
g_decal_shader, (int)(c_x - w / 2.0f + 10.0f * rstick_x),
|
||||||
|
(int)(c_y - h / 2.0f + 10.0f * rstick_y), w, h, tex_items[obj_rstick].x,
|
||||||
|
tex_items[obj_rstick].y, w, h,
|
||||||
|
(state->buttons & CONTROLLER_BUTTON_RSTICK) ? secondary_color :
|
||||||
|
primary_color,
|
||||||
|
(state->buttons & CONTROLLER_BUTTON_RSTICK) ? primary_color :
|
||||||
|
secondary_color,
|
||||||
|
0);
|
||||||
|
|
||||||
|
glBlendFunc(GL_ONE,
|
||||||
|
GL_ZERO); // Don't blend, just overwrite values in buffer
|
||||||
|
|
||||||
|
// Render trigger bars
|
||||||
|
float ltrig = state->axis[CONTROLLER_AXIS_LTRIG] / 32767.0;
|
||||||
|
float rtrig = state->axis[CONTROLLER_AXIS_RTRIG] / 32767.0;
|
||||||
|
const uint32_t animate_trigger_duration = 1000;
|
||||||
|
if ((ltrig > 0) || (rtrig > 0)) {
|
||||||
|
state->animate_trigger_end = now + animate_trigger_duration;
|
||||||
|
rumble_l = fmax(rumble_l, ltrig);
|
||||||
|
rumble_r = fmax(rumble_r, rtrig);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Animate trigger alpha down after a period of inactivity
|
||||||
|
alpha = 0x80;
|
||||||
|
if (state->animate_trigger_end > now) {
|
||||||
|
t = 1.0f - (float)(state->animate_trigger_end - now) /
|
||||||
|
(float)animate_trigger_duration;
|
||||||
|
float sin_wav = (1 - sin(M_PI * t / 2.0f));
|
||||||
|
alpha += fmin(sin_wav * 0x40, 0x80);
|
||||||
|
}
|
||||||
|
|
||||||
|
RenderMeter(g_decal_shader, original_frame_x + 10,
|
||||||
|
original_frame_y + tex_items[obj_controller].h + 20, 150, 5,
|
||||||
|
ltrig, primary_color + alpha, primary_color + 0xff);
|
||||||
|
RenderMeter(g_decal_shader,
|
||||||
|
original_frame_x + tex_items[obj_controller].w - 160,
|
||||||
|
original_frame_y + tex_items[obj_controller].h + 20, 150, 5,
|
||||||
|
rtrig, primary_color + alpha, primary_color + 0xff);
|
||||||
|
|
||||||
|
// Apply rumble updates
|
||||||
|
state->rumble_l = (int)(rumble_l * (float)0xffff);
|
||||||
|
state->rumble_r = (int)(rumble_r * (float)0xffff);
|
||||||
|
|
||||||
|
glBindVertexArray(0);
|
||||||
|
glUseProgram(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderController(float frame_x, float frame_y, uint32_t primary_color,
|
||||||
|
uint32_t secondary_color, ControllerState *state)
|
||||||
|
{
|
||||||
|
if (strcmp(bound_drivers[state->bound], DRIVER_S) == 0)
|
||||||
|
RenderControllerS(frame_x, frame_y, primary_color, secondary_color,
|
||||||
|
state);
|
||||||
|
else if (strcmp(bound_drivers[state->bound], DRIVER_DUKE) == 0)
|
||||||
|
RenderDukeController(frame_x, frame_y, primary_color, secondary_color,
|
||||||
|
state);
|
||||||
|
}
|
||||||
|
|
||||||
void RenderControllerPort(float frame_x, float frame_y, int i,
|
void RenderControllerPort(float frame_x, float frame_y, int i,
|
||||||
uint32_t port_color)
|
uint32_t port_color)
|
||||||
{
|
{
|
||||||
glUseProgram(g_decal_shader->prog);
|
glUseProgram(g_decal_shader->prog);
|
||||||
glBindVertexArray(g_decal_shader->vao);
|
glBindVertexArray(g_decal_shader->vao);
|
||||||
glActiveTexture(GL_TEXTURE0);
|
glActiveTexture(GL_TEXTURE0);
|
||||||
glBindTexture(GL_TEXTURE_2D, g_controller_tex);
|
glBindTexture(GL_TEXTURE_2D, g_controller_duke_tex);
|
||||||
glBlendFunc(GL_ONE, GL_ZERO);
|
glBlendFunc(GL_ONE, GL_ZERO);
|
||||||
|
|
||||||
// Render port socket
|
// Render port socket
|
||||||
|
|
|
@ -159,6 +159,49 @@ void MainMenuInputView::Draw()
|
||||||
ImGui::PopStyleVar(); // ItemSpacing
|
ImGui::PopStyleVar(); // ItemSpacing
|
||||||
ImGui::Columns(1);
|
ImGui::Columns(1);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Render device driver combo
|
||||||
|
//
|
||||||
|
|
||||||
|
// List available device drivers
|
||||||
|
const char *driver = bound_drivers[active];
|
||||||
|
|
||||||
|
if (strcmp(driver, DRIVER_DUKE) == 0)
|
||||||
|
driver = DRIVER_DUKE_DISPLAY_NAME;
|
||||||
|
else if (strcmp(driver, DRIVER_S) == 0)
|
||||||
|
driver = DRIVER_S_DISPLAY_NAME;
|
||||||
|
|
||||||
|
ImGui::SetNextItemWidth(-FLT_MIN);
|
||||||
|
if (ImGui::BeginCombo("###InputDrivers", driver,
|
||||||
|
ImGuiComboFlags_NoArrowButton)) {
|
||||||
|
const char *available_drivers[] = { DRIVER_DUKE, DRIVER_S };
|
||||||
|
const char *driver_display_names[] = {
|
||||||
|
DRIVER_DUKE_DISPLAY_NAME,
|
||||||
|
DRIVER_S_DISPLAY_NAME
|
||||||
|
};
|
||||||
|
bool is_selected = false;
|
||||||
|
int num_drivers = sizeof(driver_display_names) / sizeof(driver_display_names[0]);
|
||||||
|
for (int i = 0; i < num_drivers; i++) {
|
||||||
|
const char *iter = driver_display_names[i];
|
||||||
|
is_selected = strcmp(driver, iter) == 0;
|
||||||
|
ImGui::PushID(iter);
|
||||||
|
if (ImGui::Selectable(iter, is_selected)) {
|
||||||
|
for (int j = 0; j < num_drivers; j++) {
|
||||||
|
if (iter == driver_display_names[j])
|
||||||
|
bound_drivers[active] = available_drivers[j];
|
||||||
|
}
|
||||||
|
xemu_input_bind(active, bound_controllers[active], 1);
|
||||||
|
}
|
||||||
|
if (is_selected) {
|
||||||
|
ImGui::SetItemDefaultFocus();
|
||||||
|
}
|
||||||
|
ImGui::PopID();
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::EndCombo();
|
||||||
|
}
|
||||||
|
DrawComboChevron();
|
||||||
|
|
||||||
//
|
//
|
||||||
// Render input device combo
|
// Render input device combo
|
||||||
//
|
//
|
||||||
|
|
Loading…
Reference in New Issue