diff --git a/src/MeloNX/MeloNX.xcodeproj/project.xcworkspace/xcuserdata/stossy11.xcuserdatad/UserInterfaceState.xcuserstate b/src/MeloNX/MeloNX.xcodeproj/project.xcworkspace/xcuserdata/stossy11.xcuserdatad/UserInterfaceState.xcuserstate
index 471ce6b6f..faefc819f 100644
Binary files a/src/MeloNX/MeloNX.xcodeproj/project.xcworkspace/xcuserdata/stossy11.xcuserdatad/UserInterfaceState.xcuserstate and b/src/MeloNX/MeloNX.xcodeproj/project.xcworkspace/xcuserdata/stossy11.xcuserdatad/UserInterfaceState.xcuserstate differ
diff --git a/src/MeloNX/MeloNX/Core/Swift/Controller/VirtualController.swift b/src/MeloNX/MeloNX/Core/Swift/Controller/VirtualController.swift
index 6c451f2cd..7809ee7ec 100644
--- a/src/MeloNX/MeloNX/Core/Swift/Controller/VirtualController.swift
+++ b/src/MeloNX/MeloNX/Core/Swift/Controller/VirtualController.swift
@@ -6,11 +6,15 @@
 //
 
 import Foundation
+import CoreHaptics
+import UIKit
 
 class VirtualController {
     private var instanceID: SDL_JoystickID = -1
     private var controller: OpaquePointer?
     
+    public let controllername = "MeloNX Touch Controller"
+    
     init() {
         setupVirtualController()
     }
@@ -22,7 +26,45 @@ class VirtualController {
         }
         
         // Create virtual controller
-        instanceID = SDL_JoystickAttachVirtual(SDL_JoystickType(SDL_JOYSTICK_TYPE_GAMECONTROLLER.rawValue), 6, 15, 1)
+        var joystickDesc = SDL_VirtualJoystickDesc(
+            version: UInt16(SDL_VIRTUAL_JOYSTICK_DESC_VERSION),
+            type: Uint16(SDL_JOYSTICK_TYPE_GAMECONTROLLER.rawValue),
+                naxes: 6,
+                nbuttons: 15,
+                nhats: 1,
+                vendor_id: 0,
+                product_id: 0,
+                padding: 0,
+                button_mask: 0,
+                axis_mask: 0,
+                name: controllername.withCString { $0 },
+                userdata: nil,
+                Update: { userdata in
+                    // Update joystick state here
+                },
+                SetPlayerIndex: { userdata, playerIndex in
+                    print("Player index set to \(playerIndex)")
+                },
+                Rumble: { userdata, lowFreq, highFreq in
+                    print("Rumble with \(lowFreq), \(highFreq)")
+                    VirtualController.rumble(lowFreq: Float(lowFreq), highFreq: Float(highFreq))
+                    return 0
+                },
+                RumbleTriggers: { userdata, leftRumble, rightRumble in
+                    print("Trigger rumble with \(leftRumble), \(rightRumble)")
+                    return 0
+                },
+                SetLED: { userdata, red, green, blue in
+                    print("Set LED to RGB(\(red), \(green), \(blue))")
+                    return 0
+                },
+                SendEffect: { userdata, data, size in
+                    print("Effect sent with size \(size)")
+                    return 0
+                }
+            )
+        
+        instanceID = SDL_JoystickAttachVirtualEx(&joystickDesc)// SDL_JoystickAttachVirtual(SDL_JoystickType(SDL_JOYSTICK_TYPE_GAMECONTROLLER.rawValue), 6, 15, 1)
         if instanceID < 0 {
             print("Failed to create virtual joystick: \(String(cString: SDL_GetError()))")
             return
@@ -38,16 +80,58 @@ class VirtualController {
         }
     }
     
+    static func rumble(lowFreq: Float, highFreq: Float) {
+        do {
+            // Low-frequency haptic pattern
+            let lowFreqPattern = try CHHapticPattern(events: [
+                CHHapticEvent(eventType: .hapticTransient, parameters: [
+                    CHHapticEventParameter(parameterID: .hapticIntensity, value: lowFreq),
+                    CHHapticEventParameter(parameterID: .hapticSharpness, value: 0.5)
+                ], relativeTime: 0, duration: 0.2)
+            ], parameters: [])
+
+            // High-frequency haptic pattern
+            let highFreqPattern = try CHHapticPattern(events: [
+                CHHapticEvent(eventType: .hapticTransient, parameters: [
+                    CHHapticEventParameter(parameterID: .hapticIntensity, value: highFreq),
+                    CHHapticEventParameter(parameterID: .hapticSharpness, value: 1.0)
+                ], relativeTime: 0.2, duration: 0.2)
+            ], parameters: [])
+
+            // Create and start the haptic engine
+            let engine = try CHHapticEngine()
+            try engine.start()
+
+            // Create and play the low-frequency player
+            let lowFreqPlayer = try engine.makePlayer(with: lowFreqPattern)
+            try lowFreqPlayer.start(atTime: 0)
+
+            // Create and play the high-frequency player after a short delay
+            let highFreqPlayer = try engine.makePlayer(with: highFreqPattern)
+            try highFreqPlayer.start(atTime: 0.2)
+
+        } catch {
+            print("Error creating haptic patterns: \(error)")
+        }
+    }
+
+    
     func updateAxisValue(value: Sint16, forAxis axis: SDL_GameControllerAxis) {
         guard controller != nil else { return }
         let joystick = SDL_JoystickFromInstanceID(instanceID)
         SDL_JoystickSetVirtualAxis(joystick, axis.rawValue, value)
     }
     
-    func thumbstickMoved(_ stick: ThumbstickType, x: Float, y: Float) {
+    func thumbstickMoved(_ stick: ThumbstickType, x: Double, y: Double) {
         // Convert float values (-1.0 to 1.0) to SDL axis values (-32768 to 32767)
-        let scaledX = Sint16(x * 32767.0)
-        let scaledY = Sint16(y * 32767.0)
+        var scaleFactor = 32767.0
+        if UIDevice.current.systemName.contains("iPadOS") {
+            scaleFactor /= (160 * 1.2)
+        } else {
+            scaleFactor /= 160
+        }
+        let scaledX = Int16(min(32767.0, max(-32768.0, x * scaleFactor)))
+        let scaledY = Int16(min(32767.0, max(-32768.0, y * scaleFactor)))
         
         if stick == .right {
             updateAxisValue(value: scaledX, forAxis: SDL_GameControllerAxis(SDL_CONTROLLER_AXIS_RIGHTX.rawValue))
diff --git a/src/MeloNX/MeloNX/Core/Swift/Controller/WaitforVC.swift b/src/MeloNX/MeloNX/Core/Swift/Controller/WaitforVC.swift
index f5f0b91f7..eb02333eb 100644
--- a/src/MeloNX/MeloNX/Core/Swift/Controller/WaitforVC.swift
+++ b/src/MeloNX/MeloNX/Core/Swift/Controller/WaitforVC.swift
@@ -33,13 +33,16 @@ func waitforcontroller() {
         }
         
         let controllerView = ControllerView()
-
         let hostingController = UIHostingController(rootView: controllerView)
-        
-        hostingController.view.frame = window.bounds  // Set the frame of the SwiftUI view
+
+        // Create the custom container
+        let containerView = TransparentHostingContainerView(frame: window.bounds)
+        containerView.backgroundColor = .clear
+
+        hostingController.view.frame = containerView.bounds
         hostingController.view.backgroundColor = .clear
-        
-        
+        containerView.addSubview(hostingController.view)
+
         Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true) { timer in
             if findGCControllerView(in: window) == nil {
                 window.addSubview(hostingController.view)
@@ -50,3 +53,14 @@ func waitforcontroller() {
 
     }
 }
+
+
+class TransparentHostingContainerView: UIView {
+    override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
+        // Check if the point is within the subviews of this container
+        let view = super.hitTest(point, with: event)
+        
+        // Return nil if the touch is outside visible content (passes through to views below)
+        return view === self ? nil : view
+    }
+}
diff --git a/src/MeloNX/MeloNX/Views/ContentView.swift b/src/MeloNX/MeloNX/Views/ContentView.swift
index ae3e752b8..2bec99b62 100644
--- a/src/MeloNX/MeloNX/Views/ContentView.swift
+++ b/src/MeloNX/MeloNX/Views/ContentView.swift
@@ -154,7 +154,7 @@ struct ContentView: View {
         Timer.scheduledTimer(withTimeInterval: 0.5, repeats: false) { _ in
             controllersList = Ryujinx.shared.getConnectedControllers()
             
-            if let onscreen = controllersList.first(where: { $0.name == "Virtual Controller" }) {
+            if let onscreen = controllersList.first(where: { $0.name == Ryujinx.shared.virtualController.controllername }) {
                 self.onscreencontroller = onscreen
             }
             
diff --git a/src/MeloNX/MeloNX/Views/ControllerView/ControllerView.swift b/src/MeloNX/MeloNX/Views/ControllerView/ControllerView.swift
index bdbf1e846..0301b75cf 100644
--- a/src/MeloNX/MeloNX/Views/ControllerView/ControllerView.swift
+++ b/src/MeloNX/MeloNX/Views/ControllerView/ControllerView.swift
@@ -87,6 +87,7 @@ struct ControllerView: View {
                 }
             }
         }
+        .padding()
     }
 }
 
diff --git a/src/MeloNX/MeloNX/Views/ControllerView/Joystick/JoystickView.swift b/src/MeloNX/MeloNX/Views/ControllerView/Joystick/JoystickView.swift
index 70b190ea7..dc1db3d8c 100644
--- a/src/MeloNX/MeloNX/Views/ControllerView/Joystick/JoystickView.swift
+++ b/src/MeloNX/MeloNX/Views/ControllerView/Joystick/JoystickView.swift
@@ -39,13 +39,13 @@ public struct Joystick: View {
                 locksInPlace: false)
             .onChange(of: self.joystickMonitor.xyPoint) { newValue in
                 let scaledX = Float(newValue.x)
-                let scaledY = Float(newValue.y) // my dumbass broke this by having -y instead of y :/ 
+                let scaledY = Float(newValue.y) // my dumbass broke this by having -y instead of y :/
                 print("Joystick Position: (\(scaledX), \(scaledY))")
                 
                 if iscool != nil {
-                    Ryujinx.shared.virtualController.thumbstickMoved(.right, x: scaledX, y: scaledY)
+                    Ryujinx.shared.virtualController.thumbstickMoved(.right, x: newValue.x, y: newValue.y)
                 } else {
-                    Ryujinx.shared.virtualController.thumbstickMoved(.left, x: scaledX, y: scaledY)
+                    Ryujinx.shared.virtualController.thumbstickMoved(.left, x: newValue.x, y: newValue.y)
                 }
             }
         }