pad interface refractored

This commit is contained in:
red-prig 2023-06-19 20:52:25 +03:00
parent a30de1b295
commit 0511675791
5 changed files with 203 additions and 48 deletions

View File

@ -17,7 +17,7 @@ type
end;
TKbmPadInterface=class(TScePadInterface)
class function Open(index:Integer;var handle:TScePadHandle):Integer; override;
class function Open(var handle:TScePadHandle):Integer; override;
end;
TMouseAsTouchpad=class
@ -30,16 +30,10 @@ type
implementation
class function TKbmPadInterface.Open(index:Integer;var handle:TScePadHandle):Integer;
class function TKbmPadInterface.Open(var handle:TScePadHandle):Integer;
begin
Result:=0;
if (index<0) or (index>15) then Exit(SCE_PAD_ERROR_INVALID_ARG);
if (pad_opened[index]<>nil) then Exit(SCE_PAD_ERROR_ALREADY_OPENED);
handle:=TKbmPadHandle.Create;
TKbmPadHandle(handle).index:=index;
pad_opened[index]:=handle;
end;
function GetAsyncKeyState(vKey:longint):Boolean; inline;

View File

@ -6,13 +6,16 @@ interface
uses
sce_pad_types,
ps4_handles;
ps4_handles,
spinlock;
type
TScePadHandle=class(TClassHandle)
var
userID:Integer;
_type :Integer;
index :Integer;
handle:Integer;
index:Integer;
function ReadState(data:PScePadData):Integer; virtual;
function SetLightBar(data:pScePadLightBarParam):Integer; virtual;
function ResetLightBar():Integer; virtual;
@ -24,7 +27,7 @@ type
class procedure Unload; virtual;
class function Init:Integer; virtual;
class function Done:Integer; virtual;
class function Open(index:Integer;var handle:TScePadHandle):Integer; virtual;
class function Open(var handle:TScePadHandle):Integer; virtual;
end;
TAbstractScePadInterface=class of TScePadInterface;
@ -32,9 +35,49 @@ type
var
pad_handles:TIntegerHandles;
pad_opened :array[0..15] of TScePadHandle;
pad_lock :Pointer;
function FindPadByParam(userID,_type,index:Integer):TScePadHandle;
Procedure SavePadHandle(handle:TScePadHandle);
implementation
function FindPadByParam(userID,_type,index:Integer):TScePadHandle;
var
i:Integer;
begin
Result:=nil;
spin_lock(pad_lock);
For i:=Low(pad_opened) to High(pad_opened) do
if (pad_opened[i]<>nil) then
if (pad_opened[i].userID=userID) and
(pad_opened[i]._type =_type ) and
(pad_opened[i].index =index ) then
begin
Result:=pad_opened[i];
Result.Acqure;
spin_unlock(pad_lock);
Exit;
end;
spin_unlock(pad_lock);
end;
Procedure SavePadHandle(handle:TScePadHandle);
var
i:Integer;
begin
spin_lock(pad_lock);
For i:=Low(pad_opened) to High(pad_opened) do
if (pad_opened[i]=nil) then
begin
pad_opened[i]:=handle;
spin_unlock(pad_lock);
Exit;
end;
spin_unlock(pad_lock);
end;
function TScePadHandle.ReadState(data:PScePadData):Integer;
begin
Result:=SCE_PAD_ERROR_INVALID_HANDLE;
@ -51,11 +94,16 @@ begin
end;
destructor TScePadHandle.Destroy;
var
i:Integer;
begin
if (index>=0) and (index<16) then
begin
pad_opened[index]:=nil;
end;
For i:=Low(pad_opened) to High(pad_opened) do
if (pad_opened[i]=Self) then
begin
pad_opened[i]:=nil;
Break;
end;
//
inherited;
end;
@ -80,7 +128,7 @@ begin
Result:=0;
end;
class function TScePadInterface.Open(index:Integer;var handle:TScePadHandle):Integer;
class function TScePadInterface.Open(var handle:TScePadHandle):Integer;
begin
handle:=nil;
Result:=SCE_PAD_ERROR_NOT_INITIALIZED;

View File

@ -6,6 +6,7 @@ interface
uses
sysutils,
spinlock,
sdl2,
sce_pad_types,
sce_pad_interface,
@ -29,7 +30,7 @@ type
class procedure Unload; override;
class function Init:Integer; override;
class function Done:Integer; override;
class function Open(index:Integer;var handle:TScePadHandle):Integer; override;
class function Open(var handle:TScePadHandle):Integer; override;
class function FindOpened(device_index:Integer;prev:PSDL_GameController):Boolean;
class function FindDevice(prev:PSDL_GameController):PSDL_GameController;
end;
@ -105,6 +106,7 @@ var
h:TSdl2PadHandle;
begin
Result:=False;
spin_lock(pad_lock);
For i:=0 to 15 do
if (pad_opened[i]<>nil) then
if (pad_opened[i].InheritsFrom(TSdl2PadHandle)) then
@ -117,6 +119,7 @@ begin
if Result then Break;
end;
end;
spin_unlock(pad_lock);
end;
class function TSdl2PadInterface.FindDevice(prev:PSDL_GameController):PSDL_GameController;
@ -155,23 +158,18 @@ begin
SDL_UnlockJoysticks;
end;
class function TSdl2PadInterface.Open(index:Integer;var handle:TScePadHandle):Integer;
class function TSdl2PadInterface.Open(var handle:TScePadHandle):Integer;
var
game_controller:PSDL_GameController;
begin
Result:=0;
if not sdl2_init then Exit(SCE_PAD_ERROR_NOT_INITIALIZED);
if (index<0) or (index>15) then Exit(SCE_PAD_ERROR_INVALID_ARG);
if (pad_opened[index]<>nil) then Exit(SCE_PAD_ERROR_ALREADY_OPENED);
game_controller:=FindDevice(nil);
handle:=TSdl2PadHandle.Create;
TSdl2PadHandle(handle).index:=index;
TSdl2PadHandle(handle).game_controller:=game_controller;
pad_opened[index]:=handle;
Writeln('----------------------------------------------------------------------------------------');
Writeln('----------------------------------------------------------------------------------------');
Writeln('SDL2: Game Controller loaded!');

View File

@ -6,6 +6,7 @@ interface
uses
sysutils,
spinlock,
XInput,
sce_pad_types,
sce_pad_interface,
@ -14,6 +15,7 @@ uses
type
TXInputPadHandle=class(TScePadHandle)
var
UserIndex :Integer;
connected :Boolean;
connectedCount:Byte;
function ReadState(data:PScePadData):Integer; override;
@ -26,7 +28,9 @@ type
class procedure Unload; override;
class function Init:Integer; override;
class function Done:Integer; override;
class function Open(index:Integer;var handle:TScePadHandle):Integer; override;
class function FindOpened(UserIndex,prev:Integer):Boolean;
class function FindDevice(prev:Integer):Integer;
class function Open(var handle:TScePadHandle):Integer; override;
end;
implementation
@ -79,52 +83,136 @@ begin
Result:=0;
end;
class function TXInputPadInterface.Open(index:Integer;var handle:TScePadHandle):Integer;
class function TXInputPadInterface.FindOpened(UserIndex,prev:Integer):Boolean;
var
i:Integer;
h:TXInputPadHandle;
begin
Result:=False;
spin_lock(pad_lock);
For i:=0 to 15 do
if (pad_opened[i]<>nil) then
if (pad_opened[i].InheritsFrom(TXInputPadHandle)) then
begin
h:=TXInputPadHandle(pad_opened[i]);
if (h.UserIndex<>prev) then
begin
Result:=(UserIndex=h.UserIndex);
if Result then Break;
end;
end;
spin_unlock(pad_lock);
end;
class function TXInputPadInterface.FindDevice(prev:Integer):Integer;
var
cs:TXInputState;
i:Integer;
first,compared:Integer;
begin
Result:=-1;
first:=-1;
compared:=-1;
cs:=Default(TXInputState);
For i:=0 to XUSER_MAX_COUNT-1 do
if (XInputGetState(i, cs)=0) then
if not FindOpened(i,prev) then
begin
if (first=-1) then first:=i;
if (prev=-1) then
begin
compared:=i;
Break;
end else
if (i=prev) then
begin
compared:=i;
Break;
end;
end;
//
if (compared=-1) then compared:=first;
if (compared<>-1) then
begin
Result:=compared;
end;
end;
class function TXInputPadInterface.Open(var handle:TScePadHandle):Integer;
var
UserIndex:Integer;
begin
Result:=0;
if (index<0) or (index>15) then Exit(SCE_PAD_ERROR_INVALID_ARG);
if (pad_opened[index]<>nil) then Exit(SCE_PAD_ERROR_ALREADY_OPENED);
UserIndex:=FindDevice(-1);
handle:=TXInputPadHandle.Create;
TXInputPadHandle(handle).index:=index;
pad_opened[index]:=handle;
TXInputPadHandle(handle).UserIndex:=UserIndex;
end;
function TXInputPadHandle.ReadState(data:PScePadData):Integer;
var
cs:TXInputState;
controllerIndex:DWORD;
new:Integer;
stateResult:DWORD;
procedure DoConnect(new:DWORD); inline;
begin
UserIndex:=new;
if not connected then
begin
connected:=True;
Inc(connectedCount);
end;
end;
begin
Result:=0;
if (index>=XUSER_MAX_COUNT) then
if (UserIndex=-1) then //not attached
begin
data^.connected :=False;
data^.connectedCount:=0;
Exit;
new:=TXInputPadInterface.FindDevice(UserIndex);
if (new<>-1) then
begin
//connect
DoConnect(new);
end else
begin
//not connected
data^.connected :=False;
data^.connectedCount:=0;
Exit;
end;
end;
cs:=Default(TXInputState);
stateResult:=XInputGetState(index, cs);
stateResult:=XInputGetState(UserIndex, cs);
if (stateResult=ERROR_DEVICE_NOT_CONNECTED) then
begin
//disconnect
connected:=False;
//
new:=TXInputPadInterface.FindDevice(UserIndex);
if (new<>-1) then
begin
//connect
DoConnect(new);
end else
begin
//not connected
data^.connected :=False;
data^.connectedCount:=0;
Exit;
end;
//
data^.connected :=connected;
data^.connectedCount:=connectedCount;
Exit;
end else
begin
//connect
if not connected then
begin
connected:=True;
Inc(connectedCount);
end;
DoConnect(UserIndex);
end;
data^.connected :=connected;

View File

@ -85,11 +85,29 @@ var
begin
if (ScePadInterface=nil) then Exit(SCE_PAD_ERROR_NOT_INITIALIZED);
if (_type<>SCE_PAD_PORT_TYPE_STANDARD) then Exit(SCE_PAD_ERROR_INVALID_ARG);
if (index<0) or (index>15) then Exit(SCE_PAD_ERROR_INVALID_ARG);
case _type of
SCE_PAD_PORT_TYPE_STANDARD :;
SCE_PAD_PORT_TYPE_SPECIAL :;
SCE_PAD_PORT_TYPE_REMOTE_CONTROL:;
else
Exit(SCE_PAD_ERROR_INVALID_ARG);
end;
if (_type=SCE_PAD_PORT_TYPE_REMOTE_CONTROL) and
(userID<>$FF) then {SCE_USER_SERVICE_USER_ID_SYSTEM}
begin
Exit(SCE_PAD_ERROR_INVALID_ARG);
end;
sce_handle:=FindPadByParam(userID,_type,index);
if (sce_handle<>nil) then
begin
sce_handle.Release;
Exit(SCE_PAD_ERROR_ALREADY_OPENED);
end;
sce_handle:=nil;
Result:=ScePadInterface.Open(index,sce_handle);
Result:=ScePadInterface.Open(sce_handle);
if (Result<>0) then Exit;
sce_handle.SetLightBar(@DefaultPadLightBar);
@ -97,8 +115,15 @@ begin
key:=0;
if pad_handles.New(sce_handle,key) then
begin
sce_handle.userID:=userID;
sce_handle._type :=_type;
sce_handle.index :=index;
sce_handle.handle:=key;
//
SavePadHandle(sce_handle);
//
sce_handle.Release;
//
Result:=key;
end else
begin
@ -107,16 +132,18 @@ begin
end;
function ps4_scePadGetHandle(userID,_type,index:Integer):Integer; SysV_ABI_CDecl;
var
sce_handle:TScePadHandle;
begin
if (ScePadInterface=nil) then Exit(SCE_PAD_ERROR_NOT_INITIALIZED);
if (_type<>SCE_PAD_PORT_TYPE_STANDARD) then Exit(SCE_PAD_ERROR_INVALID_ARG);
sce_handle:=FindPadByParam(userID,_type,index);
if (index<0) or (index>15) then Exit(SCE_PAD_ERROR_INVALID_ARG);
if (sce_handle=nil) then Exit(SCE_PAD_ERROR_NO_HANDLE);
if (pad_opened[index]=nil) then Exit(SCE_PAD_ERROR_NO_HANDLE);
Result:=sce_handle.handle;
Result:=pad_opened[index].handle;
sce_handle.Release;
end;
function ps4_scePadClose(handle:Integer):Integer; SysV_ABI_CDecl;