summaryrefslogtreecommitdiffstatshomepage
path: root/src
diff options
context:
space:
mode:
author Vas Crabb <vas@vastheman.com>2020-12-18 15:54:52 +1100
committer Vas Crabb <vas@vastheman.com>2020-12-18 15:54:52 +1100
commit1df245cb99882892678216c3d0c6e243611d627c (patch)
treea8f3563a74d58755f4a82d4cbfc2406cf79543b3 /src
parentff9c1a0ca91f925e5c23b22a92a53c83f9f655ba (diff)
More Lua engine clean-up and documentation, resulting in core cleanup.
More Lua interface cleanup, additional properties and methods, and documentation migration/expansion. Emulated switch inputs can have "not" codes applied to host input axis directions. It works the same way as host switch inputs - push twice for a "not" prefix. Input polling helpers no longer need to store state in the input device items. There’s less leakage, and less chance of things interfering with each other. Allow snapshot view options to be configured through the internal UI via the video options menu. Made video options menus place initial focus on the currently selected view item. Removed some crud from the menu base class. Fixed the description of the "snapview" option. The value to get raw screen pixels was changed to "native" a long time ago but the description was never updated. Re-arranged the Golden Poker button lamps so that the 6-button layouts for Jolli Witch and Wild Witch make sense. In 6-button mode, the hold buttons double as bonus game and bet buttons, but the lamp outputs don't change. The simplest way to deal with this without requiring the user to switch views or using layout scripting is to place the dedicated buttons directly below the hold buttons that correspond to them. Removed some software list data that was redundantly copied into device_image_interface (m_supported was never even set, so it didn't even work), and made crc() work better (previously it wasn't recalculuated after unloading and loading another image). Made strformat.h and devcb.h play nicer with C++17 and pre-standard C++20. Format precision now correctly limits the length of string views. Confirmed that strformat.{h,cpp} works with pre-standard C++20 support in GCC 9. Removed an auto_alloc from cpu/arm7.
Diffstat (limited to 'src')
-rw-r--r--src/devices/cpu/arm7/arm7.h72
-rw-r--r--src/devices/cpu/arm7/arm7drc.hxx83
-rw-r--r--src/devices/imagedev/cassette.h8
-rw-r--r--src/emu/devcb.h30
-rw-r--r--src/emu/diimage.cpp14
-rw-r--r--src/emu/diimage.h11
-rw-r--r--src/emu/emumem.h2
-rw-r--r--src/emu/emuopts.cpp2
-rw-r--r--src/emu/inpttype.ipp15
-rw-r--r--src/emu/inputdev.cpp50
-rw-r--r--src/emu/inputdev.h7
-rw-r--r--src/emu/ioport.h1
-rw-r--r--src/emu/render.cpp18
-rw-r--r--src/emu/video.cpp20
-rw-r--r--src/emu/video.h3
-rw-r--r--src/frontend/mame/iptseqpoll.cpp182
-rw-r--r--src/frontend/mame/iptseqpoll.h4
-rw-r--r--src/frontend/mame/luaengine.cpp803
-rw-r--r--src/frontend/mame/luaengine.h2
-rw-r--r--src/frontend/mame/luaengine.ipp85
-rw-r--r--src/frontend/mame/luaengine_render.cpp150
-rw-r--r--src/frontend/mame/ui/barcode.cpp18
-rw-r--r--src/frontend/mame/ui/devctrl.h10
-rw-r--r--src/frontend/mame/ui/devopt.cpp4
-rw-r--r--src/frontend/mame/ui/info.cpp28
-rw-r--r--src/frontend/mame/ui/inifile.cpp8
-rw-r--r--src/frontend/mame/ui/mainmenu.cpp4
-rw-r--r--src/frontend/mame/ui/menu.cpp57
-rw-r--r--src/frontend/mame/ui/menu.h3
-rw-r--r--src/frontend/mame/ui/miscmenu.cpp31
-rw-r--r--src/frontend/mame/ui/tapectrl.cpp8
-rw-r--r--src/frontend/mame/ui/videoopt.cpp111
-rw-r--r--src/frontend/mame/ui/videoopt.h6
-rw-r--r--src/lib/util/strformat.h119
-rw-r--r--src/mame/drivers/goldnpkr.cpp55
-rw-r--r--src/mame/layout/goldnpkr.lay124
36 files changed, 1013 insertions, 1135 deletions
diff --git a/src/devices/cpu/arm7/arm7.h b/src/devices/cpu/arm7/arm7.h
index 80757afe13b..b303d515a8c 100644
--- a/src/devices/cpu/arm7/arm7.h
+++ b/src/devices/cpu/arm7/arm7.h
@@ -368,17 +368,17 @@ protected:
/* fast RAM info */
struct fast_ram_info
{
- offs_t start; /* start of the RAM block */
- offs_t end; /* end of the RAM block */
- bool readonly; /* true if read-only */
- void * base; /* base in memory where the RAM lives */
+ offs_t start = 0; /* start of the RAM block */
+ offs_t end = 0; /* end of the RAM block */
+ bool readonly = false; /* true if read-only */
+ void * base = nullptr; /* base in memory where the RAM lives */
};
struct hotspot_info
{
- uint32_t pc;
- uint32_t opcode;
- uint32_t cycles;
+ uint32_t pc = 0;
+ uint32_t opcode = 0;
+ uint32_t cycles = 0;
};
/* internal compiler state */
@@ -386,9 +386,9 @@ protected:
{
compiler_state &operator=(compiler_state const &) = delete;
- uint32_t cycles; /* accumulated cycles */
- uint8_t checkints; /* need to check interrupts before next instruction */
- uint8_t checksoftints; /* need to check software interrupts before next instruction */
+ uint32_t cycles = 0; /* accumulated cycles */
+ uint8_t checkints = 0; /* need to check interrupts before next instruction */
+ uint8_t checksoftints = 0; /* need to check software interrupts before next instruction */
uml::code_label labelnum; /* index for local labels */
};
@@ -396,45 +396,45 @@ protected:
struct arm7imp_state
{
/* core state */
- drc_cache * cache; /* pointer to the DRC code cache */
- drcuml_state * drcuml; /* DRC UML generator state */
- //arm7_frontend * drcfe; /* pointer to the DRC front-end state */
- uint32_t drcoptions; /* configurable DRC options */
+ std::unique_ptr<drc_cache> cache; /* pointer to the DRC code cache */
+ std::unique_ptr<drcuml_state> drcuml; /* DRC UML generator state */
+ //arm7_frontend * drcfe = nullptr; /* pointer to the DRC front-end state */
+ uint32_t drcoptions = 0; /* configurable DRC options */
/* internal stuff */
- uint8_t cache_dirty; /* true if we need to flush the cache */
- uint32_t jmpdest; /* destination jump target */
+ uint8_t cache_dirty = 0; /* true if we need to flush the cache */
+ uint32_t jmpdest = 0; /* destination jump target */
/* parameters for subroutines */
- uint64_t numcycles; /* return value from gettotalcycles */
- uint32_t mode; /* current global mode */
- const char * format; /* format string for print_debug */
- uint32_t arg0; /* print_debug argument 1 */
- uint32_t arg1; /* print_debug argument 2 */
+ uint64_t numcycles = 0; /* return value from gettotalcycles */
+ uint32_t mode = 0; /* current global mode */
+ const char * format = nullptr; /* format string for print_debug */
+ uint32_t arg0 = 0; /* print_debug argument 1 */
+ uint32_t arg1 = 0; /* print_debug argument 2 */
/* register mappings */
- uml::parameter regmap[/*NUM_REGS*/37]; /* parameter to register mappings for all 16 integer registers */
+ uml::parameter regmap[/*NUM_REGS*/37]; /* parameter to register mappings for all 16 integer registers */
/* subroutines */
- uml::code_handle * entry; /* entry point */
- uml::code_handle * nocode; /* nocode exception handler */
- uml::code_handle * out_of_cycles; /* out of cycles exception handler */
- uml::code_handle * tlb_translate; /* tlb translation handler */
- uml::code_handle * detect_fault; /* tlb fault detection handler */
- uml::code_handle * check_irq; /* irq check handler */
- uml::code_handle * read8; /* read byte */
- uml::code_handle * write8; /* write byte */
- uml::code_handle * read16; /* read half */
- uml::code_handle * write16; /* write half */
- uml::code_handle * read32; /* read word */
- uml::code_handle * write32; /* write word */
+ uml::code_handle * entry = nullptr; /* entry point */
+ uml::code_handle * nocode = nullptr; /* nocode exception handler */
+ uml::code_handle * out_of_cycles = nullptr; /* out of cycles exception handler */
+ uml::code_handle * tlb_translate = nullptr; /* tlb translation handler */
+ uml::code_handle * detect_fault = nullptr; /* tlb fault detection handler */
+ uml::code_handle * check_irq = nullptr; /* irq check handler */
+ uml::code_handle * read8 = nullptr; /* read byte */
+ uml::code_handle * write8 = nullptr; /* write byte */
+ uml::code_handle * read16 = nullptr; /* read half */
+ uml::code_handle * write16 = nullptr; /* write half */
+ uml::code_handle * read32 = nullptr; /* read word */
+ uml::code_handle * write32 = nullptr; /* write word */
/* fast RAM */
- uint32_t fastram_select;
+ uint32_t fastram_select = 0;
fast_ram_info fastram[ARM7_MAX_FASTRAM];
/* hotspots */
- uint32_t hotspot_select;
+ uint32_t hotspot_select = 0;
hotspot_info hotspot[ARM7_MAX_HOTSPOTS];
} m_impstate;
diff --git a/src/devices/cpu/arm7/arm7drc.hxx b/src/devices/cpu/arm7/arm7drc.hxx
index 621c0a7f0f8..8edd44438bd 100644
--- a/src/devices/cpu/arm7/arm7drc.hxx
+++ b/src/devices/cpu/arm7/arm7drc.hxx
@@ -127,21 +127,18 @@ void arm7_cpu_device::save_fast_iregs(drcuml_block &block)
void arm7_cpu_device::arm7_drc_init()
{
- drc_cache *cache;
drcbe_info beinfo;
uint32_t flags = 0;
/* allocate enough space for the cache and the core */
- cache = auto_alloc(machine(), drc_cache(CACHE_SIZE));
- if (cache == nullptr)
- fatalerror("Unable to allocate cache of size %d\n", (uint32_t)(CACHE_SIZE));
/* allocate the implementation-specific state from the full cache */
- memset(&m_impstate, 0, sizeof(m_impstate));
- m_impstate.cache = cache;
+ m_impstate = arm7imp_state();
+ try { m_impstate.cache = std::make_unique<drc_cache>(CACHE_SIZE); }
+ catch (std::bad_alloc const &) { throw emu_fatalerror("Unable to allocate cache of size %d\n", (uint32_t)(CACHE_SIZE)); }
/* initialize the UML generator */
- m_impstate.drcuml = new drcuml_state(*this, *cache, flags, 1, 32, 1);
+ m_impstate.drcuml = std::make_unique<drcuml_state>(*this, *m_impstate.cache, flags, 1, 32, 1);
/* add symbols for our stuff */
m_impstate.drcuml->symbol_add(&m_icount, sizeof(m_icount), "icount");
@@ -158,7 +155,7 @@ void arm7_cpu_device::arm7_drc_init()
//m_impstate.drcuml->symbol_add(&m_impstate.fpmode, sizeof(m_impstate.fpmode), "fpmode"); // TODO
/* initialize the front-end helper */
- //m_impstate.drcfe = auto_alloc(machine(), arm7_frontend(this, COMPILE_BACKWARDS_BYTES, COMPILE_FORWARDS_BYTES, SINGLE_INSTRUCTION_MODE ? 1 : COMPILE_MAX_SEQUENCE));
+ //m_impstate.drcfe = std::make_unique<arm7_frontend>(this, COMPILE_BACKWARDS_BYTES, COMPILE_FORWARDS_BYTES, SINGLE_INSTRUCTION_MODE ? 1 : COMPILE_MAX_SEQUENCE);
/* allocate memory for cache-local state and initialize it */
//memcpy(&m_impstate.fpmode, fpmode_source, sizeof(fpmode_source)); // TODO
@@ -199,7 +196,7 @@ void arm7_cpu_device::arm7_drc_init()
void arm7_cpu_device::execute_run_drc()
{
- drcuml_state *drcuml = m_impstate.drcuml;
+ drcuml_state &drcuml = *m_impstate.drcuml;
int execute_result;
/* reset the cache if dirty */
@@ -211,7 +208,7 @@ void arm7_cpu_device::execute_run_drc()
do
{
/* run as much as we can */
- execute_result = drcuml->execute(*m_impstate.entry);
+ execute_result = drcuml.execute(*m_impstate.entry);
/* if we need to recompile, do it */
if (execute_result == EXECUTE_MISSING_CODE)
@@ -231,9 +228,9 @@ void arm7_cpu_device::execute_run_drc()
void arm7_cpu_device::arm7_drc_exit()
{
/* clean up the DRC */
- //auto_free(machine(), m_impstate.drcfe);
- delete m_impstate.drcuml;
- auto_free(machine(), m_impstate.cache);
+ //m_impstate.drcfe.reset();
+ m_impstate.drcuml.reset();
+ m_impstate.cache.reset();
}
@@ -328,7 +325,7 @@ void arm7_cpu_device::code_flush_cache()
void arm7_cpu_device::code_compile_block(uint8_t mode, offs_t pc)
{
- drcuml_state *drcuml = m_impstate.drcuml;
+ drcuml_state &drcuml = *m_impstate.drcuml;
compiler_state compiler = { 0 };
const opcode_desc *seqlast;
bool override = false;
@@ -338,7 +335,7 @@ void arm7_cpu_device::code_compile_block(uint8_t mode, offs_t pc)
/* get a description of this sequence */
// TODO FIXME
const opcode_desc *desclist = nullptr; //m_impstate.drcfe->describe_code(pc); // TODO
-// if (drcuml->logging() || drcuml->logging_native())
+// if (drcuml.logging() || drcuml.logging_native())
// log_opcode_desc(drcuml, desclist, 0);
/* if we get an error back, flush the cache and try again */
@@ -348,7 +345,7 @@ void arm7_cpu_device::code_compile_block(uint8_t mode, offs_t pc)
try
{
/* start the block */
- drcuml_block &block(drcuml->begin_block(4096));
+ drcuml_block &block(drcuml.begin_block(4096));
/* loop until we get through all instruction sequences */
for (const opcode_desc *seqhead = desclist; seqhead != nullptr; seqhead = seqlast->next())
@@ -357,7 +354,7 @@ void arm7_cpu_device::code_compile_block(uint8_t mode, offs_t pc)
uint32_t nextpc;
/* add a code log entry */
- if (drcuml->logging())
+ if (drcuml.logging())
block.append_comment("-------------------------"); // comment
/* determine the last instruction in this sequence */
@@ -367,7 +364,7 @@ void arm7_cpu_device::code_compile_block(uint8_t mode, offs_t pc)
assert(seqlast != nullptr);
/* if we don't have a hash for this mode/pc, or if we are overriding all, add one */
- if (override || !drcuml->hash_exists(mode, seqhead->pc))
+ if (override || !drcuml.hash_exists(mode, seqhead->pc))
UML_HASH(block, mode, seqhead->pc); // hash mode,pc
/* if we already have a hash, and this is the first sequence, assume that we */
@@ -470,17 +467,17 @@ void arm7_cpu_device::cfunc_unimplemented()
void arm7_cpu_device::static_generate_entry_point()
{
- drcuml_state *drcuml = m_impstate.drcuml;
+ drcuml_state &drcuml = *m_impstate.drcuml;
- drcuml_block &block(drcuml->begin_block(110));
+ drcuml_block &block(drcuml.begin_block(110));
/* forward references */
- //alloc_handle(*drcuml, &m_impstate.exception_norecover[EXCEPTION_INTERRUPT], "interrupt_norecover");
- alloc_handle(*drcuml, m_impstate.nocode, "nocode");
- alloc_handle(*drcuml, m_impstate.detect_fault, "detect_fault");
- alloc_handle(*drcuml, m_impstate.tlb_translate, "tlb_translate");
+ //alloc_handle(drcuml, &m_impstate.exception_norecover[EXCEPTION_INTERRUPT], "interrupt_norecover");
+ alloc_handle(drcuml, m_impstate.nocode, "nocode");
+ alloc_handle(drcuml, m_impstate.detect_fault, "detect_fault");
+ alloc_handle(drcuml, m_impstate.tlb_translate, "tlb_translate");
- alloc_handle(*drcuml, m_impstate.entry, "entry");
+ alloc_handle(drcuml, m_impstate.entry, "entry");
UML_HANDLE(block, *m_impstate.entry); // handle entry
/* load fast integer registers */
@@ -501,7 +498,7 @@ void arm7_cpu_device::static_generate_entry_point()
void arm7_cpu_device::static_generate_check_irq()
{
- drcuml_state *drcuml = m_impstate.drcuml;
+ drcuml_state &drcuml = *m_impstate.drcuml;
uml::code_label noirq;
int nodabt = 0;
int nopabt = 0;
@@ -513,10 +510,10 @@ void arm7_cpu_device::static_generate_check_irq()
int label = 1;
/* begin generating */
- drcuml_block &block(drcuml->begin_block(120));
+ drcuml_block &block(drcuml.begin_block(120));
/* generate a hash jump via the current mode and PC */
- alloc_handle(*drcuml, m_impstate.check_irq, "check_irq");
+ alloc_handle(drcuml, m_impstate.check_irq, "check_irq");
UML_HANDLE(block, *m_impstate.check_irq); // handle check_irq
/* Exception priorities:
@@ -669,13 +666,13 @@ void arm7_cpu_device::static_generate_check_irq()
void arm7_cpu_device::static_generate_nocode_handler()
{
- drcuml_state *drcuml = m_impstate.drcuml;
+ drcuml_state &drcuml = *m_impstate.drcuml;
/* begin generating */
- drcuml_block &block(drcuml->begin_block(10));
+ drcuml_block &block(drcuml.begin_block(10));
/* generate a hash jump via the current mode and PC */
- alloc_handle(*drcuml, m_impstate.nocode, "nocode");
+ alloc_handle(drcuml, m_impstate.nocode, "nocode");
UML_HANDLE(block, *m_impstate.nocode); // handle nocode
UML_GETEXP(block, uml::I0); // getexp i0
UML_MOV(block, uml::mem(&R15), uml::I0); // mov [pc],i0
@@ -693,13 +690,13 @@ void arm7_cpu_device::static_generate_nocode_handler()
void arm7_cpu_device::static_generate_out_of_cycles()
{
- drcuml_state *drcuml = m_impstate.drcuml;
+ drcuml_state &drcuml = *m_impstate.drcuml;
/* begin generating */
- drcuml_block &block(drcuml->begin_block(10));
+ drcuml_block &block(drcuml.begin_block(10));
/* generate a hash jump via the current mode and PC */
- alloc_handle(*drcuml, m_impstate.out_of_cycles, "out_of_cycles");
+ alloc_handle(drcuml, m_impstate.out_of_cycles, "out_of_cycles");
UML_HANDLE(block, *m_impstate.out_of_cycles); // handle out_of_cycles
UML_GETEXP(block, uml::I0); // getexp i0
UML_MOV(block, uml::mem(&R15), uml::I0); // mov <pc>,i0
@@ -718,16 +715,16 @@ void arm7_cpu_device::static_generate_detect_fault(uml::code_handle **handleptr)
{
/* on entry, flags are in I2, vaddr is in I3, desc_lvl1 is in I4, ap is in R5 */
/* on exit, fault result is in I6 */
- drcuml_state *drcuml = m_impstate.drcuml;
+ drcuml_state &drcuml = *m_impstate.drcuml;
int donefault = 0;
int checkuser = 0;
int label = 1;
/* begin generating */
- drcuml_block &block(drcuml->begin_block(1024));
+ drcuml_block &block(drcuml.begin_block(1024));
/* add a global entry for this */
- alloc_handle(*drcuml, m_impstate.detect_fault, "detect_fault");
+ alloc_handle(drcuml, m_impstate.detect_fault, "detect_fault");
UML_HANDLE(block, *m_impstate.detect_fault); // handle detect_fault
UML_ROLAND(block, uml::I6, uml::I4, 32-4, 0x0f<<1); // roland i6, i4, 32-4, 0xf<<1
@@ -796,7 +793,7 @@ void arm7_cpu_device::static_generate_tlb_translate(uml::code_handle **handleptr
/* on entry, address is in I0 and flags are in I2 */
/* on exit, translated address is in I0 and success/failure is in I2 */
/* routine trashes I4-I7 */
- drcuml_state *drcuml = m_impstate.drcuml;
+ drcuml_state &drcuml = *m_impstate.drcuml;
uml::code_label smallfault;
uml::code_label smallprefetch;
int nopid = 0;
@@ -815,9 +812,9 @@ void arm7_cpu_device::static_generate_tlb_translate(uml::code_handle **handleptr
int label = 1;
/* begin generating */
- drcuml_block &block(drcuml->begin_block(170));
+ drcuml_block &block(drcuml.begin_block(170));
- alloc_handle(*drcuml, m_impstate.tlb_translate, "tlb_translate");
+ alloc_handle(drcuml, m_impstate.tlb_translate, "tlb_translate");
UML_HANDLE(block, *m_impstate.tlb_translate); // handle tlb_translate
// I3: vaddr
@@ -1004,15 +1001,15 @@ void arm7_cpu_device::static_generate_memory_accessor(int size, bool istlb, bool
/* on entry, address is in I0; data for writes is in I1, fetch type in I2 */
/* on exit, read result is in I0 */
/* routine trashes I0-I3 */
- drcuml_state *drcuml = m_impstate.drcuml;
+ drcuml_state &drcuml = *m_impstate.drcuml;
//int tlbmiss = 0;
int label = 1;
/* begin generating */
- drcuml_block &block(drcuml->begin_block(1024));
+ drcuml_block &block(drcuml.begin_block(1024));
/* add a global entry for this */
- alloc_handle(*drcuml, handleptr, name);
+ alloc_handle(drcuml, handleptr, name);
UML_HANDLE(block, *handleptr); // handle *handleptr
if (istlb)
diff --git a/src/devices/imagedev/cassette.h b/src/devices/imagedev/cassette.h
index 5310bb546d3..48e10cdbdb4 100644
--- a/src/devices/imagedev/cassette.h
+++ b/src/devices/imagedev/cassette.h
@@ -87,10 +87,10 @@ public:
bool is_playing() { return (m_state & CASSETTE_MASK_UISTATE) == CASSETTE_PLAY; }
bool is_recording() { return (m_state & CASSETTE_MASK_UISTATE) == CASSETTE_RECORD; }
- void set_motor(int state) { change_state(state ? CASSETTE_MOTOR_ENABLED : CASSETTE_MOTOR_DISABLED, CASSETTE_MASK_MOTOR); } // aka remote control
- int motor_on() { return ((m_state & CASSETTE_MASK_MOTOR) == CASSETTE_MOTOR_ENABLED) ? 1 : 0; }
- void set_speaker(int state) { change_state(state ? CASSETTE_SPEAKER_ENABLED : CASSETTE_SPEAKER_MUTED, CASSETTE_MASK_SPEAKER); }
- int speaker_on() { return ((m_state & CASSETTE_MASK_SPEAKER) == CASSETTE_SPEAKER_ENABLED) ? 1 : 0; }
+ void set_motor(bool state) { change_state(state ? CASSETTE_MOTOR_ENABLED : CASSETTE_MOTOR_DISABLED, CASSETTE_MASK_MOTOR); } // aka remote control
+ bool motor_on() { return (m_state & CASSETTE_MASK_MOTOR) == CASSETTE_MOTOR_ENABLED; }
+ void set_speaker(bool state) { change_state(state ? CASSETTE_SPEAKER_ENABLED : CASSETTE_SPEAKER_MUTED, CASSETTE_MASK_SPEAKER); }
+ bool speaker_on() { return (m_state & CASSETTE_MASK_SPEAKER) == CASSETTE_SPEAKER_ENABLED; }
cassette_image *get_image() { return m_cassette.get(); }
double get_position();
diff --git a/src/emu/devcb.h b/src/emu/devcb.h
index fd966a7afc1..cdfa9321a5b 100644
--- a/src/emu/devcb.h
+++ b/src/emu/devcb.h
@@ -88,16 +88,16 @@ protected:
template <typename Input, typename Result, typename Func, typename Enable = void> struct is_transform_form4 { static constexpr bool value = false; };
template <typename Input, typename Result, typename Func, typename Enable = void> struct is_transform_form5 { static constexpr bool value = false; };
template <typename Input, typename Result, typename Func, typename Enable = void> struct is_transform_form6 { static constexpr bool value = false; };
- template <typename Input, typename Result, typename Func> struct is_transform_form3<Input, Result, Func, std::enable_if_t<std::is_convertible<std::result_of_t<Func (offs_t &, Input, std::make_unsigned_t<Input> &)>, Result>::value> > { static constexpr bool value = true; };
- template <typename Input, typename Result, typename Func> struct is_transform_form4<Input, Result, Func, std::enable_if_t<std::is_convertible<std::result_of_t<Func (offs_t &, Input)>, Result>::value> > { static constexpr bool value = true; };
- template <typename Input, typename Result, typename Func> struct is_transform_form6<Input, Result, Func, std::enable_if_t<std::is_convertible<std::result_of_t<Func (Input)>, Result>::value> > { static constexpr bool value = true; };
+ template <typename Input, typename Result, typename Func> struct is_transform_form3<Input, Result, Func, std::enable_if_t<std::is_convertible<std::invoke_result_t<Func, offs_t &, Input, std::make_unsigned_t<Input> &>, Result>::value> > { static constexpr bool value = true; };
+ template <typename Input, typename Result, typename Func> struct is_transform_form4<Input, Result, Func, std::enable_if_t<std::is_convertible<std::invoke_result_t<Func, offs_t &, Input>, Result>::value> > { static constexpr bool value = true; };
+ template <typename Input, typename Result, typename Func> struct is_transform_form6<Input, Result, Func, std::enable_if_t<std::is_convertible<std::invoke_result_t<Func, Input>, Result>::value> > { static constexpr bool value = true; };
template <typename Input, typename Result, typename Func> struct is_transform { static constexpr bool value = is_transform_form1<Input, Result, Func>::value || is_transform_form2<Input, Result, Func>::value || is_transform_form3<Input, Result, Func>::value || is_transform_form4<Input, Result, Func>::value || is_transform_form5<Input, Result, Func>::value || is_transform_form6<Input, Result, Func>::value; };
// Determining the result type of a transform function
template <typename Input, typename Result, typename Func, typename Enable = void> struct transform_result;
- template <typename Input, typename Result, typename Func> struct transform_result<Input, Result, Func, std::enable_if_t<is_transform_form3<Input, Result, Func>::value> > { using type = std::result_of_t<Func (offs_t &, Input, std::make_unsigned_t<Input> &)>; };
- template <typename Input, typename Result, typename Func> struct transform_result<Input, Result, Func, std::enable_if_t<is_transform_form4<Input, Result, Func>::value> > { using type = std::result_of_t<Func (offs_t &, Input)>; };
- template <typename Input, typename Result, typename Func> struct transform_result<Input, Result, Func, std::enable_if_t<is_transform_form6<Input, Result, Func>::value> > { using type = std::result_of_t<Func (Input)>; };
+ template <typename Input, typename Result, typename Func> struct transform_result<Input, Result, Func, std::enable_if_t<is_transform_form3<Input, Result, Func>::value> > { using type = std::invoke_result_t<Func, offs_t &, Input, std::make_unsigned_t<Input> &>; };
+ template <typename Input, typename Result, typename Func> struct transform_result<Input, Result, Func, std::enable_if_t<is_transform_form4<Input, Result, Func>::value> > { using type = std::invoke_result_t<Func, offs_t &, Input>; };
+ template <typename Input, typename Result, typename Func> struct transform_result<Input, Result, Func, std::enable_if_t<is_transform_form6<Input, Result, Func>::value> > { using type = std::invoke_result_t<Func, Input>; };
template <typename Input, typename Result, typename Func> using transform_result_t = typename transform_result<Input, Result, Func>::type;
// Mapping method types to delegate types
@@ -214,16 +214,16 @@ protected:
template <typename Result, typename Func, typename Enable = void> struct is_read_form1 { static constexpr bool value = false; };
template <typename Result, typename Func, typename Enable = void> struct is_read_form2 { static constexpr bool value = false; };
template <typename Result, typename Func, typename Enable = void> struct is_read_form3 { static constexpr bool value = false; };
- template <typename Result, typename Func> struct is_read_form1<Result, Func, std::enable_if_t<std::is_convertible<std::result_of_t<Func (offs_t, Result)>, Result>::value> > { static constexpr bool value = true; };
- template <typename Result, typename Func> struct is_read_form2<Result, Func, std::enable_if_t<std::is_convertible<std::result_of_t<Func (offs_t)>, Result>::value> > { static constexpr bool value = true; };
- template <typename Result, typename Func> struct is_read_form3<Result, Func, std::enable_if_t<std::is_convertible<std::result_of_t<Func ()>, Result>::value> > { static constexpr bool value = true; };
+ template <typename Result, typename Func> struct is_read_form1<Result, Func, std::enable_if_t<std::is_convertible<std::invoke_result_t<Func, offs_t, Result>, Result>::value> > { static constexpr bool value = true; };
+ template <typename Result, typename Func> struct is_read_form2<Result, Func, std::enable_if_t<std::is_convertible<std::invoke_result_t<Func, offs_t>, Result>::value> > { static constexpr bool value = true; };
+ template <typename Result, typename Func> struct is_read_form3<Result, Func, std::enable_if_t<std::is_convertible<std::invoke_result_t<Func>, Result>::value> > { static constexpr bool value = true; };
template <typename Result, typename Func> struct is_read { static constexpr bool value = is_read_form1<Result, Func>::value || is_read_form2<Result, Func>::value || is_read_form3<Result, Func>::value; };
// Determining the result type of a read function
template <typename Result, typename Func, typename Enable = void> struct read_result;
- template <typename Result, typename Func> struct read_result<Result, Func, std::enable_if_t<is_read_form1<Result, Func>::value> > { using type = std::result_of_t<Func (offs_t, std::make_unsigned_t<Result>)>; };
- template <typename Result, typename Func> struct read_result<Result, Func, std::enable_if_t<is_read_form2<Result, Func>::value> > { using type = std::result_of_t<Func (offs_t)>; };
- template <typename Result, typename Func> struct read_result<Result, Func, std::enable_if_t<is_read_form3<Result, Func>::value> > { using type = std::result_of_t<Func ()>; };
+ template <typename Result, typename Func> struct read_result<Result, Func, std::enable_if_t<is_read_form1<Result, Func>::value> > { using type = std::invoke_result_t<Func, offs_t, std::make_unsigned_t<Result>>; };
+ template <typename Result, typename Func> struct read_result<Result, Func, std::enable_if_t<is_read_form2<Result, Func>::value> > { using type = std::invoke_result_t<Func, offs_t>; };
+ template <typename Result, typename Func> struct read_result<Result, Func, std::enable_if_t<is_read_form3<Result, Func>::value> > { using type = std::invoke_result_t<Func>; };
template <typename Result, typename Func> using read_result_t = typename read_result<Result, Func>::type;
// Detecting candidates for read delegates
@@ -278,9 +278,9 @@ protected:
template <typename Input, typename Func, typename Enable = void> struct is_write_form1 { static constexpr bool value = false; };
template <typename Input, typename Func, typename Enable = void> struct is_write_form2 { static constexpr bool value = false; };
template <typename Input, typename Func, typename Enable = void> struct is_write_form3 { static constexpr bool value = false; };
- template <typename Input, typename Func> struct is_write_form1<Input, Func, void_t<std::result_of_t<Func (offs_t, Input, std::make_unsigned_t<Input>)> > > { static constexpr bool value = true; };
- template <typename Input, typename Func> struct is_write_form2<Input, Func, void_t<std::result_of_t<Func (offs_t, Input)> > > { static constexpr bool value = true; };
- template <typename Input, typename Func> struct is_write_form3<Input, Func, void_t<std::result_of_t<Func (Input)> > > { static constexpr bool value = true; };
+ template <typename Input, typename Func> struct is_write_form1<Input, Func, void_t<std::invoke_result_t<Func, offs_t, Input, std::make_unsigned_t<Input>> > > { static constexpr bool value = true; };
+ template <typename Input, typename Func> struct is_write_form2<Input, Func, void_t<std::invoke_result_t<Func, offs_t, Input> > > { static constexpr bool value = true; };
+ template <typename Input, typename Func> struct is_write_form3<Input, Func, void_t<std::invoke_result_t<Func, Input> > > { static constexpr bool value = true; };
template <typename Input, typename Func> struct is_write { static constexpr bool value = is_write_form1<Input, Func>::value || is_write_form2<Input, Func>::value || is_write_form3<Input, Func>::value; };
// Detecting candidates for write delegates
diff --git a/src/emu/diimage.cpp b/src/emu/diimage.cpp
index 0b78816c8e5..4a61fcdecc3 100644
--- a/src/emu/diimage.cpp
+++ b/src/emu/diimage.cpp
@@ -94,7 +94,6 @@ device_image_interface::device_image_interface(const machine_config &mconfig, de
, m_file()
, m_mame_file()
, m_software_part_ptr(nullptr)
- , m_supported(0)
, m_readonly(false)
, m_created(false)
, m_create_format(0)
@@ -576,7 +575,8 @@ u32 device_image_interface::crc()
u32 crc = 0;
image_checkhash();
- m_hash.crc(crc);
+ if (!m_hash.crc(crc))
+ crc = 0;
return crc;
}
@@ -1073,11 +1073,6 @@ image_init_result device_image_interface::load_software(const std::string &softw
if (swinfo.longname().empty() || swinfo.publisher().empty() || swinfo.year().empty())
fatalerror("Each entry in an XML list must have all of the following fields: description, publisher, year!\n");
- // store
- m_longname = swinfo.longname();
- m_manufacturer = swinfo.publisher();
- m_year = swinfo.year();
-
// set file type
std::string filename = (m_mame_file != nullptr) && (m_mame_file->filename() != nullptr)
? m_mame_file->filename()
@@ -1204,9 +1199,6 @@ void device_image_interface::clear()
m_create_format = 0;
m_create_args = nullptr;
- m_longname.clear();
- m_manufacturer.clear();
- m_year.clear();
m_basename.clear();
m_basename_noext.clear();
m_filetype.clear();
@@ -1214,6 +1206,8 @@ void device_image_interface::clear()
m_full_software_name.clear();
m_software_part_ptr = nullptr;
m_software_list_name.clear();
+
+ m_hash.reset();
}
diff --git a/src/emu/diimage.h b/src/emu/diimage.h
index 9ec748c3bed..e9292f2f472 100644
--- a/src/emu/diimage.h
+++ b/src/emu/diimage.h
@@ -175,11 +175,6 @@ public:
void *ptr() {check_for_file(); return const_cast<void *>(m_file->buffer()); }
// configuration access
- const std::string &longname() const noexcept { return m_longname; }
- const std::string &manufacturer() const noexcept { return m_manufacturer; }
- const std::string &year() const noexcept { return m_year; }
- u32 supported() const noexcept { return m_supported; }
-
const software_info *software_entry() const noexcept;
const software_part *part_entry() const noexcept { return m_software_part_ptr; }
const char *software_list_name() const noexcept { return m_software_list_name.c_str(); }
@@ -301,12 +296,6 @@ private:
// working directory; persists across mounts
std::string m_working_directory;
- // info read from the hash file/software list
- std::string m_longname;
- std::string m_manufacturer;
- std::string m_year;
- u32 m_supported;
-
// flags
bool m_readonly;
bool m_created;
diff --git a/src/emu/emumem.h b/src/emu/emumem.h
index 5e419241162..b51e0a25c97 100644
--- a/src/emu/emumem.h
+++ b/src/emu/emumem.h
@@ -167,7 +167,7 @@ namespace emu::detail {
template <typename... T> struct void_wrapper { using type = void; };
template <typename... T> using void_t = typename void_wrapper<T...>::type;
-template <typename D, typename T, typename Enable = void> struct rw_device_class { };
+template <typename D, typename T, typename Enable = void> struct rw_device_class { };
template <typename D, typename T, typename Ret, typename... Params>
struct rw_device_class<D, Ret (T::*)(Params...), std::enable_if_t<std::is_constructible<D, device_t &, const char *, Ret (T::*)(Params...), const char *>::value> > { using type = T; };
diff --git a/src/emu/emuopts.cpp b/src/emu/emuopts.cpp
index ceda32dbbcc..9885b42b880 100644
--- a/src/emu/emuopts.cpp
+++ b/src/emu/emuopts.cpp
@@ -74,7 +74,7 @@ const options_entry emu_options::s_option_entries[] =
{ OPTION_WAVWRITE, nullptr, OPTION_STRING, "optional filename to write a WAV file of the current session" },
{ OPTION_SNAPNAME, "%g/%i", OPTION_STRING, "override of the default snapshot/movie naming; %g == gamename, %i == index" },
{ OPTION_SNAPSIZE, "auto", OPTION_STRING, "specify snapshot/movie resolution (<width>x<height>) or 'auto' to use minimal size " },
- { OPTION_SNAPVIEW, "internal", OPTION_STRING, "specify snapshot/movie view or 'internal' to use internal pixel-aspect views" },
+ { OPTION_SNAPVIEW, "", OPTION_STRING, "specify snapshot/movie view or 'native' to use internal pixel-aspect views" },
{ OPTION_SNAPBILINEAR, "1", OPTION_BOOLEAN, "specify if the snapshot/movie should have bilinear filtering applied" },
{ OPTION_STATENAME, "%g", OPTION_STRING, "override of the default state subfolder naming; %g == gamename" },
{ OPTION_BURNIN, "0", OPTION_BOOLEAN, "create burn-in snapshots for each screen" },
diff --git a/src/emu/inpttype.ipp b/src/emu/inpttype.ipp
index f16677cf5c9..ff7b17f757b 100644
--- a/src/emu/inpttype.ipp
+++ b/src/emu/inpttype.ipp
@@ -803,14 +803,14 @@ namespace {
#define CORE_INPUT_TYPES_UI \
CORE_INPUT_TYPES_BEGIN(ui) \
- INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_ON_SCREEN_DISPLAY,"On Screen Display", input_seq(KEYCODE_TILDE, input_seq::not_code, KEYCODE_LSHIFT) ) \
- INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_DEBUG_BREAK, "Break in Debugger", input_seq(KEYCODE_TILDE, input_seq::not_code, KEYCODE_LSHIFT) ) \
+ INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_ON_SCREEN_DISPLAY,"On Screen Display", input_seq(KEYCODE_TILDE, input_seq::not_code, KEYCODE_LSHIFT, input_seq::not_code, KEYCODE_RSHIFT) ) \
+ INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_DEBUG_BREAK, "Break in Debugger", input_seq(KEYCODE_TILDE, input_seq::not_code, KEYCODE_LSHIFT, input_seq::not_code, KEYCODE_RSHIFT) ) \
INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_CONFIGURE, "Config Menu", input_seq(KEYCODE_TAB) ) \
INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_PAUSE, "Pause", input_seq(KEYCODE_P, input_seq::not_code, KEYCODE_LSHIFT, input_seq::not_code, KEYCODE_RSHIFT) ) \
- INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_PAUSE_SINGLE, "Pause - Single Step", input_seq(KEYCODE_P, KEYCODE_LSHIFT) ) \
+ INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_PAUSE_SINGLE, "Pause - Single Step", input_seq(KEYCODE_P, KEYCODE_LSHIFT, input_seq::or_code, KEYCODE_P, KEYCODE_RSHIFT) ) \
INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_REWIND_SINGLE, "Rewind - Single Step", input_seq(KEYCODE_TILDE, KEYCODE_LSHIFT) ) \
- INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_RESET_MACHINE, "Reset Machine", input_seq(KEYCODE_F3, KEYCODE_LSHIFT) ) \
- INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_SOFT_RESET, "Soft Reset", input_seq(KEYCODE_F3, input_seq::not_code, KEYCODE_LSHIFT) ) \
+ INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_RESET_MACHINE, "Reset Machine", input_seq(KEYCODE_F3, KEYCODE_LSHIFT, input_seq::or_code, KEYCODE_F3, KEYCODE_RSHIFT) ) \
+ INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_SOFT_RESET, "Soft Reset", input_seq(KEYCODE_F3, input_seq::not_code, KEYCODE_LSHIFT, input_seq::not_code, KEYCODE_RSHIFT) ) \
INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_SHOW_GFX, "Show Gfx", input_seq(KEYCODE_F4) ) \
INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_FRAMESKIP_DEC, "Frameskip Dec", input_seq(KEYCODE_F8) ) \
INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_FRAMESKIP_INC, "Frameskip Inc", input_seq(KEYCODE_F9) ) \
@@ -830,8 +830,8 @@ namespace {
INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_END, "UI End", input_seq(KEYCODE_END) ) \
INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_PAGE_UP, "UI Page Up", input_seq(KEYCODE_PGUP) ) \
INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_PAGE_DOWN, "UI Page Down", input_seq(KEYCODE_PGDN) ) \
- INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_FOCUS_NEXT, "UI Focus Next", input_seq(KEYCODE_TAB, input_seq::not_code, KEYCODE_LSHIFT) ) \
- INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_FOCUS_PREV, "UI Focus Previous", input_seq(KEYCODE_TAB, KEYCODE_LSHIFT) ) \
+ INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_FOCUS_NEXT, "UI Focus Next", input_seq(KEYCODE_TAB, input_seq::not_code, KEYCODE_LSHIFT, input_seq::not_code, KEYCODE_RSHIFT) ) \
+ INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_FOCUS_PREV, "UI Focus Previous", input_seq(KEYCODE_TAB, KEYCODE_LSHIFT, input_seq::or_code, KEYCODE_TAB, KEYCODE_RSHIFT) ) \
INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_SELECT, "UI Select", input_seq(KEYCODE_ENTER, input_seq::or_code, JOYCODE_BUTTON1_INDEXED(0), input_seq::or_code, KEYCODE_ENTER_PAD) ) \
INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_CANCEL, "UI Cancel", input_seq(KEYCODE_ESC) ) \
INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_DISPLAY_COMMENT, "UI Display Comment", input_seq(KEYCODE_SPACE) ) \
@@ -843,6 +843,7 @@ namespace {
INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_ROTATE, "UI Rotate", input_seq(KEYCODE_R) ) \
INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_SHOW_PROFILER, "Show Profiler", input_seq(KEYCODE_F11, KEYCODE_LSHIFT) ) \
INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_TOGGLE_UI, "UI Toggle", input_seq(KEYCODE_SCRLOCK, input_seq::not_code, KEYCODE_LSHIFT) ) \
+ INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_RELEASE_POINTER, "UI Release Pointer", input_seq(KEYCODE_RCONTROL, KEYCODE_RALT) ) \
INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_PASTE, "UI Paste Text", input_seq(KEYCODE_SCRLOCK, KEYCODE_LSHIFT) ) \
INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_TOGGLE_DEBUG, "Toggle Debugger", input_seq(KEYCODE_F5) ) \
INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_SAVE_STATE, "Save State", input_seq(KEYCODE_F7, KEYCODE_LSHIFT) ) \
diff --git a/src/emu/inputdev.cpp b/src/emu/inputdev.cpp
index 4c2afdd7e7a..66a0794f6cd 100644
--- a/src/emu/inputdev.cpp
+++ b/src/emu/inputdev.cpp
@@ -31,7 +31,7 @@ public:
virtual s32 read_as_switch(input_item_modifier modifier) override;
virtual s32 read_as_relative(input_item_modifier modifier) override;
virtual s32 read_as_absolute(input_item_modifier modifier) override;
- virtual bool item_check_axis(input_item_modifier modifier) override;
+ virtual bool item_check_axis(input_item_modifier modifiers, s32 memory) override;
// steadykey helper
bool steadykey_changed();
@@ -57,7 +57,7 @@ public:
virtual s32 read_as_switch(input_item_modifier modifier) override;
virtual s32 read_as_relative(input_item_modifier modifier) override;
virtual s32 read_as_absolute(input_item_modifier modifier) override;
- virtual bool item_check_axis(input_item_modifier modifier) override;
+ virtual bool item_check_axis(input_item_modifier modifier, s32 memory) override;
};
@@ -74,7 +74,7 @@ public:
virtual s32 read_as_switch(input_item_modifier modifier) override;
virtual s32 read_as_relative(input_item_modifier modifier) override;
virtual s32 read_as_absolute(input_item_modifier modifier) override;
- virtual bool item_check_axis(input_item_modifier modifier) override;
+ virtual bool item_check_axis(input_item_modifier modifier, s32 memory) override;
};
@@ -675,16 +675,17 @@ input_device_item::input_device_item(input_device &device, const char *name, voi
m_itemid(itemid),
m_itemclass(itemclass),
m_getstate(getstate),
- m_current(0),
- m_memory(0)
+ m_current(0)
{
- // use a standard token name for know item IDs
const char *standard_token = manager().standard_token(itemid);
- if (standard_token != nullptr)
+ if (standard_token)
+ {
+ // use a standard token name for know item IDs
m_token.assign(standard_token);
-
- // otherwise, create a tokenized name
- else {
+ }
+ else
+ {
+ // otherwise, create a tokenized name
m_token.assign(name);
strmakeupper(m_token);
strdelchr(m_token, ' ');
@@ -707,19 +708,10 @@ input_device_item::~input_device_item()
// to trigger a read when polling
//-------------------------------------------------
-bool input_device_item::check_axis(input_item_modifier modifier)
+bool input_device_item::check_axis(input_item_modifier modifier, s32 memory)
{
- // if we've already reported this one, don't bother
- if (m_memory == INVALID_AXIS_VALUE)
- return false;
-
- if (item_check_axis(modifier))
- {
- m_memory = INVALID_AXIS_VALUE;
- return true;
- }
-
- return false;
+ // use INVALID_AXIS_VALUE as a short-circuit
+ return (memory != INVALID_AXIS_VALUE) && item_check_axis(modifier, memory);
}
@@ -801,7 +793,7 @@ s32 input_device_switch_item::read_as_absolute(input_item_modifier modifier)
// enough to trigger a read when polling
//-------------------------------------------------
-bool input_device_switch_item::item_check_axis(input_item_modifier modifier)
+bool input_device_switch_item::item_check_axis(input_item_modifier modifier, s32 memory)
{
return false;
}
@@ -889,12 +881,12 @@ s32 input_device_relative_item::read_as_absolute(input_item_modifier modifier)
// enough to trigger a read when polling
//-------------------------------------------------
-bool input_device_relative_item::item_check_axis(input_item_modifier modifier)
+bool input_device_relative_item::item_check_axis(input_item_modifier modifier, s32 memory)
{
- s32 curval = read_as_relative(modifier);
+ const s32 curval = read_as_relative(modifier);
// for relative axes, look for ~20 pixels movement
- return std::abs(curval - memory()) > 20 * INPUT_RELATIVE_PER_PIXEL;
+ return std::abs(curval - memory) > (20 * INPUT_RELATIVE_PER_PIXEL);
}
@@ -1002,15 +994,15 @@ s32 input_device_absolute_item::read_as_absolute(input_item_modifier modifier)
// enough to trigger a read when polling
//-------------------------------------------------
-bool input_device_absolute_item::item_check_axis(input_item_modifier modifier)
+bool input_device_absolute_item::item_check_axis(input_item_modifier modifier, s32 memory)
{
// ignore min/max for lightguns
// so the selection will not be affected by a gun going out of range
- s32 curval = read_as_absolute(modifier);
+ const s32 curval = read_as_absolute(modifier);
if (m_device.devclass() == DEVICE_CLASS_LIGHTGUN &&
(curval == INPUT_ABSOLUTE_MAX || curval == INPUT_ABSOLUTE_MIN))
return false;
// for absolute axes, look for 25% of maximum
- return std::abs(curval - memory()) > (INPUT_ABSOLUTE_MAX - INPUT_ABSOLUTE_MIN) / 4;
+ return std::abs(curval - memory) > ((INPUT_ABSOLUTE_MAX - INPUT_ABSOLUTE_MIN) / 4);
}
diff --git a/src/emu/inputdev.h b/src/emu/inputdev.h
index ecae0532be0..9c9f63c3961 100644
--- a/src/emu/inputdev.h
+++ b/src/emu/inputdev.h
@@ -105,18 +105,16 @@ public:
input_code code() const;
const char *token() const { return m_token.c_str(); }
s32 current() const { return m_current; }
- s32 memory() const { return m_memory; }
// helpers
s32 update_value();
- void set_memory(s32 value) { m_memory = value; }
- bool check_axis(input_item_modifier modifier);
+ bool check_axis(input_item_modifier modifier, s32 memory);
// readers
virtual s32 read_as_switch(input_item_modifier modifier) = 0;
virtual s32 read_as_relative(input_item_modifier modifier) = 0;
virtual s32 read_as_absolute(input_item_modifier modifier) = 0;
- virtual bool item_check_axis(input_item_modifier modifier) = 0;
+ virtual bool item_check_axis(input_item_modifier modifier, s32 memory) = 0;
protected:
// internal state
@@ -130,7 +128,6 @@ protected:
// live state
s32 m_current; // current raw value
- s32 m_memory; // "memory" value, to remember where we started during polling
};
diff --git a/src/emu/ioport.h b/src/emu/ioport.h
index 72add6abb41..376df1347be 100644
--- a/src/emu/ioport.h
+++ b/src/emu/ioport.h
@@ -358,6 +358,7 @@ enum ioport_type
IPT_UI_ROTATE,
IPT_UI_SHOW_PROFILER,
IPT_UI_TOGGLE_UI,
+ IPT_UI_RELEASE_POINTER,
IPT_UI_TOGGLE_DEBUG,
IPT_UI_PASTE,
IPT_UI_SAVE_STATE,
diff --git a/src/emu/render.cpp b/src/emu/render.cpp
index 26b7057ffb3..6b9a1e76f18 100644
--- a/src/emu/render.cpp
+++ b/src/emu/render.cpp
@@ -3366,17 +3366,21 @@ void render_manager::config_save(config_type cfg_type, util::xml::data_node *par
}
// iterate over targets
- for (int targetnum = 0; targetnum < 1000; targetnum++)
+ for (int targetnum = 0; ; ++targetnum)
{
// get this target and break when we fail
render_target *target = target_by_index(targetnum);
- if (target == nullptr)
+ if (!target)
+ {
break;
-
- // create a node
- util::xml::data_node *const targetnode = parentnode->add_child("target", nullptr);
- if (targetnode && !target->config_save(*targetnode))
- targetnode->delete_node();
+ }
+ else if (!target->hidden())
+ {
+ // create a node
+ util::xml::data_node *const targetnode = parentnode->add_child("target", nullptr);
+ if (targetnode && !target->config_save(*targetnode))
+ targetnode->delete_node();
+ }
}
// iterate over screen containers
diff --git a/src/emu/video.cpp b/src/emu/video.cpp
index 26b7fe1d2c2..3d6ffa43dea 100644
--- a/src/emu/video.cpp
+++ b/src/emu/video.cpp
@@ -120,7 +120,7 @@ video_manager::video_manager(running_machine &machine)
// create a render target for snapshots
const char *viewname = machine.options().snap_view();
- m_snap_native = !no_screens && (viewname[0] == 0 || strcmp(viewname, "native") == 0);
+ m_snap_native = !no_screens && !strcmp(viewname, "native");
if (m_snap_native)
{
@@ -426,13 +426,13 @@ void video_manager::begin_recording_screen(const std::string &filename, uint32_t
// create the emu_file
bool is_absolute_path = !filename.empty() && osd_is_absolute_path(filename);
std::unique_ptr<emu_file> movie_file = std::make_unique<emu_file>(
- is_absolute_path ? "" : machine().options().snapshot_directory(),
- OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
+ is_absolute_path ? "" : machine().options().snapshot_directory(),
+ OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
// and open the actual file
osd_file::error filerr = filename.empty()
- ? open_next(*movie_file, extension)
- : movie_file->open(filename);
+ ? open_next(*movie_file, extension)
+ : movie_file->open(filename);
if (filerr != osd_file::error::NONE)
{
osd_printf_error("Error creating movie, osd_file::error=%d\n", int(filerr));
@@ -554,16 +554,6 @@ void video_manager::postload()
//-------------------------------------------------
-// is_recording - returns whether or not any
-// screen is currently recording
-//-------------------------------------------------
-
-bool video_manager::is_recording() const
-{
- return !m_movie_recordings.empty();
-}
-
-//-------------------------------------------------
// effective_autoframeskip - return the effective
// autoframeskip value, accounting for fast
// forward
diff --git a/src/emu/video.h b/src/emu/video.h
index 0dec74fa5a7..bcd0d4e4394 100644
--- a/src/emu/video.h
+++ b/src/emu/video.h
@@ -51,7 +51,6 @@ public:
bool throttled() const { return m_throttled; }
float throttle_rate() const { return m_throttle_rate; }
bool fastforward() const { return m_fastforward; }
- bool is_recording() const;
// setters
void set_frameskip(int frameskip);
@@ -76,6 +75,7 @@ public:
int effective_frameskip() const;
// snapshots
+ render_target &snapshot_target() { return *m_snap_target; }
void save_snapshot(screen_device *screen, emu_file &file);
void save_active_screen_snapshots();
void save_input_timecode();
@@ -84,6 +84,7 @@ public:
void begin_recording(const char *name, movie_recording::format format);
void end_recording();
void add_sound_to_recording(const s16 *sound, int numsamples);
+ bool is_recording() const { return !m_movie_recordings.empty(); }
void set_timecode_enabled(bool value) { m_timecode_enabled = value; }
bool get_timecode_enabled() { return m_timecode_enabled; }
diff --git a/src/frontend/mame/iptseqpoll.cpp b/src/frontend/mame/iptseqpoll.cpp
index 145c64f033a..83883e5d970 100644
--- a/src/frontend/mame/iptseqpoll.cpp
+++ b/src/frontend/mame/iptseqpoll.cpp
@@ -11,7 +11,8 @@
input_code_poller::input_code_poller(input_manager &manager) noexcept :
- m_manager(manager)
+ m_manager(manager),
+ m_axis_memory()
{
}
@@ -24,26 +25,31 @@ input_code_poller::~input_code_poller()
void input_code_poller::reset()
{
// iterate over device classes and devices
+ m_axis_memory.clear();
for (input_device_class classno = DEVICE_CLASS_FIRST_VALID; DEVICE_CLASS_LAST_VALID >= classno; ++classno)
{
input_class &devclass(m_manager.device_class(classno));
- for (int devnum = 0; devclass.maxindex() >= devnum; ++devnum)
+ if (devclass.enabled())
{
- // fetch the device; ignore if nullptr
- input_device *const device(devclass.device(devnum));
- if (device)
+ for (int devnum = 0; devclass.maxindex() >= devnum; ++devnum)
{
- // iterate over items within each device
- for (input_item_id itemid = ITEM_ID_FIRST_VALID; device->maxitem() >= itemid; ++itemid)
+ // fetch the device; ignore if nullptr
+ input_device *const device(devclass.device(devnum));
+ if (device)
{
- // for any non-switch items, set memory to the current value
- input_device_item *const item(device->item(itemid));
- if (item && (item->itemclass() != ITEM_CLASS_SWITCH))
- item->set_memory(m_manager.code_value(item->code()));
+ // iterate over items within each device
+ for (input_item_id itemid = ITEM_ID_FIRST_VALID; device->maxitem() >= itemid; ++itemid)
+ {
+ // for any non-switch items, set memory to the current value
+ input_device_item *const item(device->item(itemid));
+ if (item && (item->itemclass() != ITEM_CLASS_SWITCH))
+ m_axis_memory.emplace_back(item, m_manager.code_value(item->code()));
+ }
}
}
}
}
+ std::sort(m_axis_memory.begin(), m_axis_memory.end());
}
@@ -62,7 +68,7 @@ void switch_code_poller_base::reset()
}
-bool switch_code_poller_base::code_pressed_once(input_code code)
+bool switch_code_poller_base::code_pressed_once(input_code code, bool moved)
{
// look for the code in the memory
bool const pressed(m_manager.code_pressed(code));
@@ -78,7 +84,7 @@ bool switch_code_poller_base::code_pressed_once(input_code code)
}
// if we get here, we were not previously pressed; if still not pressed, return false
- if (!pressed)
+ if (!pressed || !moved)
return false;
// otherwise, add the code to the memory and return true
@@ -96,31 +102,14 @@ axis_code_poller::axis_code_poller(input_manager &manager) noexcept :
input_code axis_code_poller::poll()
{
- // iterate over device classes and devices, skipping disabled classes
- for (input_device_class classno = DEVICE_CLASS_FIRST_VALID; DEVICE_CLASS_LAST_VALID >= classno; ++classno)
+ // iterate over the axis items we found
+ for (auto memory = m_axis_memory.begin(); m_axis_memory.end() != memory; ++memory)
{
- input_class &devclass(m_manager.device_class(classno));
- if (devclass.enabled())
+ input_code const code = memory->first->code();
+ if (memory->first->check_axis(code.item_modifier(), memory->second))
{
- for (int devnum = 0; devclass.maxindex() >= devnum; ++devnum)
- {
- // fetch the device; ignore if nullptr
- input_device *const device(devclass.device(devnum));
- if (device)
- {
- // iterate over items within each device
- for (input_item_id itemid = ITEM_ID_FIRST_VALID; device->maxitem() >= itemid; ++itemid)
- {
- input_device_item *const item(device->item(itemid));
- if (item && (item->itemclass() != ITEM_CLASS_SWITCH))
- {
- input_code const code = item->code();
- if (item->check_axis(code.item_modifier()))
- return code;
- }
- }
- }
- }
+ m_axis_memory.erase(memory);
+ return code;
}
}
@@ -142,64 +131,73 @@ input_code switch_code_poller::poll()
for (input_device_class classno = DEVICE_CLASS_FIRST_VALID; DEVICE_CLASS_LAST_VALID >= classno; ++classno)
{
input_class &devclass(m_manager.device_class(classno));
- if (devclass.enabled())
+ if (!devclass.enabled())
+ continue;
+
+ for (int devnum = 0; devclass.maxindex() >= devnum; ++devnum)
{
- for (int devnum = 0; devclass.maxindex() >= devnum; ++devnum)
+ // fetch the device; ignore if nullptr
+ input_device *const device(devclass.device(devnum));
+ if (!device)
+ continue;
+
+ // iterate over items within each device
+ for (input_item_id itemid = ITEM_ID_FIRST_VALID; device->maxitem() >= itemid; ++itemid)
{
- // fetch the device; ignore if nullptr
- input_device *const device(devclass.device(devnum));
- if (device)
+ input_device_item *const item(device->item(itemid));
+ if (!item)
+ continue;
+
+ input_code code = item->code();
+ if (item->itemclass() == ITEM_CLASS_SWITCH)
{
- // iterate over items within each device
- for (input_item_id itemid = ITEM_ID_FIRST_VALID; device->maxitem() >= itemid; ++itemid)
- {
- input_device_item *const item(device->item(itemid));
- if (item)
- {
- input_code code = item->code();
- if (item->itemclass() == ITEM_CLASS_SWITCH)
- {
- // item is natively a switch, poll it
- if (code_pressed_once(code))
- return code;
- }
- else if (item->check_axis(code.item_modifier()))
- {
- // poll axes digitally
- code.set_item_class(ITEM_CLASS_SWITCH);
- if ((classno == DEVICE_CLASS_JOYSTICK) && (code.item_id() == ITEM_ID_XAXIS))
- {
- // joystick X axis - check with left/right modifiers
- code.set_item_modifier(ITEM_MODIFIER_LEFT);
- if (code_pressed_once(code))
- return code;
- code.set_item_modifier(ITEM_MODIFIER_RIGHT);
- if (code_pressed_once(code))
- return code;
- }
- else if ((classno == DEVICE_CLASS_JOYSTICK) && (code.item_id() == ITEM_ID_YAXIS))
- {
- // if this is a joystick Y axis, check with up/down modifiers
- code.set_item_modifier(ITEM_MODIFIER_UP);
- if (code_pressed_once(code))
- return code;
- code.set_item_modifier(ITEM_MODIFIER_DOWN);
- if (code_pressed_once(code))
- return code;
- }
- else
- {
- // any other axis, check with pos/neg modifiers
- code.set_item_modifier(ITEM_MODIFIER_POS);
- if (code_pressed_once(code))
- return code;
- code.set_item_modifier(ITEM_MODIFIER_NEG);
- if (code_pressed_once(code))
- return code;
- }
- }
- }
- }
+ // item is natively a switch, poll it
+ if (code_pressed_once(code, true))
+ return code;
+ else
+ continue;
+ }
+
+ auto const memory(std::lower_bound(
+ m_axis_memory.begin(),
+ m_axis_memory.end(),
+ item,
+ [] (auto const &x, auto const &y) { return x.first < y; }));
+ if ((m_axis_memory.end() == memory) || (item != memory->first))
+ continue;
+
+ // poll axes digitally
+ bool const moved(item->check_axis(code.item_modifier(), memory->second));
+ code.set_item_class(ITEM_CLASS_SWITCH);
+ if ((classno == DEVICE_CLASS_JOYSTICK) && (code.item_id() == ITEM_ID_XAXIS))
+ {
+ // joystick X axis - check with left/right modifiers
+ code.set_item_modifier(ITEM_MODIFIER_LEFT);
+ if (code_pressed_once(code, moved))
+ return code;
+ code.set_item_modifier(ITEM_MODIFIER_RIGHT);
+ if (code_pressed_once(code, moved))
+ return code;
+ }
+ else if ((classno == DEVICE_CLASS_JOYSTICK) && (code.item_id() == ITEM_ID_YAXIS))
+ {
+ // if this is a joystick Y axis, check with up/down modifiers
+ code.set_item_modifier(ITEM_MODIFIER_UP);
+ if (code_pressed_once(code, moved))
+ return code;
+ code.set_item_modifier(ITEM_MODIFIER_DOWN);
+ if (code_pressed_once(code, moved))
+ return code;
+ }
+ else
+ {
+ // any other axis, check with pos/neg modifiers
+ code.set_item_modifier(ITEM_MODIFIER_POS);
+ if (code_pressed_once(code, moved))
+ return code;
+ code.set_item_modifier(ITEM_MODIFIER_NEG);
+ if (code_pressed_once(code, moved))
+ return code;
}
}
}
@@ -237,7 +235,7 @@ input_code keyboard_code_poller::poll()
if (item && (item->itemclass() == ITEM_CLASS_SWITCH))
{
input_code const code = item->code();
- if (code_pressed_once(code))
+ if (code_pressed_once(code, true))
return code;
}
}
diff --git a/src/frontend/mame/iptseqpoll.h b/src/frontend/mame/iptseqpoll.h
index 13c0d9c6484..b9f31f70477 100644
--- a/src/frontend/mame/iptseqpoll.h
+++ b/src/frontend/mame/iptseqpoll.h
@@ -12,6 +12,7 @@
#pragma once
+#include <utility>
#include <vector>
@@ -27,6 +28,7 @@ protected:
input_code_poller(input_manager &manager) noexcept;
input_manager &m_manager;
+ std::vector<std::pair<input_device_item *, s32> > m_axis_memory;
};
@@ -38,7 +40,7 @@ public:
protected:
switch_code_poller_base(input_manager &manager) noexcept;
- bool code_pressed_once(input_code code);
+ bool code_pressed_once(input_code code, bool moved);
private:
std::vector<input_code> m_switch_memory;
diff --git a/src/frontend/mame/luaengine.cpp b/src/frontend/mame/luaengine.cpp
index 4e7fb5412da..98f00a219d0 100644
--- a/src/frontend/mame/luaengine.cpp
+++ b/src/frontend/mame/luaengine.cpp
@@ -47,7 +47,7 @@ int luaopen_lsqlite3(lua_State *L);
template <typename T>
struct lua_engine::devenum
{
- devenum(device_t &d) : device(d), iter(d) { }
+ template <typename... U> devenum(device_t &d, U &&... args) : device(d), iter(d, std::forward<U>(args)...) { }
device_t &device;
T iter;
@@ -55,18 +55,85 @@ struct lua_engine::devenum
};
-template <typename T>
-struct lua_engine::object_ptr_vector_wrapper
+namespace {
+
+void do_draw_box(screen_device &sdev, float x1, float y1, float x2, float y2, uint32_t fgcolor, uint32_t bgcolor)
+{
+ float const sc_width(sdev.visible_area().width());
+ float const sc_height(sdev.visible_area().height());
+ x1 = std::min(std::max(0.0f, x1), sc_width) / sc_width;
+ y1 = std::min(std::max(0.0f, y1), sc_height) / sc_height;
+ x2 = std::min(std::max(0.0f, x2), sc_width) / sc_width;
+ y2 = std::min(std::max(0.0f, y2), sc_height) / sc_height;
+ mame_machine_manager::instance()->ui().draw_outlined_box(sdev.container(), x1, y1, x2, y2, fgcolor, bgcolor);
+}
+
+void do_draw_line(screen_device &sdev, float x1, float y1, float x2, float y2, uint32_t color)
+{
+ float const sc_width(sdev.visible_area().width());
+ float const sc_height(sdev.visible_area().height());
+ x1 = std::min(std::max(0.0f, x1), sc_width) / sc_width;
+ y1 = std::min(std::max(0.0f, y1), sc_height) / sc_height;
+ x2 = std::min(std::max(0.0f, x2), sc_width) / sc_width;
+ y2 = std::min(std::max(0.0f, y2), sc_height) / sc_height;
+ sdev.container().add_line(x1, y1, x2, y2, UI_LINE_WIDTH, rgb_t(color), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
+}
+
+void do_draw_text(lua_State *L, screen_device &sdev, sol::object &xobj, float y, const char *msg, rgb_t fgcolor, rgb_t bgcolor)
+{
+ float const sc_width(sdev.visible_area().width());
+ float const sc_height(sdev.visible_area().height());
+ auto justify = ui::text_layout::LEFT;
+ float x = 0;
+ if (xobj.is<float>())
+ {
+ x = std::min(std::max(0.0f, xobj.as<float>()), sc_width) / sc_width;
+ }
+ else if (xobj.is<char const *>())
+ {
+ char const *const justifystr(xobj.as<char const *>());
+ if (!strcmp(justifystr, "left"))
+ justify = ui::text_layout::LEFT;
+ else if (!strcmp(justifystr, "right"))
+ justify = ui::text_layout::RIGHT;
+ else if (!strcmp(justifystr, "center"))
+ justify = ui::text_layout::CENTER;
+ }
+ else
+ {
+ luaL_error(L, "Error in param 1 to draw_text");
+ return;
+ }
+ y = std::min(std::max(0.0f, y), sc_height) / sc_height;
+ mame_machine_manager::instance()->ui().draw_text_full(
+ sdev.container(),
+ msg,
+ x, y, (1.0f - x),
+ justify, ui::text_layout::WORD,
+ mame_ui_manager::OPAQUE_, fgcolor, bgcolor);
+}
+
+
+struct image_interface_formats
{
- object_ptr_vector_wrapper(std::vector<std::unique_ptr<T>> const &v) : vec(v) { }
+ image_interface_formats(device_image_interface &i) : image(i) { }
+ device_image_interface::formatlist_type const &items() { return image.formatlist(); }
+
+ static image_device_format const &unwrap(device_image_interface::formatlist_type::const_iterator const &it) { return **it; }
+ static int push_key(lua_State *L, device_image_interface::formatlist_type::const_iterator const &it, std::size_t ix) { return sol::stack::push_reference(L, (*it)->name()); }
- std::vector<std::unique_ptr<T>> const &vec;
+ device_image_interface &image;
};
+} // anonymous namespace
+
namespace sol
{
+template <> struct is_container<image_interface_formats> : std::true_type { };
+
+
sol::buffer *sol_lua_get(sol::types<buffer *>, lua_State *L, int index, sol::stack::record &tracking)
{
return new sol::buffer(stack::get<int>(L, index), L);
@@ -181,74 +248,30 @@ public:
};
-template <typename T>
-struct usertype_container<lua_engine::object_ptr_vector_wrapper<T> > : lua_engine::immutable_collection_helper<lua_engine::object_ptr_vector_wrapper<T>, std::vector<std::unique_ptr<T>> const, typename std::vector<std::unique_ptr<T>>::const_iterator>
+template <>
+struct usertype_container<image_interface_formats> : lua_engine::immutable_sequence_helper<image_interface_formats, device_image_interface::formatlist_type const, device_image_interface::formatlist_type::const_iterator>
{
private:
- static int next_pairs(lua_State *L)
- {
- typename usertype_container::indexed_iterator &i(stack::unqualified_get<user<typename usertype_container::indexed_iterator> >(L, 1));
- if (i.src.end() == i.it)
- return stack::push(L, lua_nil);
- int result;
- result = stack::push(L, i.ix + 1);
- result += stack::push_reference(L, i.it->get());
- ++i;
- return result;
- }
+ using format_list = device_image_interface::formatlist_type;
public:
- static int at(lua_State *L)
- {
- lua_engine::object_ptr_vector_wrapper<T> &self(usertype_container::get_self(L));
- std::ptrdiff_t const index(stack::unqualified_get<std::ptrdiff_t>(L, 2));
- if ((0 >= index) || (self.vec.size() < index))
- return stack::push(L, lua_nil);
- return stack::push_reference(L, self.vec[index - 1].get());
- }
-
- static int get(lua_State *L) { return at(L); }
- static int index_get(lua_State *L) { return at(L); }
-
- static int index_of(lua_State *L)
+ static int get(lua_State *L)
{
- lua_engine::object_ptr_vector_wrapper<T> &self(usertype_container::get_self(L));
- T &target(stack::unqualified_get<T>(L, 2));
- auto it(self.vec.begin());
- std::ptrdiff_t ix(0);
- while ((self.vec.end() != it) && (it->get() != &target))
- {
- ++it;
- ++ix;
- }
- if (self.vec.end() == it)
- return stack::push(L, lua_nil);
+ image_interface_formats &self(get_self(L));
+ char const *const name(stack::unqualified_get<char const *>(L));
+ auto const found(std::find_if(
+ self.image.formatlist().begin(),
+ self.image.formatlist().end(),
+ [&name] (std::unique_ptr<image_device_format> const &v) { return v->name() == name; }));
+ if (self.image.formatlist().end() != found)
+ return stack::push_reference(L, **found);
else
- return stack::push(L, ix + 1);
- }
-
- static int size(lua_State *L)
- {
- lua_engine::object_ptr_vector_wrapper<T> &self(usertype_container::get_self(L));
- return stack::push(L, self.vec.size());
- }
-
- static int empty(lua_State *L)
- {
- lua_engine::object_ptr_vector_wrapper<T> &self(usertype_container::get_self(L));
- return stack::push(L, self.vec.empty());
+ return stack::push(L, lua_nil);
}
- static int next(lua_State *L) { return stack::push(L, next_pairs); }
- static int pairs(lua_State *L) { return ipairs(L); }
-
- static int ipairs(lua_State *L)
+ static int index_get(lua_State *L)
{
- lua_engine::object_ptr_vector_wrapper<T> &self(usertype_container::get_self(L));
- stack::push(L, next_pairs);
- stack::push<user<typename usertype_container::indexed_iterator> >(L, self.vec, self.vec.begin());
- stack::push(L, lua_nil);
- return 3;
+ return get(L);
}
};
@@ -300,6 +323,40 @@ bool sol_lua_check(sol::types<osd_file::error>, lua_State *L, int index, Handler
}
+int sol_lua_push(sol::types<screen_type_enum>, lua_State *L, screen_type_enum &&value)
+{
+ switch (value)
+ {
+ case SCREEN_TYPE_INVALID: return sol::stack::push(L, "invalid");
+ case SCREEN_TYPE_RASTER: return sol::stack::push(L, "raster");
+ case SCREEN_TYPE_VECTOR: return sol::stack::push(L, "vector");
+ case SCREEN_TYPE_LCD: return sol::stack::push(L, "svg");
+ case SCREEN_TYPE_SVG: return sol::stack::push(L, "none");
+ }
+ return sol::stack::push(L, "unknown");
+}
+
+int sol_lua_push(sol::types<image_init_result>, lua_State *L, image_init_result &&value)
+{
+ switch (value)
+ {
+ case image_init_result::PASS: return sol::stack::push(L, "pass");
+ case image_init_result::FAIL: return sol::stack::push(L, "fail");
+ }
+ return sol::stack::push(L, "invalid");
+}
+
+int sol_lua_push(sol::types<image_verify_result>, lua_State *L, image_verify_result &&value)
+{
+ switch (value)
+ {
+ case image_verify_result::PASS: return sol::stack::push(L, "pass");
+ case image_verify_result::FAIL: return sol::stack::push(L, "fail");
+ }
+ return sol::stack::push(L, "invalid");
+}
+
+
//-------------------------------------------------
// process_snapshot_filename - processes a snapshot
// filename
@@ -558,14 +615,6 @@ void lua_engine::initialize()
};
- static const enum_parser<ui::text_layout::text_justify, 3> s_text_justify_parser =
- {
- { "left", ui::text_layout::LEFT },
- { "right", ui::text_layout::RIGHT },
- { "center", ui::text_layout::CENTER },
- };
-
-
static const enum_parser<int, 3> s_seek_parser =
{
{ "set", SEEK_SET },
@@ -617,6 +666,7 @@ void lua_engine::initialize()
* emu.device_enumerator(dev) - get device enumerator starting at arbitrary point in tree
* emu.screen_enumerator(dev) - get screen device enumerator starting at arbitrary point in tree
* emu.image_enumerator(dev) - get image interface enumerator starting at arbitrary point in tree
+ * emu.image_enumerator(dev) - get image interface enumerator starting at arbitrary point in tree
*/
sol::table emu = sol().create_named_table("emu");
@@ -712,9 +762,21 @@ void lua_engine::initialize()
osd_subst_env(result, str);
return result;
};
- emu["device_enumerator"] = [] (device_t &d) { return devenum<device_enumerator>(d); };
- emu["screen_enumerator"] = [] (device_t &d) { return devenum<screen_device_enumerator>(d); };
- emu["image_enumerator"] = [] (device_t &d) { return devenum<image_interface_enumerator>(d); };
+ emu["device_enumerator"] = sol::overload(
+ [] (device_t &dev) { return devenum<device_enumerator>(dev); },
+ [] (device_t &dev, int maxdepth) { return devenum<device_enumerator>(dev, maxdepth); });
+ emu["screen_enumerator"] = sol::overload(
+ [] (device_t &dev) { return devenum<screen_device_enumerator>(dev); },
+ [] (device_t &dev, int maxdepth) { return devenum<screen_device_enumerator>(dev, maxdepth); });
+ emu["cassette_enumerator"] = sol::overload(
+ [] (device_t &dev) { return devenum<cassette_device_enumerator>(dev); },
+ [] (device_t &dev, int maxdepth) { return devenum<cassette_device_enumerator>(dev, maxdepth); });
+ emu["image_enumerator"] = sol::overload(
+ [] (device_t &dev) { return devenum<image_interface_enumerator>(dev); },
+ [] (device_t &dev, int maxdepth) { return devenum<image_interface_enumerator>(dev, maxdepth); });
+ emu["slot_enumerator"] = sol::overload(
+ [] (device_t &dev) { return devenum<slot_interface_enumerator>(dev); },
+ [] (device_t &dev, int maxdepth) { return devenum<slot_interface_enumerator>(dev, maxdepth); });
/* emu_file library
@@ -1313,33 +1375,6 @@ void lua_engine::initialize()
game_driver_type["is_incomplete"] = sol::property([] (game_driver const &driver) { return (driver.flags & machine_flags::IS_INCOMPLETE) != 0; });
-/* device_t library
- *
- * manager:machine().devices[device_tag]
- *
- * device:subtag(tag) - get absolute tag relative to this device
- * device:siblingtag(tag) - get absolute tag relative to this device
- * device:memregion(tag) - get memory region
- * device:memshare(tag) - get memory share
- * device:membank(tag) - get memory bank
- * device:ioport(tag) - get I/O port
- * device:subdevice(tag) - get subdevice
- * device:siblingdevice(tag) - get sibling device
- * device:debug() - debug interface, CPUs only
- *
- * device.tag - device tree tag
- * device.basetag - last component of tag ("root" for root device)
- * device.name - device type full name
- * device.shortname - device type short name
- * device.owner - parent device (nil for root device)
- * device.configured - whether configuration is complete
- * device.started - whether the device has been started
- * device.spaces[] - device address spaces table (k=name, v=addr_space)
- * device.state[] - device state entries table (k=name, v=device_state_entry)
- * device.items[] - device save state items table (k=name, v=index)
- * device.roms[] - device rom entry table (k=name, v=rom_entry)
- */
-
auto device_type = sol().registry().new_usertype<device_t>("device", sol::no_constructor);
device_type["subtag"] = &device_t::subtag;
device_type["siblingtag"] = &device_t::siblingtag;
@@ -1349,13 +1384,6 @@ void lua_engine::initialize()
device_type["ioport"] = &device_t::ioport;
device_type["subdevice"] = static_cast<device_t *(device_t::*)(char const *) const>(&device_t::subdevice);
device_type["siblingdevice"] = static_cast<device_t *(device_t::*)(char const *) const>(&device_t::siblingdevice);
- device_type["debug"] =
- [this] (device_t &dev) -> sol::object
- {
- if (!(dev.machine().debug_flags & DEBUG_FLAG_ENABLED) || !dynamic_cast<cpu_device *>(&dev)) // debugger not enabled or not cpu
- return sol::make_object(sol(), sol::lua_nil);
- return sol::make_object(sol(), dev.debug());
- };
device_type["tag"] = sol::property(&device_t::tag);
device_type["basetag"] = sol::property(&device_t::basetag);
device_type["name"] = sol::property(&device_t::name);
@@ -1363,20 +1391,28 @@ void lua_engine::initialize()
device_type["owner"] = sol::property(&device_t::owner);
device_type["configured"] = sol::property(&device_t::configured);
device_type["started"] = sol::property(&device_t::started);
+ device_type["debug"] = sol::property(
+ [this] (device_t &dev) -> sol::object
+ {
+ if (!(dev.machine().debug_flags & DEBUG_FLAG_ENABLED) || !dynamic_cast<cpu_device *>(&dev)) // debugger not enabled or not cpu
+ return sol::make_object(sol(), sol::lua_nil);
+ return sol::make_object(sol(), dev.debug());
+ });
device_type["spaces"] = sol::property(
[this] (device_t &dev)
{
- device_memory_interface *memdev = dynamic_cast<device_memory_interface *>(&dev);
+ device_memory_interface *const memdev = dynamic_cast<device_memory_interface *>(&dev);
sol::table sp_table = sol().create_table();
- if(!memdev)
+ if (!memdev)
return sp_table;
- for(int sp = 0; sp < memdev->max_space_count(); ++sp)
+ for (int sp = 0; sp < memdev->max_space_count(); ++sp)
{
- if(memdev->has_space(sp))
+ if (memdev->has_space(sp))
sp_table[memdev->space(sp).name()] = addr_space(memdev->space(sp), *memdev);
}
return sp_table;
});
+ // FIXME: improve this
device_type["state"] = sol::property(
[this] (device_t &dev)
{
@@ -1388,41 +1424,246 @@ void lua_engine::initialize()
st_table[s->symbol()] = s.get();
return st_table;
});
+ // FIXME: turn into a wrapper - it's stupid slow to walk on every property access
+ // also, this mixes up things like RAM areas with stuff saved by the device itself, so there's potential for key conflicts
device_type["items"] = sol::property(
[this] (device_t &dev)
{
sol::table table = sol().create_table();
- std::string tag = dev.tag();
- // 10000 is enough?
- for(int i = 0; i < 10000; i++)
+ std::string const tag = dev.tag();
+ for (int i = 0; ; i++)
{
- std::string name;
- const char *item;
+ char const *item;
void *base;
uint32_t size, valcount, blockcount, stride;
item = dev.machine().save().indexed_item(i, base, size, valcount, blockcount, stride);
- if(!item)
+ if (!item)
break;
- name = &(strchr(item, '/')[1]);
- if(name.substr(0, name.find('/')) == tag)
- {
- name = name.substr(name.find('/') + 1, std::string::npos);
- table[name] = i;
- }
+
+ char const *name = &strchr(item, '/')[1];
+ if (!strncmp(tag.c_str(), name, tag.length()) && (name[tag.length()] == '/'))
+ table[name + tag.length() + 1] = i;
}
return table;
});
+ // FIXME: this is useless in its current form
device_type["roms"] = sol::property(
[this] (device_t &dev)
{
sol::table table = sol().create_table();
- for(auto rom : dev.rom_region_vector())
- if(!rom.name().empty())
+ for (auto rom : dev.rom_region_vector())
+ if (!rom.name().empty())
table[rom.name()] = rom;
return table;
});
+ auto screen_dev_type = sol().registry().new_usertype<screen_device>(
+ "screen_dev",
+ sol::no_constructor,
+ sol::base_classes, sol::bases<device_t>());
+ screen_dev_type["draw_box"] = sol::overload(
+ [] (screen_device &sdev, float x1, float y1, float x2, float y2, uint32_t fgcolor, uint32_t bgcolor)
+ { do_draw_box(sdev, x1, y1, x2, y2, fgcolor, bgcolor); },
+ [] (screen_device &sdev, float x1, float y1, float x2, float y2, uint32_t fgcolor)
+ { do_draw_box(sdev, x1, y1, x2, y2, fgcolor, mame_machine_manager::instance()->ui().colors().background_color()); },
+ [] (screen_device &sdev, float x1, float y1, float x2, float y2)
+ { auto const &colors(mame_machine_manager::instance()->ui().colors()); do_draw_box(sdev, x1, y1, x2, y2, colors.text_color(), colors.background_color()); });
+ screen_dev_type["draw_line"] = sol::overload(
+ &do_draw_line,
+ [] (screen_device &sdev, float x1, float y1, float x2, float y2)
+ { do_draw_line(sdev, x1, y1, x2, y2, mame_machine_manager::instance()->ui().colors().text_color()); });
+ screen_dev_type["draw_text"] = sol::overload(
+ [this] (screen_device &sdev, sol::object xobj, float y, const char *msg, uint32_t fgcolor, uint32_t bgcolor)
+ { do_draw_text(m_lua_state, sdev, xobj, y, msg, fgcolor, bgcolor); },
+ [this] (screen_device &sdev, sol::object xobj, float y, const char *msg, uint32_t fgcolor)
+ { do_draw_text(m_lua_state, sdev, xobj, y, msg, fgcolor, 0); },
+ [this] (screen_device &sdev, sol::object xobj, float y, const char *msg)
+ { do_draw_text(m_lua_state, sdev, xobj, y, msg, mame_machine_manager::instance()->ui().colors().text_color(), 0); });
+ screen_dev_type["orientation"] =
+ [] (screen_device &sdev)
+ {
+ uint32_t flags = sdev.orientation();
+ int rotation_angle = 0;
+ switch (flags)
+ {
+ case ORIENTATION_SWAP_XY:
+ case ORIENTATION_SWAP_XY | ORIENTATION_FLIP_X:
+ rotation_angle = 90;
+ flags ^= ORIENTATION_FLIP_X;
+ break;
+ case ORIENTATION_FLIP_Y:
+ case ORIENTATION_FLIP_X | ORIENTATION_FLIP_Y:
+ rotation_angle = 180;
+ flags ^= ORIENTATION_FLIP_X | ORIENTATION_FLIP_Y;
+ break;
+ case ORIENTATION_SWAP_XY | ORIENTATION_FLIP_Y:
+ case ORIENTATION_SWAP_XY | ORIENTATION_FLIP_X | ORIENTATION_FLIP_Y:
+ rotation_angle = 270;
+ flags ^= ORIENTATION_FLIP_Y;
+ break;
+ }
+ return std::tuple<int, bool, bool>(rotation_angle, flags & ORIENTATION_FLIP_X, flags & ORIENTATION_FLIP_Y);
+ };
+ screen_dev_type["time_until_pos"] = sol::overload(
+ [] (screen_device &sdev, int vpos) { return sdev.time_until_pos(vpos).as_double(); },
+ [] (screen_device &sdev, int vpos, int hpos) { return sdev.time_until_pos(vpos, hpos).as_double(); });
+ screen_dev_type["time_until_vblank_start"] = &screen_device::time_until_vblank_start;
+ screen_dev_type["time_until_vblank_end"] = &screen_device::time_until_vblank_end;
+ screen_dev_type["snapshot"] =
+ [this] (screen_device &sdev, char const *filename) -> sol::object
+ {
+ std::string snapstr;
+ bool is_absolute_path = false;
+ if (filename)
+ {
+ // a filename was specified; if it isn't absolute post-process it
+ snapstr = process_snapshot_filename(machine(), filename);
+ is_absolute_path = osd_is_absolute_path(snapstr);
+ }
+
+ // open the file
+ emu_file file(is_absolute_path ? "" : machine().options().snapshot_directory(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
+ osd_file::error filerr;
+ if (!snapstr.empty())
+ filerr = file.open(snapstr);
+ else
+ filerr = machine().video().open_next(file, "png");
+ if (filerr != osd_file::error::NONE)
+ return sol::make_object(sol(), filerr);
+
+ // and save the snapshot
+ machine().video().save_snapshot(&sdev, file);
+ return sol::make_object(sol(), sol::lua_nil);
+ };
+ screen_dev_type["pixel"] = [] (screen_device &sdev, s32 x, s32 y) { return sdev.pixel(x, y); };
+ screen_dev_type["pixels"] =
+ [] (screen_device &sdev, sol::this_state s)
+ {
+ lua_State *L = s;
+ const rectangle &visarea = sdev.visible_area();
+ luaL_Buffer buff;
+ int size = visarea.height() * visarea.width() * 4;
+ u32 *ptr = (u32 *)luaL_buffinitsize(L, &buff, size);
+ sdev.pixels(ptr);
+ luaL_pushresultsize(&buff, size);
+ return sol::make_reference(L, sol::stack_reference(L, -1));
+ };
+ screen_dev_type["screen_type"] = sol::property(&screen_device::screen_type);
+ screen_dev_type["width"] = sol::property([] (screen_device &sdev) { return sdev.visible_area().width(); });
+ screen_dev_type["height"] = sol::property([] (screen_device &sdev) { return sdev.visible_area().height(); });
+ screen_dev_type["refresh"] = sol::property([] (screen_device &sdev) { return ATTOSECONDS_TO_HZ(sdev.refresh_attoseconds()); });
+ screen_dev_type["refresh_attoseconds"] = sol::property([] (screen_device &sdev) { return sdev.refresh_attoseconds(); });
+ screen_dev_type["xofffset"] = sol::property(&screen_device::xoffset);
+ screen_dev_type["yofffset"] = sol::property(&screen_device::yoffset);
+ screen_dev_type["xscale"] = sol::property(&screen_device::xscale);
+ screen_dev_type["yscale"] = sol::property(&screen_device::yscale);
+ screen_dev_type["pixel_period"] = sol::property([] (screen_device &sdev) { return sdev.pixel_period().as_double(); });
+ screen_dev_type["scan_period"] = sol::property([] (screen_device &sdev) { return sdev.scan_period().as_double(); });
+ screen_dev_type["frame_period"] = sol::property([] (screen_device &sdev) { return sdev.frame_period().as_double(); });
+ screen_dev_type["frame_number"] = &screen_device::frame_number;
+ screen_dev_type["container"] = sol::property(&screen_device::container);
+
+
+ auto cass_type = sol().registry().new_usertype<cassette_image_device>(
+ "cassette",
+ sol::no_constructor,
+ sol::base_classes, sol::bases<device_t, device_image_interface>());
+ cass_type["stop"] = [] (cassette_image_device &c) { c.change_state(CASSETTE_STOPPED, CASSETTE_MASK_UISTATE); };
+ cass_type["play"] = [] (cassette_image_device &c) { c.change_state(CASSETTE_PLAY, CASSETTE_MASK_UISTATE); };
+ cass_type["record"] = [] (cassette_image_device &c) { c.change_state(CASSETTE_RECORD, CASSETTE_MASK_UISTATE); };
+ cass_type["forward"] = &cassette_image_device::go_forward;
+ cass_type["reverse"] = &cassette_image_device::go_reverse;
+ cass_type["seek"] = [] (cassette_image_device &c, double time, const char* origin) { if (c.exists()) c.seek(time, s_seek_parser(origin)); };
+ cass_type["is_stopped"] = sol::property(&cassette_image_device::is_stopped);
+ cass_type["is_playing"] = sol::property(&cassette_image_device::is_playing);
+ cass_type["is_recording"] = sol::property(&cassette_image_device::is_recording);
+ cass_type["motor_state"] = sol::property(&cassette_image_device::motor_on, &cassette_image_device::set_motor);
+ cass_type["speaker_state"] = sol::property(&cassette_image_device::speaker_on, &cassette_image_device::set_speaker);
+ cass_type["position"] = sol::property(&cassette_image_device::get_position);
+ cass_type["length"] = sol::property([] (cassette_image_device &c) { return c.exists() ? c.get_length() : 0.0; });
+
+
+ auto image_type = sol().registry().new_usertype<device_image_interface>("image", "new", sol::no_constructor);
+ image_type["load"] = &device_image_interface::load;
+ image_type["load_software"] = static_cast<image_init_result (device_image_interface::*)(const std::string &)>(&device_image_interface::load_software);
+ image_type["unload"] = &device_image_interface::unload;
+ image_type["create"] = static_cast<image_init_result (device_image_interface::*)(const std::string &)>(&device_image_interface::create);
+ image_type["display"] = &device_image_interface::call_display;
+ image_type["is_readable"] = sol::property(&device_image_interface::is_readable);
+ image_type["is_writeable"] = sol::property(&device_image_interface::is_writeable);
+ image_type["is_creatable"] = sol::property(&device_image_interface::is_creatable);
+ image_type["must_be_loaded"] = sol::property(&device_image_interface::must_be_loaded);
+ image_type["is_reset_on_load"] = sol::property(&device_image_interface::is_reset_on_load);
+ image_type["image_type_name"] = sol::property(&device_image_interface::image_type_name);
+ image_type["instance_name"] = sol::property(&device_image_interface::instance_name);
+ image_type["brief_instance_name"] = sol::property(&device_image_interface::brief_instance_name);
+ image_type["formatlist"] = sol::property([] (device_image_interface &image) { return image_interface_formats(image); });
+ image_type["exists"] = sol::property(&device_image_interface::exists);
+ image_type["readonly"] = sol::property(&device_image_interface::is_readonly);
+ image_type["filename"] = sol::property(&device_image_interface::filename);
+ image_type["crc"] = sol::property(&device_image_interface::crc);
+ image_type["loaded_through_softlist"] = sol::property(&device_image_interface::loaded_through_softlist);
+ image_type["software_list_name"] = sol::property(&device_image_interface::software_list_name);
+ image_type["software_longname"] = sol::property(
+ [] (device_image_interface &di)
+ {
+ software_info const *const si(di.software_entry());
+ return si ? si->longname().c_str() : nullptr;
+ });
+ image_type["software_publisher"] = sol::property(
+ [] (device_image_interface &di)
+ {
+ software_info const *const si(di.software_entry());
+ return si ? si->publisher().c_str() : nullptr;
+ });
+ image_type["software_year"] = sol::property(
+ [] (device_image_interface &di)
+ {
+ software_info const *const si(di.software_entry());
+ return si ? si->year().c_str() : nullptr;
+ });
+ image_type["software_parent"] = sol::property(
+ [] (device_image_interface &di)
+ {
+ software_info const *const si(di.software_entry());
+ return si ? si->parentname().c_str() : nullptr;
+ });
+ image_type["device"] = sol::property(static_cast<device_t & (device_image_interface::*)()>(&device_image_interface::device));
+
+
+ auto format_type = sol().registry().new_usertype<image_device_format>("image_format", sol::no_constructor);
+ format_type["name"] = sol::property(&image_device_format::name);
+ format_type["description"] = sol::property(&image_device_format::description);
+ format_type["extensions"] = sol::property(
+ [this] (image_device_format const &format)
+ {
+ int index = 1;
+ sol::table option_table = sol().create_table();
+ for (std::string const &ext : format.extensions())
+ option_table[index++] = ext;
+ return option_table;
+ });
+ format_type["option_spec"] = sol::property(&image_device_format::optspec);
+
+
+ auto slot_type = sol().registry().new_usertype<device_slot_interface>("slot", sol::no_constructor);
+ slot_type["fixed"] = sol::property(&device_slot_interface::fixed);
+ slot_type["has_selectable_options"] = sol::property(&device_slot_interface::has_selectable_options);
+ slot_type["default_option"] = sol::property(&device_slot_interface::default_option);
+ slot_type["options"] = sol::property([] (device_slot_interface const &slot) { return standard_tag_object_ptr_map<device_slot_interface::slot_option>(slot.option_list()); });
+ slot_type["device"] = sol::property(static_cast<device_t & (device_slot_interface::*)()>(&device_slot_interface::device));
+
+
+ auto dislot_option_type = sol().registry().new_usertype<device_slot_interface::slot_option>("dislot_option", sol::no_constructor);
+ dislot_option_type["name"] = sol::property(&device_slot_interface::slot_option::name);
+ dislot_option_type["device_fullname"] = sol::property([] (device_slot_interface::slot_option &opt) { return opt.devtype().fullname(); });
+ dislot_option_type["device_shortname"] = sol::property([] (device_slot_interface::slot_option &opt) { return opt.devtype().shortname(); });
+ dislot_option_type["selectable"] = sol::property(&device_slot_interface::slot_option::selectable);
+ dislot_option_type["default_bios"] = sol::property(static_cast<char const * (device_slot_interface::slot_option::*)() const>(&device_slot_interface::slot_option::default_bios));
+ dislot_option_type["clock"] = sol::property(static_cast<u32 (device_slot_interface::slot_option::*)() const>(&device_slot_interface::slot_option::clock));
+
+
/* parameters_manager library
*
* manager:machine():parameters()
@@ -1537,160 +1778,6 @@ void lua_engine::initialize()
sound_type.set("attenuation", sol::property(&sound_manager::attenuation, &sound_manager::set_attenuation));
-/* screen_device library
- *
- * manager:machine().screens[screen_tag]
- *
- * screen:draw_box(x1, y1, x2, y2, fillcol, linecol) - draw box from (x1, y1)-(x2, y2) colored linecol
- * filled with fillcol, color is 32bit argb
- * screen:draw_line(x1, y1, x2, y2, linecol) - draw line from (x1, y1)-(x2, y2) colored linecol
- * screen:draw_text(x || justify, y, message, [opt] fgcolor, [opt] bgcolor) - draw message at (x, y) or at line y
- * with left/right/center justification
- * screen:height() - screen height
- * screen:width() - screen width
- * screen:orientation() - screen angle, flipx, flipy
- * screen:refresh() - screen refresh rate in Hz
- * screen:refresh_attoseconds() - screen refresh rate in attoseconds
- * screen:snapshot([opt] filename) - save snap shot
- * screen:type() - screen drawing type
- * screen:frame_number() - screen frame count
- * screen:xscale() - screen x scale factor
- * screen:yscale() - screen y scale factor
- * screen:pixel(x, y) - get pixel at (x, y) as packed RGB in a u32
- * screen:pixels() - get whole screen binary bitmap as string
- * screen:time_until_pos(vpos, hpos) - get the time until this screen pos is reached
- */
-
- auto screen_dev_type = sol().registry().new_usertype<screen_device>(
- "screen_dev",
- sol::no_constructor,
- sol::base_classes, sol::bases<device_t>());
- screen_dev_type.set("container", sol::property(&screen_device::container));
- screen_dev_type.set("draw_box", [](screen_device &sdev, float x1, float y1, float x2, float y2, uint32_t bgcolor, uint32_t fgcolor) {
- int sc_width = sdev.visible_area().width();
- int sc_height = sdev.visible_area().height();
- x1 = std::min(std::max(0.0f, x1), float(sc_width-1)) / float(sc_width);
- y1 = std::min(std::max(0.0f, y1), float(sc_height-1)) / float(sc_height);
- x2 = std::min(std::max(0.0f, x2), float(sc_width-1)) / float(sc_width);
- y2 = std::min(std::max(0.0f, y2), float(sc_height-1)) / float(sc_height);
- mame_machine_manager::instance()->ui().draw_outlined_box(sdev.container(), x1, y1, x2, y2, fgcolor, bgcolor);
- });
- screen_dev_type.set("draw_line", [](screen_device &sdev, float x1, float y1, float x2, float y2, uint32_t color) {
- int sc_width = sdev.visible_area().width();
- int sc_height = sdev.visible_area().height();
- x1 = std::min(std::max(0.0f, x1), float(sc_width-1)) / float(sc_width);
- y1 = std::min(std::max(0.0f, y1), float(sc_height-1)) / float(sc_height);
- x2 = std::min(std::max(0.0f, x2), float(sc_width-1)) / float(sc_width);
- y2 = std::min(std::max(0.0f, y2), float(sc_height-1)) / float(sc_height);
- sdev.container().add_line(x1, y1, x2, y2, UI_LINE_WIDTH, rgb_t(color), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
- });
- screen_dev_type.set("draw_text", [this](screen_device &sdev, sol::object xobj, float y, const char *msg, sol::object color, sol::object bcolor) {
- int sc_width = sdev.visible_area().width();
- int sc_height = sdev.visible_area().height();
- auto justify = ui::text_layout::LEFT;
- float x = 0;
- if(xobj.is<float>())
- {
- x = std::min(std::max(0.0f, xobj.as<float>()), float(sc_width-1)) / float(sc_width);
- y = std::min(std::max(0.0f, y), float(sc_height-1)) / float(sc_height);
- }
- else if(xobj.is<const char *>())
- {
- justify = s_text_justify_parser(xobj.as<const char *>());
- }
- else
- {
- luaL_error(m_lua_state, "Error in param 1 to draw_text");
- return;
- }
- rgb_t textcolor = mame_machine_manager::instance()->ui().colors().text_color();
- rgb_t bgcolor = 0;
- if(color.is<uint32_t>())
- textcolor = rgb_t(color.as<uint32_t>());
- if(bcolor.is<uint32_t>())
- bgcolor = rgb_t(bcolor.as<uint32_t>());
- mame_machine_manager::instance()->ui().draw_text_full(sdev.container(), msg, x, y, (1.0f - x),
- justify, ui::text_layout::WORD, mame_ui_manager::OPAQUE_, textcolor, bgcolor);
- });
- screen_dev_type.set("height", [](screen_device &sdev) { return sdev.visible_area().height(); });
- screen_dev_type.set("width", [](screen_device &sdev) { return sdev.visible_area().width(); });
- screen_dev_type.set("orientation", [](screen_device &sdev) {
- uint32_t flags = sdev.orientation();
- int rotation_angle = 0;
- switch (flags)
- {
- case ORIENTATION_FLIP_X:
- rotation_angle = 0;
- break;
- case ORIENTATION_SWAP_XY:
- case ORIENTATION_SWAP_XY|ORIENTATION_FLIP_X:
- rotation_angle = 90;
- break;
- case ORIENTATION_FLIP_Y:
- case ORIENTATION_FLIP_X|ORIENTATION_FLIP_Y:
- rotation_angle = 180;
- break;
- case ORIENTATION_SWAP_XY|ORIENTATION_FLIP_Y:
- case ORIENTATION_SWAP_XY|ORIENTATION_FLIP_X|ORIENTATION_FLIP_Y:
- rotation_angle = 270;
- break;
- }
- return std::tuple<int, bool, bool>(rotation_angle, flags & ORIENTATION_FLIP_X, flags & ORIENTATION_FLIP_Y);
- });
- screen_dev_type.set("refresh", [](screen_device &sdev) { return ATTOSECONDS_TO_HZ(sdev.refresh_attoseconds()); });
- screen_dev_type.set("refresh_attoseconds", [](screen_device &sdev) { return sdev.refresh_attoseconds(); });
- screen_dev_type.set("snapshot", [this](screen_device &sdev, sol::object filename) -> sol::object {
- std::string snapstr;
- bool is_absolute_path = false;
- if (filename.is<const char *>())
- {
- // a filename was specified; if it isn't absolute postprocess it
- snapstr = process_snapshot_filename(machine(), filename.as<const char *>());
- is_absolute_path = osd_is_absolute_path(snapstr);
- }
-
- // open the file
- emu_file file(is_absolute_path ? "" : machine().options().snapshot_directory(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
- osd_file::error filerr;
- if (!snapstr.empty())
- filerr = file.open(snapstr);
- else
- filerr = machine().video().open_next(file, "png");
- if (filerr != osd_file::error::NONE)
- return sol::make_object(sol(), filerr);
-
- // and save the snapshot
- machine().video().save_snapshot(&sdev, file);
- return sol::make_object(sol(), sol::lua_nil);
- });
- screen_dev_type.set("type", [](screen_device &sdev) {
- switch (sdev.screen_type())
- {
- case SCREEN_TYPE_RASTER: return "raster"; break;
- case SCREEN_TYPE_VECTOR: return "vector"; break;
- case SCREEN_TYPE_LCD: return "lcd"; break;
- case SCREEN_TYPE_SVG: return "svg"; break;
- default: break;
- }
- return "unknown";
- });
- screen_dev_type.set("frame_number", &screen_device::frame_number);
- screen_dev_type.set("xscale", &screen_device::xscale);
- screen_dev_type.set("yscale", &screen_device::yscale);
- screen_dev_type.set("pixel", [](screen_device &sdev, float x, float y) { return sdev.pixel((s32)x, (s32)y); });
- screen_dev_type.set("pixels", [](screen_device &sdev, sol::this_state s) {
- lua_State *L = s;
- const rectangle &visarea = sdev.visible_area();
- luaL_Buffer buff;
- int size = visarea.height() * visarea.width() * 4;
- u32 *ptr = (u32 *)luaL_buffinitsize(L, &buff, size);
- sdev.pixels(ptr);
- luaL_pushresultsize(&buff, size);
- return sol::make_reference(L, sol::stack_reference(L, -1));
- });
- screen_dev_type.set("time_until_pos", [](screen_device &sdev, int vpos, int hpos) { return sdev.time_until_pos(vpos, hpos).as_double(); });
-
-
/* mame_ui_manager library
*
* manager:ui()
@@ -1799,160 +1886,6 @@ void lua_engine::initialize()
output_type.set("id_to_name", &output_manager::id_to_name);
-/* device_image_interface library
- *
- * manager:machine().images[image_type]
- *
- * image:exists()
- * image:filename() - full path to the image file
- * image:longname()
- * image:manufacturer()
- * image:year()
- * image:software_list_name()
- * image:image_type_name() - floppy/cart/cdrom/tape/hdd etc
- * image:load(filename)
- * image:load_software(softlist_name)
- * image:unload()
- * image:create()
- * image:crc()
- * image:display()
- *
- * image.device - get associated device_t
- * image.instance_name
- * image.brief_instance_name
- * image.software_parent
- * image.is_readable
- * image.is_writeable
- * image.is_creatable
- * image.is_reset_on_load
- * image.must_be_loaded
- * image.formatlist
- */
-
- auto image_type = sol().registry().new_usertype<device_image_interface>("image", "new", sol::no_constructor);
- image_type.set("exists", &device_image_interface::exists);
- image_type.set("filename", &device_image_interface::filename);
- image_type.set("longname", &device_image_interface::longname);
- image_type.set("manufacturer", &device_image_interface::manufacturer);
- image_type.set("year", &device_image_interface::year);
- image_type.set("software_list_name", &device_image_interface::software_list_name);
- image_type.set("software_parent", sol::property([](device_image_interface &di) {
- const software_info *si = di.software_entry();
- return si ? si->parentname() : "";
- }));
- image_type.set("image_type_name", &device_image_interface::image_type_name);
- image_type.set("load", &device_image_interface::load);
- image_type.set("load_software", static_cast<image_init_result (device_image_interface::*)(const std::string &)>(&device_image_interface::load_software));
- image_type.set("unload", &device_image_interface::unload);
- image_type.set("create", [](device_image_interface &di, const std::string &filename) { return di.create(filename); });
- image_type.set("crc", &device_image_interface::crc);
- image_type.set("display", [](device_image_interface &di) { return di.call_display(); });
- image_type.set("device", sol::property(static_cast<device_t & (device_image_interface::*)()>(&device_image_interface::device)));
- image_type.set("instance_name", sol::property(&device_image_interface::instance_name));
- image_type.set("brief_instance_name", sol::property(&device_image_interface::brief_instance_name));
- image_type.set("is_readable", sol::property(&device_image_interface::is_readable));
- image_type.set("is_writeable", sol::property(&device_image_interface::is_writeable));
- image_type.set("is_creatable", sol::property(&device_image_interface::is_creatable));
- image_type.set("is_reset_on_load", sol::property(&device_image_interface::is_reset_on_load));
- image_type.set("must_be_loaded", sol::property(&device_image_interface::must_be_loaded));
- image_type.set("formatlist", sol::property([](const device_image_interface &image) { return object_ptr_vector_wrapper<image_device_format>(image.formatlist()); }));
-
-
-/* image_device_format library
- *
- * manager:machine().images[tag].formatlist[index]
- *
- * format.name - name of the format (e.g. - "dsk")
- * format.description - the description of the format
- * format.extensions - all of the extensions, as an array
- * format.optspec - the option spec associated with the format
- *
- */
- auto format_type = sol().registry().new_usertype<image_device_format>("image_format", sol::no_constructor);
- format_type["name"] = sol::property(&image_device_format::name);
- format_type["description"] = sol::property(&image_device_format::description);
- format_type["optspec"] = sol::property(&image_device_format::optspec);
- format_type["extensions"] = sol::property([this](const image_device_format &format) {
- int index = 1;
- sol::table option_table = sol().create_table();
- for (const std::string &ext : format.extensions())
- option_table[index++] = ext;
- return option_table;
- });
-
-
-/* device_slot_interface library
- *
- * manager:machine().slots[slot_name]
- *
- * slot.fixed - whether this slot is fixed, and hence not selectable by the user
- * slot.has_selectable_options - does this slot have any selectable options at all?
- * slot.default_option - returns the default option if one exists
- * slot.options[] - get options table (k=name, v=device_slot_interface::slot_option)
- */
-
- auto slot_type = sol().registry().new_usertype<device_slot_interface>("slot", sol::no_constructor);
- slot_type["fixed"] = sol::property(&device_slot_interface::fixed);
- slot_type["has_selectable_options"] = sol::property(&device_slot_interface::has_selectable_options);
- slot_type["default_option"] = sol::property(&device_slot_interface::default_option);
- slot_type["options"] = sol::property([] (device_slot_interface const &slot) { return standard_tag_object_ptr_map<device_slot_interface::slot_option>(slot.option_list()); });
-
-
-/* device_slot_interface::slot_option library
- *
- * manager:machine().slots[slot_name].options[option_name]
- *
- * slot_option.selectable - is this item selectable by the user?
- * slot_option.default_bios - the default bios for this option
- * slot_option.clock - the clock speed associated with this option
- */
-
- auto dislot_option_type = sol().registry().new_usertype<device_slot_interface::slot_option>("dislot_option", sol::no_constructor);
- dislot_option_type["selectable"] = sol::property(&device_slot_interface::slot_option::selectable);
- dislot_option_type["default_bios"] = sol::property(static_cast<char const * (device_slot_interface::slot_option::*)() const>(&device_slot_interface::slot_option::default_bios));
- dislot_option_type["clock"] = sol::property(static_cast<u32 (device_slot_interface::slot_option::*)() const>(&device_slot_interface::slot_option::clock));
-
-
-/* cassette_image_device library
- *
- * manager:machine().cassettes[cass_name]
- *
- * cass:play()
- * cass:stop()
- * cass:record()
- * cass:forward() - forward play direction
- * cass:reverse() - reverse play direction
- * cass:seek(time, origin) - seek time sec from origin: "set", "cur", "end"
- *
- * cass.is_stopped
- * cass.is_playing
- * cass.is_recording
- * cass.motor_state
- * cass.speaker_state
- * cass.position
- * cass.length
- * cass.image - get the device_image_interface for this cassette device
- */
-
- auto cass_type = sol().registry().new_usertype<cassette_image_device>(
- "cassette",
- sol::no_constructor,
- sol::base_classes, sol::bases<device_t, device_image_interface>());
- cass_type["stop"] = [] (cassette_image_device &c) { c.change_state(CASSETTE_STOPPED, CASSETTE_MASK_UISTATE); };
- cass_type["play"] = [] (cassette_image_device &c) { c.change_state(CASSETTE_PLAY, CASSETTE_MASK_UISTATE); };
- cass_type["record"] = [] (cassette_image_device &c) { c.change_state(CASSETTE_RECORD, CASSETTE_MASK_UISTATE); };
- cass_type["forward"] = &cassette_image_device::go_forward;
- cass_type["reverse"] = &cassette_image_device::go_reverse;
- cass_type["seek"] = [] (cassette_image_device &c, double time, const char* origin) { if (c.exists()) c.seek(time, s_seek_parser(origin)); };
- cass_type["is_stopped"] = sol::property(&cassette_image_device::is_stopped);
- cass_type["is_playing"] = sol::property(&cassette_image_device::is_playing);
- cass_type["is_recording"] = sol::property(&cassette_image_device::is_recording);
- cass_type["motor_state"] = sol::property(&cassette_image_device::motor_on, &cassette_image_device::set_motor);
- cass_type["speaker_state"] = sol::property(&cassette_image_device::speaker_on, &cassette_image_device::set_speaker);
- cass_type["position"] = sol::property(&cassette_image_device::get_position);
- cass_type["length"] = sol::property([] (cassette_image_device &c) { return c.exists() ? c.get_length() : 0.0; });
-
-
/* mame_machine_manager library
*
* manager
diff --git a/src/frontend/mame/luaengine.h b/src/frontend/mame/luaengine.h
index b0bbf2210c3..973dfedfd89 100644
--- a/src/frontend/mame/luaengine.h
+++ b/src/frontend/mame/luaengine.h
@@ -34,11 +34,11 @@ public:
// helper structures
template <typename T> struct devenum;
template <typename T> struct simple_list_wrapper;
- template <typename T> struct object_ptr_vector_wrapper;
template <typename T> struct tag_object_ptr_map;
template <typename T> using standard_tag_object_ptr_map = tag_object_ptr_map<std::unordered_map<std::string, std::unique_ptr<T> > >;
template <typename T> struct immutable_container_helper;
template <typename T, typename C, typename I = typename C::iterator> struct immutable_collection_helper;
+ template <typename T, typename C, typename I = typename C::iterator> struct immutable_sequence_helper;
// construction/destruction
lua_engine();
diff --git a/src/frontend/mame/luaengine.ipp b/src/frontend/mame/luaengine.ipp
index 8d51fb0a092..d532b8be1b4 100644
--- a/src/frontend/mame/luaengine.ipp
+++ b/src/frontend/mame/luaengine.ipp
@@ -89,7 +89,6 @@ int sol_lua_push(sol::types<buffer *>, lua_State *L, buffer *value);
template <typename T> struct is_container<lua_engine::devenum<T> > : std::true_type { };
template <typename T> struct is_container<lua_engine::simple_list_wrapper<T> > : std::true_type { };
template <typename T> struct is_container<lua_engine::tag_object_ptr_map<T> > : std::true_type { };
-template <typename T> struct is_container<lua_engine::object_ptr_vector_wrapper<T> > : std::true_type { };
template <typename T> struct usertype_container<lua_engine::devenum<T> >;
@@ -256,7 +255,6 @@ public:
static int ipairs(lua_State *L) { return start_pairs<true>(L); }
};
-
} // namespace sol
@@ -265,10 +263,10 @@ int sol_lua_push(sol::types<osd_file::error>, lua_State *L, osd_file::error &&va
template <typename Handler>
bool sol_lua_check(sol::types<osd_file::error>, lua_State *L, int index, Handler &&handler, sol::stack::record &tracking);
-// map_handler_type customisation
+// enums to automatically convert to strings
int sol_lua_push(sol::types<map_handler_type>, lua_State *L, map_handler_type &&value);
-
-// endianness_t customisation
+int sol_lua_push(sol::types<image_init_result>, lua_State *L, image_init_result &&value);
+int sol_lua_push(sol::types<image_verify_result>, lua_State *L, image_verify_result &&value);
int sol_lua_push(sol::types<endianness_t>, lua_State *L, endianness_t &&value);
@@ -353,6 +351,83 @@ protected:
};
+template <typename T, typename C, typename I>
+struct lua_engine::immutable_sequence_helper : immutable_collection_helper<T, C, I>
+{
+protected:
+ template <bool Indexed>
+ static int next_pairs(lua_State *L)
+ {
+ auto &i(sol::stack::unqualified_get<sol::user<typename immutable_sequence_helper::indexed_iterator> >(L, 1));
+ if (i.src.end() == i.it)
+ return sol::stack::push(L, sol::lua_nil);
+ int result;
+ if constexpr (Indexed)
+ result = sol::stack::push(L, i.ix + 1);
+ else
+ result = T::push_key(L, i.it, i.ix);
+ result += sol::stack::push_reference(L, T::unwrap(i.it));
+ ++i;
+ return result;
+ }
+
+ template <bool Indexed>
+ static int start_pairs(lua_State *L)
+ {
+ T &self(immutable_sequence_helper::get_self(L));
+ sol::stack::push(L, next_pairs<Indexed>);
+ sol::stack::push<sol::user<typename immutable_sequence_helper::indexed_iterator> >(L, self.items(), self.items().begin());
+ sol::stack::push(L, sol::lua_nil);
+ return 3;
+ }
+
+public:
+ static int at(lua_State *L)
+ {
+ T &self(immutable_sequence_helper::get_self(L));
+ std::ptrdiff_t const index(sol::stack::unqualified_get<std::ptrdiff_t>(L, 2));
+ if ((0 >= index) || (self.items().size() < index))
+ return sol::stack::push(L, sol::lua_nil);
+ else
+ return sol::stack::push_reference(L, T::unwrap(std::next(self.items().begin(), index - 1)));
+ }
+
+ static int index_of(lua_State *L)
+ {
+ T &self(immutable_sequence_helper::get_self(L));
+ auto it(self.items().begin());
+ std::ptrdiff_t ix(0);
+ auto const &item(sol::stack::unqualified_get<decltype(T::unwrap(it))>(L, 2));
+ while ((self.items().end() != it) && (&item != &T::unwrap(it)))
+ {
+ ++it;
+ ++ix;
+ }
+ if (self.items().end() == it)
+ return sol::stack::push(L, sol::lua_nil);
+ else
+ return sol::stack::push(L, ix + 1);
+ }
+
+ static int size(lua_State *L)
+ {
+ T &self(immutable_sequence_helper::get_self(L));
+ return sol::stack::push(L, self.items().size());
+ }
+
+ static int empty(lua_State *L)
+ {
+ T &self(immutable_sequence_helper::get_self(L));
+ return sol::stack::push(L, self.items().empty());
+ }
+
+ static int next(lua_State *L) { return sol::stack::push(L, next_pairs<false>); }
+ static int pairs(lua_State *L) { return start_pairs<false>(L); }
+ static int ipairs(lua_State *L) { return start_pairs<true>(L); }
+};
+
+
+
struct lua_engine::addr_space
{
addr_space(address_space &s, device_memory_interface &d) : space(s), dev(d) { }
diff --git a/src/frontend/mame/luaengine_render.cpp b/src/frontend/mame/luaengine_render.cpp
index ca472dba675..b910a717561 100644
--- a/src/frontend/mame/luaengine_render.cpp
+++ b/src/frontend/mame/luaengine_render.cpp
@@ -21,6 +21,10 @@ namespace {
struct layout_file_views
{
layout_file_views(layout_file &f) : file(f) { }
+ layout_file::view_list &items() { return file.views(); }
+
+ static layout_view &unwrap(layout_file::view_list::iterator const &it) { return *it; }
+ static int push_key(lua_State *L, layout_file::view_list::iterator const &it, std::size_t ix) { return sol::stack::push_reference(L, it->unqualified_name()); }
layout_file &file;
};
@@ -29,6 +33,10 @@ struct layout_file_views
struct layout_view_items
{
layout_view_items(layout_view &v) : view(v) { }
+ layout_view::item_list &items() { return view.items(); }
+
+ static layout_view::item &unwrap(layout_view::item_list::iterator const &it) { return *it; }
+ static int push_key(lua_State *L, layout_view::item_list::iterator const &it, std::size_t ix) { return sol::stack::push(L, ix + 1); }
layout_view &view;
};
@@ -53,48 +61,9 @@ template <> struct is_container<render_target_view_names> : std::true_type { };
template <>
-struct usertype_container<layout_file_views> : lua_engine::immutable_collection_helper<layout_file_views, layout_file::view_list>
+struct usertype_container<layout_file_views> : lua_engine::immutable_sequence_helper<layout_file_views, layout_file::view_list>
{
-private:
- using view_list = layout_file::view_list;
-
- template <bool Indexed>
- static int next_pairs(lua_State *L)
- {
- indexed_iterator &i(stack::unqualified_get<user<indexed_iterator> >(L, 1));
- if (i.src.end() == i.it)
- return stack::push(L, lua_nil);
- int result;
- if constexpr (Indexed)
- result = stack::push(L, i.ix + 1);
- else
- result = stack::push_reference(L, i.it->unqualified_name());
- result += stack::push_reference(L, *i.it);
- ++i;
- return result;
- }
-
- template <bool Indexed>
- static int start_pairs(lua_State *L)
- {
- layout_file_views &self(get_self(L));
- stack::push(L, next_pairs<Indexed>);
- stack::push<user<indexed_iterator> >(L, self.file.views(), self.file.views().begin());
- stack::push(L, lua_nil);
- return 3;
- }
-
public:
- static int at(lua_State *L)
- {
- layout_file_views &self(get_self(L));
- std::ptrdiff_t const index(stack::unqualified_get<std::ptrdiff_t>(L, 2));
- if ((0 >= index) || (self.file.views().size() < index))
- return stack::push(L, lua_nil);
- else
- return stack::push_reference(L, *std::next(self.file.views().begin(), index - 1));
- }
-
static int get(lua_State *L)
{
layout_file_views &self(get_self(L));
@@ -113,72 +82,13 @@ public:
{
return get(L);
}
-
- static int index_of(lua_State *L)
- {
- layout_file_views &self(get_self(L));
- layout_view &view(stack::unqualified_get<layout_view>(L, 2));
- auto it(self.file.views().begin());
- std::ptrdiff_t ix(0);
- while ((self.file.views().end() != it) && (&view != &*it))
- {
- ++it;
- ++ix;
- }
- if (self.file.views().end() == it)
- return stack::push(L, lua_nil);
- else
- return stack::push(L, ix + 1);
- }
-
- static int size(lua_State *L)
- {
- layout_file_views &self(get_self(L));
- return stack::push(L, self.file.views().size());
- }
-
- static int empty(lua_State *L)
- {
- layout_file_views &self(get_self(L));
- return stack::push(L, self.file.views().empty());
- }
-
- static int next(lua_State *L) { return stack::push(L, next_pairs<false>); }
- static int pairs(lua_State *L) { return start_pairs<false>(L); }
- static int ipairs(lua_State *L) { return start_pairs<true>(L); }
};
template <>
-struct usertype_container<layout_view_items> : lua_engine::immutable_collection_helper<layout_view_items, layout_view::item_list>
+struct usertype_container<layout_view_items> : lua_engine::immutable_sequence_helper<layout_view_items, layout_view::item_list>
{
-private:
- using item_list = layout_view::item_list;
-
- static int next_pairs(lua_State *L)
- {
- indexed_iterator &i(stack::unqualified_get<user<indexed_iterator> >(L, 1));
- if (i.src.end() == i.it)
- return stack::push(L, lua_nil);
- int result;
- result = stack::push(L, i.ix + 1);
- result += stack::push_reference(L, *i.it);
- ++i.it;
- ++i.ix;
- return result;
- }
-
public:
- static int at(lua_State *L)
- {
- layout_view_items &self(get_self(L));
- std::ptrdiff_t const index(stack::unqualified_get<std::ptrdiff_t>(L, 2));
- if ((0 >= index) || (self.view.items().size() < index))
- return stack::push(L, lua_nil);
- else
- return stack::push_reference(L, *std::next(self.view.items().begin(), index - 1));
- }
-
static int get(lua_State *L)
{
layout_view_items &self(get_self(L));
@@ -195,50 +105,10 @@ public:
return get(L);
}
- static int index_of(lua_State *L)
- {
- layout_view_items &self(get_self(L));
- layout_view::item &item(stack::unqualified_get<layout_view::item>(L, 2));
- auto it(self.view.items().begin());
- std::ptrdiff_t ix(0);
- while ((self.view.items().end() != it) && (&item != &*it))
- {
- ++it;
- ++ix;
- }
- if (self.view.items().end() == it)
- return stack::push(L, lua_nil);
- else
- return stack::push(L, ix + 1);
- }
-
- static int size(lua_State *L)
- {
- layout_view_items &self(get_self(L));
- return stack::push(L, self.view.items().size());
- }
-
- static int empty(lua_State *L)
- {
- layout_view_items &self(get_self(L));
- return stack::push(L, self.view.items().empty());
- }
-
- static int next(lua_State *L) { return stack::push(L, next_pairs); }
-
static int pairs(lua_State *L)
{
return luaL_error(L, "sol: cannot call 'pairs' on type '%s': not iterable by ID", sol::detail::demangle<layout_view_items>().c_str());
}
-
- static int ipairs(lua_State *L)
- {
- layout_view_items &self(get_self(L));
- stack::push(L, next_pairs);
- stack::push<user<indexed_iterator> >(L, self.view.items(), self.view.items().begin());
- stack::push(L, lua_nil);
- return 3;
- }
};
diff --git a/src/frontend/mame/ui/barcode.cpp b/src/frontend/mame/ui/barcode.cpp
index fad2af9ffc6..846f2cc97c5 100644
--- a/src/frontend/mame/ui/barcode.cpp
+++ b/src/frontend/mame/ui/barcode.cpp
@@ -74,8 +74,8 @@ void menu_barcode_reader::populate(float &customtop, float &custombottom)
item_append(_("New Barcode:"), new_barcode, 0, ITEMREF_NEW_BARCODE);
// finish up the menu
- item_append(menu_item_type::SEPARATOR);
item_append(_("Enter Code"), 0, ITEMREF_ENTER_BARCODE);
+ item_append(menu_item_type::SEPARATOR);
customtop = ui().get_line_height() + 3.0f * ui().box_tb_border();
}
@@ -88,9 +88,6 @@ void menu_barcode_reader::populate(float &customtop, float &custombottom)
void menu_barcode_reader::handle()
{
- // rebuild the menu (so to update the selected device, if the user has pressed L or R)
- repopulate(reset_options::REMEMBER_POSITION);
-
// process the menu
const event *event = process(PROCESS_LR_REPEAT);
@@ -127,6 +124,14 @@ void menu_barcode_reader::handle()
}
break;
+ case IPT_UI_CLEAR:
+ if (get_selection_ref() == ITEMREF_NEW_BARCODE)
+ {
+ m_barcode_buffer.clear();
+ reset(reset_options::REMEMBER_POSITION);
+ }
+ break;
+
case IPT_SPECIAL:
if (get_selection_ref() == ITEMREF_NEW_BARCODE)
{
@@ -134,11 +139,6 @@ void menu_barcode_reader::handle()
reset(reset_options::REMEMBER_POSITION);
}
break;
-
- case IPT_UI_CANCEL:
- // reset the char buffer also in this case
- m_barcode_buffer.clear();
- break;
}
}
}
diff --git a/src/frontend/mame/ui/devctrl.h b/src/frontend/mame/ui/devctrl.h
index 1be2385a66f..ec9dc0d2928 100644
--- a/src/frontend/mame/ui/devctrl.h
+++ b/src/frontend/mame/ui/devctrl.h
@@ -84,8 +84,8 @@ int menu_device_control<DeviceType>::current_index()
template<class DeviceType>
void menu_device_control<DeviceType>::previous()
{
- // left arrow - rotate left through cassette devices
- if (m_device != nullptr)
+ // left arrow - rotate left through devices
+ if (m_device && (1 < m_count))
{
enumerator iter(machine().root_device());
int index = iter.indexof(*m_device);
@@ -94,6 +94,7 @@ void menu_device_control<DeviceType>::previous()
else
index = m_count - 1;
m_device = iter.byindex(index);
+ reset(reset_options::REMEMBER_POSITION);
}
}
@@ -106,7 +107,7 @@ template<class DeviceType>
void menu_device_control<DeviceType>::next()
{
// right arrow - rotate right through cassette devices
- if (m_device != nullptr)
+ if (m_device && (1 < m_count))
{
enumerator iter(machine().root_device());
int index = iter.indexof(*m_device);
@@ -115,6 +116,7 @@ void menu_device_control<DeviceType>::next()
else
index = 0;
m_device = iter.byindex(index);
+ reset(reset_options::REMEMBER_POSITION);
}
}
@@ -129,7 +131,7 @@ std::string menu_device_control<DeviceType>::current_display_name()
std::string display_name;
display_name.assign(current_device()->name());
if (count() > 1)
- display_name.append(string_format("%d", current_index() + 1));
+ display_name.append(string_format(" %d", current_index() + 1));
return display_name;
}
diff --git a/src/frontend/mame/ui/devopt.cpp b/src/frontend/mame/ui/devopt.cpp
index e423bfd4370..f5e73f290e0 100644
--- a/src/frontend/mame/ui/devopt.cpp
+++ b/src/frontend/mame/ui/devopt.cpp
@@ -9,12 +9,14 @@
*********************************************************************/
#include "emu.h"
-#include "ui/ui.h"
#include "ui/devopt.h"
+
+#include "ui/ui.h"
#include "romload.h"
namespace ui {
+
/*-------------------------------------------------
device_config - handle the game information
menu
diff --git a/src/frontend/mame/ui/info.cpp b/src/frontend/mame/ui/info.cpp
index 7d11970966f..3a57aac42c0 100644
--- a/src/frontend/mame/ui/info.cpp
+++ b/src/frontend/mame/ui/info.cpp
@@ -567,28 +567,30 @@ void menu_image_info::image_info(device_image_interface *image)
// if image has been loaded through softlist, let's add some more info
if (image->loaded_through_softlist())
{
- // display long filename
- item_append(image->longname(), FLAG_DISABLE, nullptr);
+ software_info const &swinfo(*image->software_entry());
- // display manufacturer and year
- item_append(string_format("%s, %s", image->manufacturer(), image->year()), FLAG_DISABLE, nullptr);
+ // display full name, publisher and year
+ item_append(swinfo.longname(), FLAG_DISABLE, nullptr);
+ item_append(string_format("%1$s, %2$s", swinfo.publisher(), swinfo.year()), FLAG_DISABLE, nullptr);
// display supported information, if available
- switch (image->supported())
+ switch (swinfo.supported())
{
- case SOFTWARE_SUPPORTED_NO:
- item_append(_("Not supported"), FLAG_DISABLE, nullptr);
- break;
- case SOFTWARE_SUPPORTED_PARTIAL:
- item_append(_("Partially supported"), FLAG_DISABLE, nullptr);
- break;
- default:
- break;
+ case SOFTWARE_SUPPORTED_NO:
+ item_append(_("Not supported"), FLAG_DISABLE, nullptr);
+ break;
+ case SOFTWARE_SUPPORTED_PARTIAL:
+ item_append(_("Partially supported"), FLAG_DISABLE, nullptr);
+ break;
+ default:
+ break;
}
}
}
else
+ {
item_append(image->brief_instance_name(), _("[empty]"), 0, nullptr);
+ }
item_append(std::string(), FLAG_DISABLE, nullptr);
}
diff --git a/src/frontend/mame/ui/inifile.cpp b/src/frontend/mame/ui/inifile.cpp
index 253c52c07f3..77dfd1088dc 100644
--- a/src/frontend/mame/ui/inifile.cpp
+++ b/src/frontend/mame/ui/inifile.cpp
@@ -298,11 +298,11 @@ void favorite_manager::add_favorite(running_machine &machine)
// start with simple stuff that can just be copied
info.shortname = software->shortname();
- info.longname = imagedev->longname();
+ info.longname = software->longname();
info.parentname = software->parentname();
- info.year = imagedev->year();
- info.publisher = imagedev->manufacturer();
- info.supported = imagedev->supported();
+ info.year = software->year();
+ info.publisher = software->publisher();
+ info.supported = software->supported();
info.part = part->name();
info.driver = &driver;
info.listname = imagedev->software_list_name();
diff --git a/src/frontend/mame/ui/mainmenu.cpp b/src/frontend/mame/ui/mainmenu.cpp
index 23a68c979c5..1051b322d99 100644
--- a/src/frontend/mame/ui/mainmenu.cpp
+++ b/src/frontend/mame/ui/mainmenu.cpp
@@ -114,7 +114,7 @@ void menu_main::populate(float &customtop, float &custombottom)
item_append(_("Slider Controls"), 0, (void *)SLIDERS);
- item_append(_("Video Options"), 0, (machine().render().target_by_index(1) != nullptr) ? (void *)VIDEO_TARGETS : (void *)VIDEO_OPTIONS);
+ item_append(_("Video Options"), 0, (machine().render().target_by_index(1) || machine().video().snapshot_target().view_name(1)) ? (void *)VIDEO_TARGETS : (void *)VIDEO_OPTIONS);
if (machine().crosshair().get_usage())
item_append(_("Crosshair Options"), 0, (void *)CROSSHAIR);
@@ -229,7 +229,7 @@ void menu_main::handle()
break;
case VIDEO_OPTIONS:
- menu::stack_push<menu_video_options>(ui(), container(), *machine().render().first_target());
+ menu::stack_push<menu_video_options>(ui(), container(), *machine().render().first_target(), false);
break;
case CROSSHAIR:
diff --git a/src/frontend/mame/ui/menu.cpp b/src/frontend/mame/ui/menu.cpp
index 068780f2b6e..4fb9616c355 100644
--- a/src/frontend/mame/ui/menu.cpp
+++ b/src/frontend/mame/ui/menu.cpp
@@ -136,7 +136,6 @@ void menu::global_state::stack_push(std::unique_ptr<menu> &&menu)
{
menu->m_parent = std::move(m_stack);
m_stack = std::move(menu);
- m_stack->reset(reset_options::SELECT_FIRST);
m_stack->machine().ui_input().reset();
}
@@ -289,26 +288,6 @@ void menu::reset(reset_options options)
m_items.clear();
m_visible_items = 0;
m_selected = 0;
-
- // add an item to return
- if (!m_parent)
- {
- item_append(_("Return to Machine"), 0, nullptr);
- }
- else if (m_parent->is_special_main_menu())
- {
- if (machine().options().ui() == emu_options::UI_SIMPLE)
- item_append(_("Exit"), 0, nullptr);
- else
- item_append(_("Exit"), FLAG_LEFT_ARROW | FLAG_RIGHT_ARROW, nullptr);
- }
- else
- {
- if (machine().options().ui() != emu_options::UI_SIMPLE && stack_has_special_main_menu())
- item_append(_("Return to Previous Menu"), FLAG_LEFT_ARROW | FLAG_RIGHT_ARROW, nullptr);
- else
- item_append(_("Return to Previous Menu"), 0, nullptr);
- }
}
@@ -403,17 +382,6 @@ void menu::item_append_on_off(const std::string &text, bool state, uint32_t flag
//-------------------------------------------------
-// repopulate - repopulate menu items
-//-------------------------------------------------
-
-void menu::repopulate(reset_options options)
-{
- reset(options);
- populate(m_customtop, m_custombottom);
-}
-
-
-//-------------------------------------------------
// process - process a menu, drawing it
// and returning any interesting events
//-------------------------------------------------
@@ -1201,8 +1169,31 @@ void menu::validate_selection(int scandir)
void menu::do_handle()
{
- if (m_items.size() < 2)
+ if (m_items.empty())
+ {
+ // add an item to return - this is a really hacky way of doing this
+ if (!m_parent)
+ {
+ item_append(_("Return to Machine"), 0, nullptr);
+ }
+ else if (m_parent->is_special_main_menu())
+ {
+ if (machine().options().ui() == emu_options::UI_SIMPLE)
+ item_append(_("Exit"), 0, nullptr);
+ else
+ item_append(_("Exit"), FLAG_LEFT_ARROW | FLAG_RIGHT_ARROW, nullptr);
+ }
+ else
+ {
+ if (machine().options().ui() != emu_options::UI_SIMPLE && stack_has_special_main_menu())
+ item_append(_("Return to Previous Menu"), FLAG_LEFT_ARROW | FLAG_RIGHT_ARROW, nullptr);
+ else
+ item_append(_("Return to Previous Menu"), 0, nullptr);
+ }
+
+ // let implementation add other items
populate(m_customtop, m_custombottom);
+ }
handle();
}
diff --git a/src/frontend/mame/ui/menu.h b/src/frontend/mame/ui/menu.h
index eacbae32609..8cd0057fc58 100644
--- a/src/frontend/mame/ui/menu.h
+++ b/src/frontend/mame/ui/menu.h
@@ -182,9 +182,6 @@ protected:
void add_cleanup_callback(cleanup_callback &&callback) { m_global_state->add_cleanup_callback(std::move(callback)); }
- // repopulate the menu items
- void repopulate(reset_options options);
-
// process a menu, drawing it and returning any interesting events
const event *process(uint32_t flags, float x0 = 0.0f, float y0 = 0.0f);
void process_parent() { m_parent->process(PROCESS_NOINPUT); }
diff --git a/src/frontend/mame/ui/miscmenu.cpp b/src/frontend/mame/ui/miscmenu.cpp
index 5de57de2ea6..dc5cc2ba9a3 100644
--- a/src/frontend/mame/ui/miscmenu.cpp
+++ b/src/frontend/mame/ui/miscmenu.cpp
@@ -176,33 +176,23 @@ void menu_network_devices::handle()
information menu
-------------------------------------------------*/
-void menu_bookkeeping::handle()
+menu_bookkeeping::menu_bookkeeping(mame_ui_manager &mui, render_container &container) : menu(mui, container)
{
- attotime curtime;
-
- /* if the time has rolled over another second, regenerate */
- curtime = machine().time();
- if (prevtime.seconds() != curtime.seconds())
- {
- prevtime = curtime;
- repopulate(reset_options::SELECT_FIRST);
- }
-
- /* process the menu */
- process(0);
}
-
-/*-------------------------------------------------
- menu_bookkeeping - handle the bookkeeping
- information menu
--------------------------------------------------*/
-menu_bookkeeping::menu_bookkeeping(mame_ui_manager &mui, render_container &container) : menu(mui, container)
+menu_bookkeeping::~menu_bookkeeping()
{
}
-menu_bookkeeping::~menu_bookkeeping()
+void menu_bookkeeping::handle()
{
+ /* process the menu */
+ process(0);
+
+ /* if the time has rolled over another second, regenerate */
+ attotime const curtime = machine().time();
+ if (prevtime.seconds() != curtime.seconds())
+ reset(reset_options::REMEMBER_POSITION);
}
void menu_bookkeeping::populate(float &customtop, float &custombottom)
@@ -212,6 +202,7 @@ void menu_bookkeeping::populate(float &customtop, float &custombottom)
int ctrnum;
/* show total time first */
+ prevtime = machine().time();
if (prevtime.seconds() >= (60 * 60))
util::stream_format(tempstring, _("Uptime: %1$d:%2$02d:%3$02d\n\n"), prevtime.seconds() / (60 * 60), (prevtime.seconds() / 60) % 60, prevtime.seconds() % 60);
else
diff --git a/src/frontend/mame/ui/tapectrl.cpp b/src/frontend/mame/ui/tapectrl.cpp
index 75d62038931..720622f0e81 100644
--- a/src/frontend/mame/ui/tapectrl.cpp
+++ b/src/frontend/mame/ui/tapectrl.cpp
@@ -116,14 +116,11 @@ void menu_tape_control::populate(float &customtop, float &custombottom)
void menu_tape_control::handle()
{
- // rebuild the menu (so to update the selected device, if the user has pressed L or R, and the tape counter)
- repopulate(reset_options::REMEMBER_POSITION);
-
// process the menu
const event *event = process(PROCESS_LR_REPEAT);
if (event != nullptr)
{
- switch(event->iptkey)
+ switch (event->iptkey)
{
case IPT_UI_LEFT:
if (event->itemref == TAPECMD_SLIDER)
@@ -155,6 +152,9 @@ void menu_tape_control::handle()
break;
}
}
+
+ // hacky way to update the tape counter by repopulating every frame
+ reset(reset_options::REMEMBER_POSITION);
}
diff --git a/src/frontend/mame/ui/videoopt.cpp b/src/frontend/mame/ui/videoopt.cpp
index ccb39306208..21ba181ecb7 100644
--- a/src/frontend/mame/ui/videoopt.cpp
+++ b/src/frontend/mame/ui/videoopt.cpp
@@ -55,6 +55,10 @@ void menu_video_targets::populate(float &customtop, float &custombottom)
// add a menu item
item_append(util::string_format(_("Screen #%d"), targetnum), 0, target);
}
+
+ // add option for snapshot target if it has multiple views
+ if (machine().video().snapshot_target().view_name(1))
+ item_append("Snapshot", 0, &machine().video().snapshot_target());
}
/*-------------------------------------------------
@@ -66,7 +70,15 @@ void menu_video_targets::handle()
{
event const *const menu_event = process(0);
if (menu_event && (menu_event->iptkey == IPT_UI_SELECT))
- menu::stack_push<menu_video_options>(ui(), container(), *reinterpret_cast<render_target *>(menu_event->itemref));
+ {
+ render_target *const target = reinterpret_cast<render_target *>(menu_event->itemref);
+ menu::stack_push<menu_video_options>(
+ ui(),
+ container(),
+ std::string(selected_item().text),
+ *target,
+ &machine().video().snapshot_target() == target);
+ }
}
@@ -75,10 +87,35 @@ void menu_video_targets::handle()
video options menu
-------------------------------------------------*/
-menu_video_options::menu_video_options(mame_ui_manager &mui, render_container &container, render_target &target)
+menu_video_options::menu_video_options(
+ mame_ui_manager &mui,
+ render_container &container,
+ render_target &target,
+ bool snapshot)
: menu(mui, container)
, m_target(target)
+ , m_title()
+ , m_show_title(false)
+ , m_snapshot(snapshot)
{
+ set_selected_index(target.view());
+ reset(reset_options::REMEMBER_POSITION);
+}
+
+menu_video_options::menu_video_options(
+ mame_ui_manager &mui,
+ render_container &container,
+ std::string &&title,
+ render_target &target,
+ bool snapshot)
+ : menu(mui, container)
+ , m_target(target)
+ , m_title(std::move(title))
+ , m_show_title(true)
+ , m_snapshot(snapshot)
+{
+ set_selected_index(target.view() + 2);
+ reset(reset_options::REMEMBER_POSITION);
}
menu_video_options::~menu_video_options()
@@ -89,6 +126,13 @@ void menu_video_options::populate(float &customtop, float &custombottom)
{
uintptr_t ref;
+ // add title if requested
+ if (m_show_title)
+ {
+ item_append(m_title, FLAG_DISABLE, nullptr);
+ item_append(menu_item_type::SEPARATOR);
+ }
+
// add items for each view
for (char const *name = m_target.view_name(ref = 0); name; name = m_target.view_name(++ref))
item_append(name, 0, reinterpret_cast<void *>(ITEM_VIEW_FIRST + ref));
@@ -127,33 +171,36 @@ void menu_video_options::populate(float &customtop, float &custombottom)
// cropping
item_append_on_off(_("Zoom to Screen Area"), m_target.zoom_to_screen(), 0, reinterpret_cast<void *>(ITEM_ZOOM));
- // uneven stretch
- switch (m_target.scale_mode())
+ if (!m_snapshot)
{
- case SCALE_FRACTIONAL:
- subtext = _("On");
- break;
+ // uneven stretch
+ switch (m_target.scale_mode())
+ {
+ case SCALE_FRACTIONAL:
+ subtext = _("On");
+ break;
+
+ case SCALE_FRACTIONAL_X:
+ subtext = _("X Only");
+ break;
- case SCALE_FRACTIONAL_X:
- subtext = _("X Only");
- break;
+ case SCALE_FRACTIONAL_Y:
+ subtext = _("Y Only");
+ break;
- case SCALE_FRACTIONAL_Y:
- subtext = _("Y Only");
- break;
+ case SCALE_FRACTIONAL_AUTO:
+ subtext = _("X or Y (Auto)");
+ break;
- case SCALE_FRACTIONAL_AUTO:
- subtext = _("X or Y (Auto)");
- break;
+ case SCALE_INTEGER:
+ subtext = _("Off");
+ break;
+ }
+ item_append(_("Non-Integer Scaling"), subtext, FLAG_LEFT_ARROW | FLAG_RIGHT_ARROW, reinterpret_cast<void *>(ITEM_UNEVENSTRETCH));
- case SCALE_INTEGER:
- subtext = _("Off");
- break;
+ // keep aspect
+ item_append_on_off(_("Maintain Aspect Ratio"), m_target.keepaspect(), 0, reinterpret_cast<void *>(ITEM_KEEPASPECT));
}
- item_append(_("Non-Integer Scaling"), subtext, FLAG_LEFT_ARROW | FLAG_RIGHT_ARROW, reinterpret_cast<void *>(ITEM_UNEVENSTRETCH));
-
- // keep aspect
- item_append_on_off(_("Keep Aspect"), m_target.keepaspect(), 0, reinterpret_cast<void *>(ITEM_KEEPASPECT));
}
@@ -164,6 +211,8 @@ void menu_video_options::populate(float &customtop, float &custombottom)
void menu_video_options::handle()
{
+ auto const lockout_popup([this] () { machine().popmessage(_("Cannot change options while recording!")); });
+ bool const snap_lockout(m_snapshot && machine().video().is_recording());
bool changed(false);
// process the menu
@@ -176,6 +225,8 @@ void menu_video_options::handle()
case ITEM_ROTATE:
if (menu_event->iptkey == IPT_UI_LEFT || menu_event->iptkey == IPT_UI_RIGHT)
{
+ if (snap_lockout)
+ return lockout_popup();
int const delta((menu_event->iptkey == IPT_UI_LEFT) ? ROT270 : ROT90);
m_target.set_orientation(orientation_add(delta, m_target.orientation()));
if (m_target.is_ui_target())
@@ -192,6 +243,8 @@ void menu_video_options::handle()
case ITEM_ZOOM:
if ((menu_event->iptkey == IPT_UI_LEFT) || (menu_event->iptkey == IPT_UI_RIGHT))
{
+ if (snap_lockout)
+ return lockout_popup();
m_target.set_zoom_to_screen(menu_event->iptkey == IPT_UI_RIGHT);
changed = true;
}
@@ -201,6 +254,8 @@ void menu_video_options::handle()
case ITEM_UNEVENSTRETCH:
if (menu_event->iptkey == IPT_UI_LEFT)
{
+ if (snap_lockout)
+ return lockout_popup();
switch (m_target.scale_mode())
{
case SCALE_FRACTIONAL:
@@ -227,6 +282,8 @@ void menu_video_options::handle()
}
else if (menu_event->iptkey == IPT_UI_RIGHT)
{
+ if (snap_lockout)
+ return lockout_popup();
switch (m_target.scale_mode())
{
case SCALE_FRACTIONAL:
@@ -257,6 +314,8 @@ void menu_video_options::handle()
case ITEM_KEEPASPECT:
if ((menu_event->iptkey == IPT_UI_LEFT) || (menu_event->iptkey == IPT_UI_RIGHT))
{
+ if (snap_lockout)
+ return lockout_popup();
m_target.set_keepaspect(menu_event->iptkey == IPT_UI_RIGHT);
changed = true;
}
@@ -266,6 +325,8 @@ void menu_video_options::handle()
default:
if (reinterpret_cast<uintptr_t>(menu_event->itemref) >= ITEM_VIEW_FIRST)
{
+ if (snap_lockout)
+ return lockout_popup();
if (menu_event->iptkey == IPT_UI_SELECT)
{
m_target.set_view(reinterpret_cast<uintptr_t>(menu_event->itemref) - ITEM_VIEW_FIRST);
@@ -274,6 +335,8 @@ void menu_video_options::handle()
}
else if (reinterpret_cast<uintptr_t>(menu_event->itemref) >= ITEM_TOGGLE_FIRST)
{
+ if (snap_lockout)
+ return lockout_popup();
if ((menu_event->iptkey == IPT_UI_LEFT) || (menu_event->iptkey == IPT_UI_RIGHT))
{
m_target.set_visibility_toggle(reinterpret_cast<uintptr_t>(menu_event->itemref) - ITEM_TOGGLE_FIRST, menu_event->iptkey == IPT_UI_RIGHT);
@@ -284,7 +347,7 @@ void menu_video_options::handle()
}
}
- /* if something changed, rebuild the menu */
+ // if something changed, rebuild the menu
if (changed)
reset(reset_options::REMEMBER_REF);
}
diff --git a/src/frontend/mame/ui/videoopt.h b/src/frontend/mame/ui/videoopt.h
index a70e7b8aa94..44a172cf8f5 100644
--- a/src/frontend/mame/ui/videoopt.h
+++ b/src/frontend/mame/ui/videoopt.h
@@ -32,7 +32,8 @@ private:
class menu_video_options : public menu
{
public:
- menu_video_options(mame_ui_manager &mui, render_container &container, render_target &target);
+ menu_video_options(mame_ui_manager &mui, render_container &container, render_target &target, bool snapshot);
+ menu_video_options(mame_ui_manager &mui, render_container &container, std::string &&title, render_target &target, bool snapshot);
virtual ~menu_video_options() override;
private:
@@ -40,6 +41,9 @@ private:
virtual void handle() override;
render_target &m_target;
+ std::string const m_title;
+ bool const m_show_title;
+ bool const m_snapshot;
};
} // namespace ui
diff --git a/src/lib/util/strformat.h b/src/lib/util/strformat.h
index 2ed90669284..0ce57606436 100644
--- a/src/lib/util/strformat.h
+++ b/src/lib/util/strformat.h
@@ -106,11 +106,12 @@
The format string type can be a pointer to a NUL-terminated string,
an array containing a NUL-terminated or non-terminated string, or a
STL contiguous container holding a string (e.g. std::string,
- std::vector or std::array). Note that NUL characters characters are
- only treated as terminators for pointers and arrays, they are
- treated as normal characters for other containers. A non-contiguous
- container (e.g. std::list or std::deque) will result in undesirable
- behaviour likely culminating in a crash.
+ std::string_view, std::vector or std::array). Note that NUL
+ characters characters are only treated as terminators for pointers
+ and arrays, they are treated as normal characters for other
+ containers. Using a non-contiguous container (e.g. std::list or
+ std::deque) will result in undesirable behaviour likely culminating
+ in a crash.
The value type of the format string and the character type of the
output stream/string need to match. You can't use a wchar_t format
@@ -184,6 +185,7 @@
#include <locale>
#include <sstream>
#include <string>
+#include <string_view>
#include <type_traits>
#include <utility>
@@ -576,10 +578,16 @@ template <typename Stream, typename T>
class format_output
{
private:
+ template <typename U> struct string_semantics
+ { static constexpr bool value = false; };
+ template <typename CharT, typename Traits, typename Allocator> struct string_semantics<std::basic_string<CharT, Traits, Allocator> >
+ { static constexpr bool value = true; };
+ template <typename CharT, typename Traits> struct string_semantics<std::basic_string_view<CharT, Traits> >
+ { static constexpr bool value = true; };
template <typename U> struct signed_integer_semantics
- { static constexpr bool value = std::is_integral<U>::value && std::is_signed<U>::value; };
+ { static constexpr bool value = std::is_integral_v<U>&& std::is_signed_v<U>; };
template <typename U> struct unsigned_integer_semantics
- { static constexpr bool value = std::is_integral<U>::value && !std::is_signed<U>::value; };
+ { static constexpr bool value = std::is_integral_v<U>&& !std::is_signed_v<U>; };
static void apply_signed(Stream &str, char16_t const &value)
{
@@ -590,19 +598,14 @@ private:
str << std::make_signed_t<std::uint_least32_t>(std::uint_least32_t(value));
}
template <typename U>
- static std::enable_if_t<std::is_same<std::make_signed_t<U>, std::make_signed_t<char> >::value> apply_signed(Stream &str, U const &value)
- {
- str << int(std::make_signed_t<U>(value));
- }
- template <typename U>
- static std::enable_if_t<!std::is_same<std::make_signed_t<U>, std::make_signed_t<char> >::value && signed_integer_semantics<U>::value> apply_signed(Stream &str, U const &value)
- {
- str << value;
- }
- template <typename U>
- static std::enable_if_t<!std::is_same<std::make_signed_t<U>, std::make_signed_t<char> >::value && unsigned_integer_semantics<U>::value> apply_signed(Stream &str, U const &value)
+ static std::enable_if_t<std::is_same_v<std::make_signed_t<U>, std::make_signed_t<char> > || std::is_integral_v<U> > apply_signed(Stream &str, U const &value)
{
- str << std::make_signed_t<U>(value);
+ if constexpr (std::is_same_v<std::make_signed_t<U>, std::make_signed_t<char> >)
+ str << int(std::make_signed_t<U>(value));
+ else if constexpr (std::is_signed_v<U>)
+ str << value;
+ else
+ str << std::make_signed_t<U>(value);
}
static void apply_unsigned(Stream &str, char16_t const &value)
@@ -614,26 +617,49 @@ private:
str << std::uint_least32_t(value);
}
template <typename U>
- static std::enable_if_t<std::is_same<std::make_unsigned_t<U>, std::make_unsigned_t<char> >::value> apply_unsigned(Stream &str, U const &value)
- {
- str << unsigned(std::make_unsigned_t<U>(value));
- }
- template <typename U>
- static std::enable_if_t<!std::is_same<std::make_unsigned_t<U>, std::make_unsigned_t<char> >::value && signed_integer_semantics<U>::value> apply_unsigned(Stream &str, U const &value)
+ static std::enable_if_t<std::is_same_v<std::make_unsigned_t<U>, std::make_unsigned_t<char> > || std::is_integral_v<U> > apply_unsigned(Stream &str, U const &value)
{
- str << std::make_unsigned_t<U>(value);
- }
- template <typename U>
- static std::enable_if_t<!std::is_same<std::make_unsigned_t<U>, std::make_unsigned_t<char> >::value && unsigned_integer_semantics<U>::value> apply_unsigned(Stream &str, U const &value)
- {
- str << value;
+ if constexpr (std::is_same_v<std::make_unsigned_t<U>, std::make_unsigned_t<char> >)
+ str << unsigned(std::make_unsigned_t<U>(value));
+ else if constexpr (std::is_signed_v<U>)
+ str << std::make_unsigned_t<U>(value);
+ else
+ str << value;
}
public:
template <typename U>
static void apply(Stream &str, format_flags const &flags, U const &value)
{
- if constexpr (signed_integer_semantics<U>::value)
+ if constexpr (string_semantics<U>::value)
+ {
+ int const precision(flags.get_precision());
+ if ((0 <= precision) && (value.size() > unsigned(precision)))
+ {
+ if constexpr (std::is_same_v<typename U::value_type, typename Stream::char_type>)
+ {
+ unsigned width(flags.get_field_width());
+ bool const pad(unsigned(precision) < width);
+ typename Stream::fmtflags const adjust(str.flags() & Stream::adjustfield);
+ if (!pad || (Stream::left == adjust)) str.write(&*value.begin(), unsigned(precision));
+ if (pad)
+ {
+ for (width -= precision; 0U < width; --width) str.put(str.fill());
+ if (Stream::left != adjust) str.write(&*value.begin(), unsigned(precision));
+ }
+ str.width(0);
+ }
+ else
+ {
+ str << value.substr(0, unsigned(precision));
+ }
+ }
+ else
+ {
+ str << value;
+ }
+ }
+ else if constexpr (signed_integer_semantics<U>::value)
{
switch (flags.get_conversion())
{
@@ -833,35 +859,6 @@ public:
str << value;
}
}
- template <typename CharT, typename Traits, typename Allocator>
- static void apply(Stream &str, format_flags const &flags, std::basic_string<CharT, Traits, Allocator> const &value)
- {
- int const precision(flags.get_precision());
- if ((0 <= precision) && (value.size() > unsigned(precision)))
- {
- if constexpr (std::is_same_v<CharT, typename Stream::char_type>)
- {
- unsigned width(flags.get_field_width());
- bool const pad(unsigned(precision) < width);
- typename Stream::fmtflags const adjust(str.flags() & Stream::adjustfield);
- if (!pad || (Stream::left == adjust)) str.write(&*value.begin(), unsigned(precision));
- if (pad)
- {
- for (width -= precision; 0U < width; --width) str.put(str.fill());
- if (Stream::left != adjust) str.write(&*value.begin(), unsigned(precision));
- }
- str.width(0);
- }
- else
- {
- str << value.substr(0, unsigned(precision));
- }
- }
- else
- {
- str << value;
- }
- }
};
template <typename Stream, typename T>
diff --git a/src/mame/drivers/goldnpkr.cpp b/src/mame/drivers/goldnpkr.cpp
index e331c4e5630..76455b87f7e 100644
--- a/src/mame/drivers/goldnpkr.cpp
+++ b/src/mame/drivers/goldnpkr.cpp
@@ -2406,8 +2406,8 @@ SW4 OFF ON OFF ON
PORT_DIPSETTING( 0x08, DEF_STR( Off ) )
PORT_DIPSETTING( 0x00, DEF_STR( On ) )
PORT_DIPNAME( 0x10, 0x00, "Minimal Hand" ) PORT_DIPLOCATION("SW2:5")
- PORT_DIPSETTING( 0x10, "2 Paar" )
- PORT_DIPSETTING( 0x00, "1 Paar" )
+ PORT_DIPSETTING( 0x10, "Two Pairs" )
+ PORT_DIPSETTING( 0x00, "High Pair" )
PORT_DIPNAME( 0x20, 0x20, "Frequency" ) PORT_DIPLOCATION("SW2:6")
PORT_DIPSETTING( 0x20, "50 Hz." )
PORT_DIPSETTING( 0x00, "60 Hz." )
@@ -2645,6 +2645,16 @@ static INPUT_PORTS_START( witchjol )
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_OTHER ) PORT_CODE(KEYCODE_6_PAD) PORT_NAME("IN0-1-8")
PORT_MODIFY("IN0-2")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_POKER_HOLD1 ) PORT_CONDITION("SW2", 0x08, EQUALS, 0x08)
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_POKER_HOLD2 ) PORT_CONDITION("SW2", 0x08, EQUALS, 0x08)
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_POKER_HOLD3 ) PORT_CONDITION("SW2", 0x08, EQUALS, 0x08)
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_POKER_HOLD4 ) PORT_CONDITION("SW2", 0x08, EQUALS, 0x08)
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_POKER_HOLD5 ) PORT_CONDITION("SW2", 0x08, EQUALS, 0x08)
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_POKER_HOLD1 ) PORT_NAME("Hold 1 / Take") PORT_CONDITION("SW2", 0x08, EQUALS, 0x00)
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_POKER_HOLD2 ) PORT_NAME("Hold 2 / Small") PORT_CONDITION("SW2", 0x08, EQUALS, 0x00)
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_POKER_HOLD3 ) PORT_NAME("Hold 3 / Bet") PORT_CONDITION("SW2", 0x08, EQUALS, 0x00)
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_POKER_HOLD4 ) PORT_NAME("Hold 4 / Small") PORT_CONDITION("SW2", 0x08, EQUALS, 0x00)
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_POKER_HOLD5 ) PORT_NAME("Hold 5 / Double Up") PORT_CONDITION("SW2", 0x08, EQUALS, 0x00)
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_OTHER ) PORT_CODE(KEYCODE_7_PAD) PORT_NAME("IN0-2-6")
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_OTHER ) PORT_CODE(KEYCODE_8_PAD) PORT_NAME("IN0-2-7")
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_OTHER ) PORT_CODE(KEYCODE_9_PAD) PORT_NAME("IN0-2-8")
@@ -2712,12 +2722,12 @@ static INPUT_PORTS_START( witchjol )
PORT_DIPNAME( 0x04, 0x04, "Game Type" ) PORT_DIPLOCATION("SW2:3")
PORT_DIPSETTING( 0x04, "Jolli Witch" )
PORT_DIPSETTING( 0x00, "Witch Card" )
- PORT_DIPNAME( 0x08, 0x08, "Taster?" ) PORT_DIPLOCATION("SW2:4")
- PORT_DIPSETTING( 0x00, "6 Taster" )
- PORT_DIPSETTING( 0x08, "12 Taster" )
+ PORT_DIPNAME( 0x08, 0x08, "Control Type" ) PORT_DIPLOCATION("SW2:4")
+ PORT_DIPSETTING( 0x00, "6-Button" )
+ PORT_DIPSETTING( 0x08, "12-Button" )
PORT_DIPNAME( 0x10, 0x00, "Minimal Hand" ) PORT_DIPLOCATION("SW2:5")
- PORT_DIPSETTING( 0x10, "2 Paar" )
- PORT_DIPSETTING( 0x00, "1 Paar" )
+ PORT_DIPSETTING( 0x10, "Two Pairs" )
+ PORT_DIPSETTING( 0x00, "High Pair" )
PORT_DIPNAME( 0x60, 0x20, "Uncommented 1" ) PORT_DIPLOCATION("SW2:6,7")
PORT_DIPSETTING( 0x60, "1 DM - 1 PKT" )
PORT_DIPSETTING( 0x20, "1 DM - 10 PKT" )
@@ -2821,11 +2831,16 @@ static INPUT_PORTS_START( wldwitch )
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_START("IN0-2")
- PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_POKER_HOLD1 ) PORT_NAME("Hold 1 / Take")
- PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_POKER_HOLD2 )
- PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_POKER_HOLD3 )
- PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_POKER_HOLD4 )
- PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_POKER_HOLD5 ) PORT_NAME("Hold 5 / Double-Up")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_POKER_HOLD1 ) PORT_CONDITION("SW2", 0x08, EQUALS, 0x08)
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_POKER_HOLD2 ) PORT_CONDITION("SW2", 0x08, EQUALS, 0x08)
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_POKER_HOLD3 ) PORT_CONDITION("SW2", 0x08, EQUALS, 0x08)
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_POKER_HOLD4 ) PORT_CONDITION("SW2", 0x08, EQUALS, 0x08)
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_POKER_HOLD5 ) PORT_CONDITION("SW2", 0x08, EQUALS, 0x08)
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_POKER_HOLD1 ) PORT_NAME("Hold 1 / Take") PORT_CONDITION("SW2", 0x08, EQUALS, 0x00)
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_POKER_HOLD2 ) PORT_NAME("Hold 2 / Small") PORT_CONDITION("SW2", 0x08, EQUALS, 0x00)
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_POKER_HOLD3 ) PORT_NAME("Hold 3 / Bet") PORT_CONDITION("SW2", 0x08, EQUALS, 0x00)
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_POKER_HOLD4 ) PORT_NAME("Hold 4 / Small") PORT_CONDITION("SW2", 0x08, EQUALS, 0x00)
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_POKER_HOLD5 ) PORT_NAME("Hold 5 / Double Up") PORT_CONDITION("SW2", 0x08, EQUALS, 0x00)
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN )
@@ -2921,11 +2936,11 @@ static INPUT_PORTS_START( wldwitch )
PORT_DIPSETTING( 0x04, "Wild Witch" )
PORT_DIPSETTING( 0x00, "Witch Game" )
PORT_DIPNAME( 0x08, 0x08, "Control Type" ) PORT_DIPLOCATION("SW2:4")
- PORT_DIPSETTING( 0x00, "6 Taster" )
- PORT_DIPSETTING( 0x08, "12 Taster" )
+ PORT_DIPSETTING( 0x00, "6-Button" )
+ PORT_DIPSETTING( 0x08, "12-Button" )
PORT_DIPNAME( 0x10, 0x00, "Minimal Hand" ) PORT_DIPLOCATION("SW2:5")
- PORT_DIPSETTING( 0x10, "2 Paar" )
- PORT_DIPSETTING( 0x00, "1 Paar" )
+ PORT_DIPSETTING( 0x10, "Two Pairs" )
+ PORT_DIPSETTING( 0x00, "High Pair" )
PORT_DIPNAME( 0x20, 0x20, "Uncommented 1" ) PORT_DIPLOCATION("SW2:6")
PORT_DIPSETTING( 0x20, "64er" )
PORT_DIPSETTING( 0x00, "128er" )
@@ -3019,8 +3034,8 @@ static INPUT_PORTS_START( wupndown )
PORT_DIPSETTING( 0x08, DEF_STR( Off ) )
PORT_DIPSETTING( 0x00, DEF_STR( On ) )
PORT_DIPNAME( 0x10, 0x00, "Minimal Hand" ) PORT_DIPLOCATION("SW2:5")
- PORT_DIPSETTING( 0x10, "2 Paar" )
- PORT_DIPSETTING( 0x00, "Hohes Paar" )
+ PORT_DIPSETTING( 0x10, "Two Pairs" )
+ PORT_DIPSETTING( 0x00, "High Pair" )
PORT_DIPNAME( 0x20, 0x20, DEF_STR( Unknown ) ) PORT_DIPLOCATION("SW2:6")
PORT_DIPSETTING( 0x20, DEF_STR( Off ) )
PORT_DIPSETTING( 0x00, DEF_STR( On ) )
@@ -3211,8 +3226,8 @@ static INPUT_PORTS_START( wtchjack )
PORT_DIPSETTING( 0x08, DEF_STR( Off ) )
PORT_DIPSETTING( 0x00, DEF_STR( On ) )
PORT_DIPNAME( 0x10, 0x00, "Minimal Hand" ) PORT_DIPLOCATION("SW2:5")
- PORT_DIPSETTING( 0x10, "2 Paar" )
- PORT_DIPSETTING( 0x00, "Hohes Paar" )
+ PORT_DIPSETTING( 0x10, "Two Pairs" )
+ PORT_DIPSETTING( 0x00, "High Pair" )
PORT_DIPNAME( 0x20, 0x20, DEF_STR( Unknown ) ) PORT_DIPLOCATION("SW2:6")
PORT_DIPSETTING( 0x20, DEF_STR( Off ) )
PORT_DIPSETTING( 0x00, DEF_STR( On ) )
diff --git a/src/mame/layout/goldnpkr.lay b/src/mame/layout/goldnpkr.lay
index 92d32275393..a5d11cbeb62 100644
--- a/src/mame/layout/goldnpkr.lay
+++ b/src/mame/layout/goldnpkr.lay
@@ -4,106 +4,74 @@ license:CC0
-->
<mamelayout version="2">
<element name="BET" defstate="0">
- <rect state="1">
- <color red="1.0" green="0.0" blue="0.0" />
- </rect>
- <rect state="0">
- <color red="0.3" green="0.0" blue="0.0" />
- </rect>
+ <rect state="1"><color red="1.0" green="0.0" blue="0.0" /></rect>
+ <rect state="0"><color red="0.3" green="0.0" blue="0.0" /></rect>
<text string="BET">
<color red="0.0" green="0.0" blue="0.0" />
- <bounds x="0" y="0.1" width="1" height="0.8" />
+ <bounds x="0.1" y="0.15" width="0.8" height="0.7" />
</text>
</element>
<element name="DEAL" defstate="0">
- <rect state="1">
- <color red="1.0" green="0.0" blue="0.0" />
- </rect>
- <rect state="0">
- <color red="0.3" green="0.0" blue="0.0" />
- </rect>
+ <rect state="1"><color red="1.0" green="0.0" blue="0.0" /></rect>
+ <rect state="0"><color red="0.3" green="0.0" blue="0.0" /></rect>
<text string="DEAL">
<color red="0.0" green="0.0" blue="0.0" />
- <bounds x="0" y="0.1" width="1" height="0.8" />
+ <bounds x="0.1" y="0.15" width="0.8" height="0.7" />
</text>
</element>
<element name="HOLD" defstate="0">
- <rect state="1">
- <color red="1.0" green="0.5" blue="0.0" />
- </rect>
- <rect state="0">
- <color red="0.3" green="0.1" blue="0.0" />
- </rect>
+ <rect state="1"><color red="1.0" green="0.5" blue="0.0" /></rect>
+ <rect state="0"><color red="0.3" green="0.1" blue="0.0" /></rect>
<text string="HOLD">
<color red="0.0" green="0.0" blue="0.0" />
- <bounds x="0" y="0.1" width="1" height="0.8" />
+ <bounds x="0.1" y="0.15" width="0.8" height="0.7" />
</text>
</element>
<element name="D-UP" defstate="0">
- <rect state="1">
- <color red="1.0" green="1.0" blue="1.0" />
- </rect>
- <rect state="0">
- <color red="0.2" green="0.2" blue="0.2" />
- </rect>
+ <rect state="1"><color red="1.0" green="1.0" blue="1.0" /></rect>
+ <rect state="0"><color red="0.2" green="0.2" blue="0.2" /></rect>
<text string="D-UP">
<color red="0.0" green="0.0" blue="0.0" />
- <bounds x="0" y="0.1" width="1" height="0.8" />
+ <bounds x="0.1" y="0.15" width="0.8" height="0.7" />
</text>
</element>
<element name="TAKE" defstate="0">
- <rect state="1">
- <color red="1.0" green="1.0" blue="1.0" />
- </rect>
- <rect state="0">
- <color red="0.2" green="0.2" blue="0.2" />
- </rect>
+ <rect state="1"><color red="1.0" green="1.0" blue="1.0" /></rect>
+ <rect state="0"><color red="0.2" green="0.2" blue="0.2" /></rect>
<text string="TAKE">
<color red="0.0" green="0.0" blue="0.0" />
- <bounds x="0" y="0.1" width="1" height="0.8" />
+ <bounds x="0.1" y="0.15" width="0.8" height="0.7" />
</text>
</element>
<element name="BIG" defstate="0">
- <rect state="1">
- <color red="1.0" green="1.0" blue="1.0" />
- </rect>
- <rect state="0">
- <color red="0.2" green="0.2" blue="0.2" />
- </rect>
+ <rect state="1"><color red="1.0" green="1.0" blue="1.0" /></rect>
+ <rect state="0"><color red="0.2" green="0.2" blue="0.2" /></rect>
<text string="BIG">
<color red="0.0" green="0.0" blue="0.0" />
- <bounds x="0" y="0.1" width="1" height="0.8" />
+ <bounds x="0.1" y="0.15" width="0.8" height="0.7" />
</text>
</element>
<element name="SMALL" defstate="0">
- <rect state="1">
- <color red="1.0" green="1.0" blue="1.0" />
- </rect>
- <rect state="0">
- <color red="0.2" green="0.2" blue="0.2" />
- </rect>
+ <rect state="1"><color red="1.0" green="1.0" blue="1.0" /></rect>
+ <rect state="0"><color red="0.2" green="0.2" blue="0.2" /></rect>
<text string="SMALL">
<color red="0.0" green="0.0" blue="0.0" />
- <bounds x="0" y="0.1" width="1" height="0.8" />
+ <bounds x="0.1" y="0.15" width="0.8" height="0.7" />
</text>
</element>
<element name="CANCEL" defstate="0">
- <rect state="1">
- <color red="1.0" green="0.0" blue="0.0" />
- </rect>
- <rect state="0">
- <color red="0.3" green="0.0" blue="0.0" />
- </rect>
+ <rect state="1"><color red="1.0" green="0.0" blue="0.0" /></rect>
+ <rect state="0"><color red="0.3" green="0.0" blue="0.0" /></rect>
<text string="CANCEL">
<color red="0.0" green="0.0" blue="0.0" />
- <bounds x="0" y="0.1" width="1" height="0.8" />
+ <bounds x="0.1" y="0.15" width="0.8" height="0.7" />
</text>
</element>
@@ -111,41 +79,43 @@ license:CC0
<screen index="0">
<bounds left="0" top="0" right="4" bottom="3" />
</screen>
- <element name="lamp0" ref="BET" inputtag="IN0-0" inputmask="0x01">
- <bounds x="3.0" y="3.45" width="0.40" height="0.24" />
- </element>
- <element name="lamp1" ref="DEAL" inputtag="IN0-0" inputmask="0x08">
- <bounds x="2.5" y="3.45" width="0.40" height="0.24" />
- </element>
+
<element name="lamp2" ref="HOLD" inputtag="IN0-2" inputmask="0x01">
- <bounds x="0.0" y="3.13" width="0.40" height="0.24" />
- </element>
- <element name="lamp3" ref="D-UP" inputtag="IN0-0" inputmask="0x04">
- <bounds x="1.5" y="3.45" width="0.40" height="0.24" />
- </element>
- <element name="lamp4" ref="BIG" inputtag="IN0-1" inputmask="0x08">
- <bounds x="0.5" y="3.45" width="0.40" height="0.24" />
+ <bounds x="0.25" y="3.13" width="0.50" height="0.24" />
</element>
<element name="lamp2" ref="HOLD" inputtag="IN0-2" inputmask="0x02">
- <bounds x="0.5" y="3.13" width="0.40" height="0.24" />
+ <bounds x="0.85" y="3.13" width="0.50" height="0.24" />
</element>
<element name="lamp2" ref="HOLD" inputtag="IN0-2" inputmask="0x04">
- <bounds x="1.0" y="3.13" width="0.40" height="0.24" />
+ <bounds x="1.45" y="3.13" width="0.50" height="0.24" />
</element>
<element name="lamp2" ref="HOLD" inputtag="IN0-2" inputmask="0x08">
- <bounds x="1.5" y="3.13" width="0.40" height="0.24" />
+ <bounds x="2.05" y="3.13" width="0.50" height="0.24" />
</element>
<element name="lamp2" ref="HOLD" inputtag="IN0-2" inputmask="0x10">
- <bounds x="2.0" y="3.13" width="0.40" height="0.24" />
+ <bounds x="2.65" y="3.13" width="0.50" height="0.24" />
+ </element>
+ <element name="lamp2" ref="CANCEL" inputtag="IN0-0" inputmask="0x10">
+ <bounds x="3.25" y="3.13" width="0.50" height="0.24" />
</element>
+
<element name="lamp3" ref="TAKE" inputtag="IN0-1" inputmask="0x04">
- <bounds x="2.0" y="3.45" width="0.40" height="0.24" />
+ <bounds x="0.25" y="3.45" width="0.50" height="0.24" />
</element>
<element name="lamp4" ref="SMALL" inputtag="IN0-1" inputmask="0x10">
- <bounds x="1.0" y="3.45" width="0.40" height="0.24" />
+ <bounds x="0.85" y="3.45" width="0.50" height="0.24" />
</element>
- <element name="lamp2" ref="CANCEL" inputtag="IN0-0" inputmask="0x10">
- <bounds x="0.0" y="3.45" width="0.40" height="0.24" />
+ <element name="lamp0" ref="BET" inputtag="IN0-0" inputmask="0x01">
+ <bounds x="1.45" y="3.45" width="0.50" height="0.24" />
+ </element>
+ <element name="lamp4" ref="BIG" inputtag="IN0-1" inputmask="0x08">
+ <bounds x="2.05" y="3.45" width="0.50" height="0.24" />
+ </element>
+ <element name="lamp3" ref="D-UP" inputtag="IN0-0" inputmask="0x04">
+ <bounds x="2.65" y="3.45" width="0.50" height="0.24" />
+ </element>
+ <element name="lamp1" ref="DEAL" inputtag="IN0-0" inputmask="0x08">
+ <bounds x="3.25" y="3.45" width="0.50" height="0.24" />
</element>
</view>
</mamelayout>