Compare commits
6 Commits
f7f234c408
...
e3b1122454
Author | SHA1 | Date |
---|---|---|
PlainOldPants | e3b1122454 | |
feos | 0c45a8a8ab | |
ekeeke | dbdb18eb50 | |
ekeeke | dd619513a4 | |
ekeeke | 351d052e84 | |
PlainOldPants | 22526f587c |
|
@ -58,9 +58,10 @@ Genesis Plus GX 1.7.5 (xx/xx/xxxx) (Eke-Eke)
|
|||
* fixed byte access to font data registers
|
||||
* fixed memory mode register bits masking when read from MAIN-CPU and SUB-CPU (verified on real hardware, cf. Krikzz's mcd-verificator)
|
||||
* fixed pending level 1 interrupts when GFX interrupt is disabled (fixes random freezes when exiting "Batman Returns" option menu)
|
||||
* fixed CDD seek command again (Final Fight CD freeze with model 2 BIOS)
|
||||
* fixed CDD seek command again (fixes Final Fight CD freeze with model 2 BIOS)
|
||||
* fixed CDD status reported during seek/access time (fixes sound effect synchronization issue in Bari Arm)
|
||||
* fixed CDD position reset when disc is stopped (fixes random freezes in Spiderman vs Kingpin when switching between audio tracks)
|
||||
* fixed CDD seeking start delay (fixes Radical Rex incorrect PRG-RAM & Word-RAM initialization, causing missing sprites during intro) */
|
||||
* fixed word access to CDD control register (fixes spurious audio track playback on startup with Mode 1 patched games using MSU-MD driver)
|
||||
* fixed CD communication registers state on peripheral reset (fixes SUB-CPU side initialization in MSU-MD sample demo and some Mode 1 patched games using MSU-MD driver)
|
||||
* fixed 32x32 pixels stamp index masking during GFX operation (fixes graphics rotation/scaling effects in "Chuck Rock II - Son of Chuck")
|
||||
|
|
Binary file not shown.
Binary file not shown.
Before Width: | Height: | Size: 3.8 MiB After Width: | Height: | Size: 3.8 MiB |
Binary file not shown.
Before Width: | Height: | Size: 4.0 MiB After Width: | Height: | Size: 4.0 MiB |
|
@ -2,7 +2,7 @@
|
|||
* Genesis Plus
|
||||
* Mega Drive cartridge hardware support
|
||||
*
|
||||
* Copyright (C) 2007-2023 Eke-Eke (Genesis Plus GX)
|
||||
* Copyright (C) 2007-2024 Eke-Eke (Genesis Plus GX)
|
||||
*
|
||||
* Many cartridge protections were initially documented by Haze
|
||||
* (http://haze.mameworld.info/)
|
||||
|
@ -465,7 +465,10 @@ void md_cart_init(void)
|
|||
memset(&cart.hw, 0, sizeof(cart.hw));
|
||||
|
||||
/* initialize default $200000-$20ffff mapping (for games using SRAM & ROM bankswitching) */
|
||||
cart.hw.regs[0] = (0x200000 & cart.mask) >> 16;
|
||||
if (m68k.memory_map[0x20].base == sram.sram)
|
||||
{
|
||||
cart.hw.regs[0] = (0x200000 & cart.mask) >> 16;
|
||||
}
|
||||
|
||||
/* search for game into database */
|
||||
for (i=0; i<(sizeof(rom_database)/sizeof(md_entry_t)); i++)
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* Genesis Plus
|
||||
* Mega Drive cartridge hardware support
|
||||
*
|
||||
* Copyright (C) 2007-2023 Eke-Eke (Genesis Plus GX)
|
||||
* Copyright (C) 2007-2024 Eke-Eke (Genesis Plus GX)
|
||||
*
|
||||
* Most cartridge protections were initially documented by Haze
|
||||
* (http://haze.mameworld.info/)
|
||||
|
|
196
core/cd_hw/cdd.c
196
core/cd_hw/cdd.c
|
@ -1893,6 +1893,79 @@ void cdd_update(void)
|
|||
/* udpate current track index */
|
||||
cdd.index = index;
|
||||
}
|
||||
|
||||
/* seeking should start with at least one interrupt delay (fixes Radical Rex incorrect PRG-RAM & Word-RAM initialization, causing missing sprites during intro) */
|
||||
if (scd.regs[0x38>>1].byte.h == CD_SEEK)
|
||||
{
|
||||
/* reset track index */
|
||||
int index = 0;
|
||||
|
||||
/* new LBA position */
|
||||
int lba = ((scd.regs[0x44>>1].byte.h * 10 + scd.regs[0x44>>1].byte.l) * 60 +
|
||||
(scd.regs[0x46>>1].byte.h * 10 + scd.regs[0x46>>1].byte.l)) * 75 +
|
||||
(scd.regs[0x48>>1].byte.h * 10 + scd.regs[0x48>>1].byte.l) - 150;
|
||||
|
||||
/* CD drive latency */
|
||||
if (!cdd.latency)
|
||||
{
|
||||
/* Fixes a few games hanging because they expect data to be read with some delay */
|
||||
/* Wolf Team games (Annet Futatabi, Aisle Lord, Cobra Command, Earnest Evans, Road Avenger & Time Gal) need at least 11 interrupts delay */
|
||||
/* Space Adventure Cobra (2nd morgue scene) needs at least 13 interrupts delay (incl. seek time, so 11 is OK) */
|
||||
/* By default, at least two interrupts latency is required by current emulation model (BIOS hangs otherwise) */
|
||||
cdd.latency = 2 + 9*config.cd_latency;
|
||||
}
|
||||
|
||||
/* CD drive seek time */
|
||||
/* max. seek time = 1.5 s = 1.5 x 75 = 112.5 CDD interrupts (rounded to 120) for 270000 sectors max on disc. */
|
||||
/* Note: This is only a rough approximation since, on real hardware, seek time is much likely not linear and */
|
||||
/* latency much larger than above value, but this model works fine for Sonic CD (track 26 playback needs to */
|
||||
/* be enough delayed to start in sync with intro sequence, as compared with real hardware recording). */
|
||||
/* It also works fine for Switch/Panic! intro (at least 30 interrupts are needed while seeking from 00:05:63 */
|
||||
/* to 24:03:19 in Switch or when seeking from 00:05:60 to 24:06:07 in Panic!). */
|
||||
if (lba > cdd.lba)
|
||||
{
|
||||
cdd.latency += (((lba - cdd.lba) * 120 * config.cd_latency) / 270000);
|
||||
}
|
||||
else
|
||||
{
|
||||
cdd.latency += (((cdd.lba - lba) * 120 * config.cd_latency) / 270000);
|
||||
}
|
||||
|
||||
/* update current LBA */
|
||||
cdd.lba = lba;
|
||||
|
||||
/* get track index */
|
||||
while ((cdd.toc.tracks[index].end <= lba) && (index < cdd.toc.last))
|
||||
index++;
|
||||
|
||||
/* audio track ? */
|
||||
if (cdd.toc.tracks[index].type == TYPE_AUDIO)
|
||||
{
|
||||
/* stay within track limits when seeking files */
|
||||
if (lba < cdd.toc.tracks[index].start)
|
||||
{
|
||||
lba = cdd.toc.tracks[index].start;
|
||||
}
|
||||
|
||||
/* seek to current track sector */
|
||||
cdd_seek_audio(index, lba);
|
||||
}
|
||||
|
||||
/* update current track index */
|
||||
cdd.index = index;
|
||||
|
||||
/* seek to current subcode position */
|
||||
if (cdd.toc.sub)
|
||||
{
|
||||
cdStreamSeek(cdd.toc.sub, lba * 96, SEEK_SET);
|
||||
}
|
||||
|
||||
/* no audio track playing (yet) */
|
||||
scd.regs[0x36>>1].byte.h = 0x01;
|
||||
|
||||
/* update CDD status to either PLAY or PAUSE depending on host command (will be reported to host once seeking has ended) */
|
||||
cdd.status = scd.regs[0x42>>1].byte.h & 0x05;
|
||||
}
|
||||
}
|
||||
|
||||
void cdd_process(void)
|
||||
|
@ -2069,73 +2142,7 @@ void cdd_process(void)
|
|||
|
||||
case 0x03: /* Play */
|
||||
{
|
||||
/* reset track index */
|
||||
int index = 0;
|
||||
|
||||
/* new LBA position */
|
||||
int lba = ((scd.regs[0x44>>1].byte.h * 10 + scd.regs[0x44>>1].byte.l) * 60 +
|
||||
(scd.regs[0x46>>1].byte.h * 10 + scd.regs[0x46>>1].byte.l)) * 75 +
|
||||
(scd.regs[0x48>>1].byte.h * 10 + scd.regs[0x48>>1].byte.l) - 150;
|
||||
|
||||
/* CD drive latency */
|
||||
if (!cdd.latency)
|
||||
{
|
||||
/* Fixes a few games hanging because they expect data to be read with some delay */
|
||||
/* Wolf Team games (Annet Futatabi, Aisle Lord, Cobra Command, Earnest Evans, Road Avenger & Time Gal) need at least 11 interrupts delay */
|
||||
/* Space Adventure Cobra (2nd morgue scene) needs at least 13 interrupts delay (incl. seek time, so 11 is OK) */
|
||||
/* By default, at least two interrupts latency is required by current emulation model (BIOS hangs otherwise) */
|
||||
cdd.latency = 2 + 9*config.cd_latency;
|
||||
}
|
||||
|
||||
/* CD drive seek time */
|
||||
/* max. seek time = 1.5 s = 1.5 x 75 = 112.5 CDD interrupts (rounded to 120) for 270000 sectors max on disc. */
|
||||
/* Note: This is only a rough approximation since, on real hardware, seek time is much likely not linear and */
|
||||
/* latency much larger than above value, but this model works fine for Sonic CD (track 26 playback needs to */
|
||||
/* be enough delayed to start in sync with intro sequence, as compared with real hardware recording). */
|
||||
if (lba > cdd.lba)
|
||||
{
|
||||
cdd.latency += (((lba - cdd.lba) * 120 * config.cd_latency) / 270000);
|
||||
}
|
||||
else
|
||||
{
|
||||
cdd.latency += (((cdd.lba - lba) * 120 * config.cd_latency) / 270000);
|
||||
}
|
||||
|
||||
/* update current LBA */
|
||||
cdd.lba = lba;
|
||||
|
||||
/* get track index */
|
||||
while ((cdd.toc.tracks[index].end <= lba) && (index < cdd.toc.last)) index++;
|
||||
|
||||
/* audio track ? */
|
||||
if (cdd.toc.tracks[index].type == TYPE_AUDIO)
|
||||
{
|
||||
/* stay within track limits when seeking files */
|
||||
if (lba < cdd.toc.tracks[index].start)
|
||||
{
|
||||
lba = cdd.toc.tracks[index].start;
|
||||
}
|
||||
|
||||
/* seek to current track sector */
|
||||
cdd_seek_audio(index, lba);
|
||||
}
|
||||
|
||||
/* update current track index */
|
||||
cdd.index = index;
|
||||
|
||||
/* seek to current subcode position */
|
||||
if (cdd.toc.sub)
|
||||
{
|
||||
cdStreamSeek(cdd.toc.sub, lba * 96, SEEK_SET);
|
||||
}
|
||||
|
||||
/* no audio track playing (yet) */
|
||||
scd.regs[0x36>>1].byte.h = 0x01;
|
||||
|
||||
/* update status (reported to host once seeking has ended) */
|
||||
cdd.status = CD_PLAY;
|
||||
|
||||
/* RS0 should indicates seeking until drive is ready (fixes audio delay in Bari Arm) */
|
||||
/* RS0 should indicate seeking until drive is ready (fixes audio delay in Bari Arm) */
|
||||
/* RS1=0xf to invalidate track infos in RS2-RS8 until drive is ready (fixes Snatcher Act 2 start cutscene) */
|
||||
scd.regs[0x38>>1].w = (CD_SEEK << 8) | 0x0f;
|
||||
scd.regs[0x3a>>1].w = 0x0000;
|
||||
|
@ -2147,61 +2154,6 @@ void cdd_process(void)
|
|||
|
||||
case 0x04: /* Seek */
|
||||
{
|
||||
/* reset track index */
|
||||
int index = 0;
|
||||
|
||||
/* new LBA position */
|
||||
int lba = ((scd.regs[0x44>>1].byte.h * 10 + scd.regs[0x44>>1].byte.l) * 60 +
|
||||
(scd.regs[0x46>>1].byte.h * 10 + scd.regs[0x46>>1].byte.l)) * 75 +
|
||||
(scd.regs[0x48>>1].byte.h * 10 + scd.regs[0x48>>1].byte.l) - 150;
|
||||
|
||||
/* CD drive seek time */
|
||||
/* We are using similar linear model as above, although still not exactly accurate, */
|
||||
/* it works fine for Switch/Panic! intro (Switch needs at least 30 interrupts while */
|
||||
/* seeking from 00:05:63 to 24:03:19, Panic! when seeking from 00:05:60 to 24:06:07) */
|
||||
if (lba > cdd.lba)
|
||||
{
|
||||
cdd.latency = ((lba - cdd.lba) * 120 * config.cd_latency) / 270000;
|
||||
}
|
||||
else
|
||||
{
|
||||
cdd.latency = ((cdd.lba - lba) * 120 * config.cd_latency) / 270000;
|
||||
}
|
||||
|
||||
/* update current LBA */
|
||||
cdd.lba = lba;
|
||||
|
||||
/* get current track index */
|
||||
while ((cdd.toc.tracks[index].end <= lba) && (index < cdd.toc.last)) index++;
|
||||
|
||||
/* audio track ? */
|
||||
if (cdd.toc.tracks[index].type == TYPE_AUDIO)
|
||||
{
|
||||
/* stay within track limits when seeking files */
|
||||
if (lba < cdd.toc.tracks[index].start)
|
||||
{
|
||||
lba = cdd.toc.tracks[index].start;
|
||||
}
|
||||
|
||||
/* seek to current track sector */
|
||||
cdd_seek_audio(index, lba);
|
||||
}
|
||||
|
||||
/* update current track index */
|
||||
cdd.index = index;
|
||||
|
||||
/* seek to current subcode position */
|
||||
if (cdd.toc.sub)
|
||||
{
|
||||
cdStreamSeek(cdd.toc.sub, lba * 96, SEEK_SET);
|
||||
}
|
||||
|
||||
/* no audio track playing */
|
||||
scd.regs[0x36>>1].byte.h = 0x01;
|
||||
|
||||
/* update status (reported to host once seeking has ended) */
|
||||
cdd.status = CD_PAUSE;
|
||||
|
||||
/* RS1=0xf to invalidate track infos in RS2-RS8 while seeking (fixes Final Fight CD intro when seek time is emulated) */
|
||||
scd.regs[0x38>>1].w = (CD_SEEK << 8) | 0x0f;
|
||||
scd.regs[0x3a>>1].w = 0x0000;
|
||||
|
|
|
@ -292,7 +292,7 @@ void m68k_run(unsigned int cycles)
|
|||
|
||||
#ifdef HOOK_CPU
|
||||
/* Trigger execution hook */
|
||||
if (cpu_hook)
|
||||
if (UNLIKELY(cpu_hook))
|
||||
cpu_hook(HOOK_M68K_E, 0, REG_PC, 0);
|
||||
#endif
|
||||
|
||||
|
|
|
@ -859,7 +859,7 @@ INLINE uint m68ki_read_8(uint address)
|
|||
else val = READ_BYTE(temp->base, (address) & 0xffff);
|
||||
|
||||
#ifdef HOOK_CPU
|
||||
if (cpu_hook)
|
||||
if (UNLIKELY(cpu_hook))
|
||||
cpu_hook(HOOK_M68K_R, 1, address, val);
|
||||
#endif
|
||||
|
||||
|
@ -879,7 +879,7 @@ INLINE uint m68ki_read_16(uint address)
|
|||
else val = *(uint16 *)(temp->base + ((address) & 0xffff));
|
||||
|
||||
#ifdef HOOK_CPU
|
||||
if (cpu_hook)
|
||||
if (UNLIKELY(cpu_hook))
|
||||
cpu_hook(HOOK_M68K_R, 2, address, val);
|
||||
#endif
|
||||
|
||||
|
@ -899,7 +899,7 @@ INLINE uint m68ki_read_32(uint address)
|
|||
else val = m68k_read_immediate_32(address);
|
||||
|
||||
#ifdef HOOK_CPU
|
||||
if (cpu_hook)
|
||||
if (UNLIKELY(cpu_hook))
|
||||
cpu_hook(HOOK_M68K_R, 4, address, val);
|
||||
#endif
|
||||
|
||||
|
@ -913,7 +913,7 @@ INLINE void m68ki_write_8(uint address, uint value)
|
|||
m68ki_set_fc(FLAG_S | FUNCTION_CODE_USER_DATA) /* auto-disable (see m68kcpu.h) */
|
||||
|
||||
#ifdef HOOK_CPU
|
||||
if (cpu_hook)
|
||||
if (UNLIKELY(cpu_hook))
|
||||
cpu_hook(HOOK_M68K_W, 1, address, value);
|
||||
#endif
|
||||
|
||||
|
@ -930,7 +930,7 @@ INLINE void m68ki_write_16(uint address, uint value)
|
|||
m68ki_check_address_error(address, MODE_WRITE, FLAG_S | FUNCTION_CODE_USER_DATA); /* auto-disable (see m68kcpu.h) */
|
||||
|
||||
#ifdef HOOK_CPU
|
||||
if (cpu_hook)
|
||||
if (UNLIKELY(cpu_hook))
|
||||
cpu_hook(HOOK_M68K_W, 2, address, value);
|
||||
#endif
|
||||
|
||||
|
@ -947,7 +947,7 @@ INLINE void m68ki_write_32(uint address, uint value)
|
|||
m68ki_check_address_error(address, MODE_WRITE, FLAG_S | FUNCTION_CODE_USER_DATA) /* auto-disable (see m68kcpu.h) */
|
||||
|
||||
#ifdef HOOK_CPU
|
||||
if (cpu_hook)
|
||||
if (UNLIKELY(cpu_hook))
|
||||
cpu_hook(HOOK_M68K_W, 4, address, value);
|
||||
#endif
|
||||
|
||||
|
|
|
@ -53,6 +53,15 @@
|
|||
#define ALIGNED_(x) __attribute__ ((aligned(x)))
|
||||
#endif
|
||||
|
||||
/* Provide the compiler with branch prediction information */
|
||||
#if defined(__GNUC__)
|
||||
#define LIKELY(x) __builtin_expect(!!(x), 1)
|
||||
#define UNLIKELY(x) __builtin_expect(!!(x), 0)
|
||||
#else
|
||||
#define LIKELY(x) x
|
||||
#define UNLIKELY(x) x
|
||||
#endif
|
||||
|
||||
/* Default CD image file access (read-only) functions */
|
||||
/* If you need to override default stdio.h functions with custom filesystem API,
|
||||
redefine following macros in platform specific include file (osd.h) or Makefile
|
||||
|
|
|
@ -2162,7 +2162,7 @@ static void vdp_bus_w(unsigned int data)
|
|||
}
|
||||
|
||||
#ifdef HOOK_CPU
|
||||
if (cpu_hook)
|
||||
if (UNLIKELY(cpu_hook))
|
||||
cpu_hook(HOOK_VRAM_W, 2, addr, data);
|
||||
#endif
|
||||
|
||||
|
@ -2211,7 +2211,7 @@ static void vdp_bus_w(unsigned int data)
|
|||
}
|
||||
|
||||
#ifdef HOOK_CPU
|
||||
if (cpu_hook)
|
||||
if (UNLIKELY(cpu_hook))
|
||||
cpu_hook(HOOK_CRAM_W, 2, addr, data);
|
||||
#endif
|
||||
|
||||
|
@ -2237,7 +2237,7 @@ static void vdp_bus_w(unsigned int data)
|
|||
}
|
||||
|
||||
#ifdef HOOK_CPU
|
||||
if (cpu_hook)
|
||||
if (UNLIKELY(cpu_hook))
|
||||
cpu_hook(HOOK_VSRAM_W, 2, addr, data);
|
||||
#endif
|
||||
|
||||
|
@ -2448,7 +2448,7 @@ static unsigned int vdp_68k_data_r_m5(void)
|
|||
data = *(uint16 *)&vram[addr & 0xFFFE];
|
||||
|
||||
#ifdef HOOK_CPU
|
||||
if (cpu_hook)
|
||||
if (UNLIKELY(cpu_hook))
|
||||
cpu_hook(HOOK_VRAM_R, 2, addr, data);
|
||||
#endif
|
||||
|
||||
|
@ -2477,7 +2477,7 @@ static unsigned int vdp_68k_data_r_m5(void)
|
|||
data |= (fifo[fifo_idx] & ~0x7FF);
|
||||
|
||||
#ifdef HOOK_CPU
|
||||
if (cpu_hook)
|
||||
if (UNLIKELY(cpu_hook))
|
||||
cpu_hook(HOOK_VSRAM_R, 2, addr, data);
|
||||
#endif
|
||||
|
||||
|
@ -2499,7 +2499,7 @@ static unsigned int vdp_68k_data_r_m5(void)
|
|||
data |= (fifo[fifo_idx] & ~0xEEE);
|
||||
|
||||
#ifdef HOOK_CPU
|
||||
if (cpu_hook)
|
||||
if (UNLIKELY(cpu_hook))
|
||||
cpu_hook(HOOK_CRAM_R, 2, addr, data);
|
||||
#endif
|
||||
|
||||
|
@ -2518,7 +2518,7 @@ static unsigned int vdp_68k_data_r_m5(void)
|
|||
data |= (fifo[fifo_idx] & ~0xFF);
|
||||
|
||||
#ifdef HOOK_CPU
|
||||
if (cpu_hook)
|
||||
if (UNLIKELY(cpu_hook))
|
||||
cpu_hook(HOOK_VRAM_R, 2, addr, data);
|
||||
#endif
|
||||
|
||||
|
|
|
@ -48,6 +48,7 @@
|
|||
#ifdef HW_RVL
|
||||
#include <ogc/usbmouse.h>
|
||||
#include "wiidrc.h"
|
||||
#include "retrousb.h"
|
||||
#endif
|
||||
|
||||
#include <ogc/lwp_threads.h>
|
||||
|
@ -124,6 +125,7 @@
|
|||
#include "ctrl_nunchuk_png.h"
|
||||
#include "ctrl_wiimote_png.h"
|
||||
#include "ctrl_wiiu_png.h"
|
||||
#include "ctrl_retrousb_png.h"
|
||||
#endif
|
||||
|
||||
/* Generic images */
|
||||
|
@ -2471,7 +2473,7 @@ static void ctrlmenu(void)
|
|||
|
||||
/* Player Configuration device items */
|
||||
#ifdef HW_RVL
|
||||
gui_item items_device[6] =
|
||||
gui_item items_device[7] =
|
||||
{
|
||||
{NULL,ctrl_option_off_png ,"Input\nDevice","Select Input Controller",534,244,24,24},
|
||||
{NULL,ctrl_gamecube_png ,"Input\nDevice","Select Input Controller",530,246,36,24},
|
||||
|
@ -2479,6 +2481,7 @@ static void ctrlmenu(void)
|
|||
{NULL,ctrl_nunchuk_png ,"Input\nDevice","Select Input Controller",532,242,32,32},
|
||||
{NULL,ctrl_classic_png ,"Input\nDevice","Select Input Controller",526,242,40,32},
|
||||
{NULL,ctrl_wiiu_png ,"Input\nDevice","Select Input Controller",526,246,40,24},
|
||||
{NULL,ctrl_retrousb_png ,"Input\nDevice","Select Input Controller",526,246,40,24},
|
||||
};
|
||||
#else
|
||||
gui_item items_device[2] =
|
||||
|
@ -2518,6 +2521,7 @@ static void ctrlmenu(void)
|
|||
{
|
||||
items_device[5].texture = gxTextureOpenPNG(items_device[5].data,0);
|
||||
}
|
||||
items_device[6].texture = gxTextureOpenPNG(items_device[6].data, 0);
|
||||
#endif
|
||||
|
||||
/* restore current menu elements */
|
||||
|
@ -3060,11 +3064,21 @@ static void ctrlmenu(void)
|
|||
/* support for only one gamepad */
|
||||
if (!WiiDRC_Inited() || !WiiDRC_Connected() || (config.input[player].port >= 1))
|
||||
{
|
||||
/* no input controller left */
|
||||
config.input[player].device = -1;
|
||||
config.input[player].port = player%4;
|
||||
/* test RetroUSB */
|
||||
config.input[player].device = 5;
|
||||
config.input[player].port = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (config.input[player].device == 5)
|
||||
{
|
||||
if (!RetroUSB_OK() || config.input[player].port >= 1)
|
||||
{
|
||||
/* no input controller left */
|
||||
config.input[player].device = -1;
|
||||
config.input[player].port = player % 4;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* update menu items */
|
||||
|
@ -3230,6 +3244,7 @@ static void ctrlmenu(void)
|
|||
{
|
||||
gxTextureClose(&items_device[5].texture);
|
||||
}
|
||||
gxTextureClose(&items_device[6].texture);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
273
gx/gx_input.c
273
gx/gx_input.c
|
@ -46,6 +46,7 @@
|
|||
#ifdef HW_RVL
|
||||
#include <ogc/usbmouse.h>
|
||||
#include "wiidrc.h"
|
||||
#include "retrousb.h"
|
||||
#endif
|
||||
|
||||
/* Analog sticks sensitivity */
|
||||
|
@ -79,12 +80,13 @@
|
|||
#define PAD_RIGHT 3
|
||||
|
||||
/* default directions mapping */
|
||||
static u32 wpad_dirmap[4][4] =
|
||||
static u32 wpad_dirmap[5][4] =
|
||||
{
|
||||
{WPAD_BUTTON_RIGHT, WPAD_BUTTON_LEFT, WPAD_BUTTON_UP, WPAD_BUTTON_DOWN}, /* WIIMOTE */
|
||||
{WPAD_BUTTON_UP, WPAD_BUTTON_DOWN, WPAD_BUTTON_LEFT, WPAD_BUTTON_RIGHT}, /* WIIMOTE + NUNCHUK */
|
||||
{WPAD_CLASSIC_BUTTON_UP, WPAD_CLASSIC_BUTTON_DOWN, WPAD_CLASSIC_BUTTON_LEFT, WPAD_CLASSIC_BUTTON_RIGHT}, /* CLASSIC */
|
||||
{WIIDRC_BUTTON_UP, WIIDRC_BUTTON_DOWN, WIIDRC_BUTTON_LEFT, WIIDRC_BUTTON_RIGHT} /* WIIU GAMEPAD */
|
||||
{WIIDRC_BUTTON_UP, WIIDRC_BUTTON_DOWN, WIIDRC_BUTTON_LEFT, WIIDRC_BUTTON_RIGHT}, /* WIIU GAMEPAD */
|
||||
{PAD_BUTTON_UP, PAD_BUTTON_DOWN, PAD_BUTTON_LEFT, PAD_BUTTON_RIGHT}
|
||||
};
|
||||
|
||||
#define WPAD_BUTTONS_HELD (WPAD_BUTTON_UP | WPAD_BUTTON_DOWN | WPAD_BUTTON_LEFT | WPAD_BUTTON_RIGHT | \
|
||||
|
@ -615,6 +617,7 @@ static void wpad_config(u8 exp, int chan, int first_key, int last_key)
|
|||
{
|
||||
char msg[64];
|
||||
u32 p = 255;
|
||||
bool isRetroUSB = false;
|
||||
|
||||
/* Disable background PAD scanning */
|
||||
inputs_disabled = 1;
|
||||
|
@ -624,12 +627,14 @@ static void wpad_config(u8 exp, int chan, int first_key, int last_key)
|
|||
{
|
||||
WPAD_Probe(chan, &p);
|
||||
}
|
||||
else
|
||||
else if (WiiDRC_Inited() && WiiDRC_Connected())
|
||||
{
|
||||
if (WiiDRC_Inited() && WiiDRC_Connected())
|
||||
{
|
||||
p = exp;
|
||||
}
|
||||
}
|
||||
else if (RetroUSB_OK())
|
||||
{
|
||||
p = exp;
|
||||
isRetroUSB = true;
|
||||
}
|
||||
|
||||
/* Device not detected */
|
||||
|
@ -638,7 +643,7 @@ static void wpad_config(u8 exp, int chan, int first_key, int last_key)
|
|||
if (exp == WPAD_EXP_NONE) sprintf(msg, "WIIMOTE #%d is not connected !", chan+1);
|
||||
else if (exp == WPAD_EXP_NUNCHUK) sprintf(msg, "NUNCHUK #%d is not connected !", chan+1);
|
||||
else if (exp == WPAD_EXP_CLASSIC) sprintf(msg, "CLASSIC #%d is not connected !", chan+1);
|
||||
else sprintf(msg, "WIIU GAMEPAD is not connected !");
|
||||
else sprintf(msg, "WIIU GAMEPAD or RETROUSB is not connected !");
|
||||
GUI_WaitPrompt("Error",msg);
|
||||
|
||||
/* re-enable background PAD scanning and exit */
|
||||
|
@ -661,6 +666,14 @@ static void wpad_config(u8 exp, int chan, int first_key, int last_key)
|
|||
WPAD_ScanPads();
|
||||
}
|
||||
}
|
||||
else if (isRetroUSB)
|
||||
{
|
||||
while (RetroUSB_ButtonsHeld())
|
||||
{
|
||||
VIDEO_WaitVSync();
|
||||
RetroUSB_ScanPads();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (WiiDRC_ButtonsHeld())
|
||||
|
@ -672,7 +685,7 @@ static void wpad_config(u8 exp, int chan, int first_key, int last_key)
|
|||
|
||||
/* configurable button */
|
||||
sprintf(msg,"Press key for %s\n(HOME to return)",keyname[first_key]);
|
||||
GUI_MsgBoxUpdate(0,msg);
|
||||
GUI_MsgBoxUpdate(0, msg);
|
||||
|
||||
/* wait for user input */
|
||||
p = 0;
|
||||
|
@ -684,6 +697,11 @@ static void wpad_config(u8 exp, int chan, int first_key, int last_key)
|
|||
WPAD_ScanPads();
|
||||
p = WPAD_ButtonsDown(chan);
|
||||
}
|
||||
else if (isRetroUSB)
|
||||
{
|
||||
RetroUSB_ScanPads();
|
||||
p = RetroUSB_ButtonsHeld();
|
||||
}
|
||||
else
|
||||
{
|
||||
WiiDRC_ScanPads();
|
||||
|
@ -742,17 +760,30 @@ static void wpad_config(u8 exp, int chan, int first_key, int last_key)
|
|||
/* WiiU GamePad Controller */
|
||||
default:
|
||||
{
|
||||
if (p & WIIDRC_BUTTON_A) p = WIIDRC_BUTTON_A;
|
||||
else if (p & WIIDRC_BUTTON_B) p = WIIDRC_BUTTON_B;
|
||||
else if (p & WIIDRC_BUTTON_X) p = WIIDRC_BUTTON_X;
|
||||
else if (p & WIIDRC_BUTTON_Y) p = WIIDRC_BUTTON_Y;
|
||||
else if (p & WIIDRC_BUTTON_ZL) p = WIIDRC_BUTTON_ZL;
|
||||
else if (p & WIIDRC_BUTTON_ZR) p = WIIDRC_BUTTON_ZR;
|
||||
else if (p & WIIDRC_BUTTON_PLUS) p = WIIDRC_BUTTON_PLUS;
|
||||
else if (p & WIIDRC_BUTTON_MINUS) p = WIIDRC_BUTTON_MINUS;
|
||||
else if (p & WIIDRC_BUTTON_L) p = WIIDRC_BUTTON_L;
|
||||
else if (p & WIIDRC_BUTTON_R) p = WIIDRC_BUTTON_R;
|
||||
else first_key = MAX_KEYS;
|
||||
if (isRetroUSB) {
|
||||
if (p & PAD_BUTTON_A) p = PAD_BUTTON_A;
|
||||
else if (p & PAD_BUTTON_B) p = PAD_BUTTON_B;
|
||||
else if (p & PAD_BUTTON_X) p = PAD_BUTTON_X;
|
||||
else if (p & PAD_BUTTON_Y) p = PAD_BUTTON_Y;
|
||||
else if (p & PAD_TRIGGER_Z) p = PAD_TRIGGER_Z;
|
||||
else if (p & PAD_BUTTON_START) p = PAD_BUTTON_START;
|
||||
else if (p & PAD_TRIGGER_L) p = PAD_TRIGGER_L;
|
||||
else if (p & PAD_TRIGGER_R) p = PAD_TRIGGER_R;
|
||||
else first_key = MAX_KEYS;
|
||||
}
|
||||
else {
|
||||
if (p & WIIDRC_BUTTON_A) p = WIIDRC_BUTTON_A;
|
||||
else if (p & WIIDRC_BUTTON_B) p = WIIDRC_BUTTON_B;
|
||||
else if (p & WIIDRC_BUTTON_X) p = WIIDRC_BUTTON_X;
|
||||
else if (p & WIIDRC_BUTTON_Y) p = WIIDRC_BUTTON_Y;
|
||||
else if (p & WIIDRC_BUTTON_ZL) p = WIIDRC_BUTTON_ZL;
|
||||
else if (p & WIIDRC_BUTTON_ZR) p = WIIDRC_BUTTON_ZR;
|
||||
else if (p & WIIDRC_BUTTON_PLUS) p = WIIDRC_BUTTON_PLUS;
|
||||
else if (p & WIIDRC_BUTTON_MINUS) p = WIIDRC_BUTTON_MINUS;
|
||||
else if (p & WIIDRC_BUTTON_L) p = WIIDRC_BUTTON_L;
|
||||
else if (p & WIIDRC_BUTTON_R) p = WIIDRC_BUTTON_R;
|
||||
else first_key = MAX_KEYS;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -762,6 +793,14 @@ static void wpad_config(u8 exp, int chan, int first_key, int last_key)
|
|||
{
|
||||
config.wpad_keymap[4*exp + chan][first_key] = p;
|
||||
}
|
||||
|
||||
if (isRetroUSB)
|
||||
{
|
||||
while (RetroUSB_ButtonsHeld())
|
||||
{
|
||||
VIDEO_WaitVSync();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
while (first_key++ < last_key);
|
||||
|
@ -775,6 +814,14 @@ static void wpad_config(u8 exp, int chan, int first_key, int last_key)
|
|||
WPAD_ScanPads();
|
||||
}
|
||||
}
|
||||
else if (isRetroUSB)
|
||||
{
|
||||
while (RetroUSB_ButtonsHeld())
|
||||
{
|
||||
VIDEO_WaitVSync();
|
||||
RetroUSB_ScanPads();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (WiiDRC_ButtonsHeld())
|
||||
|
@ -784,49 +831,55 @@ static void wpad_config(u8 exp, int chan, int first_key, int last_key)
|
|||
}
|
||||
}
|
||||
|
||||
/* Configurable menu key */
|
||||
GUI_MsgBoxUpdate(0,"Press key(s) for MENU");
|
||||
|
||||
/* reset key combo */
|
||||
config.wpad_keymap[4*exp + chan][KEY_MENU] = 0;
|
||||
|
||||
/* wait for user input */
|
||||
p = 0;
|
||||
while (!p)
|
||||
if (!isRetroUSB)
|
||||
{
|
||||
VIDEO_WaitVSync();
|
||||
if (exp <= WPAD_EXP_CLASSIC)
|
||||
{
|
||||
WPAD_ScanPads();
|
||||
p = WPAD_ButtonsHeld(chan);
|
||||
}
|
||||
else
|
||||
{
|
||||
WiiDRC_ScanPads();
|
||||
p = WiiDRC_ButtonsHeld();
|
||||
}
|
||||
}
|
||||
/* Configurable menu key */
|
||||
GUI_MsgBoxUpdate(0, "Press key(s) for MENU");
|
||||
|
||||
/* register keys until none are pressed anymore */
|
||||
while (p)
|
||||
/* reset key combo */
|
||||
config.wpad_keymap[4 * exp + chan][KEY_MENU] = 0;
|
||||
|
||||
/* wait for user input */
|
||||
p = 0;
|
||||
while (!p)
|
||||
{
|
||||
VIDEO_WaitVSync();
|
||||
if (exp <= WPAD_EXP_CLASSIC)
|
||||
{
|
||||
WPAD_ScanPads();
|
||||
p = WPAD_ButtonsHeld(chan);
|
||||
}
|
||||
else
|
||||
{
|
||||
WiiDRC_ScanPads();
|
||||
p = WiiDRC_ButtonsHeld();
|
||||
}
|
||||
}
|
||||
|
||||
/* register keys until none are pressed anymore */
|
||||
while (p)
|
||||
{
|
||||
/* update key combo */
|
||||
config.wpad_keymap[4 * exp + chan][KEY_MENU] |= p;
|
||||
|
||||
/* update WPAD status */
|
||||
VIDEO_WaitVSync();
|
||||
if (exp <= WPAD_EXP_CLASSIC)
|
||||
{
|
||||
WPAD_ScanPads();
|
||||
p = WPAD_ButtonsHeld(chan);
|
||||
}
|
||||
else
|
||||
{
|
||||
WiiDRC_ScanPads();
|
||||
p = WiiDRC_ButtonsHeld();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* update key combo */
|
||||
config.wpad_keymap[4*exp + chan][KEY_MENU] |= p;
|
||||
|
||||
/* update WPAD status */
|
||||
VIDEO_WaitVSync();
|
||||
if (exp <= WPAD_EXP_CLASSIC)
|
||||
{
|
||||
WPAD_ScanPads();
|
||||
p = WPAD_ButtonsHeld(chan);
|
||||
}
|
||||
else
|
||||
{
|
||||
WiiDRC_ScanPads();
|
||||
p = WiiDRC_ButtonsHeld();
|
||||
}
|
||||
config.wpad_keymap[4 * exp + chan][KEY_MENU] = 0xFFFF;
|
||||
}
|
||||
|
||||
/* re-enable background WPAD scanning and exit */
|
||||
inputs_disabled = 0;
|
||||
}
|
||||
|
@ -846,34 +899,41 @@ static void wpad_update(s8 chan, u8 i, u32 exp)
|
|||
/* WiiU GamePad Controller support */
|
||||
if (exp > WPAD_EXP_CLASSIC)
|
||||
{
|
||||
WiiDRC_ScanPads();
|
||||
if (WiiDRC_ShutdownRequested())
|
||||
{
|
||||
Shutdown = ConfigRequested = 1;
|
||||
reload = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
p = WiiDRC_ButtonsHeld();
|
||||
|
||||
/* Default fast-forward key combo */
|
||||
if (WiiDRC_ButtonsDown() & WIIDRC_BUTTON_HOME)
|
||||
{
|
||||
if (p & WIIDRC_BUTTON_MINUS)
|
||||
if (RetroUSB_OK())
|
||||
{
|
||||
audioSync ^= AUDIO_WAIT;
|
||||
videoSync = (audioSync && config.vsync && (gc_pal != vdp_pal)) ? VIDEO_WAIT : 0;
|
||||
return;
|
||||
p = RetroUSB_ButtonsHeld();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
WiiDRC_ScanPads();
|
||||
if (WiiDRC_ShutdownRequested())
|
||||
{
|
||||
Shutdown = ConfigRequested = 1;
|
||||
reload = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Left Analog Stick */
|
||||
x = (WiiDRC_lStickX() * 128) / 75;
|
||||
y = (WiiDRC_lStickY() * 128) / 75;
|
||||
if (x > 127) x = 127;
|
||||
else if (x < -128) x = -128;
|
||||
if (y > 127) y = 127;
|
||||
else if (y < -128) y = -128;
|
||||
p = WiiDRC_ButtonsHeld();
|
||||
|
||||
/* Default fast-forward key combo */
|
||||
if (WiiDRC_ButtonsDown() & WIIDRC_BUTTON_HOME)
|
||||
{
|
||||
if (p & WIIDRC_BUTTON_MINUS)
|
||||
{
|
||||
audioSync ^= AUDIO_WAIT;
|
||||
videoSync = (audioSync && config.vsync && (gc_pal != vdp_pal)) ? VIDEO_WAIT : 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Left Analog Stick */
|
||||
x = (WiiDRC_lStickX() * 128) / 75;
|
||||
y = (WiiDRC_lStickY() * 128) / 75;
|
||||
if (x > 127) x = 127;
|
||||
else if (x < -128) x = -128;
|
||||
if (y > 127) y = 127;
|
||||
else if (y < -128) y = -128;
|
||||
}
|
||||
}
|
||||
else if (exp != WPAD_EXP_NONE)
|
||||
{
|
||||
|
@ -933,7 +993,7 @@ static void wpad_update(s8 chan, u8 i, u32 exp)
|
|||
input.analog[i][1] = y ? (127 - y) : 128;
|
||||
|
||||
/* Right Stick analog position [0-255] */
|
||||
if (exp >= WPAD_EXP_CLASSIC)
|
||||
if (exp >= WPAD_EXP_CLASSIC && !RetroUSB_OK())
|
||||
{
|
||||
if (exp > WPAD_EXP_CLASSIC)
|
||||
{
|
||||
|
@ -1060,7 +1120,7 @@ static void wpad_update(s8 chan, u8 i, u32 exp)
|
|||
input.analog[i][1] = 512;
|
||||
}
|
||||
}
|
||||
else
|
||||
else if(!RetroUSB_OK())
|
||||
{
|
||||
/* Left analog stick */
|
||||
input.analog[i][0] += x / ANALOG_SENSITIVITY;
|
||||
|
@ -1114,7 +1174,7 @@ static void wpad_update(s8 chan, u8 i, u32 exp)
|
|||
input.analog[i][1] = (int)((ir.sy - 384) * 2 / 3 / ANALOG_SENSITIVITY);
|
||||
}
|
||||
}
|
||||
else
|
||||
else if(!RetroUSB_OK())
|
||||
{
|
||||
/* Left analog stick position (-127;+127) -> (-255;+255) */
|
||||
input.analog[i][0] = (x / ANALOG_SENSITIVITY) * 2;
|
||||
|
@ -1156,7 +1216,7 @@ static void wpad_update(s8 chan, u8 i, u32 exp)
|
|||
input.analog[0][1] = 0x1fc + ((ir.y + config.caly) * (0x2f7 - 0x1fc + 1)) / 480;
|
||||
}
|
||||
}
|
||||
else
|
||||
else if(!RetroUSB_OK())
|
||||
{
|
||||
/* Left analog stick */
|
||||
input.analog[0][0] += x / ANALOG_SENSITIVITY;
|
||||
|
@ -1193,7 +1253,7 @@ static void wpad_update(s8 chan, u8 i, u32 exp)
|
|||
input.analog[0][1] = ((ir.y + config.caly) * 250) / 480;
|
||||
}
|
||||
}
|
||||
else
|
||||
else if(!RetroUSB_OK())
|
||||
{
|
||||
/* Left analog stick */
|
||||
input.analog[0][0] += x / ANALOG_SENSITIVITY;
|
||||
|
@ -1226,7 +1286,7 @@ static void wpad_update(s8 chan, u8 i, u32 exp)
|
|||
input.analog[0][1] = ((ir.y + config.caly) * 255) / 480;
|
||||
}
|
||||
}
|
||||
else
|
||||
else if(!RetroUSB_OK())
|
||||
{
|
||||
/* Left analog stick */
|
||||
input.analog[0][0] += x / ANALOG_SENSITIVITY;
|
||||
|
@ -1305,6 +1365,7 @@ void gx_input_Init(void)
|
|||
WPAD_SetDataFormat(WPAD_CHAN_ALL,WPAD_FMT_BTNS_ACC_IR);
|
||||
WPAD_SetVRes(WPAD_CHAN_ALL,640,480);
|
||||
WiiDRC_Init();
|
||||
RetroUSB_OK();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -1379,6 +1440,14 @@ int gx_input_FindDevices(void)
|
|||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 5: /* RetroUSB */
|
||||
{
|
||||
if (RetroUSB_OK())
|
||||
{
|
||||
found++;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
default:
|
||||
|
@ -1461,6 +1530,17 @@ void gx_input_SetDefault(void)
|
|||
config.wpad_keymap[4*3][KEY_BUTTONZ] = WIIDRC_BUTTON_X;
|
||||
config.wpad_keymap[4*3][KEY_MODE] = WIIDRC_BUTTON_MINUS;
|
||||
config.wpad_keymap[4*3][KEY_MENU] = WIIDRC_BUTTON_HOME;
|
||||
|
||||
/* RetroUSB */
|
||||
config.wpad_keymap[4 * 3 + 1][KEY_BUTTONA] = PAD_BUTTON_Y;
|
||||
config.wpad_keymap[4 * 3 + 1][KEY_BUTTONB] = PAD_BUTTON_B;
|
||||
config.wpad_keymap[4 * 3 + 1][KEY_BUTTONC] = PAD_BUTTON_A;
|
||||
config.wpad_keymap[4 * 3 + 1][KEY_START] = PAD_BUTTON_START;
|
||||
config.wpad_keymap[4 * 3 + 1][KEY_BUTTONX] = PAD_TRIGGER_L;
|
||||
config.wpad_keymap[4 * 3 + 1][KEY_BUTTONY] = PAD_TRIGGER_R;
|
||||
config.wpad_keymap[4 * 3 + 1][KEY_BUTTONZ] = PAD_BUTTON_X;
|
||||
config.wpad_keymap[4 * 3 + 1][KEY_MODE] = PAD_TRIGGER_Z;
|
||||
config.wpad_keymap[4 * 3 + 1][KEY_MENU] = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -1473,16 +1553,21 @@ void gx_input_SetDefault(void)
|
|||
}
|
||||
|
||||
#ifdef HW_RVL
|
||||
|
||||
i = 0;
|
||||
/* autodetect connected WiiU Gamepad Controller */
|
||||
if (WiiDRC_Inited() && WiiDRC_Connected())
|
||||
{
|
||||
config.input[0].device = 4;
|
||||
config.input[0].port = 0;
|
||||
i = 1;
|
||||
config.input[i].device = 4;
|
||||
config.input[i].port = 0;
|
||||
i++;
|
||||
}
|
||||
else
|
||||
/* autodetect RetroUSB */
|
||||
if (RetroUSB_OK())
|
||||
{
|
||||
i = 0;
|
||||
config.input[i].device = 5;
|
||||
config.input[i].port = 0;
|
||||
i++;
|
||||
}
|
||||
|
||||
/* autodetect connected Wii Controllers */
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 51 KiB |
|
@ -0,0 +1,188 @@
|
|||
#ifdef HW_RVL
|
||||
#include <gccore.h>
|
||||
#include <string.h>
|
||||
|
||||
#define RETROUSB_VID 61440
|
||||
#define RETROUSB_PID 8
|
||||
|
||||
#define POLL_THREAD_STACKSIZE (1024 * 4)
|
||||
#define POLL_THREAD_PRIO 65
|
||||
|
||||
static bool setup = false;
|
||||
static bool replugRequired = false;
|
||||
static s32 deviceId = 0;
|
||||
static u8 endpoint = 0;
|
||||
static u8 bMaxPacketSize = 0;
|
||||
static u32 jpRetroUSB;
|
||||
static char testChars[65];
|
||||
static bool pollThreadRunning = false;
|
||||
static lwp_t pollThread = LWP_THREAD_NULL;
|
||||
static u8 pollStack[POLL_THREAD_STACKSIZE] ATTRIBUTE_ALIGN(8);
|
||||
u8 RetroUSB_Counter = 0;
|
||||
|
||||
static bool isRetroUSBGamepad(usb_device_entry dev)
|
||||
{
|
||||
return dev.vid == RETROUSB_VID && dev.pid == RETROUSB_PID;
|
||||
}
|
||||
|
||||
static u8 getEndpoint(usb_devdesc devdesc)
|
||||
{
|
||||
if (devdesc.configurations == NULL || devdesc.configurations->interfaces == NULL ||
|
||||
devdesc.configurations->interfaces->endpoints == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
return devdesc.configurations->interfaces->endpoints->bEndpointAddress;
|
||||
}
|
||||
|
||||
static int removal_cb(int result, void* usrdata)
|
||||
{
|
||||
s32 fd = (s32)usrdata;
|
||||
if (fd == deviceId)
|
||||
{
|
||||
deviceId = 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void open()
|
||||
{
|
||||
if (deviceId != 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
usb_device_entry dev_entry[8];
|
||||
u8 dev_count;
|
||||
if (USB_GetDeviceList(dev_entry, 8, USB_CLASS_HID, &dev_count) < 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < dev_count; ++i)
|
||||
{
|
||||
if (!isRetroUSBGamepad(dev_entry[i]))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
s32 fd;
|
||||
if (USB_OpenDevice(dev_entry[i].device_id, dev_entry[i].vid, dev_entry[i].pid, &fd) < 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
usb_devdesc devdesc;
|
||||
if (USB_GetDescriptors(fd, &devdesc) < 0)
|
||||
{
|
||||
// You have to replug the controller!
|
||||
replugRequired = true;
|
||||
USB_CloseDevice(&fd);
|
||||
break;
|
||||
}
|
||||
|
||||
deviceId = fd;
|
||||
replugRequired = false;
|
||||
endpoint = getEndpoint(devdesc);
|
||||
bMaxPacketSize = devdesc.bMaxPacketSize0;
|
||||
USB_DeviceRemovalNotifyAsync(fd, &removal_cb, (void*)fd);
|
||||
break;
|
||||
}
|
||||
|
||||
setup = true;
|
||||
}
|
||||
|
||||
u32 RetroUSB_ScanPads(void)
|
||||
{
|
||||
return jpRetroUSB;
|
||||
}
|
||||
|
||||
static void *scanThreadFunc(void *arg)
|
||||
{
|
||||
RetroUSB_Counter = 100;
|
||||
while (1)
|
||||
{
|
||||
if (deviceId == 0 || replugRequired)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
uint8_t ATTRIBUTE_ALIGN(32) buf[4];
|
||||
s32 res = USB_ReadIntrMsg(deviceId, endpoint, sizeof(buf), buf);
|
||||
if (res < 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
u32 jp = 0;
|
||||
jp |= (buf[2] & 0x80) ? PAD_BUTTON_UP : 0;
|
||||
jp |= (buf[2] & 0x40) ? PAD_BUTTON_DOWN : 0;
|
||||
jp |= (buf[2] & 0x20) ? PAD_BUTTON_LEFT : 0;
|
||||
jp |= (buf[2] & 0x10) ? PAD_BUTTON_RIGHT : 0;
|
||||
|
||||
jp |= ((buf[2] & 0x08)) ? PAD_BUTTON_A : 0;
|
||||
jp |= ((buf[2] & 0x04)) ? PAD_BUTTON_B : 0;
|
||||
jp |= ((buf[3] & 0x04)) ? PAD_BUTTON_X : 0;
|
||||
jp |= ((buf[2] & 0x02)) ? PAD_BUTTON_Y : 0;
|
||||
|
||||
jp |= ((buf[3] & 0x02)) ? PAD_TRIGGER_L : 0;
|
||||
jp |= ((buf[3] & 0x08)) ? PAD_TRIGGER_R : 0;
|
||||
|
||||
jp |= ((buf[2] & 0x01)) ? PAD_BUTTON_START : 0;
|
||||
jp |= ((buf[3] & 0x01)) ? PAD_TRIGGER_Z : 0;
|
||||
|
||||
/*int i;
|
||||
for (i = 0; i < res; i++) {
|
||||
testChars[i * 3] = "0123456789ABCDEF"[(buf[i] & 0xF0) >> 4];
|
||||
testChars[i * 3 + 1] = "0123456789ABCDEF"[buf[i] & 0xF];
|
||||
testChars[i * 3 + 2] = ' ';
|
||||
}
|
||||
|
||||
counter++;
|
||||
testChars[i * 3] = "0123456789ABCDEF"[(counter & 0xF0) >> 4];
|
||||
testChars[i * 3 + 1] = "0123456789ABCDEF"[counter & 0xF];
|
||||
testChars[i * 3 + 2] = '\0';*/
|
||||
|
||||
RetroUSB_Counter++;
|
||||
|
||||
jpRetroUSB = jp;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 RetroUSB_ButtonsHeld()
|
||||
{
|
||||
if (!setup)
|
||||
{
|
||||
open();
|
||||
}
|
||||
if (!pollThreadRunning)
|
||||
{
|
||||
memset(pollStack, 0, POLL_THREAD_STACKSIZE);
|
||||
|
||||
s32 res = LWP_CreateThread(&pollThread, scanThreadFunc, NULL,
|
||||
pollStack, POLL_THREAD_STACKSIZE,
|
||||
POLL_THREAD_PRIO);
|
||||
if (!res)
|
||||
{
|
||||
pollThreadRunning = true;
|
||||
}
|
||||
}
|
||||
if (deviceId == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return jpRetroUSB;
|
||||
}
|
||||
|
||||
char* RetroUSB_TestChars() {
|
||||
return testChars;
|
||||
}
|
||||
|
||||
bool RetroUSB_OK()
|
||||
{
|
||||
open();
|
||||
return !replugRequired && deviceId;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,13 @@
|
|||
#ifndef _RETROUSB_H_
|
||||
#define _RETROUSB_H_
|
||||
|
||||
#include <gctypes.h>
|
||||
|
||||
bool RetroUSB_ScanPads();
|
||||
u32 RetroUSB_ButtonsHeld();
|
||||
bool RetroUSB_OK();
|
||||
char* RetroUSB_TestChars();
|
||||
|
||||
extern u8 RetroUSB_Counter;
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue