From 9d7856b3e7f957aed5734cb6e0c8c8aee25e3df1 Mon Sep 17 00:00:00 2001 From: Joseph Mattiello Date: Mon, 18 Nov 2024 15:58:14 -0500 Subject: [PATCH 01/10] desmume placehold swap and rotate Signed-off-by: Joseph Mattiello --- .../Core/PVDesmume2015Core+Controls.mm | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/Cores/Desmume2015/PVDesmume2015Core/Core/PVDesmume2015Core+Controls.mm b/Cores/Desmume2015/PVDesmume2015Core/Core/PVDesmume2015Core+Controls.mm index b0f847c5fb..ea5f851c04 100644 --- a/Cores/Desmume2015/PVDesmume2015Core/Core/PVDesmume2015Core+Controls.mm +++ b/Cores/Desmume2015/PVDesmume2015Core/Core/PVDesmume2015Core+Controls.mm @@ -140,7 +140,30 @@ - (void)initControllBuffers { // } //} +- (void)screenSwap { + // TODO +} + +- (void)screenRotate { +/* + #define LAYOUT_TOP_BOTTOM 0 + #define LAYOUT_BOTTOM_TOP 1 + #define LAYOUT_LEFT_RIGHT 2 + #define LAYOUT_RIGHT_LEFT 3 + #define LAYOUT_TOP_ONLY 4 + #define LAYOUT_BOTTOM_ONLY 5 + #define LAYOUT_HYBRID_TOP_ONLY 6 + #define LAYOUT_HYBRID_BOTTOM_ONLY 7 + */ + +} + -(void)didPushDSButton:(enum PVDSButton)button forPlayer:(NSInteger)player { + if (button == PVDSButtonScreenSwap) { + [self screenSwap]; + } else if (button == PVDSButtonRotate) { + [self screenRotate]; + } // if (button == PVDSButtonL) { // lt[player] |= 0xff * true; // } else if (button == PVDSButtonR) { From f14f10d4b86332180bc1282d5c4e3b1a8d2b617c Mon Sep 17 00:00:00 2001 From: Joseph Mattiello Date: Mon, 18 Nov 2024 16:57:48 -0500 Subject: [PATCH 02/10] hacky way of doing screen swap with direct var access Signed-off-by: Joseph Mattiello --- .../Core/PVDesmume2015Core+Controls.mm | 99 ++++--------------- 1 file changed, 17 insertions(+), 82 deletions(-) diff --git a/Cores/Desmume2015/PVDesmume2015Core/Core/PVDesmume2015Core+Controls.mm b/Cores/Desmume2015/PVDesmume2015Core/Core/PVDesmume2015Core+Controls.mm index ea5f851c04..98c8a4fc5c 100644 --- a/Cores/Desmume2015/PVDesmume2015Core/Core/PVDesmume2015Core+Controls.mm +++ b/Cores/Desmume2015/PVDesmume2015Core/Core/PVDesmume2015Core+Controls.mm @@ -10,56 +10,14 @@ #import @import PVCoreBridge; @import PVCoreObjCBridge; +#import "NDSSystem.h" -#define DC_BTN_C (1<<0) -#define DC_BTN_B (1<<1) -#define DC_BTN_A (1<<2) -#define DC_BTN_START (1<<3) -#define DC_DPAD_UP (1<<4) -#define DC_DPAD_DOWN (1<<5) -#define DC_DPAD_LEFT (1<<6) -#define DC_DPAD_RIGHT (1<<7) -#define DC_BTN_Z (1<<8) -#define DC_BTN_Y (1<<9) -#define DC_BTN_X (1<<10) -#define DC_BTN_D (1<<11) -#define DC_DPAD2_UP (1<<12) -#define DC_DPAD2_DOWN (1<<13) -#define DC_DPAD2_LEFT (1<<14) -#define DC_DPAD2_RIGHT (1<<15) - -#define DC_AXIS_LT (0X10000) -#define DC_AXIS_RT (0X10001) -#define DC_AXIS_X (0X20000) -#define DC_AXIS_Y (0X20001) - -static const int DSMap[] = { - DC_DPAD_UP, DC_DPAD_DOWN, DC_DPAD_LEFT, DC_DPAD_RIGHT, - DC_BTN_A, DC_BTN_B, DC_BTN_X, DC_BTN_Y, - DC_AXIS_LT, DC_AXIS_RT, - DC_BTN_START -}; - -typedef unsigned char u8; -typedef signed char s8; -typedef unsigned short u16; -typedef unsigned int u32; - - // Desmume2015 controller data -//u16 kcode[4]; -//u8 rt[4]; -//u8 lt[4]; -//u32 vks[4]; -//s8 joyx[4], joyy[4]; +#include "libretro.h" +extern retro_log_printf_t log_cb; +extern retro_environment_t environ_cb; @implementation PVDesmume2015CoreBridge (Controls) -- (void)initControllBuffers { -// memset(&kcode, 0xFFFF, sizeof(kcode)); -// bzero(&rt, sizeof(rt)); -// bzero(<, sizeof(lt)); -} - #pragma mark - Control // //- (void)pollControllers { @@ -145,17 +103,15 @@ - (void)screenSwap { } - (void)screenRotate { -/* - #define LAYOUT_TOP_BOTTOM 0 - #define LAYOUT_BOTTOM_TOP 1 - #define LAYOUT_LEFT_RIGHT 2 - #define LAYOUT_RIGHT_LEFT 3 - #define LAYOUT_TOP_ONLY 4 - #define LAYOUT_BOTTOM_ONLY 5 - #define LAYOUT_HYBRID_TOP_ONLY 6 - #define LAYOUT_HYBRID_BOTTOM_ONLY 7 - */ - + /// Current layout state stored as static to persist between calls + static int currentLayout = LAYOUT_TOP_BOTTOM; + + /// Cycle through the layouts in a logical order + currentLayout = (currentLayout + 1) % 8; + + /// Update the global layout variable used by desmume + extern int current_layout; + current_layout = currentLayout; } -(void)didPushDSButton:(enum PVDSButton)button forPlayer:(NSInteger)player { @@ -164,37 +120,16 @@ -(void)didPushDSButton:(enum PVDSButton)button forPlayer:(NSInteger)player { } else if (button == PVDSButtonRotate) { [self screenRotate]; } -// if (button == PVDSButtonL) { -// lt[player] |= 0xff * true; -// } else if (button == PVDSButtonR) { -// rt[player] |= 0xff * true; -// } else { -// int mapped = DSMap[button]; -// kcode[player] &= ~(mapped); -// } } -(void)didReleaseDSButton:(enum PVDSButton)button forPlayer:(NSInteger)player { -// if (button == PVDSButtonL) { -// lt[player] |= 0xff * false; -// } else if (button == PVDSButtonR) { -// rt[player] |= 0xff * false; -// } else { -// int mapped = DSMap[button]; -// kcode[player] |= (mapped); -// } + } -- (void)didMoveDSJoystickDirection:(enum PVDSButton)button withValue:(CGFloat)value forPlayer:(NSInteger)player { - /* - float xvalue = gamepad.leftThumbstick.xAxis.value; - s8 x=(s8)(xvalue*127); - joyx[0] = x; +- (void)didMoveDSJoystickDirection:(enum PVDSButton)button + withValue:(CGFloat)value + forPlayer:(NSInteger)player { - float yvalue = gamepad.leftThumbstick.yAxis.value; - s8 y=(s8)(yvalue*127 * - 1); //-127 ... + 127 range - joyy[0] = y; - */ } -(void)didMoveJoystick:(NSInteger)button withValue:(CGFloat)value forPlayer:(NSInteger)player { From c140cd6e8ef41d702032cc9839ef2f89683d837f Mon Sep 17 00:00:00 2001 From: Joseph Mattiello Date: Mon, 18 Nov 2024 17:06:27 -0500 Subject: [PATCH 03/10] desmume better screen rotate, start of buttons Signed-off-by: Joseph Mattiello --- .../Core/PVDesmume2015Core+Controls.mm | 145 +++++++++++++++++- 1 file changed, 144 insertions(+), 1 deletion(-) diff --git a/Cores/Desmume2015/PVDesmume2015Core/Core/PVDesmume2015Core+Controls.mm b/Cores/Desmume2015/PVDesmume2015Core/Core/PVDesmume2015Core+Controls.mm index 98c8a4fc5c..44e71814b5 100644 --- a/Cores/Desmume2015/PVDesmume2015Core/Core/PVDesmume2015Core+Controls.mm +++ b/Cores/Desmume2015/PVDesmume2015Core/Core/PVDesmume2015Core+Controls.mm @@ -109,21 +109,164 @@ - (void)screenRotate { /// Cycle through the layouts in a logical order currentLayout = (currentLayout + 1) % 8; - /// Update the global layout variable used by desmume + /// Map our layout enum to the string values expected by desmume + const char *layoutValue; + switch(currentLayout) { + case LAYOUT_TOP_BOTTOM: + layoutValue = "top/bottom"; + break; + case LAYOUT_BOTTOM_TOP: + layoutValue = "bottom/top"; + break; + case LAYOUT_LEFT_RIGHT: + layoutValue = "left/right"; + break; + case LAYOUT_RIGHT_LEFT: + layoutValue = "right/left"; + break; + case LAYOUT_TOP_ONLY: + layoutValue = "top only"; + break; + case LAYOUT_BOTTOM_ONLY: + layoutValue = "bottom only"; + break; + case LAYOUT_HYBRID_TOP_ONLY: + layoutValue = "hybrid/top"; + break; + case LAYOUT_HYBRID_BOTTOM_ONLY: + layoutValue = "hybrid/bottom"; + break; + } + + /// Override the getVariable response for screen layout extern int current_layout; current_layout = currentLayout; + + /// Force a check of variables on next frame + bool updated = true; + environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE, &updated); } -(void)didPushDSButton:(enum PVDSButton)button forPlayer:(NSInteger)player { + /// Handle special cases first if (button == PVDSButtonScreenSwap) { [self screenSwap]; + return; } else if (button == PVDSButtonRotate) { [self screenRotate]; + return; + } + + /// Map PVDSButton to NDS button states + bool R = false, L = false, D = false, U = false, T = false; + bool S = false, B = false, A = false, Y = false, X = false; + bool W = false, E = false, G = false, F = false; + + switch(button) { + case PVDSButtonUp: + U = true; + break; + case PVDSButtonDown: + D = true; + break; + case PVDSButtonLeft: + L = true; + break; + case PVDSButtonRight: + R = true; + break; + case PVDSButtonA: + A = true; + break; + case PVDSButtonB: + B = true; + break; + case PVDSButtonX: + X = true; + break; + case PVDSButtonY: + Y = true; + break; + case PVDSButtonL: + W = true; /// Left shoulder is W in desmume + break; + case PVDSButtonR: + E = true; /// Right shoulder is E in desmume + break; + case PVDSButtonStart: + S = true; + break; + case PVDSButtonSelect: + T = true; + break; + default: + break; } + + /// Set the button states in desmume + NDS_setPad(R, L, D, U, T, S, B, A, Y, X, W, E, G, F); } -(void)didReleaseDSButton:(enum PVDSButton)button forPlayer:(NSInteger)player { + /// Handle special cases first + if (button == PVDSButtonScreenSwap || button == PVDSButtonRotate) { + return; + } + + /// Get current button states from desmume + const UserInput& currentInput = NDS_getRawUserInput(); + const UserButtons& buttons = currentInput.buttons; + + /// Map current states, but set the released button to false + bool R = buttons.R, L = buttons.L, D = buttons.D, U = buttons.U; + bool T = buttons.T, S = buttons.S, B = buttons.B, A = buttons.A; + bool Y = buttons.Y, X = buttons.X, W = buttons.W, E = buttons.E; + bool G = buttons.G, F = buttons.F; + + /// Update the released button's state + switch(button) { + case PVDSButtonUp: + U = false; + break; + case PVDSButtonDown: + D = false; + break; + case PVDSButtonLeft: + L = false; + break; + case PVDSButtonRight: + R = false; + break; + case PVDSButtonA: + A = false; + break; + case PVDSButtonB: + B = false; + break; + case PVDSButtonX: + X = false; + break; + case PVDSButtonY: + Y = false; + break; + case PVDSButtonL: + W = false; /// Left shoulder is W in desmume + break; + case PVDSButtonR: + E = false; /// Right shoulder is E in desmume + break; + case PVDSButtonStart: + S = false; + break; + case PVDSButtonSelect: + T = false; + break; + default: + break; + } + /// Update button states in desmume + NDS_setPad(R, L, D, U, T, S, B, A, Y, X, W, E, G, F); } - (void)didMoveDSJoystickDirection:(enum PVDSButton)button From b7509a0f884b67245cdafb8927f3940e58ac6878 Mon Sep 17 00:00:00 2001 From: Joseph Mattiello Date: Mon, 18 Nov 2024 17:56:41 -0500 Subject: [PATCH 04/10] desmume2015 controls work Signed-off-by: Joseph Mattiello --- .../Core/PVDesmume2015Core+Controls.mm | 92 ++++++++----------- 1 file changed, 40 insertions(+), 52 deletions(-) diff --git a/Cores/Desmume2015/PVDesmume2015Core/Core/PVDesmume2015Core+Controls.mm b/Cores/Desmume2015/PVDesmume2015Core/Core/PVDesmume2015Core+Controls.mm index 44e71814b5..15e5232344 100644 --- a/Cores/Desmume2015/PVDesmume2015Core/Core/PVDesmume2015Core+Controls.mm +++ b/Cores/Desmume2015/PVDesmume2015Core/Core/PVDesmume2015Core+Controls.mm @@ -149,124 +149,112 @@ - (void)screenRotate { -(void)didPushDSButton:(enum PVDSButton)button forPlayer:(NSInteger)player { /// Handle special cases first - if (button == PVDSButtonScreenSwap) { - [self screenSwap]; - return; - } else if (button == PVDSButtonRotate) { - [self screenRotate]; + if (button == PVDSButtonScreenSwap || button == PVDSButtonRotate) { + if (button == PVDSButtonRotate) { + [self screenRotate]; + } else { + [self screenSwap]; + } return; } - /// Map PVDSButton to NDS button states - bool R = false, L = false, D = false, U = false, T = false; - bool S = false, B = false, A = false, Y = false, X = false; - bool W = false, E = false, G = false, F = false; - + /// Map PVDSButton to RETRO_DEVICE_ID_JOYPAD values + unsigned retro_id; switch(button) { case PVDSButtonUp: - U = true; + retro_id = RETRO_DEVICE_ID_JOYPAD_UP; break; case PVDSButtonDown: - D = true; + retro_id = RETRO_DEVICE_ID_JOYPAD_DOWN; break; case PVDSButtonLeft: - L = true; + retro_id = RETRO_DEVICE_ID_JOYPAD_LEFT; break; case PVDSButtonRight: - R = true; + retro_id = RETRO_DEVICE_ID_JOYPAD_RIGHT; break; case PVDSButtonA: - A = true; + retro_id = RETRO_DEVICE_ID_JOYPAD_A; break; case PVDSButtonB: - B = true; + retro_id = RETRO_DEVICE_ID_JOYPAD_B; break; case PVDSButtonX: - X = true; + retro_id = RETRO_DEVICE_ID_JOYPAD_X; break; case PVDSButtonY: - Y = true; + retro_id = RETRO_DEVICE_ID_JOYPAD_Y; break; case PVDSButtonL: - W = true; /// Left shoulder is W in desmume + retro_id = RETRO_DEVICE_ID_JOYPAD_L; break; case PVDSButtonR: - E = true; /// Right shoulder is E in desmume + retro_id = RETRO_DEVICE_ID_JOYPAD_R; break; case PVDSButtonStart: - S = true; + retro_id = RETRO_DEVICE_ID_JOYPAD_START; break; case PVDSButtonSelect: - T = true; + retro_id = RETRO_DEVICE_ID_JOYPAD_SELECT; break; default: - break; + return; } - /// Set the button states in desmume - NDS_setPad(R, L, D, U, T, S, B, A, Y, X, W, E, G, F); + /// Update the pad state directly + _pad[player][retro_id] = 1; } -(void)didReleaseDSButton:(enum PVDSButton)button forPlayer:(NSInteger)player { - /// Handle special cases first + /// Handle special cases if (button == PVDSButtonScreenSwap || button == PVDSButtonRotate) { return; } - /// Get current button states from desmume - const UserInput& currentInput = NDS_getRawUserInput(); - const UserButtons& buttons = currentInput.buttons; - - /// Map current states, but set the released button to false - bool R = buttons.R, L = buttons.L, D = buttons.D, U = buttons.U; - bool T = buttons.T, S = buttons.S, B = buttons.B, A = buttons.A; - bool Y = buttons.Y, X = buttons.X, W = buttons.W, E = buttons.E; - bool G = buttons.G, F = buttons.F; - - /// Update the released button's state + /// Map and update pad state + unsigned retro_id; switch(button) { case PVDSButtonUp: - U = false; + retro_id = RETRO_DEVICE_ID_JOYPAD_UP; break; case PVDSButtonDown: - D = false; + retro_id = RETRO_DEVICE_ID_JOYPAD_DOWN; break; case PVDSButtonLeft: - L = false; + retro_id = RETRO_DEVICE_ID_JOYPAD_LEFT; break; case PVDSButtonRight: - R = false; + retro_id = RETRO_DEVICE_ID_JOYPAD_RIGHT; break; case PVDSButtonA: - A = false; + retro_id = RETRO_DEVICE_ID_JOYPAD_A; break; case PVDSButtonB: - B = false; + retro_id = RETRO_DEVICE_ID_JOYPAD_B; break; case PVDSButtonX: - X = false; + retro_id = RETRO_DEVICE_ID_JOYPAD_X; break; case PVDSButtonY: - Y = false; + retro_id = RETRO_DEVICE_ID_JOYPAD_Y; break; case PVDSButtonL: - W = false; /// Left shoulder is W in desmume + retro_id = RETRO_DEVICE_ID_JOYPAD_L; break; case PVDSButtonR: - E = false; /// Right shoulder is E in desmume + retro_id = RETRO_DEVICE_ID_JOYPAD_R; break; case PVDSButtonStart: - S = false; + retro_id = RETRO_DEVICE_ID_JOYPAD_START; break; case PVDSButtonSelect: - T = false; + retro_id = RETRO_DEVICE_ID_JOYPAD_SELECT; break; default: - break; + return; } - /// Update button states in desmume - NDS_setPad(R, L, D, U, T, S, B, A, Y, X, W, E, G, F); + _pad[player][retro_id] = 0; } - (void)didMoveDSJoystickDirection:(enum PVDSButton)button From f2b949929e043ca83696baba6b12cd31ee87a291 Mon Sep 17 00:00:00 2001 From: Joseph Mattiello Date: Mon, 18 Nov 2024 19:03:09 -0500 Subject: [PATCH 05/10] =?UTF-8?q?desmume2015,=20controls=20works,=20rotate?= =?UTF-8?q?=20doesn=E2=80=99t=20crash?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Joseph Mattiello --- .../Core/PVDesmume2015Core+Controls.mm | 114 ++++++------------ .../Core/PVDesmume2015Core+Video.m | 114 +++++++++--------- 2 files changed, 94 insertions(+), 134 deletions(-) diff --git a/Cores/Desmume2015/PVDesmume2015Core/Core/PVDesmume2015Core+Controls.mm b/Cores/Desmume2015/PVDesmume2015Core/Core/PVDesmume2015Core+Controls.mm index 15e5232344..df26d5a906 100644 --- a/Cores/Desmume2015/PVDesmume2015Core/Core/PVDesmume2015Core+Controls.mm +++ b/Cores/Desmume2015/PVDesmume2015Core/Core/PVDesmume2015Core+Controls.mm @@ -10,96 +10,45 @@ #import @import PVCoreBridge; @import PVCoreObjCBridge; -#import "NDSSystem.h" +// Desmume 2015 +#include "NDSSystem.h" +// Retroarch #include "libretro.h" + +// Retro arch globals extern retro_log_printf_t log_cb; extern retro_environment_t environ_cb; @implementation PVDesmume2015CoreBridge (Controls) #pragma mark - Control -// -//- (void)pollControllers { -// for (NSInteger playerIndex = 0; playerIndex < 4; playerIndex++) -// { -// GCController *controller = nil; -// -// if (self.controller1 && playerIndex == 0) -// { -// controller = self.controller1; -// } -// else if (self.controller2 && playerIndex == 1) -// { -// controller = self.controller2; -// } -// else if (self.controller3 && playerIndex == 3) -// { -// controller = self.controller3; -// } -// else if (self.controller4 && playerIndex == 4) -// { -// controller = self.controller4; -// } -// -// if ([controller extendedGamepad]) -// { -// GCExtendedGamepad *gamepad = [controller extendedGamepad]; -// GCControllerDirectionPad *dpad = [gamepad dpad]; -// -// dpad.up.isPressed ? kcode[playerIndex] &= ~(DC_DPAD_UP) : kcode[playerIndex] |= (DC_DPAD_UP); -// dpad.down.isPressed ? kcode[playerIndex] &= ~(DC_DPAD_DOWN) : kcode[playerIndex] |= (DC_DPAD_DOWN); -// dpad.left.isPressed ? kcode[playerIndex] &= ~(DC_DPAD_LEFT) : kcode[playerIndex] |= (DC_DPAD_LEFT); -// dpad.right.isPressed ? kcode[playerIndex] &= ~(DC_DPAD_RIGHT) : kcode[playerIndex] |= (DC_DPAD_RIGHT); -// -// gamepad.buttonA.isPressed ? kcode[playerIndex] &= ~(DC_BTN_A) : kcode[playerIndex] |= (DC_BTN_A); -// gamepad.buttonB.isPressed ? kcode[playerIndex] &= ~(DC_BTN_B) : kcode[playerIndex] |= (DC_BTN_B); -// gamepad.buttonX.isPressed ? kcode[playerIndex] &= ~(DC_BTN_X) : kcode[playerIndex] |= (DC_BTN_X); -// gamepad.buttonY.isPressed ? kcode[playerIndex] &= ~(DC_BTN_Y) : kcode[playerIndex] |= (DC_BTN_Y); -// -// gamepad.leftShoulder.isPressed ? kcode[playerIndex] &= ~(DC_AXIS_LT) : kcode[playerIndex] |= (DC_AXIS_LT); -// gamepad.rightShoulder.isPressed ? kcode[playerIndex] &= ~(DC_AXIS_RT) : kcode[playerIndex] |= (DC_AXIS_RT); -// -// gamepad.leftTrigger.isPressed ? kcode[playerIndex] &= ~(DC_BTN_Z) : kcode[playerIndex] |= (DC_BTN_Z); -// gamepad.rightTrigger.isPressed ? kcode[playerIndex] &= ~(DC_BTN_START) : kcode[playerIndex] |= (DC_BTN_START); -// -// -// float xvalue = gamepad.leftThumbstick.xAxis.value; -// s8 x=(s8)(xvalue*127); -// joyx[0] = x; -// -// float yvalue = gamepad.leftThumbstick.yAxis.value; -// s8 y=(s8)(yvalue*127 * - 1); //-127 ... + 127 range -// joyy[0] = y; -// -// } else if ([controller gamepad]) { -// GCGamepad *gamepad = [controller gamepad]; -// GCControllerDirectionPad *dpad = [gamepad dpad]; -// -// dpad.up.isPressed ? kcode[playerIndex] &= ~(DC_DPAD_UP) : kcode[playerIndex] |= (DC_DPAD_UP); -// dpad.down.isPressed ? kcode[playerIndex] &= ~(DC_DPAD_DOWN) : kcode[playerIndex] |= (DC_DPAD_DOWN); -// dpad.left.isPressed ? kcode[playerIndex] &= ~(DC_DPAD_LEFT) : kcode[playerIndex] |= (DC_DPAD_LEFT); -// dpad.right.isPressed ? kcode[playerIndex] &= ~(DC_DPAD_RIGHT) : kcode[playerIndex] |= (DC_DPAD_RIGHT); -// -// gamepad.buttonA.isPressed ? kcode[playerIndex] &= ~(DC_BTN_A) : kcode[playerIndex] |= (DC_BTN_A); -// gamepad.buttonB.isPressed ? kcode[playerIndex] &= ~(DC_BTN_B) : kcode[playerIndex] |= (DC_BTN_B); -// gamepad.buttonX.isPressed ? kcode[playerIndex] &= ~(DC_BTN_X) : kcode[playerIndex] |= (DC_BTN_X); -// gamepad.buttonY.isPressed ? kcode[playerIndex] &= ~(DC_BTN_Y) : kcode[playerIndex] |= (DC_BTN_Y); -// -// gamepad.leftShoulder.isPressed ? kcode[playerIndex] &= ~(DC_AXIS_LT) : kcode[playerIndex] |= (DC_AXIS_LT); -// gamepad.rightShoulder.isPressed ? kcode[playerIndex] &= ~(DC_AXIS_RT) : kcode[playerIndex] |= (DC_AXIS_RT); -// } -//#if TARGET_OS_TV -// else if ([controller microGamepad]) { -// GCMicroGamepad *gamepad = [controller microGamepad]; -// GCControllerDirectionPad *dpad = [gamepad dpad]; -// } -//#endif -// } -//} - (void)screenSwap { - // TODO + /// Get current layout through environment callback + struct retro_variable var = { "desmume_screens_layout", NULL }; + environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var); + + /// Determine current layout from variable value + const char *new_layout; + if (strstr(var.value, "top only")) + new_layout = "bottom only"; + else if (strstr(var.value, "bottom only")) + new_layout = "top only"; + else if (strstr(var.value, "hybrid/top")) + new_layout = "hybrid/bottom"; + else if (strstr(var.value, "hybrid/bottom")) + new_layout = "hybrid/top"; + else + new_layout = "top only"; // Default fallback + + /// Set new layout through environment callback + var.value = new_layout; + environ_cb(RETRO_ENVIRONMENT_SET_VARIABLE, &var); + + /// Force a check of variables on next frame + bool updated = true; + environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE, &updated); } - (void)screenRotate { @@ -275,4 +224,9 @@ - (void)didRelease:(NSInteger)button forPlayer:(NSInteger)player { [self didReleaseDSButton:(PVDSButton)button forPlayer:player]; } +// Touch Screen controls +-(void)sendEvent:(UIEvent * _Nullable)event { + [super sendEvent:event]; +} + @end diff --git a/Cores/Desmume2015/PVDesmume2015Core/Core/PVDesmume2015Core+Video.m b/Cores/Desmume2015/PVDesmume2015Core/Core/PVDesmume2015Core+Video.m index 4b04bb2bf1..51ff698634 100644 --- a/Cores/Desmume2015/PVDesmume2015Core/Core/PVDesmume2015Core+Video.m +++ b/Cores/Desmume2015/PVDesmume2015Core/Core/PVDesmume2015Core+Video.m @@ -10,6 +10,11 @@ #import "PVDesmume2015Core.h" #import +#include "libretro.h" + +extern retro_environment_t environ_cb; +extern unsigned GPU_LR_FRAMEBUFFER_NATIVE_WIDTH; +extern unsigned GPU_LR_FRAMEBUFFER_NATIVE_HEIGHT; #if !__has_include() #import @@ -19,6 +24,7 @@ #import #import #endif + @implementation PVDesmume2015CoreBridge (Video) # pragma mark - Methods @@ -45,61 +51,65 @@ @implementation PVDesmume2015CoreBridge (Video) # pragma mark - Properties -//- (CGSize)bufferSize { -// CGSize size = CGSizeMake(av_info.geometry.max_width, av_info.geometry.max_height); -// DLOG(@"<%i, %i>", size.width, size.height); -// return size; -//} -//- (CGRect)screenRect { -// CGRect rect = CGRectMake(0, 0, av_info.geometry.base_width, av_info.geometry.base_height); -// DLOG(@"<%i, %i>", rect.size.width, rect.size.height * 2); -// return rect; -//} +- (CGRect)screenRect { + struct retro_variable var = { "desmume_screens_layout", NULL }; + environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var); + + unsigned width = GPU_LR_FRAMEBUFFER_NATIVE_WIDTH; + unsigned height = GPU_LR_FRAMEBUFFER_NATIVE_HEIGHT; + + if (var.value) { + if (strstr(var.value, "hybrid")) { + return CGRectMake(0, 0, width + (width/3), height); + } else if (strstr(var.value, "top only") || strstr(var.value, "bottom only")) { + return CGRectMake(0, 0, width, height); + } else if (strstr(var.value, "top/bottom") || strstr(var.value, "bottom/top")) { + return CGRectMake(0, 0, width, height * 2); + } + } + + return CGRectMake(0, 0, width, height); +} -//- (CGSize)aspectSize { -// CGSize size = CGSizeMake(1, av_info.geometry.aspect_ratio); -// DLOG(@"<%i, %i>", size.width, size.height); -// return size; -//} -// - (CGSize)bufferSize { - return CGSizeMake(2048, 2048); + struct retro_variable var = { "desmume_screens_layout", NULL }; + environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var); + + /// Base dimensions for a single DS screen + unsigned width = GPU_LR_FRAMEBUFFER_NATIVE_WIDTH; + unsigned height = GPU_LR_FRAMEBUFFER_NATIVE_HEIGHT; + + if (var.value) { + if (strstr(var.value, "hybrid")) { + /// Hybrid layout needs extra width for the small screen + return CGSizeMake(width + (width/3), height); + } else if (strstr(var.value, "top only") || strstr(var.value, "bottom only")) { + /// Single screen layout + return CGSizeMake(width, height); + } else if (strstr(var.value, "top/bottom") || strstr(var.value, "bottom/top")) { + /// Vertical layout + return CGSizeMake(width, height * 2); + } + } + + /// Default to single screen size + return CGSizeMake(width, height); } -//// -/// 1024 / 1536 -//- (CGRect)screenRect { -// return CGRectMake(0, 0, 256, 512); -//} -//// + - (CGSize)aspectSize { - return CGSizeMake(1, 2); + struct retro_variable var = { "desmume_screens_layout", NULL }; + environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var); + + if (var.value) { + if (strstr(var.value, "top only") || strstr(var.value, "bottom only")) { + return CGSizeMake(1, 1); /// Square aspect for single screen + } else if (strstr(var.value, "left/right") || strstr(var.value, "right/left")) { + return CGSizeMake(2, 1); /// 2:1 aspect for horizontal layout + } + } + + return CGSizeMake(1, 2); /// Default 1:2 aspect for vertical layout } -// -//- (BOOL)rendersToOpenGL { -// return YES; -//} -// -//- (void)swapBuffers -//{ -// if (bitmap.data == (uint8_t*)videoBufferA) -// { -// videoBuffer = videoBufferA; -// bitmap.data = (uint8_t*)videoBufferB; -// } -// else -// { -// videoBuffer = videoBufferB; -// bitmap.data = (uint8_t*)videoBufferA; -// } -//} -// -//-(BOOL)isDoubleBuffered { -// return YES; -//} - -//- (const void *)videoBuffer { -// return videoBuffer; -//} #define USE_565 0 @@ -163,8 +173,4 @@ - (GLenum)internalPixelFormat { #endif } -//- (GLenum)depthFormat { -// // 0, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT24 -// return GL_DEPTH_COMPONENT24; -//} @end From f985667ac21c790444139f7997f7bfa79baf7906 Mon Sep 17 00:00:00 2001 From: Joseph Mattiello Date: Mon, 18 Nov 2024 19:23:42 -0500 Subject: [PATCH 06/10] desmume refactor common code Signed-off-by: Joseph Mattiello --- .../Core/PVDesmume2015Core+Controls.mm | 61 ++++++++++++------- 1 file changed, 38 insertions(+), 23 deletions(-) diff --git a/Cores/Desmume2015/PVDesmume2015Core/Core/PVDesmume2015Core+Controls.mm b/Cores/Desmume2015/PVDesmume2015Core/Core/PVDesmume2015Core+Controls.mm index df26d5a906..d5087c513b 100644 --- a/Cores/Desmume2015/PVDesmume2015Core/Core/PVDesmume2015Core+Controls.mm +++ b/Cores/Desmume2015/PVDesmume2015Core/Core/PVDesmume2015Core+Controls.mm @@ -24,26 +24,10 @@ @implementation PVDesmume2015CoreBridge (Controls) #pragma mark - Control -- (void)screenSwap { - /// Get current layout through environment callback - struct retro_variable var = { "desmume_screens_layout", NULL }; - environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var); - - /// Determine current layout from variable value - const char *new_layout; - if (strstr(var.value, "top only")) - new_layout = "bottom only"; - else if (strstr(var.value, "bottom only")) - new_layout = "top only"; - else if (strstr(var.value, "hybrid/top")) - new_layout = "hybrid/bottom"; - else if (strstr(var.value, "hybrid/bottom")) - new_layout = "hybrid/top"; - else - new_layout = "top only"; // Default fallback - +- (void)updateScreenLayout:(const char *)layoutValue { /// Set new layout through environment callback - var.value = new_layout; + struct retro_variable var = { "desmume_screens_layout", NULL }; + var.value = layoutValue; environ_cb(RETRO_ENVIRONMENT_SET_VARIABLE, &var); /// Force a check of variables on next frame @@ -51,6 +35,39 @@ - (void)screenSwap { environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE, &updated); } +- (void)screenSwap { + /// Get current layout through environment callback + struct retro_variable var = { "desmume_screens_layout", NULL }; + environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var); + + /// Determine new layout based on current layout + const char *layoutValue; + if (var.value) { + if (strstr(var.value, "top/bottom")) + layoutValue = "bottom/top"; + else if (strstr(var.value, "bottom/top")) + layoutValue = "top/bottom"; + else if (strstr(var.value, "left/right")) + layoutValue = "right/left"; + else if (strstr(var.value, "right/left")) + layoutValue = "left/right"; + else if (strstr(var.value, "top only")) + layoutValue = "bottom only"; + else if (strstr(var.value, "bottom only")) + layoutValue = "top only"; + else if (strstr(var.value, "hybrid/top")) + layoutValue = "hybrid/bottom"; + else if (strstr(var.value, "hybrid/bottom")) + layoutValue = "hybrid/top"; + else + layoutValue = "top/bottom"; /// Default fallback + } else { + layoutValue = "top/bottom"; /// Default fallback + } + + [self updateScreenLayout:layoutValue]; +} + - (void)screenRotate { /// Current layout state stored as static to persist between calls static int currentLayout = LAYOUT_TOP_BOTTOM; @@ -87,13 +104,11 @@ - (void)screenRotate { break; } - /// Override the getVariable response for screen layout + /// Update current_layout for core extern int current_layout; current_layout = currentLayout; - /// Force a check of variables on next frame - bool updated = true; - environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE, &updated); + [self updateScreenLayout:layoutValue]; } -(void)didPushDSButton:(enum PVDSButton)button forPlayer:(NSInteger)player { From 9505577812ba5f9a0a807307ea363fbd58e577ed Mon Sep 17 00:00:00 2001 From: Joseph Mattiello Date: Mon, 18 Nov 2024 19:24:29 -0500 Subject: [PATCH 07/10] desmume video add logging Signed-off-by: Joseph Mattiello --- .../Core/PVDesmume2015Core+Video.m | 83 +++++++++++-------- 1 file changed, 49 insertions(+), 34 deletions(-) diff --git a/Cores/Desmume2015/PVDesmume2015Core/Core/PVDesmume2015Core+Video.m b/Cores/Desmume2015/PVDesmume2015Core/Core/PVDesmume2015Core+Video.m index 51ff698634..2551bcb65c 100644 --- a/Cores/Desmume2015/PVDesmume2015Core/Core/PVDesmume2015Core+Video.m +++ b/Cores/Desmume2015/PVDesmume2015Core/Core/PVDesmume2015Core+Video.m @@ -15,6 +15,9 @@ extern retro_environment_t environ_cb; extern unsigned GPU_LR_FRAMEBUFFER_NATIVE_WIDTH; extern unsigned GPU_LR_FRAMEBUFFER_NATIVE_HEIGHT; +extern int current_layout; +extern int hybrid_layout_scale; +extern unsigned scale; #if !__has_include() #import @@ -52,63 +55,75 @@ @implementation PVDesmume2015CoreBridge (Video) # pragma mark - Properties - (CGRect)screenRect { - struct retro_variable var = { "desmume_screens_layout", NULL }; - environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var); - - unsigned width = GPU_LR_FRAMEBUFFER_NATIVE_WIDTH; - unsigned height = GPU_LR_FRAMEBUFFER_NATIVE_HEIGHT; - - if (var.value) { - if (strstr(var.value, "hybrid")) { - return CGRectMake(0, 0, width + (width/3), height); - } else if (strstr(var.value, "top only") || strstr(var.value, "bottom only")) { - return CGRectMake(0, 0, width, height); - } else if (strstr(var.value, "top/bottom") || strstr(var.value, "bottom/top")) { - return CGRectMake(0, 0, width, height * 2); - } - } - - return CGRectMake(0, 0, width, height); + return CGRectMake(0, 0, self.bufferSize.width, self.bufferSize.height); } - (CGSize)bufferSize { - struct retro_variable var = { "desmume_screens_layout", NULL }; - environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var); + /// Get current resolution + struct retro_variable res = { "desmume_internal_resolution", NULL }; + environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &res); + + /// Get current layout + struct retro_variable layout = { "desmume_screens_layout", NULL }; + environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &layout); /// Base dimensions for a single DS screen unsigned width = GPU_LR_FRAMEBUFFER_NATIVE_WIDTH; unsigned height = GPU_LR_FRAMEBUFFER_NATIVE_HEIGHT; - if (var.value) { - if (strstr(var.value, "hybrid")) { + CGSize size; + /// Adjust dimensions based on layout + if (layout.value) { + if (strstr(layout.value, "hybrid")) { /// Hybrid layout needs extra width for the small screen - return CGSizeMake(width + (width/3), height); - } else if (strstr(var.value, "top only") || strstr(var.value, "bottom only")) { + int awidth = width/3; + size = CGSizeMake(width + awidth, height); + } else if (strstr(layout.value, "left/right") || strstr(layout.value, "right/left")) { + /// Side by side layout - double width + size = CGSizeMake(width * 2, height); + } else if (strstr(layout.value, "top/bottom") || strstr(layout.value, "bottom/top")) { + /// Vertical layout - double height + size = CGSizeMake(width, height * 2); + } else { /// Single screen layout - return CGSizeMake(width, height); - } else if (strstr(var.value, "top/bottom") || strstr(var.value, "bottom/top")) { - /// Vertical layout - return CGSizeMake(width, height * 2); + size = CGSizeMake(width, height); } + } else { + size = CGSizeMake(width, height); } - /// Default to single screen size - return CGSizeMake(width, height); + ILOG(@"Buffer size calculation:"); + ILOG(@"Layout: %s", layout.value ? layout.value : "default"); + ILOG(@"Resolution: %ux%u", width, height); + ILOG(@"Final size: %.0fx%.0f", size.width, size.height); + + return size; } - (CGSize)aspectSize { struct retro_variable var = { "desmume_screens_layout", NULL }; environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var); + CGSize aspect; if (var.value) { - if (strstr(var.value, "top only") || strstr(var.value, "bottom only")) { - return CGSizeMake(1, 1); /// Square aspect for single screen - } else if (strstr(var.value, "left/right") || strstr(var.value, "right/left")) { - return CGSizeMake(2, 1); /// 2:1 aspect for horizontal layout + if (strstr(var.value, "left/right") || strstr(var.value, "right/left")) { + aspect = CGSizeMake(2, 1); /// 2:1 aspect for horizontal layout + } else if (strstr(var.value, "top/bottom") || strstr(var.value, "bottom/top")) { + aspect = CGSizeMake(1, 2); /// 1:2 aspect for vertical layout + } else if (strstr(var.value, "hybrid")) { + aspect = CGSizeMake(4, 3); /// 4:3 aspect for hybrid layout + } else { + aspect = CGSizeMake(1, 1); /// Square aspect for single screen } + } else { + aspect = CGSizeMake(1, 1); } - return CGSizeMake(1, 2); /// Default 1:2 aspect for vertical layout + ILOG(@"Aspect size calculation:"); + ILOG(@"Layout: %s", var.value ? var.value : "default"); + ILOG(@"Aspect: %.0f:%.0f", aspect.width, aspect.height); + + return aspect; } #define USE_565 0 From 57046024972be9e6ab300957c7da12fee0296a46 Mon Sep 17 00:00:00 2001 From: Joseph Mattiello Date: Mon, 18 Nov 2024 20:04:11 -0500 Subject: [PATCH 08/10] desmume swap and layout almost work Signed-off-by: Joseph Mattiello --- .../Core/PVDesmume2015Core+Controls.mm | 36 +++++++- .../Core/PVDesmume2015Core+Video.m | 63 +++++++++---- .../Core/PVDesmume2015Core.h | 2 + .../Core/PVDesmume2015Core.mm | 92 ++++++++----------- 4 files changed, 119 insertions(+), 74 deletions(-) diff --git a/Cores/Desmume2015/PVDesmume2015Core/Core/PVDesmume2015Core+Controls.mm b/Cores/Desmume2015/PVDesmume2015Core/Core/PVDesmume2015Core+Controls.mm index d5087c513b..153c4b608f 100644 --- a/Cores/Desmume2015/PVDesmume2015Core/Core/PVDesmume2015Core+Controls.mm +++ b/Cores/Desmume2015/PVDesmume2015Core/Core/PVDesmume2015Core+Controls.mm @@ -25,14 +25,46 @@ @implementation PVDesmume2015CoreBridge (Controls) #pragma mark - Control - (void)updateScreenLayout:(const char *)layoutValue { + /// Update our variables dictionary + _variables[@"desmume_screens_layout"] = [NSString stringWithUTF8String:layoutValue]; + /// Set new layout through environment callback struct retro_variable var = { "desmume_screens_layout", NULL }; var.value = layoutValue; environ_cb(RETRO_ENVIRONMENT_SET_VARIABLE, &var); - /// Force a check of variables on next frame - bool updated = true; + /// Update current_layout directly for immediate effect + extern int current_layout; + if (strstr(layoutValue, "top/bottom")) + current_layout = LAYOUT_TOP_BOTTOM; + else if (strstr(layoutValue, "bottom/top")) + current_layout = LAYOUT_BOTTOM_TOP; + else if (strstr(layoutValue, "left/right")) + current_layout = LAYOUT_LEFT_RIGHT; + else if (strstr(layoutValue, "right/left")) + current_layout = LAYOUT_RIGHT_LEFT; + else if (strstr(layoutValue, "top only")) + current_layout = LAYOUT_TOP_ONLY; + else if (strstr(layoutValue, "bottom only")) + current_layout = LAYOUT_BOTTOM_ONLY; + else if (strstr(layoutValue, "hybrid/top")) + current_layout = LAYOUT_HYBRID_TOP_ONLY; + else if (strstr(layoutValue, "hybrid/bottom")) + current_layout = LAYOUT_HYBRID_BOTTOM_ONLY; + + /// Force layout update + bool updated = false; environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE, &updated); + + /// Log the layout change + if (log_cb) { + log_cb(RETRO_LOG_INFO, "Layout changed to: %s\n", layoutValue); + } else { + NSLog(@"Layout changed to: %s\n", layoutValue); + } + + UIViewController* viewController = (UIViewController* )self.renderDelegate; + [viewController viewDidLayoutSubviews]; } - (void)screenSwap { diff --git a/Cores/Desmume2015/PVDesmume2015Core/Core/PVDesmume2015Core+Video.m b/Cores/Desmume2015/PVDesmume2015Core/Core/PVDesmume2015Core+Video.m index 2551bcb65c..66081940f1 100644 --- a/Cores/Desmume2015/PVDesmume2015Core/Core/PVDesmume2015Core+Video.m +++ b/Cores/Desmume2015/PVDesmume2015Core/Core/PVDesmume2015Core+Video.m @@ -55,10 +55,28 @@ @implementation PVDesmume2015CoreBridge (Video) # pragma mark - Properties - (CGRect)screenRect { - return CGRectMake(0, 0, self.bufferSize.width, self.bufferSize.height); + static NSString *lastLayout = nil; + struct retro_variable layout = { "desmume_screens_layout", NULL }; + environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &layout); + + CGRect rect = CGRectMake(0, 0, self.bufferSize.width, self.bufferSize.height); + + if (layout.value) { + NSString *currentLayout = [NSString stringWithUTF8String:layout.value]; + if (!lastLayout || ![currentLayout isEqualToString:lastLayout]) { + NSLog(@"Screen rect changed:"); + NSLog(@"Layout: %s", layout.value); + NSLog(@"Rect: %@", NSStringFromCGRect(rect)); + lastLayout = currentLayout; + } + } + + return rect; } - (CGSize)bufferSize { + static NSString *lastLayout = nil; + /// Get current resolution struct retro_variable res = { "desmume_internal_resolution", NULL }; environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &res); @@ -74,6 +92,8 @@ - (CGSize)bufferSize { CGSize size; /// Adjust dimensions based on layout if (layout.value) { + NSString *currentLayout = [NSString stringWithUTF8String:layout.value]; + if (strstr(layout.value, "hybrid")) { /// Hybrid layout needs extra width for the small screen int awidth = width/3; @@ -88,41 +108,52 @@ - (CGSize)bufferSize { /// Single screen layout size = CGSizeMake(width, height); } + + /// Only log if layout changed + if (!lastLayout || ![currentLayout isEqualToString:lastLayout]) { + NSLog(@"Layout changed:"); + NSLog(@"Layout: %s", layout.value); + NSLog(@"Resolution: %ux%u", width, height); + NSLog(@"Final size: %.0fx%.0f", size.width, size.height); + lastLayout = currentLayout; + } } else { size = CGSizeMake(width, height); } - ILOG(@"Buffer size calculation:"); - ILOG(@"Layout: %s", layout.value ? layout.value : "default"); - ILOG(@"Resolution: %ux%u", width, height); - ILOG(@"Final size: %.0fx%.0f", size.width, size.height); - return size; } - (CGSize)aspectSize { - struct retro_variable var = { "desmume_screens_layout", NULL }; - environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var); + static NSString *lastLayout = nil; + struct retro_variable layout = { "desmume_screens_layout", NULL }; + environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &layout); CGSize aspect; - if (var.value) { - if (strstr(var.value, "left/right") || strstr(var.value, "right/left")) { + if (layout.value) { + NSString *currentLayout = [NSString stringWithUTF8String:layout.value]; + + if (strstr(layout.value, "left/right") || strstr(layout.value, "right/left")) { aspect = CGSizeMake(2, 1); /// 2:1 aspect for horizontal layout - } else if (strstr(var.value, "top/bottom") || strstr(var.value, "bottom/top")) { + } else if (strstr(layout.value, "top/bottom") || strstr(layout.value, "bottom/top")) { aspect = CGSizeMake(1, 2); /// 1:2 aspect for vertical layout - } else if (strstr(var.value, "hybrid")) { + } else if (strstr(layout.value, "hybrid")) { aspect = CGSizeMake(4, 3); /// 4:3 aspect for hybrid layout } else { aspect = CGSizeMake(1, 1); /// Square aspect for single screen } + + /// Only log if layout changed + if (!lastLayout || ![currentLayout isEqualToString:lastLayout]) { + NSLog(@"Aspect changed:"); + NSLog(@"Layout: %s", layout.value); + NSLog(@"Aspect: %.0f:%.0f", aspect.width, aspect.height); + lastLayout = currentLayout; + } } else { aspect = CGSizeMake(1, 1); } - ILOG(@"Aspect size calculation:"); - ILOG(@"Layout: %s", var.value ? var.value : "default"); - ILOG(@"Aspect: %.0f:%.0f", aspect.width, aspect.height); - return aspect; } diff --git a/Cores/Desmume2015/PVDesmume2015Core/Core/PVDesmume2015Core.h b/Cores/Desmume2015/PVDesmume2015Core/Core/PVDesmume2015Core.h index c14cb9876c..888b524974 100644 --- a/Cores/Desmume2015/PVDesmume2015Core/Core/PVDesmume2015Core.h +++ b/Cores/Desmume2015/PVDesmume2015Core/Core/PVDesmume2015Core.h @@ -20,6 +20,8 @@ __attribute__((visibility("default"))) @interface PVDesmume2015CoreBridge : PVLibRetroCoreBridge { uint8_t padData[4][14]; //[PVDSButton.count]; + + NSMutableDictionary *_variables; @public dispatch_queue_t _callbackQueue; } diff --git a/Cores/Desmume2015/PVDesmume2015Core/Core/PVDesmume2015Core.mm b/Cores/Desmume2015/PVDesmume2015Core/Core/PVDesmume2015Core.mm index b4801a1d9d..d01cd41389 100644 --- a/Cores/Desmume2015/PVDesmume2015Core/Core/PVDesmume2015Core.mm +++ b/Cores/Desmume2015/PVDesmume2015Core/Core/PVDesmume2015Core.mm @@ -64,9 +64,9 @@ //static void *dlopen_myself() //{ // Dl_info info; -// +// // dladdr(dlopen_myself, &info); -// +// // return dlopen(info.dli_fname, RTLD_LAZY | RTLD_GLOBAL); //} @@ -98,6 +98,18 @@ - (instancetype)init { // // _callbackQueue = dispatch_queue_create("org.openemu.Desmume2015.CallbackHandlerQueue", queueAttributes); // _callbackHandlers = [[NSMutableDictionary alloc] init]; + _variables = [NSMutableDictionary dictionary]; + + /// Set default values based on libretro.cpp options + _variables[@"desmume_screens_layout"] = @"top/bottom"; + _variables[@"desmume_internal_resolution"] = @"256x192"; + _variables[@"desmume_num_cores"] = @"1"; + _variables[@"desmume_cpu_mode"] = @"interpreter"; + _variables[@"desmume_hybrid_layout_scale"] = @"1"; + _variables[@"desmume_pointer_colour"] = @"white"; + _variables[@"desmume_hybrid_showbothscreens"] = @"enabled"; + _variables[@"desmume_hybrid_cursor_always_smallscreen"] = @"enabled"; + _current = self; } return self; @@ -392,63 +404,31 @@ - (instancetype)init { #pragma mark - Options - (void *)getVariable:(const char *)variable { - ILOG(@"%s", variable); + NSString *varKey = [NSString stringWithUTF8String:variable]; + NSString *value = _variables[varKey]; - - #define V(x) strcmp(variable, x) == 0 - - if (V("desmume_cpu_mode")) { - // interpreter|jit - char * value = strdup("interpreter"); - return value; - } else if (V("desmume_internal_resolution")) { - // 256x192|512x384|768x576|1024x768|1280x960|1536x1152|1792x1344|2048x1536|2304x1728|2560x1920 - char * value = strdup("1024x768"); - return value; - } else if (V("desmume_num_cores")) { - // CPU cores; 1|2|3|4 - char * value = strdup("4"); - return value; - } else if (V("desmume_pointer_type")) { - // mouse|touch - char * value = strdup("touch"); - return value; - } else if (V("desmume_load_to_memory")) { - // disabled|enabled - char * value = strdup("enabled"); - return value; - } else if (V("desmume_gfx_txthack")) { - // disabled|enabled - char * value = strdup("disabled"); - return value; - } else if (V("desmume_mic_mode")) { - // internal|sample|random|physical - char * value = strdup("physical"); - return value; - } else if (V("desmume_pointer_colour")) { - // white|black|red|blue|yellow - char * value = strdup("blue"); - return value; - } else if (V("desmume_screens_layout")) { - // top/bottom|bottom/top|left/right|right/left|top only|bottom only|quick switch|hybrid/top|hybrid/bottom - char * value = strdup("top/bottom"); - return value; - } else if (V("desmume_hybrid_showboth_screens")) { - // Hybrid layout show both screens; enabled|disabled - char * value = strdup("enabled"); - return value; - } else if (V("desmume_hybrid_layout_scale")) { - // 1|3 - char * value = strdup("1"); - return value; - } else { - ELOG(@"Unprocessed var: %s", variable); - return NULL; + if (!value) { + // Fallback to defaults if not set + if (strcmp(variable, "desmume_screens_layout") == 0) { + value = @"top/bottom"; + } else if (strcmp(variable, "desmume_internal_resolution") == 0) { + value = @"256x192"; + } else if (strcmp(variable, "desmume_num_cores") == 0) { + value = @"1"; + } else if (strcmp(variable, "desmume_cpu_mode") == 0) { + value = @"interpreter"; + } else if (strcmp(variable, "desmume_hybrid_layout_scale") == 0) { + value = @"1"; + } else if (strcmp(variable, "desmume_pointer_colour") == 0) { + value = @"white"; + } else if (strcmp(variable, "desmume_hybrid_showbothscreens") == 0) { + value = @"enabled"; + } else if (strcmp(variable, "desmume_hybrid_cursor_always_smallscreen") == 0) { + value = @"enabled"; + } } -#undef V - return NULL; + return value ? strdup(value.UTF8String) : NULL; } @end - From 24122d6c157f7b90a9323abcfc0612a22612cddd Mon Sep 17 00:00:00 2001 From: Joseph Mattiello Date: Mon, 18 Nov 2024 20:11:00 -0500 Subject: [PATCH 09/10] more video layout fixes Signed-off-by: Joseph Mattiello --- .../Core/PVDesmume2015Core+Video.m | 72 ++++++++----------- 1 file changed, 29 insertions(+), 43 deletions(-) diff --git a/Cores/Desmume2015/PVDesmume2015Core/Core/PVDesmume2015Core+Video.m b/Cores/Desmume2015/PVDesmume2015Core/Core/PVDesmume2015Core+Video.m index 66081940f1..2b6343ad6d 100644 --- a/Cores/Desmume2015/PVDesmume2015Core/Core/PVDesmume2015Core+Video.m +++ b/Cores/Desmume2015/PVDesmume2015Core/Core/PVDesmume2015Core+Video.m @@ -56,19 +56,15 @@ @implementation PVDesmume2015CoreBridge (Video) - (CGRect)screenRect { static NSString *lastLayout = nil; - struct retro_variable layout = { "desmume_screens_layout", NULL }; - environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &layout); + NSString *layoutValue = _variables[@"desmume_screens_layout"]; CGRect rect = CGRectMake(0, 0, self.bufferSize.width, self.bufferSize.height); - if (layout.value) { - NSString *currentLayout = [NSString stringWithUTF8String:layout.value]; - if (!lastLayout || ![currentLayout isEqualToString:lastLayout]) { - NSLog(@"Screen rect changed:"); - NSLog(@"Layout: %s", layout.value); - NSLog(@"Rect: %@", NSStringFromCGRect(rect)); - lastLayout = currentLayout; - } + if (layoutValue && (!lastLayout || ![layoutValue isEqualToString:lastLayout])) { + ILOG(@"Screen rect changed:"); + ILOG(@"Layout: %@", layoutValue); + ILOG(@"Rect: %@", NSStringFromCGRect(rect)); + lastLayout = layoutValue; } return rect; @@ -77,31 +73,24 @@ - (CGRect)screenRect { - (CGSize)bufferSize { static NSString *lastLayout = nil; - /// Get current resolution - struct retro_variable res = { "desmume_internal_resolution", NULL }; - environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &res); - - /// Get current layout - struct retro_variable layout = { "desmume_screens_layout", NULL }; - environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &layout); + /// Get current resolution and layout from our dictionary + NSString *resolution = _variables[@"desmume_internal_resolution"]; + NSString *layoutValue = _variables[@"desmume_screens_layout"]; /// Base dimensions for a single DS screen unsigned width = GPU_LR_FRAMEBUFFER_NATIVE_WIDTH; unsigned height = GPU_LR_FRAMEBUFFER_NATIVE_HEIGHT; CGSize size; - /// Adjust dimensions based on layout - if (layout.value) { - NSString *currentLayout = [NSString stringWithUTF8String:layout.value]; - - if (strstr(layout.value, "hybrid")) { + if (layoutValue) { + if ([layoutValue containsString:@"hybrid"]) { /// Hybrid layout needs extra width for the small screen int awidth = width/3; size = CGSizeMake(width + awidth, height); - } else if (strstr(layout.value, "left/right") || strstr(layout.value, "right/left")) { + } else if ([layoutValue containsString:@"left/right"] || [layoutValue containsString:@"right/left"]) { /// Side by side layout - double width size = CGSizeMake(width * 2, height); - } else if (strstr(layout.value, "top/bottom") || strstr(layout.value, "bottom/top")) { + } else if ([layoutValue containsString:@"top/bottom"] || [layoutValue containsString:@"bottom/top"]) { /// Vertical layout - double height size = CGSizeMake(width, height * 2); } else { @@ -110,12 +99,12 @@ - (CGSize)bufferSize { } /// Only log if layout changed - if (!lastLayout || ![currentLayout isEqualToString:lastLayout]) { - NSLog(@"Layout changed:"); - NSLog(@"Layout: %s", layout.value); - NSLog(@"Resolution: %ux%u", width, height); - NSLog(@"Final size: %.0fx%.0f", size.width, size.height); - lastLayout = currentLayout; + if (!lastLayout || ![layoutValue isEqualToString:lastLayout]) { + ILOG(@"Layout changed:"); + ILOG(@"Layout: %@", layoutValue); + ILOG(@"Resolution: %ux%u", width, height); + ILOG(@"Final size: %.0fx%.0f", size.width, size.height); + lastLayout = layoutValue; } } else { size = CGSizeMake(width, height); @@ -126,29 +115,26 @@ - (CGSize)bufferSize { - (CGSize)aspectSize { static NSString *lastLayout = nil; - struct retro_variable layout = { "desmume_screens_layout", NULL }; - environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &layout); + NSString *layoutValue = _variables[@"desmume_screens_layout"]; CGSize aspect; - if (layout.value) { - NSString *currentLayout = [NSString stringWithUTF8String:layout.value]; - - if (strstr(layout.value, "left/right") || strstr(layout.value, "right/left")) { + if (layoutValue) { + if ([layoutValue containsString:@"left/right"] || [layoutValue containsString:@"right/left"]) { aspect = CGSizeMake(2, 1); /// 2:1 aspect for horizontal layout - } else if (strstr(layout.value, "top/bottom") || strstr(layout.value, "bottom/top")) { + } else if ([layoutValue containsString:@"top/bottom"] || [layoutValue containsString:@"bottom/top"]) { aspect = CGSizeMake(1, 2); /// 1:2 aspect for vertical layout - } else if (strstr(layout.value, "hybrid")) { + } else if ([layoutValue containsString:@"hybrid"]) { aspect = CGSizeMake(4, 3); /// 4:3 aspect for hybrid layout } else { aspect = CGSizeMake(1, 1); /// Square aspect for single screen } /// Only log if layout changed - if (!lastLayout || ![currentLayout isEqualToString:lastLayout]) { - NSLog(@"Aspect changed:"); - NSLog(@"Layout: %s", layout.value); - NSLog(@"Aspect: %.0f:%.0f", aspect.width, aspect.height); - lastLayout = currentLayout; + if (!lastLayout || ![layoutValue isEqualToString:lastLayout]) { + ILOG(@"Aspect changed:"); + ILOG(@"Layout: %@", layoutValue); + ILOG(@"Aspect: %.0f:%.0f", aspect.width, aspect.height); + lastLayout = layoutValue; } } else { aspect = CGSizeMake(1, 1); From 54c210de50b80d4056314c86dcd2cb128d265965 Mon Sep 17 00:00:00 2001 From: Joseph Mattiello Date: Mon, 18 Nov 2024 22:52:42 -0500 Subject: [PATCH 10/10] =?UTF-8?q?desmume=20start=20of=20PVLibRetroCoreBrid?= =?UTF-8?q?ge=20=E2=80=9Cmouse=E2=80=9D=20support?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Joseph Mattiello --- .../Core/PVDesmume2015Core+Controls.h | 13 +- .../Core/PVDesmume2015Core+Controls.mm | 37 +- .../Sources/PVLibRetro/PVLibRetroCore.h | 18 +- .../Sources/PVLibRetro/PVLibRetroCore.m | 421 +++++++++++------- 4 files changed, 315 insertions(+), 174 deletions(-) diff --git a/Cores/Desmume2015/PVDesmume2015Core/Core/PVDesmume2015Core+Controls.h b/Cores/Desmume2015/PVDesmume2015Core/Core/PVDesmume2015Core+Controls.h index 74644dcfe3..9840914469 100644 --- a/Cores/Desmume2015/PVDesmume2015Core/Core/PVDesmume2015Core+Controls.h +++ b/Cores/Desmume2015/PVDesmume2015Core/Core/PVDesmume2015Core+Controls.h @@ -7,12 +7,20 @@ // #import +#import + +// Forward declarations from libretro.cpp +extern unsigned GPU_LR_FRAMEBUFFER_NATIVE_WIDTH; +extern unsigned GPU_LR_FRAMEBUFFER_NATIVE_HEIGHT; +extern int current_layout; + +@protocol MouseResponder; typedef enum PVDSButton: NSInteger PVDSButton; NS_ASSUME_NONNULL_BEGIN -@interface PVDesmume2015CoreBridge (Controls) +@interface PVDesmume2015CoreBridge (Controls) - (void)initControllBuffers; - (void)pollControllers; @@ -26,6 +34,9 @@ NS_ASSUME_NONNULL_BEGIN - (void)didPush:(NSInteger)button forPlayer:(NSInteger)player; - (void)didRelease:(NSInteger)button forPlayer:(NSInteger)player; + +@property (nonatomic, readonly) BOOL gameSupportsMouse; +@property (nonatomic, readonly) BOOL requiresMouse; @end NS_ASSUME_NONNULL_END diff --git a/Cores/Desmume2015/PVDesmume2015Core/Core/PVDesmume2015Core+Controls.mm b/Cores/Desmume2015/PVDesmume2015Core/Core/PVDesmume2015Core+Controls.mm index 153c4b608f..8a5c5c9121 100644 --- a/Cores/Desmume2015/PVDesmume2015Core/Core/PVDesmume2015Core+Controls.mm +++ b/Cores/Desmume2015/PVDesmume2015Core/Core/PVDesmume2015Core+Controls.mm @@ -8,6 +8,8 @@ #import #import +#import "PVDesmume2015Core+Controls.h" + @import PVCoreBridge; @import PVCoreObjCBridge; @@ -271,9 +273,38 @@ - (void)didRelease:(NSInteger)button forPlayer:(NSInteger)player { [self didReleaseDSButton:(PVDSButton)button forPlayer:player]; } -// Touch Screen controls --(void)sendEvent:(UIEvent * _Nullable)event { - [super sendEvent:event]; +/// Mouse support properties +- (BOOL)gameSupportsMouse { + return YES; +} + +- (BOOL)requiresMouse { + return YES; } +/// Mouse movement handling +//- (void)mouseMoved:(CGPoint)point { +// extern bool mouse_enable; +// extern double mouse_x_delta; +// extern double mouse_y_delta; +// +// mouse_enable = YES; +// mouse_x_delta = point.x; +// mouse_y_delta = point.y; +// +// NSLog(@"Mouse moved - x: %.2f, y: %.2f", point.x, point.y); +//} +// +///// Mouse button handling +//- (void)leftMouseDown:(CGPoint)point { +// extern bool touchEnabled; +// touchEnabled = YES; +// [self mouseMoved:point]; +//} +// +//- (void)leftMouseUp { +// extern bool touchEnabled; +// touchEnabled = NO; +//} + @end diff --git a/PVCoreBridgeRetro/Sources/PVLibRetro/PVLibRetroCore.h b/PVCoreBridgeRetro/Sources/PVLibRetro/PVLibRetroCore.h index 4f1f658e7b..856e82498f 100644 --- a/PVCoreBridgeRetro/Sources/PVLibRetro/PVLibRetroCore.h +++ b/PVCoreBridgeRetro/Sources/PVLibRetro/PVLibRetroCore.h @@ -41,13 +41,13 @@ __attribute__((weak_import)) #pragma clang diagnostic pop @public unsigned short pitch_shift; - + uint32_t *videoBuffer; uint32_t *videoBufferA; uint32_t *videoBufferB; - + int16_t _pad[2][12]; - + retro_core_t* core; // MARK: - Retro Structs @@ -56,6 +56,10 @@ __attribute__((weak_import)) bool core_has_set_input_descriptors; struct retro_system_av_info av_info; enum retro_pixel_format pix_fmt; + + CGPoint currentTouchPoint; + BOOL touchActive; + BOOL mouseEnabled; } - (instancetype _Nonnull )init; - (NSInteger)controllerValueForButtonID:(unsigned)buttonID forPlayer:(NSInteger)player; @@ -69,6 +73,14 @@ __attribute__((weak_import)) @end +@protocol MouseResponder; +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Weverything" // Silence "Cannot find protocol definition" warning due to forward declaration. +@interface PVLibRetroCoreBridge (MouseResponder) +#pragma clang diagnostic pop + +@end + #define SYMBOL(x) \ do { \ function_t func = dylib_proc(lib_handle, #x); \ diff --git a/PVCoreBridgeRetro/Sources/PVLibRetro/PVLibRetroCore.m b/PVCoreBridgeRetro/Sources/PVLibRetro/PVLibRetroCore.m index c29851dfda..5336e305f3 100644 --- a/PVCoreBridgeRetro/Sources/PVLibRetro/PVLibRetroCore.m +++ b/PVCoreBridgeRetro/Sources/PVLibRetro/PVLibRetroCore.m @@ -125,9 +125,9 @@ @interface PVLibRetroCoreBridge () NSBundle *bundle = [NSBundle bundleForClass:[_current class]]; // const char* path = [bundle.executablePath fileSystemRepresentation]; NSString *executableName = bundle.infoDictionary[@"CFBundleExecutable"]; - + NSString *frameworkPath = [NSString stringWithFormat:@"%@/%@", bundle.bundlePath, executableName]; - + NSArray *fileNames = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:frameworkPath error:nil]; for (NSString *fileName in fileNames) { ILOG(@"%@", fileName); @@ -167,8 +167,8 @@ void config_clear_active_core_path(void) { // // if (!string_is_empty(global->path.config)) // return global->path.config; - - + + return NULL; } @@ -226,7 +226,7 @@ static int16_t core_input_state_poll(unsigned port, { if (!current->core_input_polled) input_poll(); - + current->core_input_polled = true; } return input_state(port, device, idx, id); @@ -256,7 +256,7 @@ int16_t input_state(unsigned port, unsigned device, { int16_t res = 0; // settings_t *settings = config_get_ptr(); - + // // device &= RETRO_DEVICE_MASK; // @@ -315,7 +315,7 @@ int16_t input_state(unsigned port, unsigned device, // // if (bsv_movie_ctl(BSV_MOVIE_CTL_PLAYBACK_OFF, NULL)) // bsv_movie_ctl(BSV_MOVIE_CTL_SET_INPUT, &res); - + return res; } @@ -335,25 +335,25 @@ static bool core_init_libretro_cbs(void *data) #ifdef HAVE_NETPLAY global_t *global = global_get_ptr(); #endif - + if (!cbs) return false; - + current->core->retro_set_video_refresh(video_driver_frame); // core->retro_set_audio_sample(audio_driver_sample); // core->retro_set_audio_sample_batch(audio_driver_sample_batch); current->core->retro_set_input_state(core_input_state_poll); current->core->retro_set_input_poll(core_input_state_poll_maybe); - + core_set_default_callbacks(cbs); - + #ifdef HAVE_NETPLAY if (!netplay_driver_ctl(RARCH_NETPLAY_CTL_IS_DATA_INITED, NULL)) return true; - + /* Force normal poll type for netplay. */ core_poll_type = POLL_TYPE_NORMAL; - + if (global->netplay.is_spectate) { core->retro_set_input_state( @@ -369,7 +369,7 @@ static bool core_init_libretro_cbs(void *data) core->retro_set_input_state(input_state_net); } #endif - + return true; } @@ -382,32 +382,32 @@ static bool core_init_libretro_cbs(void *data) bool core_set_default_callbacks(void *data) { struct retro_callbacks *cbs = (struct retro_callbacks*)data; - + if (!cbs) return false; - + cbs->frame_cb = video_driver_frame; // cbs->sample_cb = audio_callback; // cbs->sample_batch_cb = audio_batch_callback; cbs->state_cb = core_input_state_poll; cbs->poll_cb = input_poll; - + return true; } bool core_deinit(void *data) { struct retro_callbacks *cbs = (struct retro_callbacks*)data; - + if (!cbs) return false; - + cbs->frame_cb = NULL; cbs->sample_cb = NULL; cbs->sample_batch_cb = NULL; cbs->state_cb = NULL; cbs->poll_cb = NULL; - + return true; } @@ -514,7 +514,7 @@ bool core_load_game(retro_ctx_load_content_info_t *load_info) if (!load_info) return false; - + BOOL loaded = false; if (load_info->special != nil) { loaded = current->core->retro_load_game_special(load_info->special->id, load_info->info, load_info->content->size); @@ -527,15 +527,15 @@ bool core_load_game(retro_ctx_load_content_info_t *load_info) // gameInfo->path = load_info->info->path; // current->core->retro_load_game(gameInfo); // } else { - loaded = current->core->retro_load_game(load_info->info); + loaded = current->core->retro_load_game(load_info->info); // } } - + if (!loaded) { ELOG(@"Core failed to load game."); return false; } - + struct retro_system_timing timing = { 60.0f, 10000.0f }; @@ -555,8 +555,8 @@ bool core_load_game(retro_ctx_load_content_info_t *load_info) // 0, // NULL // }; - - + + current->core->retro_get_system_av_info(&av); ILOG(@"Video: %ix%i\n", av.geometry.base_width, av.geometry.base_height); current->av_info = av; @@ -603,7 +603,7 @@ bool core_frame(retro_ctx_frame_info_t *info) { GET_CURRENT_OR_RETURN(false); if (!info || !retro_ctx.frame_cb) return false; - + retro_ctx.frame_cb( info->data, info->width, info->height, info->pitch); return true; @@ -677,22 +677,22 @@ bool core_load(void) { settings_t *settings = config_get_ptr(); current->core_poll_type = settings->input.poll_type_behavior; - + if (!core_verify_api_version()) return false; if (!core_init_libretro_cbs(&retro_ctx)) return false; - + core_get_system_av_info(video_viewport_get_system_av_info()); runloop_ctl(RUNLOOP_CTL_SET_FRAME_LIMIT, NULL); - + return true; } struct retro_system_av_info *video_viewport_get_system_av_info(void) { static struct retro_system_av_info av_info; - + return &av_info; } @@ -780,9 +780,9 @@ void uninit_libretro_sym(struct retro_core_t *current_core) dylib_close(lib_handle); lib_handle = NULL; #endif - + memset(current_core, 0, sizeof(struct retro_core_t)); - + runloop_ctl(RUNLOOP_CTL_CORE_OPTIONS_DEINIT, NULL); runloop_ctl(RUNLOOP_CTL_SYSTEM_INFO_FREE, NULL); runloop_ctl(RUNLOOP_CTL_FRAME_TIME_FREE, NULL); @@ -815,14 +815,14 @@ bool runloop_ctl(enum runloop_ctl_state state, void *data) { // return shader_dir_init(&runloop_shader_dir); case RUNLOOP_CTL_SYSTEM_INFO_INIT: core_get_system_info(&runloop_system.info); - + // if (!runloop_system.info.library_name) // runloop_system.info.library_name = msg_hash_to_str(MSG_UNKNOWN); if (!runloop_system.info.library_version) runloop_system.info.library_version = "v0"; - + // video_driver_set_title_buf(); - + strlcpy(runloop_system.valid_extensions, runloop_system.info.valid_extensions ? runloop_system.info.valid_extensions : DEFAULT_EXT, @@ -855,26 +855,26 @@ bool runloop_ctl(enum runloop_ctl_state state, void *data) { } break; case RUNLOOP_CTL_SYSTEM_INFO_FREE: - + /* No longer valid. */ if (runloop_system.subsystem.data) free(runloop_system.subsystem.data); runloop_system.subsystem.data = NULL; runloop_system.subsystem.size = 0; - + if (runloop_system.ports.data) free(runloop_system.ports.data); runloop_system.ports.data = NULL; runloop_system.ports.size = 0; - + if (runloop_system.mmaps.descriptors) free((void *)runloop_system.mmaps.descriptors); runloop_system.mmaps.descriptors = NULL; runloop_system.mmaps.num_descriptors = 0; - + runloop_key_event = NULL; runloop_frontend_key_event = NULL; - + audio_driver_unset_callback(); memset(&runloop_system, 0, sizeof(rarch_system_info_t)); break; @@ -943,7 +943,7 @@ bool runloop_ctl(enum runloop_ctl_state state, void *data) { (const struct retro_frame_time_callback*)data; #ifdef HAVE_NETPLAY global_t *global = global_get_ptr(); - + /* retro_run() will be called in very strange and * mysterious ways, have to disable it. */ if (global->netplay.enable) @@ -1037,13 +1037,13 @@ bool runloop_ctl(enum runloop_ctl_state state, void *data) { // command_event(CMD_EVENT_SUBSYSTEM_FULLPATHS_DEINIT, NULL); // command_event(CMD_EVENT_RECORD_DEINIT, NULL); // command_event(CMD_EVENT_LOG_FILE_DEINIT, NULL); - + // rarch_ctl(RARCH_CTL_UNSET_BLOCK_CONFIG_READ, NULL); runloop_ctl(RUNLOOP_CTL_CLEAR_CONTENT_PATH, NULL); runloop_overrides_active = false; - + core_unset_input_descriptors(); - + // global = global_get_ptr(); memset(global, 0, sizeof(struct global)); // retroarch_override_setting_free_state(); @@ -1129,7 +1129,7 @@ bool runloop_ctl(enum runloop_ctl_state state, void *data) { runloop_ctl(RUNLOOP_CTL_MSG_QUEUE_DEINIT, NULL); // runloop_msg_queue = msg_queue_new(8); // retro_assert(runloop_msg_queue); - + #ifdef HAVE_THREADS _runloop_msg_queue_lock = slock_new(); retro_assert(_runloop_msg_queue_lock); @@ -1221,7 +1221,7 @@ bool runloop_ctl(enum runloop_ctl_state state, void *data) { // const char *options_path = settings->path.core_options; // const struct retro_variable *vars = // (const struct retro_variable*)data; - + // if (string_is_empty(options_path) // && !string_is_empty(global->path.config)) // { @@ -1247,7 +1247,7 @@ bool runloop_ctl(enum runloop_ctl_state state, void *data) { // runloop_core_options = // core_option_manager_new(options_path, vars); // } - + } break; // case RUNLOOP_CTL_CORE_OPTIONS_FREE: @@ -1310,7 +1310,7 @@ bool runloop_ctl(enum runloop_ctl_state state, void *data) { default: break; } - + return true; } @@ -1407,7 +1407,7 @@ void init_libretro_sym(enum rarch_core_type type, struct retro_core_t *current_c /* Guarantee that we can do "dirty" casting. * Every OS that this program supports should pass this. */ retro_assert(sizeof(void*) == sizeof(void (*)(void))); - + load_symbols(type, current_core); } @@ -1429,14 +1429,14 @@ static void core_log(enum retro_log_level level, const char * fmt, ...) { "err" }; va_list va; - + va_start(va, fmt); vsnprintf(buffer, sizeof(buffer), fmt, va); va_end(va); - + if (level == 0) return; - + switch (level) { case 0: DLOG(@"%s", buffer); @@ -1453,10 +1453,10 @@ static void core_log(enum retro_log_level level, const char * fmt, ...) { default: break; } - + fprintf(stderr, "[%s] %s", levelstr[level], buffer); fflush(stderr); - + if (level == RETRO_LOG_ERROR) { exit(EXIT_FAILURE); } @@ -1538,7 +1538,7 @@ static bool environment_callback(unsigned cmd, void *data) { if ([strongCurrent conformsToProtocol:@protocol(TouchPadResponder)]) { features |= 1 << RETRO_DEVICE_POINTER; } - + *(uint64_t *)data = features; return true; } @@ -1599,7 +1599,7 @@ static bool environment_callback(unsigned cmd, void *data) { CFStringRef cfString = (CFStringRef)CFBridgingRetain(BIOSPath); *(const char **)data = CFStringGetCStringPtr(cfString, kCFStringEncodingUTF8); //[BIOSPath UTF8String]; - + DLOG(@"Environ SYSTEM_DIRECTORY: \"%@\".\n", BIOSPath); return true; } @@ -1617,14 +1617,14 @@ static bool environment_callback(unsigned cmd, void *data) { //// } case RETRO_ENVIRONMENT_GET_SAVE_DIRECTORY : { NSString *appSupportPath = [strongCurrent saveStatesPath]; - + *(const char **)data = [appSupportPath UTF8String]; DLOG(@"Environ SAVE_DIRECTORY: \"%@\".\n", appSupportPath); return true; } case RETRO_ENVIRONMENT_GET_CORE_ASSETS_DIRECTORY : { NSString *batterySavesPath = [strongCurrent batterySavesPath]; - + *(const char **)data = [batterySavesPath UTF8String]; DLOG(@"Environ CONTENT_DIRECTORY: \"%@\".\n", batterySavesPath); return true; @@ -1672,17 +1672,17 @@ static bool environment_callback(unsigned cmd, void *data) { { const struct retro_game_info_ext **game_info_ext = (const struct retro_game_info_ext **)data; - + if (!game_info_ext) { ELOG(@"`game_info_ext` is nil.") return false; } - + //// struct retro_game_info_ext *game_info = (struct retro_game_info_ext*)data; // // TODO: Is there a way to pass `retro_game_info_ext` before callbacks? struct retro_game_info_ext *game_info = malloc(sizeof(struct retro_game_info_ext)); game_info->persistent_data = true; - + // void *buffer = malloc(romData.length); // [romData getBytes:buffer length:romData.length]; // @@ -1691,16 +1691,16 @@ static bool environment_callback(unsigned cmd, void *data) { CFDataRef cfData = (CFDataRef)CFBridgingRetain(romData); game_info->data = CFDataGetBytePtr(cfData); game_info->size = romData.length; - + const char *c_full_path = [strongCurrent.romPath cStringUsingEncoding:NSUTF8StringEncoding]; game_info->full_path = c_full_path; - + const char *c_dir = [[strongCurrent.romPath stringByDeletingLastPathComponent] cStringUsingEncoding:NSUTF8StringEncoding]; game_info->dir = c_dir; - + const char *c_rom_name = [[strongCurrent.romPath.lastPathComponent stringByDeletingPathExtension] cStringUsingEncoding:NSUTF8StringEncoding]; game_info->name = c_rom_name; - + const char *c_extension = [[strongCurrent.romPath.lastPathComponent pathExtension] cStringUsingEncoding:NSUTF8StringEncoding]; game_info->ext = c_extension; @@ -1782,9 +1782,9 @@ static bool environment_callback(unsigned cmd, void *data) { return false; } } - + strongCurrent = nil; - + return true; } @@ -1797,9 +1797,9 @@ static void load_dynamic_core(void) ILOG(@"Loading dynamic libretro core from: \"%s\"\n", corepath); lib_handle = dylib_load(corepath); - + // function_t sym = dylib_proc(lib_handle, "retro_init"); - + // if (sym) // { // /* Try to verify that -lretro was not linked in from other modules @@ -1848,7 +1848,7 @@ static void load_dynamic_core(void) **/ static void load_symbols(enum rarch_core_type type, struct retro_core_t *current_core) { - + switch (type) { case CORE_TYPE_PLAIN: @@ -1856,36 +1856,36 @@ static void load_symbols(enum rarch_core_type type, struct retro_core_t *current load_dynamic_core(); #endif ILOG(@"type:%x, current_core: %x, lib_handle: %x", type, current_core, lib_handle); - + SYMBOL(retro_init); SYMBOL(retro_deinit); - + SYMBOL(retro_api_version); SYMBOL(retro_get_system_info); SYMBOL(retro_get_system_av_info); - + SYMBOL(retro_set_environment); SYMBOL(retro_set_video_refresh); SYMBOL(retro_set_audio_sample); SYMBOL(retro_set_audio_sample_batch); SYMBOL(retro_set_input_poll); SYMBOL(retro_set_input_state); - + SYMBOL(retro_set_controller_port_device); - + SYMBOL(retro_reset); SYMBOL(retro_run); - + SYMBOL(retro_serialize_size); SYMBOL(retro_serialize); SYMBOL(retro_unserialize); - + SYMBOL(retro_cheat_reset); SYMBOL(retro_cheat_set); - + SYMBOL(retro_load_game); SYMBOL(retro_load_game_special); - + SYMBOL(retro_unload_game); SYMBOL(retro_get_region); SYMBOL(retro_get_memory_data); @@ -1894,33 +1894,33 @@ static void load_symbols(enum rarch_core_type type, struct retro_core_t *current case CORE_TYPE_DUMMY: SYMBOL_DUMMY(retro_init); SYMBOL_DUMMY(retro_deinit); - + SYMBOL_DUMMY(retro_api_version); SYMBOL_DUMMY(retro_get_system_info); SYMBOL_DUMMY(retro_get_system_av_info); - + SYMBOL_DUMMY(retro_set_environment); SYMBOL_DUMMY(retro_set_video_refresh); SYMBOL_DUMMY(retro_set_audio_sample); SYMBOL_DUMMY(retro_set_audio_sample_batch); SYMBOL_DUMMY(retro_set_input_poll); SYMBOL_DUMMY(retro_set_input_state); - + SYMBOL_DUMMY(retro_set_controller_port_device); - + SYMBOL_DUMMY(retro_reset); SYMBOL_DUMMY(retro_run); - + SYMBOL_DUMMY(retro_serialize_size); SYMBOL_DUMMY(retro_serialize); SYMBOL_DUMMY(retro_unserialize); - + SYMBOL_DUMMY(retro_cheat_reset); SYMBOL_DUMMY(retro_cheat_set); - + SYMBOL_DUMMY(retro_load_game); SYMBOL_DUMMY(retro_load_game_special); - + SYMBOL_DUMMY(retro_unload_game); SYMBOL_DUMMY(retro_get_region); SYMBOL_DUMMY(retro_get_memory_data); @@ -1930,33 +1930,33 @@ static void load_symbols(enum rarch_core_type type, struct retro_core_t *current #ifdef HAVE_FFMPEG SYMBOL_FFMPEG(retro_init); SYMBOL_FFMPEG(retro_deinit); - + SYMBOL_FFMPEG(retro_api_version); SYMBOL_FFMPEG(retro_get_system_info); SYMBOL_FFMPEG(retro_get_system_av_info); - + SYMBOL_FFMPEG(retro_set_environment); SYMBOL_FFMPEG(retro_set_video_refresh); SYMBOL_FFMPEG(retro_set_audio_sample); SYMBOL_FFMPEG(retro_set_audio_sample_batch); SYMBOL_FFMPEG(retro_set_input_poll); SYMBOL_FFMPEG(retro_set_input_state); - + SYMBOL_FFMPEG(retro_set_controller_port_device); - + SYMBOL_FFMPEG(retro_reset); SYMBOL_FFMPEG(retro_run); - + SYMBOL_FFMPEG(retro_serialize_size); SYMBOL_FFMPEG(retro_serialize); SYMBOL_FFMPEG(retro_unserialize); - + SYMBOL_FFMPEG(retro_cheat_reset); SYMBOL_FFMPEG(retro_cheat_set); - + SYMBOL_FFMPEG(retro_load_game); SYMBOL_FFMPEG(retro_load_game_special); - + SYMBOL_FFMPEG(retro_unload_game); SYMBOL_FFMPEG(retro_get_region); SYMBOL_FFMPEG(retro_get_memory_data); @@ -1967,33 +1967,33 @@ static void load_symbols(enum rarch_core_type type, struct retro_core_t *current #ifdef HAVE_IMAGEVIEWER SYMBOL_IMAGEVIEWER(retro_init); SYMBOL_IMAGEVIEWER(retro_deinit); - + SYMBOL_IMAGEVIEWER(retro_api_version); SYMBOL_IMAGEVIEWER(retro_get_system_info); SYMBOL_IMAGEVIEWER(retro_get_system_av_info); - + SYMBOL_IMAGEVIEWER(retro_set_environment); SYMBOL_IMAGEVIEWER(retro_set_video_refresh); SYMBOL_IMAGEVIEWER(retro_set_audio_sample); SYMBOL_IMAGEVIEWER(retro_set_audio_sample_batch); SYMBOL_IMAGEVIEWER(retro_set_input_poll); SYMBOL_IMAGEVIEWER(retro_set_input_state); - + SYMBOL_IMAGEVIEWER(retro_set_controller_port_device); - + SYMBOL_IMAGEVIEWER(retro_reset); SYMBOL_IMAGEVIEWER(retro_run); - + SYMBOL_IMAGEVIEWER(retro_serialize_size); SYMBOL_IMAGEVIEWER(retro_serialize); SYMBOL_IMAGEVIEWER(retro_unserialize); - + SYMBOL_IMAGEVIEWER(retro_cheat_reset); SYMBOL_IMAGEVIEWER(retro_cheat_set); - + SYMBOL_IMAGEVIEWER(retro_load_game); SYMBOL_IMAGEVIEWER(retro_load_game_special); - + SYMBOL_IMAGEVIEWER(retro_unload_game); SYMBOL_IMAGEVIEWER(retro_get_region); SYMBOL_IMAGEVIEWER(retro_get_memory_data); @@ -2004,33 +2004,33 @@ static void load_symbols(enum rarch_core_type type, struct retro_core_t *current #if defined(HAVE_NETWORKGAMEPAD) && defined(HAVE_NETPLAY) SYMBOL_NETRETROPAD(retro_init); SYMBOL_NETRETROPAD(retro_deinit); - + SYMBOL_NETRETROPAD(retro_api_version); SYMBOL_NETRETROPAD(retro_get_system_info); SYMBOL_NETRETROPAD(retro_get_system_av_info); - + SYMBOL_NETRETROPAD(retro_set_environment); SYMBOL_NETRETROPAD(retro_set_video_refresh); SYMBOL_NETRETROPAD(retro_set_audio_sample); SYMBOL_NETRETROPAD(retro_set_audio_sample_batch); SYMBOL_NETRETROPAD(retro_set_input_poll); SYMBOL_NETRETROPAD(retro_set_input_state); - + SYMBOL_NETRETROPAD(retro_set_controller_port_device); - + SYMBOL_NETRETROPAD(retro_reset); SYMBOL_NETRETROPAD(retro_run); - + SYMBOL_NETRETROPAD(retro_serialize_size); SYMBOL_NETRETROPAD(retro_serialize); SYMBOL_NETRETROPAD(retro_unserialize); - + SYMBOL_NETRETROPAD(retro_cheat_reset); SYMBOL_NETRETROPAD(retro_cheat_set); - + SYMBOL_NETRETROPAD(retro_load_game); SYMBOL_NETRETROPAD(retro_load_game_special); - + SYMBOL_NETRETROPAD(retro_unload_game); SYMBOL_NETRETROPAD(retro_get_region); SYMBOL_NETRETROPAD(retro_get_memory_data); @@ -2041,33 +2041,33 @@ static void load_symbols(enum rarch_core_type type, struct retro_core_t *current #if defined(HAVE_VIDEO_PROCESSOR) SYMBOL_VIDEOPROCESSOR(retro_init); SYMBOL_VIDEOPROCESSOR(retro_deinit); - + SYMBOL_VIDEOPROCESSOR(retro_api_version); SYMBOL_VIDEOPROCESSOR(retro_get_system_info); SYMBOL_VIDEOPROCESSOR(retro_get_system_av_info); - + SYMBOL_VIDEOPROCESSOR(retro_set_environment); SYMBOL_VIDEOPROCESSOR(retro_set_video_refresh); SYMBOL_VIDEOPROCESSOR(retro_set_audio_sample); SYMBOL_VIDEOPROCESSOR(retro_set_audio_sample_batch); SYMBOL_VIDEOPROCESSOR(retro_set_input_poll); SYMBOL_VIDEOPROCESSOR(retro_set_input_state); - + SYMBOL_VIDEOPROCESSOR(retro_set_controller_port_device); - + SYMBOL_VIDEOPROCESSOR(retro_reset); SYMBOL_VIDEOPROCESSOR(retro_run); - + SYMBOL_VIDEOPROCESSOR(retro_serialize_size); SYMBOL_VIDEOPROCESSOR(retro_serialize); SYMBOL_VIDEOPROCESSOR(retro_unserialize); - + SYMBOL_VIDEOPROCESSOR(retro_cheat_reset); SYMBOL_VIDEOPROCESSOR(retro_cheat_set); - + SYMBOL_VIDEOPROCESSOR(retro_load_game); SYMBOL_VIDEOPROCESSOR(retro_load_game_special); - + SYMBOL_VIDEOPROCESSOR(retro_unload_game); SYMBOL_VIDEOPROCESSOR(retro_get_region); SYMBOL_VIDEOPROCESSOR(retro_get_memory_data); @@ -2082,21 +2082,21 @@ @implementation PVLibRetroCoreBridge static void RETRO_CALLCONV audio_callback(int16_t left, int16_t right) { __strong PVLibRetroCoreBridge *strongCurrent = _current; - + [[strongCurrent ringBufferAtIndex:0] write:&left size:2]; [[strongCurrent ringBufferAtIndex:0] write:&right size:2]; - + strongCurrent = nil; } static size_t RETRO_CALLCONV audio_batch_callback(const int16_t *data, size_t frames) { __strong PVLibRetroCoreBridge *strongCurrent = _current; - + [[strongCurrent ringBufferAtIndex:0] write:data size:frames << 2]; - + strongCurrent = nil; - + return frames; } @@ -2104,15 +2104,15 @@ static void RETRO_CALLCONV video_callback(const void *data, unsigned width, unsi { // if (!video_driver_is_active()) // return; - + __strong PVLibRetroCoreBridge *strongCurrent = _current; - + static dispatch_queue_t serialQueue; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ dispatch_queue_attr_t queueAttributes = dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_CONCURRENT, QOS_CLASS_USER_INTERACTIVE, 0); serialQueue = dispatch_queue_create("com.provenance.video", queueAttributes); - + DLOG(@"vid: width: %i height: %i, pitch: %zu. _videoWidth: %f, _videoHeight: %f\n", width, height, pitch, strongCurrent.videoWidth, strongCurrent.videoHeight); }); // 512 @@ -2122,10 +2122,10 @@ static void RETRO_CALLCONV video_callback(const void *data, unsigned width, unsi size_t offset = y * shifted_pitch; const uint32_t *src = (uint16_t*)data + offset; uint32_t *dst = strongCurrent->videoBuffer + y * width; - + memcpy(dst, src, sizeof(uint32_t)*width); }); - + strongCurrent = nil; } @@ -2139,17 +2139,71 @@ static void RETRO_CALLCONV input_poll_callback(void) static int16_t RETRO_CALLCONV input_state_callback(unsigned port, unsigned device, unsigned index, unsigned _id) { //DLOG(@"polled input: port: %d device: %d id: %d", port, device, id); - + __strong PVLibRetroCoreBridge *strongCurrent = _current; int16_t value = 0; + + if (device == RETRO_DEVICE_MOUSE) { + /* + #define RETRO_DEVICE_ID_MOUSE_X 0 + #define RETRO_DEVICE_ID_MOUSE_Y 1 + #define RETRO_DEVICE_ID_MOUSE_LEFT 2 + #define RETRO_DEVICE_ID_MOUSE_RIGHT 3 + #define RETRO_DEVICE_ID_MOUSE_WHEELUP 4 + #define RETRO_DEVICE_ID_MOUSE_WHEELDOWN 5 + #define RETRO_DEVICE_ID_MOUSE_MIDDLE 6 + #define RETRO_DEVICE_ID_MOUSE_HORIZ_WHEELUP 7 + #define RETRO_DEVICE_ID_MOUSE_HORIZ_WHEELDOWN 8 + #define RETRO_DEVICE_ID_MOUSE_BUTTON_4 9 + #define RETRO_DEVICE_ID_MOUSE_BUTTON_5 10 + */ + switch (_id) { + case RETRO_DEVICE_ID_MOUSE_X: + NSLog(@"Polled for mouse X"); + break; + case RETRO_DEVICE_ID_MOUSE_Y: + NSLog(@"Polled for mouse Y"); + break; + case RETRO_DEVICE_ID_MOUSE_LEFT: + NSLog(@"Polled for mouse Left"); + break; + case RETRO_DEVICE_ID_MOUSE_RIGHT: + NSLog(@"Polled for mouse Right"); + break; + case RETRO_DEVICE_ID_MOUSE_WHEELUP: + NSLog(@"Polled for mouse WHEEL UP"); + break; + case RETRO_DEVICE_ID_MOUSE_WHEELDOWN: + NSLog(@"Polled for mouse WHEEL Down"); + break; + case RETRO_DEVICE_ID_MOUSE_MIDDLE: + NSLog(@"Polled for mouse Middle"); + break; + case RETRO_DEVICE_ID_MOUSE_HORIZ_WHEELUP: + NSLog(@"Polled for wheel up"); + break; + case RETRO_DEVICE_ID_MOUSE_HORIZ_WHEELDOWN: + NSLog(@"Polled for wheel down"); + break; + case RETRO_DEVICE_ID_MOUSE_BUTTON_4: + NSLog(@"Polled for button 4"); + break; + case RETRO_DEVICE_ID_MOUSE_BUTTON_5: + NSLog(@"Polled for mouse button 5"); + break; - if (port == 0 & device == RETRO_DEVICE_JOYPAD) + default: + NSLog(@"Polled for mouse UNHANDLED event %i", _id); + break; + } + } + else if (port == 0 & device == RETRO_DEVICE_JOYPAD) { if (strongCurrent.controller1) { value = [strongCurrent controllerValueForButtonID:_id forPlayer:port]; } - + if (value == 0) { value = strongCurrent->_pad[0][_id]; @@ -2161,15 +2215,15 @@ static int16_t RETRO_CALLCONV input_state_callback(unsigned port, unsigned devic { value = [strongCurrent controllerValueForButtonID:_id forPlayer:port]; } - + if (value == 0) { value = strongCurrent->_pad[1][_id]; } } - + strongCurrent = nil; - + return value; } @@ -2185,7 +2239,7 @@ - (instancetype)init { core = malloc(sizeof(retro_core_t)); init_libretro_sym(CORE_TYPE_PLAIN, core); retro_set_environment(environment_callback); - + memset(_pad, 0, sizeof(int16_t) * 24); // core_get_info(&info); @@ -2193,11 +2247,11 @@ - (instancetype)init { // std::cout << "Core needs fullpath " << info.need_fullpath << std::endl; // std::cout << "Running for " << maxframes << " frames with frame timeout of "; // std::cout << frametimeout << " seconds" << std::endl; - + // struct retro_system_info info; // bool load_no_info; // libretro_get_system_info("", &info, &load_no_info); - + videoBufferA = (uint32_t *)malloc(2560 * 2560 * sizeof(uint32_t)); videoBufferB = (uint32_t *)malloc(2560 * 2560 * sizeof(uint32_t)); videoBuffer = videoBufferA; @@ -2236,7 +2290,7 @@ - (BOOL)loadFileAtPath:(NSString *)path error:(NSError**)error { } [self coreInit]; - + // Load ROM data and retain it NSData *romData = [NSData dataWithContentsOfFile:path]; if (!romData) { @@ -2260,20 +2314,20 @@ - (BOOL)loadFileAtPath:(NSString *)path error:(NSError**)error { BOOL loaded = core->retro_load_game(&info); if (!loaded) { - struct retro_ctx_load_content_info info2; - info2.info = &info; - info2.content = nil; - info2.special = nil; + struct retro_ctx_load_content_info info2; + info2.info = &info; + info2.content = nil; + info2.special = nil; loaded = core_load_game(&info2); } - + if(loaded) { core->retro_reset(); } - + self->loaded = loaded; - + if(!loaded) { NSString *coreName = [self coreIdentifier]; NSString *errorMessage = FORMAT(@"%@ failed to load ROM for unknown reasons.", coreName); @@ -2286,7 +2340,7 @@ - (BOOL)loadFileAtPath:(NSString *)path error:(NSError**)error { if (error) { *error = [NSError errorWithDomain:CoreError.PVEmulatorCoreErrorDomain code:PVEmulatorCoreErrorCodeCouldNotLoadRom - userInfo:userInfo]; + userInfo:userInfo]; } } @@ -2321,7 +2375,7 @@ - (void)executeFrameSkippingFrame:(BOOL)skip { // soundBuffer[i] = (soundBuffer[i] << 16) | (soundBuffer[i] & 0xffff); // // [[self ringBufferAtIndex:0] write:soundBuffer maxLength:soundSize << 2]; - + } - (void)resetEmulation { @@ -2332,7 +2386,7 @@ - (void)stopEmulation { [super stopEmulation]; core->retro_unload_game(); - + // if (self->loaded) { // core->retro_reset(); // } @@ -2378,7 +2432,7 @@ - (CGRect)screenRect { // unsigned height = _videoHeight; // unsigned width = _videoWidth; - + return CGRectMake(0, 0, width, height); } @@ -2410,7 +2464,7 @@ - (CGSize)bufferSize { core->retro_get_system_av_info(&av_info); unsigned height = av_info.geometry.max_height; unsigned width = av_info.geometry.max_width; - + return CGSizeMake(width, height); } @@ -2489,7 +2543,7 @@ - (void)pollControllers { // TODO: This should warn or something if not in subclass for (NSInteger playerIndex = 0; playerIndex < 2; playerIndex++) { GCController *controller = nil; - + if (self.controller1 && playerIndex == 0) { controller = self.controller1; } @@ -2497,13 +2551,13 @@ - (void)pollControllers { { controller = self.controller2; } - + if ([controller extendedGamepad]) { GCExtendedGamepad *gamepad = [controller extendedGamepad]; GCControllerDirectionPad *dpad = [gamepad dpad]; - + /* TODO: To support paddles we would need to circumvent libRetro's emulation of analog controls or drop libRetro and talk to stella directly like OpenEMU did */ - + // D-Pad _pad[playerIndex][RETRO_DEVICE_ID_JOYPAD_UP] = (dpad.up.isPressed || gamepad.leftThumbstick.up.isPressed); _pad[playerIndex][RETRO_DEVICE_ID_JOYPAD_DOWN] = (dpad.down.isPressed || gamepad.leftThumbstick.down.isPressed); @@ -2525,13 +2579,13 @@ - (void)pollControllers { _pad[playerIndex][RETRO_DEVICE_ID_JOYPAD_A] = gamepad.buttonB.isPressed || gamepad.rightTrigger.isPressed; // Booster _pad[playerIndex][RETRO_DEVICE_ID_JOYPAD_X] = gamepad.buttonX.isPressed || gamepad.buttonY.isPressed || gamepad.leftTrigger.isPressed; - + // Reset _pad[playerIndex][RETRO_DEVICE_ID_JOYPAD_START] = gamepad.rightShoulder.isPressed; - + // Select _pad[playerIndex][RETRO_DEVICE_ID_JOYPAD_SELECT] = gamepad.leftShoulder.isPressed; - + /* #define RETRO_DEVICE_ID_JOYPAD_B 0 == JoystickZeroFire1 #define RETRO_DEVICE_ID_JOYPAD_Y 1 == Unmapped @@ -2553,32 +2607,32 @@ - (void)pollControllers { } else if ([controller gamepad]) { GCGamepad *gamepad = [controller gamepad]; GCControllerDirectionPad *dpad = [gamepad dpad]; - + // D-Pad _pad[playerIndex][RETRO_DEVICE_ID_JOYPAD_UP] = dpad.up.isPressed; _pad[playerIndex][RETRO_DEVICE_ID_JOYPAD_DOWN] = dpad.down.isPressed; _pad[playerIndex][RETRO_DEVICE_ID_JOYPAD_LEFT] = dpad.left.isPressed; _pad[playerIndex][RETRO_DEVICE_ID_JOYPAD_RIGHT] = dpad.right.isPressed; - + // Fire _pad[playerIndex][RETRO_DEVICE_ID_JOYPAD_B] = gamepad.buttonA.isPressed; // Trigger _pad[playerIndex][RETRO_DEVICE_ID_JOYPAD_A] = gamepad.buttonB.isPressed; // Booster _pad[playerIndex][RETRO_DEVICE_ID_JOYPAD_X] = gamepad.buttonX.isPressed || gamepad.buttonY.isPressed; - + // Reset _pad[playerIndex][RETRO_DEVICE_ID_JOYPAD_START] = gamepad.rightShoulder.isPressed; - + // Select _pad[playerIndex][RETRO_DEVICE_ID_JOYPAD_SELECT] = gamepad.leftShoulder.isPressed; - + } #if TARGET_OS_TV else if ([controller microGamepad]) { GCMicroGamepad *gamepad = [controller microGamepad]; GCControllerDirectionPad *dpad = [gamepad dpad]; - + _pad[playerIndex][RETRO_DEVICE_ID_JOYPAD_UP] = dpad.up.value > 0.5; _pad[playerIndex][RETRO_DEVICE_ID_JOYPAD_DOWN] = dpad.down.value > 0.5; _pad[playerIndex][RETRO_DEVICE_ID_JOYPAD_LEFT] = dpad.left.value > 0.5; @@ -2765,11 +2819,11 @@ - (BOOL)loadStateFromFileAtPath:(NSString *)fileName error:(NSError**)error { NSLocalizedFailureReasonErrorKey: @"Core failed to load save state.", NSLocalizedRecoverySuggestionErrorKey: @"" }; - + NSError *newError = [NSError errorWithDomain:PVEmulatorCoreErrorDomain code:PVEmulatorCoreErrorCodeCouldNotLoadState userInfo:userInfo]; - + *error = newError; } } @@ -2807,6 +2861,39 @@ - (void)setCheat:(NSString *)code setType:(NSString *)type setEnabled:(BOOL)enab @end +@implementation PVLibRetroCoreBridge (Touches) +- (void)sendEvent:(UIEvent *)event { + [super sendEvent:event]; + + if (event.type != UIEventTypeTouches) { + return; + } + + if([self conformsToProtocol:@protocol(MouseResponder)] && [self gameSupportsMouse]) { + // UITouch *touch = [[event touchesForView:nil] anyObject]; + // if (!touch) { + // self.touchActive = NO; + // return; + // } + // + // CGPoint location = [touch locationInView:nil]; + // CGRect bounds = [UIScreen mainScreen].bounds; + // + // // Convert to relative coordinates for mouse movement + // self.currentTouchPoint = CGPointMake( + // ((location.x / bounds.size.width) * 256), + // ((location.y / bounds.size.height) * 192) + // ); + // + // self.touchActive = (touch.phase != UITouchPhaseEnded && + // touch.phase != UITouchPhaseCancelled); + // + // extern bool touchEnabled; + // touchEnabled = self.touchActive; + } +} +@end + unsigned retro_api_version(void) { return RETRO_API_VERSION;