diff options
| -rw-r--r-- | nl_examples/bjt_eb.c | 4 | ||||
| -rw-r--r-- | nl_examples/vccs.c | 2 | ||||
| -rw-r--r-- | nl_examples/vccs1.c | 2 | ||||
| -rw-r--r-- | src/emu/drawgfxm.h | 9 | ||||
| -rw-r--r-- | src/emu/emualloc.c | 10 | ||||
| -rw-r--r-- | src/emu/machine/netlist.h | 2 | ||||
| -rw-r--r-- | src/emu/netlist/analog/nld_fourterm.h | 6 | ||||
| -rw-r--r-- | src/emu/netlist/analog/nld_solver.c | 296 | ||||
| -rw-r--r-- | src/emu/netlist/analog/nld_solver.h | 15 | ||||
| -rw-r--r-- | src/emu/netlist/devices/net_lib.c | 6 | ||||
| -rw-r--r-- | src/emu/netlist/devices/nld_system.h | 2 | ||||
| -rw-r--r-- | src/emu/netlist/nl_base.c | 31 | ||||
| -rw-r--r-- | src/emu/netlist/nl_lists.h | 306 | ||||
| -rw-r--r-- | src/emu/netlist/nl_setup.c | 2 | ||||
| -rw-r--r-- | src/emu/netlist/nl_setup.h | 28 | ||||
| -rw-r--r-- | src/emu/render.c | 6 | ||||
| -rw-r--r-- | src/emu/screen.c | 985 | ||||
| -rw-r--r-- | src/emu/screen.h | 114 | ||||
| -rw-r--r-- | src/emu/ui/ui.c | 242 |
19 files changed, 1711 insertions, 357 deletions
diff --git a/nl_examples/bjt_eb.c b/nl_examples/bjt_eb.c index b6cfab70994..bc35345a44d 100644 --- a/nl_examples/bjt_eb.c +++ b/nl_examples/bjt_eb.c @@ -36,7 +36,7 @@ NETLIST_START(bjt) NET_C(RCE.1, Q.C) NET_C(RCE.2, GND) - LOG(logB, Q.B) - LOG(logC, Q.C) + //LOG(logB, Q.B) + //LOG(logC, Q.C) NETLIST_END() diff --git a/nl_examples/vccs.c b/nl_examples/vccs.c index 73cefd15fb1..fdad0c04a64 100644 --- a/nl_examples/vccs.c +++ b/nl_examples/vccs.c @@ -13,7 +13,7 @@ NETLIST_START(vccs) PARAM(Solver.ACCURACY, 1e-12) PARAM(Solver.RESCHED_LOOPS, 10000) - NETDEV_VCCS(VV) + VCCS(VV) PARAM(VV.G, 100) // typical OP-AMP amplification RES(R2, 1) diff --git a/nl_examples/vccs1.c b/nl_examples/vccs1.c index c1a5725f93c..72db7467d84 100644 --- a/nl_examples/vccs1.c +++ b/nl_examples/vccs1.c @@ -13,7 +13,7 @@ NETLIST_START(vccs) PARAM(Solver.ACCURACY, 1e-6) - NETDEV_VCCS(VV) + VCCS(VV) PARAM(VV.G, 100000) // typical OP-AMP amplification RES(R1, 10000) RES(R2, 1) diff --git a/src/emu/drawgfxm.h b/src/emu/drawgfxm.h index fe8c7dae69f..42028b9e38a 100644 --- a/src/emu/drawgfxm.h +++ b/src/emu/drawgfxm.h @@ -147,6 +147,15 @@ do } \ while (0) +#define PIXEL_OP_REMAP_TRANSPEN_IND16(DEST, PRIORITY, SOURCE) \ +do \ +{ \ + UINT32 srcdata = (SOURCE); \ + if (srcdata != transpen) \ + (DEST) = srcdata + palbase; \ +} \ +while (0) \ + /*------------------------------------------------- PIXEL_OP_REBASE_TRANSPEN - render all pixels except those matching 'transpen', adding diff --git a/src/emu/emualloc.c b/src/emu/emualloc.c index 22c0e044fed..43cea456b20 100644 --- a/src/emu/emualloc.c +++ b/src/emu/emualloc.c @@ -574,6 +574,16 @@ void memory_entry::report_unfreed() fprintf(stderr, "--- memory leak warning ---\n"); total += entry->m_size; fprintf(stderr, "#%06d, nofree %d bytes (%s:%d)\n", (UINT32)entry->m_id, static_cast<UINT32>(entry->m_size), entry->m_file, (int)entry->m_line); + char * p = static_cast<char *>(entry->m_base); + for (int i = 0; i< entry->m_size; i++) + { + char c = p[i]; + if (c>=32 && c<127) + fprintf(stderr, "%c", c); + else + fprintf(stderr, "."); + } + fprintf(stderr,"\n"); } release_lock(); diff --git a/src/emu/machine/netlist.h b/src/emu/machine/netlist.h index 9bd77f3ca87..e13954e360a 100644 --- a/src/emu/machine/netlist.h +++ b/src/emu/machine/netlist.h @@ -98,7 +98,7 @@ // ---------------------------------------------------------------------------------------- #define NETLIST_MEMREGION(_name) \ - netlist.parse((char *)downcast<netlist_mame_t &>(netlist.netlist()).machine().root_device().memregion(_name)->base()); + setup.parse((char *)downcast<netlist_mame_t &>(setup.netlist()).machine().root_device().memregion(_name)->base()); #define NETDEV_ANALOG_CALLBACK_MEMBER(_name) \ void _name(const double data, const attotime &time) diff --git a/src/emu/netlist/analog/nld_fourterm.h b/src/emu/netlist/analog/nld_fourterm.h index 6ef3c6ce3e9..0f330333bcd 100644 --- a/src/emu/netlist/analog/nld_fourterm.h +++ b/src/emu/netlist/analog/nld_fourterm.h @@ -14,13 +14,11 @@ // Macros // ---------------------------------------------------------------------------------------- -#define NETDEV_VCCS(_name) \ +#define VCCS(_name) \ NET_REGISTER_DEV(VCCS, _name) -//NETDEV_PARAMI(_name, model, _model) -#define NETDEV_VCVS(_name) \ +#define VCVS(_name) \ NET_REGISTER_DEV(VCVS, _name) -//NETDEV_PARAMI(_name, model, _model) // ---------------------------------------------------------------------------------------- // nld_CCCS diff --git a/src/emu/netlist/analog/nld_solver.c b/src/emu/netlist/analog/nld_solver.c index 8f9ee0e53b1..7441f5e8057 100644 --- a/src/emu/netlist/analog/nld_solver.c +++ b/src/emu/netlist/analog/nld_solver.c @@ -5,6 +5,7 @@ #include "nld_solver.h" #include "nld_twoterm.h" +#include "../nl_lists.h" #if HAS_OPENMP #include "omp.h" @@ -19,73 +20,73 @@ ATTR_COLD void netlist_matrix_solver_t::setup(netlist_net_t::list_t &nets, NETLIB_NAME(solver) &aowner) { - m_owner = &aowner; - - NL_VERBOSE_OUT(("New solver setup\n")); - - for (netlist_net_t * const * pn = nets.first(); pn != NULL; pn = nets.next(pn)) - { - NL_VERBOSE_OUT(("setting up net\n")); - - m_nets.add(*pn); - - (*pn)->m_solver = this; - - for (netlist_core_terminal_t *p = (*pn)->m_head; p != NULL; p = p->m_update_list_next) - { - NL_VERBOSE_OUT(("%s %s %d\n", p->name().cstr(), (*pn)->name().cstr(), (int) (*pn)->isRailNet())); - switch (p->type()) - { - case netlist_terminal_t::TERMINAL: - switch (p->netdev().family()) - { - case netlist_device_t::CAPACITOR: - if (!m_steps.contains(&p->netdev())) - m_steps.add(&p->netdev()); - break; - case netlist_device_t::BJT_EB: + m_owner = &aowner; + + NL_VERBOSE_OUT(("New solver setup\n")); + + for (netlist_net_t * const * pn = nets.first(); pn != NULL; pn = nets.next(pn)) + { + NL_VERBOSE_OUT(("setting up net\n")); + + m_nets.add(*pn); + + (*pn)->m_solver = this; + + for (netlist_core_terminal_t *p = (*pn)->m_head; p != NULL; p = p->m_update_list_next) + { + NL_VERBOSE_OUT(("%s %s %d\n", p->name().cstr(), (*pn)->name().cstr(), (int) (*pn)->isRailNet())); + switch (p->type()) + { + case netlist_terminal_t::TERMINAL: + switch (p->netdev().family()) + { + case netlist_device_t::CAPACITOR: + if (!m_steps.contains(&p->netdev())) + m_steps.add(&p->netdev()); + break; + case netlist_device_t::BJT_EB: case netlist_device_t::DIODE: - //case netlist_device_t::VCVS: - case netlist_device_t::BJT_SWITCH: + //case netlist_device_t::VCVS: + case netlist_device_t::BJT_SWITCH: NL_VERBOSE_OUT(("found BJT/Diode\n")); - if (!m_dynamic.contains(&p->netdev())) - m_dynamic.add(&p->netdev()); - break; - default: - break; - } - { - netlist_terminal_t *pterm = static_cast<netlist_terminal_t *>(p); - if (pterm->m_otherterm->net().isRailNet()) - (*pn)->m_rails.add(pterm); - else - (*pn)->m_terms.add(pterm); - } - NL_VERBOSE_OUT(("Added terminal\n")); - break; - case netlist_terminal_t::INPUT: - if (!m_inps.contains(p)) - m_inps.add(p); - NL_VERBOSE_OUT(("Added input\n")); - break; - default: - owner().netlist().error("unhandled element found\n"); - break; - } - } + if (!m_dynamic.contains(&p->netdev())) + m_dynamic.add(&p->netdev()); + break; + default: + break; + } + { + netlist_terminal_t *pterm = static_cast<netlist_terminal_t *>(p); + if (pterm->m_otherterm->net().isRailNet()) + (*pn)->m_rails.add(pterm); + else + (*pn)->m_terms.add(pterm); + } + NL_VERBOSE_OUT(("Added terminal\n")); + break; + case netlist_terminal_t::INPUT: + if (!m_inps.contains(p)) + m_inps.add(p); + NL_VERBOSE_OUT(("Added input\n")); + break; + default: + owner().netlist().error("unhandled element found\n"); + break; + } + } NL_VERBOSE_OUT(("added net with %d populated connections (%d railnets)\n", (*pn)->m_terms.count(), (*pn)->m_rails.count())); - } + } } -ATTR_HOT ATTR_HOT inline void netlist_matrix_solver_t::update_inputs() +ATTR_HOT void netlist_matrix_solver_t::update_inputs() { - for (netlist_core_terminal_t * const *p = m_inps.first(); p != NULL; p = m_inps.next(p)) - { - if ((*p)->net().m_last.Analog != (*p)->net().m_cur.Analog) - { - (*p)->netdev().update_dev(); - } - } + for (netlist_core_terminal_t * const *p = m_inps.first(); p != NULL; p = m_inps.next(p)) + { + if ((*p)->net().m_last.Analog != (*p)->net().m_cur.Analog) + { + (*p)->netdev().update_dev(); + } + } for (netlist_core_terminal_t * const *p = m_inps.first(); p != NULL; p = m_inps.next(p)) { (*p)->net().m_last.Analog = (*p)->net().m_cur.Analog; @@ -94,7 +95,7 @@ ATTR_HOT ATTR_HOT inline void netlist_matrix_solver_t::update_inputs() } -ATTR_HOT ATTR_HOT inline void netlist_matrix_solver_t::update_dynamic() +ATTR_HOT void netlist_matrix_solver_t::update_dynamic() { /* update all non-linear devices */ for (netlist_core_device_t * const *p = m_dynamic.first(); p != NULL; p = m_dynamic.next(p)) @@ -109,7 +110,7 @@ ATTR_HOT ATTR_HOT inline void netlist_matrix_solver_t::update_dynamic() } } -void netlist_matrix_solver_t::schedule() +ATTR_HOT void netlist_matrix_solver_t::schedule() { if (!solve()) { @@ -131,14 +132,14 @@ ATTR_COLD void netlist_matrix_solver_t::reset() m_last_step = netlist_time::zero; } -ATTR_HOT inline void netlist_matrix_solver_t::step(const netlist_time delta) +ATTR_HOT void netlist_matrix_solver_t::step(const netlist_time delta) { const double dd = delta.as_double(); for (int k=0; k < m_steps.count(); k++) m_steps[k]->step_time(dd); } -ATTR_HOT inline bool netlist_matrix_solver_t::solve() +ATTR_HOT bool netlist_matrix_solver_t::solve() { int resched_cnt = 0; @@ -162,14 +163,14 @@ ATTR_HOT inline bool netlist_matrix_solver_t::solve() update_dynamic(); this_resched = solve_non_dynamic(); resched_cnt += this_resched; - } while (this_resched > 1 && resched_cnt < m_resched_loops); + } while (this_resched > 1 && resched_cnt < m_params.m_resched_loops); } else { resched_cnt = solve_non_dynamic(); //printf("resched_cnt %d %d\n", resched_cnt, m_resched_loops); } - return (resched_cnt >= m_resched_loops); + return (resched_cnt >= m_params.m_resched_loops); } // ---------------------------------------------------------------------------------------- @@ -240,7 +241,7 @@ ATTR_COLD void netlist_matrix_solver_direct_t<m_N, _storage_N>::setup(netlist_ne } template <int m_N, int _storage_N> -ATTR_HOT inline void netlist_matrix_solver_direct_t<m_N, _storage_N>::build_LE( +ATTR_HOT void netlist_matrix_solver_direct_t<m_N, _storage_N>::build_LE( double (* RESTRICT A)[_storage_N], double (* RESTRICT RHS)) { @@ -282,7 +283,7 @@ ATTR_HOT inline void netlist_matrix_solver_direct_t<m_N, _storage_N>::build_LE( } template <int m_N, int _storage_N> -ATTR_HOT inline void netlist_matrix_solver_direct_t<m_N, _storage_N>::gauss_LE( +ATTR_HOT void netlist_matrix_solver_direct_t<m_N, _storage_N>::gauss_LE( double (* RESTRICT A)[_storage_N], double (* RESTRICT RHS), double (* RESTRICT x)) @@ -324,11 +325,14 @@ ATTR_HOT inline void netlist_matrix_solver_direct_t<m_N, _storage_N>::gauss_LE( { double f1 = A[j][i] * f; - for (int k = i; k < N(); k++) + if (f1 != 0.0) { - A[j][k] -= A[i][k] * f1; + for (int k = i; k < N(); k++) + { + A[j][k] -= A[i][k] * f1; + } + RHS[j] -= RHS[i] * f1; } - RHS[j] -= RHS[i] * f1; } } /* back substitution */ @@ -353,7 +357,7 @@ ATTR_HOT inline void netlist_matrix_solver_direct_t<m_N, _storage_N>::gauss_LE( } template <int m_N, int _storage_N> -ATTR_HOT inline double netlist_matrix_solver_direct_t<m_N, _storage_N>::delta( +ATTR_HOT double netlist_matrix_solver_direct_t<m_N, _storage_N>::delta( const double (* RESTRICT RHS), const double (* RESTRICT V)) { @@ -370,7 +374,7 @@ ATTR_HOT inline double netlist_matrix_solver_direct_t<m_N, _storage_N>::delta( } template <int m_N, int _storage_N> -ATTR_HOT inline void netlist_matrix_solver_direct_t<m_N, _storage_N>::store( +ATTR_HOT void netlist_matrix_solver_direct_t<m_N, _storage_N>::store( const double (* RESTRICT RHS), const double (* RESTRICT V)) { @@ -404,7 +408,7 @@ ATTR_HOT int netlist_matrix_solver_direct_t<m_N, _storage_N>::solve_non_dynamic( store(RHS, new_v); - if (err > this->m_accuracy * this->m_accuracy) + if (err > this->m_params.m_accuracy * this->m_params.m_accuracy) { return 2; } @@ -419,7 +423,7 @@ ATTR_HOT int netlist_matrix_solver_direct_t<m_N, _storage_N>::solve_non_dynamic( // netlist_matrix_solver - Direct1 // ---------------------------------------------------------------------------------------- -ATTR_HOT inline int netlist_matrix_solver_direct1_t::solve_non_dynamic() +ATTR_HOT int netlist_matrix_solver_direct1_t::solve_non_dynamic() { #if 1 @@ -454,7 +458,7 @@ ATTR_HOT inline int netlist_matrix_solver_direct1_t::solve_non_dynamic() net->m_cur.Analog = net->m_new.Analog = new_val; - if (is_dynamic() && (cerr > m_accuracy * m_accuracy)) + if (is_dynamic() && (cerr > m_params.m_accuracy * m_params.m_accuracy)) { return 2; } @@ -491,7 +495,7 @@ ATTR_HOT int netlist_matrix_solver_direct2_t::solve_non_dynamic() { double err = delta(RHS, new_val); store(RHS, new_val); - if (err > m_accuracy * m_accuracy) + if (err > m_params.m_accuracy * m_params.m_accuracy) return 2; else return 1; @@ -505,7 +509,7 @@ ATTR_HOT int netlist_matrix_solver_direct2_t::solve_non_dynamic() // ---------------------------------------------------------------------------------------- template <int m_N, int _storage_N> -ATTR_HOT inline int netlist_matrix_solver_gauss_seidel_t<m_N, _storage_N>::solve_non_dynamic() +ATTR_HOT int netlist_matrix_solver_gauss_seidel_t<m_N, _storage_N>::solve_non_dynamic() { bool resched = false; @@ -547,7 +551,7 @@ ATTR_HOT inline int netlist_matrix_solver_gauss_seidel_t<m_N, _storage_N>::solve RHS_t += terms[i]->m_Idr; } - gabs_t *= m_convergence_factor; + gabs_t *= m_params.m_convergence_factor; if (gabs_t > gtot_t) { // Actually 1.0 / g_tot * g_tot / (gtot_t + gabs_t) @@ -589,13 +593,13 @@ ATTR_HOT inline int netlist_matrix_solver_gauss_seidel_t<m_N, _storage_N>::solve net->m_cur.Analog = net->m_new.Analog = new_val; } - if (resched || cerr / m_nets.count() > m_accuracy * m_accuracy) + if (resched || cerr / m_nets.count() > m_params.m_accuracy * m_params.m_accuracy) { resched = true; //last_resched_net = net; } resched_cnt++; - } while (resched && (resched_cnt < m_resched_loops / 3 )); + } while (resched && (resched_cnt < m_params.m_resched_loops / 3 )); if (resched) return m_fallback.solve_non_dynamic(); @@ -611,64 +615,64 @@ typedef netlist_net_t::list_t *net_groups_t; ATTR_COLD static bool already_processed(net_groups_t groups, int &cur_group, netlist_net_t *net) { - if (net->isRailNet()) - return true; - for (int i = 0; i <= cur_group; i++) - { - if (groups[i].contains(net)) - return true; - } - return false; + if (net->isRailNet()) + return true; + for (int i = 0; i <= cur_group; i++) + { + if (groups[i].contains(net)) + return true; + } + return false; } ATTR_COLD static void process_net(net_groups_t groups, int &cur_group, netlist_net_t *net) { - if (net->m_head == NULL) - return; + if (net->m_head == NULL) + return; /* add the net */ - SOLVER_VERBOSE_OUT(("add %d - %s\n", cur_group, net->name().cstr())); - groups[cur_group].add(net); - for (netlist_core_terminal_t *p = net->m_head; p != NULL; p = p->m_update_list_next) - { - SOLVER_VERBOSE_OUT(("terminal %s\n", p->name().cstr())); - if (p->isType(netlist_terminal_t::TERMINAL)) - { - SOLVER_VERBOSE_OUT(("isterminal\n")); - netlist_terminal_t *pt = static_cast<netlist_terminal_t *>(p); - netlist_net_t *other_net = &pt->m_otherterm->net(); - if (!already_processed(groups, cur_group, other_net)) - process_net(groups, cur_group, other_net); - } - } + SOLVER_VERBOSE_OUT(("add %d - %s\n", cur_group, net->name().cstr())); + groups[cur_group].add(net); + for (netlist_core_terminal_t *p = net->m_head; p != NULL; p = p->m_update_list_next) + { + SOLVER_VERBOSE_OUT(("terminal %s\n", p->name().cstr())); + if (p->isType(netlist_terminal_t::TERMINAL)) + { + SOLVER_VERBOSE_OUT(("isterminal\n")); + netlist_terminal_t *pt = static_cast<netlist_terminal_t *>(p); + netlist_net_t *other_net = &pt->m_otherterm->net(); + if (!already_processed(groups, cur_group, other_net)) + process_net(groups, cur_group, other_net); + } + } } NETLIB_START(solver) { - register_output("Q_sync", m_Q_sync); - register_output("Q_step", m_Q_step); - //register_input("FB", m_feedback); + register_output("Q_sync", m_Q_sync); + register_output("Q_step", m_Q_step); + //register_input("FB", m_feedback); - register_param("SYNC_DELAY", m_sync_delay, NLTIME_FROM_NS(5).as_double()); - m_nt_sync_delay = m_sync_delay.Value(); + register_param("SYNC_DELAY", m_sync_delay, NLTIME_FROM_NS(5).as_double()); + m_nt_sync_delay = m_sync_delay.Value(); - register_param("FREQ", m_freq, 48000.0); - m_inc = netlist_time::from_hz(m_freq.Value()); + register_param("FREQ", m_freq, 48000.0); + m_inc = netlist_time::from_hz(m_freq.Value()); - register_param("ACCURACY", m_accuracy, 1e-7); - register_param("CONVERG", m_convergence, 0.3); + register_param("ACCURACY", m_accuracy, 1e-7); + register_param("CONVERG", m_convergence, 0.3); register_param("RESCHED_LOOPS", m_resched_loops, 35); register_param("PARALLEL", m_parallel, 0); - // internal staff + // internal staff - register_input("FB_sync", m_fb_sync); - register_input("FB_step", m_fb_step); + register_input("FB_sync", m_fb_sync); + register_input("FB_step", m_fb_step); - connect(m_fb_sync, m_Q_sync); - connect(m_fb_step, m_Q_step); + connect(m_fb_sync, m_Q_sync); + connect(m_fb_step, m_Q_step); - save(NAME(m_last_step)); + save(NAME(m_last_step)); } @@ -682,26 +686,26 @@ NETLIB_RESET(solver) NETLIB_UPDATE_PARAM(solver) { - m_inc = netlist_time::from_hz(m_freq.Value()); + m_inc = netlist_time::from_hz(m_freq.Value()); } NETLIB_NAME(solver)::~NETLIB_NAME(solver)() { - netlist_matrix_solver_t * const *e = m_mat_solvers.first(); - while (e != NULL) - { - netlist_matrix_solver_t * const *en = m_mat_solvers.next(e); - delete *e; - e = en; - } + netlist_matrix_solver_t * const *e = m_mat_solvers.first(); + while (e != NULL) + { + netlist_matrix_solver_t * const *en = m_mat_solvers.next(e); + delete *e; + e = en; + } } NETLIB_UPDATE(solver) { - netlist_time now = netlist().time(); - netlist_time delta = now - m_last_step; - bool do_full = false; + netlist_time now = netlist().time(); + netlist_time delta = now - m_last_step; + bool do_full = false; bool global_resched = false; bool this_resched[100]; int t_cnt = m_mat_solvers.count(); @@ -749,17 +753,17 @@ NETLIB_UPDATE(solver) } } - if (global_resched) - { - netlist().warning("Gobal reschedule .. Consider increasing RESCHED_LOOPS"); - schedule(); - } - else - { - /* step circuit */ - if (!m_Q_step.net().is_queued()) - m_Q_step.net().push_to_queue(m_inc); - } + if (global_resched) + { + netlist().warning("Gobal reschedule .. Consider increasing RESCHED_LOOPS"); + schedule(); + } + else + { + /* step circuit */ + if (!m_Q_step.net().is_queued()) + m_Q_step.net().push_to_queue(m_inc); + } } @@ -838,9 +842,9 @@ ATTR_COLD void NETLIB_NAME(solver)::post_start() break; } - ms->m_accuracy = m_accuracy.Value(); - ms->m_convergence_factor = m_convergence.Value(); - ms->m_resched_loops = m_resched_loops.Value(); + ms->m_params.m_accuracy = m_accuracy.Value(); + ms->m_params.m_convergence_factor = m_convergence.Value(); + ms->m_params.m_resched_loops = m_resched_loops.Value(); ms->setup(groups[i], *this); m_mat_solvers.add(ms); SOLVER_VERBOSE_OUT(("%d ==> %d nets %s\n", i, groups[i].count(), (*groups[i].first())->m_head->name().cstr())); diff --git a/src/emu/netlist/analog/nld_solver.h b/src/emu/netlist/analog/nld_solver.h index 0618a5f6f0b..09cbede5b6d 100644 --- a/src/emu/netlist/analog/nld_solver.h +++ b/src/emu/netlist/analog/nld_solver.h @@ -25,6 +25,13 @@ class NETLIB_NAME(solver); /* FIXME: these should become proper devices */ +struct netlist_solver_parameters_t +{ + double m_accuracy; + double m_convergence_factor; + int m_resched_loops; +}; + class netlist_matrix_solver_t { public: @@ -53,9 +60,7 @@ public: ATTR_HOT inline const NETLIB_NAME(solver) &owner() const; ATTR_COLD virtual void reset(); - double m_accuracy; - double m_convergence_factor; - int m_resched_loops; + netlist_solver_parameters_t m_params; protected: netlist_net_t::list_t m_nets; @@ -120,9 +125,7 @@ public: ATTR_COLD virtual void setup(netlist_net_t::list_t &nets, NETLIB_NAME(solver) &owner) { netlist_matrix_solver_t::setup(nets, owner); - m_fallback.m_accuracy = m_accuracy; - m_fallback.m_convergence_factor = m_convergence_factor; - m_fallback.m_resched_loops = m_resched_loops; + m_fallback.m_params = m_params; m_fallback.setup(nets, owner); } diff --git a/src/emu/netlist/devices/net_lib.c b/src/emu/netlist/devices/net_lib.c index 459fcd9d85e..1774d014923 100644 --- a/src/emu/netlist/devices/net_lib.c +++ b/src/emu/netlist/devices/net_lib.c @@ -78,8 +78,8 @@ void netlist_factory_t::initialize() ENTRY(POT, POT, "R") ENTRY(C, CAP, "C") ENTRY(D, DIODE, "model") - ENTRY(VCVS, NETDEV_VCVS, "-") - ENTRY(VCCS, NETDEV_VCCS, "-") + ENTRY(VCVS, VCVS, "-") // FIXME: STD parameters ? + ENTRY(VCCS, VCCS, "-") ENTRY(QBJT_EB, QBJT_EB, "model") ENTRY(QBJT_switch, QBJT_SW, "model") ENTRY(ttl_input, TTL_INPUT, "IN") @@ -89,7 +89,7 @@ void netlist_factory_t::initialize() ENTRY(clock, CLOCK, "FREQ") ENTRY(mainclock, MAINCLOCK, "FREQ") ENTRY(solver, SOLVER, "FREQ") - ENTRY(gnd, NETDEV_GND, "-") + ENTRY(gnd, GND, "-") ENTRY(switch2, SWITCH2, "+i1,i2") ENTRY(nicRSFF, NETDEV_RSFF, "+S,R") ENTRY(7400, TTL_7400_NAND, "+A,B") diff --git a/src/emu/netlist/devices/nld_system.h b/src/emu/netlist/devices/nld_system.h index cf1588e3c5c..5bb2b4154f2 100644 --- a/src/emu/netlist/devices/nld_system.h +++ b/src/emu/netlist/devices/nld_system.h @@ -33,7 +33,7 @@ NET_REGISTER_DEV(clock, _name) \ PARAM(_name.FREQ, _freq) -#define NETDEV_GND() \ +#define GND() \ NET_REGISTER_DEV(gnd, GND) // ---------------------------------------------------------------------------------------- diff --git a/src/emu/netlist/nl_base.c b/src/emu/netlist/nl_base.c index d4828773eec..e3053ca8ff5 100644 --- a/src/emu/netlist/nl_base.c +++ b/src/emu/netlist/nl_base.c @@ -240,17 +240,17 @@ ATTR_HOT ATTR_ALIGN void netlist_base_t::process_queue(const netlist_time delta) } else { #if 0 - netlist_net_t &mcQ = m_mainclock->m_Q.net(); + netlist_net_t &mc_net = m_mainclock->m_Q.net(); const netlist_time inc = m_mainclock->m_inc; while (m_time < m_stop) { if (m_queue.is_not_empty()) { - while (m_queue.peek().time() > mcQ.time()) + while (m_queue.peek().time() > mc_net.time()) { - m_time = mcQ.time(); - NETLIB_NAME(mainclock)::mc_update(mcQ, m_time + inc); + m_time = mc_net.time(); + NETLIB_NAME(mainclock)::mc_update(mc_net, m_time + inc); } const netlist_queue_t::entry_t &e = m_queue.pop(); @@ -258,8 +258,8 @@ ATTR_HOT ATTR_ALIGN void netlist_base_t::process_queue(const netlist_time delta) e.object()->update_devs(); } else { - m_time = mcQ.time(); - NETLIB_NAME(mainclock)::mc_update(mcQ, m_time + inc); + m_time = mc_net.time(); + NETLIB_NAME(mainclock)::mc_update(mc_net, m_time + inc); } if (FATAL_ERROR_AFTER_NS) if (time() > NLTIME_FROM_NS(FATAL_ERROR_AFTER_NS)) @@ -268,9 +268,9 @@ ATTR_HOT ATTR_ALIGN void netlist_base_t::process_queue(const netlist_time delta) add_to_stat(m_perf_out_processed, 1); } #else - netlist_net_t &mcQ = m_mainclock->m_Q.net(); + netlist_net_t &mc_net = m_mainclock->m_Q.net(); const netlist_time inc = m_mainclock->m_inc; - netlist_time mc_time = mcQ.time(); + netlist_time mc_time = mc_net.time(); netlist_time cur_time = m_time; while (cur_time < m_stop) @@ -282,7 +282,7 @@ ATTR_HOT ATTR_ALIGN void netlist_base_t::process_queue(const netlist_time delta) cur_time = mc_time; mc_time += inc; m_time = cur_time; - NETLIB_NAME(mainclock)::mc_update(mcQ); + NETLIB_NAME(mainclock)::mc_update(mc_net); } const netlist_queue_t::entry_t &e = m_queue.pop(); @@ -293,7 +293,7 @@ ATTR_HOT ATTR_ALIGN void netlist_base_t::process_queue(const netlist_time delta) cur_time = mc_time; mc_time += inc; m_time = cur_time; - NETLIB_NAME(mainclock)::mc_update(mcQ); + NETLIB_NAME(mainclock)::mc_update(mc_net); } if (FATAL_ERROR_AFTER_NS) if (time() > NLTIME_FROM_NS(FATAL_ERROR_AFTER_NS)) @@ -301,7 +301,7 @@ ATTR_HOT ATTR_ALIGN void netlist_base_t::process_queue(const netlist_time delta) add_to_stat(m_perf_out_processed, 1); } - mcQ.set_time(mc_time); + mc_net.set_time(mc_time); m_time = cur_time; #endif } @@ -825,20 +825,11 @@ ATTR_COLD double netlist_param_model_t::model_value(const pstring &entity, const // mainclock // ---------------------------------------------------------------------------------------- -#if 0 -ATTR_HOT inline void NETLIB_NAME(mainclock)::mc_update(netlist_net_t &net, const netlist_time curtime) -{ - net.m_new.Q ^= 1; - net.set_time(curtime); - net.update_devs(); -} -#else ATTR_HOT inline void NETLIB_NAME(mainclock)::mc_update(netlist_net_t &net) { net.m_new.Q ^= 1; net.update_devs(); } -#endif NETLIB_START(mainclock) { diff --git a/src/emu/netlist/nl_lists.h b/src/emu/netlist/nl_lists.h index 256f9f340b8..57842dd7883 100644 --- a/src/emu/netlist/nl_lists.h +++ b/src/emu/netlist/nl_lists.h @@ -5,6 +5,8 @@ * */ +#pragma once + #ifndef NLLISTS_H_ #define NLLISTS_H_ @@ -20,78 +22,78 @@ class netlist_list_t { public: - ATTR_COLD netlist_list_t(int numElements = _NumElem) - { - m_num_elements = numElements; - m_list = new _ListClass[m_num_elements]; + ATTR_COLD netlist_list_t(int numElements = _NumElem) + { + m_num_elements = numElements; + m_list = new _ListClass[m_num_elements]; m_count = 0; - } - - ATTR_COLD netlist_list_t(const netlist_list_t &rhs) - { - m_num_elements = rhs.capacity(); - m_list = new _ListClass[m_num_elements]; - m_count = 0; - for (int i=0; i<rhs.count(); i++) - { - this->add(rhs[i]); - } - } - - ATTR_COLD netlist_list_t &operator=(const netlist_list_t &rhs) - { - this->reset(); - for (int i=0; i<rhs.count(); i++) - { - this->add(rhs[i]); - } - return *this; - } - - - ATTR_COLD ~netlist_list_t() - { - delete[] m_list; - } - - ATTR_HOT inline void add(const _ListClass &elem) - { - if (m_count >= m_num_elements) - resize(m_num_elements * 2); - - m_list[m_count++] = elem; - } - - ATTR_HOT inline void resize(const int new_size) - { - int cnt = count(); - _ListClass *m_new = new _ListClass[new_size]; - _ListClass *pd = m_new; - - for (_ListClass *ps = m_list; ps < m_list + cnt; ps++, pd++) - *pd = *ps; - delete[] m_list; - m_list = m_new; - m_count = cnt; - m_num_elements = new_size; - } - - ATTR_HOT inline void remove(const _ListClass &elem) - { - for (int i = 0; i < m_count; i++) - { - if (m_list[i] == elem) - { - m_count --; - while (i < m_count) - { - m_list[i] = m_list[i+1]; - i++; - } - return; - } - } - } + } + + ATTR_COLD netlist_list_t(const netlist_list_t &rhs) + { + m_num_elements = rhs.capacity(); + m_list = new _ListClass[m_num_elements]; + m_count = 0; + for (int i=0; i<rhs.count(); i++) + { + this->add(rhs[i]); + } + } + + ATTR_COLD netlist_list_t &operator=(const netlist_list_t &rhs) + { + this->reset(); + for (int i=0; i<rhs.count(); i++) + { + this->add(rhs[i]); + } + return *this; + } + + + ATTR_COLD ~netlist_list_t() + { + delete[] m_list; + } + + ATTR_HOT inline void add(const _ListClass &elem) + { + if (m_count >= m_num_elements) + resize(m_num_elements * 2); + + m_list[m_count++] = elem; + } + + ATTR_HOT inline void resize(const int new_size) + { + int cnt = count(); + _ListClass *m_new = new _ListClass[new_size]; + _ListClass *pd = m_new; + + for (_ListClass *ps = m_list; ps < m_list + cnt; ps++, pd++) + *pd = *ps; + delete[] m_list; + m_list = m_new; + m_count = cnt; + m_num_elements = new_size; + } + + ATTR_HOT inline void remove(const _ListClass &elem) + { + for (int i = 0; i < m_count; i++) + { + if (m_list[i] == elem) + { + m_count --; + while (i < m_count) + { + m_list[i] = m_list[i+1]; + i++; + } + return; + } + } + } ATTR_HOT inline void remove_at(const int pos) { @@ -103,15 +105,15 @@ public: } } - ATTR_HOT inline bool contains(const _ListClass &elem) const - { - for (_ListClass *i = m_list; i < m_list + m_count; i++) - { - if (*i == elem) - return true; - } - return false; - } + ATTR_HOT inline bool contains(const _ListClass &elem) const + { + for (_ListClass *i = m_list; i < m_list + m_count; i++) + { + if (*i == elem) + return true; + } + return false; + } ATTR_HOT inline int indexof(const _ListClass &elem) const { @@ -123,30 +125,30 @@ public: return -1; } - ATTR_HOT inline const _ListClass *first() const { return ((m_count > 0) ? &m_list[0] : NULL ); } - ATTR_HOT inline const _ListClass *next(const _ListClass *lc) const { return ((lc < last()) ? lc + 1 : NULL ); } - ATTR_HOT inline const _ListClass *last() const { return &m_list[m_count -1]; } - ATTR_HOT inline int count() const { return m_count; } - ATTR_HOT inline bool empty() const { return (m_count == 0); } - ATTR_HOT inline void reset() { m_count = 0; } + ATTR_HOT inline const _ListClass *first() const { return ((m_count > 0) ? &m_list[0] : NULL ); } + ATTR_HOT inline const _ListClass *next(const _ListClass *lc) const { return ((lc < last()) ? lc + 1 : NULL ); } + ATTR_HOT inline const _ListClass *last() const { return &m_list[m_count -1]; } + ATTR_HOT inline int count() const { return m_count; } + ATTR_HOT inline bool empty() const { return (m_count == 0); } + ATTR_HOT inline void reset() { m_count = 0; } ATTR_HOT inline int capacity() const { return m_num_elements; } - ATTR_COLD void reset_and_free() - { - for (_ListClass *i = m_list; i < m_list + m_count; i++) - { - delete *i; - } - reset(); - } + ATTR_COLD void reset_and_free() + { + for (_ListClass *i = m_list; i < m_list + m_count; i++) + { + delete *i; + } + reset(); + } - ATTR_HOT inline _ListClass& operator[](const int & index) { return m_list[index]; } - ATTR_HOT inline const _ListClass& operator[](const int & index) const { return m_list[index]; } + ATTR_HOT inline _ListClass& operator[](const int & index) { return m_list[index]; } + ATTR_HOT inline const _ListClass& operator[](const int & index) const { return m_list[index]; } private: - int m_count; - _ListClass * m_list; - int m_num_elements; + int m_count; + _ListClass * m_list; + int m_num_elements; }; // ---------------------------------------------------------------------------------------- @@ -156,35 +158,35 @@ private: template <class _Element, class _Time, int _Size> class netlist_timed_queue { - NETLIST_PREVENT_COPYING(netlist_timed_queue) + NETLIST_PREVENT_COPYING(netlist_timed_queue) public: - struct entry_t - { - public: - ATTR_HOT inline entry_t() - : m_time(), m_object() {} - ATTR_HOT inline entry_t(const _Time atime, const _Element elem) : m_time(atime), m_object(elem) {} - ATTR_HOT inline const _Time time() const { return m_time; } - ATTR_HOT inline const _Element object() const { return m_object; } - - private: - _Time m_time; - _Element m_object; - }; - - netlist_timed_queue() - { - //m_list = global_alloc_array(entry_t, SIZE); - clear(); - } - - ATTR_HOT inline int capacity() const { return _Size; } - ATTR_HOT inline bool is_empty() const { return (m_end == &m_list[0]); } - ATTR_HOT inline bool is_not_empty() const { return (m_end > &m_list[0]); } - - ATTR_HOT ATTR_ALIGN inline void push(const entry_t &e) - { + struct entry_t + { + public: + ATTR_HOT inline entry_t() + : m_time(), m_object() {} + ATTR_HOT inline entry_t(const _Time atime, const _Element elem) : m_time(atime), m_object(elem) {} + ATTR_HOT inline const _Time time() const { return m_time; } + ATTR_HOT inline const _Element object() const { return m_object; } + + private: + _Time m_time; + _Element m_object; + }; + + netlist_timed_queue() + { + //m_list = global_alloc_array(entry_t, SIZE); + clear(); + } + + ATTR_HOT inline int capacity() const { return _Size; } + ATTR_HOT inline bool is_empty() const { return (m_end == &m_list[0]); } + ATTR_HOT inline bool is_not_empty() const { return (m_end > &m_list[0]); } + + ATTR_HOT ATTR_ALIGN inline void push(const entry_t &e) + { entry_t * RESTRICT i = m_end++; while ((i > &m_list[0]) && (e.time() > (i - 1)->time()) ) { @@ -194,43 +196,43 @@ public: } *i = e; inc_stat(m_prof_sort); - assert(m_end - m_list < _Size); - } + assert(m_end - m_list < _Size); + } - ATTR_HOT inline const entry_t &pop() - { - return *--m_end; - } + ATTR_HOT inline const entry_t &pop() + { + return *--m_end; + } - ATTR_HOT inline const entry_t &peek() const - { - return *(m_end-1); - } + ATTR_HOT inline const entry_t &peek() const + { + return *(m_end-1); + } - ATTR_COLD void clear() - { - m_end = &m_list[0]; - } + ATTR_COLD void clear() + { + m_end = &m_list[0]; + } - // save state support & mame disasm + // save state support & mame disasm - ATTR_COLD inline const entry_t *listptr() const { return &m_list[0]; } - ATTR_HOT inline int count() const { return m_end - m_list; } - ATTR_HOT inline const entry_t & operator[](const int & index) const { return m_list[index]; } + ATTR_COLD inline const entry_t *listptr() const { return &m_list[0]; } + ATTR_HOT inline int count() const { return m_end - m_list; } + ATTR_HOT inline const entry_t & operator[](const int & index) const { return m_list[index]; } #if (NL_KEEP_STATISTICS) - // profiling - INT32 m_prof_start; - INT32 m_prof_end; - INT32 m_prof_sortmove; - INT32 m_prof_sort; + // profiling + INT32 m_prof_start; + INT32 m_prof_end; + INT32 m_prof_sortmove; + INT32 m_prof_sort; #endif private: - entry_t * RESTRICT m_end; - //entry_t *m_list; - entry_t m_list[_Size]; + entry_t * RESTRICT m_end; + //entry_t *m_list; + entry_t m_list[_Size]; }; diff --git a/src/emu/netlist/nl_setup.c b/src/emu/netlist/nl_setup.c index 23d705b6551..35cccd3ad82 100644 --- a/src/emu/netlist/nl_setup.c +++ b/src/emu/netlist/nl_setup.c @@ -16,7 +16,7 @@ static NETLIST_START(base) TTL_INPUT(ttlhigh, 1) TTL_INPUT(ttllow, 0) - NETDEV_GND() + GND() NET_MODEL(".model 1N914 D(Is=2.52n Rs=.568 N=1.752 Cjo=4p M=.4 tt=20n Iave=200m Vpk=75 mfg=OnSemi type=silicon)") NET_MODEL(".model 1N4148 D(Is=2.52n Rs=.568 N=1.752 Cjo=4p M=.4 tt=20n Iave=200m Vpk=75 mfg=OnSemi type=silicon)") diff --git a/src/emu/netlist/nl_setup.h b/src/emu/netlist/nl_setup.h index 5de2022b95f..370f51740a5 100644 --- a/src/emu/netlist/nl_setup.h +++ b/src/emu/netlist/nl_setup.h @@ -19,49 +19,49 @@ #define NET_STR(_x) # _x #define NET_MODEL(_model) \ - netlist.register_model(_model); + setup.register_model(_model); #define ALIAS(_alias, _name) \ - netlist.register_alias(# _alias, # _name); + setup.register_alias(# _alias, # _name); -#define NET_NEW(_type) netlist.factory().new_device_by_classname(NETLIB_NAME_STR(_type), netlist) +#define NET_NEW(_type) setup.factory().new_device_by_classname(NETLIB_NAME_STR(_type), setup) #define NET_REGISTER_DEV(_type, _name) \ - netlist.register_dev(NET_NEW(_type), # _name); + setup.register_dev(NET_NEW(_type), # _name); #define NET_REMOVE_DEV(_name) \ - netlist.remove_dev(# _name); + setup.remove_dev(# _name); #define NET_REGISTER_SIGNAL(_type, _name) \ NET_REGISTER_DEV(_type ## _ ## sig, _name) #define NET_CONNECT(_name, _input, _output) \ - netlist.register_link(# _name "." # _input, # _output); + setup.register_link(# _name "." # _input, # _output); #define NET_C(_input, _output) \ - netlist.register_link(NET_STR(_input) , NET_STR(_output)); + setup.register_link(NET_STR(_input) , NET_STR(_output)); #define PARAM(_name, _val) \ - netlist.register_param(# _name, _val); + setup.register_param(# _name, _val); #define NETDEV_PARAMI(_name, _param, _val) \ - netlist.register_param(# _name "." # _param, _val); + setup.register_param(# _name "." # _param, _val); #define NETLIST_NAME(_name) netlist ## _ ## _name #define NETLIST_START(_name) \ -ATTR_COLD void NETLIST_NAME(_name)(netlist_setup_t &netlist) \ +ATTR_COLD void NETLIST_NAME(_name)(netlist_setup_t &setup) \ { #define NETLIST_END() } #define INCLUDE(_name) \ - NETLIST_NAME(_name)(netlist); + NETLIST_NAME(_name)(setup); #define SUBMODEL(_name, _model) \ - netlist.namespace_push(# _name); \ - NETLIST_NAME(_model)(netlist); \ - netlist.namespace_pop(); + setup.namespace_push(# _name); \ + NETLIST_NAME(_model)(setup); \ + setup.namespace_pop(); // ---------------------------------------------------------------------------------------- // FIXME: Clean this up diff --git a/src/emu/render.c b/src/emu/render.c index 57b31a12a70..bff2c367295 100644 --- a/src/emu/render.c +++ b/src/emu/render.c @@ -401,7 +401,7 @@ void render_texture::release() void render_texture::set_bitmap(bitmap_t &bitmap, const rectangle &sbounds, texture_format format) { - assert(bitmap.cliprect().contains(sbounds)); + //assert(bitmap.cliprect().contains(sbounds)); // ensure we have a valid palette for palettized modes if (format == TEXFORMAT_PALETTE16 || format == TEXFORMAT_PALETTEA16) @@ -1338,7 +1338,10 @@ render_primitive_list &render_target::get_primitives() // if there is no associated element, it must be a screen element if (curitem->screen() != NULL) + { add_container_primitives(list, item_xform, curitem->screen()->container(), blendmode); + curitem->screen()->set_render_size((int) item_xform.xscale, (int) item_xform.yscale); + } else add_element_primitives(list, item_xform, *curitem->element(), curitem->state(), blendmode); } @@ -1701,7 +1704,6 @@ void render_target::add_container_primitives(render_primitive_list &list, const prim->bounds.x1 = render_round_nearest(container_xform.xoffs + bounds.x1 * container_xform.xscale); prim->bounds.y1 = render_round_nearest(container_xform.yoffs + bounds.y1 * container_xform.yscale); } - // compute the color of the primitive prim->color.r = container_xform.color.r * curitem->color().r; prim->color.g = container_xform.color.g * curitem->color().g; diff --git a/src/emu/screen.c b/src/emu/screen.c index 4acde133dab..b3327eb20ad 100644 --- a/src/emu/screen.c +++ b/src/emu/screen.c @@ -22,6 +22,7 @@ #define VERBOSE (0) #define LOG_PARTIAL_UPDATES(x) do { if (VERBOSE) logerror x; } while (0) +//#define USE_MONITOR (1) //************************************************************************** @@ -77,6 +78,10 @@ screen_device::screen_device(const machine_config &mconfig, const char *tag, dev m_unique_id = m_id_counter; m_id_counter++; memset(m_texture, 0, sizeof(m_texture)); + + m_render_width = m_width; + m_render_height = m_height; + } @@ -446,6 +451,13 @@ void screen_device::configure(int width, int height, const rectangle &visarea, a machine().video().update_refresh_speed(); } +const rectangle &screen_device::visible_area() const +{ + if (0 && m_crt.type() != crt_monitor::PASSTHROUGHX) + return m_crt.get_visible(); + else + return m_visarea; +} //------------------------------------------------- // reset_origin - reset the timing such that the @@ -494,9 +506,20 @@ void screen_device::realloc_screen_bitmaps() for (auto_bitmap_item *item = m_auto_bitmap_list.first(); item != NULL; item = item->next()) item->m_bitmap.resize(effwidth, effheight); - // re-set up textures + // set up textures + + if (m_crt.type() != crt_monitor::PASSTHROUGHX) + { + m_crt.resize(m_width, m_height); + rectangle crt_vis = m_crt.get_visible(); + m_texture[0]->set_bitmap(m_crt.final_bitmap(0), crt_vis, TEXFORMAT_RGB32); + m_texture[1]->set_bitmap(m_crt.final_bitmap(1), crt_vis, TEXFORMAT_RGB32); + } + else + { m_texture[0]->set_bitmap(m_bitmap[0], m_visarea, m_bitmap[0].texformat()); m_texture[1]->set_bitmap(m_bitmap[1], m_visarea, m_bitmap[1].texformat()); + } } @@ -823,10 +846,25 @@ bool screen_device::update_quads() // only update if empty and not a vector game; otherwise assume the driver did it directly if (m_type != SCREEN_TYPE_VECTOR && (machine().config().m_video_attributes & VIDEO_SELF_RENDER) == 0) { + if (m_crt.type() != crt_monitor::PASSTHROUGHX) + { + m_crt.resize(m_render_width, m_render_height); + m_crt.process(machine(), m_bitmap[m_curbitmap], m_curbitmap, m_visarea); + } + // if we're not skipping the frame and if the screen actually changed, then update the texture if (!machine().video().skip_this_frame() && m_changed) { - m_texture[m_curbitmap]->set_bitmap(m_bitmap[m_curbitmap], m_visarea, m_bitmap[m_curbitmap].texformat()); + if (m_crt.type() != crt_monitor::PASSTHROUGHX) + { + rectangle fixedvis = m_crt.get_visible(); + m_texture[m_curbitmap]->set_bitmap(m_crt.final_bitmap(m_curbitmap), fixedvis, TEXFORMAT_RGB32); + } + else + { + m_texture[m_curbitmap]->set_bitmap(m_bitmap[m_curbitmap], m_visarea, m_bitmap[m_curbitmap].texformat()); + } + m_curtexture = m_curbitmap; m_curbitmap = 1 - m_curbitmap; } @@ -1010,3 +1048,946 @@ void screen_device::load_effect_overlay(const char *filename) else mame_printf_warning("Unable to load effect PNG file '%s'\n", fullname.cstr()); } + +void screen_device::set_render_size(int width, int height) +{ + if (width<=4096 && height <=4096) + { + m_render_width = width; + m_render_height = height; + } +} + +//------------------------------------------------- +// The 3x3 matrix class +//------------------------------------------------- + +class vec3d +{ + friend class mat33d; +public: + vec3d() + { + } + vec3d(double a0, double a1, double a2) + { + a[0] = a0; + a[1] = a1; + a[2] = a2; + } + void set(double a0, double a1, double a2) + { + a[0] = a0; + a[1] = a1; + a[2] = a2; + } + double elem(int row) + { + return a[row]; + } + + void dump(void) + { + //printf("%10.4f %10.4f %10.4f\n", a[0], a[1], a[2]); + } +protected: + double a[3]; +}; + +class mat33d +{ +public: + + void setConst(double val) + { + for (int i=0;i<3;i++) + for (int j=0;j<3; j++) + a[i][j] = val; + } + + void multScalar(double val) + { + for (int i=0;i<3;i++) + for (int j=0;j<3; j++) + a[i][j] = a[i][j]*val; + } + + void copyFrom(mat33d &src) + { + for (int i=0;i<3;i++) + for (int j=0;j<3; j++) + a[i][j] = src.a[i][j]; + } + + double det(void) + { + // a11(a33a22-a32a23)-a21(a33a12-a32a13)+a31(a23a12-a22a13) + return a[0][0] * (a[2][2]*a[1][1] - a[2][1]*a[1][2]) + - a[1][0] * (a[2][2]*a[0][1] - a[2][1]*a[0][2]) + + a[2][0] * (a[1][2]*a[0][1] - a[1][1]*a[0][2]); + } + + void invert(void) + { + mat33d ret; + double temdet = det(); + + //| a11 a12 a13 |-1 | a33a22-a32a23 -(a33a12-a32a13) a23a12-a22a13 | + //| a21 a22 a23 | = 1/DET * | -(a33a21-a31a23) a33a11-a31a13 -(a23a11-a21a13) | + //| a31 a32 a33 | | a32a21-a31a22 -(a32a11-a31a12) a22a11-a21a12 | + + + ret.a[0][0] = a[2][2]*a[1][1]-a[2][1]*a[1][2]; + ret.a[0][1] = -(a[2][2]*a[0][1]-a[2][1]*a[0][2]); + ret.a[0][2] = a[1][2]*a[0][1]-a[1][1]*a[0][2]; + ret.a[1][0] = -(a[2][2]*a[1][0]-a[2][0]*a[1][2]); + ret.a[1][1] = a[2][2]*a[0][0]-a[2][0]*a[0][2]; + ret.a[1][2] = -(a[1][2]*a[0][0]-a[1][0]*a[0][2]); + ret.a[2][0] = a[2][1]*a[1][0]-a[2][0]*a[1][1]; + ret.a[2][1] = -(a[2][1]*a[0][0]-a[2][0]*a[0][1]); + ret.a[2][2] = a[1][1]*a[0][0]-a[1][0]*a[0][1]; + copyFrom(ret); + multScalar(1.0f / temdet); + } + + void multVec(vec3d &r, vec3d &v) + { + for (int row = 0; row < 3; row++) + { + r.a[row] = a[row][0] * v.a[0] + a[row][1] * v.a[1] + a[row][2] * v.a[2]; + } + } + + void setRow(int row, double c0, double c1, double c2) + { + a[row][0] = c0; + a[row][1] = c1; + a[row][2] = c2; + } + + void setCol(int col, double r0, double r1, double r2) + { + a[0][col] = r0; + a[1][col] = r1; + a[2][col] = r2; + } + + double elem(int row, int col) + { + return a[row][col]; + } + + mat33d() + { + setConst(0.0f); + } + +protected: + double a[3][3]; +}; + +//------------------------------------------------- +// The monitor class +//------------------------------------------------- + +typedef struct +{ + const char *desc; + double xr, yr, xg, yg, xb, yb, xw, yw, gamma; +} CIE_Chroma_t; + +/* + * White points below use CIE 1964 + */ + +static const CIE_Chroma_t CIE_Mons[] = +{ + { "Guru", 0.57585, 0.34435, 0.28773, 0.55582, 0.18631,0.10346, 0.3138, 0.3310, 2.2 }, // D65 + //{ "Short-Persistence", 0.61, 0.35, 0.29, 0.59, 0.15, 0.063 }, // N/A N/A [Foley96, p. 583] + //{ "Long-Persistence", 0.62, 0.33, 0.21, 0.685, 0.15, 0.063 }, // N/A N/A [Foley96, p. 583] + //CCIR 601-1 is the old NTSC standard. Now called Rec 601-1. + { "NTSC", 0.67, 0.33, 0.21, 0.71, 0.14, 0.08, 0.3104, 0.319, 2.2 }, // 1ILLUMINANT_C [Walker98] + { "EBU", 0.64, 0.33, 0.30, 0.60, 0.15, 0.06, 0.3138, 0.3310, 2.4 }, // D65 [Walker98] + // (all monitors except 21, " Mitsubishi p/n 65532) + { "Dell", 0.625, 0.340, 0.275, 0.605, 0.150, 0.065, 0.280, 0.315, 2.2 }, // 9300K [Dell, E-mail, 12 Jan 99] + { "SMPTE", 0.630, 0.340, 0.310, 0.595, 0.155, 0.070, 0.3138, 0.3310, 2.2 }, // D65 [Walker98] + { "P22 NEC C400", 0.610, 0.350, 0.307, 0.595, 0.150, 0.065, 0.280, 0.315, 2.2 }, // [NEC98], 9300 K Gamma = 2.2 + { "P22 KDS VS19", 0.625, 0.340, 0.285, 0.605, 0.150, 0.065, 0.281, 0.311, 2.2 }, // + { "High Brightness LED",0.700, 0.300, 0.170, 0.700, 0.130, 0.075, 0.310, 0.320, 2.2 }, // Nichia Corporation + { "sRGB", 0.64, 0.33, 0.30, 0.60, 0.15, 0.06, 0.3138, 0.3310, 2.4 }, // D65 + { "Couriersud", 0.633, 0.336, 0.279, 0.598, 0.149, 0.073, 0.327, 0.355, 2.4 }, + + { NULL } +}; + +/* + * Calculate the RGB to CIE matrix ... + */ + +static void calc_mat(CIE_Chroma_t cie, mat33d &m) +{ + mat33d ms; + vec3d vwhite; + vec3d s; + + ms.setCol(0, cie.xr / cie.yr, 1.0, (1.0f - cie.xr - cie.yr) / cie.yr); + ms.setCol(1, cie.xg / cie.yg, 1.0, (1.0f - cie.xg - cie.yg) / cie.yg); + ms.setCol(2, cie.xb / cie.yb, 1.0, (1.0f - cie.xb - cie.yb) / cie.yb); + + ms.invert(); + + vwhite.set(cie.xw / cie.yw, 1.0, (1.0f - cie.xw - cie.yw) / cie.yw); + ms.multVec(s, vwhite); + + m.setCol(0, s.elem(0) * cie.xr / cie.yr, s.elem(0) * 1.0, s.elem(0) * (1.0f - cie.xr - cie.yr) / cie.yr); + m.setCol(1, s.elem(1) * cie.xg / cie.yg, s.elem(1) * 1.0, s.elem(1) * (1.0f - cie.xg - cie.yg) / cie.yg); + m.setCol(2, s.elem(2) * cie.xb / cie.yb, s.elem(2) * 1.0, s.elem(2) * (1.0f - cie.xb - cie.yb) / cie.yb); +} + +static double src_gamma(double v, double g) +{ + return pow(v, g ); +} + +static double srgb_gamma(double v) +{ + return v; + if ( v > 0.0031308 ) + return 1.055 * ( pow(v, 1.0f / 2.4f ) ) - 0.055; + else + return 12.92 * v; +} + +static rgb_t vec_to_rgb_t(vec3d v) +{ + return rgb_t( + rgb_t::clamp((INT32) (srgb_gamma(v.elem(0)) * 255.0f)), + rgb_t::clamp((INT32) (srgb_gamma(v.elem(1)) * 255.0f)), + rgb_t::clamp((INT32) (srgb_gamma(v.elem(2)) * 255.0f)) + ); +} + +static void CIE_xy_to_rgbA(CIE_Chroma_t cie, rgb_t *base_r, rgb_t *base_g, rgb_t *base_b) +{ + mat33d rgb_to_cie; + mat33d cie_to_rgb; + vec3d tt, tn; + + tt.set(1,1,1); + + calc_mat(cie, rgb_to_cie); + rgb_to_cie.multVec(tn, tt); + tn.dump(); + + cie_to_rgb.setRow(0, 3.2406, -1.5372, -0.4986); + cie_to_rgb.setRow(1, -0.9689, 1.8758, 0.0415); + cie_to_rgb.setRow(2, 0.0557, -0.2040, 1.0570); + + for (int i = 0; i < 768; i++) + { + vec3d v_r, v_g, v_b, v_cie, v_rgb; + double val = src_gamma((double) i / 256.0f, cie.gamma); + + /* desaturate colors for more brightness for val > 1.0 + * at the expense of accuracy + */ + + double val2 = (val < 1.0) ? 0 : (val - 1.0) * 0.25; + v_r.set(val, val2, val2); + v_g.set(val2, val, val2); + v_b.set(val2, val2, val); + + rgb_to_cie.multVec(v_cie, v_r); + cie_to_rgb.multVec(v_rgb, v_cie); + base_r[i] = vec_to_rgb_t(v_rgb); + +#if 0 + if (i == 256) + { + printf("val %10.4f", val); + v_rgb.dump(); + } +#endif + + rgb_to_cie.multVec(v_cie, v_g); + cie_to_rgb.multVec(v_rgb, v_cie); + base_g[i] = vec_to_rgb_t(v_rgb); + +#if 0 + if (i == 256) + { + printf("val %10.4f", val); + v_rgb.dump(); + } +#endif + + rgb_to_cie.multVec(v_cie, v_b); + cie_to_rgb.multVec(v_rgb, v_cie); + base_b[i] = vec_to_rgb_t(v_rgb); + +#if 0 + if (i == 256) + { + printf("val %10.4f", val); + v_rgb.dump(); + } +#endif + + } +} + + +void crt_monitor::set_param(crt_monitor_param ¶m) { + m_param = param; + + CIE_xy_to_rgbA(CIE_Mons[m_param.source_cie], base_red, base_green, base_blue); + + for (int i=0; i<256; i++) + { + m_exp[i] = 255.0f * (1.0f - exp(-(double) i / 255.0f * (double) (m_param.bandwidth * m_param.bandwidth) / 4096.0f)); + //printf("%d %d\n", i, m_exp[i]); + } +} + + +crt_monitor::crt_monitor(void) + : m_amplifier_r(NULL), m_amplifier_g(NULL), m_amplifier_b(NULL) +{ + m_param.r_off = -256 * 3 / 10; + m_param.g_off = -256 * 3 / 10; + m_param.b_off = -256 * 3 / 10; + m_param.r_gain = 256 * 11 / 10; + m_param.g_gain = 256 * 11 / 10; + m_param.b_gain = 256 * 11 / 10; + m_param.bandwidth = 255 * 32 / 100; + m_param.focus = 255 * 21 / 100 ; + m_param.decay = 255 * 30 / 100; + m_param.source_cie = 0; + + //m_param.m_type = CROMA_CLEAR; + //m_param.m_type = SHADOW_MASK; + m_param.m_type = PASSTHROUGHX; + + set_param(m_param); + m_horz_pixel = 0; + m_vert_pixel = 0; + resize(288*11/8 * 3, 288*11/8 * 3 / 4 * 3); + +} + +crt_monitor::~crt_monitor(void) +{ + free_bitmaps(); +} + +void crt_monitor::free_bitmaps(void) +{ + if (m_amplifier_r != NULL) + global_free(m_amplifier_r); + if (m_amplifier_g != NULL) + global_free(m_amplifier_g); + if (m_amplifier_b != NULL) + global_free(m_amplifier_b); +#if 0 + // FIXME: should be done automatically ? + if (m_mask_bm != NULL) + bitmap_free(m_mask_bm); + if (m_phos_bm[0] != NULL) + bitmap_free(m_phos_bm[0]); + if (m_phos_bm[1] != NULL) + bitmap_free(m_phos_bm[1]); +#endif +} + +void crt_monitor::resize(int new_width, int new_height) +{ + int scal_width; + //int scal_height; + int adj = (m_param.m_type == SHADOW_MASK) ? 6 : 0; + + //printf("new %d %d\n", new_width, new_height); + + if (new_width > new_height) + { + scal_width = (new_width - adj) / 3; + //scal_height = (new_height - adj) / 3; + } + else + { + //scal_height = (new_width - adj) / 3; + scal_width = (new_height - adj) / 3; + int temp = new_height; + new_height = new_width; + new_width = temp; + } + + + if (scal_width == m_horz_pixel || scal_width <= 0) + return; + + int vis_height = 2048; // be safe(scal_height + 3); + int do_realloc = (scal_width > m_horz_pixel); + + m_horz_pixel = scal_width; + m_vert_pixel = m_horz_pixel * 3 / 4; + + + if (0 && m_param.m_type == SHADOW_MASK) + { + m_width = new_width; //m_horz_pixel * 3 + 6; + m_height = new_height;//m_vert_pixel * 3 + 6; + m_visible.min_x = 3; + m_visible.min_y = 3; + m_visible.max_x = m_width - 4; + m_visible.max_y = m_height - 4; + } + else + { + m_width = new_width; //m_horz_pixel * 3 + 6; + m_height = new_height;//m_vert_pixel * 3 + 6; + m_visible.min_x = 0; + m_visible.min_y = 0; + m_visible.max_x = m_width -1; + m_visible.max_y = m_height - 1; + } + + if (0 || do_realloc) + { + //free_bitmaps(); + + //printf("realloc %d %d\n", m_width, m_height); + m_amplifier_r = global_alloc_array(INT16, m_horz_pixel * vis_height); + m_amplifier_g = global_alloc_array(INT16, m_horz_pixel * vis_height); + m_amplifier_b = global_alloc_array(INT16, m_horz_pixel * vis_height); + + m_mask_bm.allocate(m_width, m_height); + m_phos_bm[0].allocate(m_width, m_height); + m_phos_bm[1].allocate(m_width, m_height); + +#if 0 + bitmap_fill(m_phos_bm[0], NULL, 0); + bitmap_fill(m_phos_bm[1], NULL, 0); +#endif + } +} + + +INLINE rgb_t bpixel(running_machine &machine, bitmap_t &bm, int y, int x) +{ + //return machine-> pens[*((UINT16 *) bm->base + y * bm->rowpixels + x)]; + + if (bm.format() == BITMAP_FORMAT_RGB32) + return bm.pixt<rgb_t>(y, x); + else + return palette_get_color(machine, bm.pixt<UINT16>(y, x)); + + //return *((UINT16 *) bm->base + y * bm->rowpixels + x); +} +#if 1 + +INLINE void set_chan(INT16 *pix, int val, int w) +{ +#if 1 + if (val-*pix>0) + *pix += ((val-*pix)*w)>>8; +#else + int nv = (val * w) >> 8; + if (nv > *pix) + *pix = nv; +#endif + +} + +void crt_monitor::scale_and_bandwith(running_machine &machine, bitmap_t &bm_src, const rectangle &cliprect) +{ + int y,w,x; + + for (y = cliprect.min_y - 1; y <= cliprect.max_y + 1; y++) + { + INT16 *dst_r = m_amplifier_r + (y - cliprect.min_y + 1) * m_horz_pixel; + INT16 *dst_g = m_amplifier_g + (y - cliprect.min_y + 1) * m_horz_pixel; + INT16 *dst_b = m_amplifier_b + (y - cliprect.min_y + 1) * m_horz_pixel; + for (x=0;x<m_horz_pixel;x++) + { + dst_r[x] = (dst_r[x] * m_param.decay)>>8; + dst_g[x] = (dst_g[x] * m_param.decay)>>8; + dst_b[x] = (dst_b[x] * m_param.decay)>>8; + } + } + + w = MAX((cliprect.max_x - cliprect.min_x/* + 1*/), m_horz_pixel); + int x_add_s = (cliprect.max_x - cliprect.min_x /*+ 1*/) * 16384 / w; + int x_add_d = 16384 * m_horz_pixel / w;; + + for (y = cliprect.min_y; y <= cliprect.max_y; y++) + { + int r = 0; + int g = 0; + int b = 0; + int rn = 0; + int bn = 0; + int gn = 0; + int lx_d = -1; + int time_r; + + INT16 *dst_r = m_amplifier_r + (y - cliprect.min_y + 1) * m_horz_pixel; + INT16 *dst_g = m_amplifier_g + (y - cliprect.min_y + 1) * m_horz_pixel; + INT16 *dst_b = m_amplifier_b + (y - cliprect.min_y + 1) * m_horz_pixel; + + int sx_s = cliprect.min_x * 16384; + int sx_d = 0; + time_r = 0; + for (x=0; x<w; x++) + { + rgb_t src = bpixel(machine, bm_src, y, (sx_s >> 14)); + int x_d = (sx_d >> 14); + int frac = (sx_s & 16383) >> 6; + + int bandwidth1; + int bandwidth0; + if (frac>time_r) + bandwidth1 = m_exp[(frac-time_r)]; + else + { + bandwidth1 = m_exp[(255 - time_r)]; + bandwidth0 = 255- bandwidth1; + r = (r * bandwidth0 + rn * bandwidth1) >> 8; + g = (g * bandwidth0 + gn * bandwidth1) >> 8; + b = (b * bandwidth0 + bn * bandwidth1) >> 8; + bandwidth1 = m_exp[(frac)]; + } + time_r = frac; + rn = ((MAX((int)src.r() - m_param.r_off, 0) * m_param.r_gain) >> 8); + gn = ((MAX((int)src.g() - m_param.g_off, 0) * m_param.g_gain) >> 8); + bn = ((MAX((int)src.b() - m_param.b_off, 0) * m_param.b_gain ) >> 8); + bandwidth0 = 255- bandwidth1; + + r = (r * bandwidth0 + rn * bandwidth1) >> 8; + g = (g * bandwidth0 + gn * bandwidth1) >> 8; + b = (b * bandwidth0 + bn * bandwidth1) >> 8; + + if (x_d>lx_d) + { + set_chan(&dst_r[x_d], r, 255); + set_chan(&dst_g[x_d], g, 255); + set_chan(&dst_b[x_d], b, 255); + + set_chan(&dst_r[x_d-m_horz_pixel], r, m_param.focus); + set_chan(&dst_g[x_d-m_horz_pixel], g, m_param.focus); + set_chan(&dst_b[x_d-m_horz_pixel], b, m_param.focus); + + set_chan(&dst_r[x_d+m_horz_pixel], r, m_param.focus); + set_chan(&dst_g[x_d+m_horz_pixel], g, m_param.focus); + set_chan(&dst_b[x_d+m_horz_pixel], b, m_param.focus); + lx_d = x_d; + } + + sx_s += x_add_s; + sx_d += x_add_d; + } + } +} +#else +void crt_monitor::scale_and_bandwith(running_machine *machine, bitmap_t *bm_src, const rectangle *cliprect) +{ + int x; + int y; + int bandwidth0 = m_param.bandwidth; + int bandwidth1 = 256 - bandwidth0; + UINT16 tr[4*1024]; + UINT16 tg[4*1024]; + UINT16 tb[4*1024]; + + int x_add = (cliprect.max_x - cliprect.min_x + 1) * 1024 * 4/ (m_horz_pixel); + + for (y = cliprect.min_y; y <= cliprect.max_y; y++) + { + int r = 0; + int g = 0; + int b = 0; + + /* bandwidth first ! */ + for (x=cliprect.min_x*4; x<=cliprect.max_x*4; x++) + { + rgb_t src = bpixel(machine, bm_src, y, x/4); + + r = (r * bandwidth0 + ((MAX((int)RGB_RED(src) - m_param.r_off, 0) * m_param.r_gain) >> 8) * bandwidth1) >> 8; + g = (g * bandwidth0 + ((MAX((int)RGB_GREEN(src) - m_param.g_off, 0) * m_param.g_gain) >> 8) * bandwidth1) >> 8; + b = (b * bandwidth0 + ((MAX((int)RGB_BLUE(src) - m_param.b_off, 0) * m_param.b_gain ) >> 8) * bandwidth1) >> 8; + + tr[x] = r; + tg[x] = g; + tb[x] = b; + } + + int sx = cliprect.min_x * 1024 * 4; + + INT16 *dst_r = m_amplifier_r + (y - cliprect.min_y) * m_horz_pixel; + INT16 *dst_g = m_amplifier_g + (y - cliprect.min_y) * m_horz_pixel; + INT16 *dst_b = m_amplifier_b + (y - cliprect.min_y) * m_horz_pixel; + + /* doing a linear interpolation is an approximation, + * however should suffice here. + */ + for (x = 0; x < m_horz_pixel; x++) + { + UINT16 frac = (sx & 0x3ff)>>2; + UINT16 xw = sx >> 10; + + frac = 0; + + *dst_r++ = (tr[xw] * (256-frac) + tr[xw+1] * frac)>>8; + *dst_g++ = (tg[xw] * (256-frac) + tg[xw+1] * frac)>>8; + *dst_b++ = (tb[xw] * (256-frac) + tb[xw+1] * frac)>>8; + + sx += x_add; + } + } +} +#endif + +void crt_monitor::copyonly(bitmap_rgb32 &bm_dst, rectangle &clip) +{ + int x; + int y; + + int sy = 0; + int s_add = (clip.max_y - clip.min_y + 1) * 256 / (m_visible.max_y - m_visible.min_y + 1) ; + + for (y = m_visible.min_y; y <= m_visible.max_y; y++) + { + rgb_t *dst = (rgb_t *) bm_dst.raw_pixptr(y, 0); + for (x = m_visible.min_x; x <= m_visible.max_x; x++) + { + int offset = (sy >> 8) * m_horz_pixel + ((x-m_visible.min_x) / 3); + UINT8 r = MIN(255, m_amplifier_r[offset]); + UINT8 g = MIN(255, m_amplifier_g[offset]); + UINT8 b = MIN(255, m_amplifier_b[offset]); + dst[0] = rgb_t(r, g, b); + dst++; + } + sy += s_add; + } +} + +INLINE void set_pixel(rgb_t *pix, int r, int g, int b) +{ + int rn = r; + int gn = g; + int bn = b; + + *pix = rgb_t( + (rgb_t::clamp((int)pix->r() + rn)), + (rgb_t::clamp((int)pix->g() + gn)), + (rgb_t::clamp((int)pix->b() + bn)) + ); +} + +INLINE void set_pixela(rgb_t *pix, rgb_t val, int w) +{ + UINT8 rn = val.r(); + UINT8 gn = val.g(); + UINT8 bn = val.b(); + + UINT8 ro = pix->r(); + UINT8 go = pix->g(); + UINT8 bo = pix->b(); + + if (rn-ro>0) + ro += ((rn-ro)*w)>>8; + if (gn-go>0) + go += ((gn-go)*w)>>8; + if (bn-bo>0) + bo += ((bn-bo)*w)>>8; + + *pix = rgb_t(ro, go, bo); +} + +void crt_monitor::copy_shadow_mask(bitmap_rgb32 &bm_dst, const rectangle &clip) +{ + int gainv[3] = { 100, 100, 100}; + int sy = 0; + int s_add = (clip.max_y - clip.min_y + 1) * 16384 / (m_visible.max_y - m_visible.min_y + 1) ; + + int x; + int y; + + gainv[1] = 255; + gainv[0] = m_param.focus; + gainv[2] = m_param.focus; + + for (y = m_visible.min_y+3; y <= m_visible.max_y-4; y++) + { + rgb_t *dst0 = (rgb_t *) bm_dst.raw_pixptr(y, m_visible.min_x); + rgb_t *dst1 = (rgb_t *) bm_dst.raw_pixptr(y + 1, m_visible.min_x); + int gaina = gainv[y % 3]; + + for (x = m_visible.min_x+3; x <= m_visible.max_x-4; x+=3) + { + int offset = ((sy + 8191) >> 14) * m_horz_pixel + (((y & 1) == 0) ? (x-m_visible.min_x) / 3 : (2*(x-m_visible.min_x)-3) / 6) ; + + int rn = (m_amplifier_r[offset] * gaina)>>8; + int gn = (m_amplifier_g[offset] * gaina)>>8; + int bn = (m_amplifier_b[offset] * gaina)>>8; +#if 0 + int r_ov = MAX(rn - 255, 0); + int g_ov = MAX(gn - 255, 0); + int b_ov = MAX(bn - 255, 0); + + if ((y & 1) == 0) + { + set_pixel(dst0 - 1, r_ov, 0, 0); + set_pixel(dst0 + 0, rn, g_ov, b_ov); + set_pixel(dst0 + 1, r_ov, gn, b_ov); + set_pixel(dst0 + 2, 0, g_ov, 0); + set_pixel(dst1 + 0, 0, 0, b_ov); + set_pixel(dst1 + 1, r_ov, g_ov, bn); + set_pixel(dst1 + 2, 0, 0, b_ov); + } + else + { + set_pixel(dst0 - 2, r_ov, 0, 0); + set_pixel(dst0 - 1, rn, g_ov, b_ov); + set_pixel(dst0 + 0, r_ov, gn, b_ov); + set_pixel(dst0 + 1, 0, g_ov, 0); + set_pixel(dst1 - 2, 0, 0, b_ov); + set_pixel(dst1 - 1, r_ov, g_ov, bn); + set_pixel(dst1 - 0, 0, 0, b_ov); + } +#else + if ((y & 1) == 0) + { + *(dst0 + 0) = base_red[rn]; + *(dst0 + 1) = base_green[gn]; + *(dst1 + 1) = base_blue[bn]; + } + else + { + *(dst0 - 1) = base_red[rn]; + *(dst0 + 0) = base_green[gn]; + *(dst1 - 1) = base_blue[bn]; + } +#endif + dst1 += 3; + dst0 += 3; + } + sy += s_add; + } +} + +void crt_monitor::copy_chroma(bitmap_rgb32 &bm_dst, const rectangle &clip) +{ +#if 1 + int gainv[4][2] = { + { 256 / 4, 256 }, + { 256, 256 }, + { 256, 256 / 4 }, + { 256, 256 } + }; +#else + int gainv[4][2] = { + { m_param.focus, 256 }, + { m_param.focus, m_param.focus }, + { 256, m_param.focus }, + { m_param.focus, m_param.focus } + }; +#endif + int sy = 0; + int s_add = (clip.max_y - clip.min_y + 1) * 16384 / (m_visible.max_y - m_visible.min_y + 1) ; + + int x; + int y; + + //gainv[0][0] = m_param.focus; + //gainv[1][0] = m_param.focus; + + for (y = m_visible.min_y; y <= m_visible.max_y; y++) + { + rgb_t *dst0 = (rgb_t *) bm_dst.raw_pixptr(y, m_visible.min_x); + rgb_t *dstm1 = dst0 - 3 * bm_dst.rowpixels(); + rgb_t *dstp1 = dst0 + 3 * bm_dst.rowpixels(); + + for (x = m_visible.min_x; x <= m_visible.max_x; x+=3) + { + int offset = (((sy + 8191) >> 14)+1) * m_horz_pixel + (x-m_visible.min_x) / 3; + int gaina = gainv[y & 3][((x-m_visible.min_x)/3) & 1]; + + int rn = (m_amplifier_r[offset] * gaina)>>8; + int gn = (m_amplifier_g[offset] * gaina)>>8; + int bn = (m_amplifier_b[offset] * gaina)>>8; + + +#if 0 + int blank=0; + + if ((((x / 3) & 1) == 0) && ((y % 4) == 0)) + blank = 1; + else if ((((x / 3) & 1) == 1) && ((y % 4) == 2)) + blank = 1; + + if (!blank) + { +#endif +#if 0 + int r_ov = MAX(rn - 255, 0); + int g_ov = MAX(gn - 255, 0); + int b_ov = MAX(bn - 255, 0); + + set_pixel(dst0 - 1, r_ov, 0, 0); + set_pixel(dst0 + 0, rn, g_ov, 0); + set_pixel(dst0 + 1, 0, gn, b_ov); + set_pixel(dst0 + 2, 0, 0, bn); +#elif 0 + int r_ov = MAX(rn - 255, 0); + int g_ov = MAX(gn - 255, 0); + int b_ov = MAX(bn - 255, 0); + + set_pixel(dst0 + 0, rn, r_ov, r_ov); + set_pixel(dst0 + 1, g_ov, gn, g_ov); + set_pixel(dst0 + 2, b_ov, b_ov, bn); +#elif 0 + int frac1 = (sy & 16383)>>6; + int frac = (255-frac1); + int rn1 = (m_amplifier_r[offset+m_horz_pixel] * gaina)>>8; + int gn1 = (m_amplifier_g[offset+m_horz_pixel] * gaina)>>8; + int bn1 = (m_amplifier_b[offset+m_horz_pixel] * gaina)>>8; + + *(dst0+0) = base_red[(rn*frac+rn1*frac1)>>8]; + *(dst0+1) = base_green[(gn*frac+gn1*frac1)>>8]; + *(dst0+2) = base_blue[(bn*frac+bn1*frac1)>>8]; +#elif 1 + *(dst0+0) = base_red[rn]; + *(dst0+1) = base_green[gn]; + *(dst0+2) = base_blue[bn]; +#elif 1 + set_pixela(dst0 , base_red[rn],192); + set_pixela(dst0+1, base_green[gn],192); + set_pixela(dst0+2, base_blue[bn],192); + if (m_param.focus > 0) + { + set_pixela(dstm1 , base_red[rn],m_param.focus); + set_pixela(dstm1+1, base_green[gn],m_param.focus); + set_pixela(dstm1+2, base_blue[bn],m_param.focus); + set_pixela(dstp1 , base_red[rn],m_param.focus); + set_pixela(dstp1+1, base_green[gn],m_param.focus); + set_pixela(dstp1+2, base_blue[bn],m_param.focus); +#if 0 + set_pixela(dst0-3, base_red[rn],m_param.focus); + set_pixela(dst0-2, base_green[gn],m_param.focus); + set_pixela(dst0-1, base_blue[bn],m_param.focus); + set_pixela(dst0+3, base_red[rn],m_param.focus); + set_pixela(dst0+4, base_green[gn],m_param.focus); + set_pixela(dst0+5, base_blue[bn],m_param.focus); +#endif + } + +#else + /* looks horrible */ + int r = RGB_RED(base_red[rn]) + RGB_RED(base_green[gn]) + RGB_RED(base_blue[bn]); + int g = RGB_GREEN(base_red[rn]) + RGB_GREEN(base_green[gn]) + RGB_GREEN(base_blue[bn]); + int b = RGB_BLUE(base_red[rn]) + RGB_BLUE(base_green[gn]) + RGB_BLUE(base_blue[bn]); + + rgb_t c = MAKE_RGB(rgb_clamp(r), rgb_clamp(g), rgb_clamp(b)); + *(dst0+0) = c; + *(dst0+1) = c; + *(dst0+2) = c; +#endif +// } + dst0 += 3; + dstm1 += 3; + dstp1 += 3; + } + sy += s_add; + } +} + +void crt_monitor::phosphor(bitmap_rgb32 &bm_dst, bitmap_rgb32 &bm_phos, bitmap_rgb32 &bm_src, const rectangle &cliprect) +{ + const int phos_decay = m_param.decay; + + const int phos_red_decay = phos_decay; + const int phos_green_decay = phos_decay; + const int phos_blue_decay = phos_decay; + + //int phos_red_decay1 = 256 - phos_red_decay; + //int phos_green_decay1 = 256 - phos_green_decay; + //int phos_blue_decay1 = 256 - phos_blue_decay; + + int x; + int y; + + for (y = cliprect.min_y; y <= cliprect.max_y; y++) + { + rgb_t *src = (rgb_t *) bm_src.raw_pixptr(y, cliprect.min_x); + rgb_t *sp = (rgb_t *) bm_phos.raw_pixptr(y, cliprect.min_x); + rgb_t *dst = (rgb_t *) bm_dst.raw_pixptr(y, cliprect.min_x); + + for (x = cliprect.min_x; x <= cliprect.max_x; x++) + { +#if 0 + int r = ((int)RGB_RED(*src) * phos_red_decay1 + (int)RGB_RED(*sp) * phos_red_decay) >> 8; + int g = ((int)RGB_GREEN(*src) * phos_green_decay1 + (int)RGB_GREEN(*sp) * phos_green_decay) >> 8;; + int b = ((int)RGB_BLUE(*src) * phos_blue_decay1 + (int)RGB_BLUE(*sp) * phos_blue_decay) >> 8; +#else + int r = ((int)sp->r() * phos_red_decay) >> 8; + int g = ((int)sp->g() * phos_green_decay) >> 8;; + int b = ((int)sp->b() * phos_blue_decay) >> 8; + int r1 = src->r(); + int g1 = src->g(); + int b1 = src->b(); + if (r1 > r) r = r1; + if (g1 > g) g = g1; + if (b1 > b) b = b1; +#endif + *dst = rgb_t(r, g, b); + + src++; sp++; dst++; + } + } +} + +void crt_monitor::process(running_machine &machine, screen_bitmap &src_bm, int cur_bm, rectangle &clip) +{ + bitmap_rgb32 *temp = (0 && m_param.decay > 0) ? &m_mask_bm : &m_phos_bm[cur_bm]; + + switch (m_param.m_type) + { + case PASSTHROUGHX: + break; + case SHADOW_MASK: + scale_and_bandwith(machine, src_bm, clip); + temp->fill(0); + copy_shadow_mask(*temp, clip ); + break; + case CROMA_CLEAR: + scale_and_bandwith(machine, src_bm, clip); + temp->fill(0); + copy_chroma(*temp, clip ); + break; + //case APERTURE_GRILLE: + //break; + } + if (m_param.m_type != PASSTHROUGHX) + { + if (0 && m_param.decay > 0) + phosphor(m_phos_bm[cur_bm],m_phos_bm[1-cur_bm], m_mask_bm, m_visible); + } +} + +int crt_monitor::get_cie_count(void) +{ + int num = 0; + const CIE_Chroma_t *t = &CIE_Mons[0]; + + while (t->desc !=NULL) + { + t++; + num++; + } + return num; +} + +const char * crt_monitor::get_cie_name(void) +{ + return CIE_Mons[m_param.source_cie].desc; +} diff --git a/src/emu/screen.h b/src/emu/screen.h index 4f44dbec031..551d840dc8e 100644 --- a/src/emu/screen.h +++ b/src/emu/screen.h @@ -127,6 +127,104 @@ typedef device_delegate<UINT32 (screen_device &, bitmap_rgb32 &, const rectangle typedef device_delegate<void (screen_device &, bool)> screen_vblank_delegate; +// ======================> monitor_device + + +class crt_monitor +{ +public: + + typedef enum + { + PASSTHROUGHX = 0, // PASSTHROUGH somewhere defined in win32 environment + SHADOW_MASK = 1, + CROMA_CLEAR = 2, +// APERTURE_GRILLE, + } crt_monitor_type; + + typedef struct + { + crt_monitor_type m_type; + INT16 r_off; + INT16 g_off; + INT16 b_off; + UINT16 r_gain; + UINT16 b_gain; + UINT16 g_gain; + UINT16 focus; + UINT16 decay; + UINT16 bandwidth; + UINT8 source_cie; + } crt_monitor_param; + + crt_monitor(void); + ~crt_monitor(void); + + void resize(int new_width, int new_height); + + bitmap_t &final_bitmap(int cur_bm) { return m_phos_bm[cur_bm]; } + + void get_param(crt_monitor_param ¶m) { param = m_param; } + void set_param(crt_monitor_param ¶m); + + crt_monitor_type type(void) const { return m_param.m_type; } + //void set_type(crt_monitor_type new_type) { m_type = new_type; } + + //void set_horz_pixel(int num) { m_horz_pixel = num; } + + void process(running_machine &machine, screen_bitmap &src_bm, int cur_bm, rectangle &clip); + + const rectangle &get_visible() const { return m_visible; } + + int get_cie_count(void); + const char * get_cie_name(void); + + int get_type_count(void) { return 3; } + const char * get_type_name(void) + { + switch (m_param.m_type) + { + case PASSTHROUGHX: + return "Passthrough"; + case CROMA_CLEAR: + return "Croma Clear"; + case SHADOW_MASK: + return "Shadow Mask"; + } + return ""; + } + + +private: + INT16 * m_amplifier_r; + INT16 * m_amplifier_g; + INT16 * m_amplifier_b; + bitmap_rgb32 m_mask_bm; + bitmap_rgb32 m_phos_bm[2]; + + crt_monitor_param m_param; + rectangle m_visible; + //rectangle m_src_visible; + + int m_vert_pixel; + int m_horz_pixel; + int m_width; + int m_height; + + void free_bitmaps(void); + void scale_and_bandwith(running_machine &machine, bitmap_t &bm_src, const rectangle &cliprect); + void copyonly(bitmap_rgb32 &bm_dst, rectangle &clip); + void copy_shadow_mask(bitmap_rgb32 &bm_dst, const rectangle &clip); + void copy_chroma(bitmap_rgb32 &bm_dst, const rectangle &clip); + void phosphor(bitmap_rgb32 &bm_dst, bitmap_rgb32 &bm_phos, bitmap_rgb32 &bm_src, const rectangle &cliprect); + + rgb_t base_red[768]; + rgb_t base_green[768]; + rgb_t base_blue[768]; + int m_exp[256]; +}; + + // ======================> screen_device class screen_device : public device_t @@ -142,7 +240,7 @@ public: screen_type_enum screen_type() const { return m_type; } int width() const { return m_width; } int height() const { return m_height; } - const rectangle &visible_area() const { return m_visarea; } + const rectangle &visible_area() const;// { return m_visarea; } const rectangle &cliprect() const { return m_bitmap[0].cliprect(); } bool oldstyle_vblank_supplied() const { return m_oldstyle_vblank_supplied; } attoseconds_t refresh_attoseconds() const { return m_refresh; } @@ -197,6 +295,8 @@ public: void update_now(); void reset_partial_updates(); + void set_render_size(int width, int height); + // additional helpers void register_vblank_callback(vblank_state_delegate vblank_callback); void register_screen_bitmap(bitmap_t &bitmap); @@ -206,6 +306,10 @@ public: bool update_quads(); void update_burnin(); + // access to crt + + crt_monitor &crt(void) { return m_crt; } + // globally accessible constants static const int DEFAULT_FRAME_RATE = 60; static const attotime DEFAULT_FRAME_PERIOD; @@ -281,6 +385,10 @@ private: UINT64 m_frame_number; // the current frame number UINT32 m_partial_updates_this_frame;// partial update counter this frame + // render size + INT32 m_render_width; + INT32 m_render_height; + // VBLANK callbacks class callback_item { @@ -312,6 +420,10 @@ private: // static data static UINT32 m_id_counter; // incremented for each constructed screen_device, // used as a unique identifier during runtime + + // monitor emulation + + crt_monitor m_crt; }; // device type definition diff --git a/src/emu/ui/ui.c b/src/emu/ui/ui.c index 8f50ead60f9..557c90099e8 100644 --- a/src/emu/ui/ui.c +++ b/src/emu/ui/ui.c @@ -123,6 +123,20 @@ static INT32 slider_overyoffset(running_machine &machine, void *arg, astring *st static INT32 slider_flicker(running_machine &machine, void *arg, astring *string, INT32 newval); static INT32 slider_beam(running_machine &machine, void *arg, astring *string, INT32 newval); static char *slider_get_screen_desc(screen_device &screen); + +static INT32 slider_crt_red_off(running_machine &machine, void *arg, astring *string, INT32 newval); +static INT32 slider_crt_green_off(running_machine &machine, void *arg, astring *string, INT32 newval); +static INT32 slider_crt_blue_off(running_machine &machine, void *arg, astring *string, INT32 newval); +static INT32 slider_crt_red_gain(running_machine &machine, void *arg, astring *string, INT32 newval); +static INT32 slider_crt_green_gain(running_machine &machine, void *arg, astring *string, INT32 newval); +static INT32 slider_crt_blue_gain(running_machine &machine, void *arg, astring *string, INT32 newval); +static INT32 slider_crt_decay(running_machine &machine, void *arg, astring *string, INT32 newval); +static INT32 slider_crt_bandwidth(running_machine &machine, void *arg, astring *string, INT32 newval); +static INT32 slider_crt_focus(running_machine &machine, void *arg, astring *string, INT32 newval); +static INT32 slider_crt_cie(running_machine &machine, void *arg, astring *string, INT32 newval); +static INT32 slider_crt_type(running_machine &machine, void *arg, astring *string, INT32 newval); + + #ifdef MAME_DEBUG static INT32 slider_crossscale(running_machine &machine, void *arg, astring *string, INT32 newval); static INT32 slider_crossoffset(running_machine &machine, void *arg, astring *string, INT32 newval); @@ -1905,6 +1919,54 @@ static slider_state *slider_init(running_machine &machine) break; } + screen_device_iterator iter(machine.root_device()); + for (screen_device *screen = iter.first(); screen != NULL; screen = iter.next()) + if (screen->screen_type() != SCREEN_TYPE_VECTOR) + { + void *param = (void *)screen; + + string.printf("%s Red Offset", slider_get_screen_desc(*screen)); + *tailptr = slider_alloc(machine, string, -256, 0, 256, 5, slider_crt_red_off, param); + tailptr = &(*tailptr)->next; + string.printf("%s Green Offset", slider_get_screen_desc(*screen)); + *tailptr = slider_alloc(machine, string, -256, 0, 256, 5, slider_crt_green_off, param); + tailptr = &(*tailptr)->next; + string.printf("%s Blue Offset", slider_get_screen_desc(*screen)); + *tailptr = slider_alloc(machine, string, -256, 0, 256, 5, slider_crt_blue_off, param); + tailptr = &(*tailptr)->next; + + string.printf("%s Red Gain", slider_get_screen_desc(*screen)); + *tailptr = slider_alloc(machine, string, 0, 256, 767, 5, slider_crt_red_gain, param); + tailptr = &(*tailptr)->next; + string.printf("%s Green Gain", slider_get_screen_desc(*screen)); + *tailptr = slider_alloc(machine, string, 0, 256, 767, 5, slider_crt_green_gain, param); + tailptr = &(*tailptr)->next; + string.printf("%s Blue Gain", slider_get_screen_desc(*screen)); + *tailptr = slider_alloc(machine, string, 0, 256, 767, 5, slider_crt_blue_gain, param); + tailptr = &(*tailptr)->next; + + string.printf("%s Phosphor decay", slider_get_screen_desc(*screen)); + *tailptr = slider_alloc(machine, string, 0, 0, 256, 5, slider_crt_decay, param); + tailptr = &(*tailptr)->next; + + string.printf("%s Bandwidth", slider_get_screen_desc(*screen)); + *tailptr = slider_alloc(machine, string, 0, 0, 256, 5, slider_crt_bandwidth, param); + tailptr = &(*tailptr)->next; + + string.printf("%s Focus", slider_get_screen_desc(*screen)); + *tailptr = slider_alloc(machine, string, 0, 256, 256, 5, slider_crt_focus, param); + tailptr = &(*tailptr)->next; + + string.printf("%s CIE", slider_get_screen_desc(*screen)); + *tailptr = slider_alloc(machine, string, 0, 0, screen->crt().get_cie_count()-1, 1, slider_crt_cie, param); + tailptr = &(*tailptr)->next; + + string.printf("%s Monitor type", slider_get_screen_desc(*screen)); + *tailptr = slider_alloc(machine, string, 0, 0, screen->crt().get_type_count()-1, 1, slider_crt_type, param); + tailptr = &(*tailptr)->next; + + } + #ifdef MAME_DEBUG // add crosshair adjusters for (port = machine.ioport().first_port(); port != NULL; port = port->next()) @@ -1924,6 +1986,186 @@ static slider_state *slider_init(running_machine &machine) return listhead; } +/*------------------------------------------------- + slider_crt_* - CRT Monitor sliders +-------------------------------------------------*/ + +static INT32 slider_crt_red_off(running_machine &machine, void *arg, astring *string, INT32 newval) +{ + screen_device *screen = reinterpret_cast<screen_device *>(arg); + crt_monitor::crt_monitor_param param; + + screen->crt().get_param(param); + if (newval != SLIDER_NOCHANGE) + { + param.r_off = newval; + screen->crt().set_param(param); + } + if (string != NULL) + string->printf("%.2f", (double) param.r_off / 256.0f); + return param.r_off; +} + +static INT32 slider_crt_green_off(running_machine &machine, void *arg, astring *string, INT32 newval) +{ + screen_device *screen = reinterpret_cast<screen_device *>(arg); + crt_monitor::crt_monitor_param param; + + screen->crt().get_param(param); + if (newval != SLIDER_NOCHANGE) + { + param.g_off = newval; + screen->crt().set_param(param); + } + if (string != NULL) + string->printf("%.2f", (double) param.g_off / 256.0f); + return param.g_off; +} + +static INT32 slider_crt_blue_off(running_machine &machine, void *arg, astring *string, INT32 newval) +{ + screen_device *screen = reinterpret_cast<screen_device *>(arg); + crt_monitor::crt_monitor_param param; + + screen->crt().get_param(param); + if (newval != SLIDER_NOCHANGE) + { + param.b_off = newval; + screen->crt().set_param(param); + } + if (string != NULL) + string->printf("%.2f", (double) param.b_off / 256.0f); + return param.b_off; +} + +static INT32 slider_crt_red_gain(running_machine &machine, void *arg, astring *string, INT32 newval) +{ + screen_device *screen = reinterpret_cast<screen_device *>(arg); + crt_monitor::crt_monitor_param param; + + screen->crt().get_param(param); + if (newval != SLIDER_NOCHANGE) + { + param.r_gain = newval; + screen->crt().set_param(param); + } + if (string != NULL) + string->printf("%.2f", (double) param.r_gain / 256.0f); + return param.r_gain; +} + +static INT32 slider_crt_green_gain(running_machine &machine, void *arg, astring *string, INT32 newval) +{ + screen_device *screen = reinterpret_cast<screen_device *>(arg); + crt_monitor::crt_monitor_param param; + + screen->crt().get_param(param); + if (newval != SLIDER_NOCHANGE) + { + param.g_gain = newval; + screen->crt().set_param(param); + } + if (string != NULL) + string->printf("%.2f", (double) param.g_gain / 256.0f); + return param.g_gain; +} + +static INT32 slider_crt_blue_gain(running_machine &machine, void *arg, astring *string, INT32 newval) +{ + screen_device *screen = reinterpret_cast<screen_device *>(arg); + crt_monitor::crt_monitor_param param; + + screen->crt().get_param(param); + if (newval != SLIDER_NOCHANGE) + { + param.b_gain = newval; + screen->crt().set_param(param); + } + if (string != NULL) + string->printf("%.2f", (double) param.b_gain / 256.0f); + return param.b_gain; +} + +static INT32 slider_crt_decay(running_machine &machine, void *arg, astring *string, INT32 newval) +{ + screen_device *screen = reinterpret_cast<screen_device *>(arg); + crt_monitor::crt_monitor_param param; + + screen->crt().get_param(param); + if (newval != SLIDER_NOCHANGE) + { + param.decay = newval; + screen->crt().set_param(param); + } + if (string != NULL) + string->printf("%.2f", (double) param.decay / 256.0f); + return param.decay; +} + +static INT32 slider_crt_bandwidth(running_machine &machine, void *arg, astring *string, INT32 newval) +{ + screen_device *screen = reinterpret_cast<screen_device *>(arg); + crt_monitor::crt_monitor_param param; + + screen->crt().get_param(param); + if (newval != SLIDER_NOCHANGE) + { + param.bandwidth = newval; + screen->crt().set_param(param); + } + if (string != NULL) + string->printf("%.2f", (double) param.bandwidth / 256.0f); + return param.bandwidth; +} + +static INT32 slider_crt_focus(running_machine &machine, void *arg, astring *string, INT32 newval) +{ + screen_device *screen = reinterpret_cast<screen_device *>(arg); + crt_monitor::crt_monitor_param param; + + screen->crt().get_param(param); + if (newval != SLIDER_NOCHANGE) + { + param.focus = newval; + screen->crt().set_param(param); + } + if (string != NULL) + string->printf("%.2f", (double) param.focus / 256.0f); + return param.focus; +} + +static INT32 slider_crt_cie(running_machine &machine, void *arg, astring *string, INT32 newval) +{ + screen_device *screen = reinterpret_cast<screen_device *>(arg); + crt_monitor::crt_monitor_param param; + + screen->crt().get_param(param); + if (newval != SLIDER_NOCHANGE) + { + param.source_cie = newval; + screen->crt().set_param(param); + } + if (string != NULL) + string->printf("%s", screen->crt().get_cie_name()); + return param.source_cie; +} + +static INT32 slider_crt_type(running_machine &machine, void *arg, astring *string, INT32 newval) +{ + screen_device *screen = reinterpret_cast<screen_device *>(arg); + crt_monitor::crt_monitor_param param; + + screen->crt().get_param(param); + if (newval != SLIDER_NOCHANGE) + { + param.m_type = (crt_monitor::crt_monitor_type) newval; + screen->crt().set_param(param); + } + if (string != NULL) + string->printf("%s", screen->crt().get_type_name()); + return param.m_type; +} + //------------------------------------------------- // slider_volume - global volume slider callback |
