예제 #1
0
        //-------------------------------------------------
        //  split
        //-------------------------------------------------
        static std.vector <string> split(string text, char sep)
        {
            std.vector <string> tokens = new std.vector <string>();
            size_t start = 0;
            size_t end   = 0;

            while ((end = text.find(sep, start)) != npos)
            {
                string temp = text.substr(start, end - start);
                if (temp != "")
                {
                    tokens.push_back(temp);
                }
                start = end + 1;
            }

            {
                string temp = text.substr(start);
                if (temp != "")
                {
                    tokens.push_back(temp);
                }
            }

            return(tokens);
        }
예제 #2
0
        void device(string dev_type)
        {
            std.vector <string> params_ = new std.vector <string>();

            require_token(m_tok_paren_left);
            string devname = get_identifier();

            m_setup.log().debug.op("Parser: IC: {0}\n", devname);

            var tok = get_token();

            while (tok.is_(m_tok_comma))
            {
                tok = get_token();
                if (/*tok.is_type(token_type::IDENTIFIER) ||*/ tok.is_type(parser_t_token_type.STRING))
                {
                    params_.push_back(tok.str());
                    tok = get_token();
                }
                else
                {
                    var value = stringify_expression(ref tok);
                    params_.push_back(value);
                }
            }

            require_token(tok, m_tok_paren_right);

            std.vector <string> params_temp = new std.vector <string>();
            params_temp.Add(devname);
            params_temp.AddRange(params_);
            m_setup.register_dev(dev_type, params_temp.ToArray());  //m_setup.register_dev(dev_type, devname, params);
        }
예제 #3
0
            public void run(netlist_state_t nlstate)
            {
                foreach (var net in nlstate.nets())
                {
                    nlstate.log().verbose.op("processing {0}", net.name());
                    if (!net.is_rail_net() && !nlstate.core_terms(net).empty())
                    {
                        nlstate.log().verbose.op("   ==> not a rail net");
                        // Must be an analog net
                        var n = (analog_net_t)net;  //auto &n = dynamic_cast<analog_net_t &>(*net);
                        if (!already_processed(n))
                        {
                            groupspre.emplace_back(new nld_solver_net_list_t());
                            process_net(nlstate, n);
                        }
                    }
                }

                foreach (var g in groupspre)
                {
                    if (!g.empty())
                    {
                        groups.push_back(g);
                    }
                }
            }
예제 #4
0
            public void add(terminal_t term, int net_other, bool sorted)
            {
                if (sorted)
                {
                    for (int i = 0; i < m_connected_net_idx.size(); i++)
                    {
                        if (m_connected_net_idx[i] > net_other)
                        {
                            m_terms.Insert(i, term);                  //plib::container::insert_at(m_terms, i, term);
                            m_connected_net_idx.Insert(i, net_other); //plib::container::insert_at(m_connected_net_idx, i, net_other);
                            m_gt.Insert(i, 0.0);                      //plib::container::insert_at(m_gt, i, 0.0);
                            m_go.Insert(i, 0.0);                      //plib::container::insert_at(m_go, i, 0.0);
                            m_Idr.Insert(i, 0.0);                     //plib::container::insert_at(m_Idr, i, 0.0);
                            m_connected_net_V.Insert(i, null);        //plib::container::insert_at(m_connected_net_V, i, null);
                            return;
                        }
                    }
                }

                m_terms.push_back(term);
                m_connected_net_idx.push_back(net_other);
                m_gt.push_back(0.0);
                m_go.push_back(0.0);
                m_Idr.push_back(0.0);
                m_connected_net_V.push_back(null);
            }
예제 #5
0
파일: text.cs 프로젝트: kwanboy/mcs
        //bool hit_test(float x, float y, size_t &start, size_t &span) const;
        //void restyle(size_t start, size_t span, rgb_t *fgcolor, rgb_t *bgcolor);


        //-------------------------------------------------
        //  get_wrap_info
        //-------------------------------------------------
        public int get_wrap_info(out std.vector <int> xstart, out std.vector <int> xend)
        {
            xstart = new std.vector <int>();
            xend   = new std.vector <int>();

            // this is a hacky method (tailored to the need to implement
            // mame_ui_manager::wrap_text) but so be it
            int line_count = 0;

            foreach (var line in m_lines)
            {
                int start_pos = 0;
                int end_pos   = 0;

                var line_character_count = line.character_count();
                if (line_character_count > 0)
                {
                    start_pos = (int)line.character(0).source.start;
                    end_pos   = (int)(line.character(line_character_count - 1).source.start
                                      + line.character(line_character_count - 1).source.span);
                }

                line_count++;
                xstart.push_back(start_pos);
                xend.push_back(end_pos);
            }

            return(line_count);
        }
예제 #6
0
        // stream creation
        //-------------------------------------------------
        //  stream_alloc - allocate a new stream
        //-------------------------------------------------
        public sound_stream stream_alloc(device_t device, int inputs, int outputs, int sample_rate, stream_update_delegate callback = null)
        {
            var stream = new sound_stream(device, inputs, outputs, sample_rate, callback);

            m_stream_list.push_back(stream);
            return(stream);
        }
예제 #7
0
        // toolbar
        protected override void inkey_export()
        {
            std.vector <game_driver> list = new std.vector <game_driver>();
            if (m_populated_favorites)
            {
                // iterate over favorites
                mame_machine_manager.instance().favorite().apply((info) =>
                {
                    assert(info.driver != null);
                    if (info.startempty != 0)
                    {
                        list.push_back(info.driver);
                    }
                });
            }
            else
            {
                list.reserve(m_displaylist.size());
                foreach (ui_system_info info in m_displaylist)
                {
                    list.emplace_back(info.driver);
                }
            }

            throw new emu_unimplemented();
#if false
#endif
        }
예제 #8
0
        //template <typename T>
        public static std.vector <string> psplit(string str, std.vector <string> onstrl)                     //std::vector<T> psplit(const T &str, const std::vector<T> &onstrl)
        {
            string col = "";                                                                                 //T col = "";

            std.vector <string> ret = new std.vector <string>();                                             //std::vector<T> ret;

            size_t i = 0;                                                                                    //auto i = str.begin();

            while (i != (size_t)str.Length)                                                                  //while (i != str.end())
            {
                size_t p = npos;                                                                             //auto p = T::npos;
                for (size_t j = 0; j < onstrl.size(); j++)                                                   //for (std::size_t j=0; j < onstrl.size(); j++)
                {
                    if (onstrl[j] == str.Substring((int)i, Math.Min(str.Length - (int)i, onstrl[j].Length))) //if (std::equal(onstrl[j].begin(), onstrl[j].end(), i))
                    {
                        p = j;
                        break;
                    }
                }

                if (p != npos)     //if (p != T::npos)
                {
                    if (col != "") //if (!col.empty())
                    {
                        ret.push_back(col);
                    }

                    col = "";                //col.clear();
                    ret.push_back(onstrl[p]);
                    i += onstrl[p].length(); //i = std::next(i, narrow_cast<typename T::difference_type>(onstrl[p].length()));
                }
                else
                {
                    char c = str[(int)i];  //typename T::value_type c = *i;
                    col += c;
                    i++;
                }
            }

            if (col != "")  //if (!col.empty())
            {
                ret.push_back(col);
            }

            return(ret);
        }
예제 #9
0
        /// \brief Get vector of devices
        ///
        /// \tparam C Device class for which devices will be returned
        ///
        /// \return vector with pointers to devices

        //template<class C>
        public std.vector <C> get_device_list <C>() where C : core_device_t
        {
            std.vector <C> tmp = new std.vector <C>();
            foreach (var d in m_devices)
            {
                var dev = d.second is C ? (C)d.second : null;  //auto dev = dynamic_cast<C *>(d.second.get());
                if (dev != null)
                {
                    tmp.push_back(dev);
                }
            }
            return(tmp);
        }
예제 #10
0
파일: text.cs 프로젝트: kwanboy/mcs
        //-------------------------------------------------
        //  start_new_line
        //-------------------------------------------------
        void start_new_line(text_layout.text_justify justify, float height)
        {
            // create a new line
            line new_line = new line(this, justify, actual_height(), height * yscale());

            // update the current line
            m_current_line = new_line;
            m_last_break   = 0;
            m_truncating   = false;

            // append it
            m_lines.push_back(new_line);
        }
예제 #11
0
        public device_state_entry state_add(device_state_entry entry)  //device_state_entry &state_add(std::unique_ptr<device_state_entry> &&entry);
        {
            // append to the end of the list
            m_state_list.push_back(entry);  //m_state_list.push_back(std::move(entry));
            device_state_entry new_entry = m_state_list.back();

            // set the fast entry if applicable
            if (new_entry.index() >= FAST_STATE_MIN && new_entry.index() <= FAST_STATE_MAX && !new_entry.divider())
            {
                m_fast_state[new_entry.index() - FAST_STATE_MIN] = new_entry;
            }

            return(new_entry);
        }
예제 #12
0
 public void run(netlist_base_t netlist)
 {
     foreach (var net in netlist.nets())
     {
         netlist.log().debug.op("processing {0}\n", net.name());
         if (!net.isRailNet() && net.num_cons() > 0)
         {
             netlist.log().debug.op("   ==> not a rail net\n");
             /* Must be an analog net */
             analog_net_t n = (analog_net_t)net;
             if (!already_processed(n))
             {
                 groups.push_back(new analog_net_t_list_t());
                 process_net(n);
             }
         }
     }
 }
예제 #13
0
파일: text.cs 프로젝트: kwanboy/mcs
            // methods

            //-------------------------------------------------
            //  line::add_character
            //-------------------------------------------------
            public void add_character(char32_t ch, char_style style, source_info source)
            {
                // get the width of this character
                float chwidth = m_layout.get_char_width(ch, style.size);

                // create the positioned character
                positioned_char positioned_char;

                positioned_char.character = ch;
                positioned_char.xoffset   = m_width;
                positioned_char.xwidth    = chwidth;
                positioned_char.style     = style;
                positioned_char.source    = source;

                // append the character
                m_characters.push_back(positioned_char);
                m_width += chwidth;

                // we might be bigger
                m_height = Math.Max(m_height, style.size * m_layout.yscale());
            }
예제 #14
0
        //-------------------------------------------------
        //  missing_mandatory_images - search for devices
        //  which need an image to be loaded
        //-------------------------------------------------
        public std.vector <string> missing_mandatory_images()  //std::vector<std::reference_wrapper<const std::string>> mame_machine_manager::missing_mandatory_images()
        {
            std.vector <string> results = new std.vector <string>();
            assert(machine() != null);

            // make sure that any required image has a mounted file
            foreach (device_image_interface image in new image_interface_enumerator(machine().root_device()))
            {
                if (image.must_be_loaded())
                {
                    if (machine().options().image_option(image.instance_name()).value().empty())
                    {
                        // this is a missing image; give LUA plugins a chance to handle it
                        if (!lua().on_missing_mandatory_image(image.instance_name()))
                        {
                            results.push_back(image.instance_name());
                        }
                    }
                }
            }

            return(results);
        }
예제 #15
0
            public void post_start()
            {
                log().verbose.op("Scanning net groups ...");
                // determine net groups

                net_splitter splitter = new net_splitter();

                splitter.run(state());

                log().verbose.op("Found {1} net groups in {2} nets\n", splitter.groups.size(), state().nets().size());

                int num_errors = 0;

                log().verbose.op("checking net consistency  ...");
                foreach (var grp in splitter.groups)
                {
                    int    railterms   = 0;
                    string nets_in_grp = "";
                    foreach (var n in grp)
                    {
                        nets_in_grp += (n.name() + " ");
                        if (!n.is_analog())
                        {
                            state().log().error.op(ME_SOLVER_CONSISTENCY_NOT_ANALOG_NET(n.name()));
                            num_errors++;
                        }

                        if (n.is_rail_net())
                        {
                            state().log().error.op(ME_SOLVER_CONSISTENCY_RAIL_NET(n.name()));
                            num_errors++;
                        }

                        foreach (var t in state().core_terms(n))
                        {
                            if (!t.has_net())
                            {
                                state().log().error.op(ME_SOLVER_TERMINAL_NO_NET(t.name()));
                                num_errors++;
                            }
                            else
                            {
                                var otherterm = t is terminal_t ? (terminal_t)t : null;  //auto *otherterm = dynamic_cast<terminal_t *>(t);
                                if (otherterm != null)
                                {
                                    if (state().setup().get_connected_terminal(otherterm).net().is_rail_net())
                                    {
                                        railterms++;
                                    }
                                }
                            }
                        }
                    }

                    if (railterms == 0)
                    {
                        state().log().error.op(ME_SOLVER_NO_RAIL_TERMINAL(nets_in_grp));
                        num_errors++;
                    }
                }

                if (num_errors > 0)
                {
                    throw new nl_exception(MF_SOLVER_CONSISTENCY_ERRORS(num_errors));
                }

                // setup the solvers
                foreach (var grp in splitter.groups)
                {
                    nld_solver_solver_ptr ms       = null;
                    string sname                   = new plib.pfmt("Solver_{0}").op(m_mat_solvers.size());
                    nld_solver_params_uptr params_ = new solver.solver_parameters_t(this, sname + ".", m_params);  //params_uptr params = plib::make_unique<solver::solver_parameters_t, solver_arena>(*this, sname + ".", m_params);

                    switch (params_.m_fp_type.op())
                    {
                    case solver.matrix_fp_type_e.FLOAT:
                        if (!config.use_float_matrix)
                        {
                            log().info.op("FPTYPE {0} not supported. Using DOUBLE", params_.m_fp_type.op().ToString());
                        }

                        //ms = create_solvers<std::conditional_t<config::use_float_matrix::value, float, double>>(sname, params.get(), grp);
                        if (config.use_float_matrix)
                        {
                            ms = create_solvers <float, plib.constants_operators_float>(sname, params_, grp);
                        }
                        else
                        {
                            ms = create_solvers <double, plib.constants_operators_double>(sname, params_, grp);
                        }
                        break;

                    case solver.matrix_fp_type_e.DOUBLE:
                        ms = create_solvers <double, plib.constants_operators_double>(sname, params_, grp);     //ms = create_solvers<double>(sname, params.get(), grp);
                        break;

                    case solver.matrix_fp_type_e.LONGDOUBLE:
                        if (!config.use_long_double_matrix)
                        {
                            log().info.op("FPTYPE {0} not supported. Using DOUBLE", params_.m_fp_type.op().ToString());
                        }

                        //ms = create_solvers<std::conditional_t<config::use_long_double_matrix::value, long double, double>>(sname, params.get(), grp);
                        if (config.use_long_double_matrix)
                        {
                            throw new emu_unimplemented();      //ms = create_solvers<long double>(sname, params_, grp);
                        }
                        else
                        {
                            ms = create_solvers <double, plib.constants_operators_double>(sname, params_, grp);
                        }
                        break;

                    case solver.matrix_fp_type_e.FLOATQ128:
#if (NL_USE_FLOAT128)
                        ms = create_solvers <FLOAT128>(sname, params.get(), grp);
#else
                        log().info.op("FPTYPE {0} not supported. Using DOUBLE", params_.m_fp_type.op().ToString());
                        ms = create_solvers <double, plib.constants_operators_double>(sname, params_, grp);     //ms = create_solvers<double>(sname, params.get(), grp);
#endif
                        break;
                    }

                    log().verbose.op("Solver {0}", ms.name());
                    log().verbose.op("       ==> {0} nets", grp.size());
                    log().verbose.op("       has {0} dynamic elements", ms.dynamic_device_count());
                    log().verbose.op("       has {0} timestep elements", ms.timestep_device_count());
                    foreach (var n in grp)
                    {
                        log().verbose.op("Net {0}", n.name());
                        foreach (var t in state().core_terms(n))
                        {
                            log().verbose.op("   {0}", t.name());
                        }
                    }

                    m_mat_params.push_back(params_);

                    m_mat_solvers.push_back(ms);
                }
            }
예제 #16
0
        }                                                                                                                  //void gaussian_back_substitution(V1 &V, const V2 &RHS)

        //template <typename V1>
        //void gaussian_back_substitution(V1 &V)


        //template <typename M>
        void build_parallel_gaussian_execution_scheme(std.vector <std.vector <unsigned> > fill)  //void build_parallel_gaussian_execution_scheme(const M &fill)
        {
            // calculate parallel scheme for gaussian elimination
            std.vector <std.vector <size_t> > rt = new std.vector <std.vector <size_t> >(base.size());
            for (size_t k = 0; k < base.size(); k++)
            {
                rt[k] = new std.vector <size_t>();
                for (size_t j = k + 1; j < base.size(); j++)
                {
                    if (fill[j][k] < (size_t)pmatrix_cr <B, B_OPS, int_N> .constants_e.FILL_INFINITY)
                    {
                        rt[k].push_back(j);
                    }
                }
            }

            std.vector <size_t> levGE = new std.vector <size_t>(base.size(), 0);
            size_t cl = 0;

            for (size_t k = 0; k < base.size(); k++)
            {
                if (levGE[k] >= cl)
                {
                    std.vector <size_t> t = rt[k];
                    for (size_t j = k + 1; j < base.size(); j++)
                    {
                        bool overlap = false;
                        // is there overlap
                        if (plib.container.contains(t, j))
                        {
                            overlap = true;
                        }

                        foreach (var x in rt[j])
                        {
                            if (plib.container.contains(t, x))
                            {
                                overlap = true;
                                break;
                            }
                        }

                        if (overlap)
                        {
                            levGE[j] = cl + 1;
                        }
                        else
                        {
                            t.push_back(j);
                            foreach (var x in rt[j])
                            {
                                t.push_back(x);
                            }
                        }
                    }
                    cl++;
                }
            }

            m_ge_par.clear();
            m_ge_par.resize(cl + 1);
            m_ge_par.Fill(() => { return(new std.vector <size_t>()); });
            for (size_t k = 0; k < base.size(); k++)
            {
                m_ge_par[levGE[k]].push_back(k);
            }

            //for (std::size_t k = 0; k < m_ge_par.size(); k++)
            //  printf("%d %d\n", (int) k, (int) m_ge_par[k].size());
        }
예제 #17
0
        // parsing/input
        //-------------------------------------------------
        //  parse_command_line - parse a series of
        //  command line arguments
        //-------------------------------------------------
        public void parse_command_line(std.vector <string> args, int priority, bool ignore_unknown_options = false)
        {
            string         error_stream = ""; //std::ostringstream error_stream;
            condition_type condition    = condition_type.NONE;

            // reset the errors and the command
            m_command = "";

            // we want to identify commands first
            for (int arg = 1; arg < args.Count; arg++)
            {
                if (!args[(int)arg].empty() && args[(int)arg][0] == '-')
                {
                    var curentry = get_entry(args[arg].Substring(1));
                    if (curentry != null && curentry.type() == OPTION_COMMAND)
                    {
                        // can only have one command
                        if (!m_command.empty())
                        {
                            throw new options_error_exception("Error: multiple commands specified -{0} and {1}\n", m_command, args[arg]);
                        }

                        m_command = curentry.name();
                    }
                }
            }

            // iterate through arguments
            int unadorned_index = 0;

            for (int arg = 1; arg < args.Count; arg++)
            {
                // determine the entry name to search for
                string curarg       = args[(int)arg];
                bool   is_unadorned = curarg[0] != '-';
                string optionname   = is_unadorned ? core_options.unadorned(unadorned_index++) : curarg.Remove(0, 1); // curarg[1];

                // special case - collect unadorned arguments after commands into a special place
                if (is_unadorned && !m_command.empty())
                {
                    m_command_arguments.push_back(args[(int)arg]);
                    command_argument_processed();
                    continue;
                }

                // find our entry; if not found, continue
                var curentry = get_entry(optionname);
                if (curentry == null)
                {
                    if (!ignore_unknown_options)
                    {
                        throw new options_error_exception("Error: unknown option: -{0}\n", optionname);
                    }
                    continue;
                }

                // at this point, we've already processed commands
                if (curentry.type() == OPTION_COMMAND)
                {
                    continue;
                }

                // get the data for this argument, special casing booleans
                string newdata;
                if (curentry.type() == OPTION_BOOLEAN)
                {
                    newdata = string.Compare(curarg.Remove(0, 1), 0, "no", 0, 2) == 0 ? "0" : "1";  //(strncmp(&curarg[1], "no", 2) == 0) ? "0" : "1";
                }
                else if (is_unadorned)
                {
                    newdata = curarg;
                }
                else if (arg + 1 < args.Count)
                {
                    newdata = args[++arg];
                }
                else
                {
                    throw new options_error_exception("Error: option {0} expected a parameter\n", curarg);
                }

                // set the new data
                do_set_value(curentry, newdata, priority, ref error_stream, condition);
            }

            // did we have any errors that may need to be aggregated?
            throw_options_exception_if_appropriate(condition, error_stream);
        }
예제 #18
0
        //-------------------------------------------------
        //  add_entry - adds an entry based on an
        //  options_entry
        //-------------------------------------------------
        void add_entry(options_entry opt, bool override_existing = false)
        {
            std.vector <string> names = new std.vector <string>();
            string minimum            = "";
            string maximum            = "";

            // copy in the name(s) as appropriate
            if (opt.name != null)
            {
                // first extract any range
                string namestr = opt.name;
                size_t lparen  = namestr.find_first_of('(', 0);
                if (lparen != npos)
                {
                    size_t dash = namestr.find_first_of('-', lparen + 1);
                    if (dash != npos)
                    {
                        size_t rparen = namestr.find_first_of(')', dash + 1);
                        if (rparen != npos)
                        {
                            minimum = namestr.Substring((int)lparen + 1, (int)(dash - (lparen + 1))).Trim(); //minimum.assign(strtrimspace(std::string_view(&namestr[lparen + 1], dash - (lparen + 1))));
                            maximum = namestr.Substring((int)dash + 1, (int)(rparen - (dash + 1))).Trim();   //maximum.assign(strtrimspace(std::string_view(&namestr[dash + 1], rparen - (dash + 1))));
                            namestr = namestr.Remove((int)lparen, (int)(rparen + 1 - lparen));               //namestr.erase(lparen, rparen + 1 - lparen);
                        }
                    }
                }

                // then chop up any semicolon-separated names
                size_t semi;
                while ((semi = namestr.find_first_of(';')) != npos)
                {
                    names.push_back(namestr.substr(0, semi));

                    // for booleans, add the "-noXYZ" option as well
                    if (opt.type == option_type.BOOLEAN)
                    {
                        names.push_back("no" + names.back());
                    }

                    namestr = namestr.Remove(0, (int)semi + 1);  //namestr.erase(0, semi + 1);
                }

                // finally add the last item
                names.push_back(namestr);
                if (opt.type == option_type.BOOLEAN)
                {
                    names.push_back("no" + names.back());
                }
            }

            // we might be called with an existing entry
            entry existing_entry = null;

            do
            {
                foreach (string name in names)
                {
                    existing_entry = get_entry(name);
                    if (existing_entry != null)
                    {
                        break;
                    }
                }

                if (existing_entry != null)
                {
                    if (override_existing)
                    {
                        remove_entry(existing_entry);
                    }
                    else
                    {
                        return;
                    }
                }
            } while (existing_entry != null);

            // set the default value
            string defdata = opt.defvalue != null ? opt.defvalue : "";

            // create and add the entry
            add_entry(
                names,
                opt.description,
                opt.type,
                defdata,
                minimum,
                maximum);
        }
예제 #19
0
        //struct stats_info
        //{
        //    const detail::queue_t               &m_queue;// performance
        //    const plib::pperftime_t<true>       &m_stat_mainloop;
        //    const plib::pperfcount_t<true>      &m_perf_out_processed;
        //};

        /// \brief print statistics gathered during run
        ///
        //void print_stats(stats_info &si) const;


        /// \brief call reset on all netlist components
        ///
        public void reset()
        {
            // Reset all nets once !
            log().verbose.op("Call reset on all nets:");
            foreach (var n in nets())
            {
                n.reset();
            }

            // Reset all devices once !
            log().verbose.op("Call reset on all devices:");
            foreach (var dev in m_devices)
            {
                dev.second.reset();
            }

            // Make sure everything depending on parameters is set
            // Currently analog input and logic input also
            // push their outputs to queue.

            std.vector <core_device_t> devices_called = new std.vector <core_device_t>();
            log().verbose.op("Call update_param on all devices:");
            foreach (var dev in m_devices)
            {
                dev.second.update_param();
                if (!plib.container.contains(devices_called, dev.second))
                {
                    devices_called.push_back(dev.second);
                }
            }

            // Step all devices once !
            //
            // INFO: The order here affects power up of e.g. breakout. However, such
            // variations are explicitly stated in the breakout manual.

            var netlist_params = get_single_device <devices.nld_netlistparams>("parameter");

            switch (netlist_params.m_startup_strategy.op())
            {
            case 0:
            {
                std.vector <nldelegate> t = new std.vector <nldelegate>();
                log().verbose.op("Using default startup strategy");
                foreach (var n in m_nets)
                {
                    n.update_inputs();     // only used if USE_COPY_INSTEAD_OF_REFERENCE == 1
                    foreach (var term in core_terms(n))
                    {
                        if (!plib.container.contains(t, term.delegate_()))
                        {
                            t.push_back(term.delegate_());
                            term.run_delegate();
                        }

                        // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
                        var dev = (core_device_t)term.delegate_device();      //auto *dev = reinterpret_cast<core_device_t *>(term->delegate().object());
                        if (!plib.container.contains(devices_called, dev))
                        {
                            devices_called.push_back(dev);
                        }
                    }
                }

                log().verbose.op("Devices not yet updated:");
                foreach (var dev in m_devices)
                {
                    if (!plib.container.contains(devices_called, dev.second))
                    {
                        // FIXME: doesn't seem to be needed, use cases include
                        // analog output devices. Check and remove
                        log().error.op("\t Device {0} not yet updated", dev.second.name());
                        //dev.second->update();
                    }
                }
            }
            break;
            }

            // the above may screw up m_active and the list
            rebuild_lists();
        }
예제 #20
0
        public void compile_infix(string expr, std.vector <string> inputs)  //void compile_infix(const pstring &expr, const inputs_container &inputs = inputs_container()) noexcept(false);
        {
            // Shunting-yard infix parsing
            std.vector <string> sep = new std.vector <string> {
                "(", ")", ",", "*", "/", "+", "-", "^", "<=", ">=", "==", "!=", "<", ">"
            };
            std.vector <string> sexpr2  = plib.pg.psplit(plib.pg.replace_all(expr, " ", ""), sep);
            std.stack <string>  opstk   = new std.stack <string>();
            std.vector <string> postfix = new std.vector <string>();
            std.vector <string> sexpr1  = new std.vector <string>();
            std.vector <string> sexpr   = new std.vector <string>();

            // FIXME: We really need to switch to ptokenizer and fix negative number
            //        handling in ptokenizer.

            // copy/paste to the int version below

            // Fix numbers exponential numbers
            for (size_t i = 0; i < sexpr2.size();)
            {
                if (i + 2 < sexpr2.size() && sexpr2[i].length() > 1)
                {
                    var r  = plib.pg.right(sexpr2[i], 1);
                    var ne = sexpr2[i + 1];
                    if (is_number(sexpr2[i]) &&
                        (r == "e" || r == "E") &&
                        (ne == "-" || ne == "+"))
                    {
                        sexpr1.push_back(sexpr2[i] + ne + sexpr2[i + 2]);
                        i += 3;
                    }
                    else
                    {
                        sexpr1.push_back(sexpr2[i++]);
                    }
                }
                else
                {
                    sexpr1.push_back(sexpr2[i++]);
                }
            }

            // Fix numbers with unary minus/plus
            for (size_t i = 0; i < sexpr1.size();)
            {
                if (sexpr1[i] == "-" && (i + 1 < sexpr1.size()) && is_number(sexpr1[i + 1]))
                {
                    if (i == 0 || !(is_number(sexpr1[i - 1]) || sexpr1[i - 1] == ")" || is_id(sexpr1[i - 1])))
                    {
                        sexpr.push_back("-" + sexpr1[i + 1]);
                        i += 2;
                    }
                    else
                    {
                        sexpr.push_back(sexpr1[i++]);
                    }
                }
                else if (sexpr1[i] == "-" && (i + 1 < sexpr1.size()) && (is_id(sexpr1[i + 1]) || sexpr1[i + 1] == "("))
                {
                    if (i == 0 || !(is_number(sexpr1[i - 1]) || sexpr1[i - 1] == ")" || is_id(sexpr1[i - 1])))
                    {
                        sexpr.emplace_back("neg");
                        sexpr.push_back(sexpr1[i + 1]);
                        i += 2;
                    }
                    else
                    {
                        sexpr.push_back(sexpr1[i++]);
                    }
                }
                else
                {
                    sexpr.push_back(sexpr1[i++]);
                }
            }

            for (size_t i = 0; i < sexpr.size(); i++)
            {
                string s = sexpr[i];
                if (s == "(")
                {
                    opstk.push(s);
                }
                else if (s == ")")
                {
                    string x = pop_check(opstk, expr);
                    while (x != "(")
                    {
                        postfix.push_back(x);
                        x = pop_check(opstk, expr);
                    }

                    if (!opstk.empty() && get_prio(opstk.top()) == 0)
                    {
                        postfix.push_back(pop_check(opstk, expr));
                    }
                }
                else if (s == ",")
                {
                    string x = pop_check(opstk, expr);
                    while (x != "(")
                    {
                        postfix.push_back(x);
                        x = pop_check(opstk, expr);
                    }

                    opstk.push(x);
                }
                else
                {
                    int prio = get_prio(s);
                    if (prio > 0)
                    {
                        if (opstk.empty())
                        {
                            opstk.push(s);
                        }
                        else
                        {
                            if (get_prio(opstk.top()) >= prio)
                            {
                                postfix.push_back(pop_check(opstk, expr));
                            }

                            opstk.push(s);
                        }
                    }
                    else if (prio == 0) // Function or variable
                    {
                        if ((i + 1 < sexpr.size()) && sexpr[i + 1] == "(")
                        {
                            opstk.push(s);
                        }
                        else
                        {
                            postfix.push_back(s);
                        }
                    }
                    else
                    {
                        postfix.push_back(s);
                    }
                }
            }

            while (!opstk.empty())
            {
                postfix.push_back(opstk.top());
                opstk.pop();
            }

            //for (auto &e : postfix)
            //  printf("\t%s\n", e.c_str());
            compile_postfix(inputs, postfix, expr);
        }
예제 #21
0
        //template <typename NT>
        void compile_postfix(std.vector <string> inputs, std.vector <string> cmds, string expr)  //void pfunction<NT>::compile_postfix(const inputs_container &inputs, const std::vector<pstring> &cmds, const pstring &expr) noexcept(false)
        {
            m_precompiled.clear();
            int stk = 0;

            foreach (string cmd in cmds)
            {
                rpn_inst rc = new rpn_inst();
                var      p  = pcmds().find(cmd);
                if (p != default)
                {
                    rc   = new rpn_inst(p.cmd);
                    stk -= p.adj;
                }
                else
                {
                    for (size_t i = 0; i < inputs.size(); i++)
                    {
                        if (inputs[i] == cmd)
                        {
                            rc   = new rpn_inst(rpn_cmd.PUSH_INPUT, i);
                            stk += 1;
                            break;
                        }
                    }

                    if (rc.cmd() != rpn_cmd.PUSH_INPUT)
                    {
                        bool err = false;
                        var  rs  = plib.pg.right(cmd, 1);
                        var  r   = units_si().find(rs);                             //auto r=units_si<NT>().find(rs);
                        if (ops.equals(r, ops.default_))                            //if (r == units_si<NT>().end())
                        {
                            rc = new rpn_inst(ops.pstonum_ne(false, cmd, out err)); //rc = rpn_inst(plib::pstonum_ne<NT>(cmd, err));
                        }
                        else
                        {
                            rc = new rpn_inst(ops.multiply(ops.pstonum_ne(false, plib.pg.left(cmd, cmd.length() - 1), out err), r));  //rc = rpn_inst(plib::pstonum_ne<NT>(plib::left(cmd, cmd.length()-1), err) * r->second);
                        }

                        if (err)
                        {
                            throw new pexception(new plib.pfmt("pfunction: unknown/misformatted token <{0}> in <{1}>").op(cmd, expr));
                        }

                        stk += 1;
                    }
                }

                if (stk < 1)
                {
                    throw new pexception(new plib.pfmt("pfunction: stack underflow on token <{0}> in <{1}>").op(cmd, expr));
                }

                if (stk >= (int)MAX_STACK)
                {
                    throw new pexception(new plib.pfmt("pfunction: stack overflow on token <{0}> in <{1}>").op(cmd, expr));
                }

                if (rc.cmd() == rpn_cmd.LP || rc.cmd() == rpn_cmd.RP)
                {
                    throw new pexception(new plib.pfmt("pfunction: parenthesis inequality on token <{1}> in <{2}>").op(cmd, expr));
                }

                m_precompiled.push_back(rc);
            }

            if (stk != 1)
            {
                throw new pexception(new plib.pfmt("pfunction: stack count {0} different to one on <{1}>").op(stk, expr));
            }

            compress();
        }
예제 #22
0
        //-------------------------------------------------
        //  add_entry - adds an entry based on an
        //  options_entry
        //-------------------------------------------------
        void add_entry(options_entry opt, bool override_existing = false)
        {
            std.vector <string> names = new std.vector <string>();
            string minimum            = "";
            string maximum            = "";

            // copy in the name(s) as appropriate
            if (opt.name != null)
            {
                // first extract any range
                string namestr = opt.name;
                int    lparen  = namestr.find_first_of('(', 0);
                int    dash    = namestr.find_first_of('-', lparen + 1);
                int    rparen  = namestr.find_first_of(')', dash + 1);
                if (lparen != -1 && dash != -1 && rparen != -1)
                {
                    minimum = namestr.substr(lparen + 1, dash - (lparen + 1)).Trim(); //strtrimspace(minimum.assign(namestr.substr(lparen + 1, dash - (lparen + 1))));
                    maximum = namestr.substr(dash + 1, rparen - (dash + 1)).Trim();   //strtrimspace(maximum.assign(namestr.substr(dash + 1, rparen - (dash + 1))));
                    namestr = namestr.Remove(lparen, rparen + 1 - lparen);            // .erase(lparen, rparen + 1 - lparen);
                }

                // then chop up any semicolon-separated names
                int semi;
                while ((semi = namestr.find_first_of(';')) != -1)
                {
                    names.push_back(namestr.substr(0, semi));
                    namestr = namestr.Remove(0, semi + 1);  //namestr.erase(0, semi + 1);
                }

                // finally add the last item
                names.push_back(namestr);
            }

            // we might be called with an existing entry
            entry existing_entry = null;

            do
            {
                foreach (string name in names)
                {
                    existing_entry = get_entry(name.c_str());
                    if (existing_entry != null)
                    {
                        break;
                    }
                }

                if (existing_entry != null)
                {
                    if (override_existing)
                    {
                        remove_entry(existing_entry);
                    }
                    else
                    {
                        return;
                    }
                }
            } while (existing_entry != null);

            // set the default value
            string defdata = opt.defvalue != null ? opt.defvalue : "";

            // create and add the entry
            add_entry(
                names,
                opt.description,
                opt.type,
                defdata,
                minimum,
                maximum);
        }
예제 #23
0
        //speaker_device &rear_center()       { set_position( 0.0,  0.0, -0.5); return *this; }
        //speaker_device &rear_left()         { set_position(-0.2,  0.0, -0.5); return *this; }
        //speaker_device &rear_right()        { set_position( 0.2,  0.0, -0.5); return *this; }
        //speaker_device &headrest_center()   { set_position( 0.0,  0.0, -0.1); return *this; }
        //speaker_device &headrest_left()     { set_position(-0.1,  0.0, -0.1); return *this; }
        //speaker_device &headrest_right()    { set_position( 0.1,  0.0, -0.1); return *this; }
        //speaker_device &seat()              { set_position( 0.0, -0.5,  0.0); return *this; }
        //speaker_device &backrest()          { set_position( 0.0, -0.2,  0.1); return *this; }


        // internally for use by the sound system
        //-------------------------------------------------
        //  mix - mix in samples from the speaker's stream
        //-------------------------------------------------
        public void mix(Pointer <stream_buffer_sample_t> leftmix, Pointer <stream_buffer_sample_t> rightmix, attotime start, attotime end, int expected_samples, bool suppress)  //void mix(stream_buffer::sample_t *leftmix, stream_buffer::sample_t *rightmix, attotime start, attotime end, int expected_samples, bool suppress)
        {
            // skip if no stream
            if (m_dimixer.m_mixer_stream == null)
            {
                return;
            }

            // skip if invalid range
            if (start > end)
            {
                return;
            }

            // get a view on the desired range
            read_stream_view view = m_dimixer.m_mixer_stream.update_view(start, end);

            sound_assert(view.samples() >= expected_samples);

            // track maximum sample value for each 0.1s bucket
            if (machine().options().speaker_report() != 0)
            {
                u32 samples_per_bucket = m_dimixer.m_mixer_stream.sample_rate() / BUCKETS_PER_SECOND;
                for (int sample = 0; sample < expected_samples; sample++)
                {
                    m_current_max = std.max(m_current_max, std.fabsf(view.get(sample)));
                    if (++m_samples_this_bucket >= samples_per_bucket)
                    {
                        m_max_sample.push_back(m_current_max);
                        m_current_max         = 0.0f;
                        m_samples_this_bucket = 0;
                    }
                }
            }

            // mix if sound is enabled
            if (!suppress)
            {
                // if the speaker is centered, send to both left and right
                if (m_x == 0)
                {
                    for (int sample = 0; sample < expected_samples; sample++)
                    {
                        stream_buffer_sample_t cursample = view.get(sample);
                        leftmix[sample]  += cursample;
                        rightmix[sample] += cursample;
                    }
                }

                // if the speaker is to the left, send only to the left
                else if (m_x < 0)
                {
                    for (int sample = 0; sample < expected_samples; sample++)
                    {
                        leftmix[sample] += view.get(sample);
                    }
                }

                // if the speaker is to the right, send only to the right
                else
                {
                    for (int sample = 0; sample < expected_samples; sample++)
                    {
                        rightmix[sample] += view.get(sample);
                    }
                }
            }
        }
예제 #24
0
            //~nld_solver()
            //{
            //    for (auto &s : m_mat_solvers)
            //    {
            //        plib::pfree(s);
            //    }
            //}


            public void post_start()
            {
                const bool use_specific = true;

                m_params.m_pivot    = m_pivot.op() ? 1 : 0;
                m_params.m_accuracy = m_accuracy.op();
                /* FIXME: Throw when negative */
                m_params.m_gs_loops        = (UInt32)m_gs_loops.op();
                m_params.m_nr_loops        = (UInt32)m_nr_loops.op();
                m_params.m_nr_recalc_delay = netlist_time.from_double(m_nr_recalc_delay.op());
                m_params.m_dynamic_lte     = m_dynamic_lte.op();
                m_params.m_gs_sor          = m_gs_sor.op();

                m_params.m_min_timestep = m_dynamic_min_ts.op();
                m_params.m_dynamic_ts   = (m_dynamic_ts.op() == true ? true : false);
                m_params.m_max_timestep = netlist_time.from_double(1.0 / m_freq.op()).as_double();

                if (m_params.m_dynamic_ts)
                {
                    m_params.m_max_timestep *= 1;//NL_FCONST(1000.0);
                }
                else
                {
                    m_params.m_min_timestep = m_params.m_max_timestep;
                }

                //m_params.m_max_timestep = std::max(m_params.m_max_timestep, m_params.m_max_timestep::)

                // Override log statistics
                string p = "";  //plib::util::environment("NL_STATS", "");

                if (p != "")
                {
                    m_params.m_log_stats = plib.pstring_global.pstonum_bool(p);  //plib::pstonum<decltype(m_params.m_log_stats)>(p);
                }
                else
                {
                    m_params.m_log_stats = m_log_stats.op();
                }

                log().verbose.op("Scanning net groups ...");
                // determine net groups

                net_splitter splitter = new net_splitter();

                splitter.run(state());

                // setup the solvers
                log().verbose.op("Found {0} net groups in {1} nets\n", splitter.groups.size(), state().nets().size());
                foreach (var grp in splitter.groups)
                {
                    matrix_solver_t ms;
                    UInt32          net_count = (UInt32)grp.size();
                    string          sname     = new plib.pfmt("Solver_{0}").op(m_mat_solvers.size());

                    switch (net_count)
                    {
#if true
                    case 1:
                        if (use_specific)
                        {
                            ms = new matrix_solver_direct1_t(state(), sname, m_params);      //ms = plib::palloc<matrix_solver_direct1_t<double>>(state(), sname, &m_params);
                        }
                        else
                        {
                            ms = create_solver/*<double, 1>*/ (1, 1, sname);
                        }
                        break;

                    case 2:
                        if (use_specific)
                        {
                            ms = new matrix_solver_direct2_t(state(), sname, m_params);      //ms =  plib::palloc<matrix_solver_direct2_t<double>>(state(), sname, &m_params);
                        }
                        else
                        {
                            ms = create_solver/*<double, 2>*/ (2, 2, sname);
                        }
                        break;

#if false
                    case 3:
                        ms = create_solver <double, 3>(3, sname);
                        break;

                    case 4:
                        ms = create_solver <double, 4>(4, sname);
                        break;

                    case 5:
                        ms = create_solver <double, 5>(5, sname);
                        break;

                    case 6:
                        ms = create_solver <double, 6>(6, sname);
                        break;

                    case 7:
                        ms = create_solver <double, 7>(7, sname);
                        break;

                    case 8:
                        ms = create_solver <double, 8>(8, sname);
                        break;

                    case 9:
                        ms = create_solver <double, 9>(9, sname);
                        break;

                    case 10:
                        ms = create_solver <double, 10>(10, sname);
                        break;

                    case 11:
                        ms = create_solver <double, 11>(11, sname);
                        break;

                    case 12:
                        ms = create_solver <double, 12>(12, sname);
                        break;

                    case 15:
                        ms = create_solver <double, 15>(15, sname);
                        break;

                    case 31:
                        ms = create_solver <double, 31>(31, sname);
                        break;

                    case 35:
                        ms = create_solver <double, 35>(35, sname);
                        break;

                    case 43:
                        ms = create_solver <double, 43>(43, sname);
                        break;

                    case 49:
                        ms = create_solver <double, 49>(49, sname);
                        break;
#endif
#if false
                    case 87:
                        ms = create_solver <87, 87>(87, sname);
                        break;
#endif
#endif
                    default:
                        log().warning.op(nl_errstr_global.MW_1_NO_SPECIFIC_SOLVER, net_count);
                        if (net_count <= 8)
                        {
                            ms = create_solver/*<double, -8>*/ (-8, net_count, sname);
                        }
                        else if (net_count <= 16)
                        {
                            ms = create_solver/*<double, -16>*/ (-16, net_count, sname);
                        }
                        else if (net_count <= 32)
                        {
                            ms = create_solver/*<double, -32>*/ (-32, net_count, sname);
                        }
                        else
                        if (net_count <= 64)
                        {
                            ms = create_solver/*<double, -64>*/ (-64, net_count, sname);
                        }
                        else
                        if (net_count <= 128)
                        {
                            ms = create_solver/*<double, -128>*/ (-128, net_count, sname);
                        }
                        else
                        {
                            log().fatal.op(nl_errstr_global.MF_1_NETGROUP_SIZE_EXCEEDED_1, 128);
                            ms = null;     /* tease compilers */
                        }
                        break;
                    }

                    // FIXME ...
                    ms.setup(grp);

                    log().verbose.op("Solver {0}", ms.name());
                    log().verbose.op("       ==> {0} nets", grp.size());
                    log().verbose.op("       has {0} elements", ms.has_dynamic_devices() ? "dynamic" : "no dynamic");
                    log().verbose.op("       has {0} elements", ms.has_timestep_devices() ? "timestep" : "no timestep");

                    foreach (var n in grp)
                    {
                        log().verbose.op("Net {0}", n.name());
                        foreach (var pcore in n.core_terms)
                        {
                            log().verbose.op("   {0}", pcore.name());
                        }
                    }

                    m_mat_solvers.push_back(ms);
                    if (ms.has_timestep_devices())
                    {
                        m_mat_solvers_timestepping.push_back(ms);
                    }
                }
            }
예제 #25
0
            /* return number of floating point operations for solve */
            //std::size_t ops() { return m_ops; }


            protected void setup_base(analog_net_t_list_t nets)
            {
                log().debug.op("New solver setup\n");

                m_nets.clear();
                m_terms.clear();

                foreach (var net in nets)
                {
                    m_nets.push_back(net);
                    m_terms.push_back(new terms_for_net_t());
                    m_rails_temp.push_back(new terms_for_net_t());
                }

                for (UInt32 k = 0; k < nets.size(); k++)
                {
                    analog_net_t net = nets[k];

                    log().debug.op("setting up net\n");

                    net.set_solver(this);

                    foreach (var p in net.core_terms)
                    {
                        log().debug.op("{0} {1} {2}\n", p.name(), net.name(), net.isRailNet());

                        switch (p.type())
                        {
                        case detail.terminal_type.TERMINAL:
                            if (p.device().is_timestep())
                            {
                                if (!m_step_devices.Contains(p.device()))      //(!plib::container::contains(m_step_devices, &p->device()))
                                {
                                    m_step_devices.push_back(p.device());
                                }
                            }

                            if (p.device().is_dynamic())
                            {
                                if (!m_dynamic_devices.Contains(p.device()))      //if (!plib::container::contains(m_dynamic_devices, &p->device()))
                                {
                                    m_dynamic_devices.push_back(p.device());
                                }
                            }

                            {
                                terminal_t pterm = (terminal_t)p;
                                add_term(k, pterm);
                            }

                            log().debug.op("Added terminal {0}\n", p.name());
                            break;

                        case detail.terminal_type.INPUT:
                        {
                            proxied_analog_output_t net_proxy_output = null;
                            foreach (var input in m_inps)
                            {
                                if (input.proxied_net == p.net())
                                {
                                    net_proxy_output = input;
                                    break;
                                }
                            }

                            if (net_proxy_output == null)
                            {
                                string nname = this.name() + "." + new plib.pfmt("m{0}").op(m_inps.size());
                                var    net_proxy_output_u = new proxied_analog_output_t(this, nname);
                                net_proxy_output = net_proxy_output_u;
                                m_inps.push_back(net_proxy_output_u);
                                nl_base_global.nl_assert(p.net().is_analog());
                                net_proxy_output.proxied_net = (analog_net_t)p.net();
                            }

                            net_proxy_output.net().add_terminal(p);

                            // FIXME: repeated calling - kind of brute force
                            net_proxy_output.net().rebuild_list();

                            log().debug.op("Added input\n");
                        }
                        break;

                        case detail.terminal_type.OUTPUT:
                            log().fatal.op(nl_errstr_global.MF_1_UNHANDLED_ELEMENT_1_FOUND, p.name());
                            break;
                        }
                    }

                    log().debug.op("added net with {0} populated connections\n", net.core_terms.size());
                }

                /* now setup the matrix */
                setup_matrix();
            }
예제 #26
0
        // debugging
        //void dump(std::ostream &str) const;
        //std::string dump();


        // internal helpers

        //-------------------------------------------------
        //  build_codes - given an input port table, create
        //  an input code table useful for mapping unicode
        //  chars
        //-------------------------------------------------
        void build_codes()
        {
            ioport_manager manager = machine().ioport();

            // find all the devices with keyboard or keypad inputs
            foreach (var port in manager.ports())
            {
                var devinfo =
                    std.find_if(
                        m_keyboards,
                        (kbd_dev_info info) =>
                {
                    return(port.second().device() == info.device);
                });

                foreach (ioport_field field in port.second().fields())
                {
                    bool is_keyboard = field.type() == ioport_type.IPT_KEYBOARD;
                    if (is_keyboard || (field.type() == ioport_type.IPT_KEYPAD))
                    {
                        if (default == devinfo)
                        {
                            //devinfo = m_keyboards.emplace(devinfo, port.second->device());
                            devinfo = new kbd_dev_info(port.second().device());
                            m_keyboards.push_back(devinfo);
                        }

                        devinfo.keyfields.emplace_back(field);

                        if (is_keyboard)
                        {
                            devinfo.keyboard = true;
                        }
                        else
                        {
                            devinfo.keypad = true;
                        }
                    }
                }
            }

            std.sort(
                m_keyboards,
                (kbd_dev_info l, kbd_dev_info r) =>
            {
                return(std.strcmp(l.device.tag(), r.device.tag()));
            });

            // set up key mappings for each keyboard
            std.array <ioport_field, size_t_const_SHIFT_COUNT> shift = new std.array <ioport_field, size_t_const_SHIFT_COUNT>();
            unsigned mask;
            bool     have_keyboard = false;

            foreach (kbd_dev_info devinfo in m_keyboards)
            {
                if (LOG_NATURAL_KEYBOARD)
                {
                    machine().logerror("natural_keyboard: building codes for {0}... ({1} fields)\n", devinfo.device.tag(), devinfo.keyfields.size());
                }

                // enable all pure keypads and the first keyboard
                if (!devinfo.keyboard || !have_keyboard)
                {
                    devinfo.enabled = true;
                }
                have_keyboard = have_keyboard || devinfo.keyboard;

                // find all shift keys
                std.fill(shift, (ioport_field)null);  //std::fill(std::begin(shift), std::end(shift), nullptr);
                mask = 0;
                foreach (ioport_field field in devinfo.keyfields)
                {
                    if (field.type() == ioport_type.IPT_KEYBOARD)
                    {
                        std.vector <char32_t> codes = field.keyboard_codes(0);
                        foreach (char32_t code in codes)
                        {
                            if ((code >= UCHAR_SHIFT_BEGIN) && (code <= UCHAR_SHIFT_END))
                            {
                                mask |= 1U << (int)(code - UCHAR_SHIFT_BEGIN);
                                shift[code - UCHAR_SHIFT_BEGIN] = field;
                                if (LOG_NATURAL_KEYBOARD)
                                {
                                    machine().logerror("natural_keyboard: UCHAR_SHIFT_{0} found\n", code - UCHAR_SHIFT_BEGIN + 1);
                                }
                            }
                        }
                    }
                }

                // iterate over keyboard/keypad fields
                foreach (ioport_field field in devinfo.keyfields)
                {
                    field.live().lockout = !devinfo.enabled;
                    if (field.type() == ioport_type.IPT_KEYBOARD)
                    {
                        // iterate over all shift states
                        for (unsigned curshift = 0; curshift < SHIFT_STATES; ++curshift)
                        {
                            if ((curshift & ~mask) == 0)
                            {
                                // fetch the code, ignoring 0 and shifters
                                std.vector <char32_t> codes = field.keyboard_codes((int)curshift);
                                foreach (char32_t code in codes)
                                {
                                    if (((code < UCHAR_SHIFT_BEGIN) || (code > UCHAR_SHIFT_END)) && (code != 0))
                                    {
                                        m_have_charkeys = true;
                                        var found = devinfo.codemap.find(code);      //keycode_map::iterator const found(devinfo.codemap.find(code));
                                        keycode_map_entry newcode = new keycode_map_entry();
                                        std.fill(newcode.field, (ioport_field)null); //std::fill(std::begin(newcode.field), std::end(newcode.field), nullptr);
                                        newcode.shift     = curshift;
                                        newcode.condition = field.condition();

                                        unsigned fieldnum = 0;
                                        for (unsigned i = 0, bits = curshift; (i < SHIFT_COUNT) && (bits != 0); ++i, bits >>= 1)
                                        {
                                            if (BIT(bits, 0) != 0)
                                            {
                                                newcode.field[fieldnum++] = shift[i];
                                            }
                                        }

                                        newcode.field[fieldnum] = field;
                                        if (default == found)
                                        {
                                            natural_keyboard_keycode_map_entries entries = new natural_keyboard_keycode_map_entries();
                                            entries.emplace_back(newcode);
                                            devinfo.codemap.emplace(code, entries);
                                        }
                                        else
                                        {
                                            found.emplace_back(newcode);
                                        }

                                        if (LOG_NATURAL_KEYBOARD)
                                        {
                                            machine().logerror("natural_keyboard: code={0} ({1}) port={2} field.name='{3}'\n",
                                                               code, unicode_to_string(code), field.port(), field.name());
                                        }
                                    }
                                }
                            }
                        }
                    }
                }

                // sort mapping entries by shift state
                foreach (var mapping in devinfo.codemap)
                {
                    std.sort(
                        mapping.second(),
                        (keycode_map_entry x, keycode_map_entry y) => { return(x.shift.CompareTo(y.shift)); });     //[] (keycode_map_entry const &x, keycode_map_entry const &y) { return x.shift < y.shift; });
                }
            }