diff --git a/3rdparty/sol2/docs/source/api/containers.rst b/3rdparty/sol2/docs/source/api/containers.rst index dba03df8a58..81bbdc40584 100644 --- a/3rdparty/sol2/docs/source/api/containers.rst +++ b/3rdparty/sol2/docs/source/api/containers.rst @@ -53,7 +53,17 @@ Here's a complete working example of it working for Lua 5.3 and Lua 5.2, and how return 0; } -Note that this will not work well in 5.1, as it has explicit table checks and does not check metamethods, even when ``pairs`` or ``ipairs`` is passed a table. In that case, you will need to use a more manual iteration scheme or you will have to convert it to a table. In C++, you can use :doc:`sol::as_table` when passing something to the library to get a table out of it. + +Note that this will not work well in Lua 5.1, as it has explicit table checks and does not check metamethods, even when ``pairs`` or ``ipairs`` is passed a table. In that case, you will need to use a more manual iteration scheme or you will have to convert it to a table. In C++, you can use :doc:`sol::as_table` when passing something to the library to get a table out of it: ``lua["arr"] = as_table( std::vector{ ... });``. For manual iteration in Lua code without using ``as_table`` for something with indices, try: + +.. code-block:: lua + :caption: iteration.lua + + for i = 1, #vec do + print(i, vec[i]) + end + +There are also other ways to iterate over key/values, but they can be difficult due to not having proper support in Lua 5.1. We recommend that you upgrade to Lua 5.2 or 5.3. additional functions @@ -90,4 +100,4 @@ If you have a type that has ``begin`` or ``end`` member functions but don't prov namespace sol { template <> struct is_container : std::false_type {}; - } \ No newline at end of file + } diff --git a/3rdparty/sol2/single/sol/sol.hpp b/3rdparty/sol2/single/sol/sol.hpp index b681f7e32bf..29fcf1d30ba 100644 --- a/3rdparty/sol2/single/sol/sol.hpp +++ b/3rdparty/sol2/single/sol/sol.hpp @@ -20,8 +20,8 @@ // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // This file was generated with a script. -// Generated 2016-11-06 21:33:58.899927 UTC -// This header was generated with sol v2.15.0 (revision 34fe8a1) +// Generated 2016-11-07 18:50:10.518977 UTC +// This header was generated with sol v2.15.0 (revision 29f10c4) // https://github.com/ThePhD/sol2 #ifndef SOL_SINGLE_INCLUDE_HPP @@ -5922,7 +5922,7 @@ namespace sol { }; template - struct pusher>, meta::neg>, std::is_base_of>>>>::value>> { + struct pusher, meta::neg>, std::is_base_of>>>>::value>> { template static int push(lua_State* L, Args&&... args) { return pusher>{}.push(L, std::forward(args)...); diff --git a/3rdparty/sol2/sol/stack_push.hpp b/3rdparty/sol2/sol/stack_push.hpp index cf39d1e40c8..0478bcbe1ff 100644 --- a/3rdparty/sol2/sol/stack_push.hpp +++ b/3rdparty/sol2/sol/stack_push.hpp @@ -108,7 +108,7 @@ namespace sol { }; template - struct pusher>, meta::neg>, std::is_base_of>>>>::value>> { + struct pusher, meta::neg>, std::is_base_of>>>>::value>> { template static int push(lua_State* L, Args&&... args) { return pusher>{}.push(L, std::forward(args)...); diff --git a/3rdparty/sol2/test_containers.cpp b/3rdparty/sol2/test_containers.cpp index d43db52d4b4..1ed07e24a9f 100644 --- a/3rdparty/sol2/test_containers.cpp +++ b/3rdparty/sol2/test_containers.cpp @@ -359,3 +359,67 @@ a_ref = b.a_list[2] REQUIRE(&b.a_list[1] == &a_ref); REQUIRE(b.a_list[1].a == a_ref.a); } + +struct options { + static int livingcount; + static options* last; + options() { + ++livingcount; + last = this; + INFO("constructor: " << this); + } + + std::string output_help() { + last = this; + INFO("func: " << this); + return ""; + } + + void begin() {} + void end() {} + + ~options() { + last = this; + --livingcount; + } +}; + +options* options::last = nullptr; +int options::livingcount = 0; + +struct machine { + options opt; +}; + +namespace sol { + template <> + struct is_container : std::false_type {}; +} + +TEST_CASE("containers/is-container", "make sure the is_container trait behaves properly") { + sol::state lua; + lua.open_libraries(); + + lua.new_usertype("options_type", + "output_help", &options::output_help + ); + + lua.new_usertype("machine_type", + "new", sol::no_constructor, + "opt", [](machine& m) { return &m.opt; }, + "copy_opt", [](machine& m) { return m.opt; } + ); + + { + machine m; + lua["machine"] = &m; + + lua.script(R"( + machine:opt():output_help() + )"); + + REQUIRE(options::last == &m.opt); + REQUIRE(options::livingcount == 1); + } + REQUIRE(options::livingcount == 0); +} diff --git a/hash/sms.xml b/hash/sms.xml index 9a7546d7b35..69e92c607be 100644 --- a/hash/sms.xml +++ b/hash/sms.xml @@ -6165,7 +6165,18 @@ - + + + Sports Pad Soccer (Jpn) 1988 @@ -6173,8 +6184,8 @@ - - + + diff --git a/plugins/console/init.lua b/plugins/console/init.lua index 0b6cf595c9c..c27e55164bc 100644 --- a/plugins/console/init.lua +++ b/plugins/console/init.lua @@ -25,25 +25,56 @@ function console.startplugin() -- that also means that bad things will happen if anything outside lua tries to use it -- especially the completion callback ln.historysetmaxlen(10) - local scr = "local ln = require('linenoise')\n" - scr = scr .. "ln.setcompletion(function(c, str) status = str\n" - scr = scr .. " yield()\n" -- coroutines can't yield in the middle of a callback so this is a real thread - scr = scr .. " status:gsub('[^,]*', function(s) if s ~= '' then ln.addcompletion(c, s) end end)\n" - scr = scr .. "end)\n" - scr = scr .. "return ln.linenoise('\x1b[1;36m[MAME]\x1b[0m> ')" + local scr = [[ +local ln = require('linenoise') +ln.setcompletion(function(c, str) + status = str + yield() + status:gsub('[^,]*', function(s) if s ~= '' then ln.addcompletion(c, s) end end) +end) +return ln.linenoise('\x1b[1;36m[MAME]\x1b[0m> ') +]] + + local function find_unmatch(str, openpar, pair) + local done = false + if not str:match(openpar) then + return str + end + local tmp = str:gsub(pair, "") + if not tmp:match(openpar) then + return str + end + repeat + str = str:gsub(".-" .. openpar .. "(.*)", function (s) + tmp = s:gsub(pair, "") + if not tmp:match(openpar) then + done = true + end + return s + end) + until done or str == "" + return str + end local function get_completions(str) local comps = "," - local table = str:match("([(]?[%w.:()]-)[:.][%w_]*$") - local rest, last = str:match("(.-[:.]?)([%w_]*)$") + local rest, dot, last = str:match("(.-)([.:]?)([^.:]*)$") + str = find_unmatch(str, "%(", "%b()") + str = find_unmatch(str, "%[", "%b[]") + local table = str:match("([%w_%.:%(%)%[%]]-)[:.][%w_]*$") local err - if table == "" or not table then - table = "_G" + if rest == "" or not table then + if dot == "" then + table = "_G" + else + return comps + end end err, tablef = pcall(load("return " .. table)) if (not err) or (not tablef) then return comps end + rest = rest .. dot if type(tablef) == 'table' then for k, v in pairs(tablef) do if k:match("^" .. last) then diff --git a/src/devices/bus/sms_ctrl/sports.cpp b/src/devices/bus/sms_ctrl/sports.cpp index b98861a4fa0..a85ca1e2709 100644 --- a/src/devices/bus/sms_ctrl/sports.cpp +++ b/src/devices/bus/sms_ctrl/sports.cpp @@ -21,8 +21,10 @@ Notes: Games designed for the US model of the Sports Pad controller use the TH line of the controller port to select which nibble, of the two axis bytes, will be read at a time. The Japanese cartridge Sports Pad Soccer - uses a different mode, because the Sega Mark III lacks the TH line, so - there is a different Sports Pad model released in Japan (see sportsjp.c). + uses a different mode when not detect a SMSJ, because the Sega Mark III + lacks the TH line. There is a different Sports Pad model released in + Japan and no information was found about it supporting both modes, so + that model is currently emulated as a different device (see sportsjp.c). It was discovered that games designed for the Paddle Controller, released in Japan, switch to a mode incompatible with the original Paddle when diff --git a/src/devices/bus/sms_ctrl/sportsjp.cpp b/src/devices/bus/sms_ctrl/sportsjp.cpp index 97914397272..398a3b7730e 100644 --- a/src/devices/bus/sms_ctrl/sportsjp.cpp +++ b/src/devices/bus/sms_ctrl/sportsjp.cpp @@ -17,13 +17,23 @@ TODO: Notes: - The Japanese Sports Pad controller is only required to play the cartridge - Sports Pad Soccer, released in Japan. It uses a different mode than the - used by the US model, due to the missing TH line on Sega Mark III - controller ports. + This Japanese Sports Pad controller device is only required to play the + cartridge Sports Pad Soccer, released in Japan, on non-SMSJ consoles without + ROM header validation, like the Sega Mark III and the Korean SMS2 version. - A bug was discovered in the player 2 input handling code of the only known - good ROM dump of Sports Pad Soccer (JP): + The Japanese version of Sports Pad Soccer has code to operate the Sports + Pad controller in two diffent modes. When it detects a Japanese SMS (testing + if port $F2 has two bits for mute control), the operation is the same used + by US Sports Pad games. Otherwise, it uses a mode that polls bits TR and TL + of the controller ports, compatible with the Sega Mark III, that lacks the + TH line used by the US Sports Pad mode. This Mark III mode is also used on + other non-SMSJ consoles, like the Korean SMS2 version. The two controller + modes are significantly different from each other and no information was + found about support for both modes on the Japanese Sports Pad model, so that + model is currently emulated as a different device. + + A bug was discovered in the player 2 input handling code of the Mark III + compatible mode of the only known good ROM dump of Sports Pad Soccer (JP): size="131072" crc="41c948bf" sha1="7634ce39e87049dad1ee4f32a80d728e4bd1f81f" At address $12D1, instead read the upper 2 bits of port $DC and lower 2 bits of port $DD (to obtain the lower nibble of the current axis for player 2), diff --git a/src/frontend/mame/luaengine.cpp b/src/frontend/mame/luaengine.cpp index 0afe9ddc304..dd0574620b1 100644 --- a/src/frontend/mame/luaengine.cpp +++ b/src/frontend/mame/luaengine.cpp @@ -75,11 +75,8 @@ namespace sol int len; char *ptr; }; - namespace meta - { - template<> - struct has_begin_end : std::false_type {}; // don't convert core_optons to a table directly - } + template<> + struct is_container : std::false_type {}; // don't convert core_optons to a table directly namespace stack { template <>