User File #28485160549799088

Upload All User Files

#28485160549799088 - Auto Analog Input v1.91 (now with "tastudio support", don'T use it)

AutoInput.lua
System: Nintendo 64
749 downloads
Uploaded 1/26/2016 7:40 PM by TASeditor (see all 188)
some fixes and rudimentary tastudio support, you need to type in the values that appear at the bottom of the window manually into the columns.
-- Auto analog input script written by TASeditor
-- Main window
-- This function runs after the user clicked on the Start button.
function Start()

	if PauseFlag == false
	then if StartFlag == false
		 then if forms.ischecked(PosCheck) and not forms.ischecked(AngCheck)
			  then CalcAngle();
				   FollowAngle = forms.gettext(AngFollowTxt);
				   Radius = forms.gettext(RadiusTxt);
				   --savestate.saveslot(0);
				   StartFlag = true;
				   forms.settext(StatLabel, "Started");
				   -- if forms.ischecked(AdvCheck)
				   -- then AdvMode = true;
				   -- else AdvMode = false;
				   -- end;
				   --X_0 = XPosition;
				   --Y_0 = YPosition;
				   --frame_start = emu.framecount();
			  elseif not forms.ischecked(PosCheck) and forms.ischecked(AngCheck)
				  then FollowAngle = forms.gettext(AngFollowTxt);
					   Radius = forms.gettext(RadiusTxt);
					   --savestate.saveslot(0);
					   StartFlag = true;
					   forms.settext(StatLabel, "Started");
				  elseif forms.ischecked(PosCheck) and forms.ischecked(AngCheck)
					  then forms.settext(StatLabel, "Error: Uncheck one checkbox");
					  
			  end;
		 end;
	end;
	
end;

-- This function runs after the user clicked on the Pause button.
function Pause()

	if StartFlag == true
	then if PauseFlag == false
		 then PauseFlag = true;
			  forms.settext(StatLabel, "Paused");
			  forms.settext(PauseButton, "Continue");
			  client.pause();
			  Xinput["P1 X Axis"] = 0;
			  Yinput["P1 Y Axis"] = 0;
			  joypad.setanalog(Xinput);
			  joypad.setanalog(Yinput);
		 else PauseFlag = false
			  forms.settext(StatLabel, "Started");
			  forms.settext(PauseButton, "Pause");
		 end;
	end;

end;

-- This function runs after the user clicked on the Stop button.
function Stop()

	if StartFlag == true
	then StartFlag = false;
		 PauseFlag = false;
		 forms.settext(StatLabel, "Stopped");
		 forms.settext(PauseButton, "Pause");
		 client.pause();
		 Xinput["P1 X Axis"] = 0;
		 Yinput["P1 Y Axis"] = 0;
		 joypad.setanalog(Xinput);
		 joypad.setanalog(Yinput);
		 X = 0;
		 Y = 0;
	end;

end;

-- These functions run after the user clicked the "+" or "-" button.
function Add()

	console.writeline("not implemented");

end;

function Sub()

	console.writeline("not implemented");

end;

function CalcAngle()

	DeltaX = forms.gettext(XPosGotoTxt) - memory.readfloat(XPosAddr, true);
	DeltaY = forms.gettext(YPosGotoTxt) - memory.readfloat(YPosAddr, true);
	Distance = math.sqrt(DeltaX^2 + DeltaY^2);
	
	if FloatBool == "true"
	then Alpha = math.atan2(DeltaX , DeltaY) * 180 / math.pi;
	else Alpha = math.floor(math.atan2(DeltaX , DeltaY) * 32768/math.pi + 0.5);
	end;
	
	forms.settext(AngFollowTxt, Alpha);
		
end;

-- This function creates the main window.
function WindowForm()

	Window = forms.newform(300, 500, "Auto analog input");

	PosCheck = forms.checkbox(Window, "Go to position:", 5, 20); 
	forms.label(Window, "X =", 110, 10, 30, 15);
	XPosGotoTxt = forms.textbox(Window, "0", 120, 20, nil, 140, 5);
	forms.label(Window, "Y =", 110, 40, 30, 15);
	YPosGotoTxt = forms.textbox(Window, "0", 120, 20, nil, 140, 35);
	
	AngCheck = forms.checkbox(Window, "Follow angle:", 5, 75);
	forms.label(Window, "a =", 110, 80, 30, 15);
	AngFollowTxt = forms.textbox(Window, "0", 120, 20, nil, 140, 75);
	
	forms.label(Window, "Radius =", 5, 120, 50, 15);
	RadiusTxt = forms.textbox(Window, "127", 30, 20, nil, 60, 115);
	
	forms.button(Window, "+", Add, 205, 115, 23,23);
	forms.button(Window, "-", Sub, 180, 115, 23,23);
	
	forms.label(Window, "Status:", 5, 150, 40, 15);
	StatLabel = forms.label(Window, "Stopped", 45, 150, 200, 15);
	
	forms.button(Window, "Start", Start, 5, 180);
	PauseButton = forms.button(Window, "Pause", Pause, 105, 180);
	forms.button(Window, "Stop", Stop, 205, 180);
	
	forms.label(Window, "Information:", 5, 220, 70, 15);
	
	forms.label(Window, "Current angle:", 5, 240, 80, 15);
	CurrAngLabel = forms.label(Window, "", 85, 240, 40, 15);
	forms.label(Window, "Difference:", 130, 240, 60, 15);
	DiffCurrAngLabel = forms.label(Window, "", 200, 240, 40, 15);
	
	forms.label(Window, "Best angle:", 5, 260, 60, 15);
	BestAngLabel = forms.label(Window, "", 85, 260, 40, 15);
	forms.label(Window, "Difference:", 130, 260, 60, 15);
	DiffBestAngLabel = forms.label(Window, "", 200, 260, 40, 15);
	
	--OptCheck = forms.checkbox(Window, "Optimize", 5, 280);
	
	if tastudio.engaged()
	then xLabel = forms.label(Window, "", 5, 280, 30, 15);
		 yLabel = forms.label(Window, "", 40, 280, 30, 15);
	end;

end;

 -- Address window
-- This function checks wheter the user has typed in the memory addresses or not.
-- It doesn't check if the typed address is the correct one.
-- The "0x" should not be deleted.
function Check()
	
	-- Reading the addresses as a string.
	XPosAddr = forms.gettext(XPosAddrTxt);
	YPosAddr = forms.gettext(YPosAddrTxt);
	MovAngAddr = forms.gettext(MovAngAddrTxt);
	CamAngAddr = forms.gettext(CamAngAddrTxt);
	FloatBool = forms.ischecked(FloatCheck);
	
	if XPosAddr ~= "0x" and YPosAddr ~= "0x" and MovAngAddr ~= "0x" and CamAngAddr ~= "0x"
	then -- Converting the string into an integer number.
		 XPosAddr = tonumber(XPosAddr); 
	     YPosAddr = tonumber(YPosAddr);
	     MovAngAddr = tonumber(MovAngAddr);
		 CamAngAddr = tonumber(CamAngAddr);
		 
		 -- Writes the addresses into a text file.
		 -- The user doesn't have to type in the addresses everytime.
		 AddrFile = io.open(ROMname, "a");
		 AddrFile:write(XPosAddr, "\n", YPosAddr, "\n", MovAngAddr, "\n", CamAngAddr, "\n", tostring(FloatBool));
		 AddrFile:close();
		 
		 -- Closes the form where the user typed in the addresses.
		 forms.destroy(Addr);
		 WindowForm();
	end;
	
end;

-- This function creates the form where the user needs to type in memory addresses.
function AddrForm()

	Addr = forms.newform(320, 230, "Memory addresses");
	
	forms.label(Addr, "Type in horizontal position addresses:", 5, 5, 280, 20);
	forms.label(Addr, "X =",5, 30, 30, 15);
	XPosAddrTxt = forms.textbox(Addr, "0x", 70, 20, nil, 40, 25);
	forms.label(Addr, "Y =",120, 30, 30, 15); 
	YPosAddrTxt = forms.textbox(Addr, "0x", 70, 20, nil, 155, 25);
	
	forms.label(Addr, "Type in horizontal movement angle address:", 5, 55, 350, 20);
	forms.label(Addr, "a =", 5, 80, 30, 15); 
	MovAngAddrTxt = forms.textbox(Addr, "0x", 70, 20, nil, 40, 75);
	FloatCheck = forms.checkbox(Addr, "Float?", 120, 75);
	
	forms.label(Addr, "Type in horizontal camera angle address:", 5, 100, 340, 20);
	forms.label(Addr, "b =", 5, 125, 30, 15);
	CamAngAddrTxt = forms.textbox(Addr, "0x", 70, 20, nil, 40, 120);
	
	forms.button(Addr, "Done", Check, 5, 160);

end;

-- Reads out the memory addresses from the file, if there's content in the file.
-- The memory addresses are saved in decimal numbers.
-- The file is in the main BizHawk folder and is called "<romname>.txt".
-- The main window will open.

XPosAddr = nil;
YPosAddr = nil;
MovAngAddr = nil;
CamAngAddr = nil;
FloatBool = nil;
AddrFile = nil;

ROMname = gameinfo.getromname()..".txt";
AddrFile = io.open(ROMname, "r");

if AddrFile ~= nil
then XPosAddr = tonumber(AddrFile:read("*line"));
     YPosAddr = tonumber(AddrFile:read("*line"));
     MovAngAddr = tonumber(AddrFile:read("*line"));
	 CamAngAddr = tonumber(AddrFile:read("*line"));
	 FloatBool = (AddrFile:read("*line"));
	 WindowForm(); 
	 AddrFile:close();
end;
 
-- If there's no content in the file a window will open, where the user types in the memory addresses once.
if XPosAddr == nil and YPosAddr == nil and MovAngAddr == nil and CamAngAddr == nil and FloatBool == nil
then AddrForm();
	 -- Prevents crash.
	 XPosAddr = 0;
	 YPosAddr = 0;
	 MovAngAddr = 0;
	 CamAngAddr = 0;
	 FloatBool = false;
end



--**************************************************************************************************--
--Brute force script																				--
--**************************************************************************************************--

Xinput = {};
Yinput = {};

StartFlag = false;
PauseFlag = false;
X = 0; Y = 0;
CamAngle = 0;
InputAngle = 0;
Radius = 0;
--Steps = 1;
done = false;
--j = 0;
--diff = 10;
--bestdiff = 10;
-- X_0=0; Y_0=0;
-- X_g=0; Y_g=0;
-- X_b=0; Y_b=0;
-- frame_start = 0;
f=0;
f_old=0;

function CreateInput()

	if FloatBool == "true"
	then InputAngle = ((FollowAngle - CamAngle - 90) % 360)*math.pi/180; --console.writeline("Flt InA"..InputAngle);
	else InputAngle = ((FollowAngle - CamAngle - 49152) % 65536)*math.pi/32768; --console.writeline("Int InA"..InputAngle);
	end; 
	
	
	Xbest = math.floor(math.cos(InputAngle)*Radius+0.5); --console.writeline("X"..X);
	Ybest = math.floor(math.sin(InputAngle)*Radius+0.5); --console.writeline("Y"..Y);
	-- X = Xbest
	-- Y = Ybest
	
	-- InputAngleInt = math.atan2(Y, X); --console.writeline(InputAngle.." "..InputAngleInt);
		
	-- if InputAngleInt == InputAngle
	-- then --console.writeline("perfect");
	-- else 	
		-- repeat
		
			-- if Steps % 2 == 0
			-- then for i = 1,Steps,1 do
					-- X = X - 1;
					-- InputAngleInt = math.atan2(Y, X); --console.writeline(X.." "..Y.." "..Steps);
					-- diff = math.abs(InputAngleInt - InputAngle);
					-- if diff < bestdiff then Xbest = X; Ybest = Y; bestdiff = diff; end;
				 -- end;
				 -- if InputAngleInt == InputAngle then Xbest = X; Ybest = Y; break; end; 
				 -- for i = 1,Steps,1 do
					 -- Y = Y - 1;
					 -- InputAngleInt = math.atan2(Y, X); --console.writeline(X.." "..Y.." "..Steps);
					 -- diff = math.abs(InputAngleInt - InputAngle);
					-- if diff < bestdiff then Xbest = X; Ybest = Y; bestdiff = diff; end;
				 -- end;
				 -- if InputAngleInt == InputAngle then Xbest = X; Ybest = Y; break; end;	
			-- else for i = 1,Steps,1 do
					 -- X = X + 1;
					 -- InputAngleInt = math.atan2(Y, X); --console.writeline(X.." "..Y.." "..Steps);
					 -- diff = math.abs(InputAngleInt - InputAngle);
					 -- if diff < bestdiff then Xbest = X; Ybest = Y; bestdiff = diff; end;
				 -- end;
				 -- if InputAngleInt == InputAngle then Xbest = X; Ybest = Y; break; end;
				
				 -- for i = 1,Steps,1 do
					 -- Y = Y + 1;
					 -- InputAngleInt = math.atan2(Y, X); --console.writeline(X.." "..Y.." "..Steps);
					 -- diff = math.abs(InputAngleInt - InputAngle);
					 -- if diff < bestdiff then Xbest = X; Ybest = Y; bestdiff = diff; end;
				 -- end;
				 -- if InputAngleInt == InputAngle then Xbest = X; Ybest = Y; break; end;
				
			-- end;
			-- Steps = Steps + 1;
			-- j = j +1;
		-- until j == 100 --how long does this need to run?
		
		-- Steps = 1;
		
	-- end
	 done = true;
	-- console.writeline("test");
	-- j = 0;
end;

function BruteForce()

	XPosition = memory.readfloat(XPosAddr, true);
	YPosition = memory.readfloat(YPosAddr, true);
	if FloatBool == "true"
	then MovAngle = memory.readfloat(MovAngAddr, true);
		 CamAngle = memory.readfloat(CamAngAddr, true);
	else MovAngle = memory.read_u16_be(MovAngAddr);
		 CamAngle = memory.read_u16_be(CamAngAddr);
	end;
	
	
	CreateInput(); -- only call this function once every frame

	if tastudio.engaged()
	then forms.settext(xLabel, Xbest);
		 forms.settext(yLabel, Ybest);
	else 
	
	
	Xinput["P1 X Axis"] = Xbest;
	Yinput["P1 Y Axis"] = Ybest;
	joypad.setanalog(Xinput);
	joypad.setanalog(Yinput);

	end;
	
end;

while true do
	
	f = emu.framecount();
	
	if f_old ~= f then done = false; end;
	
	f_old = f;
	
	if StartFlag and not PauseFlag and not emu.islagged() --and not done
	then BruteForce();
	end;
	
	emu.yield();
end;