Post subject: Another fabulous FCEUX Lua bug
Banned User, Former player
Joined: 12/23/2004
Posts: 1850
inputprev	= {
	A		= false,
	B		= false,
	select	= false,
	start	= false,
	up		= false,
	down	= false,
	left	= false,
	right	= false,
	}

function force(i)
	out	= {};
	for k,v in pairs(i) do
		if v == nil then
			v = false;
		end;
		out[k]	= v;
	end;

	return out;
end;

while true do
	temp	= force(joypad.get(1));

	z	= 0;
	for k,v in pairs(temp) do
		gui.text(8, z * 8 + 8, string.format("%s > %s", k, tostring(v)));
		z = z + 1;
	end;

	joypad.set(1, inputprev);
	inputprev	= temp;
	
	emu.frameadvance();
end;
This will destroy all input in FCEUX. The user's input is ignored, replaced by the joypad.set. It works as intended in VBA and possibly other emulators. Perhaps you should add a "joypad.readuser()" that always reads the user's input, regardless of movie/force settings?
Perma-banned
Editor, Skilled player (1172)
Joined: 9/27/2008
Posts: 1085
Here's what's happening: Joypad.get, in "boundary"*, will get the previous frame's input. While the user may be trying to mess with the joypad, it is not detected, instead preferring to read the joypad on the previous frame. And already, by the time the user joypad is read, it's blown away by the false you've injected. It's still poorly implemented, making it impossible to read the user's input, transform it, and inject it all in the same frame. I'm aware of a joypad.peek() function that has been implemented in a few other emulators. Especially useful for emulators that can run lua code while emulation is paused, as it tells you what the user is pressing rather than what was passed to the emulation. Would love it here, myself. * My definition of "boundary" is lua code that precedes emu.frameadvance(). It is possible to place code that isn't in "boundary" by instead passing a function to emu.registerbefore, emu.registerafter, or gui.register. The code would be in their respective registers which I do not consider "boundary". Regardless, while emu.registerbefore and emu.registerafter would get the user's current input through joypad.get, it is incapable of injecting new input in the immediate frame through joypad.set. Still a crippling problem.
Banned User, Former player
Joined: 12/23/2004
Posts: 1850
Wrong. You can change it to use emu.registerbefore() and the issue is still there (in fact, it was what I was initially testing.) You can set input in emu.registerbefore(). But you cannot read the user's input next frame. Reminds me, I wonder if a shitty workaround would be something like this:
t = joypad.get(1); -- get intended input
joypad.set(1, {}); -- clear forced
p = joypad.get(1); -- get user input
joypad.set(1, t); -- re-enable intended input
Pretty messy, but who knows.
Perma-banned
Banned User, Former player
Joined: 12/23/2004
Posts: 1850
Xkeeper wrote:
Reminds me, I wonder if a shitty workaround would be something like this:
t = joypad.get(1); -- get intended input
joypad.set(1, {}); -- clear forced
p = joypad.get(1); -- get user input
joypad.set(1, t); -- re-enable intended input
I just tested, and this doesn't work either.
	joypad.set(1, {});				-- Force input cleared.
	temp	= force(joypad.get(1));
Sigh.
Perma-banned
Editor, Skilled player (1172)
Joined: 9/27/2008
Posts: 1085
My statement still stands:
Language: lua

local function Fn() local a= joypad.get(1) if a.A then gui.text(1,1,"Yay!") else gui.text(1,3,"No.") end end
Use "boundary", it detects your button press one frame later. Use emu.register before, it detects your button press immediately. However, joypad.set works immediately in "boundary", and is late one frame in emu.register before. Either way you go, your problem still stands, naturally. I have wrestled with how FCEUX deals with joypad, for several days, in fact, and I even wrote up details in here. I think I know my stuff. (After all this, I'd hate being called wrong without further investigation, which is why I'm defensive) There is no solution to your problem for FCEUX as it currently stands. The implementation needs to change.
Regardless, while emu.registerbefore and emu.registerafter would get the user's current input through joypad.get, it is incapable of injecting new input in the immediate frame through joypad.set. Still a crippling problem.
Banned User, Former player
Joined: 12/23/2004
Posts: 1850
FatRatKnight wrote:
blah blah words
I was under the impression you were saying that it would be fixed by using emu.registerbefore() as opposed to the way it was done, so try not to take it the wrong way. (I was also using emu.registerbefore() in my test scripts -- I just moved it to the main loop to make it as simple as possible.) And yes, I saw that post pretty soon afterwards, though it's really long and turns into a wall of text. Regardless, I hope the issue is fixed soon.
Perma-banned
Post subject: Re: Another fabulous FCEUX Lua bug
Editor, Skilled player (1941)
Joined: 6/15/2005
Posts: 3247
Xkeeper wrote:
It works as intended in VBA and possibly other emulators
VBA23 changelog wrote:
gochaism - Lua: changed joypad.set, it no longer adds input if the field value means false.
It might be unintended.
Post subject: Re: Another fabulous FCEUX Lua bug
Banned User, Former player
Joined: 12/23/2004
Posts: 1850
FractalFusion wrote:
Xkeeper wrote:
It works as intended in VBA and possibly other emulators
VBA23 changelog wrote:
gochaism - Lua: changed joypad.set, it no longer adds input if the field value means false.
It might be unintended.
That seems to imply that it doesn't press the button. The standard seems to be: nil: do nothing. Leave it as is. (this is not used in the script for obvious reasons) true: force button on. false: force button off. I'm not sure what that bug fixed or the end resolution, but as of my last test using the new release, it works as intended (delays buttons by a frame).
Perma-banned
Editor, Skilled player (1172)
Joined: 9/27/2008
Posts: 1085
I just thought of one way to get instantaneous reaction from the user. But it involves input.get, seeing as joypad.get is one frame too late, no matter how you use it. It also has a layer of inconvenience, since you need to set the controls from lua rather than use the emulator's internal set-up. An example piece of code set only for player 1:
Language: lua

local Tbl= { left= "G", right= "J", up= "Y", down= "H", A= "X", B= "C", start= "V", select="B" } local Joys= {} -- Avoid reconstructing this table over and over... --***************************************************************************** local function Fn() --***************************************************************************** local keys= input.get() for k,v in pairs(Tbl) do Joys[k]= keys[v] or false --If it's nil, I'd rather take false end joypad.set(1,Joys) end
Call this function alongside emu.frameadvance(). See if it is of any help. Still, involving input.get isn't a solution I would like to give. So the earlier mess was just that we didn't communicate properly. I'm always learning ways to communicate, no matter how good I think I may be at this point.
Banned User, Former player
Joined: 12/23/2004
Posts: 1850
Has there been any progress? I recently redownloaded the latest interm build ("updated nightly", which was apparently last September or so) and judging from the fairly ancient date and lack of FCEUX mailing list nags I'm guessing not. orz
Perma-banned