Compare commits

...

6 Commits

16 changed files with 504 additions and 238 deletions

View File

@ -58,9 +58,10 @@ Genesis Plus GX 1.7.5 (xx/xx/xxxx) (Eke-Eke)
* fixed byte access to font data registers * 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 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 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 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 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 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 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") * 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

View File

@ -2,7 +2,7 @@
* Genesis Plus * Genesis Plus
* Mega Drive cartridge hardware support * 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 * Many cartridge protections were initially documented by Haze
* (http://haze.mameworld.info/) * (http://haze.mameworld.info/)
@ -465,7 +465,10 @@ void md_cart_init(void)
memset(&cart.hw, 0, sizeof(cart.hw)); memset(&cart.hw, 0, sizeof(cart.hw));
/* initialize default $200000-$20ffff mapping (for games using SRAM & ROM bankswitching) */ /* 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 */ /* search for game into database */
for (i=0; i<(sizeof(rom_database)/sizeof(md_entry_t)); i++) for (i=0; i<(sizeof(rom_database)/sizeof(md_entry_t)); i++)

View File

@ -2,7 +2,7 @@
* Genesis Plus * Genesis Plus
* Mega Drive cartridge hardware support * 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 * Most cartridge protections were initially documented by Haze
* (http://haze.mameworld.info/) * (http://haze.mameworld.info/)

View File

@ -1893,6 +1893,79 @@ void cdd_update(void)
/* udpate current track index */ /* udpate current track index */
cdd.index = 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) void cdd_process(void)
@ -2069,73 +2142,7 @@ void cdd_process(void)
case 0x03: /* Play */ case 0x03: /* Play */
{ {
/* reset track index */ /* RS0 should indicate seeking until drive is ready (fixes audio delay in Bari Arm) */
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) */
/* RS1=0xf to invalidate track infos in RS2-RS8 until drive is ready (fixes Snatcher Act 2 start cutscene) */ /* 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[0x38>>1].w = (CD_SEEK << 8) | 0x0f;
scd.regs[0x3a>>1].w = 0x0000; scd.regs[0x3a>>1].w = 0x0000;
@ -2147,61 +2154,6 @@ void cdd_process(void)
case 0x04: /* Seek */ 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) */ /* 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[0x38>>1].w = (CD_SEEK << 8) | 0x0f;
scd.regs[0x3a>>1].w = 0x0000; scd.regs[0x3a>>1].w = 0x0000;

View File

@ -292,7 +292,7 @@ void m68k_run(unsigned int cycles)
#ifdef HOOK_CPU #ifdef HOOK_CPU
/* Trigger execution hook */ /* Trigger execution hook */
if (cpu_hook) if (UNLIKELY(cpu_hook))
cpu_hook(HOOK_M68K_E, 0, REG_PC, 0); cpu_hook(HOOK_M68K_E, 0, REG_PC, 0);
#endif #endif

View File

@ -859,7 +859,7 @@ INLINE uint m68ki_read_8(uint address)
else val = READ_BYTE(temp->base, (address) & 0xffff); else val = READ_BYTE(temp->base, (address) & 0xffff);
#ifdef HOOK_CPU #ifdef HOOK_CPU
if (cpu_hook) if (UNLIKELY(cpu_hook))
cpu_hook(HOOK_M68K_R, 1, address, val); cpu_hook(HOOK_M68K_R, 1, address, val);
#endif #endif
@ -879,7 +879,7 @@ INLINE uint m68ki_read_16(uint address)
else val = *(uint16 *)(temp->base + ((address) & 0xffff)); else val = *(uint16 *)(temp->base + ((address) & 0xffff));
#ifdef HOOK_CPU #ifdef HOOK_CPU
if (cpu_hook) if (UNLIKELY(cpu_hook))
cpu_hook(HOOK_M68K_R, 2, address, val); cpu_hook(HOOK_M68K_R, 2, address, val);
#endif #endif
@ -899,7 +899,7 @@ INLINE uint m68ki_read_32(uint address)
else val = m68k_read_immediate_32(address); else val = m68k_read_immediate_32(address);
#ifdef HOOK_CPU #ifdef HOOK_CPU
if (cpu_hook) if (UNLIKELY(cpu_hook))
cpu_hook(HOOK_M68K_R, 4, address, val); cpu_hook(HOOK_M68K_R, 4, address, val);
#endif #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) */ m68ki_set_fc(FLAG_S | FUNCTION_CODE_USER_DATA) /* auto-disable (see m68kcpu.h) */
#ifdef HOOK_CPU #ifdef HOOK_CPU
if (cpu_hook) if (UNLIKELY(cpu_hook))
cpu_hook(HOOK_M68K_W, 1, address, value); cpu_hook(HOOK_M68K_W, 1, address, value);
#endif #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) */ m68ki_check_address_error(address, MODE_WRITE, FLAG_S | FUNCTION_CODE_USER_DATA); /* auto-disable (see m68kcpu.h) */
#ifdef HOOK_CPU #ifdef HOOK_CPU
if (cpu_hook) if (UNLIKELY(cpu_hook))
cpu_hook(HOOK_M68K_W, 2, address, value); cpu_hook(HOOK_M68K_W, 2, address, value);
#endif #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) */ m68ki_check_address_error(address, MODE_WRITE, FLAG_S | FUNCTION_CODE_USER_DATA) /* auto-disable (see m68kcpu.h) */
#ifdef HOOK_CPU #ifdef HOOK_CPU
if (cpu_hook) if (UNLIKELY(cpu_hook))
cpu_hook(HOOK_M68K_W, 4, address, value); cpu_hook(HOOK_M68K_W, 4, address, value);
#endif #endif

View File

@ -53,6 +53,15 @@
#define ALIGNED_(x) __attribute__ ((aligned(x))) #define ALIGNED_(x) __attribute__ ((aligned(x)))
#endif #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 */ /* Default CD image file access (read-only) functions */
/* If you need to override default stdio.h functions with custom filesystem API, /* 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 redefine following macros in platform specific include file (osd.h) or Makefile

View File

@ -2162,7 +2162,7 @@ static void vdp_bus_w(unsigned int data)
} }
#ifdef HOOK_CPU #ifdef HOOK_CPU
if (cpu_hook) if (UNLIKELY(cpu_hook))
cpu_hook(HOOK_VRAM_W, 2, addr, data); cpu_hook(HOOK_VRAM_W, 2, addr, data);
#endif #endif
@ -2211,7 +2211,7 @@ static void vdp_bus_w(unsigned int data)
} }
#ifdef HOOK_CPU #ifdef HOOK_CPU
if (cpu_hook) if (UNLIKELY(cpu_hook))
cpu_hook(HOOK_CRAM_W, 2, addr, data); cpu_hook(HOOK_CRAM_W, 2, addr, data);
#endif #endif
@ -2237,7 +2237,7 @@ static void vdp_bus_w(unsigned int data)
} }
#ifdef HOOK_CPU #ifdef HOOK_CPU
if (cpu_hook) if (UNLIKELY(cpu_hook))
cpu_hook(HOOK_VSRAM_W, 2, addr, data); cpu_hook(HOOK_VSRAM_W, 2, addr, data);
#endif #endif
@ -2448,7 +2448,7 @@ static unsigned int vdp_68k_data_r_m5(void)
data = *(uint16 *)&vram[addr & 0xFFFE]; data = *(uint16 *)&vram[addr & 0xFFFE];
#ifdef HOOK_CPU #ifdef HOOK_CPU
if (cpu_hook) if (UNLIKELY(cpu_hook))
cpu_hook(HOOK_VRAM_R, 2, addr, data); cpu_hook(HOOK_VRAM_R, 2, addr, data);
#endif #endif
@ -2477,7 +2477,7 @@ static unsigned int vdp_68k_data_r_m5(void)
data |= (fifo[fifo_idx] & ~0x7FF); data |= (fifo[fifo_idx] & ~0x7FF);
#ifdef HOOK_CPU #ifdef HOOK_CPU
if (cpu_hook) if (UNLIKELY(cpu_hook))
cpu_hook(HOOK_VSRAM_R, 2, addr, data); cpu_hook(HOOK_VSRAM_R, 2, addr, data);
#endif #endif
@ -2499,7 +2499,7 @@ static unsigned int vdp_68k_data_r_m5(void)
data |= (fifo[fifo_idx] & ~0xEEE); data |= (fifo[fifo_idx] & ~0xEEE);
#ifdef HOOK_CPU #ifdef HOOK_CPU
if (cpu_hook) if (UNLIKELY(cpu_hook))
cpu_hook(HOOK_CRAM_R, 2, addr, data); cpu_hook(HOOK_CRAM_R, 2, addr, data);
#endif #endif
@ -2518,7 +2518,7 @@ static unsigned int vdp_68k_data_r_m5(void)
data |= (fifo[fifo_idx] & ~0xFF); data |= (fifo[fifo_idx] & ~0xFF);
#ifdef HOOK_CPU #ifdef HOOK_CPU
if (cpu_hook) if (UNLIKELY(cpu_hook))
cpu_hook(HOOK_VRAM_R, 2, addr, data); cpu_hook(HOOK_VRAM_R, 2, addr, data);
#endif #endif

View File

@ -48,6 +48,7 @@
#ifdef HW_RVL #ifdef HW_RVL
#include <ogc/usbmouse.h> #include <ogc/usbmouse.h>
#include "wiidrc.h" #include "wiidrc.h"
#include "retrousb.h"
#endif #endif
#include <ogc/lwp_threads.h> #include <ogc/lwp_threads.h>
@ -124,6 +125,7 @@
#include "ctrl_nunchuk_png.h" #include "ctrl_nunchuk_png.h"
#include "ctrl_wiimote_png.h" #include "ctrl_wiimote_png.h"
#include "ctrl_wiiu_png.h" #include "ctrl_wiiu_png.h"
#include "ctrl_retrousb_png.h"
#endif #endif
/* Generic images */ /* Generic images */
@ -2471,7 +2473,7 @@ static void ctrlmenu(void)
/* Player Configuration device items */ /* Player Configuration device items */
#ifdef HW_RVL #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_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}, {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_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_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_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 #else
gui_item items_device[2] = 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[5].texture = gxTextureOpenPNG(items_device[5].data,0);
} }
items_device[6].texture = gxTextureOpenPNG(items_device[6].data, 0);
#endif #endif
/* restore current menu elements */ /* restore current menu elements */
@ -3060,11 +3064,21 @@ static void ctrlmenu(void)
/* support for only one gamepad */ /* support for only one gamepad */
if (!WiiDRC_Inited() || !WiiDRC_Connected() || (config.input[player].port >= 1)) if (!WiiDRC_Inited() || !WiiDRC_Connected() || (config.input[player].port >= 1))
{ {
/* no input controller left */ /* test RetroUSB */
config.input[player].device = -1; config.input[player].device = 5;
config.input[player].port = player%4; 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 #endif
/* update menu items */ /* update menu items */
@ -3230,6 +3244,7 @@ static void ctrlmenu(void)
{ {
gxTextureClose(&items_device[5].texture); gxTextureClose(&items_device[5].texture);
} }
gxTextureClose(&items_device[6].texture);
#endif #endif
} }

View File

@ -46,6 +46,7 @@
#ifdef HW_RVL #ifdef HW_RVL
#include <ogc/usbmouse.h> #include <ogc/usbmouse.h>
#include "wiidrc.h" #include "wiidrc.h"
#include "retrousb.h"
#endif #endif
/* Analog sticks sensitivity */ /* Analog sticks sensitivity */
@ -79,12 +80,13 @@
#define PAD_RIGHT 3 #define PAD_RIGHT 3
/* default directions mapping */ /* 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_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_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 */ {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 | \ #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]; char msg[64];
u32 p = 255; u32 p = 255;
bool isRetroUSB = false;
/* Disable background PAD scanning */ /* Disable background PAD scanning */
inputs_disabled = 1; 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); WPAD_Probe(chan, &p);
} }
else else if (WiiDRC_Inited() && WiiDRC_Connected())
{ {
if (WiiDRC_Inited() && WiiDRC_Connected())
{
p = exp; p = exp;
} }
else if (RetroUSB_OK())
{
p = exp;
isRetroUSB = true;
} }
/* Device not detected */ /* 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); 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_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 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); GUI_WaitPrompt("Error",msg);
/* re-enable background PAD scanning and exit */ /* 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(); WPAD_ScanPads();
} }
} }
else if (isRetroUSB)
{
while (RetroUSB_ButtonsHeld())
{
VIDEO_WaitVSync();
RetroUSB_ScanPads();
}
}
else else
{ {
while (WiiDRC_ButtonsHeld()) while (WiiDRC_ButtonsHeld())
@ -672,7 +685,7 @@ static void wpad_config(u8 exp, int chan, int first_key, int last_key)
/* configurable button */ /* configurable button */
sprintf(msg,"Press key for %s\n(HOME to return)",keyname[first_key]); 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 */ /* wait for user input */
p = 0; p = 0;
@ -684,6 +697,11 @@ static void wpad_config(u8 exp, int chan, int first_key, int last_key)
WPAD_ScanPads(); WPAD_ScanPads();
p = WPAD_ButtonsDown(chan); p = WPAD_ButtonsDown(chan);
} }
else if (isRetroUSB)
{
RetroUSB_ScanPads();
p = RetroUSB_ButtonsHeld();
}
else else
{ {
WiiDRC_ScanPads(); WiiDRC_ScanPads();
@ -742,17 +760,30 @@ static void wpad_config(u8 exp, int chan, int first_key, int last_key)
/* WiiU GamePad Controller */ /* WiiU GamePad Controller */
default: default:
{ {
if (p & WIIDRC_BUTTON_A) p = WIIDRC_BUTTON_A; if (isRetroUSB) {
else if (p & WIIDRC_BUTTON_B) p = WIIDRC_BUTTON_B; if (p & PAD_BUTTON_A) p = PAD_BUTTON_A;
else if (p & WIIDRC_BUTTON_X) p = WIIDRC_BUTTON_X; else if (p & PAD_BUTTON_B) p = PAD_BUTTON_B;
else if (p & WIIDRC_BUTTON_Y) p = WIIDRC_BUTTON_Y; else if (p & PAD_BUTTON_X) p = PAD_BUTTON_X;
else if (p & WIIDRC_BUTTON_ZL) p = WIIDRC_BUTTON_ZL; else if (p & PAD_BUTTON_Y) p = PAD_BUTTON_Y;
else if (p & WIIDRC_BUTTON_ZR) p = WIIDRC_BUTTON_ZR; else if (p & PAD_TRIGGER_Z) p = PAD_TRIGGER_Z;
else if (p & WIIDRC_BUTTON_PLUS) p = WIIDRC_BUTTON_PLUS; else if (p & PAD_BUTTON_START) p = PAD_BUTTON_START;
else if (p & WIIDRC_BUTTON_MINUS) p = WIIDRC_BUTTON_MINUS; else if (p & PAD_TRIGGER_L) p = PAD_TRIGGER_L;
else if (p & WIIDRC_BUTTON_L) p = WIIDRC_BUTTON_L; else if (p & PAD_TRIGGER_R) p = PAD_TRIGGER_R;
else if (p & WIIDRC_BUTTON_R) p = WIIDRC_BUTTON_R; else first_key = MAX_KEYS;
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; 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; config.wpad_keymap[4*exp + chan][first_key] = p;
} }
if (isRetroUSB)
{
while (RetroUSB_ButtonsHeld())
{
VIDEO_WaitVSync();
}
}
} }
} }
while (first_key++ < last_key); 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(); WPAD_ScanPads();
} }
} }
else if (isRetroUSB)
{
while (RetroUSB_ButtonsHeld())
{
VIDEO_WaitVSync();
RetroUSB_ScanPads();
}
}
else else
{ {
while (WiiDRC_ButtonsHeld()) while (WiiDRC_ButtonsHeld())
@ -784,49 +831,55 @@ static void wpad_config(u8 exp, int chan, int first_key, int last_key)
} }
} }
/* Configurable menu key */ if (!isRetroUSB)
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)
{ {
VIDEO_WaitVSync(); /* Configurable menu key */
if (exp <= WPAD_EXP_CLASSIC) GUI_MsgBoxUpdate(0, "Press key(s) for MENU");
{
WPAD_ScanPads();
p = WPAD_ButtonsHeld(chan);
}
else
{
WiiDRC_ScanPads();
p = WiiDRC_ButtonsHeld();
}
}
/* register keys until none are pressed anymore */ /* reset key combo */
while (p) 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] = 0xFFFF;
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();
}
} }
/* re-enable background WPAD scanning and exit */ /* re-enable background WPAD scanning and exit */
inputs_disabled = 0; inputs_disabled = 0;
} }
@ -846,34 +899,41 @@ static void wpad_update(s8 chan, u8 i, u32 exp)
/* WiiU GamePad Controller support */ /* WiiU GamePad Controller support */
if (exp > WPAD_EXP_CLASSIC) if (exp > WPAD_EXP_CLASSIC)
{ {
WiiDRC_ScanPads(); if (RetroUSB_OK())
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)
{ {
audioSync ^= AUDIO_WAIT; p = RetroUSB_ButtonsHeld();
videoSync = (audioSync && config.vsync && (gc_pal != vdp_pal)) ? VIDEO_WAIT : 0;
return;
} }
} else
{
WiiDRC_ScanPads();
if (WiiDRC_ShutdownRequested())
{
Shutdown = ConfigRequested = 1;
reload = 0;
return;
}
/* Left Analog Stick */ p = WiiDRC_ButtonsHeld();
x = (WiiDRC_lStickX() * 128) / 75;
y = (WiiDRC_lStickY() * 128) / 75; /* Default fast-forward key combo */
if (x > 127) x = 127; if (WiiDRC_ButtonsDown() & WIIDRC_BUTTON_HOME)
else if (x < -128) x = -128; {
if (y > 127) y = 127; if (p & WIIDRC_BUTTON_MINUS)
else if (y < -128) y = -128; {
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) 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; input.analog[i][1] = y ? (127 - y) : 128;
/* Right Stick analog position [0-255] */ /* Right Stick analog position [0-255] */
if (exp >= WPAD_EXP_CLASSIC) if (exp >= WPAD_EXP_CLASSIC && !RetroUSB_OK())
{ {
if (exp > WPAD_EXP_CLASSIC) if (exp > WPAD_EXP_CLASSIC)
{ {
@ -1060,7 +1120,7 @@ static void wpad_update(s8 chan, u8 i, u32 exp)
input.analog[i][1] = 512; input.analog[i][1] = 512;
} }
} }
else else if(!RetroUSB_OK())
{ {
/* Left analog stick */ /* Left analog stick */
input.analog[i][0] += x / ANALOG_SENSITIVITY; 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); 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) */ /* Left analog stick position (-127;+127) -> (-255;+255) */
input.analog[i][0] = (x / ANALOG_SENSITIVITY) * 2; 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; input.analog[0][1] = 0x1fc + ((ir.y + config.caly) * (0x2f7 - 0x1fc + 1)) / 480;
} }
} }
else else if(!RetroUSB_OK())
{ {
/* Left analog stick */ /* Left analog stick */
input.analog[0][0] += x / ANALOG_SENSITIVITY; 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; input.analog[0][1] = ((ir.y + config.caly) * 250) / 480;
} }
} }
else else if(!RetroUSB_OK())
{ {
/* Left analog stick */ /* Left analog stick */
input.analog[0][0] += x / ANALOG_SENSITIVITY; 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; input.analog[0][1] = ((ir.y + config.caly) * 255) / 480;
} }
} }
else else if(!RetroUSB_OK())
{ {
/* Left analog stick */ /* Left analog stick */
input.analog[0][0] += x / ANALOG_SENSITIVITY; 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_SetDataFormat(WPAD_CHAN_ALL,WPAD_FMT_BTNS_ACC_IR);
WPAD_SetVRes(WPAD_CHAN_ALL,640,480); WPAD_SetVRes(WPAD_CHAN_ALL,640,480);
WiiDRC_Init(); WiiDRC_Init();
RetroUSB_OK();
#endif #endif
} }
@ -1379,6 +1440,14 @@ int gx_input_FindDevices(void)
} }
break; break;
} }
case 5: /* RetroUSB */
{
if (RetroUSB_OK())
{
found++;
}
}
#endif #endif
default: 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_BUTTONZ] = WIIDRC_BUTTON_X;
config.wpad_keymap[4*3][KEY_MODE] = WIIDRC_BUTTON_MINUS; config.wpad_keymap[4*3][KEY_MODE] = WIIDRC_BUTTON_MINUS;
config.wpad_keymap[4*3][KEY_MENU] = WIIDRC_BUTTON_HOME; 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 #endif
@ -1473,16 +1553,21 @@ void gx_input_SetDefault(void)
} }
#ifdef HW_RVL #ifdef HW_RVL
i = 0;
/* autodetect connected WiiU Gamepad Controller */ /* autodetect connected WiiU Gamepad Controller */
if (WiiDRC_Inited() && WiiDRC_Connected()) if (WiiDRC_Inited() && WiiDRC_Connected())
{ {
config.input[0].device = 4; config.input[i].device = 4;
config.input[0].port = 0; config.input[i].port = 0;
i = 1; i++;
} }
else /* autodetect RetroUSB */
if (RetroUSB_OK())
{ {
i = 0; config.input[i].device = 5;
config.input[i].port = 0;
i++;
} }
/* autodetect connected Wii Controllers */ /* autodetect connected Wii Controllers */

BIN
gx/images/ctrl_retrousb.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

188
gx/retrousb.c Normal file
View File

@ -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

13
gx/retrousb.h Normal file
View File

@ -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