Processing Ajax...

Title
Close Dialog

Message

Confirm
Close Dialog

Confirm
Close Dialog

Confirm
Close Dialog

Rocksmith 2014 USB Cable Hack

Description
This function is to be used with a Window Location Rule or a Hotkey. It will force Rocksmith 2014 to look for your own USB guitar cable if you don't own the Real Tone cable.
Language
C#.net
Minimum Version
Created By
Thomas Malloch (BFS)
Contributors
-
Date Created
Mar 23, 2015
Date Last Modified
Mar 23, 2015

Scripted Function (Macro) Code

using System;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Diagnostics;

// The 'windowHandle' parameter will contain the window handle for the:
// - Active window when run by hotkey
// - Window Location target when run by a Window Location rule
// - TitleBar Button owner when run by a TitleBar Button
// - Jump List owner when run from a Taskbar Jump List
// - Currently focused window if none of these match

//This function is to be used with a Window Location Rule or a Hotkey
//It will get Rocksmith 2014 to look for your own USB guitar cable if you don't own the Real Tone cable
public static class DisplayFusionFunction
{
	[DllImport("kernel32.dll", EntryPoint = "ReadProcessMemory")]
	public static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] buffer, uint size, out uint lpNumberOfBytesRead);

	[DllImport("kernel32.dll", EntryPoint = "WriteProcessMemory")]
	public static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] buffer, uint size, out uint lpNumberOfBytesWritten);

	/*
	to get the PID and VID of your cable: 
	1) Right click on the speaker icon on your taskbar and select 'Recording Devices'. 
	2) Find your cable and right click on it and select Properties
	3) Click the Properties button again on the General tab
	4) To to the details tab of the new window
	5) Select 'Hardware Ids' from the dropdown
	6) There should be a string that looks something like this:

	USB\VID_0D8C&PID_0139&REV_0100&MI_00

	The 4 character after the VID_ is your VID, and the 4 characters after the PID_ is your PID.	
	Enter those values into the static arrays below.
	*/

	//the vender id of your cable
	private static byte[] VID = new byte[] {0x0D, 0x8C};

	//the product id of your cable
	private static byte[] PID = new byte[] {0x01, 0x39};

	public static void Run(IntPtr windowHandle)
	{//if this isn't a rocksmith window, exit
		if (BFS.Application.GetMainFileByWindow(windowHandle).IndexOf("rocksmith", StringComparison.OrdinalIgnoreCase) == -1)
			return;

		//put the arrays into the proper bitness order
		Array.Reverse(VID);
		Array.Reverse(PID);

		//get the rocksmith 2014 process
		Process rocksmith = Process.GetProcessById((int)BFS.Application.GetAppIDByWindow(windowHandle));
		if (rocksmith == null)
			return;

		//get the first address that we want to search. my version of rocksmith 2014 i find the value around 17000.
		//offset the first search address to speed things up
		IntPtr current = new IntPtr(rocksmith.MainModule.BaseAddress.ToInt64() + 10000);
		long end = rocksmith.MainModule.ModuleMemorySize + rocksmith.MainModule.BaseAddress.ToInt64();

		//Search for the value F806BA12
		byte[] desiredAddress = new byte[] {0xF8, 0x06, 0xBA, 0x12};
		byte[] buffer = new byte[4];
		while (current.ToInt64() < end)
		{
			uint numberOfBytesRead;

			//read some memory
			if (!ReadProcessMemory(rocksmith.Handle, current, buffer, (uint)buffer.Length, out numberOfBytesRead))
				return;

			//couldnt read enough data
			if (numberOfBytesRead != (uint)buffer.Length)
				return;

			//check to see if we were lucky enough to get the address
			if (BitConverter.ToInt32(buffer, 0) == BitConverter.ToInt32(desiredAddress, 0))
				break;

			//check to see if the array contains the first element in the desired result
			bool found = false;
			for (int i = 1; i < buffer.Length; i++)
			{
				if (buffer[i] != desiredAddress[0])
					continue;

			//found it, grab the 4 bytes
				current = new IntPtr(current.ToInt64() + i);
				if (!ReadProcessMemory(rocksmith.Handle, current, buffer, (uint)buffer.Length, out numberOfBytesRead))
					return;

			//check to see if its what we want
				if (BitConverter.ToInt32(buffer, 0) == BitConverter.ToInt32(desiredAddress, 0))
					found = true;

				break;
			}

			if (found == true)
				break;

			//increment the pointer
			current = new IntPtr(current.ToInt64() + (uint)buffer.Length);
		}

		//write the memory
		// Susbtitute the BA 12 with YOUR cable's vendor ID
		// BA 12 is offset by 2 in F806BA12
		current = new IntPtr(current.ToInt64() + 2);
		uint numberOfByteWritten;
		if (!WriteProcessMemory(rocksmith.Handle, current, VID, 2, out numberOfByteWritten))
			return;

		//Locate FF 00 in the line below
		desiredAddress = new byte[] {0xFF, 0x00};
		buffer = new byte[2];
		while (current.ToInt64() < end)
		{
			uint numberOfBytesRead;
			//read some memory
			if (!ReadProcessMemory(rocksmith.Handle, current, buffer, (uint)desiredAddress.Length, out numberOfBytesRead))
				return;

			//couldnt read enough data
			if (numberOfBytesRead != desiredAddress.Length)
				return;

			//check to see if we were lucky enough to get the address
			if (BitConverter.ToInt16(desiredAddress, 0) == BitConverter.ToInt16(buffer, 0))
				break;

			//check to see if the array contains the first element in the desired result
			bool found = false;
			for (int i = 1; i < buffer.Length; i++)
			{
				if (buffer[i] != desiredAddress[0])
					continue;

			//found it, grab the 4 bytes
				current = new IntPtr(current.ToInt64() + i);
				if (!ReadProcessMemory(rocksmith.Handle, current, buffer, (uint)buffer.Length, out numberOfBytesRead))
					return;

			//check to see if its what we want
				if (BitConverter.ToInt16(buffer, 0) == BitConverter.ToInt16(desiredAddress, 0))
					found = true;

				break;
			}

			if (found == true)
				break;

			//increment the pointer
			current = new IntPtr(current.ToInt64() + desiredAddress.Length);
		}

		if (current.ToInt64() >= end)
			return;

		//substitute 0xff00 with YOUR cable's product ID
		if (!WriteProcessMemory(rocksmith.Handle, current, PID, (uint)desiredAddress.Length, out numberOfByteWritten))
			return;
	}
}