mirror of
https://github.com/ekeeke/Genesis-Plus-GX.git
synced 2024-05-20 05:10:30 -04:00
Compare commits
5 commits
452f094df5
...
886fd429bb
Author | SHA1 | Date | |
---|---|---|---|
886fd429bb | |||
6972a5b0d6 | |||
8c72ba0d45 | |||
5af254cd23 | |||
22526f587c |
|
@ -159,6 +159,7 @@ Genesis Plus GX 1.7.5 (xx/xx/xxxx) (Eke-Eke)
|
|||
* improved Mode 5 sprites parsing accuracy (verified on real hardware)
|
||||
* improved Mode 5 sprites rendering timings (fixes "Overdrive" demo)
|
||||
* improved FIFO timings accuracy (fixes "Overdrive" Demo)
|
||||
* improved FIFO emulation (fixes potential lockup when switching between H32 & H40 mode during active display)
|
||||
* improved H-Counter accuracy in H32 mode
|
||||
* improved VDP status timing accuracy
|
||||
* improved HBLANK flag timing accuracy (verified on real hardware by Nemesis)
|
||||
|
|
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 MiB After Width: | Height: | Size: 4 MiB |
|
@ -334,8 +334,10 @@ void system_frame_gen(int do_skip)
|
|||
mcycles_vdp = 0;
|
||||
|
||||
/* reset VDP FIFO */
|
||||
fifo_write_cnt = 0;
|
||||
fifo_slots = 0;
|
||||
fifo_cycles[0] = 0;
|
||||
fifo_cycles[1] = 0;
|
||||
fifo_cycles[2] = 0;
|
||||
fifo_cycles[3] = 0;
|
||||
|
||||
/* check if display setings have changed during previous frame */
|
||||
if (bitmap.viewport.changed & 2)
|
||||
|
@ -420,8 +422,8 @@ void system_frame_gen(int do_skip)
|
|||
/* clear DMA Busy, FIFO FULL & field flags */
|
||||
status &= 0xFEED;
|
||||
|
||||
/* set VBLANK & FIFO EMPTY flags */
|
||||
status |= 0x0208;
|
||||
/* set VBLANK flag */
|
||||
status |= 0x08;
|
||||
|
||||
/* check interlaced modes */
|
||||
if (interlaced)
|
||||
|
@ -675,8 +677,10 @@ void system_frame_scd(int do_skip)
|
|||
scd.cycles = 0;
|
||||
|
||||
/* reset VDP FIFO */
|
||||
fifo_write_cnt = 0;
|
||||
fifo_slots = 0;
|
||||
fifo_cycles[0] = 0;
|
||||
fifo_cycles[1] = 0;
|
||||
fifo_cycles[2] = 0;
|
||||
fifo_cycles[3] = 0;
|
||||
|
||||
/* check if display setings have changed during previous frame */
|
||||
if (bitmap.viewport.changed & 2)
|
||||
|
@ -761,8 +765,8 @@ void system_frame_scd(int do_skip)
|
|||
/* clear DMA Busy, FIFO FULL & field flags */
|
||||
status &= 0xFEED;
|
||||
|
||||
/* set VBLANK & FIFO EMPTY flags */
|
||||
status |= 0x0208;
|
||||
/* set VBLANK flag */
|
||||
status |= 0x08;
|
||||
|
||||
/* check interlaced modes */
|
||||
if (interlaced)
|
||||
|
@ -1000,8 +1004,10 @@ void system_frame_sms(int do_skip)
|
|||
mcycles_vdp = 0;
|
||||
|
||||
/* reset VDP FIFO */
|
||||
fifo_write_cnt = 0;
|
||||
fifo_slots = 0;
|
||||
fifo_cycles[0] = 0;
|
||||
fifo_cycles[1] = 0;
|
||||
fifo_cycles[2] = 0;
|
||||
fifo_cycles[3] = 0;
|
||||
|
||||
/* check if display settings has changed during previous frame */
|
||||
if (bitmap.viewport.changed & 2)
|
||||
|
|
205
core/vdp_ctrl.c
205
core/vdp_ctrl.c
|
@ -52,6 +52,7 @@
|
|||
} \
|
||||
bg_name_dirty[name] |= (1 << ((addr >> 2) & 7)); \
|
||||
}
|
||||
|
||||
/* VINT timings */
|
||||
#define VINT_H32_MCYCLE (770)
|
||||
#define VINT_H40_MCYCLE (788)
|
||||
|
@ -98,8 +99,7 @@ uint16 v_counter; /* Vertical counter */
|
|||
uint16 vc_max; /* Vertical counter overflow value */
|
||||
uint16 lines_per_frame; /* PAL: 313 lines, NTSC: 262 lines */
|
||||
uint16 max_sprite_pixels; /* Max. sprites pixels per line (parsing & rendering) */
|
||||
int32 fifo_write_cnt; /* VDP FIFO write count */
|
||||
uint32 fifo_slots; /* VDP FIFO access slot count */
|
||||
uint32 fifo_cycles[4]; /* VDP FIFO read-out cycles */
|
||||
uint32 hvc_latch; /* latched HV counter */
|
||||
uint32 vint_cycle; /* VINT occurence cycle */
|
||||
const uint8 *hctab; /* pointer to H Counter table */
|
||||
|
@ -123,7 +123,6 @@ static void vdp_z80_data_w_ms(unsigned int data);
|
|||
static void vdp_z80_data_w_gg(unsigned int data);
|
||||
static void vdp_z80_data_w_sg(unsigned int data);
|
||||
static void vdp_bus_w(unsigned int data);
|
||||
static void vdp_fifo_update(unsigned int cycles);
|
||||
static void vdp_reg_w(unsigned int r, unsigned int d, unsigned int cycles);
|
||||
static void vdp_dma_68k_ext(unsigned int length);
|
||||
static void vdp_dma_68k_ram(unsigned int length);
|
||||
|
@ -150,7 +149,6 @@ static int cached_write; /* 2nd part of 32-bit CTRL port write (Genesis m
|
|||
static uint16 fifo[4]; /* FIFO ring-buffer */
|
||||
static int fifo_idx; /* FIFO write index */
|
||||
static int fifo_byte_access; /* FIFO byte access flag */
|
||||
static uint32 fifo_cycles; /* FIFO next access cycle */
|
||||
static int *fifo_timing; /* FIFO slots timing table */
|
||||
static int hblank_start_cycle; /* HBLANK flag set cycle */
|
||||
static int hblank_end_cycle; /* HBLANK flag clear cycle */
|
||||
|
@ -170,16 +168,20 @@ static const uint16 vc_table[4][2] =
|
|||
};
|
||||
|
||||
/* FIFO access slots timings */
|
||||
static const int fifo_timing_h32[16+4] =
|
||||
static const int fifo_timing_h32[] =
|
||||
{
|
||||
230, 510, 810, 970, 1130, 1450, 1610, 1770, 2090, 2250, 2410, 2730, 2890, 3050, 3350, 3370,
|
||||
MCYCLES_PER_LINE + 230, MCYCLES_PER_LINE + 510, MCYCLES_PER_LINE + 810, MCYCLES_PER_LINE + 970,
|
||||
MCYCLES_PER_LINE + 1130, MCYCLES_PER_LINE + 1450, MCYCLES_PER_LINE + 1610, MCYCLES_PER_LINE + 1770,
|
||||
MCYCLES_PER_LINE + 2090, MCYCLES_PER_LINE + 2250, MCYCLES_PER_LINE + 2410, MCYCLES_PER_LINE + 2730
|
||||
};
|
||||
|
||||
static const int fifo_timing_h40[18+4] =
|
||||
static const int fifo_timing_h40[] =
|
||||
{
|
||||
352, 820, 948, 1076, 1332, 1460, 1588, 1844, 1972, 2100, 2356, 2484, 2612, 2868, 2996, 3124, 3364, 3380,
|
||||
MCYCLES_PER_LINE + 352, MCYCLES_PER_LINE + 820, MCYCLES_PER_LINE + 948, MCYCLES_PER_LINE + 1076,
|
||||
MCYCLES_PER_LINE + 1332, MCYCLES_PER_LINE + 1460, MCYCLES_PER_LINE + 1588, MCYCLES_PER_LINE + 1844,
|
||||
MCYCLES_PER_LINE + 1972, MCYCLES_PER_LINE + 2100, MCYCLES_PER_LINE + 2356, MCYCLES_PER_LINE + 2484
|
||||
};
|
||||
|
||||
/* DMA Timings (number of access slots per line) */
|
||||
|
@ -276,9 +278,6 @@ void vdp_reset(void)
|
|||
odd_frame = 0;
|
||||
im2_flag = 0;
|
||||
interlaced = 0;
|
||||
fifo_write_cnt = 0;
|
||||
fifo_cycles = 0;
|
||||
fifo_slots = 0;
|
||||
fifo_idx = 0;
|
||||
cached_write = -1;
|
||||
fifo_byte_access = 1;
|
||||
|
@ -306,10 +305,10 @@ void vdp_reset(void)
|
|||
/* default Window clipping */
|
||||
window_clip(0,0);
|
||||
|
||||
/* reset VDP status (FIFO empty flag is set) */
|
||||
/* reset VDP status */
|
||||
if (system_hw & SYSTEM_MD)
|
||||
{
|
||||
status = vdp_pal | 0x200;
|
||||
status = vdp_pal;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -593,7 +592,7 @@ int vdp_context_load(uint8 *state)
|
|||
|
||||
void vdp_dma_update(unsigned int cycles)
|
||||
{
|
||||
unsigned int dma_cycles, dma_bytes;
|
||||
int dma_cycles, dma_bytes;
|
||||
|
||||
/* DMA transfer rate (bytes per line)
|
||||
|
||||
|
@ -630,6 +629,12 @@ void vdp_dma_update(unsigned int cycles)
|
|||
else if (rate == 204) rate = 198; /* 6 refresh slots per line in H40 mode when display is off */
|
||||
}
|
||||
|
||||
/* Adjust DMA start cycle for DMA fill to take in account intial data port write */
|
||||
else if (dmafill)
|
||||
{
|
||||
cycles += (2 * (MCYCLES_PER_LINE / rate));
|
||||
}
|
||||
|
||||
/* Available DMA cycles */
|
||||
if (status & 8)
|
||||
{
|
||||
|
@ -692,7 +697,7 @@ void vdp_dma_update(unsigned int cycles)
|
|||
}
|
||||
|
||||
/* Process DMA */
|
||||
if (dma_bytes)
|
||||
if (dma_bytes > 0)
|
||||
{
|
||||
/* Update DMA length */
|
||||
dma_length -= dma_bytes;
|
||||
|
@ -1188,12 +1193,6 @@ unsigned int vdp_68k_ctrl_r(unsigned int cycles)
|
|||
/* Cycle-accurate VDP status read (adjust CPU time with current instruction execution time) */
|
||||
cycles += m68k_cycles();
|
||||
|
||||
/* Update FIFO status flags if not empty */
|
||||
if (fifo_write_cnt)
|
||||
{
|
||||
vdp_fifo_update(cycles);
|
||||
}
|
||||
|
||||
/* Check if DMA Busy flag is set */
|
||||
if (status & 2)
|
||||
{
|
||||
|
@ -1214,6 +1213,20 @@ unsigned int vdp_68k_ctrl_r(unsigned int cycles)
|
|||
/* Clear SOVR & SCOL flags */
|
||||
status &= 0xFF9F;
|
||||
|
||||
/* Check if FIFO last entry read-out cycle has been reached */
|
||||
if (cycles >= fifo_cycles[(fifo_idx + 3) & 3])
|
||||
{
|
||||
/* FIFO is empty */
|
||||
temp |= 0x200;
|
||||
}
|
||||
|
||||
/* Check if FIFO oldest entry read-out cycle is not yet reached */
|
||||
else if (cycles < fifo_cycles[fifo_idx])
|
||||
{
|
||||
/* FIFO is full */
|
||||
temp |= 0x100;
|
||||
}
|
||||
|
||||
/* VBLANK flag is set when display is disabled */
|
||||
if (!(reg[1] & 0x40))
|
||||
{
|
||||
|
@ -1985,13 +1998,6 @@ static void vdp_reg_w(unsigned int r, unsigned int d, unsigned int cycles)
|
|||
/* Active display width */
|
||||
if (r & 0x01)
|
||||
{
|
||||
/* FIFO access slots timings depend on active width */
|
||||
if (fifo_slots)
|
||||
{
|
||||
/* Synchronize VDP FIFO */
|
||||
vdp_fifo_update(cycles);
|
||||
}
|
||||
|
||||
if (d & 0x01)
|
||||
{
|
||||
/* Update display-dependant registers */
|
||||
|
@ -2108,68 +2114,6 @@ static void vdp_reg_w(unsigned int r, unsigned int d, unsigned int cycles)
|
|||
}
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* FIFO emulation (Mega Drive VDP specific) */
|
||||
/* ---------------------------------------- */
|
||||
/* */
|
||||
/* CPU access to VRAM, CRAM & VSRAM is limited during active display: */
|
||||
/* H32 mode -> 16 access per line */
|
||||
/* H40 mode -> 18 access per line */
|
||||
/* */
|
||||
/* with fixed access slots timings detailled below. */
|
||||
/* */
|
||||
/* Each VRAM access is byte wide, so one VRAM write (word) need two slots. */
|
||||
/* */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
static void vdp_fifo_update(unsigned int cycles)
|
||||
{
|
||||
int fifo_read_cnt, line_slots = 0;
|
||||
|
||||
/* number of access slots up to current line */
|
||||
int total_slots = dma_timing[0][reg[12] & 1] * ((v_counter + 1) % lines_per_frame);
|
||||
|
||||
/* number of access slots within current line */
|
||||
cycles -= mcycles_vdp;
|
||||
while (fifo_timing[line_slots] <= cycles)
|
||||
{
|
||||
line_slots++;
|
||||
}
|
||||
|
||||
/* number of processed FIFO entries since last access (byte access needs two slots to process one FIFO word) */
|
||||
fifo_read_cnt = (total_slots + line_slots - fifo_slots) >> fifo_byte_access;
|
||||
|
||||
if (fifo_read_cnt > 0)
|
||||
{
|
||||
/* process FIFO entries */
|
||||
fifo_write_cnt -= fifo_read_cnt;
|
||||
|
||||
/* Clear FIFO full flag */
|
||||
status &= 0xFEFF;
|
||||
|
||||
if (fifo_write_cnt <= 0)
|
||||
{
|
||||
/* No more FIFO entries */
|
||||
fifo_write_cnt = 0;
|
||||
|
||||
/* Set FIFO empty flag */
|
||||
status |= 0x200;
|
||||
|
||||
/* Reinitialize FIFO access slot counter */
|
||||
fifo_slots = total_slots + line_slots;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Update FIFO access slot counter */
|
||||
fifo_slots += (fifo_read_cnt << fifo_byte_access);
|
||||
}
|
||||
}
|
||||
|
||||
/* next FIFO update cycle */
|
||||
fifo_cycles = mcycles_vdp + fifo_timing[fifo_slots - total_slots + fifo_byte_access];
|
||||
}
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* Internal 16-bit data bus access function (Mode 5 only) */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
@ -2329,29 +2273,31 @@ static void vdp_68k_data_w_m4(unsigned int data)
|
|||
/* Restricted VDP writes during active display */
|
||||
if (!(status & 8) && (reg[1] & 0x40))
|
||||
{
|
||||
/* Update VDP FIFO */
|
||||
vdp_fifo_update(m68k.cycles);
|
||||
int slot = 0;
|
||||
|
||||
/* Clear FIFO empty flag */
|
||||
status &= 0xFDFF;
|
||||
/* Cycle-accurate VDP data port access */
|
||||
int cycles = m68k.cycles;
|
||||
|
||||
/* up to 4 words can be stored */
|
||||
if (fifo_write_cnt < 4)
|
||||
/* Check against last FIFO entry read-out cycle */
|
||||
if (cycles < fifo_cycles[(fifo_idx + 3) & 3])
|
||||
{
|
||||
/* Increment FIFO counter */
|
||||
fifo_write_cnt++;
|
||||
/* Check against oldest FIFO entry read-out cycle */
|
||||
if (cycles < fifo_cycles[fifo_idx])
|
||||
{
|
||||
/* FIFO is full, 68k waits until oldest FIFO entry is processed (Chaos Engine / Soldiers of Fortune, Double Clutch, Titan Overdrive Demo) */
|
||||
m68k.cycles = (((fifo_cycles[fifo_idx] + 6) / 7) * 7);
|
||||
}
|
||||
|
||||
/* Set FIFO full flag if 4 words are stored */
|
||||
status |= ((fifo_write_cnt & 4) << 6);
|
||||
/* FIFO is not empty, next FIFO entry will be processed after last FIFO entry */
|
||||
cycles = fifo_cycles[(fifo_idx + 3) & 3];
|
||||
}
|
||||
else
|
||||
{
|
||||
/* CPU is halted until next FIFO entry processing */
|
||||
m68k.cycles = fifo_cycles;
|
||||
|
||||
/* Update FIFO access slot counter */
|
||||
fifo_slots += (fifo_byte_access + 1);
|
||||
}
|
||||
/* Determine next FIFO entry processing slot */
|
||||
cycles -= mcycles_vdp;
|
||||
while (cycles >= fifo_timing[slot]) slot++;
|
||||
|
||||
/* Update last FIFO entry read-out cycle */
|
||||
fifo_cycles[fifo_idx] = mcycles_vdp + fifo_timing[slot + fifo_byte_access];
|
||||
}
|
||||
|
||||
/* Check destination code */
|
||||
|
@ -2421,40 +2367,39 @@ static void vdp_68k_data_w_m5(unsigned int data)
|
|||
/* Restricted VDP writes during active display */
|
||||
if (!(status & 8) && (reg[1] & 0x40))
|
||||
{
|
||||
/* Update VDP FIFO */
|
||||
vdp_fifo_update(m68k.cycles);
|
||||
int slot = 0;
|
||||
|
||||
/* Clear FIFO empty flag */
|
||||
status &= 0xFDFF;
|
||||
/* Cycle-accurate VDP data port access */
|
||||
int cycles = m68k.cycles;
|
||||
|
||||
/* up to 4 words can be stored */
|
||||
if (fifo_write_cnt < 4)
|
||||
/* Check against last FIFO entry read-out cycle */
|
||||
if (cycles < fifo_cycles[(fifo_idx + 3) & 3])
|
||||
{
|
||||
/* Increment FIFO counter */
|
||||
fifo_write_cnt++;
|
||||
/* Check against oldest FIFO entry read-out cycle */
|
||||
if (cycles < fifo_cycles[fifo_idx])
|
||||
{
|
||||
/* FIFO is full, 68k waits until oldest FIFO entry is processed (Chaos Engine / Soldiers of Fortune, Double Clutch, Titan Overdrive Demo) */
|
||||
m68k.cycles = (((fifo_cycles[fifo_idx] + 6) / 7) * 7);
|
||||
}
|
||||
|
||||
/* Set FIFO full flag if 4 words are stored */
|
||||
status |= ((fifo_write_cnt & 4) << 6);
|
||||
/* FIFO is not empty, next FIFO entry will be processed after last FIFO entry */
|
||||
cycles = fifo_cycles[(fifo_idx + 3) & 3];
|
||||
}
|
||||
else
|
||||
{
|
||||
/* CPU is halted until next FIFO entry processing (Chaos Engine / Soldiers of Fortune, Double Clutch, Titan Overdrive Demo) */
|
||||
m68k.cycles = fifo_cycles;
|
||||
|
||||
/* Update FIFO access slot counter */
|
||||
fifo_slots += (fifo_byte_access + 1);
|
||||
}
|
||||
/* Determine next FIFO entry processing slot */
|
||||
cycles -= mcycles_vdp;
|
||||
while (cycles >= fifo_timing[slot]) slot++;
|
||||
|
||||
/* Update last FIFO entry read-out cycle */
|
||||
fifo_cycles[fifo_idx] = mcycles_vdp + fifo_timing[slot + fifo_byte_access];
|
||||
}
|
||||
|
||||
|
||||
/* Write data */
|
||||
vdp_bus_w(data);
|
||||
|
||||
/* Check if DMA Fill is pending */
|
||||
if (dmafill)
|
||||
{
|
||||
/* Clear DMA Fill pending flag */
|
||||
dmafill = 0;
|
||||
|
||||
/* DMA length */
|
||||
dma_length = (reg[20] << 8) | reg[19];
|
||||
|
||||
|
@ -2464,11 +2409,11 @@ static void vdp_68k_data_w_m5(unsigned int data)
|
|||
dma_length = 0x10000;
|
||||
}
|
||||
|
||||
/* Take into account initial data word processing */
|
||||
dma_length += 2;
|
||||
|
||||
/* Trigger DMA */
|
||||
vdp_dma_update(m68k.cycles);
|
||||
|
||||
/* Clear DMA Fill pending flag */
|
||||
dmafill = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3190,7 +3135,7 @@ static void vdp_dma_fill(unsigned int length)
|
|||
{
|
||||
int name;
|
||||
|
||||
/* Get source data from last written FIFO entry */
|
||||
/* Get source data from last written FIFO entry */
|
||||
uint8 data = fifo[(fifo_idx+3)&3] >> 8;
|
||||
|
||||
do
|
||||
|
|
|
@ -78,8 +78,7 @@ extern uint16 vc_max;
|
|||
extern uint16 vscroll;
|
||||
extern uint16 lines_per_frame;
|
||||
extern uint16 max_sprite_pixels;
|
||||
extern int32 fifo_write_cnt;
|
||||
extern uint32 fifo_slots;
|
||||
extern uint32 fifo_cycles[4];
|
||||
extern uint32 hvc_latch;
|
||||
extern uint32 vint_cycle;
|
||||
extern const uint8 *hctab;
|
||||
|
|
|
@ -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 */
|
||||
|
|
BIN
gx/images/ctrl_retrousb.png
Normal file
BIN
gx/images/ctrl_retrousb.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 51 KiB |
188
gx/retrousb.c
Normal file
188
gx/retrousb.c
Normal 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
13
gx/retrousb.h
Normal 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
|
Loading…
Reference in a new issue