Main Restorations Software Audio/Jukebox/MP3 Everything Else Buy/Sell/Trade
Project Announcements Monitor/Video GroovyMAME Merit/JVL Touchscreen Meet Up Retail Vendors
Driving & Racing Woodworking Software Support Forums Consoles Project Arcade Reviews
Automated Projects Artwork Frontend Support Forums Pinball Forum Discussion Old Boards
Raspberry Pi & Dev Board controls.dat Linux Miscellaneous Arcade Wiki Discussion Old Archives
Lightguns Arcade1Up Try the site in https mode Site News

Unread posts | New Replies | Recent posts | Rules | Chatroom | Wiki | File Repository | RSS | Submit news

  

Author Topic: MAME Lua Autofire Plugin  (Read 9655 times)

0 Members and 1 Guest are viewing this topic.

tj0390

  • Trade Count: (0)
  • Jr. Member
  • **
  • Offline Offline
  • Posts: 4
  • Last login:September 06, 2017, 12:59:23 am
  • I want to build my own arcade controls!
MAME Lua Autofire Plugin
« on: August 20, 2017, 03:59:32 pm »
I got tired of having to turn on autofire for my 3 year old every time so I decided to try to make a plugin. I am a DBA by trade so my coding is fairly weak. Below is my script. It seems close but does not work. I can actually get it to autofire without holding the button but not while holding it. I did not see anywhere in the API to set the autofire setting in MAME. If I missed this option I wasted some time. Any help is greatly appreciated. One additional question I tried the following, key = manager:machine():input():code_from_token("KEYCODE_LCONTROL"), but it returns nil. It looks correct to me though.

local button
local counter
local state

counter = 1

for tag, port in pairs(manager:machine():ioport().ports) do
   if port.fields["P1 Button 1"] then
      button = {port = port, field = port.fields["P1 Button 1"]} --TODO move this to config file
   end
end

local function press()
   button.field:set_value(1)
end

local function unpress()
   button.field:set_value(0)
end

local function check()
   state = ((button.port:read() & button.field.mask) ~ button.field.defvalue) --Gets current state of button pressed or released

   if state == 1 and counter % 3 == 0 then
      unpress() --if the button is pressed and it is every third frame release button
   else
      counter = counter + 1
      return
   end

end


emu.register_frame(check)

PL1

  • Global Moderator
  • Trade Count: (+1)
  • Full Member
  • *****
  • Offline Offline
  • Posts: 9393
  • Last login:Today at 02:54:41 am
  • Designated spam hunter
Re: MAME Lua Autofire Plugin
« Reply #1 on: August 20, 2017, 04:21:41 pm »
I got tired of having to turn on autofire for my 3 year old every time so I decided to try to make a plugin. I am a DBA by trade so my coding is fairly weak. Below is my script. It seems close but does not work. I can actually get it to autofire without holding the button but not while holding it. I did not see anywhere in the API to set the autofire setting in MAME. If I missed this option I wasted some time. Any help is greatly appreciated. One additional question I tried the following, key = manager:machine():input():code_from_token("KEYCODE_LCONTROL"), but it returns nil. It looks correct to me though.
Code: [Select]
local button
local counter
local state

counter = 1

for tag, port in pairs(manager:machine():ioport().ports) do
if port.fields["P1 Button 1"] then
button = {port = port, field = port.fields["P1 Button 1"]} --TODO move this to config file
end
end

local function press()
button.field:set_value(1)
end

local function unpress()
button.field:set_value(0)
end

local function check()
state = ((button.port:read() & button.field.mask) ~ button.field.defvalue) --Gets current state of button pressed or released

if state == 1 and counter % 3 == 0 then
unpress() --if the button is pressed and it is every third frame release button
else
counter = counter + 1
return
end

end


emu.register_frame(check)
For future reference, you may want to use the icon to insert code tags since some font colors like beige are hard to read in some themes or on odd-numbered replies like this one.   :cheers:


Scott
« Last Edit: August 20, 2017, 04:26:30 pm by PL1 »

tj0390

  • Trade Count: (0)
  • Jr. Member
  • **
  • Offline Offline
  • Posts: 4
  • Last login:September 06, 2017, 12:59:23 am
  • I want to build my own arcade controls!
Re: MAME Lua Autofire Plugin
« Reply #2 on: August 21, 2017, 04:40:17 pm »
Thanks for the tip. I have lurked on here but never posted before.

crazyc

  • Trade Count: (0)
  • Full Member
  • ***
  • Offline Offline
  • Posts: 14
  • Last login:October 17, 2018, 10:11:00 pm
  • I want to build my own arcade controls!
Re: MAME Lua Autofire Plugin
« Reply #3 on: August 23, 2017, 05:22:46 pm »
There isn't any way to enable the builtin autofire from lua but your code is as you guessed is close to a native lua implementation.  The problem is that pressing the button overrides any set_value from lua.  Making a key for autofire is the way to get around it and what you have "key = manager:machine():input():code_from_token("KEYCODE_LCONTROL")" is correct and works for me.  I'd guess that you aren't using 0.188 which is the first version with that API.

tj0390

  • Trade Count: (0)
  • Jr. Member
  • **
  • Offline Offline
  • Posts: 4
  • Last login:September 06, 2017, 12:59:23 am
  • I want to build my own arcade controls!
Re: MAME Lua Autofire Plugin
« Reply #4 on: August 24, 2017, 09:47:18 am »
There isn't any way to enable the builtin autofire from lua but your code is as you guessed is close to a native lua implementation.  The problem is that pressing the button overrides any set_value from lua.  Making a key for autofire is the way to get around it and what you have "key = manager:machine():input():code_from_token("KEYCODE_LCONTROL")" is correct and works for me.  I'd guess that you aren't using 0.188 which is the first version with that API.

Thanks Crazy. That was exactly it, I was using .183. I think this will get me there. If I get the plugin working and polished I will post it here. Thanks again for the help I feel dumb now, I had been wracking my brain on that one.

tj0390

  • Trade Count: (0)
  • Jr. Member
  • **
  • Offline Offline
  • Posts: 4
  • Last login:September 06, 2017, 12:59:23 am
  • I want to build my own arcade controls!
Re: MAME Lua Autofire Plugin
« Reply #5 on: September 06, 2017, 12:59:23 am »
I got my plugin working. I attached the files if anyone wants to look or use it. The code is probably a little janky and could use some polish. I am pretty close to having Joy and button sequences working as well, so I can throw a SHORYUKEN with a single button push. If I get motivated and anyone is interested I will post it. Thanks again Crazy for the help.

massivelycolourfulbread

  • Guest
  • Trade Count: (0)
Re: MAME Lua Autofire Plugin
« Reply #6 on: October 13, 2018, 04:18:25 am »
And so a bit more than a year later I stumbled upon this thread and script. I too have grown tired of enabling autofire every time I play raiden, so slogging through ioport.cpp and cheatopt.cpp thinking  I'd just hardcode a few things I realised that:

a) Hahahaha, no.
b) I am terrible at c++ (but c++ is terrible so we're even!?)

I'm not very knowledgable about the MAME internals, but I've done my best to read the code and attempt an implementation.

The lua api doesn't have access to the ioports_live bits or we'd be able to flip the 'on' switch for a button. I still have no idea why the .cfg can't just have an autofire='on' in the tag line.

Either way, I tried to use this script and found that at least with current (0.202) it didn't work. So I did what any obsessive compulsive person would do: one trillion print statements.

This is where things got a bit strange. First off, I couldn't get 'map_from' to match so button would be set. I tried multiple games, but none of them worked properly. I ended up hardcoding it just to make it function for my tests.

Code: [Select]
for tag, port in pairs(manager:machine():ioport().ports) do
   --if port.fields[map_from ] then
   if port.fields['P1 Button 1'] then
      print("Found eet: ",port.fields['P1 Button 1'])
      button = port.fields['P1 Button 1']
      print ("button is: ",button)
   end
end

This worked, but when I tried raiden nothing happened when I pushed button 1. On accident I pushed button 2 and /both/ button 1 and 2 fired (and did autofire).

This lead me to try dumping values while it was running and I ended up with this:

Code: [Select]
port fields:
tag: :P1_P2
port: sol.ioport_port *: 0x7fca20ef0798
table["P2 Up"] = sol.ioport_field *: 0x7fca20ef2918
table["P1 Right"] = sol.ioport_field *: 0x7fca20ef2858
table["P2 Button 2"] = sol.ioport_field *: 0x7fca20ef2a08
table["P2 Button 1"] = sol.ioport_field *: 0x7fca20ef29d8
table["1 Player Start"] = sol.ioport_field *: 0x7fca20ef28e8
table["P1 Up"] = sol.ioport_field *: 0x7fca20ef27c8
table["P1 Left"] = sol.ioport_field *: 0x7fca20ef2828
table["2 Players Start"] = sol.ioport_field *: 0x7fca20ef2a38
table["P2 Right"] = sol.ioport_field *: 0x7fca20ef29a8
table["P1 Button 1"] = sol.ioport_field *: 0x7fca20ef2888
table["P1 Down"] = sol.ioport_field *: 0x7fca20ef27f8
table["P2 Down"] = sol.ioport_field *: 0x7fca20ef2948
table["P1 Button 2"] = sol.ioport_field *: 0x7fca20ef28b8
table["P2 Left"] = sol.ioport_field *: 0x7fca20ef2978

I then did a 5x loop around the button = port.fields["P1 Button 1"] and... whaaat?

Code: [Select]
Found eet: sol.ioport_field *: 0x7fca20ef55d8
button is: sol.ioport_field *: 0x7fca20ed8578
Found eet: sol.ioport_field *: 0x7fca26005d48
button is: sol.ioport_field *: 0x7fca26006578
Found eet: sol.ioport_field *: 0x7fca26307e28
button is: sol.ioport_field *: 0x7fca26308628
Found eet: sol.ioport_field *: 0x7fca26309fd8
button is: sol.ioport_field *: 0x7fca2630a7d8
Found eet: sol.ioport_field *: 0x7fca2630c188
button is: sol.ioport_field *: 0x7fca2630c988

Notice that the values not only don't match the first table dump, but they change constantly.

At this point I'm not sure I know how to move forward. The map_from match issue isn't a big deal as I could just hardcode it, but I really have no idea why the autofire works at all because the call to button should fail. Of course, button 2 also doesn't match.

Is this script still functioning for you with 0.202?

crazyc

  • Trade Count: (0)
  • Full Member
  • ***
  • Offline Offline
  • Posts: 14
  • Last login:October 17, 2018, 10:11:00 pm
  • I want to build my own arcade controls!
Re: MAME Lua Autofire Plugin
« Reply #7 on: October 14, 2018, 09:25:15 pm »
Quote from: massivelycolourfulbread
Notice that the values not only don't match the first table dump, but they change constantly.
These are lua references to the ioport_field struct and a new reference is created each time you load the value from the table.  Anyway, nothing significant has changed with input since 0.188 so you need to make sure the settings are correct in mapautofire.dat.

massivelycolourfulbread

  • Guest
  • Trade Count: (0)
Re: MAME Lua Autofire Plugin
« Reply #8 on: October 14, 2018, 11:45:30 pm »
Quote
These are lua references to the ioport_field struct and a new reference is created each time you load the value from the table.  Anyway, nothing significant has changed with input since 0.188 so you need to make sure the settings are correct in mapautofire.dat.

Thank you for the pointer (sorry, couldn't resist). Since posting this I've been wandering aimlessly in ioport.cpp and understand it a bit better; fsvo 'understand'.

Initially I noticed something was wrong when I made an attempt at using the script and got:

Code: [Select]
[LUA ERROR] in execute_function: plugins/mapautofire/init.lua:73: attempt to index a nil value (upvalue 'button')

Meaning button was unset from line 62, here:

Code: [Select]
for tag, port in pairs(manager:machine():ioport().ports) do
   if port.fields[map_from ] then
      button = port.fields[map_from ]
   end
end

Which is why I added the print inside the if end. It's never set meaning that the if port.fields[map_from ] never matches. I went further and added more prints
above that to the tune of:

Code: [Select]
print("map to",map_to)
print("map from",map_from)

I verified they were being set properly from mapautofire.dat, which has:
Code: [Select]
raiden
@JOYCODE_BUTTON4,P1 Button 1

I even went back and used the author's own initial settings (and rtypeu) only to have the same result. Hence I simply hardcoded it to get past that issue.

Lastly I added prints like:

Code: [Select]
print("entered press")
print("button is: ",button)

inside of the press() and unpress() functions and print("counter is: ",counter) inside check(button). I can watch it entering and exiting the press/unpress
functions as well as counting properly, but it simply never autofires.

crazyc

  • Trade Count: (0)
  • Full Member
  • ***
  • Offline Offline
  • Posts: 14
  • Last login:October 17, 2018, 10:11:00 pm
  • I want to build my own arcade controls!
Re: MAME Lua Autofire Plugin
« Reply #9 on: October 15, 2018, 09:10:44 am »
Quote
I even went back and used the author's own initial settings (and rtypeu) only to have the same result. Hence I simply hardcoded it to get past that issue.

I just tried it with rtypeu and set the autofire to KEYCODE_0PAD and it works perfectly so I don't know what to say.

Edit: works in raiden dx too.  Make sure that you don't have the autofire button set to the same as the mapped button otherwise they cancel each other out.
« Last Edit: October 15, 2018, 09:22:04 am by crazyc »

massivelycolourfulbread

  • Guest
  • Trade Count: (0)
Re: MAME Lua Autofire Plugin
« Reply #10 on: October 17, 2018, 02:21:21 am »
Quote
I just tried it with rtypeu and set the autofire to KEYCODE_0PAD and it works perfectly so I don't know what to say.

Edit: works in raiden dx too.  Make sure that you don't have the autofire button set to the same as the mapped button otherwise they cancel each other out.

Maybe that's what I've been doing incorrectly, but I also set cheat to 0 in mame.ini to test. Neither way
worked.

There are only two buttons fire and bomb, which are button 1 and 2 respectively. Those are mapped in the raiden.cfg like:

P1_BUTTON1 -> JOYCODE_1_BUTTON4
P1_BUTTON2 -> JOYCODE_1_BUTTON3

I've tried the following combinations:

@JOYCODE_BUTTON4,P1 Button 1
@JOYCODE_BUTTON3,P1 Button 1
@KEYCODE_A,P1 Button 1

No matter what I set in mapautofire.dat, I always get:

Code: [Select]
[LUA ERROR] in execute_function: plugins/mapautofire/init.lua:73: attempt to index a nil value (upvalue 'button')

When I hardcode the result is the same. I tried with keycode a as a test using a key that wasn't mapped to either of the in-game
buttons. No luck.

I can only assume there's some very basic setting I have either skipped or am missing all together.

Oh well. I appreciate the attempts to help.

crazyc

  • Trade Count: (0)
  • Full Member
  • ***
  • Offline Offline
  • Posts: 14
  • Last login:October 17, 2018, 10:11:00 pm
  • I want to build my own arcade controls!
Re: MAME Lua Autofire Plugin
« Reply #11 on: October 17, 2018, 09:43:35 am »
Something is missing here.  It's not possible that port.fields["P1 Button 1"] is not nil but map_from = "P1 Button 1" port.fields[map_from] is.  Are you sure that map_from and map_to are set correctly?

massivelycolourfulbread

  • Guest
  • Trade Count: (0)
Re: MAME Lua Autofire Plugin
« Reply #12 on: October 17, 2018, 07:25:12 pm »
Something is missing here.  It's not possible that port.fields["P1 Button 1"] is not nil but map_from = "P1 Button 1" port.fields[map_from] is.  Are you sure that map_from and map_to are set correctly?

Exactly. That's why I thought that my sanity was finally slipping away. I set some debug prints because I assumed it was something tedious like quoting or a line feed that (sans chomp)
that was causing the match to fail later on. Here's what happens when I print:

Code: [Select]
map to  KEYCODE_A
map from        P1 Button 1
tag:    :COIN
port:   sol.ioport_port *: 0x7fb39ca86a88
table["Coin 1"] = sol.ioport_field *: 0x7fb39ca86c88
table["Coin 2"] = sol.ioport_field *: 0x7fb39ca86cb8
port fields:
tag:    :DSW
port:   sol.ioport_port *: 0x7fb39ca86ab8
table["Credits to Start"] = sol.ioport_field *: 0x7fb39ca87798
table["Unused"] = sol.ioport_field *: 0x7fb39ca877c8
table["Coinage"] = sol.ioport_field *: 0x7fb39ca87768
table["Demo Sounds"] = sol.ioport_field *: 0x7fb39ca878e8
table["Coin B"] = sol.ioport_field *: 0x7fb39ca87738
table["Coin Mode"] = sol.ioport_field *: 0x7fb39ca876d8
table["Bonus Life"] = sol.ioport_field *: 0x7fb39ca87858
table["Difficulty"] = sol.ioport_field *: 0x7fb39ca87888
table["Allow Continue"] = sol.ioport_field *: 0x7fb39ca878b8
table["Coin A"] = sol.ioport_field *: 0x7fb39ca87708
table["Lives"] = sol.ioport_field *: 0x7fb39ca87828
table["Flip Screen"] = sol.ioport_field *: 0x7fb39ca877f8
port fields:
tag:    :P1_P2
port:   sol.ioport_port *: 0x7fb39ca84d98
table["P2 Down"] = sol.ioport_field *: 0x7fb39ca890f8
table["P2 Button 2"] = sol.ioport_field *: 0x7fb39ca891b8
table["P2 Button 1"] = sol.ioport_field *: 0x7fb39ca89188
table["2 Players Start"] = sol.ioport_field *: 0x7fb39ca891e8
table["P1 Up"] = sol.ioport_field *: 0x7fb39ca88f78
table["P2 Up"] = sol.ioport_field *: 0x7fb39ca890c8
table["P1 Button 1"] = sol.ioport_field *: 0x7fb39ca89038
table["P1 Button 2"] = sol.ioport_field *: 0x7fb39ca89068
table["P2 Right"] = sol.ioport_field *: 0x7fb39ca89158
table["P1 Down"] = sol.ioport_field *: 0x7fb39ca88fa8
table["P1 Right"] = sol.ioport_field *: 0x7fb39ca89008
table["1 Player Start"] = sol.ioport_field *: 0x7fb39ca89098
table["P1 Left"] = sol.ioport_field *: 0x7fb39ca88fd8
table["P2 Left"] = sol.ioport_field *: 0x7fb39ca89128
port fields:
In the port.fields loop now
map to  KEYCODE_A
map from        P1 Button 1
In the port.fields loop now
map to  KEYCODE_A
map from        P1 Button 1
In the port.fields loop now
map to  KEYCODE_A
map from        P1 Button 1

I added a function to loop through and print the port values as well as print in the match/map loop. The diff is attached, but you
can clearly see P1 Button 1 mapped right there and the variable populated.

After posting this I had an idea and tried something else - I created a new local variable called testbutton and manually set it like
this:

testbutton = "P1 Button1"

then I printed it directly below the one set by the script:

map from        P1 Button 1
testbutton is   P1 Button 1

I thought maybe the whitespace mattered so I pushed map_from through s:gsub("^%s*", ""). Unfortunately this made no difference.


« Last Edit: October 17, 2018, 07:40:08 pm by massivelycolourfulbread »

crazyc

  • Trade Count: (0)
  • Full Member
  • ***
  • Offline Offline
  • Posts: 14
  • Last login:October 17, 2018, 10:11:00 pm
  • I want to build my own arcade controls!
Re: MAME Lua Autofire Plugin
« Reply #13 on: October 17, 2018, 10:11:00 pm »
Quote
line feed that (sans chomp)

This is probably the problem if you are using Linux or macos (I checked and the CR is preserved in map_from).  Try "for line in string.gmatch(map_str, '([^\n\r]+)') do" on line 55.

massivelycolourfulbread

  • Guest
  • Trade Count: (0)
Re: MAME Lua Autofire Plugin
« Reply #14 on: October 18, 2018, 05:03:06 am »
Quote
line feed that (sans chomp)

This is probably the problem if you are using Linux or macos (I checked and the CR is preserved in map_from).  Try "for line in string.gmatch(map_str, '([^\n\r]+)') do" on line 55.

Sigh, that was it. Thank you for your perseverance.

Meanwhile, I'd been poking at the MAME source in case this wasn't ever solved. In a rare turn of events I actually managed it there too.
It's about as elegant as a dump truck, but it works.

If you modify ioport.cpp like this you can flip the toggle bit on autofire for button 1 at start-up. When cheats are on autofire is enabled,
but the buttons are all "off". This let's you skip the manual toggle of off->on.

Obviously it's much more tedious as it requires a compile, but I take my victories any way I can get them.

Code: [Select]
--- a/src/emu/ioport.cpp
+++ b/src/emu/ioport.cpp
@@ -2267,7 +2267,11 @@ bool ioport_manager::load_game_config(util::xml::data_node const *portnode, int
                                        {
                                                // fetch the value
                                                field.live().value = portnode->get_attribute_int("value", field.defvalue());
-
+                                               // fine, we'll do it this way then. autofire for button one by default.
+                                               if (field.type() == IPT_BUTTON1)
+                                               {
+                                                       field.live().autofire = true;
+                                               }
                                                // fetch yes/no for toggle setting
                                                const char *togstring = portnode->get_attribute_string("toggle", nullptr);
                                                if (togstring != nullptr)

I also disabled the 'may not function properly' warning too while I was at it (had to compile anyway). Even
though it doesn't tell me every single time, I do remember that Raiden may not function properly. I have
been thoroughly warned :)

Thank you again for the assistance.

IrisColt

  • Trade Count: (0)
  • Jr. Member
  • **
  • Offline Offline
  • Posts: 1
  • Last login:October 26, 2018, 08:35:51 am
  • M4M3
Re: MAME Lua Autofire Plugin
« Reply #15 on: October 26, 2018, 03:09:28 am »
Code: [Select]
state = ((button.port:read() & button.field.mask) ~ button.field.defvalue) --Gets current state of button pressed or released
Incidentally, this post provided me with the hint to solve the problem that I was having just now. Thanks @tj0390 and @cracyc!
« Last Edit: October 26, 2018, 03:21:41 am by IrisColt »

yacsha

  • Trade Count: (0)
  • Jr. Member
  • **
  • Offline Offline
  • Posts: 1
  • Last login:May 18, 2020, 07:59:16 pm
  • I want to build my own arcade controls!
Re: MAME Lua Autofire Plugin
« Reply #16 on: January 19, 2020, 12:04:29 pm »
I got my plugin working. I attached the files if anyone wants to look or use it. The code is probably a little janky and could use some polish. I am pretty close to having Joy and button sequences working as well, so I can throw a SHORYUKEN with a single button push. If I get motivated and anyone is interested I will post it. Thanks again Crazy for the help.

Dear tj0390, thanks for sharing your code, please if you have any advanced code for button sequences, such as to launch the shoryuken, please share it, I am working on something similar and it would be good not to start from scratch.

regards