summaryrefslogtreecommitdiffstatshomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/devices/bus/a2bus/pc_xporter.cpp50
-rw-r--r--src/devices/bus/a2bus/pc_xporter.h1
-rw-r--r--src/devices/bus/intv/ecs.cpp424
-rw-r--r--src/devices/bus/intv/ecs.h20
-rw-r--r--src/devices/bus/intv_ctrl/ctrl.cpp95
-rw-r--r--src/devices/bus/intv_ctrl/ctrl.h76
-rw-r--r--src/devices/bus/intv_ctrl/ecs_ctrl.cpp448
-rw-r--r--src/devices/bus/intv_ctrl/ecs_ctrl.h171
-rw-r--r--src/devices/bus/intv_ctrl/handctrl.cpp179
-rw-r--r--src/devices/bus/intv_ctrl/handctrl.h55
-rw-r--r--src/devices/bus/snes_ctrl/joypad.h2
-rw-r--r--src/devices/bus/snes_ctrl/mouse.h2
-rw-r--r--src/devices/bus/snes_ctrl/multitap.h2
-rw-r--r--src/devices/bus/snes_ctrl/pachinko.h2
-rw-r--r--src/devices/bus/snes_ctrl/sscope.h2
-rw-r--r--src/devices/bus/snes_ctrl/twintap.h2
-rw-r--r--src/devices/bus/ti99_peb/spchsyn.cpp105
-rw-r--r--src/devices/bus/ti99_peb/spchsyn.h6
-rw-r--r--src/devices/machine/netlist.cpp11
-rw-r--r--src/devices/machine/netlist.h4
-rw-r--r--src/devices/sound/tms5220.cpp148
-rw-r--r--src/devices/sound/tms5220.h6
-rw-r--r--src/emu/debug/debugcmd.h1
-rw-r--r--src/emu/debug/debugcon.h1
-rw-r--r--src/emu/emu.h4
-rw-r--r--src/emu/luaengine.cpp12
-rw-r--r--src/emu/luaengine.h4
-rw-r--r--src/emu/machine.cpp18
-rw-r--r--src/emu/machine.h53
-rw-r--r--src/emu/machine.ipp77
-rw-r--r--src/emu/render.h4
-rw-r--r--src/emu/ui/ctrlmenu.cpp150
-rw-r--r--src/emu/ui/ctrlmenu.h41
-rw-r--r--src/emu/ui/dsplmenu.cpp223
-rw-r--r--src/emu/ui/dsplmenu.h44
-rw-r--r--src/emu/ui/menu.cpp34
-rw-r--r--src/emu/ui/menu.h26
-rw-r--r--src/emu/ui/optsmenu.cpp14
-rw-r--r--src/emu/ui/pluginopt.cpp18
-rw-r--r--src/emu/ui/selgame.cpp1
-rw-r--r--src/emu/ui/selsoft.cpp5
-rw-r--r--src/emu/ui/sliders.cpp62
-rw-r--r--src/emu/ui/sliders.h4
-rw-r--r--src/emu/ui/submenu.cpp96
-rw-r--r--src/emu/ui/submenu.h44
-rw-r--r--src/emu/ui/ui.cpp224
-rw-r--r--src/emu/ui/ui.h11
-rw-r--r--src/lib/netlist/build/makefile4
-rw-r--r--src/lib/netlist/devices/nld_system.h6
-rw-r--r--src/lib/netlist/nl_base.cpp52
-rw-r--r--src/lib/netlist/nl_base.h36
-rw-r--r--src/lib/netlist/nl_setup.cpp5
-rw-r--r--src/lib/netlist/nl_util.h41
-rw-r--r--src/lib/netlist/plib/pstate.h45
-rw-r--r--src/lib/netlist/prg/nltool.cpp9
-rw-r--r--src/lib/netlist/solver/nld_matrix_solver.h106
-rw-r--r--src/lib/netlist/solver/nld_ms_direct.h212
-rw-r--r--src/lib/netlist/solver/nld_ms_direct1.h4
-rw-r--r--src/lib/netlist/solver/nld_ms_direct2.h4
-rw-r--r--src/lib/netlist/solver/nld_ms_direct_lu.h11
-rw-r--r--src/lib/netlist/solver/nld_ms_sm.h192
-rw-r--r--src/lib/netlist/solver/nld_ms_sor_mat.h4
-rw-r--r--src/lib/netlist/solver/nld_ms_w.h190
-rw-r--r--src/lib/netlist/solver/nld_solver.cpp77
-rw-r--r--src/lib/util/chdcodec.cpp29
-rw-r--r--src/lib/util/un7z.cpp15
-rw-r--r--src/lib/util/unzip.cpp786
-rw-r--r--src/lib/util/zippath.cpp98
-rw-r--r--src/mame/audio/seibu.cpp2
-rw-r--r--src/mame/drivers/cshooter.cpp423
-rw-r--r--src/mame/drivers/fidel6502.cpp112
-rw-r--r--src/mame/drivers/fidel68k.cpp3
-rw-r--r--src/mame/drivers/fidelz80.cpp1
-rw-r--r--src/mame/drivers/harddriv.cpp84
-rw-r--r--src/mame/drivers/hh_hmcs40.cpp10
-rw-r--r--src/mame/drivers/intv.cpp120
-rw-r--r--src/mame/drivers/model2.cpp11
-rw-r--r--src/mame/drivers/neogeo_noslot.cpp26
-rw-r--r--src/mame/drivers/playch10.cpp37
-rw-r--r--src/mame/drivers/r9751.cpp35
-rw-r--r--src/mame/drivers/raiden2.cpp37
-rw-r--r--src/mame/drivers/skylncr.cpp34
-rw-r--r--src/mame/drivers/vsnes.cpp38
-rw-r--r--src/mame/includes/fidelz80.h1
-rw-r--r--src/mame/includes/intv.h10
-rw-r--r--src/mame/includes/playch10.h1
-rw-r--r--src/mame/layout/fidel_sc12.lay115
-rw-r--r--src/mame/layout/fidel_sc9.lay437
-rw-r--r--src/mame/machine/intv.cpp93
-rw-r--r--src/mame/machine/m3comm.cpp63
-rw-r--r--src/mame/machine/m3comm.h6
-rw-r--r--src/mame/mame.lst8
-rw-r--r--src/osd/modules/input/input_xinput.cpp32
-rw-r--r--src/osd/modules/input/input_xinput.h18
-rw-r--r--src/osd/modules/ipc/raw_tcp_connection.cpp29
-rw-r--r--src/osd/modules/ipc/raw_tcp_connection.h30
-rw-r--r--src/osd/modules/ipc/raw_tcp_server.cpp42
-rw-r--r--src/osd/modules/ipc/raw_tcp_server.h36
-rw-r--r--src/osd/modules/ipc/rtc_tcp_connection.cpp150
-rw-r--r--src/osd/modules/ipc/rtc_tcp_connection.h33
-rw-r--r--src/osd/modules/ipc/rtc_tcp_server.cpp42
-rw-r--r--src/osd/modules/ipc/rtc_tcp_server.h36
-rw-r--r--src/osd/modules/ipc/tcp_connection.cpp414
-rw-r--r--src/osd/modules/ipc/tcp_connection.h137
-rw-r--r--src/osd/modules/ipc/tcp_server.cpp279
-rw-r--r--src/osd/modules/ipc/tcp_server.h72
-rw-r--r--src/osd/modules/lib/osdobj_common.cpp42
-rw-r--r--src/osd/modules/lib/osdobj_common.h11
-rw-r--r--src/osd/modules/osdwindow.cpp8
-rw-r--r--src/osd/modules/osdwindow.h25
-rw-r--r--src/osd/modules/output/console.cpp32
-rw-r--r--src/osd/modules/output/network.cpp86
-rw-r--r--src/osd/modules/output/none.cpp32
-rw-r--r--src/osd/modules/output/output_module.h30
-rw-r--r--src/osd/modules/render/bgfx/chain.cpp13
-rw-r--r--src/osd/modules/render/bgfx/chain.h7
-rw-r--r--src/osd/modules/render/bgfx/chainentry.cpp3
-rw-r--r--src/osd/modules/render/bgfx/chainmanager.cpp361
-rw-r--r--src/osd/modules/render/bgfx/chainmanager.h53
-rw-r--r--src/osd/modules/render/bgfx/chainreader.cpp7
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/default/varying.def.sc4
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/hlsl/fs_blit.sc (renamed from src/osd/modules/render/bgfx/shaders/fs_blit.sc)0
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/hlsl/fs_color.sc (renamed from src/osd/modules/render/bgfx/shaders/fs_color.sc)0
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/hlsl/fs_deconverge.sc (renamed from src/osd/modules/render/bgfx/shaders/fs_deconverge.sc)0
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/hlsl/fs_defocus.sc (renamed from src/osd/modules/render/bgfx/shaders/fs_defocus.sc)0
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/hlsl/fs_distortion.sc (renamed from src/osd/modules/render/bgfx/shaders/fs_distortion.sc)0
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/hlsl/fs_ntsc_decode.sc (renamed from src/osd/modules/render/bgfx/shaders/fs_ntsc_decode.sc)0
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/hlsl/fs_ntsc_encode.sc (renamed from src/osd/modules/render/bgfx/shaders/fs_ntsc_encode.sc)0
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/hlsl/fs_phosphor.sc (renamed from src/osd/modules/render/bgfx/shaders/fs_phosphor.sc)0
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/hlsl/fs_post.sc (renamed from src/osd/modules/render/bgfx/shaders/fs_post.sc)0
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/hlsl/fs_prescale.sc (renamed from src/osd/modules/render/bgfx/shaders/fs_prescale.sc)0
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/hlsl/varying.def.sc9
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_blit.sc (renamed from src/osd/modules/render/bgfx/shaders/vs_blit.sc)0
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_color.sc (renamed from src/osd/modules/render/bgfx/shaders/vs_color.sc)0
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_deconverge.sc (renamed from src/osd/modules/render/bgfx/shaders/vs_deconverge.sc)0
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_defocus.sc (renamed from src/osd/modules/render/bgfx/shaders/vs_defocus.sc)0
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_distortion.sc (renamed from src/osd/modules/render/bgfx/shaders/vs_distortion.sc)0
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_ntsc_decode.sc (renamed from src/osd/modules/render/bgfx/shaders/vs_ntsc_decode.sc)0
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_ntsc_encode.sc (renamed from src/osd/modules/render/bgfx/shaders/vs_ntsc_encode.sc)0
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_phosphor.sc (renamed from src/osd/modules/render/bgfx/shaders/vs_phosphor.sc)0
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_post.sc (renamed from src/osd/modules/render/bgfx/shaders/vs_post.sc)0
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_prescale.sc (renamed from src/osd/modules/render/bgfx/shaders/vs_prescale.sc)0
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/unfiltered/fs_blit.sc14
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/unfiltered/varying.def.sc6
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/unfiltered/vs_blit.sc14
-rw-r--r--src/osd/modules/render/bgfx/shaders/varying.def.sc4
-rw-r--r--src/osd/modules/render/bgfx/slider.cpp4
-rw-r--r--src/osd/modules/render/bgfx/targetmanager.cpp28
-rw-r--r--src/osd/modules/render/bgfx/targetmanager.h3
-rw-r--r--src/osd/modules/render/bgfx/targetreader.cpp23
-rw-r--r--src/osd/modules/render/bgfx/targetreader.h3
-rw-r--r--src/osd/modules/render/bgfx/texturemanager.cpp35
-rw-r--r--src/osd/modules/render/bgfx/texturemanager.h1
-rw-r--r--src/osd/modules/render/bgfxutil.cpp3
-rw-r--r--src/osd/modules/render/d3d/d3dhlsl.cpp63
-rw-r--r--src/osd/modules/render/d3d/d3dhlsl.h8
-rw-r--r--src/osd/modules/render/drawbgfx.cpp11
-rw-r--r--src/osd/modules/render/drawbgfx.h10
-rw-r--r--src/osd/modules/render/drawd3d.cpp14
-rw-r--r--src/osd/modules/render/drawd3d.h1
-rw-r--r--src/osd/modules/render/sdlglcontext.h1
-rw-r--r--src/osd/modules/render/sliderdirtynotifier.h22
-rw-r--r--src/osd/modules/sync/osdsync.cpp118
-rw-r--r--src/osd/modules/sync/osdsync.h222
-rw-r--r--src/osd/modules/sync/work_osd.cpp286
-rw-r--r--src/osd/osdepend.h5
-rw-r--r--src/osd/sdl/ledutil.sh95
-rw-r--r--src/osd/sdl/osdsdl.h10
-rw-r--r--src/osd/sdl/output.cpp138
-rw-r--r--src/osd/sdl/sdlmain.cpp2
-rw-r--r--src/osd/sdl/video.cpp15
-rw-r--r--src/osd/sdl/video.h5
-rw-r--r--src/osd/sdl/watchdog.cpp9
-rw-r--r--src/osd/sdl/watchdog.h8
-rw-r--r--src/osd/sdl/window.cpp96
-rw-r--r--src/osd/sdl/window.h43
-rw-r--r--src/osd/strconv.h11
-rw-r--r--src/osd/windows/ledutil.cpp710
-rw-r--r--src/osd/windows/main.cpp17
-rw-r--r--src/osd/windows/output.cpp320
-rw-r--r--src/osd/windows/output.h86
-rw-r--r--src/osd/windows/video.cpp9
-rw-r--r--src/osd/windows/window.cpp27
-rw-r--r--src/osd/windows/winmain.cpp99
-rw-r--r--src/osd/windows/winmain.h34
185 files changed, 6486 insertions, 4835 deletions
diff --git a/src/devices/bus/a2bus/pc_xporter.cpp b/src/devices/bus/a2bus/pc_xporter.cpp
index 8159a5bd9b2..49d71fe455a 100644
--- a/src/devices/bus/a2bus/pc_xporter.cpp
+++ b/src/devices/bus/a2bus/pc_xporter.cpp
@@ -5,7 +5,7 @@
pcxporter.cpp
Implementation of the Applied Engineering PC Transporter card
- Preliminary version by R. Belmont
+ Preliminary version by R. Belmont, additional reverse-engineering by Peter Ferrie
The PC Transporter is basically a PC-XT on an Apple II card.
Features include:
@@ -37,18 +37,42 @@
plus used for general storage by the system.
RAM from 0xB0000-0xBFFFF is the CGA framebuffer as usual.
+ C800-CBFF?: RAM, used as scratchpad space by the software
CF00: PC memory pointer (bits 0-7)
CF01: PC memory pointer (bits 8-15)
CF02: PC memory pointer (bits 16-23)
CF03: read/write PC memory at the pointer and increment the pointer
CF04: read/write PC memory at the pointer and *don't* increment the pointer
+ CF2C: CGA 6845 register select (port 3D0/3D2/3D4/3D6)
+ CF2D: CGA 6845 data read/write (port 3D1/3D3/3D5/3D7)
+ CF2E: CGA mode select (port 3D8)
+ CF2F: CGA color select (port 3D9)
TODO:
- - A2 probably also can access the V30's I/O space: where's that at? CF0E/CF0F
- are suspects...
+ - What's going on at CF0E/CF0F?
+ - How is the V30 started/stopped?
- There's likely A2 ROM at CnXX and C800-CBFF to support the "Slinky" memory
expansion card emulation function inside one of the custom ASICs. Need to
dump this...
+
+ The final stages before the software settles into its loop are:
+
+ 20 to C800 at cf30
+ 00 to C800 at cf31
+ 12 to C800 at cf2b
+ 21 to C800 at cf25
+ 33 to C800 at cf24
+ 80 to C800 at cf31
+ 20 to C800 at cf30
+ loop:
+ Read $C800 at cf36
+ Read $C800 at cf31
+ Read $C800 at cf31
+ Read $C800 at cf36
+ Read $C800 at cf31
+ Read $C800 at cf31
+ 80 to C800 at cf31
+ loop end: (return to loop)
*********************************************************************/
@@ -176,7 +200,7 @@ UINT8 a2bus_pcxporter_device::read_c800(address_space &space, UINT16 offset)
if (offset < 0x400)
{
- return 0xff;
+ return m_c800_ram[offset];
}
else
{
@@ -195,12 +219,20 @@ UINT8 a2bus_pcxporter_device::read_c800(address_space &space, UINT16 offset)
case 0x703: // read with increment
rv = m_ram[m_offset];
- m_offset++;
+ // don't increment if the debugger's reading
+ if (!space.debugger_access())
+ {
+ m_offset++;
+ }
return rv;
case 0x704: // read w/o increment
rv = m_ram[m_offset];
- return rv;
+ return rv;
+
+ default:
+ printf("Read $C800 at %x\n", offset + 0xc800);
+ break;
}
return m_regs[offset];
@@ -214,6 +246,7 @@ void a2bus_pcxporter_device::write_c800(address_space &space, UINT16 offset, UIN
{
if (offset < 0x400)
{
+ m_c800_ram[offset] = data;
}
else
{
@@ -245,6 +278,11 @@ void a2bus_pcxporter_device::write_c800(address_space &space, UINT16 offset, UIN
case 0x704: // write w/o increment
m_ram[m_offset] = data;
break;
+
+ case 0x72c: // CGA 6845 register select
+ case 0x72d: // CGA 6845 data read/write
+ case 0x72e: // CGA mode select
+ break;
default:
printf("%02x to C800 at %x\n", data, offset + 0xc800);
diff --git a/src/devices/bus/a2bus/pc_xporter.h b/src/devices/bus/a2bus/pc_xporter.h
index f7359de699a..36675c09c04 100644
--- a/src/devices/bus/a2bus/pc_xporter.h
+++ b/src/devices/bus/a2bus/pc_xporter.h
@@ -44,6 +44,7 @@ protected:
private:
UINT8 m_ram[768*1024];
+ UINT8 m_c800_ram[0x400];
UINT8 m_regs[0x400];
UINT32 m_offset;
};
diff --git a/src/devices/bus/intv/ecs.cpp b/src/devices/bus/intv/ecs.cpp
index b9da2d9803b..bbee4f3074b 100644
--- a/src/devices/bus/intv/ecs.cpp
+++ b/src/devices/bus/intv/ecs.cpp
@@ -31,15 +31,6 @@ intv_ecs_device::intv_ecs_device(const machine_config &mconfig, const char *tag,
: intv_rom_device(mconfig, INTV_ROM_ECS, "Intellivision ECS Expansion", tag, owner, clock, "intv_ecs", __FILE__),
m_snd(*this, "ay8914"),
m_subslot(*this, "subslot"),
- m_keybd(*this, "ROW"),
- m_synth(*this, "SYNTH"),
- m_cntrlsel(*this, "CNTRLSEL"),
- m_options(*this, "OPTIONS"),
- m_keypad(*this, "KEYPAD"),
- m_disc(*this, "DISC"),
- m_discx(*this, "DISCX"),
- m_discy(*this, "DISCY"),
- m_psg_porta(0),
m_voice_enabled(false),
m_ramd0_enabled(false),
m_ram88_enabled(false)
@@ -65,7 +56,6 @@ void intv_ecs_device::device_start()
}
save_item(NAME(m_bank_base));
- save_item(NAME(m_psg_porta));
}
void intv_ecs_device::device_reset()
@@ -102,135 +92,17 @@ void intv_ecs_device::late_subslot_setup()
// MACHINE_CONFIG_FRAGMENT( sub_slot )
//-------------------------------------------------
-UINT8 intv_ecs_device::intv_control_r(int hand)
-{
- static const UINT8 keypad_table[] =
- {
- 0xFF, 0x3F, 0x9F, 0x5F, 0xD7, 0xB7, 0x77, 0xDB,
- 0xBB, 0x7B, 0xDD, 0xBD, 0x7D, 0xDE, 0xBE, 0x7E
- };
-
- static const UINT8 disc_table[] =
- {
- 0xF3, 0xE3, 0xE7, 0xF7, 0xF6, 0xE6, 0xEE, 0xFE,
- 0xFC, 0xEC, 0xED, 0xFD, 0xF9, 0xE9, 0xEB, 0xFB
- };
-
- static const UINT8 discyx_table[5][5] =
- {
- { 0xE3, 0xF3, 0xFB, 0xEB, 0xE9 },
- { 0xE7, 0xE3, 0xFB, 0xE9, 0xF9 },
- { 0xF7, 0xF7, 0xFF, 0xFD, 0xFD },
- { 0xF6, 0xE6, 0xFE, 0xEC, 0xED },
- { 0xE6, 0xEE, 0xFE, 0xFC, 0xEC }
- };
-
- int x, y;
- UINT8 val = 0xff;
-
- /* keypad */
- x = m_keypad[hand]->read();
- for (y = 0; y < 16; y++)
- {
- if (x & (1 << y))
- {
- val &= keypad_table[y];
- }
- }
-
- y = (m_options->read() >> ((hand + 2) * 2)) & 3;
- switch (y)
- {
- case 0: /* disc == digital 8-way */
- case 1: /* disc == digital 16-way */
- default:
-
- x = m_disc[hand]->read();
- if (!!x && (!y || !(x & 0x7777)))
- {
- // merge cardinals to form true diagonals
- y = ((x >> 2) & (x << 2)) | ((x >> (16 - 2)) & (x >> 2));
- x = y | (x & ~((y << 2) | (y >> 2) | (y << (16 - 2))));
- }
-
- // only one disc direction is allowed
- x &= -x;
-
- for (y = 0; y < 16; y++)
- {
- if (x & (1 << y))
- {
- val &= disc_table[y];
- }
- }
- break;
-
- case 2: /* disc == _fake_ analog */
-
- x = m_discx[hand]->read();
- y = m_discy[hand]->read();
- val &= discyx_table[y / 32][x / 32];
- }
-
- return val;
-}
-
-READ8_MEMBER( intv_ecs_device::ay_porta_r )
-{
- if (m_cntrlsel->read() == 0)
- return intv_control_r(0);
- else
- return 0xff; // not sure what to return here, maybe it should be last output?
-}
-
-READ8_MEMBER( intv_ecs_device::ay_portb_r )
-{
- switch (m_cntrlsel->read())
- {
- case 0x00: // hand controller
- return intv_control_r(1);
-
- case 0x01: // synthesizer keyboard
- {
- UINT8 val = 0xff;
- // return correct result if more than one bit of 0xFE is set
- for (int i = 0; i < 7; i++)
- {
- if (BIT(m_psg_porta, i))
- val &= m_synth[i]->read();
- }
- return val;
- }
- case 0x02: // ecs keyboard
- {
- UINT8 val = 0xff;
- // return correct result if more than one bit of 0xFE is set
- for (int i = 0; i < 7; i++)
- {
- if (BIT(m_psg_porta, i))
- val &= m_keybd[i]->read();
- }
- return val;
- }
- default:
- return 0xff;
- }
-}
-
-WRITE8_MEMBER( intv_ecs_device::ay_porta_w )
-{
- m_psg_porta = (~data) & 0xff;
-}
static MACHINE_CONFIG_FRAGMENT( sub_slot )
MCFG_SPEAKER_STANDARD_MONO("mono_ecs")
MCFG_SOUND_ADD("ay8914", AY8914, XTAL_3_579545MHz/2)
- MCFG_AY8910_PORT_A_READ_CB(READ8(intv_ecs_device, ay_porta_r))
- MCFG_AY8910_PORT_B_READ_CB(READ8(intv_ecs_device, ay_portb_r))
- MCFG_AY8910_PORT_A_WRITE_CB(WRITE8(intv_ecs_device, ay_porta_w))
+ MCFG_AY8910_PORT_A_READ_CB(DEVREAD8("ctrl_port", intvecs_control_port_device, portA_r))
+ MCFG_AY8910_PORT_B_READ_CB(DEVREAD8("ctrl_port", intvecs_control_port_device, portB_r))
+ MCFG_AY8910_PORT_A_WRITE_CB(DEVWRITE8("ctrl_port", intvecs_control_port_device, portA_w))
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono_ecs", 0.33)
+ MCFG_INTVECS_CONTROL_PORT_ADD("ctrl_port", intvecs_control_port_devices, "keybd")
MCFG_INTV_CARTRIDGE_ADD("subslot", intv_cart, nullptr)
MACHINE_CONFIG_END
@@ -254,294 +126,6 @@ const rom_entry *intv_ecs_device::device_rom_region() const
}
-static INPUT_PORTS_START( intv_ecs_kbd )
-/*
- ECS matrix scanned by setting 0xFE bits to output and reading 0xFF
- ECS Keyboard Layout:
- FF\FE Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0
- Bit 0 NC RTN 0 ESC P ; . (left)
- Bit 1 L O 8 9 I K M ,
- Bit 2 J U 6 7 Y H B N
- Bit 3 G T 4 5 R F C V
- Bit 4 D E 2 3 W S Z X
- Bit 5 A CTL (right) 1 Q (up) (down) (space)
- Bit 6 SHIFT NC NC NC NC NC NC NC
-
- Shifted keys that differ from pc:
- Key : 1 2 5 6 7 (left) (right) (up) (down)
- Shift + key: = " + - / % ' ^ ?
- */
-
- PORT_START("ROW.0")
- PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED )
- PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("RTN") PORT_CODE(KEYCODE_ENTER) PORT_CHAR(13) PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x02)
- PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR(')') PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x02)
- PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_ESC) PORT_CHAR(UCHAR_MAMEKEY(ESC)) PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x02)
- PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_P) PORT_CHAR('P') PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x02)
- PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COLON) PORT_CHAR(';') PORT_CHAR(':') PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x02)
- PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x02)
- PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_LEFT) PORT_CHAR(UCHAR_MAMEKEY(LEFT)) PORT_CHAR('%') PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x02)
-
- PORT_START("ROW.1")
- PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_L) PORT_CHAR('L') PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x02)
- PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_O) PORT_CHAR('O') PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x02)
- PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('*') PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x02)
- PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR('(') PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x02)
- PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_I) PORT_CHAR('I') PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x02)
- PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_K) PORT_CHAR('K') PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x02)
- PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_M) PORT_CHAR('M') PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x02)
- PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x02)
-
- PORT_START("ROW.2")
- PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_J) PORT_CHAR('J') PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x02)
- PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_U) PORT_CHAR('U') PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x02)
- PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('-') PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x02)
- PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('/') PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x02)
- PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Y) PORT_CHAR('Y') PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x02)
- PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_H) PORT_CHAR('H') PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x02)
- PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_B) PORT_CHAR('B') PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x02)
- PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_N) PORT_CHAR('N') PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x02)
-
- PORT_START("ROW.3")
- PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_G) PORT_CHAR('G') PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x02)
- PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_T) PORT_CHAR('T') PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x02)
- PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR('$') PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x02)
- PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%') PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x02)
- PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_R) PORT_CHAR('R') PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x02)
- PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F) PORT_CHAR('F') PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x02)
- PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_C) PORT_CHAR('C') PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x02)
- PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_V) PORT_CHAR('V') PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x02)
-
- PORT_START("ROW.4")
- PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_D) PORT_CHAR('D') PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x02)
- PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_E) PORT_CHAR('E') PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x02)
- PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('"') PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x02)
- PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR('#') PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x02)
- PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_W) PORT_CHAR('W') PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x02)
- PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_S) PORT_CHAR('S') PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x02)
- PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Z) PORT_CHAR('Z') PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x02)
- PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_X) PORT_CHAR('X') PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x02)
-
- PORT_START("ROW.5")
- PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_A) PORT_CHAR('A') PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x02)
- PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("CTL") PORT_CODE(KEYCODE_RCONTROL) PORT_CODE(KEYCODE_LCONTROL) PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x02)
- PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_RIGHT) PORT_CHAR(UCHAR_MAMEKEY(RIGHT)) PORT_CHAR('\'') PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x02)
- PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('=') PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x02)
- PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Q) PORT_CHAR('Q') PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x02)
- PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_UP) PORT_CHAR(UCHAR_MAMEKEY(UP)) PORT_CHAR('^') PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x02)
- PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_DOWN) PORT_CHAR(UCHAR_MAMEKEY(DOWN)) PORT_CHAR('?') PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x02)
- PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ') PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x02)
-
- PORT_START("ROW.6")
- PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("SHIFT") PORT_CODE(KEYCODE_RSHIFT) PORT_CODE(KEYCODE_LSHIFT) PORT_CHAR(UCHAR_SHIFT_1) PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x02)
- PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNUSED )
- PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNUSED )
- PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNUSED )
- PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNUSED )
- PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNUSED )
- PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNUSED )
- PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNUSED )
-INPUT_PORTS_END
-
-static INPUT_PORTS_START( intv_ecs_synth )
-/*
- ECS Synthesizer Layout:
- FF\FE Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0
- Bit 0 G2 Gb2 F2 E2 Eb2 D2 Db2 C2
- Bit 1 Eb3 D3 Db3 C3 B2 Bb2 A2 Ab2
- Bit 2 B3 Bb3 A3 Ab3 G3 Gb3 F3 E3
- Bit 3 G4 Gb4 F4 E4 Eb4 D4 Db4 C4
- Bit 4 Eb5 D5 Db5 C5 B4 Bb4 A4 Ab4
- Bit 5 B5 Bb5 A5 Ab5 G5 Gb5 F5 E5
- Bit 6 C6 NC NC NC NC NC NC NC
- */
- PORT_START("SYNTH.0")
- PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("G2") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x01)
- PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Gb2") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x01)
- PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F2") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x01)
- PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("E2") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x01)
- PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Eb2") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x01)
- PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("D2") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x01)
- PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Db2") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x01)
- PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("C2") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x01)
-
- PORT_START("SYNTH.1")
- PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Eb3") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x01)
- PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("D3") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x01)
- PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Db3") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x01)
- PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("C3") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x01)
- PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("B2") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x01)
- PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Bb2") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x01)
- PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("A2") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x01)
- PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Ab2") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x01)
-
- PORT_START("SYNTH.2")
- PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("B3") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x01)
- PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Bb3") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x01)
- PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("A3") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x01)
- PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Ab3") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x01)
- PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("G3") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x01)
- PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Gb3") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x01)
- PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F3") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x01)
- PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("E3") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x01)
-
- PORT_START("SYNTH.3")
- PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("G4") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x01)
- PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Gb4") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x01)
- PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F4") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x01)
- PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("E4") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x01)
- PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Eb4") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x01)
- PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("D4") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x01)
- PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Db4") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x01)
- PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("C4") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x01)
-
- PORT_START("SYNTH.4")
- PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Eb5") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x01)
- PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("D5") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x01)
- PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Db5") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x01)
- PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("C5") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x01)
- PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("B4") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x01)
- PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Bb4") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x01)
- PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("A4") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x01)
- PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Ab4") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x01)
-
- PORT_START("SYNTH.5")
- PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("B5") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x01)
- PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Bb5") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x01)
- PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("A5") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x01)
- PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Ab5") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x01)
- PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("G5") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x01)
- PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Gb5") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x01)
- PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F5") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x01)
- PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("E5") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x01)
-
- PORT_START("SYNTH.6")
- PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("C6") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x01)
- PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNUSED )
- PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNUSED )
- PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNUSED )
- PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNUSED )
- PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNUSED )
- PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNUSED )
- PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNUSED )
-INPUT_PORTS_END
-
-static INPUT_PORTS_START( intv_ecs_pads )
- // First ECS Hand Controller
- PORT_START("KEYPAD.0")
- PORT_BIT( 0x8000, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("P3 1") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00)
- PORT_BIT( 0x4000, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("P3 2") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00)
- PORT_BIT( 0x2000, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("P3 3") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00)
- PORT_BIT( 0x1000, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("P3 4") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00)
- PORT_BIT( 0x0800, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("P3 5") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00)
- PORT_BIT( 0x0400, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("P3 6") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00)
- PORT_BIT( 0x0200, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("P3 7") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00)
- PORT_BIT( 0x0100, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("P3 8") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00)
- PORT_BIT( 0x0080, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("P3 9") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00)
- PORT_BIT( 0x0040, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("P3 Clear") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00)
- PORT_BIT( 0x0020, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("P3 0") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00)
- PORT_BIT( 0x0010, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("P3 Enter") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00)
- PORT_BIT( 0x0008, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("P3 Upper") PORT_PLAYER(3) PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00)
- PORT_BIT( 0x0004, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("P3 Lower-Left") PORT_PLAYER(3) PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00)
- PORT_BIT( 0x0002, IP_ACTIVE_HIGH, IPT_BUTTON3 ) PORT_NAME("P3 Lower-Right") PORT_PLAYER(3) PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00)
- PORT_BIT( 0x0001, IP_ACTIVE_HIGH, IPT_UNUSED )
-
- PORT_START("DISC.0")
- PORT_BIT( 0x8000, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) PORT_NAME("P3 Up") PORT_PLAYER(3) PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00) PORT_CONDITION("OPTIONS",0x30,NOTEQUALS,0x20)
- PORT_BIT( 0x4000, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P3 Up-Up-Right") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00) PORT_CONDITION("OPTIONS",0x30,EQUALS,0x10)
- PORT_BIT( 0x2000, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P3 Up-Right") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00) PORT_CONDITION("OPTIONS",0x30,EQUALS,0x10)
- PORT_BIT( 0x1000, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P3 Right-Up-Right") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00) PORT_CONDITION("OPTIONS",0x30,EQUALS,0x10)
- PORT_BIT( 0x0800, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_NAME("P3 Right") PORT_PLAYER(3) PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00) PORT_CONDITION("OPTIONS",0x30,NOTEQUALS,0x20)
- PORT_BIT( 0x0400, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P3 Right-Down-Right") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00) PORT_CONDITION("OPTIONS",0x30,EQUALS,0x10)
- PORT_BIT( 0x0200, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P3 Down-Right") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00) PORT_CONDITION("OPTIONS",0x30,EQUALS,0x10)
- PORT_BIT( 0x0100, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P3 Down-Down-Right") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00) PORT_CONDITION("OPTIONS",0x30,EQUALS,0x10)
- PORT_BIT( 0x0080, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_NAME("P3 Down") PORT_PLAYER(3) PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00) PORT_CONDITION("OPTIONS",0x30,NOTEQUALS,0x20)
- PORT_BIT( 0x0040, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P3 Down-Down-Left") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00) PORT_CONDITION("OPTIONS",0x30,EQUALS,0x10)
- PORT_BIT( 0x0020, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P3 Down-Left") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00) PORT_CONDITION("OPTIONS",0x30,EQUALS,0x10)
- PORT_BIT( 0x0010, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P3 Left-Down-Left") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00) PORT_CONDITION("OPTIONS",0x30,EQUALS,0x10)
- PORT_BIT( 0x0008, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_NAME("P3 Left") PORT_PLAYER(3) PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00) PORT_CONDITION("OPTIONS",0x30,NOTEQUALS,0x20)
- PORT_BIT( 0x0004, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P3 Left-Up-Left") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00) PORT_CONDITION("OPTIONS",0x30,EQUALS,0x10)
- PORT_BIT( 0x0002, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P3 Up-Left") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00) PORT_CONDITION("OPTIONS",0x30,EQUALS,0x10)
- PORT_BIT( 0x0001, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P3 Up-Up-Left") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00) PORT_CONDITION("OPTIONS",0x30,EQUALS,0x10)
-
- PORT_START("DISCX.0")
- PORT_BIT( 0xff, 0x50, IPT_AD_STICK_X ) PORT_NAME("P3 X") PORT_MINMAX(0x00,0x9f) PORT_SENSITIVITY(100) PORT_KEYDELTA(0x50) PORT_PLAYER(3) PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00) PORT_CONDITION("OPTIONS",0x30,EQUALS,0x20)
-
- PORT_START("DISCY.0")
- PORT_BIT( 0xff, 0x50, IPT_AD_STICK_Y ) PORT_NAME("P3 Y") PORT_MINMAX(0x00,0x9f) PORT_SENSITIVITY(100) PORT_KEYDELTA(0x50) PORT_PLAYER(3) PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00) PORT_CONDITION("OPTIONS",0x30,EQUALS,0x20)
-
- // Second ECS Hand Controller
- PORT_START("KEYPAD.1")
- PORT_BIT( 0x8000, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("P4 1") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00)
- PORT_BIT( 0x4000, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("P4 2") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00)
- PORT_BIT( 0x2000, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("P4 3") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00)
- PORT_BIT( 0x1000, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("P4 4") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00)
- PORT_BIT( 0x0800, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("P4 5") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00)
- PORT_BIT( 0x0400, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("P4 6") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00)
- PORT_BIT( 0x0200, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("P4 7") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00)
- PORT_BIT( 0x0100, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("P4 8") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00)
- PORT_BIT( 0x0080, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("P4 9") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00)
- PORT_BIT( 0x0040, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("P4 Clear") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00)
- PORT_BIT( 0x0020, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("P4 0") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00)
- PORT_BIT( 0x0010, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("P4 Enter") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00)
- PORT_BIT( 0x0008, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("P4 Upper") PORT_PLAYER(4) PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00)
- PORT_BIT( 0x0004, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("P4 Lower-Left") PORT_PLAYER(4) PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00)
- PORT_BIT( 0x0002, IP_ACTIVE_HIGH, IPT_BUTTON3 ) PORT_NAME("P4 Lower-Right") PORT_PLAYER(4) PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00)
- PORT_BIT( 0x0001, IP_ACTIVE_HIGH, IPT_UNUSED )
-
- PORT_START("DISC.1")
- PORT_BIT( 0x8000, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) PORT_NAME("P4 Up") PORT_PLAYER(4) PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00) PORT_CONDITION("OPTIONS",0xC0,NOTEQUALS,0x80)
- PORT_BIT( 0x4000, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P4 Up-Up-Right") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00) PORT_CONDITION("OPTIONS",0xC0,EQUALS,0x40)
- PORT_BIT( 0x2000, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P4 Up-Right") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00) PORT_CONDITION("OPTIONS",0xC0,EQUALS,0x40)
- PORT_BIT( 0x1000, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P4 Right-Up-Right") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00) PORT_CONDITION("OPTIONS",0xC0,EQUALS,0x40)
- PORT_BIT( 0x0800, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_NAME("P4 Right") PORT_PLAYER(4) PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00) PORT_CONDITION("OPTIONS",0xC0,NOTEQUALS,0x80)
- PORT_BIT( 0x0400, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P4 Right-Down-Right") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00) PORT_CONDITION("OPTIONS",0xC0,EQUALS,0x40)
- PORT_BIT( 0x0200, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P4 Down-Right") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00) PORT_CONDITION("OPTIONS",0xC0,EQUALS,0x40)
- PORT_BIT( 0x0100, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P4 Down-Down-Right") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00) PORT_CONDITION("OPTIONS",0xC0,EQUALS,0x40)
- PORT_BIT( 0x0080, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_NAME("P4 Down") PORT_PLAYER(4) PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00) PORT_CONDITION("OPTIONS",0xC0,NOTEQUALS,0x80)
- PORT_BIT( 0x0040, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P4 Down-Down-Left") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00) PORT_CONDITION("OPTIONS",0xC0,EQUALS,0x40)
- PORT_BIT( 0x0020, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P4 Down-Left") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00) PORT_CONDITION("OPTIONS",0xC0,EQUALS,0x40)
- PORT_BIT( 0x0010, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P4 Left-Down-Left") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00) PORT_CONDITION("OPTIONS",0xC0,EQUALS,0x40)
- PORT_BIT( 0x0008, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_NAME("P4 Left") PORT_PLAYER(4) PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00) PORT_CONDITION("OPTIONS",0xC0,NOTEQUALS,0x80)
- PORT_BIT( 0x0004, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P4 Left-Up-Left") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00) PORT_CONDITION("OPTIONS",0xC0,EQUALS,0x40)
- PORT_BIT( 0x0002, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P4 Up-Left") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00) PORT_CONDITION("OPTIONS",0xC0,EQUALS,0x40)
- PORT_BIT( 0x0001, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P4 Up-Up-Left") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00) PORT_CONDITION("OPTIONS",0xC0,EQUALS,0x40)
-
- PORT_START("DISCX.1")
- PORT_BIT( 0xff, 0x50, IPT_AD_STICK_X ) PORT_NAME("P4 X") PORT_MINMAX(0x00,0x9f) PORT_SENSITIVITY(100) PORT_KEYDELTA(0x50) PORT_CODE_DEC(KEYCODE_D) PORT_CODE_INC(KEYCODE_G) PORT_PLAYER(4) PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00) PORT_CONDITION("OPTIONS",0xC0,EQUALS,0x80)
-
- PORT_START("DISCY.1")
- PORT_BIT( 0xff, 0x50, IPT_AD_STICK_Y ) PORT_NAME("P4 Y") PORT_MINMAX(0x00,0x9f) PORT_SENSITIVITY(100) PORT_KEYDELTA(0x50) PORT_CODE_DEC(KEYCODE_R) PORT_CODE_INC(KEYCODE_F) PORT_PLAYER(4) PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00) PORT_CONDITION("OPTIONS",0xC0,EQUALS,0x80)
-INPUT_PORTS_END
-
-static INPUT_PORTS_START( intv_ecs )
- PORT_INCLUDE( intv_ecs_pads )
- PORT_INCLUDE( intv_ecs_synth )
- PORT_INCLUDE( intv_ecs_kbd )
-
- PORT_START("OPTIONS")
- PORT_CONFNAME( 0x30, 0x00, "ECS P3 Disc" ) PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00)
- PORT_CONFSETTING( 0x00, "Digital 8-way" )
- PORT_CONFSETTING( 0x10, "Digital 16-way" )
- PORT_CONFSETTING( 0x20, "Analog" )
- PORT_CONFNAME( 0xC0, 0x00, "ECS P4 Disc" ) PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00)
- PORT_CONFSETTING( 0x00, "Digital 8-way" )
- PORT_CONFSETTING( 0x40, "Digital 16-way" )
- PORT_CONFSETTING( 0x80, "Analog" )
-
- PORT_START("CNTRLSEL")
- PORT_CONFNAME( 0x0F, 0x02, "ECS Controller")
- PORT_CONFSETTING( 0x00, "Gamepads" )
- PORT_CONFSETTING( 0x01, "Piano" )
- PORT_CONFSETTING( 0x02, "Keyboard" )
-INPUT_PORTS_END
-
-ioport_constructor intv_ecs_device::device_input_ports() const
-{
- return INPUT_PORTS_NAME( intv_ecs );
-}
-
-
/*-------------------------------------------------
Paged ROM handling
-------------------------------------------------*/
diff --git a/src/devices/bus/intv/ecs.h b/src/devices/bus/intv/ecs.h
index 3dc2f37e7b6..ce22d4f7481 100644
--- a/src/devices/bus/intv/ecs.h
+++ b/src/devices/bus/intv/ecs.h
@@ -6,7 +6,7 @@
#include "slot.h"
#include "rom.h"
#include "sound/ay8910.h"
-
+#include "bus/intv_ctrl/ecs_ctrl.h"
// ======================> intv_ecs_device
@@ -21,7 +21,6 @@ public:
virtual void device_start() override;
virtual void device_reset() override;
virtual machine_config_constructor device_mconfig_additions() const override;
- virtual ioport_constructor device_input_ports() const override;
virtual const rom_entry *device_rom_region() const override;
// reading and writing
@@ -38,9 +37,6 @@ public:
// AY8914
virtual DECLARE_READ16_MEMBER(read_ay) override;
virtual DECLARE_WRITE16_MEMBER(write_ay) override;
- DECLARE_READ8_MEMBER(ay_porta_r);
- DECLARE_READ8_MEMBER(ay_portb_r);
- DECLARE_WRITE8_MEMBER(ay_porta_w);
// passthru accesses
virtual DECLARE_READ16_MEMBER(read_rom04) override { return m_subslot->read_rom04(space, offset, mem_mask); }
@@ -117,30 +113,16 @@ public:
virtual void late_subslot_setup() override;
- UINT8 intv_control_r(int hand);
-
private:
required_device<ay8914_device> m_snd;
required_device<intv_cart_slot_device> m_subslot;
- required_ioport_array<7> m_keybd;
- required_ioport_array<7> m_synth;
- required_ioport m_cntrlsel;
- required_ioport m_options;
- required_ioport_array<2> m_keypad;
- required_ioport_array<2> m_disc;
- required_ioport_array<2> m_discx;
- required_ioport_array<2> m_discy;
int m_bank_base[0x10];
- UINT8 m_psg_porta;
bool m_voice_enabled, m_ramd0_enabled, m_ram88_enabled;
};
-
-
-
// device type definition
extern const device_type INTV_ROM_ECS;
diff --git a/src/devices/bus/intv_ctrl/ctrl.cpp b/src/devices/bus/intv_ctrl/ctrl.cpp
new file mode 100644
index 00000000000..4d57c558d0e
--- /dev/null
+++ b/src/devices/bus/intv_ctrl/ctrl.cpp
@@ -0,0 +1,95 @@
+// license:BSD-3-Clause
+// copyright-holders:Fabio Priuli
+/**********************************************************************
+
+ Mattel Intellivision controller port emulation
+
+**********************************************************************/
+
+#include "ctrl.h"
+// slot devices
+#include "handctrl.h"
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+const device_type INTV_CONTROL_PORT = &device_creator<intv_control_port_device>;
+
+
+//**************************************************************************
+// CARD INTERFACE
+//**************************************************************************
+
+//-------------------------------------------------
+// device_intv_control_port_interface - constructor
+//-------------------------------------------------
+
+device_intv_control_port_interface::device_intv_control_port_interface(const machine_config &mconfig, device_t &device)
+ : device_slot_card_interface(mconfig,device)
+{
+ m_port = dynamic_cast<intv_control_port_device *>(device.owner());
+}
+
+
+//-------------------------------------------------
+// ~device_intv_control_port_interface - destructor
+//-------------------------------------------------
+
+device_intv_control_port_interface::~device_intv_control_port_interface()
+{
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// intv_control_port_device - constructor
+//-------------------------------------------------
+
+intv_control_port_device::intv_control_port_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
+ device_t(mconfig, INTV_CONTROL_PORT, "Mattel Intellivision control port", tag, owner, clock, "intv_control_port", __FILE__),
+ device_slot_interface(mconfig, *this), m_device(nullptr)
+{
+}
+
+
+//-------------------------------------------------
+// intv_control_port_device - destructor
+//-------------------------------------------------
+
+intv_control_port_device::~intv_control_port_device()
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void intv_control_port_device::device_start()
+{
+ m_device = dynamic_cast<device_intv_control_port_interface *>(get_card_device());
+}
+
+
+UINT8 intv_control_port_device::read_ctrl()
+{
+ UINT8 data = 0;
+ if (m_device)
+ data |= m_device->read_ctrl();
+ return data;
+}
+
+
+//-------------------------------------------------
+// SLOT_INTERFACE( intv_control_port_devices )
+//-------------------------------------------------
+
+SLOT_INTERFACE_START( intv_control_port_devices )
+ SLOT_INTERFACE("handctrl", INTV_HANDCTRL)
+SLOT_INTERFACE_END
+
diff --git a/src/devices/bus/intv_ctrl/ctrl.h b/src/devices/bus/intv_ctrl/ctrl.h
new file mode 100644
index 00000000000..b29891efe87
--- /dev/null
+++ b/src/devices/bus/intv_ctrl/ctrl.h
@@ -0,0 +1,76 @@
+// license:BSD-3-Clause
+// copyright-holders:Fabio Priuli
+/**********************************************************************
+
+ Mattel Intellivision controller port emulation
+
+**********************************************************************/
+
+
+#pragma once
+
+#ifndef __INTV_CONTROL_PORT__
+#define __INTV_CONTROL_PORT__
+
+#include "emu.h"
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class intv_control_port_device;
+
+// ======================> device_intv_control_port_interface
+
+class device_intv_control_port_interface : public device_slot_card_interface
+{
+public:
+ // construction/destruction
+ device_intv_control_port_interface(const machine_config &mconfig, device_t &device);
+ virtual ~device_intv_control_port_interface();
+
+ virtual UINT8 read_ctrl() { return 0; };
+
+protected:
+ intv_control_port_device *m_port;
+};
+
+// ======================> intv_control_port_device
+
+class intv_control_port_device : public device_t,
+ public device_slot_interface
+{
+public:
+ // construction/destruction
+ intv_control_port_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+ virtual ~intv_control_port_device();
+
+ DECLARE_READ8_MEMBER( ctrl_r ) { return read_ctrl(); }
+ UINT8 read_ctrl();
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+
+ device_intv_control_port_interface *m_device;
+};
+
+
+// device type definition
+extern const device_type INTV_CONTROL_PORT;
+
+
+//**************************************************************************
+// INTERFACE CONFIGURATION MACROS
+//**************************************************************************
+
+#define MCFG_INTV_CONTROL_PORT_ADD(_tag, _slot_intf, _def_slot) \
+ MCFG_DEVICE_ADD(_tag, INTV_CONTROL_PORT, 0) \
+ MCFG_DEVICE_SLOT_INTERFACE(_slot_intf, _def_slot, false)
+
+
+
+SLOT_INTERFACE_EXTERN( intv_control_port_devices );
+
+
+#endif
diff --git a/src/devices/bus/intv_ctrl/ecs_ctrl.cpp b/src/devices/bus/intv_ctrl/ecs_ctrl.cpp
new file mode 100644
index 00000000000..19bc059531a
--- /dev/null
+++ b/src/devices/bus/intv_ctrl/ecs_ctrl.cpp
@@ -0,0 +1,448 @@
+// license:BSD-3-Clause
+// copyright-holders:Fabio Priuli
+/**********************************************************************
+
+ Mattel Intellivision ECS hack for controller port emulation
+
+ FIXME: This device is the best I could come up with to emulate
+ the fact that Keyboard and Synth controllers for the ECS should be
+ plugged in both ECS control ports, while the 3rd and 4th additional
+ hand controller should only be plugged in a single port.
+ Since the core currently does not allow a single device mounted
+ in more than a slot, this has been worked around with this device
+ which supports as options
+ - ECS keyboard
+ - ECS synth
+ - a pair of Intellivision controller
+
+ All the code for both the controller port and the slot devices has
+ been included in this single source file to make easier to clean
+ them up once we extend the core to support this kind of setup
+ (necessary for Atari 2600 Compumate as well)
+
+**********************************************************************/
+
+#include "ecs_ctrl.h"
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+const device_type INTVECS_CONTROL_PORT = &device_creator<intvecs_control_port_device>;
+
+
+//**************************************************************************
+// CARD INTERFACE
+//**************************************************************************
+
+//-------------------------------------------------
+// device_intvecs_control_port_interface - constructor
+//-------------------------------------------------
+
+device_intvecs_control_port_interface::device_intvecs_control_port_interface(const machine_config &mconfig, device_t &device)
+ : device_slot_card_interface(mconfig,device)
+{
+ m_port = dynamic_cast<intvecs_control_port_device *>(device.owner());
+}
+
+
+//-------------------------------------------------
+// ~device_intvecs_control_port_interface - destructor
+//-------------------------------------------------
+
+device_intvecs_control_port_interface::~device_intvecs_control_port_interface()
+{
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// intvecs_control_port_device - constructor
+//-------------------------------------------------
+
+intvecs_control_port_device::intvecs_control_port_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
+ device_t(mconfig, INTVECS_CONTROL_PORT, "Mattel Intellivision ECS control port (HACK)", tag, owner, clock, "intvecs_control_port", __FILE__),
+ device_slot_interface(mconfig, *this), m_device(nullptr)
+{
+}
+
+
+//-------------------------------------------------
+// intvecs_control_port_device - destructor
+//-------------------------------------------------
+
+intvecs_control_port_device::~intvecs_control_port_device()
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void intvecs_control_port_device::device_start()
+{
+ m_device = dynamic_cast<device_intvecs_control_port_interface *>(get_card_device());
+}
+
+
+UINT8 intvecs_control_port_device::read_portA()
+{
+ UINT8 data = 0;
+ if (m_device)
+ data |= m_device->read_portA();
+ return data;
+}
+
+UINT8 intvecs_control_port_device::read_portB()
+{
+ UINT8 data = 0;
+ if (m_device)
+ data |= m_device->read_portB();
+ return data;
+}
+
+void intvecs_control_port_device::write_portA(UINT8 data)
+{
+ if (m_device)
+ m_device->write_portA(data);
+}
+
+
+//-------------------------------------------------
+// SLOT_INTERFACE( intvecs_control_port_devices )
+//-------------------------------------------------
+
+SLOT_INTERFACE_START( intvecs_control_port_devices )
+ SLOT_INTERFACE("ctrls", ECS_CTRLS)
+ SLOT_INTERFACE("keybd", ECS_KEYBD)
+ SLOT_INTERFACE("synth", ECS_SYNTH)
+SLOT_INTERFACE_END
+
+
+
+
+
+//**************************************************************************
+// ACTUAL SLOT DEVICES - included here until core issues are solved...
+//**************************************************************************
+
+
+//-------------------------------------------------
+// ECS_CTRLS - A pair of hand controllers
+//-------------------------------------------------
+
+const device_type ECS_CTRLS = &device_creator<intvecs_ctrls_device>;
+
+static SLOT_INTERFACE_START( intvecs_controller )
+ SLOT_INTERFACE("handctrl", INTV_HANDCTRL)
+SLOT_INTERFACE_END
+
+static MACHINE_CONFIG_FRAGMENT( intvecs_ctrls )
+ MCFG_INTV_CONTROL_PORT_ADD("port1", intvecs_controller, "handctrl")
+ MCFG_INTV_CONTROL_PORT_ADD("port2", intvecs_controller, "handctrl")
+MACHINE_CONFIG_END
+
+
+machine_config_constructor intvecs_ctrls_device::device_mconfig_additions() const
+{
+ return MACHINE_CONFIG_NAME( intvecs_ctrls );
+}
+
+intvecs_ctrls_device::intvecs_ctrls_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
+ device_t(mconfig, ECS_CTRLS, "Mattel Intellivision ECS Hand Controller x2 (HACK)", tag, owner, clock, "intvecs_ctrls", __FILE__),
+ device_intvecs_control_port_interface(mconfig, *this),
+ m_hand1(*this, "port1"),
+ m_hand2(*this, "port2")
+{
+}
+
+void intvecs_ctrls_device::device_start()
+{
+}
+
+void intvecs_ctrls_device::device_reset()
+{
+}
+
+UINT8 intvecs_ctrls_device::read_portA()
+{
+ return m_hand1->read_ctrl();
+}
+
+UINT8 intvecs_ctrls_device::read_portB()
+{
+ return m_hand2->read_ctrl();
+}
+
+//-------------------------------------------------
+// ECS_KEYBD - Keyboard
+//-------------------------------------------------
+
+const device_type ECS_KEYBD = &device_creator<intvecs_keybd_device>;
+
+static INPUT_PORTS_START( intvecs_keybd )
+/*
+ ECS matrix scanned by setting 0xFE bits to output and reading 0xFF
+ ECS Keyboard Layout:
+ FF\FE Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0
+ Bit 0 NC RTN 0 ESC P ; . (left)
+ Bit 1 L O 8 9 I K M ,
+ Bit 2 J U 6 7 Y H B N
+ Bit 3 G T 4 5 R F C V
+ Bit 4 D E 2 3 W S Z X
+ Bit 5 A CTL (right) 1 Q (up) (down) (space)
+ Bit 6 SHIFT NC NC NC NC NC NC NC
+
+ Shifted keys that differ from pc:
+ Key : 1 2 5 6 7 (left) (right) (up) (down)
+ Shift + key: = " + - / % ' ^ ?
+ */
+
+ PORT_START("ROW.0")
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED )
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("RTN") PORT_CODE(KEYCODE_ENTER) PORT_CHAR(13)
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR(')')
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_ESC) PORT_CHAR(UCHAR_MAMEKEY(ESC))
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_P) PORT_CHAR('P')
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COLON) PORT_CHAR(';') PORT_CHAR(':')
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_STOP) PORT_CHAR('.')
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_LEFT) PORT_CHAR(UCHAR_MAMEKEY(LEFT)) PORT_CHAR('%')
+
+ PORT_START("ROW.1")
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_L) PORT_CHAR('L')
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_O) PORT_CHAR('O')
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('*')
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR('(')
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_I) PORT_CHAR('I')
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_K) PORT_CHAR('K')
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_M) PORT_CHAR('M')
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',')
+
+ PORT_START("ROW.2")
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_J) PORT_CHAR('J')
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_U) PORT_CHAR('U')
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('-')
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('/')
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Y) PORT_CHAR('Y')
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_H) PORT_CHAR('H')
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_B) PORT_CHAR('B')
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_N) PORT_CHAR('N')
+
+ PORT_START("ROW.3")
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_G) PORT_CHAR('G')
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_T) PORT_CHAR('T')
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR('$')
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%')
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_R) PORT_CHAR('R')
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F) PORT_CHAR('F')
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_C) PORT_CHAR('C')
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_V) PORT_CHAR('V')
+
+ PORT_START("ROW.4")
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_D) PORT_CHAR('D')
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_E) PORT_CHAR('E')
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('"')
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR('#')
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_W) PORT_CHAR('W')
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_S) PORT_CHAR('S')
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Z) PORT_CHAR('Z')
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_X) PORT_CHAR('X')
+
+ PORT_START("ROW.5")
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_A) PORT_CHAR('A')
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("CTL") PORT_CODE(KEYCODE_RCONTROL) PORT_CODE(KEYCODE_LCONTROL)
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_RIGHT) PORT_CHAR(UCHAR_MAMEKEY(RIGHT)) PORT_CHAR('\'')
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('=')
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Q) PORT_CHAR('Q')
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_UP) PORT_CHAR(UCHAR_MAMEKEY(UP)) PORT_CHAR('^')
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_DOWN) PORT_CHAR(UCHAR_MAMEKEY(DOWN)) PORT_CHAR('?')
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ')
+
+ PORT_START("ROW.6")
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("SHIFT") PORT_CODE(KEYCODE_RSHIFT) PORT_CODE(KEYCODE_LSHIFT) PORT_CHAR(UCHAR_SHIFT_1)
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNUSED )
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNUSED )
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNUSED )
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNUSED )
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNUSED )
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNUSED )
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNUSED )
+INPUT_PORTS_END
+
+ioport_constructor intvecs_keybd_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( intvecs_keybd );
+}
+
+intvecs_keybd_device::intvecs_keybd_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
+ device_t(mconfig, ECS_KEYBD, "Mattel Intellivision ECS Keyboard", tag, owner, clock, "intvecs_keybd", __FILE__),
+ device_intvecs_control_port_interface(mconfig, *this),
+ m_keybd(*this, "ROW")
+{
+}
+
+void intvecs_keybd_device::device_start()
+{
+ save_item(NAME(m_psg_portA));
+}
+
+void intvecs_keybd_device::device_reset()
+{
+ m_psg_portA = 0;
+}
+
+UINT8 intvecs_keybd_device::read_portB()
+{
+ UINT8 val = 0xff;
+ // return correct result if more than one bit of 0xFE is set
+ for (int i = 0; i < 7; i++)
+ {
+ if (BIT(m_psg_portA, i))
+ val &= m_keybd[i]->read();
+ }
+ return val;
+}
+
+void intvecs_keybd_device::write_portA(UINT8 data)
+{
+ m_psg_portA = (~data) & 0xff;
+}
+
+
+
+//-------------------------------------------------
+// ECS_SYNTH - Synth
+//-------------------------------------------------
+
+const device_type ECS_SYNTH = &device_creator<intvecs_synth_device>;
+
+
+static INPUT_PORTS_START( intvecs_synth )
+/*
+ ECS Synthesizer Layout:
+ FF\FE Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0
+ Bit 0 G2 Gb2 F2 E2 Eb2 D2 Db2 C2
+ Bit 1 Eb3 D3 Db3 C3 B2 Bb2 A2 Ab2
+ Bit 2 B3 Bb3 A3 Ab3 G3 Gb3 F3 E3
+ Bit 3 G4 Gb4 F4 E4 Eb4 D4 Db4 C4
+ Bit 4 Eb5 D5 Db5 C5 B4 Bb4 A4 Ab4
+ Bit 5 B5 Bb5 A5 Ab5 G5 Gb5 F5 E5
+ Bit 6 C6 NC NC NC NC NC NC NC
+ */
+ PORT_START("SYNTH.0")
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("G2")
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Gb2")
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F2")
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("E2")
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Eb2")
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("D2")
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Db2")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("C2")
+
+ PORT_START("SYNTH.1")
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Eb3")
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("D3")
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Db3")
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("C3")
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("B2")
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Bb2")
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("A2")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Ab2")
+
+ PORT_START("SYNTH.2")
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("B3")
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Bb3")
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("A3")
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Ab3")
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("G3")
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Gb3")
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F3")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("E3")
+
+ PORT_START("SYNTH.3")
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("G4")
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Gb4")
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F4")
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("E4")
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Eb4")
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("D4")
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Db4")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("C4")
+
+ PORT_START("SYNTH.4")
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Eb5")
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("D5")
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Db5")
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("C5")
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("B4")
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Bb4")
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("A4")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Ab4")
+
+ PORT_START("SYNTH.5")
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("B5")
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Bb5")
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("A5")
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Ab5")
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("G5")
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Gb5")
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F5")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("E5")
+
+ PORT_START("SYNTH.6")
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("C6")
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNUSED )
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNUSED )
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNUSED )
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNUSED )
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNUSED )
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNUSED )
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNUSED )
+INPUT_PORTS_END
+
+
+ioport_constructor intvecs_synth_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( intvecs_synth );
+}
+
+
+intvecs_synth_device::intvecs_synth_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
+ device_t(mconfig, ECS_SYNTH, "Mattel Intellivision ECS Synthetizer", tag, owner, clock, "intvecs_synth", __FILE__),
+ device_intvecs_control_port_interface(mconfig, *this),
+ m_synth(*this, "SYNTH")
+{
+}
+
+void intvecs_synth_device::device_start()
+{
+ save_item(NAME(m_psg_portA));
+}
+
+void intvecs_synth_device::device_reset()
+{
+ m_psg_portA = 0;
+}
+
+UINT8 intvecs_synth_device::read_portB()
+{
+ UINT8 val = 0xff;
+ // return correct result if more than one bit of 0xFE is set
+ for (int i = 0; i < 7; i++)
+ {
+ if (BIT(m_psg_portA, i))
+ val &= m_synth[i]->read();
+ }
+ return val;
+}
+
+void intvecs_synth_device::write_portA(UINT8 data)
+{
+ m_psg_portA = (~data) & 0xff;
+}
+
diff --git a/src/devices/bus/intv_ctrl/ecs_ctrl.h b/src/devices/bus/intv_ctrl/ecs_ctrl.h
new file mode 100644
index 00000000000..40d94ca5d1b
--- /dev/null
+++ b/src/devices/bus/intv_ctrl/ecs_ctrl.h
@@ -0,0 +1,171 @@
+// license:BSD-3-Clause
+// copyright-holders:Fabio Priuli
+/**********************************************************************
+
+ Mattel Intellivision ECS hack for controller port emulation
+
+**********************************************************************/
+
+
+#pragma once
+
+#ifndef __INTVECS_CONTROL_PORT__
+#define __INTVECS_CONTROL_PORT__
+
+#include "emu.h"
+#include "bus/intv_ctrl/ctrl.h"
+#include "bus/intv_ctrl/handctrl.h"
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class intvecs_control_port_device;
+
+// ======================> device_intvecs_control_port_interface
+
+class device_intvecs_control_port_interface : public device_slot_card_interface
+{
+public:
+ // construction/destruction
+ device_intvecs_control_port_interface(const machine_config &mconfig, device_t &device);
+ virtual ~device_intvecs_control_port_interface();
+
+ virtual UINT8 read_portA() { return 0xff; };
+ virtual UINT8 read_portB() { return 0xff; };
+ virtual void write_portA(UINT8 data) { };
+
+protected:
+ intvecs_control_port_device *m_port;
+};
+
+// ======================> intvecs_control_port_device
+
+class intvecs_control_port_device : public device_t,
+ public device_slot_interface
+{
+public:
+ // construction/destruction
+ intvecs_control_port_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+ virtual ~intvecs_control_port_device();
+
+ DECLARE_READ8_MEMBER( portA_r ) { return read_portA(); }
+ DECLARE_READ8_MEMBER( portB_r ) { return read_portB(); }
+ DECLARE_WRITE8_MEMBER( portA_w ) { return write_portA(data); }
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+ UINT8 read_portA();
+ UINT8 read_portB();
+ void write_portA(UINT8 data);
+
+ device_intvecs_control_port_interface *m_device;
+};
+
+
+// device type definition
+extern const device_type INTVECS_CONTROL_PORT;
+
+
+//**************************************************************************
+// INTERFACE CONFIGURATION MACROS
+//**************************************************************************
+
+#define MCFG_INTVECS_CONTROL_PORT_ADD(_tag, _slot_intf, _def_slot) \
+ MCFG_DEVICE_ADD(_tag, INTVECS_CONTROL_PORT, 0) \
+ MCFG_DEVICE_SLOT_INTERFACE(_slot_intf, _def_slot, false)
+
+
+
+SLOT_INTERFACE_EXTERN( intvecs_control_port_devices );
+
+
+//**************************************************************************
+// ACTUAL SLOT DEVICES - included here until core issues are solved...
+//**************************************************************************
+
+// ======================> intvecs_ctrls_device
+
+class intvecs_ctrls_device : public device_t,
+ public device_intvecs_control_port_interface
+{
+public:
+ // construction/destruction
+ intvecs_ctrls_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ // optional information overrides
+ virtual machine_config_constructor device_mconfig_additions() const override;
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ virtual UINT8 read_portA() override;
+ virtual UINT8 read_portB() override;
+
+private:
+ required_device<intv_control_port_device> m_hand1;
+ required_device<intv_control_port_device> m_hand2;
+};
+
+// ======================> intvecs_keybd_device
+
+class intvecs_keybd_device : public device_t,
+ public device_intvecs_control_port_interface
+{
+public:
+ // construction/destruction
+ intvecs_keybd_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ // optional information overrides
+ virtual ioport_constructor device_input_ports() const override;
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ virtual UINT8 read_portB() override;
+ virtual void write_portA(UINT8 data) override;
+
+private:
+ UINT8 m_psg_portA;
+ required_ioport_array<7> m_keybd;
+};
+
+// ======================> intvecs_synth_device
+
+class intvecs_synth_device : public device_t,
+ public device_intvecs_control_port_interface
+{
+public:
+ // construction/destruction
+ intvecs_synth_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ // optional information overrides
+ virtual ioport_constructor device_input_ports() const override;
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ virtual UINT8 read_portB() override;
+ virtual void write_portA(UINT8 data) override;
+
+private:
+ UINT8 m_psg_portA;
+ required_ioport_array<7> m_synth;
+};
+
+
+// device type definition
+extern const device_type ECS_CTRLS;
+extern const device_type ECS_KEYBD;
+extern const device_type ECS_SYNTH;
+
+
+
+#endif
diff --git a/src/devices/bus/intv_ctrl/handctrl.cpp b/src/devices/bus/intv_ctrl/handctrl.cpp
new file mode 100644
index 00000000000..512f9f32adc
--- /dev/null
+++ b/src/devices/bus/intv_ctrl/handctrl.cpp
@@ -0,0 +1,179 @@
+// license:BSD-3-Clause
+// copyright-holders:Fabio Priuli
+/**********************************************************************
+
+ Mattel Intellivision Hand Controllers
+
+**********************************************************************/
+
+#include "handctrl.h"
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+const device_type INTV_HANDCTRL = &device_creator<intv_handctrl_device>;
+
+
+static INPUT_PORTS_START( intv_handctrl )
+ PORT_START("KEYPAD")
+ PORT_BIT( 0x8000, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("1") PORT_CODE(KEYCODE_1_PAD)
+ PORT_BIT( 0x4000, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("2") PORT_CODE(KEYCODE_2_PAD)
+ PORT_BIT( 0x2000, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("3") PORT_CODE(KEYCODE_3_PAD)
+ PORT_BIT( 0x1000, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("4") PORT_CODE(KEYCODE_4_PAD)
+ PORT_BIT( 0x0800, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("5") PORT_CODE(KEYCODE_5_PAD)
+ PORT_BIT( 0x0400, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("6") PORT_CODE(KEYCODE_6_PAD)
+ PORT_BIT( 0x0200, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("7") PORT_CODE(KEYCODE_7_PAD)
+ PORT_BIT( 0x0100, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("8") PORT_CODE(KEYCODE_8_PAD)
+ PORT_BIT( 0x0080, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("9") PORT_CODE(KEYCODE_9_PAD)
+ PORT_BIT( 0x0040, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Clear") PORT_CODE(KEYCODE_DEL_PAD)
+ PORT_BIT( 0x0020, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("0") PORT_CODE(KEYCODE_0_PAD)
+ PORT_BIT( 0x0010, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Enter") PORT_CODE(KEYCODE_ENTER_PAD)
+ PORT_BIT( 0x0008, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("Upper") PORT_PLAYER(1)
+ PORT_BIT( 0x0004, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("Lower-Left") PORT_PLAYER(1)
+ PORT_BIT( 0x0002, IP_ACTIVE_HIGH, IPT_BUTTON3 ) PORT_NAME("Lower-Right") PORT_PLAYER(1)
+ PORT_BIT( 0x0001, IP_ACTIVE_HIGH, IPT_UNUSED )
+
+ PORT_START("DISC_DG")
+ PORT_BIT( 0x8000, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) PORT_NAME("Up") PORT_PLAYER(1) PORT_CONDITION("OPTIONS",0x01,EQUALS,0x00)
+ PORT_BIT( 0x4000, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Up-Up-Right") PORT_CONDITION("OPTIONS",0x01,EQUALS,0x00)
+ PORT_BIT( 0x2000, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Up-Right") PORT_CONDITION("OPTIONS",0x01,EQUALS,0x00)
+ PORT_BIT( 0x1000, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Right-Up-Right") PORT_CONDITION("OPTIONS",0x01,EQUALS,0x00)
+ PORT_BIT( 0x0800, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_NAME("Right") PORT_PLAYER(1) PORT_CONDITION("OPTIONS",0x01,EQUALS,0x00)
+ PORT_BIT( 0x0400, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Right-Down-Right") PORT_CONDITION("OPTIONS",0x01,EQUALS,0x00)
+ PORT_BIT( 0x0200, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Down-Right") PORT_CONDITION("OPTIONS",0x01,EQUALS,0x00)
+ PORT_BIT( 0x0100, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Down-Down-Right") PORT_CONDITION("OPTIONS",0x01,EQUALS,0x00)
+ PORT_BIT( 0x0080, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_NAME("Down") PORT_PLAYER(1) PORT_CONDITION("OPTIONS",0x01,EQUALS,0x00)
+ PORT_BIT( 0x0040, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Down-Down-Left") PORT_CONDITION("OPTIONS",0x01,EQUALS,0x00)
+ PORT_BIT( 0x0020, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Down-Left") PORT_CONDITION("OPTIONS",0x01,EQUALS,0x00)
+ PORT_BIT( 0x0010, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Left-Down-Left") PORT_CONDITION("OPTIONS",0x01,EQUALS,0x00)
+ PORT_BIT( 0x0008, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_NAME("Left") PORT_PLAYER(1) PORT_CONDITION("OPTIONS",0x01,EQUALS,0x00)
+ PORT_BIT( 0x0004, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Left-Up-Left") PORT_CONDITION("OPTIONS",0x01,EQUALS,0x00)
+ PORT_BIT( 0x0002, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Up-Left") PORT_CONDITION("OPTIONS",0x01,EQUALS,0x00)
+ PORT_BIT( 0x0001, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Up-Up-Left") PORT_CONDITION("OPTIONS",0x01,EQUALS,0x00)
+
+ PORT_START("DISC_AN_X")
+ PORT_BIT( 0xff, 0x50, IPT_AD_STICK_X ) PORT_NAME("X") PORT_MINMAX(0x00,0x9f) PORT_SENSITIVITY(100) PORT_KEYDELTA(0x50) PORT_CODE_DEC(KEYCODE_LEFT) PORT_CODE_INC(KEYCODE_RIGHT) PORT_PLAYER(1) PORT_CONDITION("OPTIONS",0x01,EQUALS,0x01)
+
+ PORT_START("DISC_AN_Y")
+ PORT_BIT( 0xff, 0x50, IPT_AD_STICK_Y ) PORT_NAME("Y") PORT_MINMAX(0x00,0x9f) PORT_SENSITIVITY(100) PORT_KEYDELTA(0x50) PORT_CODE_DEC(KEYCODE_UP) PORT_CODE_INC(KEYCODE_DOWN) PORT_PLAYER(1) PORT_CONDITION("OPTIONS",0x01,EQUALS,0x01)
+
+
+ PORT_START("OPTIONS")
+ PORT_CONFNAME( 0x01, 0x01, "Controller Disc Emulation" )
+ PORT_CONFSETTING( 0x00, "Digital" )
+ PORT_CONFSETTING( 0x01, "Analog" )
+INPUT_PORTS_END
+
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor intv_handctrl_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( intv_handctrl );
+}
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// intv_handctrl_device - constructor
+//-------------------------------------------------
+
+intv_handctrl_device::intv_handctrl_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
+ device_t(mconfig, INTV_HANDCTRL, "Mattel Intellivision Hand Controller", tag, owner, clock, "intv_hand", __FILE__),
+ device_intv_control_port_interface(mconfig, *this),
+ m_cfg(*this, "OPTIONS"),
+ m_keypad(*this, "KEYPAD"),
+ m_disc_dig(*this, "DISC_DG"),
+ m_disc_anx(*this, "DISC_AN_X"),
+ m_disc_any(*this, "DISC_AN_Y")
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void intv_handctrl_device::device_start()
+{
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void intv_handctrl_device::device_reset()
+{
+}
+
+
+//-------------------------------------------------
+// read_ctrl
+//-------------------------------------------------
+
+UINT8 intv_handctrl_device::read_ctrl()
+{
+ static const UINT8 keypad_table[] =
+ {
+ 0xff, 0x3f, 0x9f, 0x5f, 0xd7, 0xb7, 0x77, 0xdb,
+ 0xbb, 0x7b, 0xdd, 0xbd, 0x7d, 0xde, 0xbe, 0x7e
+ };
+
+ static const UINT8 disc_table[] =
+ {
+ 0xf3, 0xe3, 0xe7, 0xf7, 0xf6, 0xe6, 0xee, 0xfe,
+ 0xfc, 0xec, 0xed, 0xfd, 0xf9, 0xe9, 0xeb, 0xfb
+ };
+
+ static const UINT8 discyx_table[5][5] =
+ {
+ { 0xe3, 0xf3, 0xfb, 0xeb, 0xe9 },
+ { 0xe7, 0xe3, 0xfb, 0xe9, 0xf9 },
+ { 0xf7, 0xf7, 0xff, 0xfd, 0xfd },
+ { 0xf6, 0xe6, 0xfe, 0xec, 0xed },
+ { 0xe6, 0xee, 0xfe, 0xfc, 0xec }
+ };
+
+ int x, y;
+ UINT8 res = 0xff;
+
+ /* keypad */
+ x = m_keypad->read();
+ for (int i = 0; i < 16; i++)
+ {
+ if (BIT(x, i))
+ res &= keypad_table[i];
+ }
+
+ switch (m_cfg->read() & 1)
+ {
+ /* disc == digital */
+ case 0:
+ default:
+ x = m_disc_dig->read();
+ for (int i = 0; i < 16; i++)
+ {
+ if (BIT(x, i))
+ res &= disc_table[i];
+ }
+ break;
+
+ /* disc == _fake_ analog */
+ case 1:
+ x = m_disc_anx->read();
+ y = m_disc_any->read();
+ res &= discyx_table[y / 32][x / 32];
+ break;
+ }
+
+ return res;
+}
+
diff --git a/src/devices/bus/intv_ctrl/handctrl.h b/src/devices/bus/intv_ctrl/handctrl.h
new file mode 100644
index 00000000000..5b6fc4a3fb9
--- /dev/null
+++ b/src/devices/bus/intv_ctrl/handctrl.h
@@ -0,0 +1,55 @@
+// license:BSD-3-Clause
+// copyright-holders:Fabio Priuli
+/**********************************************************************
+
+ Mattel Intellivision Hand Controller
+
+**********************************************************************/
+
+#pragma once
+
+#ifndef __INTV_HANDCTRL__
+#define __INTV_HANDCTRL__
+
+
+#include "emu.h"
+#include "ctrl.h"
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> intv_handctrl_device
+
+class intv_handctrl_device : public device_t,
+ public device_intv_control_port_interface
+{
+public:
+ // construction/destruction
+ intv_handctrl_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ // optional information overrides
+ virtual ioport_constructor device_input_ports() const override;
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ // device_intv_control_port_interface overrides
+ virtual UINT8 read_ctrl() override;
+
+private:
+ required_ioport m_cfg;
+ required_ioport m_keypad;
+ required_ioport m_disc_dig;
+ required_ioport m_disc_anx;
+ required_ioport m_disc_any;
+};
+
+
+// device type definition
+extern const device_type INTV_HANDCTRL;
+
+
+#endif
diff --git a/src/devices/bus/snes_ctrl/joypad.h b/src/devices/bus/snes_ctrl/joypad.h
index 8daa922f20a..7ba3ea3e514 100644
--- a/src/devices/bus/snes_ctrl/joypad.h
+++ b/src/devices/bus/snes_ctrl/joypad.h
@@ -36,7 +36,7 @@ protected:
virtual void device_start() override;
virtual void device_reset() override;
- // device_sms_control_port_interface overrides
+ // device_snes_control_port_interface overrides
virtual UINT8 read_pin4() override;
virtual void write_strobe(UINT8 data) override;
virtual void port_poll() override;
diff --git a/src/devices/bus/snes_ctrl/mouse.h b/src/devices/bus/snes_ctrl/mouse.h
index 53602b96be3..39daae165d2 100644
--- a/src/devices/bus/snes_ctrl/mouse.h
+++ b/src/devices/bus/snes_ctrl/mouse.h
@@ -36,7 +36,7 @@ protected:
virtual void device_start() override;
virtual void device_reset() override;
- // device_sms_control_port_interface overrides
+ // device_snes_control_port_interface overrides
virtual UINT8 read_pin4() override;
virtual void write_strobe(UINT8 data) override;
virtual void port_poll() override;
diff --git a/src/devices/bus/snes_ctrl/multitap.h b/src/devices/bus/snes_ctrl/multitap.h
index e978a9d13ca..edc6ee110dc 100644
--- a/src/devices/bus/snes_ctrl/multitap.h
+++ b/src/devices/bus/snes_ctrl/multitap.h
@@ -37,7 +37,7 @@ protected:
virtual void device_start() override;
virtual void device_reset() override;
- // device_sms_control_port_interface overrides
+ // device_snes_control_port_interface overrides
virtual UINT8 read_pin4() override;
virtual UINT8 read_pin5() override;
virtual void write_strobe(UINT8 data) override;
diff --git a/src/devices/bus/snes_ctrl/pachinko.h b/src/devices/bus/snes_ctrl/pachinko.h
index 149d5775157..d340a1c8689 100644
--- a/src/devices/bus/snes_ctrl/pachinko.h
+++ b/src/devices/bus/snes_ctrl/pachinko.h
@@ -36,7 +36,7 @@ protected:
virtual void device_start() override;
virtual void device_reset() override;
- // device_sms_control_port_interface overrides
+ // device_snes_control_port_interface overrides
virtual UINT8 read_pin4() override;
virtual void write_strobe(UINT8 data) override;
virtual void port_poll() override;
diff --git a/src/devices/bus/snes_ctrl/sscope.h b/src/devices/bus/snes_ctrl/sscope.h
index 064ee0c941d..d625bc237ea 100644
--- a/src/devices/bus/snes_ctrl/sscope.h
+++ b/src/devices/bus/snes_ctrl/sscope.h
@@ -36,7 +36,7 @@ protected:
virtual void device_start() override;
virtual void device_reset() override;
- // device_sms_control_port_interface overrides
+ // device_snes_control_port_interface overrides
virtual UINT8 read_pin4() override;
virtual void write_strobe(UINT8 data) override;
virtual void port_poll() override;
diff --git a/src/devices/bus/snes_ctrl/twintap.h b/src/devices/bus/snes_ctrl/twintap.h
index 5adf0bf1cc1..085a9ead09c 100644
--- a/src/devices/bus/snes_ctrl/twintap.h
+++ b/src/devices/bus/snes_ctrl/twintap.h
@@ -36,7 +36,7 @@ protected:
virtual void device_start() override;
virtual void device_reset() override;
- // device_sms_control_port_interface overrides
+ // device_snes_control_port_interface overrides
virtual UINT8 read_pin4() override;
virtual void write_strobe(UINT8 data) override;
virtual void port_poll() override;
diff --git a/src/devices/bus/ti99_peb/spchsyn.cpp b/src/devices/bus/ti99_peb/spchsyn.cpp
index 1fb447f6d17..76c94cc7842 100644
--- a/src/devices/bus/ti99_peb/spchsyn.cpp
+++ b/src/devices/bus/ti99_peb/spchsyn.cpp
@@ -25,15 +25,15 @@
#include "sound/wave.h"
#include "machine/spchrom.h"
-#define TMS5220_ADDRESS_MASK 0x3FFFFUL /* 18-bit mask for tms5220 address */
-
-#define VERBOSE 1
-#define LOG logerror
+#define TRACE_MEM 0
+#define TRACE_ADDR 0
+#define TRACE_READY 0
/****************************************************************************/
ti_speech_synthesizer_device::ti_speech_synthesizer_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
-: ti_expansion_card_device(mconfig, TI99_SPEECH, "TI-99 Speech synthesizer (on adapter card)", tag, owner, clock, "ti99_speech", __FILE__), m_vsp(nullptr), m_read_mode(false)
+: ti_expansion_card_device(mconfig, TI99_SPEECH, "TI-99 Speech synthesizer (on adapter card)", tag, owner, clock, "ti99_speech", __FILE__),
+ m_vsp(nullptr), m_reading(false), m_sbe(false)
{
}
@@ -45,16 +45,15 @@ READ8Z_MEMBER( ti_speech_synthesizer_device::readz )
{
if (space.debugger_access()) return;
- if ((offset & m_select_mask)==m_select_value)
+ if (m_sbe)
{
- *value = m_vsp->status_r(space, offset, 0xff) & 0xff;
- if (VERBOSE>4) LOG("spchsyn: read value = %02x\n", *value);
+ *value = m_vsp->status_r(space, 0, 0xff) & 0xff;
+ if (TRACE_MEM) logerror("read value = %02x\n", *value);
// We should clear the lines at this point. The TI-99/4A clears the
// lines by setting the address bus to a different value, but the
// Geneve may behave differently. This may not 100% reflect the real
// situation, but it ensures a safe processing.
- m_vsp->rsq_w(TRUE);
- m_vsp->wsq_w(TRUE);
+ m_vsp->combined_rsq_wsq_w(space, 0, ~0);
}
}
@@ -65,10 +64,10 @@ WRITE8_MEMBER( ti_speech_synthesizer_device::write )
{
if (space.debugger_access()) return;
- if ((offset & m_select_mask)==(m_select_value | 0x0400))
+ if (m_sbe)
{
- if (VERBOSE>4) LOG("spchsyn: write value = %02x\n", data);
- m_vsp->data_w(space, offset, data);
+ if (TRACE_MEM) logerror("write value = %02x\n", data);
+ m_vsp->data_w(space, 0, data);
// Note that we must NOT clear the lines here. Find the lines in the
// READY callback below.
}
@@ -76,41 +75,29 @@ WRITE8_MEMBER( ti_speech_synthesizer_device::write )
SETADDRESS_DBIN_MEMBER( ti_speech_synthesizer_device::setaddress_dbin )
{
- if ((offset & m_select_mask & ~0x0400)==m_select_value)
+ // 1001 00xx xxxx xxx0 DBIN=1
+ // 1001 01xx xxxx xxx0 DBIN=0
+ // 1111 1000 0000 0001 mask
+ m_space = &space;
+ m_reading = (state==ASSERT_LINE);
+
+ bool valid = (((offset & 0x0400)==0) == m_reading);
+ m_sbe = ((offset & m_select_mask)==m_select_value) && valid;
+
+ if (m_sbe)
{
- if (VERBOSE>4) LOG("spchsyn: set address = %04x, dbin = %d\n", offset, state);
- m_read_mode = (state==ASSERT_LINE);
- bool readop = (offset & 0x0400)==0;
-
- if (m_read_mode != readop)
- {
- // reset all; this is not a valid access
- m_vsp->rsq_w(TRUE);
- m_vsp->wsq_w(TRUE);
- }
- else
- {
- if (readop)
- {
- // Caution: We MUST first clear (TRUE) one line to avoid
- // both RS* and WS* be asserted (otherwise tms5220 will report "illegal")
- m_vsp->wsq_w(TRUE);
- m_vsp->rsq_w(FALSE);
- }
- else
- {
- m_vsp->rsq_w(TRUE);
- m_vsp->wsq_w(FALSE);
- }
- }
+ if (TRACE_ADDR) logerror("set address = %04x, dbin = %d\n", offset, state);
+
+ // Caution: In the current tms5220 emulation, care must be taken
+ // to clear one line before asserting the other line, or otherwise
+ // both RS* and WS* are active, which is illegal.
+ // Alternatively, we'll use the combined settings method
+
+ m_vsp->combined_rsq_wsq_w(space, 0, m_reading? ~RS : ~WS);
}
else
- {
// If other address, turn off RS* and WS* (negative logic!)
- m_vsp->rsq_w(TRUE);
- m_vsp->wsq_w(TRUE);
- return;
- }
+ m_vsp->combined_rsq_wsq_w(space, 0, ~0);
}
/****************************************************************************/
@@ -121,40 +108,41 @@ WRITE_LINE_MEMBER( ti_speech_synthesizer_device::speech_ready )
// and we have to adapt a /READY to a READY line.
// The real synthesizer board uses a transistor for that purpose.
m_slot->set_ready((state==0)? ASSERT_LINE : CLEAR_LINE);
- if (VERBOSE>5) LOG("spchsyn: READY = %d\n", (state==0));
+ if (TRACE_READY) logerror("READY = %d\n", (state==0));
- if ((state==0) && !m_read_mode)
- {
+ if ((state==0) && !m_reading)
// Clear the lines only when we are done with writing.
- m_vsp->rsq_w(TRUE);
- m_vsp->wsq_w(TRUE);
- }
+ m_vsp->combined_rsq_wsq_w(*m_space, 0, ~0);
}
void ti_speech_synthesizer_device::device_start()
{
- m_read_mode = false;
}
void ti_speech_synthesizer_device::device_config_complete()
{
m_vsp = subdevice<cd2501e_device>("speechsyn");
+
+ // Need to configure the speech ROM for inverse bit order
+ speechrom_device* mem = subdevice<speechrom_device>("vsm");
+ mem->set_reverse_bit_order(true);
}
void ti_speech_synthesizer_device::device_reset()
{
- if (VERBOSE>5) LOG("spchsyn: reset\n");
if (m_genmod)
{
- m_select_mask = 0x1ffc01;
+ m_select_mask = 0x1ff801;
m_select_value = 0x179000;
}
else
{
- m_select_mask = 0x7fc01;
+ m_select_mask = 0x7f801;
m_select_value = 0x79000;
}
- m_read_mode = false;
+
+ m_reading = false;
+ m_sbe = false;
}
MACHINE_CONFIG_FRAGMENT( ti99_speech )
@@ -169,11 +157,8 @@ MACHINE_CONFIG_END
ROM_START( ti99_speech )
ROM_REGION(0x8000, "vsm", 0)
- // Note: the following line is actually wrong; the speech roms in the ti 99/4a and 99/8 are two VSM roms labeled CD2325A and CD2326A, and contain the same data as the following line rom does, but with the byte bit order reversed. This bit ordering issue needs to be fixed elsewhere in the code here before the original/real roms can be used.
- ROM_LOAD_OPTIONAL("spchrom.bin", 0x0000, 0x8000, CRC(58b155f7) SHA1(382292295c00dff348d7e17c5ce4da12a1d87763)) /* system speech ROM */
- // correct lines are:
- // ROM_LOAD_OPTIONAL("cd2325a.u2a", 0x0000, 0x4000, CRC(1f58b571) SHA1(0ef4f178716b575a1c0c970c56af8a8d97561ffe)) // at location u2, bottom of stack
- // ROM_LOAD_OPTIONAL("cd2326a.u2b", 0x4000, 0x4000, CRC(65d00401) SHA1(a367242c2c96cebf0e2bf21862f3f6734b2b3020)) // at location u2, top of stack
+ ROM_LOAD("cd2325a.u2a", 0x0000, 0x4000, CRC(1f58b571) SHA1(0ef4f178716b575a1c0c970c56af8a8d97561ffe)) // at location u2, bottom of stack
+ ROM_LOAD("cd2326a.u2b", 0x4000, 0x4000, CRC(65d00401) SHA1(a367242c2c96cebf0e2bf21862f3f6734b2b3020)) // at location u2, top of stack
ROM_END
machine_config_constructor ti_speech_synthesizer_device::device_mconfig_additions() const
diff --git a/src/devices/bus/ti99_peb/spchsyn.h b/src/devices/bus/ti99_peb/spchsyn.h
index 44e7aca54c4..e5c8d19f49b 100644
--- a/src/devices/bus/ti99_peb/spchsyn.h
+++ b/src/devices/bus/ti99_peb/spchsyn.h
@@ -40,8 +40,10 @@ protected:
virtual void device_config_complete() override;
private:
- cd2501e_device *m_vsp;
- bool m_read_mode;
+ address_space* m_space;
+ cd2501e_device* m_vsp;
+ bool m_reading;
+ bool m_sbe; // Signal "Speech block enable"
};
#endif
diff --git a/src/devices/machine/netlist.cpp b/src/devices/machine/netlist.cpp
index 1ca8d185e47..bae8137edff 100644
--- a/src/devices/machine/netlist.cpp
+++ b/src/devices/machine/netlist.cpp
@@ -300,9 +300,8 @@ void netlist_mame_device_t::device_start()
//printf("clock is %d\n", clock());
- m_netlist = global_alloc(netlist_mame_t(*this));
+ m_netlist = global_alloc(netlist_mame_t(*this, "netlist"));
m_setup = global_alloc(netlist::setup_t(m_netlist));
- netlist().init_object(*m_netlist, "netlist");
m_setup->init();
// register additional devices
@@ -325,9 +324,9 @@ void netlist_mame_device_t::device_start()
m_setup->start_devices();
m_setup->resolve_inputs();
- netlist().save(NAME(m_rem));
- netlist().save(NAME(m_div));
- netlist().save(NAME(m_old));
+ netlist().save_item(m_rem, this, "m_rem");
+ netlist().save_item(m_div, this, "m_div");
+ netlist().save_item(m_old, this, "m_old");
save_state();
@@ -348,7 +347,7 @@ void netlist_mame_device_t::device_reset()
LOG_DEV_CALLS(("device_reset\n"));
m_old = netlist::netlist_time::zero;
m_rem = netlist::netlist_time::zero;
- netlist().do_reset();
+ netlist().reset();
}
void netlist_mame_device_t::device_stop()
diff --git a/src/devices/machine/netlist.h b/src/devices/machine/netlist.h
index 9550ee57f9d..00b1e3ad352 100644
--- a/src/devices/machine/netlist.h
+++ b/src/devices/machine/netlist.h
@@ -85,8 +85,8 @@ class netlist_mame_t : public netlist::netlist_t
{
public:
- netlist_mame_t(netlist_mame_device_t &parent)
- : netlist::netlist_t(),
+ netlist_mame_t(netlist_mame_device_t &parent, const pstring &aname)
+ : netlist::netlist_t(aname),
m_parent(parent)
{}
virtual ~netlist_mame_t() { };
diff --git a/src/devices/sound/tms5220.cpp b/src/devices/sound/tms5220.cpp
index 8bc51d5683f..bb050d53182 100644
--- a/src/devices/sound/tms5220.cpp
+++ b/src/devices/sound/tms5220.cpp
@@ -525,7 +525,7 @@ static void printbits(long data, int num)
{
int i;
for (i=(num-1); i>=0; i--)
- fprintf(stderr,"%0ld", (data>>i)&1);
+ logerror("%0ld", (data>>i)&1);
}
#endif
#ifdef DEBUG_PARSE_FRAME_DUMP_HEX
@@ -534,19 +534,19 @@ static void printbits(long data, int num)
switch((num-1)&0xFC)
{
case 0:
- fprintf(stderr,"%0lx", data);
+ logerror("%0lx", data);
break;
case 4:
- fprintf(stderr,"%02lx", data);
+ logerror("%02lx", data);
break;
case 8:
- fprintf(stderr,"%03lx", data);
+ logerror("%03lx", data);
break;
case 12:
- fprintf(stderr,"%04lx", data);
+ logerror("%04lx", data);
break;
default:
- fprintf(stderr,"%04lx", data);
+ logerror("%04lx", data);
break;
}
}
@@ -625,7 +625,7 @@ void tms5220_device::data_write(int data)
m_fifo_tail = (m_fifo_tail + 1) % FIFO_SIZE;
m_fifo_count++;
#ifdef DEBUG_FIFO
- fprintf(stderr,"data_write: Added byte to FIFO (current count=%2d)\n", m_fifo_count);
+ logerror("data_write: Added byte to FIFO (current count=%2d)\n", m_fifo_count);
#endif
update_fifo_status_and_ints();
// if we just unset buffer low with that last write, and SPEN *was* zero (see circuit 251, sheet 12)
@@ -633,7 +633,7 @@ void tms5220_device::data_write(int data)
{
int i;
#ifdef DEBUG_FIFO
- fprintf(stderr,"data_write triggered SPEN to go active!\n");
+ logerror("data_write triggered SPEN to go active!\n");
#endif
// ...then we now have enough bytes to start talking; set zpar and clear out the new frame parameters (it will become old frame just before the first call to parse_frame() )
m_zpar = 1;
@@ -662,7 +662,7 @@ void tms5220_device::data_write(int data)
else
{
#ifdef DEBUG_FIFO
- fprintf(stderr,"data_write: Ran out of room in the tms52xx FIFO! this should never happen!\n");
+ logerror("data_write: Ran out of room in the tms52xx FIFO! this should never happen!\n");
// at this point, /READY should remain HIGH/inactive until the fifo has at least one byte open in it.
#endif
}
@@ -736,7 +736,7 @@ void tms5220_device::update_fifo_status_and_ints()
if (m_previous_TALK_STATUS == 1 && (TALK_STATUS == 0))
{
#ifdef VERBOSE
- fprintf(stderr,"Talk status WAS 1, is now 0, unsetting DDIS and firing an interrupt!\n");
+ logerror("Talk status WAS 1, is now 0, unsetting DDIS and firing an interrupt!\n");
#endif
set_interrupt_state(1);
m_DDIS = 0;
@@ -825,7 +825,7 @@ int tms5220_device::status_read()
/* clear the interrupt pin on status read */
set_interrupt_state(0);
#ifdef DEBUG_PIN_READS
- fprintf(stderr,"Status read: TS=%d BL=%d BE=%d\n", TALK_STATUS, m_buffer_low, m_buffer_empty);
+ logerror("Status read: TS=%d BL=%d BE=%d\n", TALK_STATUS, m_buffer_low, m_buffer_empty);
#endif
return (TALK_STATUS << 7) | (m_buffer_low << 6) | (m_buffer_empty << 5);
}
@@ -841,7 +841,7 @@ int tms5220_device::status_read()
int tms5220_device::ready_read()
{
#ifdef DEBUG_PIN_READS
- fprintf(stderr,"ready_read: ready pin read, io_ready is %d, fifo count is %d, DDIS(speak external) is %d\n", m_io_ready, m_fifo_count, m_DDIS);
+ logerror("ready_read: ready pin read, io_ready is %d, fifo count is %d, DDIS(speak external) is %d\n", m_io_ready, m_fifo_count, m_DDIS);
#endif
return ((m_fifo_count < FIFO_SIZE)||(!m_DDIS)) && m_io_ready;
}
@@ -899,7 +899,7 @@ int tms5220_device::cycles_to_ready()
int tms5220_device::int_read()
{
#ifdef DEBUG_PIN_READS
- fprintf(stderr,"int_read: irq pin read, state is %d\n", m_irq_pin);
+ logerror("int_read: irq pin read, state is %d\n", m_irq_pin);
#endif
return m_irq_pin;
}
@@ -918,7 +918,7 @@ void tms5220_device::process(INT16 *buffer, unsigned int size)
INT32 this_sample;
#ifdef VERBOSE
- fprintf(stderr,"process called with size of %d; IP=%d, PC=%d, subcycle=%d, m_SPEN=%d, m_TALK=%d, m_TALKD=%d\n", size, m_IP, m_PC, m_subcycle, m_SPEN, m_TALK, m_TALKD);
+ logerror("process called with size of %d; IP=%d, PC=%d, subcycle=%d, m_SPEN=%d, m_TALK=%d, m_TALKD=%d\n", size, m_IP, m_PC, m_subcycle, m_SPEN, m_TALK, m_TALKD);
#endif
/* loop until the buffer is full or we've stopped speaking */
@@ -975,14 +975,14 @@ void tms5220_device::process(INT16 *buffer, unsigned int size)
#ifdef DEBUG_GENERATION
/* Debug info for current parsed frame */
- fprintf(stderr, "OLDE: %d; NEWE: %d; OLDP: %d; NEWP: %d ", OLD_FRAME_SILENCE_FLAG, NEW_FRAME_SILENCE_FLAG, OLD_FRAME_UNVOICED_FLAG, NEW_FRAME_UNVOICED_FLAG);
- fprintf(stderr,"Processing new frame: ");
+ logerror( "OLDE: %d; NEWE: %d; OLDP: %d; NEWP: %d ", OLD_FRAME_SILENCE_FLAG, NEW_FRAME_SILENCE_FLAG, OLD_FRAME_UNVOICED_FLAG, NEW_FRAME_UNVOICED_FLAG);
+ logerror("Processing new frame: ");
if (m_inhibit == 0)
- fprintf(stderr, "Normal Frame\n");
+ logerror( "Normal Frame\n");
else
- fprintf(stderr,"Interpolation Inhibited\n");
- fprintf(stderr,"*** current Energy, Pitch and Ks = %04d, %04d, %04d, %04d, %04d, %04d, %04d, %04d, %04d, %04d, %04d, %04d\n",m_current_energy, m_current_pitch, m_current_k[0], m_current_k[1], m_current_k[2], m_current_k[3], m_current_k[4], m_current_k[5], m_current_k[6], m_current_k[7], m_current_k[8], m_current_k[9]);
- fprintf(stderr,"*** target Energy(idx), Pitch, and Ks = %04d(%x),%04d, %04d, %04d, %04d, %04d, %04d, %04d, %04d, %04d, %04d, %04d\n",
+ logerror("Interpolation Inhibited\n");
+ logerror("*** current Energy, Pitch and Ks = %04d, %04d, %04d, %04d, %04d, %04d, %04d, %04d, %04d, %04d, %04d, %04d\n",m_current_energy, m_current_pitch, m_current_k[0], m_current_k[1], m_current_k[2], m_current_k[3], m_current_k[4], m_current_k[5], m_current_k[6], m_current_k[7], m_current_k[8], m_current_k[9]);
+ logerror("*** target Energy(idx), Pitch, and Ks = %04d(%x),%04d, %04d, %04d, %04d, %04d, %04d, %04d, %04d, %04d, %04d, %04d\n",
(m_coeff->energytable[m_new_frame_energy_idx] * (1-m_zpar)),
m_new_frame_energy_idx,
(m_coeff->pitchtable[m_new_frame_pitch_idx] * (1-m_zpar)),
@@ -1006,7 +1006,7 @@ void tms5220_device::process(INT16 *buffer, unsigned int size)
int samples_per_frame = m_subc_reload?175:266; // either (13 A cycles + 12 B cycles) * 7 interps for normal SPEAK/SPKEXT, or (13*2 A cycles + 12 B cycles) * 7 interps for SPKSLOW
//int samples_per_frame = m_subc_reload?200:304; // either (13 A cycles + 12 B cycles) * 8 interps for normal SPEAK/SPKEXT, or (13*2 A cycles + 12 B cycles) * 8 interps for SPKSLOW
int current_sample = (m_subcycle - m_subc_reload)+(m_PC*(3-m_subc_reload))+((m_subc_reload?25:38)*((m_IP-1)&7));
- //fprintf(stderr, "CS: %03d", current_sample);
+ //logerror( "CS: %03d", current_sample);
// reset the current energy, pitch, etc to what it was at frame start
m_current_energy = (m_coeff->energytable[m_old_frame_energy_idx] * (1-m_old_zpar));
m_current_pitch = (m_coeff->pitchtable[m_old_frame_pitch_idx] * (1-m_old_zpar));
@@ -1089,18 +1089,18 @@ void tms5220_device::process(INT16 *buffer, unsigned int size)
}
this_sample = lattice_filter(); /* execute lattice filter */
#ifdef DEBUG_GENERATION_VERBOSE
- //fprintf(stderr,"C:%01d; ",m_subcycle);
- fprintf(stderr,"IP:%01d PC:%02d X:%04d E:%03d P:%03d Pc:%03d ",m_IP, m_PC, m_excitation_data, m_current_energy, m_current_pitch, m_pitch_count);
- //fprintf(stderr,"X:%04d E:%03d P:%03d Pc:%03d ", m_excitation_data, m_current_energy, m_current_pitch, m_pitch_count);
+ //logerror("C:%01d; ",m_subcycle);
+ logerror("IP:%01d PC:%02d X:%04d E:%03d P:%03d Pc:%03d ",m_IP, m_PC, m_excitation_data, m_current_energy, m_current_pitch, m_pitch_count);
+ //logerror("X:%04d E:%03d P:%03d Pc:%03d ", m_excitation_data, m_current_energy, m_current_pitch, m_pitch_count);
for (i=0; i<10; i++)
- fprintf(stderr,"K%d:%04d ", i+1, m_current_k[i]);
- fprintf(stderr,"Out:%06d ", this_sample);
+ logerror("K%d:%04d ", i+1, m_current_k[i]);
+ logerror("Out:%06d ", this_sample);
//#ifdef PERFECT_INTERPOLATION_HACK
-// fprintf(stderr,"%d%d%d%d",m_old_zpar,m_zpar,m_old_uv_zpar,m_uv_zpar);
+// logerror("%d%d%d%d",m_old_zpar,m_zpar,m_old_uv_zpar,m_uv_zpar);
//#else
-// fprintf(stderr,"x%dx%d",m_zpar,m_uv_zpar);
+// logerror("x%dx%d",m_zpar,m_uv_zpar);
//#endif
- fprintf(stderr,"\n");
+ logerror("\n");
#endif
/* next, force result to 14 bits (since its possible that the addition at the final (k1) stage of the lattice overflowed) */
while (this_sample > 16383) this_sample -= 32768;
@@ -1145,17 +1145,17 @@ void tms5220_device::process(INT16 *buffer, unsigned int size)
OLD_FRAME_UNVOICED_FLAG = NEW_FRAME_UNVOICED_FLAG; // m_OLDP
/* if TALK was clear last frame, halt speech now, since TALKD (latched from TALK on new frame) just went inactive. */
#ifdef DEBUG_GENERATION
- fprintf(stderr,"RESETL4, about to update status: IP=%d, PC=%d, subcycle=%d, m_SPEN=%d, m_TALK=%d, m_TALKD=%d\n", m_IP, m_PC, m_subcycle, m_SPEN, m_TALK, m_TALKD);
+ logerror("RESETL4, about to update status: IP=%d, PC=%d, subcycle=%d, m_SPEN=%d, m_TALK=%d, m_TALKD=%d\n", m_IP, m_PC, m_subcycle, m_SPEN, m_TALK, m_TALKD);
#endif
#ifdef DEBUG_GENERATION
if ((!m_TALK) && (!m_SPEN))
- fprintf(stderr,"tms5220_process: processing frame: TALKD = 0 caused by stop frame or buffer empty, halting speech.\n");
+ logerror("tms5220_process: processing frame: TALKD = 0 caused by stop frame or buffer empty, halting speech.\n");
#endif
m_TALKD = m_TALK; // TALKD is latched from TALK
update_fifo_status_and_ints(); // to trigger an interrupt if TALK_STATUS has changed
if ((!m_TALK) && m_SPEN) m_TALK = 1; // TALK is only activated if it wasn't already active, if m_SPEN is active, and if we're in RESETL4 (which we are).
#ifdef DEBUG_GENERATION
- fprintf(stderr,"RESETL4, status updated: IP=%d, PC=%d, subcycle=%d, m_SPEN=%d, m_TALK=%d, m_TALKD=%d\n", m_IP, m_PC, m_subcycle, m_SPEN, m_TALK, m_TALKD);
+ logerror("RESETL4, status updated: IP=%d, PC=%d, subcycle=%d, m_SPEN=%d, m_TALK=%d, m_TALKD=%d\n", m_IP, m_PC, m_subcycle, m_SPEN, m_TALK, m_TALKD);
#endif
}
m_subcycle = m_subc_reload;
@@ -1217,7 +1217,7 @@ static INT16 clip_analog(INT16 cliptemp)
* 0x xxxx xxxx xxxx -> 0b01111111
*/
#ifdef DEBUG_CLIP
- if ((cliptemp > 2047) || (cliptemp < -2048)) fprintf(stderr,"clipping cliptemp to range; was %d\n", cliptemp);
+ if ((cliptemp > 2047) || (cliptemp < -2048)) logerror("clipping cliptemp to range; was %d\n", cliptemp);
#endif
if (cliptemp > 2047) cliptemp = 2047;
else if (cliptemp < -2048) cliptemp = -2048;
@@ -1257,8 +1257,8 @@ static INT32 matrix_multiply(INT32 a, INT32 b)
while (b<-16384) { b+=32768; }
result = ((a*b)>>9); /** TODO: this isn't technically right to the chip, which truncates the lowest result bit, but it causes glitches otherwise. **/
#ifdef VERBOSE
- if (result>16383) fprintf(stderr,"matrix multiplier overflowed! a: %x, b: %x, result: %x", a, b, result);
- if (result<-16384) fprintf(stderr,"matrix multiplier underflowed! a: %x, b: %x, result: %x", a, b, result);
+ if (result>16383) logerror("matrix multiplier overflowed! a: %x, b: %x, result: %x", a, b, result);
+ if (result<-16384) logerror("matrix multiplier underflowed! a: %x, b: %x, result: %x", a, b, result);
#endif
return result;
}
@@ -1321,18 +1321,18 @@ INT32 tms5220_device::lattice_filter()
m_previous_energy = m_current_energy;
#ifdef DEBUG_LATTICE
int i;
- fprintf(stderr,"V:%04d ", m_u[10]);
+ logerror("V:%04d ", m_u[10]);
for (i = 9; i >= 0; i--)
{
- fprintf(stderr,"Y%d:%04d ", i+1, m_u[i]);
+ logerror("Y%d:%04d ", i+1, m_u[i]);
}
- fprintf(stderr,"\n");
- fprintf(stderr,"E:%04d ", err);
+ logerror("\n");
+ logerror("E:%04d ", err);
for (i = 9; i >= 0; i--)
{
- fprintf(stderr,"b%d:%04d ", i+1, m_x[i]);
+ logerror("b%d:%04d ", i+1, m_x[i]);
}
- fprintf(stderr,"\n");
+ logerror("\n");
#endif
return m_u[0];
}
@@ -1348,7 +1348,7 @@ void tms5220_device::process_command(unsigned char cmd)
{
int i;
#ifdef DEBUG_COMMAND_DUMP
- fprintf(stderr,"process_command called with parameter %02X\n",cmd);
+ logerror("process_command called with parameter %02X\n",cmd);
#endif
/* parse the command */
switch (cmd & 0x70)
@@ -1379,7 +1379,7 @@ void tms5220_device::process_command(unsigned char cmd)
if (TALK_STATUS == 0) /* TALKST must be clear for RB */
{
#ifdef VERBOSE
- fprintf(stderr,"read and branch command received\n");
+ logerror("read and branch command received\n");
#endif
m_RDB_flag = FALSE;
if (m_speechrom)
@@ -1495,7 +1495,7 @@ void tms5220_device::parse_frame()
i = extract_bits(2);
#ifdef DEBUG_PARSE_FRAME_DUMP
printbits(i,2);
- fprintf(stderr," ");
+ logerror(" ");
#endif
m_IP = reload_table[i];
}
@@ -1509,7 +1509,7 @@ void tms5220_device::parse_frame()
m_new_frame_energy_idx = extract_bits(m_coeff->energy_bits);
#ifdef DEBUG_PARSE_FRAME_DUMP
printbits(m_new_frame_energy_idx,m_coeff->energy_bits);
- fprintf(stderr," ");
+ logerror(" ");
#endif
update_fifo_status_and_ints();
if (m_DDIS && m_buffer_empty) goto ranout;
@@ -1522,14 +1522,14 @@ void tms5220_device::parse_frame()
rep_flag = extract_bits(1);
#ifdef DEBUG_PARSE_FRAME_DUMP
printbits(rep_flag, 1);
- fprintf(stderr," ");
+ logerror(" ");
#endif
// attempt to extract the pitch
m_new_frame_pitch_idx = extract_bits(m_coeff->pitch_bits);
#ifdef DEBUG_PARSE_FRAME_DUMP
printbits(m_new_frame_pitch_idx,m_coeff->pitch_bits);
- fprintf(stderr," ");
+ logerror(" ");
#endif
// if the new frame is unvoiced, be sure to zero out the k5-k10 parameters
m_uv_zpar = NEW_FRAME_UNVOICED_FLAG;
@@ -1545,7 +1545,7 @@ void tms5220_device::parse_frame()
m_new_frame_k_idx[i] = extract_bits(m_coeff->kbits[i]);
#ifdef DEBUG_PARSE_FRAME_DUMP
printbits(m_new_frame_k_idx[i],m_coeff->kbits[i]);
- fprintf(stderr," ");
+ logerror(" ");
#endif
update_fifo_status_and_ints();
if (m_DDIS && m_buffer_empty) goto ranout;
@@ -1564,25 +1564,25 @@ void tms5220_device::parse_frame()
m_new_frame_k_idx[i] = extract_bits(m_coeff->kbits[i]);
#ifdef DEBUG_PARSE_FRAME_DUMP
printbits(m_new_frame_k_idx[i],m_coeff->kbits[i]);
- fprintf(stderr," ");
+ logerror(" ");
#endif
update_fifo_status_and_ints();
if (m_DDIS && m_buffer_empty) goto ranout;
}
#ifdef DEBUG_PARSE_FRAME_DUMP
- fprintf(stderr,"\n");
+ logerror("\n");
#endif
#ifdef VERBOSE
if (m_DDIS)
- fprintf(stderr,"Parsed a frame successfully in FIFO - %d bits remaining\n", (m_fifo_count*8)-(m_fifo_bits_taken));
+ logerror("Parsed a frame successfully in FIFO - %d bits remaining\n", (m_fifo_count*8)-(m_fifo_bits_taken));
else
- fprintf(stderr,"Parsed a frame successfully in ROM\n");
+ logerror("Parsed a frame successfully in ROM\n");
#endif
return;
ranout:
#ifdef DEBUG_FRAME_ERRORS
- fprintf(stderr,"Ran out of bits on a parse!\n");
+ logerror("Ran out of bits on a parse!\n");
#endif
return;
}
@@ -1597,7 +1597,7 @@ void tms5220_device::set_interrupt_state(int state)
{
if (!TMS5220_IS_52xx) return; // bail out if not a 52xx chip, since there's no int pin
#ifdef DEBUG_PIN_READS
- fprintf(stderr,"irq pin set to state %d\n", state);
+ logerror("irq pin set to state %d\n", state);
#endif
if (!m_irq_handler.isnull() && state != m_irq_pin)
m_irq_handler(!state);
@@ -1614,7 +1614,7 @@ void tms5220_device::update_ready_state()
{
int state = ready_read();
#ifdef DEBUG_PIN_READS
- fprintf(stderr,"ready pin set to state %d\n", state);
+ logerror("ready pin set to state %d\n", state);
#endif
if (!m_readyq_handler.isnull() && state != m_ready_pin)
m_readyq_handler(!state);
@@ -1759,7 +1759,7 @@ void tms5220_device::device_reset()
m_speechrom->read(1);
m_schedule_dummy_read = FALSE;
}
-
+
// 5110 specific stuff
m_PDC = 0;
m_CTL_pins = 0;
@@ -1790,8 +1790,8 @@ void tms5220_device::device_timer(emu_timer &timer, device_timer_id id, int para
/* Write */
/* bring up to date first */
#ifdef DEBUG_IO_READY
- fprintf(stderr,"Serviced write: %02x\n", m_write_latch);
- //fprintf(stderr, "Processed write data: %02X\n", m_write_latch);
+ logerror("Serviced write: %02x\n", m_write_latch);
+ //logerror( "Processed write data: %02X\n", m_write_latch);
#endif
m_stream->update();
data_write(m_write_latch);
@@ -1802,7 +1802,7 @@ void tms5220_device::device_timer(emu_timer &timer, device_timer_id id, int para
m_stream->update();
m_read_latch = status_read();
#ifdef DEBUG_IO_READY
- fprintf(stderr,"Serviced read, returning %02x\n", m_read_latch);
+ logerror("Serviced read, returning %02x\n", m_read_latch);
#endif
break;
case 0x03:
@@ -1829,7 +1829,7 @@ WRITE_LINE_MEMBER( tms5220_device::rsq_w )
m_true_timing = 1;
state &= 0x01;
#ifdef DEBUG_RS_WS
- fprintf(stderr,"/RS written with data: %d\n", state);
+ logerror("/RS written with data: %d\n", state);
#endif
new_val = (m_rs_ws & 0x01) | (state<<1);
if (new_val != m_rs_ws)
@@ -1842,7 +1842,7 @@ WRITE_LINE_MEMBER( tms5220_device::rsq_w )
#ifdef DEBUG_RS_WS
else
/* illegal */
- fprintf(stderr,"tms5220_rsq_w: illegal\n");
+ logerror("tms5220_rsq_w: illegal\n");
#endif
return;
}
@@ -1860,7 +1860,7 @@ WRITE_LINE_MEMBER( tms5220_device::rsq_w )
{
/* high to low - schedule ready cycle */
#ifdef DEBUG_RS_WS
- fprintf(stderr,"Scheduling ready cycle for /RS...\n");
+ logerror("Scheduling ready cycle for /RS...\n");
#endif
/* upon /RS being activated, /READY goes inactive after 100 nsec from data sheet, through 3 asynchronous gates on patent. This is effectively within one clock, so we immediately set io_ready to 0 and activate the callback. */
m_io_ready = 0;
@@ -1881,7 +1881,7 @@ WRITE_LINE_MEMBER( tms5220_device::wsq_w )
m_true_timing = 1;
state &= 0x01;
#ifdef DEBUG_RS_WS
- fprintf(stderr,"/WS written with data: %d\n", state);
+ logerror("/WS written with data: %d\n", state);
#endif
new_val = (m_rs_ws & 0x02) | (state<<0);
if (new_val != m_rs_ws)
@@ -1894,7 +1894,7 @@ WRITE_LINE_MEMBER( tms5220_device::wsq_w )
#ifdef DEBUG_RS_WS
else
/* illegal */
- fprintf(stderr,"tms5220_wsq_w: illegal\n");
+ logerror("tms5220_wsq_w: illegal\n");
#endif
return;
}
@@ -1912,7 +1912,7 @@ WRITE_LINE_MEMBER( tms5220_device::wsq_w )
{
/* high to low - schedule ready cycle */
#ifdef DEBUG_RS_WS
- fprintf(stderr,"Scheduling ready cycle for /WS...\n");
+ logerror("Scheduling ready cycle for /WS...\n");
#endif
/* upon /WS being activated, /READY goes inactive after 100 nsec from data sheet, through 3 asynchronous gates on patent. This is effectively within one clock, so we immediately set io_ready to 0 and activate the callback. */
m_io_ready = 0;
@@ -1944,7 +1944,7 @@ WRITE8_MEMBER( tms5220_device::combined_rsq_wsq_w )
UINT8 falling_edges;
m_true_timing = 1;
#ifdef DEBUG_RS_WS
- fprintf(stderr,"/RS and /WS written with %d and %d respectively\n", (data&2)>>1), data&1;
+ logerror("/RS and /WS written with %d and %d respectively\n", (data&2)>>1, data&1);
#endif
new_val = data&0x03;
if (new_val != m_rs_ws)
@@ -1959,7 +1959,7 @@ WRITE8_MEMBER( tms5220_device::combined_rsq_wsq_w )
#ifdef DEBUG_RS_WS
else
/* illegal */
- fprintf(stderr,"tms5220_combined_rsq_wsq_w: illegal\n");
+ logerror("tms5220_combined_rsq_wsq_w: illegal\n");
#endif
return;
case 3:
@@ -1968,10 +1968,10 @@ WRITE8_MEMBER( tms5220_device::combined_rsq_wsq_w )
return;
case 2: // /WS active, /RS not
/* check for falling or rising edge */
- if (!(falling_edges&0x02)) return; /* low to high, do nothing */
+ if (!(falling_edges&0x01)) return; /* low to high, do nothing */
/* high to low - schedule ready cycle */
#ifdef DEBUG_RS_WS
- fprintf(stderr,"Scheduling ready cycle for /WS...\n");
+ logerror("Scheduling ready cycle for /WS...\n");
#endif
/* upon /WS being activated, /READY goes inactive after 100 nsec from data sheet, through 3 asynchronous gates on patent. This is effectively within one clock, so we immediately set io_ready to 0 and activate the callback. */
m_io_ready = 0;
@@ -1991,10 +1991,10 @@ WRITE8_MEMBER( tms5220_device::combined_rsq_wsq_w )
return;
case 1: // /RS active, /WS not
/* check for falling or rising edge */
- if (!(falling_edges&0x01)) return; /* low to high, do nothing */
+ if (!(falling_edges&0x02)) return; /* low to high, do nothing */
/* high to low - schedule ready cycle */
#ifdef DEBUG_RS_WS
- fprintf(stderr,"Scheduling ready cycle for /RS...\n");
+ logerror("Scheduling ready cycle for /RS...\n");
#endif
/* upon /RS being activated, /READY goes inactive after 100 nsec from data sheet, through 3 asynchronous gates on patent. This is effectively within one clock, so we immediately set io_ready to 0 and activate the callback. */
m_io_ready = 0;
@@ -2019,7 +2019,7 @@ WRITE8_MEMBER( tms5220_device::data_w )
if (space.debugger_access()) return;
#ifdef DEBUG_RS_WS
- fprintf(stderr,"tms5220_data_w: data %02x\n", data);
+ logerror("tms5220_data_w: data %02x\n", data);
#endif
if (!m_true_timing)
{
@@ -2032,7 +2032,7 @@ WRITE8_MEMBER( tms5220_device::data_w )
/* actually in a write ? */
#ifdef DEBUG_RS_WS
if (!(m_rs_ws == 0x02))
- fprintf(stderr,"tms5220_data_w: data written outside ws, status: %02x!\n", m_rs_ws);
+ logerror("tms5220_data_w: data written outside ws, status: %02x!\n", m_rs_ws);
#endif
m_write_latch = data;
}
@@ -2064,7 +2064,7 @@ READ8_MEMBER( tms5220_device::status_r )
return m_read_latch;
#ifdef DEBUG_RS_WS
else
- fprintf(stderr,"tms5220_status_r: data read outside rs!\n");
+ logerror("tms5220_status_r: data read outside rs!\n");
#endif
return 0xff;
}
diff --git a/src/devices/sound/tms5220.h b/src/devices/sound/tms5220.h
index 706a728b28a..4e17dd53574 100644
--- a/src/devices/sound/tms5220.h
+++ b/src/devices/sound/tms5220.h
@@ -8,6 +8,12 @@
#include "emu.h"
#include "machine/spchrom.h"
+enum
+{
+ RS=2,
+ WS=1
+};
+
/* HACK: if defined, uses impossibly perfect 'straight line' interpolation */
#undef PERFECT_INTERPOLATION_HACK
diff --git a/src/emu/debug/debugcmd.h b/src/emu/debug/debugcmd.h
index d3c52225550..311f19e5dbd 100644
--- a/src/emu/debug/debugcmd.h
+++ b/src/emu/debug/debugcmd.h
@@ -11,6 +11,7 @@
#ifndef __DEBUGCMD_H__
#define __DEBUGCMD_H__
+#include "emu.h"
/***************************************************************************
FUNCTION PROTOTYPES
diff --git a/src/emu/debug/debugcon.h b/src/emu/debug/debugcon.h
index c15874184af..95aa2e0f8c8 100644
--- a/src/emu/debug/debugcon.h
+++ b/src/emu/debug/debugcon.h
@@ -11,6 +11,7 @@
#ifndef __DEBUGCON_H__
#define __DEBUGCON_H__
+#include "emu.h"
#include "textbuf.h"
diff --git a/src/emu/emu.h b/src/emu/emu.h
index 07474f871b3..1411ecda1db 100644
--- a/src/emu/emu.h
+++ b/src/emu/emu.h
@@ -106,9 +106,6 @@ typedef device_t * (*machine_config_constructor)(machine_config &config, device_
#include "sound.h"
#include "speaker.h"
-// user interface
-#include "ui/ui.h"
-
// generic helpers
#include "devcb.h"
#include "dispatch.h"
@@ -118,6 +115,5 @@ typedef device_t * (*machine_config_constructor)(machine_config &config, device_
// member templates that don't like incomplete types
#include "device.ipp"
-#include "machine.ipp"
#endif /* __EMU_H__ */
diff --git a/src/emu/luaengine.cpp b/src/emu/luaengine.cpp
index a5cd130fb81..d6acd940726 100644
--- a/src/emu/luaengine.cpp
+++ b/src/emu/luaengine.cpp
@@ -1738,9 +1738,8 @@ lua_engine::~lua_engine()
close();
}
-std::vector<lua_engine::menu_item> &lua_engine::menu_populate(std::string &menu)
+void lua_engine::menu_populate(std::string &menu, std::vector<menu_item> &menu_list)
{
- std::vector<menu_item> &menu_list = *global_alloc(std::vector<menu_item>);
std::string field = "menu_pop_" + menu;
lua_settop(m_lua_state, 0);
lua_getfield(m_lua_state, LUA_REGISTRYINDEX, field.c_str());
@@ -1748,19 +1747,19 @@ std::vector<lua_engine::menu_item> &lua_engine::menu_populate(std::string &menu)
if(!lua_isfunction(m_lua_state, -1))
{
lua_pop(m_lua_state, 1);
- return menu_list;
+ return;
}
if(int error = lua_pcall(m_lua_state, 0, 1, 0))
{
if(error == 2)
printf("%s\n", lua_tostring(m_lua_state, -1));
lua_pop(m_lua_state, 1);
- return menu_list;
+ return;
}
if(!lua_istable(m_lua_state, -1))
{
lua_pop(m_lua_state, 1);
- return menu_list;
+ return;
}
lua_pushnil(m_lua_state);
@@ -1776,14 +1775,13 @@ std::vector<lua_engine::menu_item> &lua_engine::menu_populate(std::string &menu)
item.subtext = lua_tostring(m_lua_state, -1);
lua_pop(m_lua_state, 1);
lua_rawgeti(m_lua_state, -1, 3);
- item.flags = lua_tointeger(m_lua_state, -1);
+ item.flags = lua_tostring(m_lua_state, -1);
lua_pop(m_lua_state, 1);
menu_list.push_back(item);
}
lua_pop(m_lua_state, 1);
}
lua_pop(m_lua_state, 1);
- return menu_list;
}
bool lua_engine::menu_callback(std::string &menu, int index, std::string event)
diff --git a/src/emu/luaengine.h b/src/emu/luaengine.h
index 69247a84cdf..aaa774d00e6 100644
--- a/src/emu/luaengine.h
+++ b/src/emu/luaengine.h
@@ -52,9 +52,9 @@ public:
struct menu_item {
std::string text;
std::string subtext;
- int flags;
+ std::string flags;
};
- std::vector<menu_item> &menu_populate(std::string &menu);
+ void menu_populate(std::string &menu, std::vector<menu_item> &menu_list);
bool menu_callback(std::string &menu, int index, std::string event);
void resume(lua_State *L, int nparam = 0, lua_State *root = nullptr);
diff --git a/src/emu/machine.cpp b/src/emu/machine.cpp
index 726979cadbc..7940bd6dfb0 100644
--- a/src/emu/machine.cpp
+++ b/src/emu/machine.cpp
@@ -1202,6 +1202,24 @@ void running_machine::nvram_save()
}
}
}
+
+
+//**************************************************************************
+// OUTPUT
+//**************************************************************************
+
+void running_machine::popup_clear() const
+{
+ ui().popup_time(0, " ");
+}
+
+void running_machine::popup_message(util::format_argument_pack<std::ostream> const &args) const
+{
+ std::string const temp(string_format(args));
+ ui().popup_time(temp.length() / 40 + 2, "%s", temp);
+}
+
+
//**************************************************************************
// CALLBACK ITEMS
//**************************************************************************
diff --git a/src/emu/machine.h b/src/emu/machine.h
index f892e79c3c9..6f18ef60001 100644
--- a/src/emu/machine.h
+++ b/src/emu/machine.h
@@ -17,6 +17,7 @@
#ifndef __MACHINE_H__
#define __MACHINE_H__
+#include "strformat.h"
#include "vecstream.h"
#include <time.h>
@@ -274,6 +275,8 @@ private:
std::string nvram_filename(device_t &device) const;
void nvram_load();
void nvram_save();
+ void popup_clear() const;
+ void popup_message(util::format_argument_pack<std::ostream> const &args) const;
// internal callbacks
static void logfile_callback(const running_machine &machine, const char *buffer);
@@ -382,4 +385,54 @@ private:
mutable util::ovectorstream m_string_buffer;
};
+
+
+//**************************************************************************
+// MEMBER TEMPLATES
+//**************************************************************************
+
+/*-------------------------------------------------
+ popmessage - pop up a user-visible message
+-------------------------------------------------*/
+
+template <typename Format, typename... Params>
+inline void running_machine::popmessage(Format &&fmt, Params &&... args) const
+{
+ // if the format is NULL, it is a signal to clear the popmessage
+ // otherwise, generate the buffer and call the UI to display the message
+ if (is_null<Format>::value(fmt))
+ popup_clear();
+ else
+ popup_message(util::make_format_argument_pack(std::forward<Format>(fmt), std::forward<Params>(args)...));
+}
+
+
+/*-------------------------------------------------
+ logerror - log to the debugger and any other
+ OSD-defined output streams
+-------------------------------------------------*/
+
+template <typename Format, typename... Params>
+inline void running_machine::logerror(Format &&fmt, Params &&... args) const
+{
+ // process only if there is a target
+ if (!m_logerror_list.empty())
+ {
+ g_profiler.start(PROFILER_LOGERROR);
+
+ // dump to the buffer
+ m_string_buffer.clear();
+ m_string_buffer.seekp(0);
+ util::stream_format(m_string_buffer, std::forward<Format>(fmt), std::forward<Params>(args)...);
+ m_string_buffer.put('\0');
+
+ // log to all callbacks
+ char const *const str(&m_string_buffer.vec()[0]);
+ for (auto &cb : m_logerror_list)
+ (cb->m_func)(*this, str);
+
+ g_profiler.stop();
+ }
+}
+
#endif /* __MACHINE_H__ */
diff --git a/src/emu/machine.ipp b/src/emu/machine.ipp
deleted file mode 100644
index 44d029fd309..00000000000
--- a/src/emu/machine.ipp
+++ /dev/null
@@ -1,77 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Aaron Giles
-/***************************************************************************
-
- machine.ipp
-
- Controls execution of the core MAME system.
-
-***************************************************************************/
-
-#pragma once
-
-#ifndef __EMU_H__
-#error Dont include this file directly; include emu.h instead.
-#endif
-
-#ifndef __MACHINE_IPP__
-#define __MACHINE_IPP__
-
-#include "strformat.h"
-
-//**************************************************************************
-// MEMBER TEMPLATES
-//**************************************************************************
-
-/*-------------------------------------------------
- popmessage - pop up a user-visible message
--------------------------------------------------*/
-
-template <typename Format, typename... Params>
-inline void running_machine::popmessage(Format &&fmt, Params &&... args) const
-{
- if (is_null<Format>::value(fmt))
- {
- // if the format is NULL, it is a signal to clear the popmessage
- ui().popup_time(0, " ");
- }
- else
- {
- // otherwise, generate the buffer and call the UI to display the message
- std::string const temp(string_format(std::forward<Format>(fmt), std::forward<Params>(args)...));
-
- // pop it in the UI
- ui().popup_time(temp.length() / 40 + 2, "%s", temp.c_str());
- }
-}
-
-
-/*-------------------------------------------------
- logerror - log to the debugger and any other
- OSD-defined output streams
--------------------------------------------------*/
-
-template <typename Format, typename... Params>
-inline void running_machine::logerror(Format &&fmt, Params &&... args) const
-{
- // process only if there is a target
- if (!m_logerror_list.empty())
- {
- g_profiler.start(PROFILER_LOGERROR);
-
- // dump to the buffer
- m_string_buffer.clear();
- m_string_buffer.seekp(0);
- util::stream_format(m_string_buffer, std::forward<Format>(fmt), std::forward<Params>(args)...);
- m_string_buffer.put('\0');
-
- // log to all callbacks
- char const *const str(&m_string_buffer.vec()[0]);
- for (auto &cb : m_logerror_list)
- (cb->m_func)(*this, str);
-
- g_profiler.stop();
- }
-}
-
-#endif // __MACHINE_IPP__
diff --git a/src/emu/render.h b/src/emu/render.h
index 13d17e5aced..6092a37b45a 100644
--- a/src/emu/render.h
+++ b/src/emu/render.h
@@ -51,7 +51,9 @@
#include <math.h>
#include <mutex>
-#include "bitmap.h"
+#include "emu.h"
+//#include "bitmap.h"
+//#include "screen.h"
//**************************************************************************
// CONSTANTS
diff --git a/src/emu/ui/ctrlmenu.cpp b/src/emu/ui/ctrlmenu.cpp
deleted file mode 100644
index 3a82a9f5e9f..00000000000
--- a/src/emu/ui/ctrlmenu.cpp
+++ /dev/null
@@ -1,150 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Maurizio Petrarota
-/*********************************************************************
-
- ui/ctrlmenu.cpp
-
- Internal UI user interface.
-
-*********************************************************************/
-
-#include "emu.h"
-#include "emuopts.h"
-#include "ui/ui.h"
-#include "ui/menu.h"
-#include "ui/ctrlmenu.h"
-
-const char *ui_menu_controller_mapping::m_device_status[] = { "none", "keyboard", "mouse", "lightgun", "joystick" };
-
-ui_menu_controller_mapping::ctrl_option ui_menu_controller_mapping::m_options[] = {
- { 0, nullptr, nullptr },
- { 0, __("Lightgun Device Assignment"), OPTION_LIGHTGUN_DEVICE },
- { 0, __("Trackball Device Assignment"), OPTION_TRACKBALL_DEVICE },
- { 0, __("Pedal Device Assignment"), OPTION_PEDAL_DEVICE },
- { 0, __("Adstick Device Assignment"), OPTION_ADSTICK_DEVICE },
- { 0, __("Paddle Device Assignment"), OPTION_PADDLE_DEVICE },
- { 0, __("Dial Device Assignment"), OPTION_DIAL_DEVICE },
- { 0, __("Positional Device Assignment"), OPTION_POSITIONAL_DEVICE },
- { 0, __("Mouse Device Assignment"), OPTION_MOUSE_DEVICE }
-};
-
-//-------------------------------------------------
-// ctor
-//-------------------------------------------------
-
-ui_menu_controller_mapping::ui_menu_controller_mapping(running_machine &machine, render_container *container) : ui_menu(machine, container)
-{
- for (int d = 1; d < ARRAY_LENGTH(m_options); ++d)
- m_options[d].status = check_status(machine.options().value(m_options[d].option), m_options[d].option);
-}
-
-//-------------------------------------------------
-// dtor
-//-------------------------------------------------
-
-ui_menu_controller_mapping::~ui_menu_controller_mapping()
-{
- std::string error_string;
- for (int d = 1; d < ARRAY_LENGTH(m_options); ++d)
- {
- if (strcmp(machine().options().value(m_options[d].option), m_device_status[m_options[d].status])!=0)
- {
- machine().options().set_value(m_options[d].option, m_device_status[m_options[d].status], OPTION_PRIORITY_CMDLINE, error_string);
- machine().options().mark_changed(m_options[d].option);
- }
- }
-}
-
-//-------------------------------------------------
-// handle
-//-------------------------------------------------
-
-void ui_menu_controller_mapping::handle()
-{
- bool changed = false;
-
- // process the menu
- const ui_menu_event *m_event = process(0);
- if (m_event != nullptr && m_event->itemref != nullptr)
- {
- if (m_event->iptkey == IPT_UI_LEFT || m_event->iptkey == IPT_UI_RIGHT)
- {
- changed = true;
- FPTR value = (FPTR)m_event->itemref;
- (m_event->iptkey == IPT_UI_RIGHT) ? m_options[value].status++ : m_options[value].status--;
- }
- }
-
- if (changed)
- reset(UI_MENU_RESET_REMEMBER_REF);
-}
-
-//-------------------------------------------------
-// populate
-//-------------------------------------------------
-
-void ui_menu_controller_mapping::populate()
-{
- // add options
- for (int d = 1; d < ARRAY_LENGTH(m_options); ++d)
- {
- UINT32 arrow_flags = get_arrow_flags(0, ARRAY_LENGTH(m_device_status) - 1, m_options[d].status);
- item_append(_(m_options[d].description), m_device_status[m_options[d].status], arrow_flags, (void *)(FPTR)d);
- }
- item_append(MENU_SEPARATOR_ITEM, nullptr, 0, nullptr);
- customtop = machine().ui().get_line_height() + (3.0f * UI_BOX_TB_BORDER);
-}
-
-//-------------------------------------------------
-// perform our special rendering
-//-------------------------------------------------
-
-void ui_menu_controller_mapping::custom_render(void *selectedref, float top, float bottom, float origx1, float origy1, float origx2, float origy2)
-{
- float width, maxwidth = origx2 - origx1;
- ui_manager &mui = machine().ui();
-
- mui.draw_text_full(container, _("Device Mapping"), 0.0f, 0.0f, 1.0f, JUSTIFY_CENTER, WRAP_TRUNCATE,
- DRAW_NONE, ARGB_WHITE, ARGB_BLACK, &width, nullptr);
- width += 2 * UI_BOX_LR_BORDER;
- maxwidth = MAX(maxwidth, width);
-
- // compute our bounds
- float x1 = 0.5f - 0.5f * maxwidth;
- float x2 = x1 + maxwidth;
- float y1 = origy1 - top;
- float y2 = origy1 - UI_BOX_TB_BORDER;
-
- // draw a box
- mui.draw_outlined_box(container, x1, y1, x2, y2, UI_GREEN_COLOR);
-
- // take off the borders
- x1 += UI_BOX_LR_BORDER;
- x2 -= UI_BOX_LR_BORDER;
- y1 += UI_BOX_TB_BORDER;
-
- // draw the text within it
- mui.draw_text_full(container, _("Device Mapping"), x1, y1, x2 - x1, JUSTIFY_CENTER, WRAP_TRUNCATE,
- DRAW_NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr);
-
-}
-
-//-------------------------------------------------
-// return current value
-//-------------------------------------------------
-
-int ui_menu_controller_mapping::check_status(const char *status, const char *option)
-{
- for (int d = 0; *m_device_status[d]; d++)
- if (!strcmp(m_device_status[d], status))
- return d;
-
- emu_options def_opt;
- const char *def_val = def_opt.value(option);
-
- for (int d = 0; *m_device_status[d]; d++)
- if (!strcmp(m_device_status[d], def_val))
- return d;
-
- return 1;
-}
diff --git a/src/emu/ui/ctrlmenu.h b/src/emu/ui/ctrlmenu.h
deleted file mode 100644
index 0db85ee878a..00000000000
--- a/src/emu/ui/ctrlmenu.h
+++ /dev/null
@@ -1,41 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Maurizio Petrarota
-/***************************************************************************
-
- ui/ctrlmenu.h
-
- Internal UI user interface.
-
-***************************************************************************/
-#pragma once
-
-#ifndef __UI_CTRLMENU_H__
-#define __UI_CTRLMENU_H__
-
-//-------------------------------------------------
-// class controller mapping menu
-//-------------------------------------------------
-
-class ui_menu_controller_mapping : public ui_menu
-{
-public:
- ui_menu_controller_mapping(running_machine &machine, render_container *container);
- virtual ~ui_menu_controller_mapping();
- virtual void populate() override;
- virtual void handle() override;
- virtual void custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2) override;
-
-private:
- struct ctrl_option
- {
- int status;
- const char *description;
- const char *option;
- };
-
- static const char *m_device_status[];
- static ctrl_option m_options[];
- int check_status(const char *status, const char *option);
-};
-
-#endif /* __UI_CTRLMENU_H__ */
diff --git a/src/emu/ui/dsplmenu.cpp b/src/emu/ui/dsplmenu.cpp
deleted file mode 100644
index 02e5e75611b..00000000000
--- a/src/emu/ui/dsplmenu.cpp
+++ /dev/null
@@ -1,223 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Maurizio Petrarota
-/*********************************************************************
-
- ui/dsplmenu.cpp
-
- UI video options menu.
-
-*********************************************************************/
-
-#include "emu.h"
-#include "ui/ui.h"
-#include "ui/menu.h"
-#include "ui/dsplmenu.h"
-#include "ui/selector.h"
-#include "ui/utils.h"
-
-#if defined(UI_WINDOWS) && !defined(UI_SDL)
-#include "../osd/windows/winmain.h"
-#else
-#include "../osd/modules/lib/osdobj_common.h"
-#endif
-
-
-ui_menu_display_options::video_modes ui_menu_display_options::m_video = {
- { "auto", "Auto" },
- { "opengl", "OpenGL" },
- { "bgfx", "BGFX" },
- { "d3d", "Direct3D" },
- { "gdi", "GDI" },
- { "ddraw", "DirectDraw" },
- { "soft", "Software" },
- { "accel", "SDL2 Accelerated" }
-};
-
-ui_menu_display_options::dspl_option ui_menu_display_options::m_options[] = {
- { 0, nullptr, nullptr },
- { 0, __("Video Mode"), OSDOPTION_VIDEO },
-#if defined(UI_WINDOWS) && !defined(UI_SDL)
- { 0, __("Triple Buffering"), WINOPTION_TRIPLEBUFFER },
- { 0, __("HLSL"), WINOPTION_HLSL_ENABLE },
-#endif
- { 0, __("GLSL"), OSDOPTION_GL_GLSL },
- { 0, __("Bilinear Filtering"), OSDOPTION_FILTER },
- { 0, __("Bitmap Prescaling"), OSDOPTION_PRESCALE },
- { 0, __("Window Mode"), OSDOPTION_WINDOW },
- { 0, __("Enforce Aspect Ratio"), OPTION_KEEPASPECT },
- { 0, __("Start Out Maximized"), OSDOPTION_MAXIMIZE },
- { 0, __("Synchronized Refresh"), OSDOPTION_SYNCREFRESH },
- { 0, __("Wait Vertical Sync"), OSDOPTION_WAITVSYNC }
-};
-
-
-//-------------------------------------------------
-// ctor
-//-------------------------------------------------
-
-ui_menu_display_options::ui_menu_display_options(running_machine &machine, render_container *container) : ui_menu(machine, container)
-{
- osd_options &options = downcast<osd_options &>(machine.options());
-
- for (int d = 2; d < ARRAY_LENGTH(m_options); ++d)
- m_options[d].status = options.int_value(m_options[d].option);
-
- // create video list
- m_list.push_back("auto");
-
- std::string descr = options.description(OSDOPTION_VIDEO);
- descr.erase(0, descr.find(":") + 2);
- std::string delim = ", ";
- size_t p1, p2 = 0;
- for (;;)
- {
- p1 = descr.find_first_not_of(delim, p2);
- if (p1 == std::string::npos)
- break;
- p2 = descr.find_first_of(delim, p1 + 1);
- if (p2 != std::string::npos)
- {
- std::string txt(descr.substr(p1, p2 - p1));
- if (txt != "or" && txt != "none")
- m_list.push_back(txt);
- }
- else
- {
- m_list.push_back(descr.substr(p1));
- break;
- }
- }
-
- m_options[1].status = 0;
- for (int cur = 0; cur < m_list.size(); ++cur)
- if (options.video() == m_list[cur])
- {
- m_options[1].status = cur;
- break;
- }
-}
-
-//-------------------------------------------------
-// dtor
-//-------------------------------------------------
-
-ui_menu_display_options::~ui_menu_display_options()
-{
- std::string error_string;
- for (int d = 2; d < ARRAY_LENGTH(m_options); ++d)
- {
- if (machine().options().int_value(m_options[d].option) != m_options[d].status)
- {
- machine().options().set_value(m_options[d].option, m_options[d].status, OPTION_PRIORITY_CMDLINE, error_string);
- machine().options().mark_changed(m_options[d].option);
- }
- }
- if (machine().options().value(m_options[1].option) != m_list[m_options[1].status])
- {
- machine().options().set_value(m_options[1].option, m_list[m_options[1].status].c_str(), OPTION_PRIORITY_CMDLINE, error_string);
- machine().options().mark_changed(m_options[1].option);
-
- }
- ui_globals::reset = true;
-}
-
-
-//-------------------------------------------------
-// handle
-//-------------------------------------------------
-
-void ui_menu_display_options::handle()
-{
- bool changed = false;
-
- // process the menu
- const ui_menu_event *m_event = process(0);
-
- if (m_event != nullptr && m_event->itemref != nullptr)
- {
- int value = (FPTR)m_event->itemref;
- if (!strcmp(m_options[value].option, OSDOPTION_VIDEO) || !strcmp(m_options[value].option, OSDOPTION_PRESCALE))
- {
- if (m_event->iptkey == IPT_UI_LEFT || m_event->iptkey == IPT_UI_RIGHT)
- {
- changed = true;
- (m_event->iptkey == IPT_UI_LEFT) ? m_options[value].status-- : m_options[value].status++;
- }
- else if (m_event->iptkey == IPT_UI_SELECT && !strcmp(m_options[value].option, OSDOPTION_VIDEO))
- {
- int total = m_list.size();
- std::vector<std::string> s_sel(total);
- for (int index = 0; index < total; ++index)
- s_sel[index] = m_video[m_list[index]];
-
- ui_menu::stack_push(global_alloc_clear<ui_menu_selector>(machine(), container, s_sel, m_options[value].status));
- }
- }
- else if (m_event->iptkey == IPT_UI_LEFT || m_event->iptkey == IPT_UI_RIGHT || m_event->iptkey == IPT_UI_SELECT)
- {
- changed = true;
- m_options[value].status = !m_options[value].status;
- }
- }
-
- if (changed)
- reset(UI_MENU_RESET_REMEMBER_REF);
-}
-
-//-------------------------------------------------
-// populate
-//-------------------------------------------------
-
-void ui_menu_display_options::populate()
-{
- // add video mode option
- std::string v_text(m_video[m_list[m_options[1].status]]);
- UINT32 arrow_flags = get_arrow_flags(0, m_list.size() - 1, m_options[1].status);
- item_append(_(m_options[1].description), v_text.c_str(), arrow_flags, (void *)(FPTR)1);
-
- // add options items
- for (int opt = 2; opt < ARRAY_LENGTH(m_options); ++opt)
- if (strcmp(m_options[opt].option, OSDOPTION_PRESCALE) != 0)
- item_append(_(m_options[opt].description), m_options[opt].status ? _("On") : _("Off"),
- m_options[opt].status ? MENU_FLAG_RIGHT_ARROW : MENU_FLAG_LEFT_ARROW, (void *)(FPTR)opt);
- else
- {
- arrow_flags = get_arrow_flags(1, 3, m_options[opt].status);
- item_append(_(m_options[opt].description), string_format("%d", m_options[opt].status).c_str(), arrow_flags, (void *)(FPTR)opt);
- }
-
- item_append(MENU_SEPARATOR_ITEM, nullptr, 0, nullptr);
- customtop = machine().ui().get_line_height() + (3.0f * UI_BOX_TB_BORDER);
-}
-
-//-------------------------------------------------
-// perform our special rendering
-//-------------------------------------------------
-
-void ui_menu_display_options::custom_render(void *selectedref, float top, float bottom, float origx1, float origy1, float origx2, float origy2)
-{
- float width;
- ui_manager &mui = machine().ui();
- mui.draw_text_full(container, _("Display Options"), 0.0f, 0.0f, 1.0f, JUSTIFY_CENTER, WRAP_TRUNCATE, DRAW_NONE,
- ARGB_WHITE, ARGB_BLACK, &width, nullptr);
- width += 2 * UI_BOX_LR_BORDER;
- float maxwidth = MAX(origx2 - origx1, width);
-
- // compute our bounds
- float x1 = 0.5f - 0.5f * maxwidth;
- float x2 = x1 + maxwidth;
- float y1 = origy1 - top;
- float y2 = origy1 - UI_BOX_TB_BORDER;
-
- // draw a box
- mui.draw_outlined_box(container, x1, y1, x2, y2, UI_GREEN_COLOR);
-
- // take off the borders
- x1 += UI_BOX_LR_BORDER;
- x2 -= UI_BOX_LR_BORDER;
- y1 += UI_BOX_TB_BORDER;
-
- // draw the text within it
- mui.draw_text_full(container, _("Display Options"), x1, y1, x2 - x1, JUSTIFY_CENTER, WRAP_TRUNCATE, DRAW_NORMAL,
- UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr);
-}
diff --git a/src/emu/ui/dsplmenu.h b/src/emu/ui/dsplmenu.h
deleted file mode 100644
index 69b92e3bbe0..00000000000
--- a/src/emu/ui/dsplmenu.h
+++ /dev/null
@@ -1,44 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Maurizio Petrarota
-/***************************************************************************
-
- ui/dsplmenu.h
-
- UI video options menu.
-
-***************************************************************************/
-
-#pragma once
-
-#ifndef __UI_DSPLMENU_H__
-#define __UI_DSPLMENU_H__
-
-//-------------------------------------------------
-// class display options menu
-//-------------------------------------------------
-class ui_menu_display_options : public ui_menu
-{
-public:
- ui_menu_display_options(running_machine &machine, render_container *container);
- virtual ~ui_menu_display_options();
- virtual void populate() override;
- virtual void handle() override;
- virtual void custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2) override;
-
-private:
- struct dspl_option
- {
- UINT16 status;
- const char *description;
- const char *option;
- };
-
- using video_modes = std::unordered_map<std::string, std::string>;
-
- static video_modes m_video;
- static dspl_option m_options[];
-
- std::vector<std::string> m_list;
-};
-
-#endif /* __UI_DSPLMENU_H__ */
diff --git a/src/emu/ui/menu.cpp b/src/emu/ui/menu.cpp
index 335668fb417..f9094824534 100644
--- a/src/emu/ui/menu.cpp
+++ b/src/emu/ui/menu.cpp
@@ -296,7 +296,17 @@ void ui_menu::set_special_main_menu(bool special)
// end of the menu
//-------------------------------------------------
-void ui_menu::item_append(const char *text, const char *subtext, UINT32 flags, void *ref)
+void ui_menu::item_append(ui_menu_item item)
+{
+ item_append(item.text, item.subtext, item.flags, item.ref, item.type);
+}
+
+//-------------------------------------------------
+// item_append - append a new item to the
+// end of the menu
+//-------------------------------------------------
+
+void ui_menu::item_append(const char *text, const char *subtext, UINT32 flags, void *ref, ui_menu_item_type type)
{
// only allow multiline as the first item
if ((flags & MENU_FLAG_MULTILINE) != 0)
@@ -312,6 +322,7 @@ void ui_menu::item_append(const char *text, const char *subtext, UINT32 flags, v
pitem.subtext = (subtext != nullptr) ? pool_strdup(subtext) : nullptr;
pitem.flags = flags;
pitem.ref = ref;
+ pitem.type = type;
// append to array
int index = item.size();
@@ -380,6 +391,7 @@ const ui_menu_event *ui_menu::process(UINT32 flags)
if (menu_event.iptkey != IPT_INVALID && selected >= 0 && selected < item.size())
{
menu_event.itemref = item[selected].ref;
+ menu_event.type = item[selected].type;
return &menu_event;
}
return nullptr;
@@ -527,6 +539,7 @@ void ui_menu::draw(bool customonly, bool noimage, bool noinput)
visible_main_menu_height = 1.0f - 2.0f * UI_BOX_TB_BORDER - visible_extra_menu_height;
visible_lines = floor(visible_main_menu_height / line_height);
+ if (visible_lines > item.size()) visible_lines = item.size();
visible_main_menu_height = (float)visible_lines * line_height;
// compute top/left of inner menu area by centering
@@ -553,7 +566,8 @@ void ui_menu::draw(bool customonly, bool noimage, bool noinput)
bool show_bottom_arrow = false;
// if scrolling, show arrows
- if (item.size() > visible_lines) {
+ if (item.size() > visible_lines)
+ {
if (top_line > 0)
show_top_arrow = true;
if (top_line != item.size() - visible_lines)
@@ -907,9 +921,10 @@ void ui_menu::handle_events(UINT32 flags)
top_line -= local_menu_event.num_lines;
return;
}
- selected -= local_menu_event.num_lines;
+ (selected == 0) ? selected = top_line = item.size() - 1 : selected -= local_menu_event.num_lines;
validate_selection(-1);
- if (selected < top_line + (top_line != 0))
+ top_line -= (selected <= top_line && top_line != 0);
+ if (selected <= top_line && visitems != visible_lines)
top_line -= local_menu_event.num_lines;
}
else
@@ -919,11 +934,10 @@ void ui_menu::handle_events(UINT32 flags)
top_line += local_menu_event.num_lines;
return;
}
- selected += local_menu_event.num_lines;
+ (selected == item.size() - 1) ? selected = top_line = 0 : selected += local_menu_event.num_lines;
validate_selection(1);
- if (selected > item.size() - 1)
- selected = item.size() - 1;
- if (selected >= top_line + visitems + (top_line != 0))
+ top_line += (selected >= top_line + visitems + (top_line != 0));
+ if (selected >= (top_line + visitems + (top_line != 0)))
top_line += local_menu_event.num_lines;
}
}
@@ -1467,9 +1481,8 @@ void ui_menu::draw_select_game(bool noinput)
x1 = visible_left - UI_BOX_LR_BORDER;
x2 = visible_left + visible_width + UI_BOX_LR_BORDER;
float line = visible_top + (float)(visible_lines * line_height);
-
- //machine().ui().draw_outlined_box(container, x1, y1, x2, y2, rgb_t(0xEF, 0x12, 0x47, 0x7B));
mui.draw_outlined_box(container, x1, y1, x2, y2, UI_BACKGROUND_COLOR);
+
if (visible_items < visible_lines)
visible_lines = visible_items;
if (top_line < 0 || selected == 0)
@@ -2784,7 +2797,6 @@ void ui_menu::draw_dats_menu()
float y2 = visible_top + visible_main_menu_height + UI_BOX_TB_BORDER + extra_height;
float line = visible_top + (float)(visible_lines * line_height);
- //machine().ui().draw_outlined_box(container, x1, y1, x2, y2, rgb_t(0xEF, 0x12, 0x47, 0x7B));
mui.draw_outlined_box(container, x1, y1, x2, y2, UI_BACKGROUND_COLOR);
if (visible_items < visible_lines)
diff --git a/src/emu/ui/menu.h b/src/emu/ui/menu.h
index fee8305f05b..a07bcd1c519 100644
--- a/src/emu/ui/menu.h
+++ b/src/emu/ui/menu.h
@@ -53,6 +53,13 @@ enum ui_menu_reset_options
UI_MENU_RESET_REMEMBER_REF
};
+// types of menu items (TODO: please expand)
+enum class ui_menu_item_type
+{
+ UI_MENU_ITEM_TYPE_UNKNOWN,
+ UI_MENU_ITEM_TYPE_SLIDER,
+ UI_MENU_ITEM_TYPE_SEPARATOR
+};
/***************************************************************************
@@ -62,9 +69,10 @@ enum ui_menu_reset_options
// menu-related events
struct ui_menu_event
{
- void *itemref; // reference for the selected item
- int iptkey; // one of the IPT_* values from inptport.h
- unicode_char unichar; // unicode character if iptkey == IPT_SPECIAL
+ void *itemref; // reference for the selected item
+ ui_menu_item_type type; // item type (eventually will go away when itemref is proper ui_menu_item class rather than void*)
+ int iptkey; // one of the IPT_* values from inptport.h
+ unicode_char unichar; // unicode character if iptkey == IPT_SPECIAL
};
struct ui_menu_pool
@@ -78,10 +86,11 @@ struct ui_menu_pool
class ui_menu_item
{
public:
- const char *text;
- const char *subtext;
- UINT32 flags;
- void *ref;
+ const char *text;
+ const char *subtext;
+ UINT32 flags;
+ void *ref;
+ ui_menu_item_type type; // item type (eventually will go away when itemref is proper ui_menu_item class rather than void*)
inline bool is_selectable() const;
};
@@ -111,7 +120,8 @@ public:
void reset(ui_menu_reset_options options);
// append a new item to the end of the menu
- void item_append(const char *text, const char *subtext, UINT32 flags, void *ref);
+ void item_append(const char *text, const char *subtext, UINT32 flags, void *ref, ui_menu_item_type type = ui_menu_item_type::UI_MENU_ITEM_TYPE_UNKNOWN);
+ void item_append(ui_menu_item item);
// process a menu, drawing it and returning any interesting events
const ui_menu_event *process(UINT32 flags);
diff --git a/src/emu/ui/optsmenu.cpp b/src/emu/ui/optsmenu.cpp
index 05232636d2e..796bd665512 100644
--- a/src/emu/ui/optsmenu.cpp
+++ b/src/emu/ui/optsmenu.cpp
@@ -17,8 +17,6 @@
#include "ui/selector.h"
#include "ui/custui.h"
#include "ui/sndmenu.h"
-#include "ui/ctrlmenu.h"
-#include "ui/dsplmenu.h"
#include "ui/miscmenu.h"
#include "ui/optsmenu.h"
#include "ui/custmenu.h"
@@ -171,7 +169,7 @@ void ui_menu_game_options::handle()
break;
case DISPLAY_MENU:
if (m_event->iptkey == IPT_UI_SELECT)
- ui_menu::stack_push(global_alloc_clear<ui_menu_display_options>(machine(), container));
+ ui_menu::stack_push(global_alloc_clear<ui_submenu>(machine(), container, video_submenu_options));
break;
case CUSTOM_MENU:
if (m_event->iptkey == IPT_UI_SELECT)
@@ -179,7 +177,7 @@ void ui_menu_game_options::handle()
break;
case CONTROLLER_MENU:
if (m_event->iptkey == IPT_UI_SELECT)
- ui_menu::stack_push(global_alloc_clear<ui_menu_controller_mapping>(machine(), container));
+ ui_menu::stack_push(global_alloc_clear<ui_submenu>(machine(), container, control_submenu_options));
break;
case CGI_MENU:
if (m_event->iptkey == IPT_UI_SELECT)
@@ -263,12 +261,12 @@ void ui_menu_game_options::populate()
item_append(_("Customize UI"), nullptr, 0, (void *)(FPTR)CUSTOM_MENU);
item_append(_("Configure Directories"), nullptr, 0, (void *)(FPTR)CONF_DIR);
}
- item_append(_("Display Options"), nullptr, 0, (void *)(FPTR)DISPLAY_MENU);
+ item_append(_(video_submenu_options[0].description), nullptr, 0, (void *)(FPTR)DISPLAY_MENU);
item_append(_("Sound Options"), nullptr, 0, (void *)(FPTR)SOUND_MENU);
- item_append(_(misc_submenu_options[0].description), nullptr, 0, (void *)(FPTR)MISC_MENU);
- item_append(_("Device Mapping"), nullptr, 0, (void *)(FPTR)CONTROLLER_MENU);
+ item_append(_(misc_submenu_options[0].description), nullptr, 0, (void *)(FPTR)MISC_MENU);
+ item_append(_(control_submenu_options[0].description), nullptr, 0, (void *)(FPTR)CONTROLLER_MENU);
item_append(_("General Inputs"), nullptr, 0, (void *)(FPTR)CGI_MENU);
- item_append(_(advanced_submenu_options[0].description), nullptr, 0, (void *)(FPTR)ADVANCED_MENU);
+ item_append(_(advanced_submenu_options[0].description), nullptr, 0, (void *)(FPTR)ADVANCED_MENU);
item_append(MENU_SEPARATOR_ITEM, nullptr, 0, nullptr);
item_append(_("Save Configuration"), nullptr, 0, (void *)(FPTR)SAVE_CONFIG);
diff --git a/src/emu/ui/pluginopt.cpp b/src/emu/ui/pluginopt.cpp
index 625d60600f1..9fd02404a0a 100644
--- a/src/emu/ui/pluginopt.cpp
+++ b/src/emu/ui/pluginopt.cpp
@@ -87,12 +87,24 @@ void ui_menu_plugin_opt::handle()
void ui_menu_plugin_opt::populate()
{
- std::vector<lua_engine::menu_item> &menu_list = machine().manager().lua()->menu_populate(m_menu);
+ std::vector<lua_engine::menu_item> menu_list;
+ machine().manager().lua()->menu_populate(m_menu, menu_list);
FPTR i = 1;
for(auto &item : menu_list)
- item_append(item.text.c_str(), item.subtext.c_str(), item.flags, (void *)i++);
+ {
+ UINT32 flags = 0;
+ if(item.flags == "off")
+ flags = MENU_FLAG_DISABLE;
+ else if(item.flags == "l")
+ flags = MENU_FLAG_LEFT_ARROW;
+ else if(item.flags == "r")
+ flags = MENU_FLAG_RIGHT_ARROW;
+ else if(item.flags == "lr")
+ flags = MENU_FLAG_RIGHT_ARROW | MENU_FLAG_LEFT_ARROW;
+
+ item_append(item.text.c_str(), item.subtext.c_str(), flags, (void *)i++);
+ }
item_append(MENU_SEPARATOR_ITEM, nullptr, 0, nullptr);
- global_free(&menu_list);
}
ui_menu_plugin_opt::~ui_menu_plugin_opt()
diff --git a/src/emu/ui/selgame.cpp b/src/emu/ui/selgame.cpp
index 171c2c5d817..8560bb846af 100644
--- a/src/emu/ui/selgame.cpp
+++ b/src/emu/ui/selgame.cpp
@@ -2260,7 +2260,6 @@ void ui_menu_select_game::draw_right_panel(void *selectedref, float origx1, floa
float ar_x1 = ar_x0 + lr_arrow_width;
float ar_y1 = 0.5f * (origy2 + origy1) + 0.9f * space;
- //machine().ui().draw_outlined_box(container, origx1, origy1, origx2, origy2, UI_BACKGROUND_COLOR);
mui.draw_outlined_box(container, origx1, origy1, origx2, origy2, rgb_t(0xEF, 0x12, 0x47, 0x7B));
if (mouse_hit && origx1 <= mouse_x && x2 > mouse_x && origy1 <= mouse_y && origy2 > mouse_y)
diff --git a/src/emu/ui/selsoft.cpp b/src/emu/ui/selsoft.cpp
index 918827eaafe..c4d2fab576a 100644
--- a/src/emu/ui/selsoft.cpp
+++ b/src/emu/ui/selsoft.cpp
@@ -431,7 +431,6 @@ void ui_menu_select_software::populate()
machine_config config(*m_driver, machine().options());
image_interface_iterator iter(config.root_device());
-
for (device_image_interface *image = iter.first(); image != nullptr; image = iter.next())
if (image->filename() == nullptr && image->must_be_loaded())
{
@@ -1431,7 +1430,6 @@ float ui_menu_select_software::draw_left_panel(float x1, float y1, float x2, flo
}
x2 = x1 + left_width + 2.0f * UI_BOX_LR_BORDER;
- //machine().ui().draw_outlined_box(container, x1, y1, x2, y2, rgb_t(0xEF, 0x12, 0x47, 0x7B));
mui.draw_outlined_box(container, x1, y1, x2, y2, UI_BACKGROUND_COLOR);
// take off the borders
@@ -1512,7 +1510,6 @@ float ui_menu_select_software::draw_left_panel(float x1, float y1, float x2, flo
float ar_x1 = ar_x0 + lr_arrow_width;
float ar_y1 = 0.5f * (y2 + y1) + 0.9f * space;
- //machine().ui().draw_outlined_box(container, x1, y1, x2, y2, UI_BACKGROUND_COLOR);
mui.draw_outlined_box(container, x1, y1, x2, y2, rgb_t(0xEF, 0x12, 0x47, 0x7B));
if (mouse_hit && x1 <= mouse_x && x2 > mouse_x && y1 <= mouse_y && y2 > mouse_y)
@@ -1536,7 +1533,6 @@ float ui_menu_select_software::draw_left_panel(float x1, float y1, float x2, flo
float ar_x1 = ar_x0 + lr_arrow_width;
float ar_y1 = 0.5f * (y2 + y1) + 0.9f * space;
- //machine().ui().draw_outlined_box(container, x1, y1, x2, y2, UI_BACKGROUND_COLOR);
mui.draw_outlined_box(container, x1, y1, x2, y2, rgb_t(0xEF, 0x12, 0x47, 0x7B));
if (mouse_hit && x1 <= mouse_x && x2 > mouse_x && y1 <= mouse_y && y2 > mouse_y)
@@ -1899,7 +1895,6 @@ void ui_menu_select_software::draw_right_panel(void *selectedref, float origx1,
float ar_x1 = ar_x0 + lr_arrow_width;
float ar_y1 = 0.5f * (origy2 + origy1) + 0.9f * space;
- //machine().ui().draw_outlined_box(container, origx1, origy1, origx2, origy2, UI_BACKGROUND_COLOR);
mui.draw_outlined_box(container, origx1, origy1, origx2, origy2, rgb_t(0xEF, 0x12, 0x47, 0x7B));
if (mouse_hit && origx1 <= mouse_x && x2 > mouse_x && origy1 <= mouse_y && origy2 > mouse_y)
diff --git a/src/emu/ui/sliders.cpp b/src/emu/ui/sliders.cpp
index 87508df3dd0..20cb435233a 100644
--- a/src/emu/ui/sliders.cpp
+++ b/src/emu/ui/sliders.cpp
@@ -39,10 +39,10 @@ void ui_menu_sliders::handle()
if (menu_event != nullptr)
{
/* handle keys if there is a valid item selected */
- if (menu_event->itemref != nullptr)
+ if (menu_event->itemref != nullptr && menu_event->type == ui_menu_item_type::UI_MENU_ITEM_TYPE_SLIDER)
{
const slider_state *slider = (const slider_state *)menu_event->itemref;
- INT32 curvalue = (*slider->update)(machine(), slider->arg, nullptr, SLIDER_NOCHANGE);
+ INT32 curvalue = (*slider->update)(machine(), slider->arg, slider->id, nullptr, SLIDER_NOCHANGE);
INT32 increment = 0;
bool alt_pressed = machine().input().code_pressed(KEYCODE_LALT) || machine().input().code_pressed(KEYCODE_RALT);
bool ctrl_pressed = machine().input().code_pressed(KEYCODE_LCONTROL) || machine().input().code_pressed(KEYCODE_RCONTROL);
@@ -104,7 +104,7 @@ void ui_menu_sliders::handle()
newvalue = slider->maxval;
/* update the slider and recompute the menu */
- (*slider->update)(machine(), slider->arg, nullptr, newvalue);
+ (*slider->update)(machine(), slider->arg, slider->id, nullptr, newvalue);
reset(UI_MENU_RESET_REMEMBER_REF);
}
}
@@ -140,27 +140,47 @@ void ui_menu_sliders::populate()
std::string tempstring;
/* add UI sliders */
- for (const slider_state *curslider = machine().ui().get_slider_list(); curslider != nullptr; curslider = curslider->next)
+ std::vector<ui_menu_item> ui_sliders = machine().ui().get_slider_list();
+ for (ui_menu_item item : ui_sliders)
{
- INT32 curval = (*curslider->update)(machine(), curslider->arg, &tempstring, SLIDER_NOCHANGE);
- UINT32 flags = 0;
- if (curval > curslider->minval)
- flags |= MENU_FLAG_LEFT_ARROW;
- if (curval < curslider->maxval)
- flags |= MENU_FLAG_RIGHT_ARROW;
- item_append(curslider->description, tempstring.c_str(), flags, (void *)curslider);
+ if (item.type == ui_menu_item_type::UI_MENU_ITEM_TYPE_SLIDER)
+ {
+ slider_state* slider = reinterpret_cast<slider_state *>(item.ref);
+ INT32 curval = (*slider->update)(machine(), slider->arg, slider->id, &tempstring, SLIDER_NOCHANGE);
+ UINT32 flags = 0;
+ if (curval > slider->minval)
+ flags |= MENU_FLAG_LEFT_ARROW;
+ if (curval < slider->maxval)
+ flags |= MENU_FLAG_RIGHT_ARROW;
+ item_append(slider->description, tempstring.c_str(), flags, (void *)slider, ui_menu_item_type::UI_MENU_ITEM_TYPE_SLIDER);
+ }
+ else
+ {
+ item_append(item);
+ }
}
- /* add OSD sliders */
- for (const slider_state *curslider = (slider_state*)machine().osd().get_slider_list(); curslider != nullptr; curslider = curslider->next)
+ item_append(MENU_SEPARATOR_ITEM, nullptr, 0, nullptr);
+
+ /* add OSD options */
+ std::vector<ui_menu_item> osd_sliders = machine().osd().get_slider_list();
+ for (ui_menu_item item : osd_sliders)
{
- INT32 curval = (*curslider->update)(machine(), curslider->arg, &tempstring, SLIDER_NOCHANGE);
- UINT32 flags = 0;
- if (curval > curslider->minval)
- flags |= MENU_FLAG_LEFT_ARROW;
- if (curval < curslider->maxval)
- flags |= MENU_FLAG_RIGHT_ARROW;
- item_append(curslider->description, tempstring.c_str(), flags, (void *)curslider);
+ if (item.type == ui_menu_item_type::UI_MENU_ITEM_TYPE_SLIDER)
+ {
+ slider_state* slider = reinterpret_cast<slider_state *>(item.ref);
+ INT32 curval = (*slider->update)(machine(), slider->arg, slider->id, &tempstring, SLIDER_NOCHANGE);
+ UINT32 flags = 0;
+ if (curval > slider->minval)
+ flags |= MENU_FLAG_LEFT_ARROW;
+ if (curval < slider->maxval)
+ flags |= MENU_FLAG_RIGHT_ARROW;
+ item_append(slider->description, tempstring.c_str(), flags, (void *)slider, ui_menu_item_type::UI_MENU_ITEM_TYPE_SLIDER);
+ }
+ else
+ {
+ item_append(item);
+ }
}
custombottom = 2.0f * machine().ui().get_line_height() + 2.0f * UI_BOX_TB_BORDER;
@@ -184,7 +204,7 @@ void ui_menu_sliders::custom_render(void *selectedref, float top, float bottom,
INT32 curval;
/* determine the current value and text */
- curval = (*curslider->update)(machine(), curslider->arg, &tempstring, SLIDER_NOCHANGE);
+ curval = (*curslider->update)(machine(), curslider->arg, curslider->id, &tempstring, SLIDER_NOCHANGE);
/* compute the current and default percentages */
percentage = (float)(curval - curslider->minval) / (float)(curslider->maxval - curslider->minval);
diff --git a/src/emu/ui/sliders.h b/src/emu/ui/sliders.h
index c21555dc336..f420b094cbe 100644
--- a/src/emu/ui/sliders.h
+++ b/src/emu/ui/sliders.h
@@ -27,6 +27,10 @@ public:
static UINT32 ui_handler(running_machine &machine, render_container *container, UINT32 state);
private:
+ enum {
+ INPUT_GROUPS,
+ INPUT_SPECIFIC,
+ };
bool m_menuless_mode;
bool m_hidden;
};
diff --git a/src/emu/ui/submenu.cpp b/src/emu/ui/submenu.cpp
index d0431c2c467..a06d75adb83 100644
--- a/src/emu/ui/submenu.cpp
+++ b/src/emu/ui/submenu.cpp
@@ -13,6 +13,7 @@
#include "ui/submenu.h"
#include "ui/utils.h"
#include <limits>
+#include <iterator>
//-------------------------------------------------
// ctor / dtor
@@ -24,19 +25,65 @@ ui_submenu::ui_submenu(running_machine &machine, render_container *container, st
{
for (auto & sm_option : m_options)
{
- if (sm_option.type < ui_submenu::EMU)
- continue;
-
- // fixme use switch
- sm_option.entry = machine.options().get_entry(sm_option.name);
- if (sm_option.entry == nullptr)
- {
- sm_option.entry = machine.ui().options().get_entry(sm_option.name);
- sm_option.options = dynamic_cast<core_options*>(&machine.ui().options());
- }
- else
+ switch (sm_option.type)
{
- sm_option.options = dynamic_cast<core_options*>(&machine.options());
+ case ui_submenu::EMU:
+ sm_option.entry = machine.options().get_entry(sm_option.name);
+ sm_option.options = dynamic_cast<core_options*>(&machine.options());
+ if (sm_option.entry->type() == OPTION_STRING)
+ {
+ sm_option.value.clear();
+ std::string namestr(sm_option.entry->description());
+ int lparen = namestr.find_first_of('(', 0);
+ int vslash = namestr.find_first_of('|', lparen + 1);
+ int rparen = namestr.find_first_of(')', vslash + 1);
+ if (lparen != -1 && vslash != -1 && rparen != -1)
+ {
+ int semi;
+ namestr.erase(rparen);
+ namestr.erase(0, lparen + 1);
+ while ((semi = namestr.find_first_of('|')) != -1)
+ {
+ sm_option.value.emplace_back(namestr.substr(0, semi));
+ namestr.erase(0, semi + 1);
+ }
+ sm_option.value.emplace_back(namestr);
+ }
+ }
+ break;
+ case ui_submenu::OSD:
+ sm_option.entry = machine.options().get_entry(sm_option.name);
+ sm_option.options = dynamic_cast<core_options*>(&machine.options());
+ if (sm_option.entry->type() == OPTION_STRING)
+ {
+ sm_option.value.clear();
+ std::string descr(sm_option.entry->description()), delim(", ");
+ descr.erase(0, descr.find(":") + 2);
+ size_t p1, p2 = 0;
+ while ((p1 = descr.find_first_not_of(delim, p2)) != std::string::npos)
+ {
+ p2 = descr.find_first_of(delim, p1 + 1);
+ if (p2 != std::string::npos)
+ {
+ std::string txt(descr.substr(p1, p2 - p1));
+ if (txt != "or")
+ sm_option.value.push_back(txt);
+ }
+ else
+ {
+ sm_option.value.push_back(descr.substr(p1));
+ break;
+ }
+ }
+ }
+ break;
+ case ui_submenu::UI:
+ sm_option.entry = machine.ui().options().get_entry(sm_option.name);
+ sm_option.options = dynamic_cast<core_options*>(&machine.ui().options());
+ break;
+ default:
+ continue;
+ break;
}
}
}
@@ -115,6 +162,20 @@ void ui_submenu::handle()
sm_option->entry->mark_changed();
}
break;
+ case OPTION_STRING:
+ if (m_event->iptkey == IPT_UI_LEFT || m_event->iptkey == IPT_UI_RIGHT)
+ {
+ changed = true;
+ std::string v_cur(sm_option->entry->value());
+ int cur_value = std::distance(sm_option->value.begin(), std::find(sm_option->value.begin(), sm_option->value.end(), v_cur));
+ if (m_event->iptkey == IPT_UI_LEFT)
+ v_cur = sm_option->value[--cur_value];
+ else
+ v_cur = sm_option->value[++cur_value];
+ sm_option->options->set_value(sm_option->name, v_cur.c_str(), OPTION_PRIORITY_CMDLINE, error_string);
+ sm_option->entry->mark_changed();
+ }
+ break;
}
break;
default:
@@ -207,6 +268,16 @@ void ui_submenu::populate()
static_cast<void*>(&(*sm_option)));
break;
}
+ case OPTION_STRING:
+ {
+ std::string v_cur(sm_option->entry->value());
+ int cur_value = std::distance(sm_option->value.begin(), std::find(sm_option->value.begin(), sm_option->value.end(), v_cur));
+ arrow_flags = get_arrow_flags(0, sm_option->value.size() - 1, cur_value);
+ item_append(_(sm_option->description),
+ sm_option->options->value(sm_option->name),
+ arrow_flags, static_cast<void*>(&(*sm_option)));
+ break;
+ }
default:
arrow_flags = MENU_FLAG_RIGHT_ARROW;
item_append(_(sm_option->description),
@@ -260,7 +331,6 @@ void ui_submenu::custom_render(void *selectedref, float top, float bottom, float
if (selectedref != nullptr)
{
ui_submenu::option *selected_sm_option = (ui_submenu::option *)selectedref;
-
if (selected_sm_option->entry != nullptr)
{
mui.draw_text_full(container, selected_sm_option->entry->description(), 0.0f, 0.0f, 1.0f, JUSTIFY_CENTER, WRAP_TRUNCATE,
diff --git a/src/emu/ui/submenu.h b/src/emu/ui/submenu.h
index a47a84f4d5b..3e25ba18c94 100644
--- a/src/emu/ui/submenu.h
+++ b/src/emu/ui/submenu.h
@@ -15,6 +15,12 @@
#include "emuopts.h"
#include "ui/menu.h"
+#if defined(UI_WINDOWS) && !defined(UI_SDL)
+#include "../osd/windows/winmain.h"
+#else
+#include "../osd/modules/lib/osdobj_common.h"
+#endif
+
//-------------------------------------------------
// class ui menu
//-------------------------------------------------
@@ -37,6 +43,7 @@ public:
const char *name;
core_options::entry *entry;
core_options (*options);
+ std::vector<std::string> value;
};
ui_submenu(running_machine &machine, render_container *container, std::vector<ui_submenu::option> &suboptions);
@@ -74,9 +81,7 @@ static std::vector<ui_submenu::option> advanced_submenu_options = {
{ ui_submenu::EMU, __("Sleep"), OPTION_SLEEP },
{ ui_submenu::EMU, __("Speed"), OPTION_SPEED },
{ ui_submenu::EMU, __("Refresh speed"), OPTION_REFRESHSPEED },
-//};
-//static std::vector<ui_submenu::option> rotate_submenu_options = {
{ ui_submenu::HEAD, __("Rotation Options") },
{ ui_submenu::EMU, __("Rotate"), OPTION_ROTATE },
{ ui_submenu::EMU, __("Rotate right"), OPTION_ROR },
@@ -85,9 +90,7 @@ static std::vector<ui_submenu::option> advanced_submenu_options = {
{ ui_submenu::EMU, __("Auto rotate left"), OPTION_AUTOROL },
{ ui_submenu::EMU, __("Flip X"), OPTION_FLIPX },
{ ui_submenu::EMU, __("Flip Y"), OPTION_FLIPY },
-//};
-//static std::vector<ui_submenu::option> artwork_submenu_options = {
{ ui_submenu::HEAD, __("Artwork Options") },
{ ui_submenu::EMU, __("Artwork Crop"), OPTION_ARTWORK_CROP },
{ ui_submenu::EMU, __("Use Backdrops"), OPTION_USE_BACKDROPS },
@@ -95,16 +98,12 @@ static std::vector<ui_submenu::option> advanced_submenu_options = {
{ ui_submenu::EMU, __("Use Bezels"), OPTION_USE_BEZELS },
{ ui_submenu::EMU, __("Use Control Panels"), OPTION_USE_CPANELS },
{ ui_submenu::EMU, __("Use Marquees"), OPTION_USE_MARQUEES },
-//};
-//static std::vector<ui_submenu::option> state_submenu_options = {
{ ui_submenu::HEAD, __("State/Playback Options") },
{ ui_submenu::EMU, __("Automatic save/restore"), OPTION_AUTOSAVE },
{ ui_submenu::EMU, __("Bilinear snapshot"), OPTION_SNAPBILINEAR },
{ ui_submenu::EMU, __("Burn-in"), OPTION_BURNIN },
-//};
-//static std::vector<ui_submenu::option> input_submenu_options = {
{ ui_submenu::HEAD, __("Input Options") },
{ ui_submenu::EMU, __("Coin lockout"), OPTION_COIN_LOCKOUT },
{ ui_submenu::EMU, __("Mouse"), OPTION_MOUSE },
@@ -122,6 +121,35 @@ static std::vector<ui_submenu::option> advanced_submenu_options = {
{ ui_submenu::EMU, __("Coin impulse"), OPTION_COIN_IMPULSE },
};
+static std::vector<ui_submenu::option> control_submenu_options = {
+ { ui_submenu::HEAD, __("Device Mapping") },
+ { ui_submenu::EMU, __("Lightgun Device Assignment"), OPTION_LIGHTGUN_DEVICE },
+ { ui_submenu::EMU, __("Trackball Device Assignment"), OPTION_TRACKBALL_DEVICE },
+ { ui_submenu::EMU, __("Pedal Device Assignment"), OPTION_PEDAL_DEVICE },
+ { ui_submenu::EMU, __("Adstick Device Assignment"), OPTION_ADSTICK_DEVICE },
+ { ui_submenu::EMU, __("Paddle Device Assignment"), OPTION_PADDLE_DEVICE },
+ { ui_submenu::EMU, __("Dial Device Assignment"), OPTION_DIAL_DEVICE },
+ { ui_submenu::EMU, __("Positional Device Assignment"), OPTION_POSITIONAL_DEVICE },
+ { ui_submenu::EMU, __("Mouse Device Assignment"), OPTION_MOUSE_DEVICE }
+};
+
+static std::vector<ui_submenu::option> video_submenu_options = {
+ { ui_submenu::HEAD, __("Display Options") },
+ { ui_submenu::OSD, __("Video Mode"), OSDOPTION_VIDEO },
+#if defined(UI_WINDOWS) && !defined(UI_SDL)
+ { ui_submenu::OSD, __("Triple Buffering"), WINOPTION_TRIPLEBUFFER },
+ { ui_submenu::OSD, __("HLSL"), WINOPTION_HLSL_ENABLE },
+#endif
+ { ui_submenu::OSD, __("GLSL"), OSDOPTION_GL_GLSL },
+ { ui_submenu::OSD, __("Bilinear Filtering"), OSDOPTION_FILTER },
+ { ui_submenu::OSD, __("Bitmap Prescaling"), OSDOPTION_PRESCALE },
+ { ui_submenu::OSD, __("Window Mode"), OSDOPTION_WINDOW },
+ { ui_submenu::EMU, __("Enforce Aspect Ratio"), OPTION_KEEPASPECT },
+ { ui_submenu::OSD, __("Start Out Maximized"), OSDOPTION_MAXIMIZE },
+ { ui_submenu::OSD, __("Synchronized Refresh"), OSDOPTION_SYNCREFRESH },
+ { ui_submenu::OSD, __("Wait Vertical Sync"), OSDOPTION_WAITVSYNC }
+};
+
//static std::vector<ui_submenu::option> export_submenu_options = {
// { ui_submenu::COMMAND, __("Export XML format (like -listxml)"), "exportxml" },
// { ui_submenu::COMMAND, __("Export TXT format (like -listfull)"), "exporttxt" },
diff --git a/src/emu/ui/ui.cpp b/src/emu/ui/ui.cpp
index 274a347b1ac..b8ad5ee7f9c 100644
--- a/src/emu/ui/ui.cpp
+++ b/src/emu/ui/ui.cpp
@@ -118,7 +118,7 @@ std::string ui_manager::messagebox_poptext;
rgb_t ui_manager::messagebox_backcolor;
// slider info
-slider_state *ui_manager::slider_list;
+std::vector<ui_menu_item> ui_manager::slider_list;
slider_state *ui_manager::slider_current;
@@ -128,31 +128,30 @@ slider_state *ui_manager::slider_current;
// slider controls
static slider_state *slider_alloc(running_machine &machine, const char *title, INT32 minval, INT32 defval, INT32 maxval, INT32 incval, slider_update update, void *arg);
-static slider_state *slider_init(running_machine &machine);
-static INT32 slider_volume(running_machine &machine, void *arg, std::string *str, INT32 newval);
-static INT32 slider_mixervol(running_machine &machine, void *arg, std::string *str, INT32 newval);
-static INT32 slider_adjuster(running_machine &machine, void *arg, std::string *str, INT32 newval);
-static INT32 slider_overclock(running_machine &machine, void *arg, std::string *str, INT32 newval);
-static INT32 slider_refresh(running_machine &machine, void *arg, std::string *str, INT32 newval);
-static INT32 slider_brightness(running_machine &machine, void *arg, std::string *str, INT32 newval);
-static INT32 slider_contrast(running_machine &machine, void *arg, std::string *str, INT32 newval);
-static INT32 slider_gamma(running_machine &machine, void *arg, std::string *str, INT32 newval);
-static INT32 slider_xscale(running_machine &machine, void *arg, std::string *str, INT32 newval);
-static INT32 slider_yscale(running_machine &machine, void *arg, std::string *str, INT32 newval);
-static INT32 slider_xoffset(running_machine &machine, void *arg, std::string *str, INT32 newval);
-static INT32 slider_yoffset(running_machine &machine, void *arg, std::string *str, INT32 newval);
-static INT32 slider_overxscale(running_machine &machine, void *arg, std::string *str, INT32 newval);
-static INT32 slider_overyscale(running_machine &machine, void *arg, std::string *str, INT32 newval);
-static INT32 slider_overxoffset(running_machine &machine, void *arg, std::string *str, INT32 newval);
-static INT32 slider_overyoffset(running_machine &machine, void *arg, std::string *str, INT32 newval);
-static INT32 slider_flicker(running_machine &machine, void *arg, std::string *str, INT32 newval);
-static INT32 slider_beam_width_min(running_machine &machine, void *arg, std::string *str, INT32 newval);
-static INT32 slider_beam_width_max(running_machine &machine, void *arg, std::string *str, INT32 newval);
-static INT32 slider_beam_intensity_weight(running_machine &machine, void *arg, std::string *str, INT32 newval);
+static INT32 slider_volume(running_machine &machine, void *arg, int id, std::string *str, INT32 newval);
+static INT32 slider_mixervol(running_machine &machine, void *arg, int id, std::string *str, INT32 newval);
+static INT32 slider_adjuster(running_machine &machine, void *arg, int id, std::string *str, INT32 newval);
+static INT32 slider_overclock(running_machine &machine, void *arg, int id, std::string *str, INT32 newval);
+static INT32 slider_refresh(running_machine &machine, void *arg, int id, std::string *str, INT32 newval);
+static INT32 slider_brightness(running_machine &machine, void *arg, int id, std::string *str, INT32 newval);
+static INT32 slider_contrast(running_machine &machine, void *arg, int id, std::string *str, INT32 newval);
+static INT32 slider_gamma(running_machine &machine, void *arg, int id, std::string *str, INT32 newval);
+static INT32 slider_xscale(running_machine &machine, void *arg, int id, std::string *str, INT32 newval);
+static INT32 slider_yscale(running_machine &machine, void *arg, int id, std::string *str, INT32 newval);
+static INT32 slider_xoffset(running_machine &machine, void *arg, int id, std::string *str, INT32 newval);
+static INT32 slider_yoffset(running_machine &machine, void *arg, int id, std::string *str, INT32 newval);
+static INT32 slider_overxscale(running_machine &machine, void *arg, int id, std::string *str, INT32 newval);
+static INT32 slider_overyscale(running_machine &machine, void *arg, int id, std::string *str, INT32 newval);
+static INT32 slider_overxoffset(running_machine &machine, void *arg, int id, std::string *str, INT32 newval);
+static INT32 slider_overyoffset(running_machine &machine, void *arg, int id, std::string *str, INT32 newval);
+static INT32 slider_flicker(running_machine &machine, void *arg, int id, std::string *str, INT32 newval);
+static INT32 slider_beam_width_min(running_machine &machine, void *arg, int id, std::string *str, INT32 newval);
+static INT32 slider_beam_width_max(running_machine &machine, void *arg, int id, std::string *str, INT32 newval);
+static INT32 slider_beam_intensity_weight(running_machine &machine, void *arg, int id, std::string *str, INT32 newval);
static std::string slider_get_screen_desc(screen_device &screen);
#ifdef MAME_DEBUG
-static INT32 slider_crossscale(running_machine &machine, void *arg, std::string *str, INT32 newval);
-static INT32 slider_crossoffset(running_machine &machine, void *arg, std::string *str, INT32 newval);
+static INT32 slider_crossscale(running_machine &machine, void *arg, int id, std::string *str, INT32 newval);
+static INT32 slider_crossoffset(running_machine &machine, void *arg, int id, std::string *str, INT32 newval);
#endif
@@ -338,7 +337,15 @@ void ui_manager::exit()
void ui_manager::initialize(running_machine &machine)
{
// initialize the on-screen display system
- slider_list = slider_current = slider_init(machine);
+ slider_list = slider_init(machine);
+ if (slider_list.size() > 0)
+ {
+ slider_current = reinterpret_cast<slider_state *>(slider_list[0].ref);
+ }
+ else
+ {
+ slider_current = nullptr;
+ }
}
@@ -1866,7 +1873,7 @@ UINT32 ui_manager::handler_confirm_quit(running_machine &machine, render_contain
// ui_get_slider_list - get the list of sliders
//-------------------------------------------------
-const slider_state *ui_manager::get_slider_list(void)
+std::vector<ui_menu_item>& ui_manager::get_slider_list(void)
{
return slider_list;
}
@@ -1894,43 +1901,40 @@ static slider_state *slider_alloc(running_machine &machine, const char *title, I
}
-//-------------------------------------------------
-// slider_init - initialize the list of slider
+//----------------------------------------------------------
+// ui_manager::slider_init - initialize the list of slider
// controls
-//-------------------------------------------------
+//----------------------------------------------------------
-static slider_state *slider_init(running_machine &machine)
+std::vector<ui_menu_item> ui_manager::slider_init(running_machine &machine)
{
- slider_state *listhead = nullptr;
- slider_state **tailptr = &listhead;
- std::string str;
- int item;
+ std::vector<slider_state *> sliders;
// add overall volume
- *tailptr = slider_alloc(machine, _("Master Volume"), -32, 0, 0, 1, slider_volume, nullptr);
- tailptr = &(*tailptr)->next;
+ sliders.push_back(slider_alloc(machine, _("Master Volume"), -32, 0, 0, 1, slider_volume, nullptr));
// add per-channel volume
mixer_input info;
- for (item = 0; machine.sound().indexed_mixer_input(item, info); item++)
+ for (int item = 0; machine.sound().indexed_mixer_input(item, info); item++)
{
INT32 maxval = 2000;
INT32 defval = 1000;
- str = string_format(_("%1$s Volume"), info.stream->input_name(info.inputnum));
- *tailptr = slider_alloc(machine, str.c_str(), 0, defval, maxval, 20, slider_mixervol, (void *)(FPTR)item);
- tailptr = &(*tailptr)->next;
+ std::string str = string_format(_("%1$s Volume"), info.stream->input_name(info.inputnum));
+ sliders.push_back(slider_alloc(machine, str.c_str(), 0, defval, maxval, 20, slider_mixervol, (void *)(FPTR)item));
}
// add analog adjusters
for (ioport_port &port : machine.ioport().ports())
+ {
for (ioport_field &field : port.fields())
+ {
if (field.type() == IPT_ADJUSTER)
{
- void *param = (void *)&field;
- *tailptr = slider_alloc(machine, field.name(), field.minval(), field.defvalue(), field.maxval(), 1, slider_adjuster, param);
- tailptr = &(*tailptr)->next;
+ sliders.push_back(slider_alloc(machine, field.name(), field.minval(), field.defvalue(), field.maxval(), 1, slider_adjuster, (void *)&field));
}
+ }
+ }
// add CPU overclocking (cheat only)
if (machine.options().cheat())
@@ -1939,9 +1943,8 @@ static slider_state *slider_init(running_machine &machine)
for (device_execute_interface *exec = iter.first(); exec != nullptr; exec = iter.next())
{
void *param = (void *)&exec->device();
- str = string_format(_("Overclock CPU %1$s"), exec->device().tag());
- *tailptr = slider_alloc(machine, str.c_str(), 10, 1000, 2000, 1, slider_overclock, param);
- tailptr = &(*tailptr)->next;
+ std::string str = string_format(_("Overclock CPU %1$s"), exec->device().tag());
+ sliders.push_back(slider_alloc(machine, str.c_str(), 10, 1000, 2000, 1, slider_overclock, param));
}
}
@@ -1959,39 +1962,32 @@ static slider_state *slider_init(running_machine &machine)
// add refresh rate tweaker
if (machine.options().cheat())
{
- str = string_format(_("%1$s Refresh Rate"), screen_desc);
- *tailptr = slider_alloc(machine, str.c_str(), -10000, 0, 10000, 1000, slider_refresh, param);
- tailptr = &(*tailptr)->next;
+ std::string str = string_format(_("%1$s Refresh Rate"), screen_desc);
+ sliders.push_back(slider_alloc(machine, str.c_str(), -10000, 0, 10000, 1000, slider_refresh, param));
}
// add standard brightness/contrast/gamma controls per-screen
- str = string_format(_("%1$s Brightness"), screen_desc);
- *tailptr = slider_alloc(machine, str.c_str(), 100, 1000, 2000, 10, slider_brightness, param);
- tailptr = &(*tailptr)->next;
+ std::string str = string_format(_("%1$s Brightness"), screen_desc);
+ sliders.push_back(slider_alloc(machine, str.c_str(), 100, 1000, 2000, 10, slider_brightness, param));
str = string_format(_("%1$s Contrast"), screen_desc);
- *tailptr = slider_alloc(machine, str.c_str(), 100, 1000, 2000, 50, slider_contrast, param);
- tailptr = &(*tailptr)->next;
+ sliders.push_back(slider_alloc(machine, str.c_str(), 100, 1000, 2000, 50, slider_contrast, param));
str = string_format(_("%1$s Gamma"), screen_desc);
- *tailptr = slider_alloc(machine, str.c_str(), 100, 1000, 3000, 50, slider_gamma, param);
- tailptr = &(*tailptr)->next;
+ sliders.push_back(slider_alloc(machine, str.c_str(), 100, 1000, 3000, 50, slider_gamma, param));
// add scale and offset controls per-screen
str = string_format(_("%1$s Horiz Stretch"), screen_desc);
- *tailptr = slider_alloc(machine, str.c_str(), 500, defxscale, 1500, 2, slider_xscale, param);
- tailptr = &(*tailptr)->next;
+ sliders.push_back(slider_alloc(machine, str.c_str(), 500, defxscale, 1500, 2, slider_xscale, param));
str = string_format(_("%1$s Horiz Position"), screen_desc);
- *tailptr = slider_alloc(machine, str.c_str(), -500, defxoffset, 500, 2, slider_xoffset, param);
- tailptr = &(*tailptr)->next;
+ sliders.push_back(slider_alloc(machine, str.c_str(), -500, defxoffset, 500, 2, slider_xoffset, param));
str = string_format(_("%1$s Vert Stretch"), screen_desc);
- *tailptr = slider_alloc(machine, str.c_str(), 500, defyscale, 1500, 2, slider_yscale, param);
- tailptr = &(*tailptr)->next;
+ sliders.push_back(slider_alloc(machine, str.c_str(), 500, defyscale, 1500, 2, slider_yscale, param));
str = string_format(_("%1$s Vert Position"), screen_desc);
- *tailptr = slider_alloc(machine, str.c_str(), -500, defyoffset, 500, 2, slider_yoffset, param);
- tailptr = &(*tailptr)->next;
+ sliders.push_back(slider_alloc(machine, str.c_str(), -500, defyoffset, 500, 2, slider_yoffset, param));
}
laserdisc_device_iterator lditer(machine.root_device());
for (laserdisc_device *laserdisc = lditer.first(); laserdisc != nullptr; laserdisc = lditer.next())
+ {
if (laserdisc->overlay_configured())
{
laserdisc_overlay_config config;
@@ -2003,52 +1999,60 @@ static slider_state *slider_init(running_machine &machine)
void *param = (void *)laserdisc;
// add scale and offset controls per-overlay
- str = string_format(_("Laserdisc '%1$s' Horiz Stretch"), laserdisc->tag());
- *tailptr = slider_alloc(machine, str.c_str(), 500, (defxscale == 0) ? 1000 : defxscale, 1500, 2, slider_overxscale, param);
- tailptr = &(*tailptr)->next;
+ std::string str = string_format(_("Laserdisc '%1$s' Horiz Stretch"), laserdisc->tag());
+ sliders.push_back(slider_alloc(machine, str.c_str(), 500, (defxscale == 0) ? 1000 : defxscale, 1500, 2, slider_overxscale, param));
str = string_format(_("Laserdisc '%1$s' Horiz Position"), laserdisc->tag());
- *tailptr = slider_alloc(machine, str.c_str(), -500, defxoffset, 500, 2, slider_overxoffset, param);
- tailptr = &(*tailptr)->next;
+ sliders.push_back(slider_alloc(machine, str.c_str(), -500, defxoffset, 500, 2, slider_overxoffset, param));
str = string_format(_("Laserdisc '%1$s' Vert Stretch"), laserdisc->tag());
- *tailptr = slider_alloc(machine, str.c_str(), 500, (defyscale == 0) ? 1000 : defyscale, 1500, 2, slider_overyscale, param);
- tailptr = &(*tailptr)->next;
+ sliders.push_back(slider_alloc(machine, str.c_str(), 500, (defyscale == 0) ? 1000 : defyscale, 1500, 2, slider_overyscale, param));
str = string_format(_("Laserdisc '%1$s' Vert Position"), laserdisc->tag());
- *tailptr = slider_alloc(machine, str.c_str(), -500, defyoffset, 500, 2, slider_overyoffset, param);
- tailptr = &(*tailptr)->next;
+ sliders.push_back(slider_alloc(machine, str.c_str(), -500, defyoffset, 500, 2, slider_overyoffset, param));
}
+ }
for (screen_device *screen = scriter.first(); screen != nullptr; screen = scriter.next())
+ {
if (screen->screen_type() == SCREEN_TYPE_VECTOR)
{
// add vector control
- *tailptr = slider_alloc(machine, _("Vector Flicker"), 0, 0, 1000, 10, slider_flicker, nullptr);
- tailptr = &(*tailptr)->next;
- *tailptr = slider_alloc(machine, _("Beam Width Minimum"), 1, 100, 1000, 1, slider_beam_width_min, nullptr);
- tailptr = &(*tailptr)->next;
- *tailptr = slider_alloc(machine, _("Beam Width Maximum"), 1, 100, 1000, 1, slider_beam_width_max, nullptr);
- tailptr = &(*tailptr)->next;
- *tailptr = slider_alloc(machine, _("Beam Intensity Weight"), -1000, 0, 1000, 10, slider_beam_intensity_weight, nullptr);
- tailptr = &(*tailptr)->next;
+ sliders.push_back(slider_alloc(machine, _("Vector Flicker"), 0, 0, 1000, 10, slider_flicker, nullptr));
+ sliders.push_back(slider_alloc(machine, _("Beam Width Minimum"), 1, 100, 1000, 1, slider_beam_width_min, nullptr));
+ sliders.push_back(slider_alloc(machine, _("Beam Width Maximum"), 1, 100, 1000, 1, slider_beam_width_max, nullptr));
+ sliders.push_back(slider_alloc(machine, _("Beam Intensity Weight"), -1000, 0, 1000, 10, slider_beam_intensity_weight, nullptr));
break;
}
+ }
#ifdef MAME_DEBUG
// add crosshair adjusters
for (ioport_port &port : machine.ioport().ports())
+ {
for (ioport_field &field : port.fields())
+ {
if (field.crosshair_axis() != CROSSHAIR_AXIS_NONE && field.player() == 0)
{
- void *param = (void *)&field;
- str = string_format(_("Crosshair Scale %1$s"), (field.crosshair_axis() == CROSSHAIR_AXIS_X) ? _("X") : _("Y"));
- *tailptr = slider_alloc(machine, str.c_str(), -3000, 1000, 3000, 100, slider_crossscale, param);
- tailptr = &(*tailptr)->next;
+ std::string str = string_format(_("Crosshair Scale %1$s"), (field.crosshair_axis() == CROSSHAIR_AXIS_X) ? _("X") : _("Y"));
+ sliders.push_back(slider_alloc(machine, str.c_str(), -3000, 1000, 3000, 100, slider_crossscale, (void *)&field));
str = string_format(_("Crosshair Offset %1$s"), (field.crosshair_axis() == CROSSHAIR_AXIS_X) ? _("X") : _("Y"));
- *tailptr = slider_alloc(machine, str.c_str(), -3000, 0, 3000, 100, slider_crossoffset, param);
- tailptr = &(*tailptr)->next;
+ sliders.push_back(slider_alloc(machine, str.c_str(), -3000, 0, 3000, 100, slider_crossoffset, (void *)&field));
}
+ }
+ }
#endif
- return listhead;
+ std::vector<ui_menu_item> items;
+ for (slider_state *slider : sliders)
+ {
+ ui_menu_item item;
+ item.text = slider->description;
+ item.subtext = "";
+ item.flags = 0;
+ item.ref = slider;
+ item.type = ui_menu_item_type::UI_MENU_ITEM_TYPE_SLIDER;
+ items.push_back(item);
+ }
+
+ return items;
}
@@ -2056,7 +2060,7 @@ static slider_state *slider_init(running_machine &machine)
// slider_volume - global volume slider callback
//-------------------------------------------------
-static INT32 slider_volume(running_machine &machine, void *arg, std::string *str, INT32 newval)
+static INT32 slider_volume(running_machine &machine, void *arg, int id, std::string *str, INT32 newval)
{
if (newval != SLIDER_NOCHANGE)
machine.sound().set_attenuation(newval);
@@ -2071,7 +2075,7 @@ static INT32 slider_volume(running_machine &machine, void *arg, std::string *str
// slider callback
//-------------------------------------------------
-static INT32 slider_mixervol(running_machine &machine, void *arg, std::string *str, INT32 newval)
+static INT32 slider_mixervol(running_machine &machine, void *arg, int id, std::string *str, INT32 newval)
{
mixer_input info;
if (!machine.sound().indexed_mixer_input((FPTR)arg, info))
@@ -2093,7 +2097,7 @@ static INT32 slider_mixervol(running_machine &machine, void *arg, std::string *s
// callback
//-------------------------------------------------
-static INT32 slider_adjuster(running_machine &machine, void *arg, std::string *str, INT32 newval)
+static INT32 slider_adjuster(running_machine &machine, void *arg, int id, std::string *str, INT32 newval)
{
ioport_field *field = (ioport_field *)arg;
ioport_field::user_settings settings;
@@ -2115,7 +2119,7 @@ static INT32 slider_adjuster(running_machine &machine, void *arg, std::string *s
// callback
//-------------------------------------------------
-static INT32 slider_overclock(running_machine &machine, void *arg, std::string *str, INT32 newval)
+static INT32 slider_overclock(running_machine &machine, void *arg, int id, std::string *str, INT32 newval)
{
device_t *cpu = (device_t *)arg;
if (newval != SLIDER_NOCHANGE)
@@ -2130,7 +2134,7 @@ static INT32 slider_overclock(running_machine &machine, void *arg, std::string *
// slider_refresh - refresh rate slider callback
//-------------------------------------------------
-static INT32 slider_refresh(running_machine &machine, void *arg, std::string *str, INT32 newval)
+static INT32 slider_refresh(running_machine &machine, void *arg, int id, std::string *str, INT32 newval)
{
screen_device *screen = reinterpret_cast<screen_device *>(arg);
double defrefresh = ATTOSECONDS_TO_HZ(screen->refresh_attoseconds());
@@ -2155,7 +2159,7 @@ static INT32 slider_refresh(running_machine &machine, void *arg, std::string *st
// callback
//-------------------------------------------------
-static INT32 slider_brightness(running_machine &machine, void *arg, std::string *str, INT32 newval)
+static INT32 slider_brightness(running_machine &machine, void *arg, int id, std::string *str, INT32 newval)
{
screen_device *screen = reinterpret_cast<screen_device *>(arg);
render_container::user_settings settings;
@@ -2177,7 +2181,7 @@ static INT32 slider_brightness(running_machine &machine, void *arg, std::string
// callback
//-------------------------------------------------
-static INT32 slider_contrast(running_machine &machine, void *arg, std::string *str, INT32 newval)
+static INT32 slider_contrast(running_machine &machine, void *arg, int id, std::string *str, INT32 newval)
{
screen_device *screen = reinterpret_cast<screen_device *>(arg);
render_container::user_settings settings;
@@ -2198,7 +2202,7 @@ static INT32 slider_contrast(running_machine &machine, void *arg, std::string *s
// slider_gamma - screen gamma slider callback
//-------------------------------------------------
-static INT32 slider_gamma(running_machine &machine, void *arg, std::string *str, INT32 newval)
+static INT32 slider_gamma(running_machine &machine, void *arg, int id, std::string *str, INT32 newval)
{
screen_device *screen = reinterpret_cast<screen_device *>(arg);
render_container::user_settings settings;
@@ -2220,7 +2224,7 @@ static INT32 slider_gamma(running_machine &machine, void *arg, std::string *str,
// callback
//-------------------------------------------------
-static INT32 slider_xscale(running_machine &machine, void *arg, std::string *str, INT32 newval)
+static INT32 slider_xscale(running_machine &machine, void *arg, int id, std::string *str, INT32 newval)
{
screen_device *screen = reinterpret_cast<screen_device *>(arg);
render_container::user_settings settings;
@@ -2242,7 +2246,7 @@ static INT32 slider_xscale(running_machine &machine, void *arg, std::string *str
// callback
//-------------------------------------------------
-static INT32 slider_yscale(running_machine &machine, void *arg, std::string *str, INT32 newval)
+static INT32 slider_yscale(running_machine &machine, void *arg, int id, std::string *str, INT32 newval)
{
screen_device *screen = reinterpret_cast<screen_device *>(arg);
render_container::user_settings settings;
@@ -2264,7 +2268,7 @@ static INT32 slider_yscale(running_machine &machine, void *arg, std::string *str
// slider callback
//-------------------------------------------------
-static INT32 slider_xoffset(running_machine &machine, void *arg, std::string *str, INT32 newval)
+static INT32 slider_xoffset(running_machine &machine, void *arg, int id, std::string *str, INT32 newval)
{
screen_device *screen = reinterpret_cast<screen_device *>(arg);
render_container::user_settings settings;
@@ -2286,7 +2290,7 @@ static INT32 slider_xoffset(running_machine &machine, void *arg, std::string *st
// slider callback
//-------------------------------------------------
-static INT32 slider_yoffset(running_machine &machine, void *arg, std::string *str, INT32 newval)
+static INT32 slider_yoffset(running_machine &machine, void *arg, int id, std::string *str, INT32 newval)
{
screen_device *screen = reinterpret_cast<screen_device *>(arg);
render_container::user_settings settings;
@@ -2308,7 +2312,7 @@ static INT32 slider_yoffset(running_machine &machine, void *arg, std::string *st
// callback
//-------------------------------------------------
-static INT32 slider_overxscale(running_machine &machine, void *arg, std::string *str, INT32 newval)
+static INT32 slider_overxscale(running_machine &machine, void *arg, int id, std::string *str, INT32 newval)
{
laserdisc_device *laserdisc = (laserdisc_device *)arg;
laserdisc_overlay_config settings;
@@ -2330,7 +2334,7 @@ static INT32 slider_overxscale(running_machine &machine, void *arg, std::string
// callback
//-------------------------------------------------
-static INT32 slider_overyscale(running_machine &machine, void *arg, std::string *str, INT32 newval)
+static INT32 slider_overyscale(running_machine &machine, void *arg, int id, std::string *str, INT32 newval)
{
laserdisc_device *laserdisc = (laserdisc_device *)arg;
laserdisc_overlay_config settings;
@@ -2352,7 +2356,7 @@ static INT32 slider_overyscale(running_machine &machine, void *arg, std::string
// slider callback
//-------------------------------------------------
-static INT32 slider_overxoffset(running_machine &machine, void *arg, std::string *str, INT32 newval)
+static INT32 slider_overxoffset(running_machine &machine, void *arg, int id, std::string *str, INT32 newval)
{
laserdisc_device *laserdisc = (laserdisc_device *)arg;
laserdisc_overlay_config settings;
@@ -2374,7 +2378,7 @@ static INT32 slider_overxoffset(running_machine &machine, void *arg, std::string
// slider callback
//-------------------------------------------------
-static INT32 slider_overyoffset(running_machine &machine, void *arg, std::string *str, INT32 newval)
+static INT32 slider_overyoffset(running_machine &machine, void *arg, int id, std::string *str, INT32 newval)
{
laserdisc_device *laserdisc = (laserdisc_device *)arg;
laserdisc_overlay_config settings;
@@ -2396,7 +2400,7 @@ static INT32 slider_overyoffset(running_machine &machine, void *arg, std::string
// callback
//-------------------------------------------------
-static INT32 slider_flicker(running_machine &machine, void *arg, std::string *str, INT32 newval)
+static INT32 slider_flicker(running_machine &machine, void *arg, int id, std::string *str, INT32 newval)
{
vector_device *vector = nullptr;
if (newval != SLIDER_NOCHANGE)
@@ -2412,7 +2416,7 @@ static INT32 slider_flicker(running_machine &machine, void *arg, std::string *st
// callback
//-------------------------------------------------
-static INT32 slider_beam_width_min(running_machine &machine, void *arg, std::string *str, INT32 newval)
+static INT32 slider_beam_width_min(running_machine &machine, void *arg, int id, std::string *str, INT32 newval)
{
vector_device *vector = nullptr;
if (newval != SLIDER_NOCHANGE)
@@ -2428,7 +2432,7 @@ static INT32 slider_beam_width_min(running_machine &machine, void *arg, std::str
// callback
//-------------------------------------------------
-static INT32 slider_beam_width_max(running_machine &machine, void *arg, std::string *str, INT32 newval)
+static INT32 slider_beam_width_max(running_machine &machine, void *arg, int id, std::string *str, INT32 newval)
{
vector_device *vector = nullptr;
if (newval != SLIDER_NOCHANGE)
@@ -2444,7 +2448,7 @@ static INT32 slider_beam_width_max(running_machine &machine, void *arg, std::str
// callback
//-------------------------------------------------
-static INT32 slider_beam_intensity_weight(running_machine &machine, void *arg, std::string *str, INT32 newval)
+static INT32 slider_beam_intensity_weight(running_machine &machine, void *arg, int id, std::string *str, INT32 newval)
{
vector_device *vector = nullptr;
if (newval != SLIDER_NOCHANGE)
@@ -2477,7 +2481,7 @@ static std::string slider_get_screen_desc(screen_device &screen)
//-------------------------------------------------
#ifdef MAME_DEBUG
-static INT32 slider_crossscale(running_machine &machine, void *arg, std::string *str, INT32 newval)
+static INT32 slider_crossscale(running_machine &machine, void *arg, int id, std::string *str, INT32 newval)
{
ioport_field *field = (ioport_field *)arg;
@@ -2496,7 +2500,7 @@ static INT32 slider_crossscale(running_machine &machine, void *arg, std::string
//-------------------------------------------------
#ifdef MAME_DEBUG
-static INT32 slider_crossoffset(running_machine &machine, void *arg, std::string *str, INT32 newval)
+static INT32 slider_crossoffset(running_machine &machine, void *arg, int id, std::string *str, INT32 newval)
{
ioport_field *field = (ioport_field *)arg;
diff --git a/src/emu/ui/ui.h b/src/emu/ui/ui.h
index 8639c1fba27..9af361c8cc5 100644
--- a/src/emu/ui/ui.h
+++ b/src/emu/ui/ui.h
@@ -13,9 +13,13 @@
#ifndef __USRINTRF_H__
#define __USRINTRF_H__
+#include <vector>
+
#include "render.h"
#include "moptions.h"
+class ui_menu_item;
+
/***************************************************************************
CONSTANTS
***************************************************************************/
@@ -92,7 +96,7 @@ enum
typedef UINT32 (*ui_callback)(running_machine &, render_container *, UINT32);
-typedef INT32(*slider_update)(running_machine &machine, void *arg, std::string *str, INT32 newval);
+typedef INT32(*slider_update)(running_machine &machine, void *arg, int id, std::string *str, INT32 newval);
struct slider_state
{
@@ -128,6 +132,7 @@ public:
// methods
void initialize(running_machine &machine);
+ std::vector<ui_menu_item> slider_init(running_machine &machine);
UINT32 set_handler(ui_callback callback, UINT32 param);
void display_startup_screens(bool first_time);
void set_startup_text(const char *text, bool force);
@@ -166,7 +171,7 @@ public:
std::string &game_info_astring(std::string &str);
// slider controls
- const slider_state *get_slider_list(void);
+ std::vector<ui_menu_item>& get_slider_list(void);
// other
void process_natural_keyboard();
@@ -209,7 +214,7 @@ private:
static std::string messagebox_poptext;
static rgb_t messagebox_backcolor;
- static slider_state *slider_list;
+ static std::vector<ui_menu_item> slider_list;
static slider_state *slider_current;
// text generators
diff --git a/src/lib/netlist/build/makefile b/src/lib/netlist/build/makefile
index be49d098a0d..684b2687ba1 100644
--- a/src/lib/netlist/build/makefile
+++ b/src/lib/netlist/build/makefile
@@ -20,8 +20,8 @@ CDEFS = -DPSTANDALONE=1 -DPTR64=1
#-Werror
#CFLAGS = $(LTO) -g -O3 -std=c++98 -Doverride="" -march=native -msse4.2 -Wall -Wpedantic -Wsign-compare -Wextra -Wno-long-long -Wno-unused-parameter -Wno-unused-result -Wno-variadic-macros -I..
#LDFLAGS = $(LTO) -g -O3 -std=c++98
-CFLAGS = $(LTO) -g -O3 -std=c++11 -I.. -Wall -Wpedantic -Wsign-compare -Wextra -Wno-unused-parameter
-LDFLAGS = $(LTO) -g -O3 -std=c++11
+CFLAGS = $(LTO) -g -O3 -std=c++11 -march=native -I.. -Wall -Wpedantic -Wsign-compare -Wextra -Wno-unused-parameter
+LDFLAGS = $(LTO) -g -O3 -std=c++11 -lpthread
CC = @g++-5
LD = @g++-5
diff --git a/src/lib/netlist/devices/nld_system.h b/src/lib/netlist/devices/nld_system.h
index 8ea3640ec14..7b9cb7298e5 100644
--- a/src/lib/netlist/devices/nld_system.h
+++ b/src/lib/netlist/devices/nld_system.h
@@ -479,10 +479,10 @@ public:
const pstring &def_param)
: base_factory_t(name, classname, def_param), m_setup(setup) { }
- class dummy : public device_t
+ class wrapper : public device_t
{
public:
- dummy(const pstring &dev_name) : device_t(), m_dev_name(dev_name) { }
+ wrapper(const pstring &dev_name) : device_t(), m_dev_name(dev_name) { }
protected:
virtual void init(netlist_t &anetlist, const pstring &aname) override
{
@@ -499,7 +499,7 @@ public:
ATTR_COLD device_t *Create() override
{
- device_t *r = palloc(dummy(this->name()));
+ device_t *r = palloc(wrapper(this->name()));
return r;
}
diff --git a/src/lib/netlist/nl_base.cpp b/src/lib/netlist/nl_base.cpp
index 7afa0285ef8..eb83749c79b 100644
--- a/src/lib/netlist/nl_base.cpp
+++ b/src/lib/netlist/nl_base.cpp
@@ -74,13 +74,12 @@ logic_family_desc_t *family_CD4XXX = palloc(logic_family_cd4xxx_t);
queue_t::queue_t(netlist_t &nl)
: timed_queue<net_t *, netlist_time>(512)
- , object_t(QUEUE, GENERIC)
+ , object_t(nl, "QUEUE", QUEUE, GENERIC)
, pstate_callback_t()
, m_qsize(0)
, m_times(512)
, m_names(512)
{
- this->init_object(nl, "QUEUE");
}
void queue_t::register_state(pstate_manager_t &manager, const pstring &module)
@@ -128,13 +127,33 @@ void queue_t::on_post_load()
ATTR_COLD object_t::object_t(const type_t atype, const family_t afamily)
: m_objtype(atype)
, m_family(afamily)
-, m_netlist(NULL)
+, m_netlist(nullptr)
{}
+ATTR_COLD object_t::object_t(netlist_t &nl, const type_t atype, const family_t afamily)
+: m_objtype(atype)
+, m_family(afamily)
+, m_netlist(&nl)
+{}
+
+ATTR_COLD object_t::object_t(netlist_t &nl, const pstring &aname, const type_t atype, const family_t afamily)
+: m_name(aname)
+, m_objtype(atype)
+, m_family(afamily)
+, m_netlist(&nl)
+{
+}
+
ATTR_COLD object_t::~object_t()
{
}
+ATTR_COLD void object_t::init_object(const pstring &aname)
+{
+ m_name = aname;
+ save_register();
+}
+
ATTR_COLD void object_t::init_object(netlist_t &nl, const pstring &aname)
{
m_netlist = &nl;
@@ -171,8 +190,8 @@ ATTR_COLD void device_object_t::init_object(core_device_t &dev,
// netlist_t
// ----------------------------------------------------------------------------------------
-netlist_t::netlist_t()
- : object_t(NETLIST, GENERIC), pstate_manager_t(),
+netlist_t::netlist_t(const pstring &aname)
+ : pstate_manager_t(),
m_stop(netlist_time::zero),
m_time(netlist_time::zero),
m_use_deactivate(0),
@@ -181,9 +200,12 @@ netlist_t::netlist_t()
m_solver(NULL),
m_gnd(NULL),
m_params(NULL),
+ m_name(aname),
m_setup(NULL),
m_log(this)
{
+ save_item(static_cast<pstate_callback_t &>(m_queue), this, "m_queue");
+ save_item(m_time, this, "m_time");
}
netlist_t::~netlist_t()
@@ -202,13 +224,6 @@ netlist_t::~netlist_t()
pstring::resetmem();
}
-ATTR_COLD void netlist_t::save_register()
-{
- save(static_cast<pstate_callback_t &>(m_queue), "m_queue");
- save(NLNAME(m_time));
- object_t::save_register();
-}
-
ATTR_HOT nl_double netlist_t::gmin() const
{
return solver()->gmin();
@@ -925,6 +940,19 @@ ATTR_COLD analog_output_t::analog_output_t()
net().m_cur_Analog = NL_FCONST(0.99);
}
+ATTR_COLD analog_output_t::analog_output_t(core_device_t &dev, const pstring &aname)
+ : analog_t(OUTPUT), m_proxied_net(NULL)
+{
+ this->set_net(m_my_net);
+ set_state(STATE_OUT);
+
+ net().m_cur_Analog = NL_FCONST(0.99);
+
+ analog_t::init_object(dev, aname);
+ net().init_object(dev.netlist(), aname + ".net");
+ net().register_railterminal(*this);
+}
+
ATTR_COLD void analog_output_t::init_object(core_device_t &dev, const pstring &aname)
{
analog_t::init_object(dev, aname);
diff --git a/src/lib/netlist/nl_base.h b/src/lib/netlist/nl_base.h
index 52a91704607..3b6eb7b75e1 100644
--- a/src/lib/netlist/nl_base.h
+++ b/src/lib/netlist/nl_base.h
@@ -367,7 +367,7 @@ namespace netlist
// object_t
// -----------------------------------------------------------------------------
- class object_t
+ class object_t : public pstate_interface_t<object_t>
{
P_PREVENT_COPYING(object_t)
public:
@@ -378,8 +378,7 @@ namespace netlist
PARAM = 3,
NET = 4,
DEVICE = 5,
- NETLIST = 6,
- QUEUE = 7
+ QUEUE = 6
};
enum family_t {
// Terminal families
@@ -405,15 +404,18 @@ namespace netlist
};
ATTR_COLD object_t(const type_t atype, const family_t afamily);
+ ATTR_COLD object_t(netlist_t &nl, const type_t atype, const family_t afamily);
+ ATTR_COLD object_t(netlist_t &nl, const pstring &aname, const type_t atype, const family_t afamily);
virtual ~object_t();
+ ATTR_COLD void init_object(const pstring &aname);
ATTR_COLD void init_object(netlist_t &nl, const pstring &aname);
ATTR_COLD bool isInitialized() { return (m_netlist != NULL); }
ATTR_COLD const pstring &name() const;
- PSTATE_INTERFACE_DECL()
+ ATTR_COLD inline pstate_manager_t *state_manager();
ATTR_HOT type_t type() const { return m_objtype; }
ATTR_HOT family_t family() const { return m_family; }
@@ -904,6 +906,7 @@ namespace netlist
P_PREVENT_COPYING(analog_output_t)
public:
+ ATTR_COLD analog_output_t(core_device_t &dev, const pstring &aname);
ATTR_COLD analog_output_t();
ATTR_COLD void init_object(core_device_t &dev, const pstring &aname);
@@ -1183,14 +1186,16 @@ namespace netlist
// -----------------------------------------------------------------------------
- class netlist_t : public object_t, public pstate_manager_t, public plog_dispatch_intf
+ class netlist_t : public pstate_manager_t, public plog_dispatch_intf
{
P_PREVENT_COPYING(netlist_t)
public:
- netlist_t();
+ netlist_t(const pstring &aname);
virtual ~netlist_t();
+ pstring name() const { return m_name; }
+
ATTR_COLD void start();
ATTR_COLD void stop();
@@ -1265,14 +1270,12 @@ namespace netlist
pnamedlist_t<core_device_t *> m_started_devices;
#endif
- ATTR_COLD plog_base<NL_DEBUG> &log() { return m_log; }
- ATTR_COLD const plog_base<NL_DEBUG> &log() const { return m_log; }
+ ATTR_COLD plog_base<NL_DEBUG> &log() { return m_log; }
+ ATTR_COLD const plog_base<NL_DEBUG> &log() const { return m_log; }
- protected:
+ virtual void reset();
- /* from object */
- virtual void reset() override;
- virtual void save_register() override;
+ protected:
#if (NL_KEEP_STATISTICS)
// performance
@@ -1288,13 +1291,13 @@ namespace netlist
bool m_use_deactivate;
queue_t m_queue;
-
devices::NETLIB_NAME(mainclock) * m_mainclock;
devices::NETLIB_NAME(solver) * m_solver;
devices::NETLIB_NAME(gnd) * m_gnd;
-
devices::NETLIB_NAME(netlistparams) *m_params;
+
+ pstring m_name;
setup_t *m_setup;
plog_base<NL_DEBUG> m_log;
};
@@ -1303,7 +1306,10 @@ namespace netlist
// inline implementations
// -----------------------------------------------------------------------------
- PSTATE_INTERFACE(object_t, m_netlist, name())
+ ATTR_COLD inline pstate_manager_t *object_t::state_manager()
+ {
+ return m_netlist;
+ }
template <class C, param_t::param_type_t T>
ATTR_HOT inline void param_template_t<C, T>::setTo(const C &param)
diff --git a/src/lib/netlist/nl_setup.cpp b/src/lib/netlist/nl_setup.cpp
index 399fe86d213..dad17991b87 100644
--- a/src/lib/netlist/nl_setup.cpp
+++ b/src/lib/netlist/nl_setup.cpp
@@ -197,8 +197,6 @@ pstring setup_t::objtype_as_astr(object_t &in) const
return "PARAM";
case terminal_t::DEVICE:
return "DEVICE";
- case terminal_t::NETLIST:
- return "NETLIST";
case terminal_t::QUEUE:
return "QUEUE";
}
@@ -283,9 +281,6 @@ void setup_t::register_object(device_t &dev, const pstring &name, object_t &obj)
case terminal_t::DEVICE:
log().fatal("Device registration not yet supported - {1}\n", name);
break;
- case terminal_t::NETLIST:
- log().fatal("Netlist registration not yet supported - {1}\n", name);
- break;
case terminal_t::QUEUE:
log().fatal("QUEUE registration not yet supported - {1}\n", name);
break;
diff --git a/src/lib/netlist/nl_util.h b/src/lib/netlist/nl_util.h
index 87ec2270231..50c545c22e3 100644
--- a/src/lib/netlist/nl_util.h
+++ b/src/lib/netlist/nl_util.h
@@ -11,6 +11,7 @@
#include <cmath>
#include <cstring>
#include <cstdlib>
+#include <algorithm>
#include "plib/pstring.h"
#include "plib/plists.h"
@@ -40,26 +41,35 @@ private:
nl_math() {};
public:
- ATTR_HOT inline static float exp(const float x) { return std::exp(x); }
- ATTR_HOT inline static double abs(const double x) { return std::fabs(x); }
- ATTR_HOT inline static float abs(const float x) { return std::fabs(x); }
- ATTR_HOT inline static double log(const double x) { return std::log(x); }
- ATTR_HOT inline static float log(const float x) { return std::log(x); }
-#if defined(_MSC_VER) && _MSC_VER < 1800
- ATTR_HOT inline static double e_log1p(const double x) { return nl_math::log(1.0 + x); }
- ATTR_HOT inline static float e_log1p(const float x) { return nl_math::log(1.0 + x); }
+ template <typename T>
+ static T abs(const T &x) { return std::abs(x); }
+
+ template <typename T>
+ static T max(const T &x, const T &y) { return std::max(x, y); }
+
+ template <typename T>
+ static T min(const T &x, const T &y) { return std::min(x, y); }
+
+ template <typename T>
+ static T log(const T &x) { return std::log(x); }
+
+ #if defined(_MSC_VER) && _MSC_VER < 1800
+ ATTR_HOT inline static double e_log1p(const double &x) { return nl_math::log(1.0 + x); }
+ ATTR_HOT inline static float e_log1p(const float &x) { return nl_math::log(1.0 + x); }
#else
- ATTR_HOT inline static double e_log1p(const double x) { return log1p(x); }
- ATTR_HOT inline static float e_log1p(const float x) { return log1pf(x); }
+ template <typename T>
+ static T e_log1p(const T &x) { return log1p(x); }
#endif
- ATTR_HOT inline static double sqrt(const double x) { return std::sqrt(x); }
- ATTR_HOT inline static float sqrt(const float x) { return std::sqrt(x); }
+
+ template <typename T>
+ static T sqrt(const T &x) { return std::sqrt(x); }
// this one has an accuracy of better than 5%. That's enough for our purpose
// add c3 and it'll be better than 1%
#if 0
- inline static double fastexp_h(const double x)
+ ATTR_HOT inline static float exp(const float &x) { return std::exp(x); }
+ inline static double fastexp_h(const double &x)
{
/* static */ const double ln2r = 1.442695040888963387;
/* static */ const double ln2 = 0.693147180559945286;
@@ -79,7 +89,7 @@ public:
return pow(2.0, t)*e;
}
- ATTR_HOT inline static double exp(const double x)
+ ATTR_HOT inline static double exp(const double &x)
{
if (x<0)
return 1.0 / fastexp_h(-x);
@@ -87,7 +97,8 @@ public:
return fastexp_h(x);
}
#else
- ATTR_HOT inline static double exp(const double x) { return std::exp(x); }
+ template <typename T>
+ static double exp(const T &x) { return std::exp(x); }
#endif
};
diff --git a/src/lib/netlist/plib/pstate.h b/src/lib/netlist/plib/pstate.h
index 91c67ee0e1c..88c0c005927 100644
--- a/src/lib/netlist/plib/pstate.h
+++ b/src/lib/netlist/plib/pstate.h
@@ -15,19 +15,6 @@
// state saving ...
// ----------------------------------------------------------------------------------------
-#define PSTATE_INTERFACE_DECL() \
- template<typename C> ATTR_COLD void save(C &state, const pstring &stname); \
- template<typename C, std::size_t N> ATTR_COLD void save(C (&state)[N], const pstring &stname); \
- template<typename C> ATTR_COLD void save(C *state, const pstring &stname, const int count);
-
-#define PSTATE_INTERFACE(obj, manager, module) \
- template<typename C> ATTR_COLD void obj::save(C &state, const pstring &stname) \
- { manager->save_item(state, this, module + "." + stname); } \
- template<typename C, std::size_t N> ATTR_COLD void obj::save(C (&state)[N], const pstring &stname) \
- { manager->save_state_ptr(module + "." + stname, pstate_datatype<C>::type, this, sizeof(state[0]), N, &(state[0]), false); } \
- template<typename C> ATTR_COLD void obj::save(C *state, const pstring &stname, const int count) \
- { manager->save_state_ptr(module + "." + stname, pstate_datatype<C>::type, this, sizeof(C), count, state, false); }
-
enum pstate_data_type_e {
NOT_SUPPORTED,
DT_CUSTOM,
@@ -148,6 +135,12 @@ public:
save_state_ptr(stname, pstate_datatype<C>::type, owner, sizeof(C), count, state, false);
}
+ template<typename C>
+ void save_item(std::vector<C> &v, const void *owner, const pstring &stname)
+ {
+ save_state(v.data(), owner, stname, v.size());
+ }
+
ATTR_COLD void pre_save();
ATTR_COLD void post_load();
ATTR_COLD void remove_save_items(const void *owner);
@@ -164,5 +157,31 @@ private:
template<> ATTR_COLD void pstate_manager_t::save_item(pstate_callback_t &state, const void *owner, const pstring &stname);
+template <typename T>
+class pstate_interface_t
+{
+public:
+ pstate_interface_t() { }
+
+ template<typename C> void save(C &state, const pstring &stname)
+ {
+ pstate_manager_t *manager = static_cast<T*>(this)->state_manager();
+ pstring module = static_cast<T*>(this)->name();
+ manager->save_item(state, this, module + "." + stname);
+ }
+ template<typename C, std::size_t N> ATTR_COLD void save(C (&state)[N], const pstring &stname)
+ {
+ pstate_manager_t *manager = static_cast<T*>(this)->state_manager();
+ pstring module = static_cast<T*>(this)->name();
+ manager->save_state_ptr(module + "." + stname, pstate_datatype<C>::type, this, sizeof(state[0]), N, &(state[0]), false);
+ }
+ template<typename C> ATTR_COLD void save(C *state, const pstring &stname, const int count)
+ {
+ pstate_manager_t *manager = static_cast<T*>(this)->state_manager();
+ pstring module = static_cast<T*>(this)->name();
+ manager->save_state_ptr(module + "." + stname, pstate_datatype<C>::type, this, sizeof(C), count, state, false);
+ }
+};
+
#endif /* PSTATE_H_ */
diff --git a/src/lib/netlist/prg/nltool.cpp b/src/lib/netlist/prg/nltool.cpp
index ea5211a3c87..6d34683731e 100644
--- a/src/lib/netlist/prg/nltool.cpp
+++ b/src/lib/netlist/prg/nltool.cpp
@@ -145,8 +145,8 @@ class netlist_tool_t : public netlist::netlist_t
{
public:
- netlist_tool_t()
- : netlist::netlist_t(), m_opts(NULL), m_setup(NULL)
+ netlist_tool_t(const pstring &aname)
+ : netlist::netlist_t(aname), m_opts(NULL), m_setup(NULL)
{
}
@@ -159,7 +159,6 @@ public:
void init()
{
m_setup = palloc(netlist::setup_t(this));
- this->init_object(*this, "netlist");
m_setup->init();
}
@@ -281,7 +280,7 @@ pvector_t<input_t> *read_input(netlist::netlist_t *netlist, pstring fname)
static void run(tool_options_t &opts)
{
- netlist_tool_t nt;
+ netlist_tool_t nt("netlist");
osd_ticks_t t = osd_ticks();
nt.m_opts = &opts;
@@ -326,7 +325,7 @@ static void run(tool_options_t &opts)
static void listdevices()
{
- netlist_tool_t nt;
+ netlist_tool_t nt("netlist");
nt.init();
const netlist::factory_list_t &list = nt.setup().factory();
diff --git a/src/lib/netlist/solver/nld_matrix_solver.h b/src/lib/netlist/solver/nld_matrix_solver.h
index 715eab6756a..58947144ff5 100644
--- a/src/lib/netlist/solver/nld_matrix_solver.h
+++ b/src/lib/netlist/solver/nld_matrix_solver.h
@@ -10,14 +10,16 @@
#include "solver/nld_solver.h"
+#include <type_traits>
+
NETLIB_NAMESPACE_DEVICES_START()
class terms_t
{
P_PREVENT_COPYING(terms_t)
- public:
- ATTR_COLD terms_t() : m_railstart(0)
+public:
+ ATTR_COLD terms_t() : m_railstart(0), m_last_V(0)
{}
ATTR_COLD void clear()
@@ -48,6 +50,10 @@ class terms_t
pvector_t<unsigned> m_nz; /* all non zero for multiplication */
pvector_t<unsigned> m_nzrd; /* non zero right of the diagonal for elimination, may include RHS element */
pvector_t<unsigned> m_nzbd; /* non zero below of the diagonal for elimination */
+
+ /* state */
+ nl_double m_last_V;
+
private:
pvector_t<terminal_t *> m_term;
pvector_t<int> m_net_other;
@@ -55,6 +61,7 @@ private:
pvector_t<nl_double> m_gt;
pvector_t<nl_double> m_Idr;
pvector_t<nl_double *> m_other_curanalog;
+
};
class matrix_solver_t : public device_t
@@ -104,14 +111,28 @@ protected:
ATTR_COLD void setup_base(analog_net_t::list_t &nets);
void update_dynamic();
- virtual void add_term(int net_idx, terminal_t *term) = 0;
virtual void vsetup(analog_net_t::list_t &nets) = 0;
virtual int vsolve_non_dynamic(const bool newton_raphson) = 0;
- virtual netlist_time compute_next_timestep() = 0;
+ /* virtual */ netlist_time compute_next_timestep();
+ /* virtual */ void add_term(int net_idx, terminal_t *term);
+
+ template <typename T>
+ void store(const T * RESTRICT V);
+ template <typename T>
+ T delta(const T * RESTRICT V);
+
+ template <typename T>
+ void build_LE_A(T & child);
+ template <typename T>
+ void build_LE_RHS(T & child);
+
+ pvector_t<terms_t *> m_terms;
pvector_t<analog_net_t *> m_nets;
pvector_t<analog_output_t *> m_inps;
+ pvector_t<terms_t *> m_rails_temp;
+
int m_stat_calculations;
int m_stat_newton_raphson;
int m_stat_vsolver_calls;
@@ -138,6 +159,83 @@ private:
const eSolverType m_type;
};
+template <typename T>
+T matrix_solver_t::delta(const T * RESTRICT V)
+{
+ /* FIXME: Ideally we should also include currents (RHS) here. This would
+ * need a revaluation of the right hand side after voltages have been updated
+ * and thus belong into a different calculation. This applies to all solvers.
+ */
+
+ const unsigned iN = this->m_terms.size();
+ T cerr = 0;
+ for (unsigned i = 0; i < iN; i++)
+ cerr = nl_math::max(cerr, nl_math::abs(V[i] - (T) this->m_nets[i]->m_cur_Analog));
+ return cerr;
+}
+
+template <typename T>
+void matrix_solver_t::store(const T * RESTRICT V)
+{
+ for (unsigned i = 0, iN=m_terms.size(); i < iN; i++)
+ this->m_nets[i]->m_cur_Analog = V[i];
+}
+
+template <typename T>
+void matrix_solver_t::build_LE_A(T & child)
+{
+ static_assert(std::is_base_of<matrix_solver_t, T>::value, "T must derive from matrix_solver_t");
+
+ const unsigned iN = child.N();
+ for (unsigned k = 0; k < iN; k++)
+ {
+ for (unsigned i=0; i < iN; i++)
+ child.A(k,i) = 0.0;
+
+ const unsigned terms_count = m_terms[k]->count();
+ const unsigned railstart = m_terms[k]->m_railstart;
+ const nl_double * RESTRICT gt = m_terms[k]->gt();
+
+ {
+ nl_double akk = 0.0;
+ for (unsigned i = 0; i < terms_count; i++)
+ akk += gt[i];
+
+ child.A(k,k) = akk;
+ }
+
+ const nl_double * RESTRICT go = m_terms[k]->go();
+ const int * RESTRICT net_other = m_terms[k]->net_other();
+
+ for (unsigned i = 0; i < railstart; i++)
+ child.A(k,net_other[i]) -= go[i];
+ }
+}
+
+template <typename T>
+void matrix_solver_t::build_LE_RHS(T & child)
+{
+ const unsigned iN = child.N();
+ for (unsigned k = 0; k < iN; k++)
+ {
+ nl_double rhsk_a = 0.0;
+ nl_double rhsk_b = 0.0;
+
+ const unsigned terms_count = m_terms[k]->count();
+ const nl_double * RESTRICT go = m_terms[k]->go();
+ const nl_double * RESTRICT Idr = m_terms[k]->Idr();
+ const nl_double * const * RESTRICT other_cur_analog = m_terms[k]->other_curanalog();
+
+ for (unsigned i = 0; i < terms_count; i++)
+ rhsk_a = rhsk_a + Idr[i];
+
+ for (unsigned i = m_terms[k]->m_railstart; i < terms_count; i++)
+ //rhsk = rhsk + go[i] * terms[i]->m_otherterm->net().as_analog().Q_Analog();
+ rhsk_b = rhsk_b + go[i] * *other_cur_analog[i];
+
+ child.RHS(k) = rhsk_a + rhsk_b;
+ }
+}
NETLIB_NAMESPACE_DEVICES_END()
diff --git a/src/lib/netlist/solver/nld_ms_direct.h b/src/lib/netlist/solver/nld_ms_direct.h
index f0c892ab698..2b0ae80b855 100644
--- a/src/lib/netlist/solver/nld_ms_direct.h
+++ b/src/lib/netlist/solver/nld_ms_direct.h
@@ -50,8 +50,7 @@ struct ti_t
};
static ti_t ti[MAXTHR];
-//static std::thread thr[MAXTHR];
-static std::thread thr[num_thr];
+static std::thread thr[MAXTHR];
int thr_init = 0;
@@ -119,6 +118,7 @@ class matrix_solver_direct_t: public matrix_solver_t, public thr_intf
class matrix_solver_direct_t: public matrix_solver_t
#endif
{
+ friend class matrix_solver_t;
public:
matrix_solver_direct_t(const solver_parameters_t *params, const int size);
@@ -130,27 +130,16 @@ public:
virtual void reset() override { matrix_solver_t::reset(); }
protected:
- virtual void add_term(int net_idx, terminal_t *term) override;
virtual int vsolve_non_dynamic(const bool newton_raphson) override;
int solve_non_dynamic(const bool newton_raphson);
inline unsigned N() const { if (m_N == 0) return m_dim; else return m_N; }
- void build_LE_A();
- void build_LE_RHS();
void LE_solve();
template <typename T>
void LE_back_subst(T * RESTRICT x);
- template <typename T>
- T delta(const T * RESTRICT V);
-
- template <typename T>
- void store(const T * RESTRICT V);
-
- virtual netlist_time compute_next_timestep() override;
-
#if TEST_PARALLEL
int x_i[10];
int x_start[10];
@@ -170,10 +159,6 @@ protected:
inline nl_ext_double &RHS(const T1 &r) { return m_A[r][N()]; }
#endif
ATTR_ALIGN nl_double m_last_RHS[_storage_N]; // right hand side - contains currents
- ATTR_ALIGN nl_double m_last_V[_storage_N];
-
- terms_t * m_terms[_storage_N];
- terms_t *m_rails_temp;
private:
static const std::size_t m_pitch = (((_storage_N + 1) + 7) / 8) * 8;
@@ -197,109 +182,36 @@ private:
template <unsigned m_N, unsigned _storage_N>
matrix_solver_direct_t<m_N, _storage_N>::~matrix_solver_direct_t()
{
- for (unsigned k = 0; k < N(); k++)
- {
- pfree(m_terms[k]);
- }
- pfree_array(m_rails_temp);
#if (NL_USE_DYNAMIC_ALLOCATION)
pfree_array(m_A);
#endif
#if TEST_PARALLEL
thr_dispose();
#endif
-
}
template <unsigned m_N, unsigned _storage_N>
-netlist_time matrix_solver_direct_t<m_N, _storage_N>::compute_next_timestep()
-{
- nl_double new_solver_timestep = m_params.m_max_timestep;
-
- if (m_params.m_dynamic)
- {
- /*
- * FIXME: We should extend the logic to use either all nets or
- * only output nets.
- */
- for (unsigned k = 0, iN=N(); k < iN; k++)
- {
- analog_net_t *n = m_nets[k];
-
- const nl_double DD_n = (n->Q_Analog() - m_last_V[k]);
- const nl_double hn = current_timestep();
-
- nl_double DD2 = (DD_n / hn - n->m_DD_n_m_1 / n->m_h_n_m_1) / (hn + n->m_h_n_m_1);
- nl_double new_net_timestep;
-
- n->m_h_n_m_1 = hn;
- n->m_DD_n_m_1 = DD_n;
- if (nl_math::abs(DD2) > NL_FCONST(1e-30)) // avoid div-by-zero
- new_net_timestep = nl_math::sqrt(m_params.m_lte / nl_math::abs(NL_FCONST(0.5)*DD2));
- else
- new_net_timestep = m_params.m_max_timestep;
-
- if (new_net_timestep < new_solver_timestep)
- new_solver_timestep = new_net_timestep;
-
- m_last_V[k] = n->Q_Analog();
- }
- if (new_solver_timestep < m_params.m_min_timestep)
- new_solver_timestep = m_params.m_min_timestep;
- }
- //if (new_solver_timestep > 10.0 * hn)
- // new_solver_timestep = 10.0 * hn;
- return netlist_time::from_double(new_solver_timestep);
-}
-
-template <unsigned m_N, unsigned _storage_N>
-ATTR_COLD void matrix_solver_direct_t<m_N, _storage_N>::add_term(int k, terminal_t *term)
-{
- if (term->m_otherterm->net().isRailNet())
- {
- m_rails_temp[k].add(term, -1, false);
- }
- else
- {
- int ot = get_net_idx(&term->m_otherterm->net());
- if (ot>=0)
- {
- m_terms[k]->add(term, ot, true);
- }
- /* Should this be allowed ? */
- else // if (ot<0)
- {
- m_rails_temp[k].add(term, ot, true);
- log().fatal("found term with missing othernet {1}\n", term->name());
- }
- }
-}
-
-
-template <unsigned m_N, unsigned _storage_N>
ATTR_COLD void matrix_solver_direct_t<m_N, _storage_N>::vsetup(analog_net_t::list_t &nets)
{
if (m_dim < nets.size())
log().fatal("Dimension {1} less than {2}", m_dim, nets.size());
- for (unsigned k = 0; k < N(); k++)
- {
- m_terms[k]->clear();
- m_rails_temp[k].clear();
- }
-
matrix_solver_t::setup_base(nets);
for (unsigned k = 0; k < N(); k++)
{
m_terms[k]->m_railstart = m_terms[k]->count();
- for (unsigned i = 0; i < m_rails_temp[k].count(); i++)
- this->m_terms[k]->add(m_rails_temp[k].terms()[i], m_rails_temp[k].net_other()[i], false);
+ for (unsigned i = 0; i < m_rails_temp[k]->count(); i++)
+ this->m_terms[k]->add(m_rails_temp[k]->terms()[i], m_rails_temp[k]->net_other()[i], false);
- m_rails_temp[k].clear(); // no longer needed
+ m_rails_temp[k]->clear(); // no longer needed
m_terms[k]->set_pointers();
}
+ for (unsigned k = 0; k < N(); k++)
+ pfree(m_rails_temp[k]); // no longer needed
+
+ m_rails_temp.clear();
#if 1
/* Sort in descending order by number of connected matrix voltages.
@@ -431,13 +343,13 @@ ATTR_COLD void matrix_solver_direct_t<m_N, _storage_N>::vsetup(analog_net_t::lis
* save states
*/
save(NLNAME(m_last_RHS));
- save(NLNAME(m_last_V));
for (unsigned k = 0; k < N(); k++)
{
pstring num = pfmt("{1}")(k);
save(RHS(k), "RHS" + num);
+ save(m_terms[k]->m_last_V, "lastV" + num);
save(m_terms[k]->go(),"GO" + num, m_terms[k]->count());
save(m_terms[k]->gt(),"GT" + num, m_terms[k]->count());
@@ -447,59 +359,6 @@ ATTR_COLD void matrix_solver_direct_t<m_N, _storage_N>::vsetup(analog_net_t::lis
}
-template <unsigned m_N, unsigned _storage_N>
-void matrix_solver_direct_t<m_N, _storage_N>::build_LE_A()
-{
- const unsigned iN = N();
- for (unsigned k = 0; k < iN; k++)
- {
- for (unsigned i=0; i < iN; i++)
- A(k,i) = 0.0;
-
- const unsigned terms_count = m_terms[k]->count();
- const unsigned railstart = m_terms[k]->m_railstart;
- const nl_double * RESTRICT gt = m_terms[k]->gt();
-
- {
- nl_double akk = 0.0;
- for (unsigned i = 0; i < terms_count; i++)
- akk += gt[i];
-
- A(k,k) = akk;
- }
-
- const nl_double * RESTRICT go = m_terms[k]->go();
- const int * RESTRICT net_other = m_terms[k]->net_other();
-
- for (unsigned i = 0; i < railstart; i++)
- A(k,net_other[i]) -= go[i];
- }
-}
-
-template <unsigned m_N, unsigned _storage_N>
-void matrix_solver_direct_t<m_N, _storage_N>::build_LE_RHS()
-{
- const unsigned iN = N();
- for (unsigned k = 0; k < iN; k++)
- {
- nl_double rhsk_a = 0.0;
- nl_double rhsk_b = 0.0;
-
- const int terms_count = m_terms[k]->count();
- const nl_double * RESTRICT go = m_terms[k]->go();
- const nl_double * RESTRICT Idr = m_terms[k]->Idr();
- const nl_double * const * RESTRICT other_cur_analog = m_terms[k]->other_curanalog();
-
- for (int i = 0; i < terms_count; i++)
- rhsk_a = rhsk_a + Idr[i];
-
- for (int i = m_terms[k]->m_railstart; i < terms_count; i++)
- //rhsk = rhsk + go[i] * terms[i]->m_otherterm->net().as_analog().Q_Analog();
- rhsk_b = rhsk_b + go[i] * *other_cur_analog[i];
-
- RHS(k) = rhsk_a + rhsk_b;
- }
-}
#if TEST_PARALLEL
template <unsigned m_N, unsigned _storage_N>
@@ -587,9 +446,9 @@ void matrix_solver_direct_t<m_N, _storage_N>::LE_solve()
{
#if TEST_PARALLEL
const unsigned eb = m_terms[i]->m_nzbd.size();
- if (eb > 16)
+ if (eb > 0)
{
- printf("here %d\n", eb);
+ //printf("here %d\n", eb);
unsigned chunks = (eb) / (num_thr + 1);
for (int p=0; p < num_thr + 1; p++)
{
@@ -617,10 +476,10 @@ void matrix_solver_direct_t<m_N, _storage_N>::LE_solve()
/* Eliminate column i from row j */
- for (auto j : nzbd)
+ for (auto & j : nzbd)
{
const nl_double f1 = - A(j,i) * f;
- for (auto k : nzrd)
+ for (auto & k : nzrd)
A(j,k) += A(i,k) * f1;
//RHS(j) += RHS(i) * f1;
}
@@ -632,10 +491,10 @@ void matrix_solver_direct_t<m_N, _storage_N>::LE_solve()
/* Eliminate column i from row j */
- for (auto j : nzbd)
+ for (auto & j : nzbd)
{
const nl_double f1 = - A(j,i) * f;
- for (auto k : nzrd)
+ for (auto & k : nzrd)
A(j,k) += A(i,k) * f1;
//RHS(j) += RHS(i) * f1;
}
@@ -684,35 +543,6 @@ void matrix_solver_direct_t<m_N, _storage_N>::LE_back_subst(
template <unsigned m_N, unsigned _storage_N>
-template <typename T>
-T matrix_solver_direct_t<m_N, _storage_N>::delta(
- const T * RESTRICT V)
-{
- /* FIXME: Ideally we should also include currents (RHS) here. This would
- * need a revaluation of the right hand side after voltages have been updated
- * and thus belong into a different calculation. This applies to all solvers.
- */
-
- const unsigned iN = this->N();
- T cerr = 0;
- for (unsigned i = 0; i < iN; i++)
- cerr = std::fmax(cerr, nl_math::abs(V[i] - (T) this->m_nets[i]->m_cur_Analog));
- return cerr;
-}
-
-template <unsigned m_N, unsigned _storage_N>
-template <typename T>
-void matrix_solver_direct_t<m_N, _storage_N>::store(
- const T * RESTRICT V)
-{
- for (unsigned i = 0, iN=N(); i < iN; i++)
- {
- this->m_nets[i]->m_cur_Analog = V[i];
- }
-}
-
-
-template <unsigned m_N, unsigned _storage_N>
int matrix_solver_direct_t<m_N, _storage_N>::solve_non_dynamic(ATTR_UNUSED const bool newton_raphson)
{
nl_double new_V[_storage_N]; // = { 0.0 };
@@ -738,8 +568,8 @@ int matrix_solver_direct_t<m_N, _storage_N>::solve_non_dynamic(ATTR_UNUSED const
template <unsigned m_N, unsigned _storage_N>
inline int matrix_solver_direct_t<m_N, _storage_N>::vsolve_non_dynamic(const bool newton_raphson)
{
- this->build_LE_A();
- this->build_LE_RHS();
+ this->build_LE_A(*this);
+ this->build_LE_RHS(*this);
for (unsigned i=0, iN=N(); i < iN; i++)
m_last_RHS[i] = RHS(i);
@@ -753,15 +583,12 @@ matrix_solver_direct_t<m_N, _storage_N>::matrix_solver_direct_t(const solver_par
: matrix_solver_t(GAUSSIAN_ELIMINATION, params)
, m_dim(size)
{
- m_rails_temp = palloc_array(terms_t, N());
#if (NL_USE_DYNAMIC_ALLOCATION)
m_A = palloc_array(nl_ext_double, N() * m_pitch);
#endif
for (unsigned k = 0; k < N(); k++)
{
- m_terms[k] = palloc(terms_t);
m_last_RHS[k] = 0.0;
- m_last_V[k] = 0.0;
}
#if TEST_PARALLEL
thr_initialize();
@@ -773,15 +600,12 @@ matrix_solver_direct_t<m_N, _storage_N>::matrix_solver_direct_t(const eSolverTyp
: matrix_solver_t(type, params)
, m_dim(size)
{
- m_rails_temp = palloc_array(terms_t, N());
#if (NL_USE_DYNAMIC_ALLOCATION)
m_A = palloc_array(nl_ext_double, N() * m_pitch);
#endif
for (unsigned k = 0; k < N(); k++)
{
- m_terms[k] = palloc(terms_t);
m_last_RHS[k] = 0.0;
- m_last_V[k] = 0.0;
}
#if TEST_PARALLEL
thr_initialize();
diff --git a/src/lib/netlist/solver/nld_ms_direct1.h b/src/lib/netlist/solver/nld_ms_direct1.h
index ab19c92a4cb..abf9518bfbe 100644
--- a/src/lib/netlist/solver/nld_ms_direct1.h
+++ b/src/lib/netlist/solver/nld_ms_direct1.h
@@ -30,8 +30,8 @@ public:
inline int matrix_solver_direct1_t::vsolve_non_dynamic(ATTR_UNUSED const bool newton_raphson)
{
- this->build_LE_A();
- this->build_LE_RHS();
+ this->build_LE_A(*this);
+ this->build_LE_RHS(*this);
//NL_VERBOSE_OUT(("{1} {2}\n", new_val, m_RHS[0] / m_A[0][0]);
nl_double new_val[1] = { RHS(0) / A(0,0) };
diff --git a/src/lib/netlist/solver/nld_ms_direct2.h b/src/lib/netlist/solver/nld_ms_direct2.h
index 2488e573bf2..f71133d95f0 100644
--- a/src/lib/netlist/solver/nld_ms_direct2.h
+++ b/src/lib/netlist/solver/nld_ms_direct2.h
@@ -30,8 +30,8 @@ public:
inline int matrix_solver_direct2_t::vsolve_non_dynamic(ATTR_UNUSED const bool newton_raphson)
{
- build_LE_A();
- build_LE_RHS();
+ build_LE_A(*this);
+ build_LE_RHS(*this);
const nl_double a = A(0,0);
const nl_double b = A(0,1);
diff --git a/src/lib/netlist/solver/nld_ms_direct_lu.h b/src/lib/netlist/solver/nld_ms_direct_lu.h
index 757970e5c07..e6ccf819653 100644
--- a/src/lib/netlist/solver/nld_ms_direct_lu.h
+++ b/src/lib/netlist/solver/nld_ms_direct_lu.h
@@ -144,7 +144,6 @@ protected:
ATTR_ALIGN nl_double m_last_RHS[_storage_N]; // right hand side - contains currents
ATTR_ALIGN nl_double m_last_V[_storage_N];
- terms_t **m_terms;
terms_t *m_rails_temp;
private:
@@ -161,11 +160,6 @@ private:
template <unsigned m_N, unsigned _storage_N>
matrix_solver_direct_t<m_N, _storage_N>::~matrix_solver_direct_t()
{
- for (unsigned k = 0; k < N(); k++)
- {
- pfree(m_terms[k]);
- }
- pfree_array(m_terms);
pfree_array(m_rails_temp);
}
@@ -608,14 +602,11 @@ matrix_solver_direct_t<m_N, _storage_N>::matrix_solver_direct_t(const solver_par
, m_dim(size)
, m_lp_fact(0)
{
- m_terms = palloc_array(terms_t *, N());
m_rails_temp = palloc_array(terms_t, N());
for (unsigned k = 0; k < N(); k++)
{
- m_terms[k] = palloc(terms_t);
m_last_RHS[k] = 0.0;
- m_last_V[k] = 0.0;
}
}
@@ -625,14 +616,12 @@ matrix_solver_direct_t<m_N, _storage_N>::matrix_solver_direct_t(const eSolverTyp
, m_dim(size)
, m_lp_fact(0)
{
- m_terms = palloc_array(terms_t *, N());
m_rails_temp = palloc_array(terms_t, N());
for (unsigned k = 0; k < N(); k++)
{
m_terms[k] = palloc(terms_t);
m_last_RHS[k] = 0.0;
- m_last_V[k] = 0.0;
}
}
diff --git a/src/lib/netlist/solver/nld_ms_sm.h b/src/lib/netlist/solver/nld_ms_sm.h
index 3dd440d4b15..bff8197127c 100644
--- a/src/lib/netlist/solver/nld_ms_sm.h
+++ b/src/lib/netlist/solver/nld_ms_sm.h
@@ -48,6 +48,8 @@ NETLIB_NAMESPACE_DEVICES_START()
template <unsigned m_N, unsigned _storage_N>
class matrix_solver_sm_t: public matrix_solver_t
{
+ friend class matrix_solver_t;
+
public:
matrix_solver_sm_t(const solver_parameters_t *params, const int size);
@@ -59,26 +61,16 @@ public:
virtual void reset() override { matrix_solver_t::reset(); }
protected:
- virtual void add_term(int net_idx, terminal_t *term) override;
virtual int vsolve_non_dynamic(const bool newton_raphson) override;
int solve_non_dynamic(const bool newton_raphson);
inline unsigned N() const { if (m_N == 0) return m_dim; else return m_N; }
- void build_LE_A();
- void build_LE_RHS();
void LE_invert();
template <typename T>
void LE_compute_x(T * RESTRICT x);
- template <typename T>
- T delta(const T * RESTRICT V);
-
- template <typename T>
- void store(const T * RESTRICT V);
-
- virtual netlist_time compute_next_timestep() override;
template <typename T1, typename T2>
inline nl_ext_double &A(const T1 &r, const T2 &c) { return m_A[r][c]; }
@@ -96,10 +88,6 @@ protected:
inline nl_ext_double &lAinv(const T1 &r, const T2 &c) { return m_lAinv[r][c]; }
ATTR_ALIGN nl_double m_last_RHS[_storage_N]; // right hand side - contains currents
- ATTR_ALIGN nl_double m_last_V[_storage_N];
-
- terms_t * m_terms[_storage_N];
- terms_t *m_rails_temp;
private:
static const std::size_t m_pitch = ((( _storage_N) + 7) / 8) * 8;
@@ -124,102 +112,26 @@ private:
template <unsigned m_N, unsigned _storage_N>
matrix_solver_sm_t<m_N, _storage_N>::~matrix_solver_sm_t()
{
- for (unsigned k = 0; k < N(); k++)
- {
- pfree(m_terms[k]);
- }
- pfree_array(m_rails_temp);
#if (NL_USE_DYNAMIC_ALLOCATION)
pfree_array(m_A);
#endif
}
template <unsigned m_N, unsigned _storage_N>
-netlist_time matrix_solver_sm_t<m_N, _storage_N>::compute_next_timestep()
-{
- nl_double new_solver_timestep = m_params.m_max_timestep;
-
- if (m_params.m_dynamic)
- {
- /*
- * FIXME: We should extend the logic to use either all nets or
- * only output nets.
- */
- for (unsigned k = 0, iN=N(); k < iN; k++)
- {
- analog_net_t *n = m_nets[k];
-
- const nl_double DD_n = (n->Q_Analog() - m_last_V[k]);
- const nl_double hn = current_timestep();
-
- nl_double DD2 = (DD_n / hn - n->m_DD_n_m_1 / n->m_h_n_m_1) / (hn + n->m_h_n_m_1);
- nl_double new_net_timestep;
-
- n->m_h_n_m_1 = hn;
- n->m_DD_n_m_1 = DD_n;
- if (nl_math::abs(DD2) > NL_FCONST(1e-30)) // avoid div-by-zero
- new_net_timestep = nl_math::sqrt(m_params.m_lte / nl_math::abs(NL_FCONST(0.5)*DD2));
- else
- new_net_timestep = m_params.m_max_timestep;
-
- if (new_net_timestep < new_solver_timestep)
- new_solver_timestep = new_net_timestep;
-
- m_last_V[k] = n->Q_Analog();
- }
- if (new_solver_timestep < m_params.m_min_timestep)
- new_solver_timestep = m_params.m_min_timestep;
- }
- //if (new_solver_timestep > 10.0 * hn)
- // new_solver_timestep = 10.0 * hn;
- return netlist_time::from_double(new_solver_timestep);
-}
-
-template <unsigned m_N, unsigned _storage_N>
-ATTR_COLD void matrix_solver_sm_t<m_N, _storage_N>::add_term(int k, terminal_t *term)
-{
- if (term->m_otherterm->net().isRailNet())
- {
- m_rails_temp[k].add(term, -1, false);
- }
- else
- {
- int ot = get_net_idx(&term->m_otherterm->net());
- if (ot>=0)
- {
- m_terms[k]->add(term, ot, true);
- }
- /* Should this be allowed ? */
- else // if (ot<0)
- {
- m_rails_temp[k].add(term, ot, true);
- log().fatal("found term with missing othernet {1}\n", term->name());
- }
- }
-}
-
-
-template <unsigned m_N, unsigned _storage_N>
ATTR_COLD void matrix_solver_sm_t<m_N, _storage_N>::vsetup(analog_net_t::list_t &nets)
{
if (m_dim < nets.size())
log().fatal("Dimension {1} less than {2}", m_dim, nets.size());
- for (unsigned k = 0; k < N(); k++)
- {
- m_terms[k]->clear();
- m_rails_temp[k].clear();
- }
-
matrix_solver_t::setup_base(nets);
for (unsigned k = 0; k < N(); k++)
{
m_terms[k]->m_railstart = m_terms[k]->count();
- for (unsigned i = 0; i < m_rails_temp[k].count(); i++)
- this->m_terms[k]->add(m_rails_temp[k].terms()[i], m_rails_temp[k].net_other()[i], false);
+ for (unsigned i = 0; i < m_rails_temp[k]->count(); i++)
+ this->m_terms[k]->add(m_rails_temp[k]->terms()[i], m_rails_temp[k]->net_other()[i], false);
- m_rails_temp[k].clear(); // no longer needed
+ m_rails_temp[k]->clear(); // no longer needed
m_terms[k]->set_pointers();
}
@@ -315,13 +227,13 @@ ATTR_COLD void matrix_solver_sm_t<m_N, _storage_N>::vsetup(analog_net_t::list_t
* save states
*/
save(NLNAME(m_last_RHS));
- save(NLNAME(m_last_V));
for (unsigned k = 0; k < N(); k++)
{
pstring num = pfmt("{1}")(k);
save(RHS(k), "RHS" + num);
+ save(m_terms[k]->m_last_V, "lastV" + num);
save(m_terms[k]->go(),"GO" + num, m_terms[k]->count());
save(m_terms[k]->gt(),"GT" + num, m_terms[k]->count());
@@ -331,59 +243,6 @@ ATTR_COLD void matrix_solver_sm_t<m_N, _storage_N>::vsetup(analog_net_t::list_t
}
-template <unsigned m_N, unsigned _storage_N>
-void matrix_solver_sm_t<m_N, _storage_N>::build_LE_A()
-{
- const unsigned iN = N();
- for (unsigned k = 0; k < iN; k++)
- {
- for (unsigned i=0; i < iN; i++)
- A(k,i) = 0.0;
-
- const unsigned terms_count = m_terms[k]->count();
- const unsigned railstart = m_terms[k]->m_railstart;
- const nl_double * RESTRICT gt = m_terms[k]->gt();
-
- {
- nl_double akk = 0.0;
- for (unsigned i = 0; i < terms_count; i++)
- akk += gt[i];
-
- A(k,k) = akk;
- }
-
- const nl_double * RESTRICT go = m_terms[k]->go();
- const int * RESTRICT net_other = m_terms[k]->net_other();
-
- for (unsigned i = 0; i < railstart; i++)
- A(k,net_other[i]) -= go[i];
- }
-}
-
-template <unsigned m_N, unsigned _storage_N>
-void matrix_solver_sm_t<m_N, _storage_N>::build_LE_RHS()
-{
- const unsigned iN = N();
- for (unsigned k = 0; k < iN; k++)
- {
- nl_double rhsk_a = 0.0;
- nl_double rhsk_b = 0.0;
-
- const int terms_count = m_terms[k]->count();
- const nl_double * RESTRICT go = m_terms[k]->go();
- const nl_double * RESTRICT Idr = m_terms[k]->Idr();
- const nl_double * const * RESTRICT other_cur_analog = m_terms[k]->other_curanalog();
-
- for (int i = 0; i < terms_count; i++)
- rhsk_a = rhsk_a + Idr[i];
-
- for (int i = m_terms[k]->m_railstart; i < terms_count; i++)
- //rhsk = rhsk + go[i] * terms[i]->m_otherterm->net().as_analog().Q_Analog();
- rhsk_b = rhsk_b + go[i] * *other_cur_analog[i];
-
- RHS(k) = rhsk_a + rhsk_b;
- }
-}
template <unsigned m_N, unsigned _storage_N>
void matrix_solver_sm_t<m_N, _storage_N>::LE_invert()
@@ -469,35 +328,6 @@ void matrix_solver_sm_t<m_N, _storage_N>::LE_compute_x(
template <unsigned m_N, unsigned _storage_N>
-template <typename T>
-T matrix_solver_sm_t<m_N, _storage_N>::delta(
- const T * RESTRICT V)
-{
- /* FIXME: Ideally we should also include currents (RHS) here. This would
- * need a revaluation of the right hand side after voltages have been updated
- * and thus belong into a different calculation. This applies to all solvers.
- */
-
- const unsigned iN = this->N();
- T cerr = 0;
- for (unsigned i = 0; i < iN; i++)
- cerr = std::fmax(cerr, nl_math::abs(V[i] - (T) this->m_nets[i]->m_cur_Analog));
- return cerr;
-}
-
-template <unsigned m_N, unsigned _storage_N>
-template <typename T>
-void matrix_solver_sm_t<m_N, _storage_N>::store(
- const T * RESTRICT V)
-{
- for (unsigned i = 0, iN=N(); i < iN; i++)
- {
- this->m_nets[i]->m_cur_Analog = V[i];
- }
-}
-
-
-template <unsigned m_N, unsigned _storage_N>
int matrix_solver_sm_t<m_N, _storage_N>::solve_non_dynamic(ATTR_UNUSED const bool newton_raphson)
{
static const bool incremental = true;
@@ -590,8 +420,8 @@ int matrix_solver_sm_t<m_N, _storage_N>::solve_non_dynamic(ATTR_UNUSED const boo
template <unsigned m_N, unsigned _storage_N>
inline int matrix_solver_sm_t<m_N, _storage_N>::vsolve_non_dynamic(const bool newton_raphson)
{
- this->build_LE_A();
- this->build_LE_RHS();
+ this->build_LE_A(*this);
+ this->build_LE_RHS(*this);
for (unsigned i=0, iN=N(); i < iN; i++)
m_last_RHS[i] = RHS(i);
@@ -605,15 +435,12 @@ matrix_solver_sm_t<m_N, _storage_N>::matrix_solver_sm_t(const solver_parameters_
: matrix_solver_t(GAUSSIAN_ELIMINATION, params)
, m_dim(size)
{
- m_rails_temp = palloc_array(terms_t, N());
#if (NL_USE_DYNAMIC_ALLOCATION)
m_A = palloc_array(nl_ext_double, N() * m_pitch);
#endif
for (unsigned k = 0; k < N(); k++)
{
- m_terms[k] = palloc(terms_t);
m_last_RHS[k] = 0.0;
- m_last_V[k] = 0.0;
}
}
@@ -622,15 +449,12 @@ matrix_solver_sm_t<m_N, _storage_N>::matrix_solver_sm_t(const eSolverType type,
: matrix_solver_t(type, params)
, m_dim(size)
{
- m_rails_temp = palloc_array(terms_t, N());
#if (NL_USE_DYNAMIC_ALLOCATION)
m_A = palloc_array(nl_ext_double, N() * m_pitch);
#endif
for (unsigned k = 0; k < N(); k++)
{
- m_terms[k] = palloc(terms_t);
m_last_RHS[k] = 0.0;
- m_last_V[k] = 0.0;
}
}
diff --git a/src/lib/netlist/solver/nld_ms_sor_mat.h b/src/lib/netlist/solver/nld_ms_sor_mat.h
index a4fce8dec2a..10192717a90 100644
--- a/src/lib/netlist/solver/nld_ms_sor_mat.h
+++ b/src/lib/netlist/solver/nld_ms_sor_mat.h
@@ -128,8 +128,8 @@ int matrix_solver_SOR_mat_t<m_N, _storage_N>::vsolve_non_dynamic(const bool newt
int resched_cnt = 0;
- this->build_LE_A();
- this->build_LE_RHS();
+ this->build_LE_A(*this);
+ this->build_LE_RHS(*this);
#if 0
static int ws_cnt = 0;
diff --git a/src/lib/netlist/solver/nld_ms_w.h b/src/lib/netlist/solver/nld_ms_w.h
index 154f618a697..aa6f7104c6c 100644
--- a/src/lib/netlist/solver/nld_ms_w.h
+++ b/src/lib/netlist/solver/nld_ms_w.h
@@ -55,6 +55,7 @@ NETLIB_NAMESPACE_DEVICES_START()
template <unsigned m_N, unsigned _storage_N>
class matrix_solver_w_t: public matrix_solver_t
{
+ friend class matrix_solver_t;
public:
matrix_solver_w_t(const solver_parameters_t *params, const int size);
@@ -66,26 +67,16 @@ public:
virtual void reset() override { matrix_solver_t::reset(); }
protected:
- virtual void add_term(int net_idx, terminal_t *term) override;
virtual int vsolve_non_dynamic(const bool newton_raphson) override;
int solve_non_dynamic(const bool newton_raphson);
inline unsigned N() const { if (m_N == 0) return m_dim; else return m_N; }
- void build_LE_A();
- void build_LE_RHS();
void LE_invert();
template <typename T>
void LE_compute_x(T * RESTRICT x);
- template <typename T>
- T delta(const T * RESTRICT V);
-
- template <typename T>
- void store(const T * RESTRICT V);
-
- virtual netlist_time compute_next_timestep() override;
template <typename T1, typename T2>
inline nl_ext_double &A(const T1 &r, const T2 &c) { return m_A[r][c]; }
@@ -103,10 +94,6 @@ protected:
inline nl_ext_double &lA(const T1 &r, const T2 &c) { return m_lA[r][c]; }
ATTR_ALIGN nl_double m_last_RHS[_storage_N]; // right hand side - contains currents
- ATTR_ALIGN nl_double m_last_V[_storage_N];
-
- terms_t * m_terms[_storage_N];
- terms_t *m_rails_temp;
private:
static const std::size_t m_pitch = ((( _storage_N) + 7) / 8) * 8;
@@ -138,102 +125,26 @@ private:
template <unsigned m_N, unsigned _storage_N>
matrix_solver_w_t<m_N, _storage_N>::~matrix_solver_w_t()
{
- for (unsigned k = 0; k < N(); k++)
- {
- pfree(m_terms[k]);
- }
- pfree_array(m_rails_temp);
#if (NL_USE_DYNAMIC_ALLOCATION)
pfree_array(m_A);
#endif
}
template <unsigned m_N, unsigned _storage_N>
-netlist_time matrix_solver_w_t<m_N, _storage_N>::compute_next_timestep()
-{
- nl_double new_solver_timestep = m_params.m_max_timestep;
-
- if (m_params.m_dynamic)
- {
- /*
- * FIXME: We should extend the logic to use either all nets or
- * only output nets.
- */
- for (unsigned k = 0, iN=N(); k < iN; k++)
- {
- analog_net_t *n = m_nets[k];
-
- const nl_double DD_n = (n->Q_Analog() - m_last_V[k]);
- const nl_double hn = current_timestep();
-
- nl_double DD2 = (DD_n / hn - n->m_DD_n_m_1 / n->m_h_n_m_1) / (hn + n->m_h_n_m_1);
- nl_double new_net_timestep;
-
- n->m_h_n_m_1 = hn;
- n->m_DD_n_m_1 = DD_n;
- if (nl_math::abs(DD2) > NL_FCONST(1e-30)) // avoid div-by-zero
- new_net_timestep = nl_math::sqrt(m_params.m_lte / nl_math::abs(NL_FCONST(0.5)*DD2));
- else
- new_net_timestep = m_params.m_max_timestep;
-
- if (new_net_timestep < new_solver_timestep)
- new_solver_timestep = new_net_timestep;
-
- m_last_V[k] = n->Q_Analog();
- }
- if (new_solver_timestep < m_params.m_min_timestep)
- new_solver_timestep = m_params.m_min_timestep;
- }
- //if (new_solver_timestep > 10.0 * hn)
- // new_solver_timestep = 10.0 * hn;
- return netlist_time::from_double(new_solver_timestep);
-}
-
-template <unsigned m_N, unsigned _storage_N>
-ATTR_COLD void matrix_solver_w_t<m_N, _storage_N>::add_term(int k, terminal_t *term)
-{
- if (term->m_otherterm->net().isRailNet())
- {
- m_rails_temp[k].add(term, -1, false);
- }
- else
- {
- int ot = get_net_idx(&term->m_otherterm->net());
- if (ot>=0)
- {
- m_terms[k]->add(term, ot, true);
- }
- /* Should this be allowed ? */
- else // if (ot<0)
- {
- m_rails_temp[k].add(term, ot, true);
- log().fatal("found term with missing othernet {1}\n", term->name());
- }
- }
-}
-
-
-template <unsigned m_N, unsigned _storage_N>
ATTR_COLD void matrix_solver_w_t<m_N, _storage_N>::vsetup(analog_net_t::list_t &nets)
{
if (m_dim < nets.size())
log().fatal("Dimension {1} less than {2}", m_dim, nets.size());
- for (unsigned k = 0; k < N(); k++)
- {
- m_terms[k]->clear();
- m_rails_temp[k].clear();
- }
-
matrix_solver_t::setup_base(nets);
for (unsigned k = 0; k < N(); k++)
{
m_terms[k]->m_railstart = m_terms[k]->count();
- for (unsigned i = 0; i < m_rails_temp[k].count(); i++)
- this->m_terms[k]->add(m_rails_temp[k].terms()[i], m_rails_temp[k].net_other()[i], false);
+ for (unsigned i = 0; i < m_rails_temp[k]->count(); i++)
+ this->m_terms[k]->add(m_rails_temp[k]->terms()[i], m_rails_temp[k]->net_other()[i], false);
- m_rails_temp[k].clear(); // no longer needed
+ m_rails_temp[k]->clear(); // no longer needed
m_terms[k]->set_pointers();
}
@@ -329,13 +240,13 @@ ATTR_COLD void matrix_solver_w_t<m_N, _storage_N>::vsetup(analog_net_t::list_t &
* save states
*/
save(NLNAME(m_last_RHS));
- save(NLNAME(m_last_V));
for (unsigned k = 0; k < N(); k++)
{
pstring num = pfmt("{1}")(k);
save(RHS(k), "RHS" + num);
+ save(m_terms[k]->m_last_V, "lastV" + num);
save(m_terms[k]->go(),"GO" + num, m_terms[k]->count());
save(m_terms[k]->gt(),"GT" + num, m_terms[k]->count());
@@ -345,59 +256,6 @@ ATTR_COLD void matrix_solver_w_t<m_N, _storage_N>::vsetup(analog_net_t::list_t &
}
-template <unsigned m_N, unsigned _storage_N>
-void matrix_solver_w_t<m_N, _storage_N>::build_LE_A()
-{
- const unsigned iN = N();
- for (unsigned k = 0; k < iN; k++)
- {
- for (unsigned i=0; i < iN; i++)
- A(k,i) = 0.0;
-
- const unsigned terms_count = m_terms[k]->count();
- const unsigned railstart = m_terms[k]->m_railstart;
- const nl_double * RESTRICT gt = m_terms[k]->gt();
-
- {
- nl_double akk = 0.0;
- for (unsigned i = 0; i < terms_count; i++)
- akk += gt[i];
-
- A(k,k) = akk;
- }
-
- const nl_double * RESTRICT go = m_terms[k]->go();
- const int * RESTRICT net_other = m_terms[k]->net_other();
-
- for (unsigned i = 0; i < railstart; i++)
- A(k,net_other[i]) -= go[i];
- }
-}
-
-template <unsigned m_N, unsigned _storage_N>
-void matrix_solver_w_t<m_N, _storage_N>::build_LE_RHS()
-{
- const unsigned iN = N();
- for (unsigned k = 0; k < iN; k++)
- {
- nl_double rhsk_a = 0.0;
- nl_double rhsk_b = 0.0;
-
- const int terms_count = m_terms[k]->count();
- const nl_double * RESTRICT go = m_terms[k]->go();
- const nl_double * RESTRICT Idr = m_terms[k]->Idr();
- const nl_double * const * RESTRICT other_cur_analog = m_terms[k]->other_curanalog();
-
- for (int i = 0; i < terms_count; i++)
- rhsk_a = rhsk_a + Idr[i];
-
- for (int i = m_terms[k]->m_railstart; i < terms_count; i++)
- //rhsk = rhsk + go[i] * terms[i]->m_otherterm->net().as_analog().Q_Analog();
- rhsk_b = rhsk_b + go[i] * *other_cur_analog[i];
-
- RHS(k) = rhsk_a + rhsk_b;
- }
-}
template <unsigned m_N, unsigned _storage_N>
void matrix_solver_w_t<m_N, _storage_N>::LE_invert()
@@ -482,34 +340,6 @@ void matrix_solver_w_t<m_N, _storage_N>::LE_compute_x(
template <unsigned m_N, unsigned _storage_N>
-template <typename T>
-T matrix_solver_w_t<m_N, _storage_N>::delta(
- const T * RESTRICT V)
-{
- /* FIXME: Ideally we should also include currents (RHS) here. This would
- * need a revaluation of the right hand side after voltages have been updated
- * and thus belong into a different calculation. This applies to all solvers.
- */
-
- const unsigned iN = this->N();
- T cerr = 0;
- for (unsigned i = 0; i < iN; i++)
- cerr = std::fmax(cerr, nl_math::abs(V[i] - (T) this->m_nets[i]->m_cur_Analog));
- return cerr;
-}
-
-template <unsigned m_N, unsigned _storage_N>
-template <typename T>
-void matrix_solver_w_t<m_N, _storage_N>::store(
- const T * RESTRICT V)
-{
- for (unsigned i = 0, iN=N(); i < iN; i++)
- {
- this->m_nets[i]->m_cur_Analog = V[i];
- }
-}
-
-template <unsigned m_N, unsigned _storage_N>
int matrix_solver_w_t<m_N, _storage_N>::solve_non_dynamic(ATTR_UNUSED const bool newton_raphson)
{
const auto iN = N();
@@ -652,8 +482,8 @@ int matrix_solver_w_t<m_N, _storage_N>::solve_non_dynamic(ATTR_UNUSED const bool
template <unsigned m_N, unsigned _storage_N>
inline int matrix_solver_w_t<m_N, _storage_N>::vsolve_non_dynamic(const bool newton_raphson)
{
- this->build_LE_A();
- this->build_LE_RHS();
+ this->build_LE_A(*this);
+ this->build_LE_RHS(*this);
for (unsigned i=0, iN=N(); i < iN; i++)
m_last_RHS[i] = RHS(i);
@@ -668,15 +498,12 @@ matrix_solver_w_t<m_N, _storage_N>::matrix_solver_w_t(const solver_parameters_t
,m_cnt(0)
, m_dim(size)
{
- m_rails_temp = palloc_array(terms_t, N());
#if (NL_USE_DYNAMIC_ALLOCATION)
m_A = palloc_array(nl_ext_double, N() * m_pitch);
#endif
for (unsigned k = 0; k < N(); k++)
{
- m_terms[k] = palloc(terms_t);
m_last_RHS[k] = 0.0;
- m_last_V[k] = 0.0;
}
}
@@ -686,12 +513,9 @@ matrix_solver_w_t<m_N, _storage_N>::matrix_solver_w_t(const eSolverType type, co
,m_cnt(0)
, m_dim(size)
{
- m_rails_temp = palloc_array(terms_t, N());
for (unsigned k = 0; k < N(); k++)
{
- m_terms[k] = palloc(terms_t);
m_last_RHS[k] = 0.0;
- m_last_V[k] = 0.0;
}
}
diff --git a/src/lib/netlist/solver/nld_solver.cpp b/src/lib/netlist/solver/nld_solver.cpp
index ed011ff254d..5dd0af53313 100644
--- a/src/lib/netlist/solver/nld_solver.cpp
+++ b/src/lib/netlist/solver/nld_solver.cpp
@@ -108,6 +108,11 @@ ATTR_COLD matrix_solver_t::matrix_solver_t(const eSolverType type, const solver_
ATTR_COLD matrix_solver_t::~matrix_solver_t()
{
m_inps.clear_and_free();
+ for (unsigned k = 0; k < m_terms.size(); k++)
+ {
+ pfree(m_terms[k]);
+ }
+
}
ATTR_COLD void matrix_solver_t::setup_base(analog_net_t::list_t &nets)
@@ -115,9 +120,14 @@ ATTR_COLD void matrix_solver_t::setup_base(analog_net_t::list_t &nets)
log().debug("New solver setup\n");
m_nets.clear();
+ m_terms.clear();
for (auto & net : nets)
+ {
m_nets.push_back(net);
+ m_terms.push_back(palloc(terms_t));
+ m_rails_temp.push_back(palloc(terms_t));
+ }
for (std::size_t k = 0; k < nets.size(); k++)
{
@@ -168,6 +178,9 @@ ATTR_COLD void matrix_solver_t::setup_base(analog_net_t::list_t &nets)
if (net_proxy_output == NULL)
{
+ //net_proxy_output = palloc(analog_output_t(*this,
+ // this->name() + "." + pfmt("m{1}")(m_inps.size())));
+
net_proxy_output = palloc(analog_output_t);
net_proxy_output->init_object(*this, this->name() + "." + pfmt("m{1}")(m_inps.size()));
m_inps.push_back(net_proxy_output);
@@ -308,6 +321,70 @@ ATTR_COLD int matrix_solver_t::get_net_idx(net_t *net)
return -1;
}
+ATTR_COLD void matrix_solver_t::add_term(int k, terminal_t *term)
+{
+ if (term->m_otherterm->net().isRailNet())
+ {
+ m_rails_temp[k]->add(term, -1, false);
+ }
+ else
+ {
+ int ot = get_net_idx(&term->m_otherterm->net());
+ if (ot>=0)
+ {
+ m_terms[k]->add(term, ot, true);
+ }
+ /* Should this be allowed ? */
+ else // if (ot<0)
+ {
+ m_rails_temp[k]->add(term, ot, true);
+ log().fatal("found term with missing othernet {1}\n", term->name());
+ }
+ }
+}
+
+netlist_time matrix_solver_t::compute_next_timestep()
+{
+ nl_double new_solver_timestep = m_params.m_max_timestep;
+
+ if (m_params.m_dynamic)
+ {
+ /*
+ * FIXME: We should extend the logic to use either all nets or
+ * only output nets.
+ */
+ for (unsigned k = 0, iN=m_terms.size(); k < iN; k++)
+ {
+ analog_net_t *n = m_nets[k];
+
+ const nl_double DD_n = (n->Q_Analog() - m_terms[k]->m_last_V);
+ const nl_double hn = current_timestep();
+
+ nl_double DD2 = (DD_n / hn - n->m_DD_n_m_1 / n->m_h_n_m_1) / (hn + n->m_h_n_m_1);
+ nl_double new_net_timestep;
+
+ n->m_h_n_m_1 = hn;
+ n->m_DD_n_m_1 = DD_n;
+ if (nl_math::abs(DD2) > NL_FCONST(1e-30)) // avoid div-by-zero
+ new_net_timestep = nl_math::sqrt(m_params.m_lte / nl_math::abs(NL_FCONST(0.5)*DD2));
+ else
+ new_net_timestep = m_params.m_max_timestep;
+
+ if (new_net_timestep < new_solver_timestep)
+ new_solver_timestep = new_net_timestep;
+
+ m_terms[k]->m_last_V = n->Q_Analog();
+ }
+ if (new_solver_timestep < m_params.m_min_timestep)
+ new_solver_timestep = m_params.m_min_timestep;
+ }
+ //if (new_solver_timestep > 10.0 * hn)
+ // new_solver_timestep = 10.0 * hn;
+ return netlist_time::from_double(new_solver_timestep);
+}
+
+
+
void matrix_solver_t::log_stats()
{
if (this->m_stat_calculations != 0 && this->m_stat_vsolver_calls && this->m_params.m_log_stats)
diff --git a/src/lib/util/chdcodec.cpp b/src/lib/util/chdcodec.cpp
index be1d2022cd7..ba1840489d6 100644
--- a/src/lib/util/chdcodec.cpp
+++ b/src/lib/util/chdcodec.cpp
@@ -1128,20 +1128,35 @@ chd_lzma_decompressor::chd_lzma_decompressor(chd_file &chd, UINT32 hunkbytes, bo
// construct the decoder
LzmaDec_Construct(&m_decoder);
+ // FIXME: this code is written in a way that makes it impossible to safely upgrade the LZMA SDK
+ // This code assumes that the current version of the encoder imposes the same requirements on the
+ // decoder as the encoder used to produce the file. This is not necessarily true. The format
+ // needs to be changed so the encoder properties are written to the file.
+
// configure the properties like the compressor did
CLzmaEncProps encoder_props;
chd_lzma_compressor::configure_properties(encoder_props, hunkbytes);
// convert to decoder properties
- CLzmaProps decoder_props;
- decoder_props.lc = encoder_props.lc;
- decoder_props.lp = encoder_props.lp;
- decoder_props.pb = encoder_props.pb;
- decoder_props.dicSize = encoder_props.dictSize;
+ CLzmaEncHandle enc = LzmaEnc_Create(&m_allocator);
+ if (!enc)
+ throw CHDERR_DECOMPRESSION_ERROR;
+ if (LzmaEnc_SetProps(enc, &encoder_props) != SZ_OK)
+ {
+ LzmaEnc_Destroy(enc, &m_allocator, &m_allocator);
+ throw CHDERR_DECOMPRESSION_ERROR;
+ }
+ Byte decoder_props[LZMA_PROPS_SIZE];
+ SizeT props_size = sizeof(decoder_props);
+ if (LzmaEnc_WriteProperties(enc, decoder_props, &props_size) != SZ_OK)
+ {
+ LzmaEnc_Destroy(enc, &m_allocator, &m_allocator);
+ throw CHDERR_DECOMPRESSION_ERROR;
+ }
+ LzmaEnc_Destroy(enc, &m_allocator, &m_allocator);
// do memory allocations
- SRes res = LzmaDec_Allocate_MAME(&m_decoder, &decoder_props, &m_allocator);
- if (res != SZ_OK)
+ if (LzmaDec_Allocate(&m_decoder, decoder_props, LZMA_PROPS_SIZE, &m_allocator) != SZ_OK)
throw CHDERR_DECOMPRESSION_ERROR;
}
diff --git a/src/lib/util/un7z.cpp b/src/lib/util/un7z.cpp
index 5822479c4f0..a2fbf380d35 100644
--- a/src/lib/util/un7z.cpp
+++ b/src/lib/util/un7z.cpp
@@ -404,25 +404,24 @@ int m7z_file_impl::search(
bool matchname,
bool partialpath)
{
- for ( ; i < m_db.db.NumFiles; i++)
+ for ( ; i < m_db.NumFiles; i++)
{
- const CSzFileItem &f(m_db.db.Files[i]);
-
make_utf8_name(i);
- const std::uint64_t size(f.Size);
- const std::uint32_t crc(f.Crc);
- const bool crcmatch(crc == search_crc);
+ bool const is_dir(SzArEx_IsDir(&m_db, i));
+ const std::uint64_t size(SzArEx_GetFileSize(&m_db, i));
+ const std::uint32_t crc(m_db.CRCs.Vals[i]);
+ const bool crcmatch(SzBitArray_Check(m_db.CRCs.Defs, i) && (crc == search_crc));
auto const partialoffset(m_utf8_buf.size() - 1 - search_filename.length());
bool const partialpossible((m_utf8_buf.size() > (search_filename.length() + 1)) && (m_utf8_buf[partialoffset - 1] == '/'));
const bool namematch(
!core_stricmp(search_filename.c_str(), &m_utf8_buf[0]) ||
(partialpath && partialpossible && !core_stricmp(search_filename.c_str(), &m_utf8_buf[partialoffset])));
- const bool found = ((!matchcrc && !matchname) || !f.IsDir) && (!matchcrc || crcmatch) && (!matchname || namematch);
+ const bool found = ((!matchcrc && !matchname) || !is_dir) && (!matchcrc || crcmatch) && (!matchname || namematch);
if (found)
{
m_curr_file_idx = i;
- m_curr_is_dir = bool(f.IsDir);
+ m_curr_is_dir = is_dir;
m_curr_name = &m_utf8_buf[0];
m_curr_length = size;
m_curr_crc = crc;
diff --git a/src/lib/util/unzip.cpp b/src/lib/util/unzip.cpp
index 7e92650aaa1..ad51400d9d1 100644
--- a/src/lib/util/unzip.cpp
+++ b/src/lib/util/unzip.cpp
@@ -11,9 +11,9 @@
#include "unzip.h"
#include "corestr.h"
+#include "hashing.h"
#include "osdcore.h"
-
#include <algorithm>
#include <array>
#include <cassert>
@@ -25,6 +25,8 @@
#include <zlib.h>
+#include "lzma/C/LzmaDec.h"
+
namespace util {
namespace {
@@ -46,10 +48,8 @@ public:
, m_cd_pos(0)
, m_header()
, m_curr_is_dir(false)
- , m_curr_name()
, m_buffer()
{
- std::memset(&m_header, 0, sizeof(m_header));
std::fill(m_buffer.begin(), m_buffer.end(), 0);
}
@@ -63,6 +63,7 @@ public:
{
ptr result;
std::swap(s_cache[cachenum], result);
+ osd_printf_verbose("unzip: found %s in cache\n", filename.c_str());
return result;
}
}
@@ -84,23 +85,51 @@ public:
return ziperr;
// verify that we can work with this zipfile (no disk spanning allowed)
- if ((m_ecd.disk_number != m_ecd.cd_start_disk_number) ||
- (m_ecd.cd_disk_entries != m_ecd.cd_total_entries) ||
- (std::size_t(m_ecd.cd_size) != m_ecd.cd_size))
+ if (m_ecd.disk_number != m_ecd.cd_start_disk_number)
+ {
+ osd_printf_error("unzip: %s central directory starts in another segment\n", m_filename.c_str());
+ return archive_file::error::UNSUPPORTED;
+ }
+ if (m_ecd.cd_disk_entries != m_ecd.cd_total_entries)
+ {
+ osd_printf_error("unzip: %s not all central directory entries reside in this segment\n", m_filename.c_str());
return archive_file::error::UNSUPPORTED;
+ }
+ if (std::size_t(m_ecd.cd_size) != m_ecd.cd_size)
+ {
+ osd_printf_error("unzip: %s central directory too large to load\n", m_filename.c_str());
+ return archive_file::error::UNSUPPORTED;
+ }
// allocate memory for the central directory
try { m_cd.resize(std::size_t(m_ecd.cd_size)); }
- catch (...) { return archive_file::error::OUT_OF_MEMORY; }
+ catch (...)
+ {
+ osd_printf_error("unzip: %s failed to allocate memory for central directory\n", m_filename.c_str());
+ return archive_file::error::OUT_OF_MEMORY;
+ }
// read the central directory
- // FIXME: central directory can theoretically be bigger than maximum 32-bit integer value, should use a loop
- std::uint32_t read_length;
- auto const filerr = m_file->read(&m_cd[0], m_ecd.cd_start_disk_offset, m_ecd.cd_size, read_length);
- if (filerr != osd_file::error::NONE)
- return archive_file::error::FILE_ERROR;
- if (read_length != m_ecd.cd_size)
- return archive_file::error::FILE_TRUNCATED;
+ auto cd_remaining(m_ecd.cd_size);
+ std::size_t cd_offs(0);
+ while (cd_remaining)
+ {
+ std::uint32_t const chunk(std::uint32_t((std::min<std::uint64_t>)(std::numeric_limits<std::uint32_t>::max(), cd_remaining)));
+ std::uint32_t read_length(0);
+ auto const filerr = m_file->read(&m_cd[cd_offs], m_ecd.cd_start_disk_offset + cd_offs, chunk, read_length);
+ if (filerr != osd_file::error::NONE)
+ {
+ osd_printf_error("unzip: %s error reading central directory (%d)\n", m_filename.c_str(), int(filerr));
+ return archive_file::error::FILE_ERROR;
+ }
+ if (!read_length)
+ {
+ osd_printf_error("unzip: %s unexpectedly reached end-of-file while reading central directory\n", m_filename.c_str());
+ return archive_file::error::FILE_TRUNCATED;
+ }
+ cd_remaining -= read_length;
+ cd_offs += read_length;
+ }
return archive_file::error::NONE;
}
@@ -132,7 +161,7 @@ public:
}
bool current_is_directory() const { return m_curr_is_dir; }
- const std::string &current_name() const { return m_curr_name; }
+ const std::string &current_name() const { return m_header.file_name; }
std::uint64_t current_uncompressed_length() const { return m_header.uncompressed_length; }
std::uint32_t current_crc() const { return m_header.crc; }
@@ -152,7 +181,15 @@ private:
{
auto const filerr = osd_file::open(m_filename, OPEN_FLAG_READ, m_file, m_length);
if (filerr != osd_file::error::NONE)
+ {
+ // this would spam every time it looks for a non-existent archive, which is a lot
+ //osd_printf_error("unzip: error reopening archive file %s (%d)\n", m_filename.c_str(), int(filerr));
return archive_file::error::FILE_ERROR;
+ }
+ else
+ {
+ osd_printf_verbose("unzip: opened archive file %s\n", m_filename.c_str());
+ }
}
return archive_file::error::NONE;
}
@@ -164,6 +201,7 @@ private:
// decompression interfaces
archive_file::error decompress_data_type_0(std::uint64_t offset, void *buffer, std::uint32_t length);
archive_file::error decompress_data_type_8(std::uint64_t offset, void *buffer, std::uint32_t length);
+ archive_file::error decompress_data_type_14(std::uint64_t offset, void *buffer, std::uint32_t length);
struct file_header
{
@@ -176,6 +214,7 @@ private:
std::uint64_t uncompressed_length; // uncompressed size
std::uint32_t start_disk_number; // disk number start
std::uint64_t local_header_offset; // relative offset of local header
+ std::string file_name; // file name
};
// contains extracted end of central directory information
@@ -204,7 +243,6 @@ private:
std::uint32_t m_cd_pos; // position in central directory
file_header m_header; // current file header
bool m_curr_is_dir; // current file is directory
- std::string m_curr_name; // current file name
std::array<std::uint8_t, DECOMPRESS_BUFSIZE> m_buffer; // buffer for decompression
};
@@ -283,6 +321,10 @@ protected:
{
return std::string(reinterpret_cast<char const *>(m_buffer + offs), len);
}
+ void read_string(std::string &result, std::size_t offs, std::string::size_type len) const
+ {
+ result.assign(reinterpret_cast<char const *>(m_buffer + offs), len);
+ }
std::uint8_t const *m_buffer;
};
@@ -308,52 +350,28 @@ private:
};
-class zip64_ext_info_reader : private reader_base
-{
-public:
- zip64_ext_info_reader(void const *buf) : reader_base(buf) { }
-
- std::uint64_t uncompressed_size() const { return read_qword(0x00); }
- std::uint64_t compressed_size() const { return read_qword(0x08); }
- std::uint64_t header_offset() const { return read_qword(0x10); }
- std::uint32_t start_disk() const { return read_dword(0x18); }
-
- std::size_t total_length() const { return minimum_length(); }
- static std::size_t minimum_length() { return 0x1c; }
-};
-
-
class local_file_header_reader : private reader_base
{
public:
local_file_header_reader(void const *buf) : reader_base(buf) { }
- std::uint32_t signature() const { return read_dword(0x00); }
- std::uint8_t version_needed() const { return m_buffer[0x04]; }
- std::uint8_t os_needed() const { return m_buffer[0x05]; }
- std::uint16_t general_flag() const { return read_word(0x06); }
- std::uint16_t compression_method() const { return read_word(0x08); }
- std::uint16_t modified_time() const { return read_word(0x0a); }
- std::uint16_t modified_date() const { return read_word(0x0c); }
- std::uint32_t crc32() const { return read_dword(0x0e); }
- std::uint32_t compressed_size() const { return read_dword(0x12); }
- std::uint32_t uncompressed_size() const { return read_dword(0x16); }
- std::uint16_t file_name_length() const { return read_word(0x1a); }
- std::uint16_t extra_field_length() const { return read_word(0x1c); }
- std::string file_name() const { return read_string(0x1e, file_name_length()); }
- extra_field_reader extra_field() const { return extra_field_reader(m_buffer + 0x1e + file_name_length(), extra_field_length()); }
-
- bool signature_correct() const { return signature() == 0x04034b50; }
-
- bool encrypted() const { return bool(general_flag() & 0x0001); }
- bool implode_8k_dict() const { return bool(general_flag() & 0x0002); }
- bool implode_3_trees() const { return bool(general_flag() & 0x0004); }
- unsigned deflate_option() const { return unsigned((general_flag() >> 1) & 0x0003); }
- bool use_descriptor() const { return bool(general_flag() & 0x0008); }
- bool patch_data() const { return bool(general_flag() & 0x0020); }
- bool strong_encryption() const { return bool(general_flag() & 0x0040); }
- bool utf8_encoding() const { return bool(general_flag() & 0x0800); }
- bool directory_encryption() const { return bool(general_flag() & 0x2000); }
+ std::uint32_t signature() const { return read_dword(0x00); }
+ std::uint8_t version_needed() const { return m_buffer[0x04]; }
+ std::uint8_t os_needed() const { return m_buffer[0x05]; }
+ std::uint16_t general_flag() const { return read_word(0x06); }
+ std::uint16_t compression_method() const { return read_word(0x08); }
+ std::uint16_t modified_time() const { return read_word(0x0a); }
+ std::uint16_t modified_date() const { return read_word(0x0c); }
+ std::uint32_t crc32() const { return read_dword(0x0e); }
+ std::uint32_t compressed_size() const { return read_dword(0x12); }
+ std::uint32_t uncompressed_size() const { return read_dword(0x16); }
+ std::uint16_t file_name_length() const { return read_word(0x1a); }
+ std::uint16_t extra_field_length() const { return read_word(0x1c); }
+ std::string file_name() const { return read_string(0x1e, file_name_length()); }
+ void file_name(std::string &result) const { read_string(result, 0x1e, file_name_length()); }
+ extra_field_reader extra_field() const { return extra_field_reader(m_buffer + 0x1e + file_name_length(), extra_field_length()); }
+
+ bool signature_correct() const { return signature() == 0x04034b50; }
std::size_t total_length() const { return minimum_length() + file_name_length() + extra_field_length(); }
static std::size_t minimum_length() { return 0x1e; }
@@ -365,40 +383,32 @@ class central_dir_entry_reader : private reader_base
public:
central_dir_entry_reader(void const *buf) : reader_base(buf) { }
- std::uint32_t signature() const { return read_dword(0x00); }
- std::uint8_t version_created() const { return m_buffer[0x04]; }
- std::uint8_t os_created() const { return m_buffer[0x05]; }
- std::uint8_t version_needed() const { return m_buffer[0x06]; }
- std::uint8_t os_needed() const { return m_buffer[0x07]; }
- std::uint16_t general_flag() const { return read_word(0x08); }
- std::uint16_t compression_method() const { return read_word(0x0a); }
- std::uint16_t modified_time() const { return read_word(0x0c); }
- std::uint16_t modified_date() const { return read_word(0x0e); }
- std::uint32_t crc32() const { return read_dword(0x10); }
- std::uint32_t compressed_size() const { return read_dword(0x14); }
- std::uint32_t uncompressed_size() const { return read_dword(0x18); }
- std::uint16_t file_name_length() const { return read_word(0x1c); }
- std::uint16_t extra_field_length() const { return read_word(0x1e); }
- std::uint16_t file_comment_length() const { return read_word(0x20); }
- std::uint16_t start_disk() const { return read_word(0x22); }
- std::uint16_t int_file_attr() const { return read_word(0x24); }
- std::uint32_t ext_file_attr() const { return read_dword(0x26); }
- std::uint32_t header_offset() const { return read_dword(0x2a); }
- std::string file_name() const { return read_string(0x2e, file_name_length()); }
- extra_field_reader extra_field() const { return extra_field_reader(m_buffer + 0x2e + file_name_length(), extra_field_length()); }
- std::string file_comment() const { return read_string(0x2e + file_name_length() + extra_field_length(), file_comment_length()); }
-
- bool signature_correct() const { return signature() == 0x02014b50; }
-
- bool encrypted() const { return bool(general_flag() & 0x0001); }
- bool implode_8k_dict() const { return bool(general_flag() & 0x0002); }
- bool implode_3_trees() const { return bool(general_flag() & 0x0004); }
- unsigned deflate_option() const { return unsigned((general_flag() >> 1) & 0x0003); }
- bool use_descriptor() const { return bool(general_flag() & 0x0008); }
- bool patch_data() const { return bool(general_flag() & 0x0020); }
- bool strong_encryption() const { return bool(general_flag() & 0x0040); }
- bool utf8_encoding() const { return bool(general_flag() & 0x0800); }
- bool directory_encryption() const { return bool(general_flag() & 0x2000); }
+ std::uint32_t signature() const { return read_dword(0x00); }
+ std::uint8_t version_created() const { return m_buffer[0x04]; }
+ std::uint8_t os_created() const { return m_buffer[0x05]; }
+ std::uint8_t version_needed() const { return m_buffer[0x06]; }
+ std::uint8_t os_needed() const { return m_buffer[0x07]; }
+ std::uint16_t general_flag() const { return read_word(0x08); }
+ std::uint16_t compression_method() const { return read_word(0x0a); }
+ std::uint16_t modified_time() const { return read_word(0x0c); }
+ std::uint16_t modified_date() const { return read_word(0x0e); }
+ std::uint32_t crc32() const { return read_dword(0x10); }
+ std::uint32_t compressed_size() const { return read_dword(0x14); }
+ std::uint32_t uncompressed_size() const { return read_dword(0x18); }
+ std::uint16_t file_name_length() const { return read_word(0x1c); }
+ std::uint16_t extra_field_length() const { return read_word(0x1e); }
+ std::uint16_t file_comment_length() const { return read_word(0x20); }
+ std::uint16_t start_disk() const { return read_word(0x22); }
+ std::uint16_t int_file_attr() const { return read_word(0x24); }
+ std::uint32_t ext_file_attr() const { return read_dword(0x26); }
+ std::uint32_t header_offset() const { return read_dword(0x2a); }
+ std::string file_name() const { return read_string(0x2e, file_name_length()); }
+ void file_name(std::string &result) const { read_string(result, 0x2e, file_name_length()); }
+ extra_field_reader extra_field() const { return extra_field_reader(m_buffer + 0x2e + file_name_length(), extra_field_length()); }
+ std::string file_comment() const { return read_string(0x2e + file_name_length() + extra_field_length(), file_comment_length()); }
+ void file_comment(std::string &result) const { read_string(result, 0x2e + file_name_length() + extra_field_length(), file_comment_length()); }
+
+ bool signature_correct() const { return signature() == 0x02014b50; }
std::size_t total_length() const { return minimum_length() + file_name_length() + extra_field_length() + file_comment_length(); }
static std::size_t minimum_length() { return 0x2e; }
@@ -453,23 +463,103 @@ class ecd_reader : private reader_base
public:
ecd_reader(void const *buf) : reader_base(buf) { }
- std::uint32_t signature() const { return read_dword(0x00); }
- std::uint16_t this_disk_no() const { return read_word(0x04); }
- std::uint16_t dir_start_disk() const { return read_word(0x06); }
- std::uint16_t dir_disk_entries() const { return read_word(0x08); }
- std::uint16_t dir_total_entries() const { return read_word(0x0a); }
- std::uint32_t dir_size() const { return read_dword(0x0c); }
- std::uint32_t dir_offset() const { return read_dword(0x10); }
- std::uint16_t comment_length() const { return read_word(0x14); }
- std::string comment() const { return read_string(0x16, comment_length()); }
+ std::uint32_t signature() const { return read_dword(0x00); }
+ std::uint16_t this_disk_no() const { return read_word(0x04); }
+ std::uint16_t dir_start_disk() const { return read_word(0x06); }
+ std::uint16_t dir_disk_entries() const { return read_word(0x08); }
+ std::uint16_t dir_total_entries() const { return read_word(0x0a); }
+ std::uint32_t dir_size() const { return read_dword(0x0c); }
+ std::uint32_t dir_offset() const { return read_dword(0x10); }
+ std::uint16_t comment_length() const { return read_word(0x14); }
+ std::string comment() const { return read_string(0x16, comment_length()); }
+ void comment(std::string &result) const { read_string(result, 0x16, comment_length()); }
- bool signature_correct() const { return signature() == 0x06054b50; }
+ bool signature_correct() const { return signature() == 0x06054b50; }
std::size_t total_length() const { return minimum_length() + comment_length(); }
static std::size_t minimum_length() { return 0x16; }
};
+class zip64_ext_info_reader : private reader_base
+{
+public:
+ template <typename T>
+ zip64_ext_info_reader(
+ T const &header,
+ extra_field_reader const &field)
+ : reader_base(field.data())
+ , m_uncompressed_size(header.uncompressed_size())
+ , m_compressed_size(header.compressed_size())
+ , m_header_offset(header.header_offset())
+ , m_start_disk(header.start_disk())
+ , m_offs_compressed_size(~m_uncompressed_size ? 0 : 8)
+ , m_offs_header_offset(m_offs_compressed_size + (~m_compressed_size ? 0 : 8))
+ , m_offs_start_disk(m_offs_header_offset + (~m_header_offset ? 0 : 8))
+ , m_offs_end(m_offs_start_disk + (~m_start_disk ? 0 : 4))
+ {
+ }
+
+ std::uint64_t uncompressed_size() const { return ~m_uncompressed_size ? m_uncompressed_size : read_qword(0x00); }
+ std::uint64_t compressed_size() const { return ~m_compressed_size ? m_compressed_size : read_qword(m_offs_compressed_size); }
+ std::uint64_t header_offset() const { return ~m_header_offset ? m_header_offset : read_qword(m_offs_header_offset); }
+ std::uint32_t start_disk() const { return ~m_start_disk ? m_start_disk : read_dword(m_offs_start_disk); }
+
+ std::size_t total_length() const { return minimum_length() + m_offs_end; }
+ static std::size_t minimum_length() { return 0x00; }
+
+private:
+ std::uint32_t m_uncompressed_size;
+ std::uint32_t m_compressed_size;
+ std::uint32_t m_header_offset;
+ std::uint16_t m_start_disk;
+
+ std::size_t m_offs_compressed_size;
+ std::size_t m_offs_header_offset;
+ std::size_t m_offs_start_disk;
+ std::size_t m_offs_end;
+};
+
+
+class utf8_path_reader : private reader_base
+{
+public:
+ utf8_path_reader(extra_field_reader const &field) : reader_base(field.data()), m_length(field.data_size()) { }
+
+ std::uint8_t version() const { return m_buffer[0]; }
+ std::uint32_t name_crc32() const { return read_dword(0x01); }
+ std::string unicode_name() const { return read_string(0x05, m_length - 0x05); }
+ void unicode_name(std::string &result) const { return read_string(result, 0x05, m_length - 0x05); }
+
+ std::size_t total_length() const { return m_length; }
+ static std::size_t minimum_length() { return 0x05; }
+
+private:
+ std::size_t m_length;
+};
+
+
+class general_flag_reader
+{
+public:
+ general_flag_reader(std::uint16_t val) : m_value(val) { }
+
+ bool encrypted() const { return bool(m_value & 0x0001); }
+ bool implode_8k_dict() const { return bool(m_value & 0x0002); }
+ bool implode_3_trees() const { return bool(m_value & 0x0004); }
+ unsigned deflate_option() const { return unsigned((m_value >> 1) & 0x0003); }
+ bool lzma_eos_mark() const { return bool(m_value & 0x0002); }
+ bool use_descriptor() const { return bool(m_value & 0x0008); }
+ bool patch_data() const { return bool(m_value & 0x0020); }
+ bool strong_encryption() const { return bool(m_value & 0x0040); }
+ bool utf8_encoding() const { return bool(m_value & 0x0800); }
+ bool directory_encryption() const { return bool(m_value & 0x2000); }
+
+private:
+ std::uint16_t m_value;
+};
+
+
/***************************************************************************
GLOBAL VARIABLES
@@ -486,14 +576,6 @@ std::mutex zip_file_impl::s_cache_mutex;
to the cache
-------------------------------------------------*/
-/**
- * @fn void zip_file_close(zip_file *zip)
- *
- * @brief Zip file close.
- *
- * @param [in,out] zip If non-null, the zip.
- */
-
void zip_file_impl::close(ptr &&zip)
{
if (!zip) return;
@@ -510,7 +592,11 @@ void zip_file_impl::close(ptr &&zip)
// if no room left in the cache, free the bottommost entry
if (cachenum == s_cache.size())
- s_cache[--cachenum].reset();
+ {
+ cachenum--;
+ osd_printf_verbose("unzip: removing %s from cache to make space\n", s_cache[cachenum]->m_filename.c_str());
+ s_cache[cachenum].reset();
+ }
// move everyone else down and place us at the top
for ( ; cachenum > 0; cachenum--)
@@ -524,19 +610,13 @@ void zip_file_impl::close(ptr &&zip)
***************************************************************************/
/*-------------------------------------------------
- zip_file_first_entry - return the first entry
- in the ZIP
--------------------------------------------------*/
-
-/*-------------------------------------------------
- zip_file_next_entry - return the next entry
- in the ZIP
+ zip_file_search - return the next matching
+ entry in the ZIP
-------------------------------------------------*/
int zip_file_impl::search(std::uint32_t search_crc, const std::string &search_filename, bool matchcrc, bool matchname, bool partialpath)
{
// if we're at or past the end, we're done
- std::string filename;
while ((m_cd_pos + central_dir_entry_reader::minimum_length()) <= m_ecd.cd_size)
{
// make sure we have enough data
@@ -555,43 +635,65 @@ int zip_file_impl::search(std::uint32_t search_crc, const std::string &search_fi
m_header.start_disk_number = reader.start_disk();
m_header.local_header_offset = reader.header_offset();
- // look for ZIP64 extended info
+ // advance the position
+ m_cd_pos += reader.total_length();
+
+ // copy the filename
+ bool is_utf8(general_flag_reader(m_header.bit_flag).utf8_encoding());
+ reader.file_name(m_header.file_name);
+
+ // walk the extra data
for (auto extra = reader.extra_field(); extra.length_sufficient(); extra = extra.next())
{
+ // look for ZIP64 extended info
if ((extra.header_id() == 0x0001) && (extra.data_size() >= zip64_ext_info_reader::minimum_length()))
{
- zip64_ext_info_reader const ext64(extra.data());
+ zip64_ext_info_reader const ext64(reader, extra);
if (extra.data_size() >= ext64.total_length())
{
m_header.compressed_length = ext64.compressed_size();
m_header.uncompressed_length = ext64.uncompressed_size();
m_header.start_disk_number = ext64.start_disk();
- break;
+ m_header.local_header_offset = ext64.header_offset();
+ }
+ }
+
+ // look for Info-ZIP UTF-8 path
+ if (!is_utf8 && (extra.header_id() == 0x7075) && (extra.data_size() >= utf8_path_reader::minimum_length()))
+ {
+ utf8_path_reader const utf8path(extra);
+ if (utf8path.version() == 1)
+ {
+ auto const addr(m_header.file_name.empty() ? nullptr : &m_header.file_name[0]);
+ auto const length(m_header.file_name.empty() ? 0 : m_header.file_name.length() * sizeof(m_header.file_name[0]));
+ auto const crc(crc32_creator::simple(addr, length));
+ if (utf8path.name_crc32() == crc.m_raw)
+ {
+ utf8path.unicode_name(m_header.file_name);
+ is_utf8 = true;
+ }
}
}
}
- // advance the position
- m_cd_pos += reader.total_length();
+ // FIXME: if (!is_utf8) convert filename to UTF8 (assume CP437 or something)
- // copy the filename filename
- filename = reader.file_name();
- bool const is_dir((filename.length() > 0) && (filename[filename.length() - 1] == '/'));
- if (is_dir) filename.resize(filename.length() - 1);
+ // chop off trailing slash for directory entries
+ bool const is_dir(!m_header.file_name.empty() && (m_header.file_name.back() == '/'));
+ if (is_dir) m_header.file_name.resize(m_header.file_name.length() - 1);
// check to see if it matches query
bool const crcmatch(search_crc == m_header.crc);
- auto const partialoffset(filename.length() - search_filename.length());
- bool const partialpossible((filename.length() > search_filename.length()) && (filename[partialoffset - 1] == '/'));
+ auto const partialoffset(m_header.file_name.length() - search_filename.length());
+ bool const partialpossible((m_header.file_name.length() > search_filename.length()) && (m_header.file_name[partialoffset - 1] == '/'));
const bool namematch(
- !core_stricmp(search_filename.c_str(), filename.c_str()) ||
- (partialpath && partialpossible && !core_stricmp(search_filename.c_str(), filename.c_str() + partialoffset)));
+ !core_stricmp(search_filename.c_str(), m_header.file_name.c_str()) ||
+ (partialpath && partialpossible && !core_stricmp(search_filename.c_str(), m_header.file_name.c_str() + partialoffset)));
bool const found = ((!matchcrc && !matchname) || !is_dir) && (!matchcrc || crcmatch) && (!matchname || namematch);
if (found)
{
m_curr_is_dir = is_dir;
- m_curr_name = std::move(filename);
return 0;
}
}
@@ -604,18 +706,6 @@ int zip_file_impl::search(std::uint32_t search_crc, const std::string &search_fi
from a ZIP into the target buffer
-------------------------------------------------*/
-/**
- * @fn zip_error zip_file_decompress(zip_file *zip, void *buffer, UINT32 length)
- *
- * @brief Zip file decompress.
- *
- * @param [in,out] zip If non-null, the zip.
- * @param [in,out] buffer If non-null, the buffer.
- * @param length The length.
- *
- * @return A zip_error.
- */
-
archive_file::error zip_file_impl::decompress(void *buffer, std::uint32_t length)
{
archive_file::error ziperr;
@@ -623,11 +713,17 @@ archive_file::error zip_file_impl::decompress(void *buffer, std::uint32_t length
// if we don't have enough buffer, error
if (length < m_header.uncompressed_length)
+ {
+ osd_printf_error("unzip: buffer too small to decompress %s from %s\n", m_header.file_name.c_str(), m_filename.c_str());
return archive_file::error::BUFFER_TOO_SMALL;
+ }
// make sure the info in the header aligns with what we know
if (m_header.start_disk_number != m_ecd.disk_number)
+ {
+ osd_printf_error("unzip: %s does not reside in segment %s\n", m_header.file_name.c_str(), m_filename.c_str());
return archive_file::error::UNSUPPORTED;
+ }
// get the compressed data offset
ziperr = get_compressed_data_offset(offset);
@@ -645,7 +741,14 @@ archive_file::error zip_file_impl::decompress(void *buffer, std::uint32_t length
ziperr = decompress_data_type_8(offset, buffer, length);
break;
+ case 14:
+ ziperr = decompress_data_type_14(offset, buffer, length);
+ break;
+
default:
+ osd_printf_error(
+ "unzip: %s in %s uses unsupported compression method %u\n",
+ m_header.file_name.c_str(), m_filename.c_str(), m_header.compression);
ziperr = archive_file::error::UNSUPPORTED;
break;
}
@@ -662,16 +765,6 @@ archive_file::error zip_file_impl::decompress(void *buffer, std::uint32_t length
read_ecd - read the ECD data
-------------------------------------------------*/
-/**
- * @fn static zip_error read_ecd(zip_file *zip)
- *
- * @brief Reads an ecd.
- *
- * @param [in,out] zip If non-null, the zip.
- *
- * @return The ecd.
- */
-
archive_file::error zip_file_impl::read_ecd()
{
// make sure the file handle is open
@@ -692,12 +785,19 @@ archive_file::error zip_file_impl::read_ecd()
// allocate buffer
std::unique_ptr<std::uint8_t []> buffer;
try { buffer.reset(new std::uint8_t[buflen + 1]); }
- catch (...) { return archive_file::error::OUT_OF_MEMORY; }
+ catch (...)
+ {
+ osd_printf_error("unzip: %s failed to allocate memory for ECD search\n", m_filename.c_str());
+ return archive_file::error::OUT_OF_MEMORY;
+ }
// read in one buffers' worth of data
error = m_file->read(&buffer[0], m_length - buflen, buflen, read_length);
if ((error != osd_file::error::NONE) || (read_length != buflen))
+ {
+ osd_printf_error("unzip: %s error reading file to search for ECD (%d)\n", m_filename.c_str(), int(error));
return archive_file::error::FILE_ERROR;
+ }
// find the ECD signature
std::int32_t offset;
@@ -722,7 +822,10 @@ archive_file::error zip_file_impl::read_ecd()
// is the file too small to contain a ZIP64 ECD locator?
if ((m_length - buflen + offset) < ecd64_locator_reader::minimum_length())
+ {
+ osd_printf_verbose("unzip: %s too small to contain ZIP64 ECD locator\n", m_filename.c_str());
return archive_file::error::NONE;
+ }
// try to read the ZIP64 ECD locator
error = m_file->read(
@@ -731,32 +834,61 @@ archive_file::error zip_file_impl::read_ecd()
ecd64_locator_reader::minimum_length(),
read_length);
if ((error != osd_file::error::NONE) || (read_length != ecd64_locator_reader::minimum_length()))
+ {
+ osd_printf_error("unzip: error reading %s to search for ZIP64 ECD locator (%d)\n", m_filename.c_str(), int(error));
return archive_file::error::FILE_ERROR;
+ }
// if the signature isn't correct, it's not a ZIP64 archive
ecd64_locator_reader const ecd64_loc_rd(buffer.get());
if (!ecd64_loc_rd.signature_correct())
+ {
+ osd_printf_verbose("unzip: %s has no ZIP64 ECD locator\n", m_filename.c_str());
return archive_file::error::NONE;
+ }
// check that the ZIP64 ECD is in this segment (assuming this segment is the last segment)
if ((ecd64_loc_rd.ecd64_disk() + 1) != ecd64_loc_rd.total_disks())
+ {
+ osd_printf_error("unzip: %s ZIP64 ECD resides in a different segment\n", m_filename.c_str());
return archive_file::error::UNSUPPORTED;
+ }
// try to read the ZIP64 ECD
error = m_file->read(&buffer[0], ecd64_loc_rd.ecd64_offset(), ecd64_reader::minimum_length(), read_length);
if (error != osd_file::error::NONE)
+ {
+ osd_printf_error("unzip: error reading %s ZIP64 ECD (%d)\n", m_filename.c_str(), int(error));
return archive_file::error::FILE_ERROR;
+ }
if (read_length != ecd64_reader::minimum_length())
+ {
+ osd_printf_error("unzip: unexpectedly reached end-of-file while reading %s ZIP64 ECD\n", m_filename.c_str());
return archive_file::error::FILE_TRUNCATED;
+ }
// check ZIP64 ECD
ecd64_reader const ecd64_rd(buffer.get());
if (!ecd64_rd.signature_correct())
+ {
+ osd_printf_error(
+ "unzip: %s ZIP64 ECD has incorrect signature 0x%08lx\n",
+ m_filename.c_str(), long(ecd64_rd.signature()));
return archive_file::error::BAD_SIGNATURE;
+ }
if (ecd64_rd.total_length() < ecd64_reader::minimum_length())
+ {
+ osd_printf_error("unzip: %s ZIP64 ECD appears to be too small\n", m_filename.c_str());
return archive_file::error::UNSUPPORTED;
+ }
if (ecd64_rd.version_needed() > 63)
+ {
+ osd_printf_error(
+ "unzip: %s ZIP64 ECD requires unsupported version %u.%u\n",
+ m_filename.c_str(), unsigned(ecd64_rd.version_needed() / 10), unsigned(ecd64_rd.version_needed() % 10));
return archive_file::error::UNSUPPORTED;
+ }
+ osd_printf_verbose("unzip: found %s ZIP64 ECD\n", m_filename.c_str());
// extract ZIP64 ECD info
m_ecd.disk_number = ecd64_rd.this_disk_no();
@@ -771,10 +903,16 @@ archive_file::error zip_file_impl::read_ecd()
// didn't find it; free this buffer and expand our search
if (buflen < m_length)
+ {
buflen *= 2;
+ }
else
+ {
+ osd_printf_error("unzip: %s couldn't find ECD\n", m_filename.c_str());
return archive_file::error::BAD_SIGNATURE;
+ }
}
+ osd_printf_error("unzip: %s couldn't find ECD in last 64KiB\n", m_filename.c_str());
return archive_file::error::OUT_OF_MEMORY;
}
@@ -784,27 +922,32 @@ archive_file::error zip_file_impl::read_ecd()
offset of the compressed data
-------------------------------------------------*/
-/**
- * @fn static zip_error get_compressed_data_offset(zip_file *zip, UINT64 *offset)
- *
- * @brief Gets compressed data offset.
- *
- * @param [in,out] zip If non-null, the zip.
- * @param [in,out] offset If non-null, the offset.
- *
- * @return The compressed data offset.
- */
-
archive_file::error zip_file_impl::get_compressed_data_offset(std::uint64_t &offset)
{
// don't support a number of features
- if ((m_header.start_disk_number != m_ecd.disk_number) || // in a different segment
- (m_header.version_needed > 63) || // future version of specification
- (m_header.bit_flag & 0x0001) || // encrypted
- (m_header.bit_flag & 0x0020) || // compressed patch data
- (m_header.bit_flag & 0x0040) || // strong encryption
- (m_header.bit_flag & 0x2000)) // directory encryption
+ general_flag_reader const flags(m_header.bit_flag);
+ if (m_header.start_disk_number != m_ecd.disk_number)
+ {
+ osd_printf_error("unzip: %s does not reside in segment %s\n", m_header.file_name.c_str(), m_filename.c_str());
+ return archive_file::error::UNSUPPORTED;
+ }
+ if (m_header.version_needed > 63)
+ {
+ osd_printf_error(
+ "unzip: %s in %s requires unsupported version %u.%u\n",
+ m_header.file_name.c_str(), m_filename.c_str(), unsigned(m_header.version_needed / 10), unsigned(m_header.version_needed % 10));
return archive_file::error::UNSUPPORTED;
+ }
+ if (flags.encrypted() || flags.strong_encryption())
+ {
+ osd_printf_error("unzip: %s in %s is encrypted\n", m_header.file_name.c_str(), m_filename.c_str());
+ return archive_file::error::UNSUPPORTED;
+ }
+ if (flags.patch_data())
+ {
+ osd_printf_error("unzip: %s in %s is compressed patch data\n", m_header.file_name.c_str(), m_filename.c_str());
+ return archive_file::error::UNSUPPORTED;
+ }
// make sure the file handle is open
auto const ziperr = reopen();
@@ -815,14 +958,29 @@ archive_file::error zip_file_impl::get_compressed_data_offset(std::uint64_t &off
std::uint32_t read_length;
auto const error = m_file->read(&m_buffer[0], m_header.local_header_offset, local_file_header_reader::minimum_length(), read_length);
if (error != osd_file::error::NONE)
+ {
+ osd_printf_error(
+ "unzip: error reading local file header for %s in %s (%d)\n",
+ m_header.file_name.c_str(), m_filename.c_str(), int(error));
return archive_file::error::FILE_ERROR;
+ }
if (read_length != local_file_header_reader::minimum_length())
+ {
+ osd_printf_error(
+ "unzip: unexpectedly reached end-of-file while reading local file header for %s in %s\n",
+ m_header.file_name.c_str(), m_filename.c_str());
return archive_file::error::FILE_TRUNCATED;
+ }
// compute the final offset
local_file_header_reader reader(&m_buffer[0]);
if (!reader.signature_correct())
+ {
+ osd_printf_error(
+ "unzip: local file header for %s in %s has incorrect signature %04lx\n",
+ m_header.file_name.c_str(), m_filename.c_str(), long(reader.signature()));
return archive_file::error::BAD_SIGNATURE;
+ }
offset = m_header.local_header_offset + reader.total_length();
return archive_file::error::NONE;
@@ -839,31 +997,25 @@ archive_file::error zip_file_impl::get_compressed_data_offset(std::uint64_t &off
type 0 data (which is uncompressed)
-------------------------------------------------*/
-/**
- * @fn static zip_error decompress_data_type_0(zip_file *zip, UINT64 offset, void *buffer, UINT32 length)
- *
- * @brief Decompress the data type 0.
- *
- * @param [in,out] zip If non-null, the zip.
- * @param offset The offset.
- * @param [in,out] buffer If non-null, the buffer.
- * @param length The length.
- *
- * @return A zip_error.
- */
-
archive_file::error zip_file_impl::decompress_data_type_0(std::uint64_t offset, void *buffer, std::uint32_t length)
{
- std::uint32_t read_length;
-
// the data is uncompressed; just read it
+ std::uint32_t read_length(0);
auto const filerr = m_file->read(buffer, offset, m_header.compressed_length, read_length);
if (filerr != osd_file::error::NONE)
+ {
+ osd_printf_error("unzip: error reading %s from %s (%d)\n", m_header.file_name.c_str(), m_filename.c_str(), int(filerr));
return archive_file::error::FILE_ERROR;
+ }
else if (read_length != m_header.compressed_length)
+ {
+ osd_printf_error("unzip: unexpectedly reached end-of-file while reading %s from %s\n", m_header.file_name.c_str(), m_filename.c_str());
return archive_file::error::FILE_TRUNCATED;
+ }
else
+ {
return archive_file::error::NONE;
+ }
}
@@ -872,51 +1024,56 @@ archive_file::error zip_file_impl::decompress_data_type_0(std::uint64_t offset,
type 8 data (which is deflated)
-------------------------------------------------*/
-/**
- * @fn static zip_error decompress_data_type_8(zip_file *zip, UINT64 offset, void *buffer, UINT32 length)
- *
- * @brief Decompress the data type 8.
- *
- * @param [in,out] zip If non-null, the zip.
- * @param offset The offset.
- * @param [in,out] buffer If non-null, the buffer.
- * @param length The length.
- *
- * @return A zip_error.
- */
-
archive_file::error zip_file_impl::decompress_data_type_8(std::uint64_t offset, void *buffer, std::uint32_t length)
{
- std::uint32_t input_remaining = m_header.compressed_length;
+ std::uint64_t input_remaining = m_header.compressed_length;
int zerr;
- /* reset the stream */
+ // reset the stream
z_stream stream;
- memset(&stream, 0, sizeof(stream));
- stream.next_out = (Bytef *)buffer;
+ stream.zalloc = Z_NULL;
+ stream.zfree = Z_NULL;
+ stream.opaque = Z_NULL;
+ stream.avail_in = 0;
+ stream.next_out = reinterpret_cast<Bytef *>(buffer);
stream.avail_out = length;
// initialize the decompressor
zerr = inflateInit2(&stream, -MAX_WBITS);
if (zerr != Z_OK)
+ {
+ osd_printf_error(
+ "unzip: error allocating zlib stream to inflate %s from %s (%d)\n",
+ m_header.file_name.c_str(), m_filename.c_str(), zerr);
return archive_file::error::DECOMPRESS_ERROR;
+ }
// loop until we're done
while (1)
{
// read in the next chunk of data
- std::uint32_t read_length;
- auto const filerr = m_file->read(&m_buffer[0], offset, (std::min<std::uint32_t>)(input_remaining, m_buffer.size()), read_length);
+ std::uint32_t read_length(0);
+ auto const filerr = m_file->read(
+ &m_buffer[0],
+ offset,
+ std::uint32_t((std::min<std::uint64_t>)(input_remaining, m_buffer.size())),
+ read_length);
if (filerr != osd_file::error::NONE)
{
+ osd_printf_error(
+ "unzip: error reading compressed data for %s in %s (%d)\n",
+ m_header.file_name.c_str(), m_filename.c_str(), int(filerr));
inflateEnd(&stream);
return archive_file::error::FILE_ERROR;
}
offset += read_length;
// if we read nothing, but still have data left, the file is truncated
- if (read_length == 0 && input_remaining > 0)
+ if ((read_length == 0) && (input_remaining > 0))
{
+ osd_printf_error(
+ "unzip: unexpectedly reached end-of-file while reading compressed data for %s in %s\n",
+ m_header.file_name.c_str(), m_filename.c_str());
inflateEnd(&stream);
return archive_file::error::FILE_TRUNCATED;
}
@@ -933,9 +1090,12 @@ archive_file::error zip_file_impl::decompress_data_type_8(std::uint64_t offset,
// now inflate
zerr = inflate(&stream, Z_NO_FLUSH);
if (zerr == Z_STREAM_END)
+ {
break;
- if (zerr != Z_OK)
+ }
+ else if (zerr != Z_OK)
{
+ osd_printf_error("unzip: error inflating %s from %s (%d)\n", m_header.file_name.c_str(), m_filename.c_str(), zerr);
inflateEnd(&stream);
return archive_file::error::DECOMPRESS_ERROR;
}
@@ -944,15 +1104,210 @@ archive_file::error zip_file_impl::decompress_data_type_8(std::uint64_t offset,
// finish decompression
zerr = inflateEnd(&stream);
if (zerr != Z_OK)
+ {
+ osd_printf_error("unzip: error finishing inflation of %s from %s (%d)\n", m_header.file_name.c_str(), m_filename.c_str(), zerr);
return archive_file::error::DECOMPRESS_ERROR;
+ }
- /* if anything looks funny, report an error */
- if (stream.avail_out > 0 || input_remaining > 0)
+ // if anything looks funny, report an error
+ if ((stream.avail_out > 0) || (input_remaining > 0))
+ {
+ osd_printf_error(
+ "unzip: inflation of %s from %s doesn't appear to have completed correctly\n",
+ m_header.file_name.c_str(), m_filename.c_str());
return archive_file::error::DECOMPRESS_ERROR;
+ }
return archive_file::error::NONE;
}
+
+/*-------------------------------------------------
+ decompress_data_type_14 - decompress
+ type 14 data (LZMA)
+-------------------------------------------------*/
+
+archive_file::error zip_file_impl::decompress_data_type_14(std::uint64_t offset, void *buffer, std::uint32_t length)
+{
+ // two-byte version
+ // two-byte properties size (little-endian)
+ // properties
+ // compressed data
+
+ assert(4 <= m_buffer.size());
+ assert(LZMA_PROPS_SIZE <= m_buffer.size());
+
+ bool const eos_mark(general_flag_reader(m_header.bit_flag).lzma_eos_mark());
+ Byte *const output(reinterpret_cast<Byte *>(buffer));
+ SizeT output_remaining(length);
+ std::uint64_t input_remaining(m_header.compressed_length);
+
+ std::uint32_t read_length;
+ osd_file::error filerr;
+ SRes lzerr;
+ ELzmaStatus lzstatus(LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK);
+
+ // reset the stream
+ ISzAlloc alloc_imp;
+ alloc_imp.Alloc = [](void *p, std::size_t size) -> void * { return (size == 0) ? nullptr : std::malloc(size); };
+ alloc_imp.Free = [](void *p, void *address) -> void { std::free(address); };
+ CLzmaDec stream;
+ LzmaDec_Construct(&stream);
+
+ // need to read LZMA properties before we can initialise the decompressor
+ if (4 > input_remaining)
+ {
+ osd_printf_error(
+ "unzip:compressed data for %s in %s is too small to hold LZMA properties header\n",
+ m_header.file_name.c_str(), m_filename.c_str());
+ return archive_file::error::DECOMPRESS_ERROR;
+ }
+ filerr = m_file->read(&m_buffer[0], offset, 4, read_length);
+ if (filerr != osd_file::error::NONE)
+ {
+ osd_printf_error(
+ "unzip: error reading LZMA properties header for %s in %s (%d)\n",
+ m_header.file_name.c_str(), m_filename.c_str(), int(filerr));
+ return archive_file::error::FILE_ERROR;
+ }
+ offset += read_length;
+ input_remaining -= read_length;
+ if (4 != read_length)
+ {
+ osd_printf_error(
+ "unzip: unexpectedly reached end-of-file while reading LZMA properties header for %s in %s\n",
+ m_header.file_name.c_str(), m_filename.c_str());
+ return archive_file::error::FILE_TRUNCATED;
+ }
+ std::uint16_t const props_size((std::uint16_t(m_buffer[3]) << 8) | std::uint16_t(m_buffer[2]));
+ if (props_size > m_buffer.size())
+ {
+ osd_printf_error(
+ "unzip: %s in %s has excessively large LZMA properties\n",
+ m_header.file_name.c_str(), m_filename.c_str());
+ return archive_file::error::UNSUPPORTED;
+ }
+ else if (props_size > input_remaining)
+ {
+ osd_printf_error(
+ "unzip:compressed data for %s in %s is too small to hold LZMA properties\n",
+ m_header.file_name.c_str(), m_filename.c_str());
+ return archive_file::error::DECOMPRESS_ERROR;
+ }
+ filerr = m_file->read(&m_buffer[0], offset, props_size, read_length);
+ if (filerr != osd_file::error::NONE)
+ {
+ osd_printf_error(
+ "unzip: error reading LZMA properties for %s in %s (%d)\n",
+ m_header.file_name.c_str(), m_filename.c_str(), int(filerr));
+ return archive_file::error::FILE_ERROR;
+ }
+ offset += read_length;
+ input_remaining -= read_length;
+ if (props_size != read_length)
+ {
+ osd_printf_error(
+ "unzip: unexpectedly reached end-of-file while reading LZMA properties for %s in %s\n",
+ m_header.file_name.c_str(), m_filename.c_str());
+ return archive_file::error::FILE_TRUNCATED;
+ }
+
+ // initialize the decompressor
+ lzerr = LzmaDec_Allocate(&stream, &m_buffer[0], props_size, &alloc_imp);
+ if (SZ_ERROR_MEM == lzerr)
+ {
+ osd_printf_error(
+ "unzip: memory error allocating LZMA decoder to decompress %s from %s\n",
+ m_header.file_name.c_str(), m_filename.c_str());
+ return archive_file::error::OUT_OF_MEMORY;
+ }
+ else if (SZ_OK != lzerr)
+ {
+ osd_printf_error(
+ "unzip: error allocating LZMA decoder to decompress %s from %s (%d)\n",
+ m_header.file_name.c_str(), m_filename.c_str(), int(lzerr));
+ return archive_file::error::DECOMPRESS_ERROR;
+ }
+ LzmaDec_Init(&stream);
+
+ // loop until we're done
+ while (0 < input_remaining)
+ {
+ // read in the next chunk of data
+ filerr = m_file->read(
+ &m_buffer[0],
+ offset,
+ std::uint32_t((std::min<std::uint64_t>)(input_remaining, m_buffer.size())),
+ read_length);
+ if (filerr != osd_file::error::NONE)
+ {
+ osd_printf_error(
+ "unzip: error reading compressed data for %s in %s (%d)\n",
+ m_header.file_name.c_str(), m_filename.c_str(), int(filerr));
+ LzmaDec_Free(&stream, &alloc_imp);
+ return archive_file::error::FILE_ERROR;
+ }
+ offset += read_length;
+ input_remaining -= read_length;
+
+ // if we read nothing, but still have data left, the file is truncated
+ if ((0 == read_length) && (0 < input_remaining))
+ {
+ osd_printf_error(
+ "unzip: unexpectedly reached end-of-file while reading compressed data for %s in %s\n",
+ m_header.file_name.c_str(), m_filename.c_str());
+ LzmaDec_Free(&stream, &alloc_imp);
+ return archive_file::error::FILE_TRUNCATED;
+ }
+
+ // now decompress
+ SizeT len(read_length);
+ // FIXME: is the input length really an in/out parameter or not?
+ // At least on reaching the end of the input, the input length doesn't seem to get updated
+ lzerr = LzmaDec_DecodeToBuf(
+ &stream,
+ output + length - output_remaining,
+ &output_remaining,
+ reinterpret_cast<Byte const *>(&m_buffer[0]),
+ &len,
+ ((0 == input_remaining) && eos_mark) ? LZMA_FINISH_END : LZMA_FINISH_ANY,
+ &lzstatus);
+ if (SZ_OK != lzerr)
+ {
+ osd_printf_error("unzip: error decoding LZMA data for %s in %s (%d)\n", m_header.file_name.c_str(), m_filename.c_str(), int(lzerr));
+ LzmaDec_Free(&stream, &alloc_imp);
+ return archive_file::error::DECOMPRESS_ERROR;
+ }
+ }
+
+ // finish decompression
+ LzmaDec_Free(&stream, &alloc_imp);
+
+ // if anything looks funny, report an error
+ if (LZMA_STATUS_FINISHED_WITH_MARK == lzstatus)
+ {
+ return archive_file::error::NONE;
+ }
+ else if (eos_mark)
+ {
+ osd_printf_error(
+ "unzip: LZMA end mark not found for %s in %s (%d)\n",
+ m_header.file_name.c_str(), m_filename.c_str(), int(lzstatus));
+ return archive_file::error::DECOMPRESS_ERROR;
+ }
+ else if (LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK != lzstatus)
+ {
+ osd_printf_error(
+ "unzip: LZMA decompression of %s from %s doesn't appear to have completed correctly (%d)\n",
+ m_header.file_name.c_str(), m_filename.c_str(), int(lzstatus));
+ return archive_file::error::DECOMPRESS_ERROR;
+ }
+ else
+ {
+ return archive_file::error::NONE;
+ }
+}
+
} // anonymous namespace
@@ -973,17 +1328,6 @@ void m7z_file_cache_clear();
zip_file_open - opens a ZIP file for reading
-------------------------------------------------*/
-/**
- * @fn zip_error zip_file_open(const char *filename, zip_file **zip)
- *
- * @brief Queries if a given zip file open.
- *
- * @param filename Filename of the file.
- * @param [in,out] zip If non-null, the zip.
- *
- * @return A zip_error.
- */
-
archive_file::error archive_file::open_zip(const std::string &filename, ptr &result)
{
// ensure we start with a NULL result
diff --git a/src/lib/util/zippath.cpp b/src/lib/util/zippath.cpp
index f16dcf824e6..1e4fb6dd293 100644
--- a/src/lib/util/zippath.cpp
+++ b/src/lib/util/zippath.cpp
@@ -17,6 +17,7 @@
#include <cassert>
#include <cctype>
+#include <forward_list>
#include <new>
@@ -26,20 +27,6 @@ namespace util {
***************************************************************************/
/**
- * @struct zippath_returned_directory
- *
- * @brief A zippath returned directory.
- */
-
-struct zippath_returned_directory
-{
- /** @brief The next. */
- zippath_returned_directory *next;
- /** @brief The name. */
- std::string name;
-};
-
-/**
* @class zippath_directory
*
* @brief A zippath directory.
@@ -49,11 +36,13 @@ class zippath_directory
{
public:
zippath_directory()
- : returned_parent(false),
- directory(nullptr),
- called_zip_first(false),
- zipfile(nullptr),
- returned_dirlist(nullptr) { }
+ : returned_parent(false)
+ , directory(nullptr)
+ , called_zip_first(false)
+ , zipfile(nullptr)
+ , returned_dirlist()
+ {
+ }
/* common */
/** @brief true to returned parent. */
@@ -73,7 +62,7 @@ public:
/** @brief The zipprefix. */
std::string zipprefix;
/** @brief The returned dirlist. */
- zippath_returned_directory *returned_dirlist;
+ std::forward_list<std::string> returned_dirlist;
};
@@ -856,12 +845,7 @@ void zippath_closedir(zippath_directory *directory)
if (directory->zipfile != nullptr)
directory->zipfile.reset();
- while (directory->returned_dirlist != nullptr)
- {
- zippath_returned_directory *dirlist = directory->returned_dirlist;
- directory->returned_dirlist = directory->returned_dirlist->next;
- delete dirlist;
- }
+ directory->returned_dirlist.clear();
delete directory;
}
@@ -887,24 +871,28 @@ void zippath_closedir(zippath_directory *directory)
static const char *get_relative_path(zippath_directory const &directory)
{
auto len = directory.zipprefix.length();
- const char *prefix = directory.zipprefix.c_str();
+ char const *prefix = directory.zipprefix.c_str();
while (is_zip_file_separator(*prefix))
{
len--;
prefix++;
}
- if ((len <= directory.zipfile->current_name().length()) &&
- !strncmp(prefix, directory.zipfile->current_name().c_str(), len))
+ std::string const &current(directory.zipfile->current_name());
+ char const *result = directory.zipfile->current_name().c_str() + len;
+ if ((current.length() >= len) &&
+ !strncmp(prefix, current.c_str(), len) &&
+ (!*prefix || is_zip_file_separator(*result) || is_zip_file_separator(directory.zipprefix.back())))
{
- const char *result = &directory.zipfile->current_name().c_str()[len];
while (is_zip_file_separator(*result))
result++;
return *result ? result : nullptr;
}
-
- return nullptr;
+ else
+ {
+ return nullptr;
+ }
}
@@ -925,11 +913,6 @@ static const char *get_relative_path(zippath_directory const &directory)
const osd_directory_entry *zippath_readdir(zippath_directory *directory)
{
const osd_directory_entry *result = nullptr;
- int header;
- const char *relpath;
- const char *separator;
- const char *s;
- zippath_returned_directory *rdent;
if (!directory->returned_parent)
{
@@ -947,10 +930,10 @@ const osd_directory_entry *zippath_readdir(zippath_directory *directory)
{
result = osd_readdir(directory->directory);
}
- while((result != nullptr) && (!strcmp(result->name, ".") || !strcmp(result->name, "..")));
+ while (result && (!strcmp(result->name, ".") || !strcmp(result->name, "..")));
/* special case - is this entry a ZIP file? if so we need to return it as a "directory" */
- if ((result != nullptr) && (is_zip_file(result->name) || is_7z_file(result->name)))
+ if (result && (is_zip_file(result->name) || is_7z_file(result->name)))
{
/* copy; but change the entry type */
directory->returned_entry = *result;
@@ -960,47 +943,46 @@ const osd_directory_entry *zippath_readdir(zippath_directory *directory)
}
else if (directory->zipfile)
{
+ char const *relpath;
do
{
/* a zip file read */
+ int header;
do
{
- if (!directory->called_zip_first)
- header = directory->zipfile->first_file();
- else
- header = directory->zipfile->next_file();
+ header = directory->called_zip_first ? directory->zipfile->next_file() : directory->zipfile->first_file();
directory->called_zip_first = true;
relpath = nullptr;
}
- while((header >= 0) && ((relpath = get_relative_path(*directory)) == nullptr));
+ while ((header >= 0) && ((relpath = get_relative_path(*directory)) == nullptr));
- if (relpath != nullptr)
+ if (relpath)
{
/* we've found a ZIP entry; but this may be an entry deep within the target directory */
- for (s = relpath; *s && !is_zip_file_separator(*s); s++)
- ;
- separator = *s ? s : nullptr;
+ char const *separator = relpath;
+ while (*separator && !is_zip_file_separator(*separator)) separator++;
- if (separator != nullptr)
+ if (*separator || directory->zipfile->current_is_directory())
{
/* a nested entry; loop through returned_dirlist to see if we've returned the parent directory */
- for (rdent = directory->returned_dirlist; rdent != nullptr; rdent = rdent->next)
+ auto const len(separator - relpath);
+ auto rdent = directory->returned_dirlist.begin();
+ while (directory->returned_dirlist.end() != rdent)
{
- if (!core_strnicmp(rdent->name.c_str(), relpath, separator - relpath))
+ if ((rdent->length() == len) && !core_strnicmp(rdent->c_str(), relpath, len))
break;
+ else
+ ++rdent;
}
- if (rdent == nullptr)
+ if (directory->returned_dirlist.end() == rdent)
{
/* we've found a new directory; add this to returned_dirlist */
- rdent = new zippath_returned_directory;
- rdent->next = directory->returned_dirlist;
- rdent->name.assign(relpath, separator - relpath);
- directory->returned_dirlist = rdent;
+ directory->returned_dirlist.emplace_front(relpath, separator - relpath);
/* ...and return it */
memset(&directory->returned_entry, 0, sizeof(directory->returned_entry));
- directory->returned_entry.name = rdent->name.c_str();
+ directory->returned_entry.name = directory->returned_dirlist.front().c_str();
directory->returned_entry.type = ENTTYPE_DIR;
result = &directory->returned_entry;
}
@@ -1016,7 +998,7 @@ const osd_directory_entry *zippath_readdir(zippath_directory *directory)
}
}
}
- while((relpath != nullptr) && (result == nullptr));
+ while (relpath && !result);
}
return result;
}
diff --git a/src/mame/audio/seibu.cpp b/src/mame/audio/seibu.cpp
index c6b4c6b654d..d3add75d6fd 100644
--- a/src/mame/audio/seibu.cpp
+++ b/src/mame/audio/seibu.cpp
@@ -388,7 +388,7 @@ ADDRESS_MAP_START( seibu2_airraid_sound_map, AS_PROGRAM, 8, driver_device )
AM_RANGE(0x4001, 0x4001) AM_DEVWRITE("seibu_sound", seibu_sound_device, irq_clear_w)
AM_RANGE(0x4002, 0x4002) AM_DEVWRITE("seibu_sound", seibu_sound_device, rst10_ack_w)
AM_RANGE(0x4003, 0x4003) AM_DEVWRITE("seibu_sound", seibu_sound_device, rst18_ack_w)
- AM_RANGE(0x4007, 0x4007) AM_WRITENOP // bank, always 0
+ AM_RANGE(0x4007, 0x4007) AM_DEVWRITE("seibu_sound", seibu_sound_device, bank_w)
AM_RANGE(0x4008, 0x4009) AM_DEVREADWRITE("ymsnd", ym2151_device, read, write)
AM_RANGE(0x4010, 0x4011) AM_DEVREAD("seibu_sound", seibu_sound_device, soundlatch_r)
AM_RANGE(0x4012, 0x4012) AM_DEVREAD("seibu_sound", seibu_sound_device, main_data_pending_r)
diff --git a/src/mame/drivers/cshooter.cpp b/src/mame/drivers/cshooter.cpp
index d667d57e710..f64d950dc61 100644
--- a/src/mame/drivers/cshooter.cpp
+++ b/src/mame/drivers/cshooter.cpp
@@ -7,17 +7,8 @@
- added sprites, bgmap reading and few fixes here and there
airraid and cshootere are a bit "playable" ;) without gfx
-
-Haze's notes :
-
- - interrupts are probably wrong .. it ends up writing to rom etc.
- - how do the sprites / bg's work .. these big black unknown things on the pcb
- also sound a bit disturbing, what are they?
- - i can't decode the other gfx? rom
- - there don't seem to be any sprites / bg's in ram, interrupts?
- - palette? format isn't understood
- - the other sets ('cshootere' and 'airraid') need decrypting ..
- is the main one protected ? theres a 68705 on it
+Haze's notes
+ - video system is very similar to darkmist.cpp
Stephh's notes (based on the game Z80 code and some tests) :
@@ -85,6 +76,55 @@ Stephh's notes (based on the game Z80 code and some tests) :
*/
+
+
+/*
+
+ Custom SIMM module placement
+
+ The Air Raid PCB has 3 custom modules shown
+ in the rough diagram of the PCB below.
+
+ The modules do not appear to be 100%
+ identical based on external shapes visible.
+
+ The data they contain is as follows
+ MODULE1
+ Background tilemap graphic data
+ Background tilemap layout data
+
+ MODULE2
+ Foreground tilemap graphic data
+ Foreground tilemap layout data
+
+ MODULE3
+ Sprite graphic data
+
+ it's also possible each module contains a
+ 0x100 colour look up table for that layer.
+
+
+ |-------------------------------------------------|
+ | A B C D E F G H I J K |
+ 20| ##MOD1####### |
+ | # Z80 |
+ | M -|
+ | O |
+ | D |=J
+ | 2 |=A
+ | # |=M
+ 11| |=M
+ | |=A
+ | |
+ | -|
+ | Z80 |
+ | |
+ | ##MOD3####### |
+ |-------------------------------------------------|
+
+*/
+
+
#include "emu.h"
#include "cpu/z80/z80.h"
#include "audio/seibu.h"
@@ -98,6 +138,7 @@ public:
m_maincpu(*this, "maincpu"),
m_seibu_sound(*this, "seibu_sound"),
m_txram(*this, "txram"),
+ m_vregs(*this, "vregs"),
m_mainram(*this, "mainram"),
m_spriteram(*this, "spriteram"),
m_gfxdecode(*this, "gfxdecode"),
@@ -109,28 +150,36 @@ public:
required_device<cpu_device> m_maincpu;
optional_device<seibu_sound_device> m_seibu_sound;
required_shared_ptr<UINT8> m_txram;
+ required_shared_ptr<UINT8> m_vregs;
optional_shared_ptr<UINT8> m_mainram;
optional_shared_ptr<UINT8> m_spriteram;
required_device<gfxdecode_device> m_gfxdecode;
required_device<palette_device> m_palette;
required_shared_ptr<UINT8> m_generic_paletteram_8;
required_shared_ptr<UINT8> m_generic_paletteram2_8;
- required_shared_ptr<UINT8> m_decrypted_opcodes;
+ optional_shared_ptr<UINT8> m_decrypted_opcodes;
+
+ TILEMAP_MAPPER_MEMBER(bg_scan);
+ TILEMAP_MAPPER_MEMBER(fg_scan);
+ TILE_GET_INFO_MEMBER(get_bg_tile_info);
+ tilemap_t *m_bg_tilemap;
+ TILE_GET_INFO_MEMBER(get_fg_tile_info);
+ tilemap_t *m_fg_tilemap;
+ TILE_GET_INFO_MEMBER(get_cstx_tile_info);
tilemap_t *m_txtilemap;
- int m_coin_stat;
- int m_counter;
+ UINT16 m_hw;
DECLARE_WRITE8_MEMBER(cshooter_txram_w);
DECLARE_READ8_MEMBER(cshooter_coin_r);
DECLARE_WRITE8_MEMBER(cshooter_c500_w);
DECLARE_WRITE8_MEMBER(cshooter_c700_w);
DECLARE_WRITE8_MEMBER(bank_w);
+ DECLARE_WRITE8_MEMBER(vregs_w);
DECLARE_READ8_MEMBER(seibu_sound_comms_r);
DECLARE_WRITE8_MEMBER(seibu_sound_comms_w);
DECLARE_DRIVER_INIT(cshootere);
DECLARE_DRIVER_INIT(cshooter);
- TILE_GET_INFO_MEMBER(get_cstx_tile_info);
virtual void video_start() override;
DECLARE_PALETTE_INIT(cshooter);
DECLARE_MACHINE_RESET(cshooter);
@@ -142,7 +191,7 @@ public:
PALETTE_INIT_MEMBER(cshooter_state, cshooter)
{
- const UINT8 *color_prom = memregion("proms")->base();
+ const UINT8 *color_prom = memregion("tx_clut")->base();
int i;
// text uses colors 0xc0-0xdf
@@ -152,8 +201,55 @@ PALETTE_INIT_MEMBER(cshooter_state, cshooter)
// rest is still unknown..
for (i = 0x40; i < 0x100; i++)
palette.set_pen_indirect(i, color_prom[i]);
+
+ // just make a direct copy of palette at the end for debug
+ for (i = 0x100; i < 0x200; i++)
+ palette.set_pen_indirect(i, i-0x100);
+
+}
+
+
+TILEMAP_MAPPER_MEMBER(cshooter_state::bg_scan)
+{
+ return ((row&0xf) * 0x10) + (col&0xf) + (((col&0x7f0) >> 4)*0x100) + ((row & 0x30)>>4) * 0x8000;
+}
+
+TILEMAP_MAPPER_MEMBER(cshooter_state::fg_scan)
+{
+ return ((row&0xf) * 0x10) + (col&0xf) + (((col&0x0f0) >> 4)*0x100) + ((row & 0x1f0)>>4) * 0x1000;
+}
+
+
+TILE_GET_INFO_MEMBER(cshooter_state::get_bg_tile_info)
+{
+ UINT8 *bgMap = memregion("bg_map")->base();
+ int tile = bgMap[(tile_index*2)+1] & 0xff;
+ int attr = bgMap[(tile_index*2)+0] & 0xff;
+
+ tile |= (attr & 0x70) << 4;
+
+ SET_TILE_INFO_MEMBER(2,
+ tile,
+ 0,
+ 0);
+}
+
+TILE_GET_INFO_MEMBER(cshooter_state::get_fg_tile_info)
+{
+ UINT8 *bgMap = memregion("fg_map")->base();
+ int tile = bgMap[(tile_index*2)+1] & 0xff;
+ int attr = bgMap[(tile_index*2)+0] & 0xff;
+
+ tile |= (attr & 0x70) << 4;
+
+ SET_TILE_INFO_MEMBER(3,
+ tile,
+ 0,
+ 0);
}
+
+
TILE_GET_INFO_MEMBER(cshooter_state::get_cstx_tile_info)
{
int code = (m_txram[tile_index*2]);
@@ -171,6 +267,16 @@ WRITE8_MEMBER(cshooter_state::cshooter_txram_w)
void cshooter_state::video_start()
{
+
+ // there might actually be 4 banks of 2048 x 16 tilemaps in here as the upper scroll bits are with the rom banking.
+ m_bg_tilemap = &machine().tilemap().create(m_gfxdecode, tilemap_get_info_delegate(FUNC(cshooter_state::get_bg_tile_info),this),tilemap_mapper_delegate(FUNC(cshooter_state::bg_scan),this),16,16,2048, 64);
+
+ // which could in turn mean this is actually 256 x 128, not 256 x 512
+// m_fg_tilemap = &machine().tilemap().create(m_gfxdecode, tilemap_get_info_delegate(FUNC(cshooter_state::get_fg_tile_info),this),tilemap_mapper_delegate(FUNC(cshooter_state::fg_scan),this),16,16,256, 512);
+ m_fg_tilemap = &machine().tilemap().create(m_gfxdecode, tilemap_get_info_delegate(FUNC(cshooter_state::get_fg_tile_info),this),tilemap_mapper_delegate(FUNC(cshooter_state::fg_scan),this),16,16,256, 128);
+
+ m_fg_tilemap->set_transparent_pen(0);
+
m_txtilemap = &machine().tilemap().create(m_gfxdecode, tilemap_get_info_delegate(FUNC(cshooter_state::get_cstx_tile_info),this),TILEMAP_SCAN_ROWS, 8,8,32,32);
m_txtilemap->set_transparent_pen(0);
}
@@ -182,22 +288,32 @@ void cshooter_state::draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprec
if (m_spriteram[i+1]&0x80)
continue;
- /* BCD debug code, to be removed in the end */
- UINT8 tile_low = (m_spriteram[i]&0x0f);
- UINT8 tile_high = ((m_spriteram[i]&0xf0)>>4);
-
- tile_low += (tile_low > 0x9) ? 0x37 : 0x30;
- tile_high += (tile_high > 0x9) ? 0x37 : 0x30;
+ UINT16 tile = (m_spriteram[i]);
+ tile |= (m_spriteram[i + 1] & 0x70) << 4;
- m_gfxdecode->gfx(0)->transpen(bitmap,cliprect, tile_high << 1, m_spriteram[i+1], 0, 0, m_spriteram[i+3],m_spriteram[i+2],0);
- m_gfxdecode->gfx(0)->transpen(bitmap,cliprect, tile_high << 1, m_spriteram[i+1], 0, 0, m_spriteram[i+3]+8,m_spriteram[i+2],0);
- m_gfxdecode->gfx(0)->transpen(bitmap,cliprect, tile_low << 1, m_spriteram[i+1], 0, 0, m_spriteram[i+3]+8,m_spriteram[i+2]+8,0);
- m_gfxdecode->gfx(0)->transpen(bitmap,cliprect, tile_low << 1, m_spriteram[i+1], 0, 0, m_spriteram[i+3],m_spriteram[i+2]+8,0);
+ m_gfxdecode->gfx(1)->transpen(bitmap,cliprect, tile, 0, 0, 0, m_spriteram[i+3],m_spriteram[i+2],0);
}
}
+
+#define DISPLAY_SPR 1
+#define DISPLAY_FG 2
+#define DISPLAY_BG 4
+#define DISPLAY_TXT 8
+#define DM_GETSCROLL(n) (((m_vregs[(n)]<<1)&0xff) + ((m_vregs[(n)]&0x80)?1:0) +( ((m_vregs[(n)-1]<<4) | (m_vregs[(n)-1]<<12) )&0xff00))
+
UINT32 cshooter_state::screen_update_airraid(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
+
+ UINT16 bgscrolly = DM_GETSCROLL(0x6);
+ // this is more likely to be 'bank' than scroll, like NMK16
+ bgscrolly += ((m_hw & 0xc0) >> 6) * 256;
+
+ m_bg_tilemap->set_scrollx(0, DM_GETSCROLL(0x2));
+ m_bg_tilemap->set_scrolly(0, bgscrolly);
+ m_fg_tilemap->set_scrollx(0, DM_GETSCROLL(0xa));
+ m_fg_tilemap->set_scrolly(0, DM_GETSCROLL(0xe));
+
// set palette (compared to cshooter, r and g are swapped)
for (int i = 0; i < 0x100; i++)
{
@@ -209,23 +325,34 @@ UINT32 cshooter_state::screen_update_airraid(screen_device &screen, bitmap_ind16
m_palette->set_indirect_color(i, color);
}
+ // draw screen
bitmap.fill(0x80, cliprect); // temp
- draw_sprites(bitmap, cliprect);
+ if ((m_hw & DISPLAY_BG) == 0x00)
+ m_bg_tilemap->draw(screen, bitmap, cliprect, 0,0);
+
+ if ((m_hw & DISPLAY_FG) == 0x00)
+ m_fg_tilemap->draw(screen, bitmap, cliprect, 0,0);
+
+ if(m_hw & DISPLAY_SPR)
+ draw_sprites(bitmap, cliprect);
+
+ if(m_hw & DISPLAY_TXT)
+ m_txtilemap->draw(screen, bitmap, cliprect, 0,0);
- m_txtilemap->draw(screen, bitmap, cliprect, 0,0);
return 0;
}
+
/* main cpu */
TIMER_DEVICE_CALLBACK_MEMBER(cshooter_state::cshooter_scanline)
{
int scanline = param;
-// if(scanline == 240) // presumably a SW trap, not an irq
-// m_maincpu->set_input_line_and_vector(0, HOLD_LINE,0xd7); /* RST 10h */
+ if(scanline == 120) // updates scroll resgiters
+ m_maincpu->set_input_line_and_vector(0, HOLD_LINE,0xd7); /* RST 10h */
if(scanline == 240) // vblank-out irq
m_maincpu->set_input_line_and_vector(0, HOLD_LINE,0xcf); /* RST 08h */
@@ -234,15 +361,6 @@ TIMER_DEVICE_CALLBACK_MEMBER(cshooter_state::cshooter_scanline)
MACHINE_RESET_MEMBER(cshooter_state,cshooter)
{
- m_counter = 0;
-}
-
-READ8_MEMBER(cshooter_state::cshooter_coin_r)
-{
- /* Even reads must return 0xff - Odd reads must return the contents of input port 5.
- Code at 0x5061 is executed once during P.O.S.T. where there is one read.
- Code at 0x50b4 is then executed each frame (not sure) where there are 2 reads. */
- return ( (m_counter++ & 1) ? 0xff : ioport("COIN")->read() );
}
WRITE8_MEMBER(cshooter_state::cshooter_c500_w)
@@ -255,6 +373,19 @@ WRITE8_MEMBER(cshooter_state::cshooter_c700_w)
WRITE8_MEMBER(cshooter_state::bank_w)
{
+ // format of this address is TTBB tbfs
+
+ // TT = bg tilemap upper scroll bits (probably bg tilemap bank select?)
+ // BB = prg ROM bank select
+ // t = text layer enable
+ // b = bg layer disable
+ // f = fg layer disable
+ // s = sprite layer enable
+
+// printf("bankw %02x\n", data & 0xc0);
+
+ m_hw = data;
+
membank("bank1")->set_entry((data>>4)&3);
}
@@ -269,29 +400,15 @@ WRITE8_MEMBER(cshooter_state::seibu_sound_comms_w)
m_seibu_sound->main_word_w(space,offset,data,0x00ff);
}
-#if 0
-static ADDRESS_MAP_START( cshooter_map, AS_PROGRAM, 8, cshooter_state )
- AM_RANGE(0x0000, 0x7fff) AM_ROM
- AM_RANGE(0x8000, 0xafff) AM_READ_BANK("bank1") AM_WRITEONLY
- AM_RANGE(0xb000, 0xb0ff) AM_READONLY // sound related ?
- AM_RANGE(0xc000, 0xc0ff) AM_RAM AM_SHARE("paletteram")
- AM_RANGE(0xc100, 0xc1ff) AM_RAM AM_SHARE("paletteram2")
- AM_RANGE(0xc200, 0xc200) AM_READ_PORT("IN0")
- AM_RANGE(0xc201, 0xc201) AM_READ_PORT("IN1")
- AM_RANGE(0xc202, 0xc202) AM_READ_PORT("IN2")
- AM_RANGE(0xc203, 0xc203) AM_READ_PORT("DSW2")
- AM_RANGE(0xc204, 0xc204) AM_READ_PORT("DSW1")
- AM_RANGE(0xc205, 0xc205) AM_READ(cshooter_coin_r) // hack until I understand
- AM_RANGE(0xc500, 0xc500) AM_WRITE(cshooter_c500_w)
- AM_RANGE(0xc600, 0xc600) AM_WRITENOP // see notes
- AM_RANGE(0xc700, 0xc700) AM_WRITE(cshooter_c700_w)
- AM_RANGE(0xc801, 0xc801) AM_WRITENOP // see notes
- AM_RANGE(0xd000, 0xd7ff) AM_RAM_WRITE(cshooter_txram_w) AM_SHARE("txram")
- AM_RANGE(0xd800, 0xdfff) AM_RAM
- AM_RANGE(0xe000, 0xffff) AM_RAM
-ADDRESS_MAP_END
-#endif
+WRITE8_MEMBER(cshooter_state::vregs_w)
+{
+ m_vregs[offset] = data;
+
+ if ((offset != 0x2) && (offset != 0x01) && (offset != 0xa) && (offset != 0x09) && (offset != 0xe) && (offset != 0x0d) )
+ printf("vregs_w %02x: %02x\n", offset, data);
+}
+
static ADDRESS_MAP_START( airraid_map, AS_PROGRAM, 8, cshooter_state )
AM_RANGE(0x0000, 0x7fff) AM_ROM
@@ -302,14 +419,19 @@ static ADDRESS_MAP_START( airraid_map, AS_PROGRAM, 8, cshooter_state )
AM_RANGE(0xc003, 0xc003) AM_READ_PORT("DSW2")
AM_RANGE(0xc004, 0xc004) AM_READ_PORT("DSW1")
AM_RANGE(0xc500, 0xc500) AM_WRITE(cshooter_c500_w)
- AM_RANGE(0xc600, 0xc600) AM_WRITENOP // see notes
+// AM_RANGE(0xc600, 0xc600) AM_WRITE(cshooter_c600_w) // see notes
AM_RANGE(0xc700, 0xc700) AM_WRITE(cshooter_c700_w)
- AM_RANGE(0xc801, 0xc801) AM_WRITENOP // see notes
+// AM_RANGE(0xc801, 0xc801) AM_WRITE(cshooter_c801_w) // see notes
AM_RANGE(0xd000, 0xd7ff) AM_RAM_WRITE(cshooter_txram_w) AM_SHARE("txram")
AM_RANGE(0xd800, 0xd8ff) AM_RAM AM_SHARE("paletteram")
AM_RANGE(0xda00, 0xdaff) AM_RAM AM_SHARE("paletteram2")
AM_RANGE(0xdc11, 0xdc11) AM_WRITE(bank_w)
- AM_RANGE(0xdc00, 0xdc1f) AM_RAM //video registers
+ AM_RANGE(0xdc00, 0xdc0f) AM_RAM_WRITE(vregs_w) AM_SHARE("vregs")
+// AM_RANGE(0xdc10, 0xdc10) AM_RAM
+// AM_RANGE(0xdc19, 0xdc19) AM_RAM
+// AM_RANGE(0xdc1e, 0xdc1e) AM_RAM
+// AM_RANGE(0xdc1f, 0xdc1f) AM_RAM
+
AM_RANGE(0xde00, 0xde0f) AM_READWRITE(seibu_sound_comms_r,seibu_sound_comms_w)
AM_RANGE(0xe000, 0xfdff) AM_RAM AM_SHARE("mainram")
AM_RANGE(0xfe00, 0xffff) AM_RAM AM_SHARE("spriteram")
@@ -319,16 +441,6 @@ static ADDRESS_MAP_START( decrypted_opcodes_map, AS_DECRYPTED_OPCODES, 8, cshoot
AM_RANGE(0x0000, 0x7fff) AM_ROM AM_SHARE("decrypted_opcodes")
ADDRESS_MAP_END
-#if 0
-/* Sound CPU */
-
-static ADDRESS_MAP_START( sound_map, AS_PROGRAM, 8, cshooter_state )
- AM_RANGE(0x0000, 0x1fff) AM_ROM
- AM_RANGE(0xc000, 0xc001) AM_WRITENOP // AM_DEVWRITE("ym1", ym2203_device, write) ?
- AM_RANGE(0xc800, 0xc801) AM_WRITENOP // AM_DEVWRITE("ym2", ym2203_device, write) ?
- AM_RANGE(0xf800, 0xffff) AM_RAM
-ADDRESS_MAP_END
-#endif
static INPUT_PORTS_START( cshooter )
PORT_START("IN0") /* IN0 (0xc200) */
@@ -425,6 +537,7 @@ static INPUT_PORTS_START( airraid )
PORT_BIT( 0xfc, IP_ACTIVE_HIGH, IPT_UNUSED )
INPUT_PORTS_END
+
static const gfx_layout cshooter_charlayout =
{
8,8, /* 8*8 characters */
@@ -436,23 +549,39 @@ static const gfx_layout cshooter_charlayout =
128*1
};
+static const gfx_layout cshooter_char16layout =
+{
+ 16,16, /* 8*8 characters */
+ RGN_FRAC(1,1), /* 512 characters */
+ 4, /* 4 bits per pixel */
+ { 0,8,4,12 },
+ { 0,1,2,3, 16,17,18,19, 512+0,512+1,512+2,512+3, 512+16,512+17,512+18,512+19},
+ { 0*32, 1*32, 2*32, 3*32, 4*32, 5*32, 6*32, 7*32, 8*32, 9*32, 10*32, 11*32, 12*32, 13*32, 14*32, 15*32 },
+ 32*32
+};
+
+
static GFXDECODE_START( cshooter )
- GFXDECODE_ENTRY( "gfx1", 0, cshooter_charlayout, 0, 16 )
+ GFXDECODE_ENTRY( "tx_gfx", 0, cshooter_charlayout, 0, 16 )
+ GFXDECODE_ENTRY( "spr_gfx", 0, cshooter_char16layout, 0x100, 16 )
+ GFXDECODE_ENTRY( "bg_gfx", 0, cshooter_char16layout, 0x100, 16 )
+ GFXDECODE_ENTRY( "fg_gfx", 0, cshooter_char16layout, 0x100, 16 )
GFXDECODE_END
+
+
static MACHINE_CONFIG_START( airraid, cshooter_state )
/* basic machine hardware */
MCFG_CPU_ADD("maincpu", Z80,XTAL_12MHz/2) /* verified on pcb */
MCFG_CPU_PROGRAM_MAP(airraid_map)
- MCFG_CPU_DECRYPTED_OPCODES_MAP(decrypted_opcodes_map)
MCFG_TIMER_DRIVER_ADD_SCANLINE("scantimer", cshooter_state, cshooter_scanline, "screen", 0, 1)
SEIBU2_AIRRAID_SOUND_SYSTEM_CPU(XTAL_14_31818MHz/4) /* verified on pcb */
SEIBU_SOUND_SYSTEM_ENCRYPTED_LOW()
- MCFG_QUANTUM_TIME(attotime::from_hz(6000))
+ MCFG_QUANTUM_PERFECT_CPU("maincpu")
/* video hardware */
MCFG_SCREEN_ADD("screen", RASTER)
@@ -464,8 +593,8 @@ static MACHINE_CONFIG_START( airraid, cshooter_state )
MCFG_SCREEN_PALETTE("palette")
MCFG_GFXDECODE_ADD("gfxdecode", "palette", cshooter)
- MCFG_PALETTE_ADD("palette", 0x100)
- MCFG_PALETTE_INDIRECT_ENTRIES(0x100)
+ MCFG_PALETTE_ADD("palette", 0x200)
+ MCFG_PALETTE_INDIRECT_ENTRIES(0x200)
MCFG_PALETTE_INIT_OWNER(cshooter_state, cshooter)
/* sound hardware */
@@ -473,6 +602,12 @@ static MACHINE_CONFIG_START( airraid, cshooter_state )
MACHINE_CONFIG_END
+static MACHINE_CONFIG_DERIVED( airraid_crypt, airraid )
+ MCFG_CPU_MODIFY("maincpu")
+ MCFG_CPU_DECRYPTED_OPCODES_MAP(decrypted_opcodes_map)
+MACHINE_CONFIG_END
+
+
@@ -513,28 +648,51 @@ ROM_START( cshootere )
ROM_REGION( 0x10000, "maincpu", 0 ) // Main CPU
ROM_LOAD( "1.k19", 0x00000, 0x08000, CRC(71418952) SHA1(9745ca006576381c9e9595d8e42ab276bab80a41) )
- ROM_REGION( 0x10000, "audiocpu", 0 ) // Sub/Sound CPU
+ ROM_REGION( 0x10000, "user1", 0 ) // cpu data
+ ROM_LOAD( "2.k20", 0x00000, 0x10000, CRC(5812fe72) SHA1(3b28bff6b62a411d2195bb228952db62ad32ef3d) )
+
+ ROM_REGION( 0x18000, "audiocpu", 0 ) // Sub/Sound CPU
ROM_LOAD( "5.6f", 0x00000, 0x02000, CRC(30be398c) SHA1(6c61200ee8888d6270c8cec50423b3b5602c2027) ) // 5.g6
- ROM_LOAD( "4.7f", 0x08000, 0x08000, CRC(3cd715b4) SHA1(da735fb5d262908ddf7ed7dacdea68899f1723ff) ) // 4.g8
+ ROM_LOAD( "4.7f", 0x10000, 0x08000, CRC(3cd715b4) SHA1(da735fb5d262908ddf7ed7dacdea68899f1723ff) ) // 4.g8
- ROM_REGION( 0x02000, "gfx1", 0 ) // TX Layer
+ ROM_REGION( 0x02000, "tx_gfx", 0 ) // TX Layer
ROM_LOAD( "3.f11", 0x00000, 0x02000, CRC(67b50a47) SHA1(b1f4aefc9437edbeefba5371149cc08c0b55c741) )
- ROM_REGION( 0x20000, "gfx2", 0 ) // tiles
- ROM_LOAD( "graphics1.bin", 0x00000, 0x10000, NO_DUMP )
- ROM_LOAD( "graphics2.bin", 0x10000, 0x10000, NO_DUMP )
-
- ROM_REGION( 0x10000, "gfx3", 0 ) // sprites
- ROM_LOAD( "graphics3.bin", 0x00000, 0x10000, NO_DUMP )
-
- ROM_REGION( 0x10000, "user1", 0 ) // Tilemaps
- ROM_LOAD( "2.k20", 0x00000, 0x10000, CRC(5812fe72) SHA1(3b28bff6b62a411d2195bb228952db62ad32ef3d) )
- ROM_REGION( 0x320, "proms", 0 ) // taken from parent set
+ ROM_REGION( 0x100, "tx_clut", 0 ) // taken from parent set (need proper IC locations for this PCB type)
ROM_LOAD( "63s281.16a", 0x0000, 0x0100, CRC(0b8b914b) SHA1(8cf4910b846de79661cc187887171ed8ebfd6719) ) // clut
- ROM_LOAD( "82s123.7a", 0x0100, 0x0020, CRC(93e2d292) SHA1(af8edd0cfe85f28ede9604cfaf4516d54e5277c9) ) // sprite color related? (not used)
- ROM_LOAD( "82s129.9s", 0x0120, 0x0100, CRC(cf14ba30) SHA1(3284b6809075756b3c8e07d9705fc7eacb7556f1) ) // timing? (not used)
- ROM_LOAD( "82s129.4e", 0x0220, 0x0100, CRC(0eaf5158) SHA1(bafd4108708f66cd7b280e47152b108f3e254fc9) ) // timing? (not used)
+
+ ROM_REGION( 0x220, "proms", 0 ) // taken from parent set (need proper IC locations for this PCB type)
+ ROM_LOAD( "82s123.7a", 0x0000, 0x0020, CRC(93e2d292) SHA1(af8edd0cfe85f28ede9604cfaf4516d54e5277c9) ) // sprite color related? (not used)
+ ROM_LOAD( "82s129.9s", 0x0020, 0x0100, CRC(cf14ba30) SHA1(3284b6809075756b3c8e07d9705fc7eacb7556f1) ) // timing? (not used)
+ ROM_LOAD( "82s129.4e", 0x0120, 0x0100, CRC(0eaf5158) SHA1(bafd4108708f66cd7b280e47152b108f3e254fc9) ) // timing? (not used)
+
+ /* ### MODULE 1 ### Background generation / graphics */
+ ROM_REGION( 0x40000, "bg_map", 0 )
+ ROM_LOAD16_BYTE( "bg_layouts_even", 0x00000, 0x20000, NO_DUMP )
+ ROM_LOAD16_BYTE( "bg_layouts_odd", 0x00001, 0x20000, NO_DUMP )
+ ROM_REGION( 0x40000, "bg_gfx", 0 )
+ ROM_LOAD16_BYTE( "bg_tiles_even", 0x00000, 0x20000, NO_DUMP )
+ ROM_LOAD16_BYTE( "bg_tiles_odd", 0x00001, 0x20000, NO_DUMP )
+ ROM_REGION( 0x100, "bg_clut", 0 )
+ ROM_LOAD( "bg_clut", 0x000, 0x100, NO_DUMP )
+
+ /* ### MODULE 2 ### Foreground generation / graphics */
+ ROM_REGION( 0x40000, "fg_map", 0 )
+ ROM_LOAD16_BYTE( "fg_layouts_even", 0x00000, 0x20000, NO_DUMP )
+ ROM_LOAD16_BYTE( "fg_layouts_odd", 0x00001, 0x20000, NO_DUMP )
+ ROM_REGION( 0x40000, "fg_gfx", 0 )
+ ROM_LOAD16_BYTE( "fg_tiles_even", 0x00000, 0x20000, NO_DUMP )
+ ROM_LOAD16_BYTE( "fg_tiles_odd", 0x00001, 0x20000, NO_DUMP )
+ ROM_REGION( 0x100, "fg_clut", 0 )
+ ROM_LOAD( "fg_clut", 0x000, 0x100, NO_DUMP )
+
+ /* ### MODULE 3 ### Sprite graphics */
+ ROM_REGION( 0x40000, "spr_gfx", 0 )
+ ROM_LOAD16_BYTE( "sprite_tiles_even", 0x00000, 0x20000, NO_DUMP )
+ ROM_LOAD16_BYTE( "sprite_tiles_odd", 0x00001, 0x20000, NO_DUMP )
+ ROM_REGION( 0x100, "spr_clut", 0 )
+ ROM_LOAD( "spr_clut", 0x000, 0x100, NO_DUMP )
ROM_END
/*
@@ -563,43 +721,59 @@ ROM_START( airraid )
ROM_REGION( 0x10000, "maincpu", 0 ) // Main CPU
ROM_LOAD( "1.16j", 0x00000, 0x08000, CRC(7ac2cedf) SHA1(272831f51a2731e067b5aec6dba6bddd3c5350c9) )
- ROM_REGION( 0x10000, "audiocpu", 0 ) // Sub/Sound CPU
+ ROM_REGION( 0x10000, "user1", 0 ) // cpu data
+ ROM_LOAD( "2.19j", 0x00000, 0x10000, CRC(842ae6c2) SHA1(0468445e4ab6f42bac786f9a258df3972fd1fde9) )
+
+ ROM_REGION( 0x18000, "audiocpu", 0 ) // Sub/Sound CPU
ROM_LOAD( "5.6f", 0x00000, 0x02000, CRC(30be398c) SHA1(6c61200ee8888d6270c8cec50423b3b5602c2027) )
- ROM_LOAD( "4.7f", 0x08000, 0x08000, CRC(3cd715b4) SHA1(da735fb5d262908ddf7ed7dacdea68899f1723ff) )
+ ROM_LOAD( "4.7f", 0x10000, 0x08000, CRC(3cd715b4) SHA1(da735fb5d262908ddf7ed7dacdea68899f1723ff) )
- ROM_REGION( 0x02000, "gfx1", 0 ) // TX Layer
+ ROM_REGION( 0x02000, "tx_gfx", 0 ) // TX Layer
ROM_LOAD( "3.13e", 0x00000, 0x02000, CRC(672ec0e8) SHA1(a11cd90d6494251ceee3bc7c72f4e7b1580b77e2) )
- ROM_REGION( 0x20000, "gfx2", 0 ) // tiles
- ROM_LOAD( "graphics1.bin", 0x00000, 0x10000, NO_DUMP )
- ROM_LOAD( "graphics2.bin", 0x10000, 0x10000, NO_DUMP )
+ ROM_REGION( 0x100, "tx_clut", 0 ) // taken from parent set (need proper IC locations for this PCB type)
+ ROM_LOAD( "63s281.16a", 0x0000, 0x0100, CRC(0b8b914b) SHA1(8cf4910b846de79661cc187887171ed8ebfd6719) ) // clut
- ROM_REGION( 0x10000, "gfx3", 0 ) // sprites
- ROM_LOAD( "graphics3.bin", 0x00000, 0x10000, NO_DUMP )
+ ROM_REGION( 0x220, "proms", 0 ) // taken from parent set (need proper IC locations for this PCB type)
+ ROM_LOAD( "82s123.7a", 0x0000, 0x0020, CRC(93e2d292) SHA1(af8edd0cfe85f28ede9604cfaf4516d54e5277c9) ) // sprite color related? (not used)
+ ROM_LOAD( "82s129.9s", 0x0020, 0x0100, CRC(cf14ba30) SHA1(3284b6809075756b3c8e07d9705fc7eacb7556f1) ) // timing? (not used)
+ ROM_LOAD( "82s129.4e", 0x0120, 0x0100, CRC(0eaf5158) SHA1(bafd4108708f66cd7b280e47152b108f3e254fc9) ) // timing? (not used)
+
+ /* ### MODULE 1 ### Background generation / graphics */
+ ROM_REGION( 0x40000, "bg_map", 0 )
+ ROM_LOAD16_BYTE( "bg_layouts_even", 0x00000, 0x20000, NO_DUMP )
+ ROM_LOAD16_BYTE( "bg_layouts_odd", 0x00001, 0x20000, NO_DUMP )
+ ROM_REGION( 0x40000, "bg_gfx", 0 )
+ ROM_LOAD16_BYTE( "bg_tiles_even", 0x00000, 0x20000, NO_DUMP )
+ ROM_LOAD16_BYTE( "bg_tiles_odd", 0x00001, 0x20000, NO_DUMP )
+ ROM_REGION( 0x100, "bg_clut", 0 )
+ ROM_LOAD( "bg_clut", 0x000, 0x100, NO_DUMP )
+
+ /* ### MODULE 2 ### Foreground generation / graphics */
+ ROM_REGION( 0x40000, "fg_map", 0 )
+ ROM_LOAD16_BYTE( "fg_layouts_even", 0x00000, 0x20000, NO_DUMP )
+ ROM_LOAD16_BYTE( "fg_layouts_odd", 0x00001, 0x20000, NO_DUMP )
+ ROM_REGION( 0x40000, "fg_gfx", 0 )
+ ROM_LOAD16_BYTE( "fg_tiles_even", 0x00000, 0x20000, NO_DUMP )
+ ROM_LOAD16_BYTE( "fg_tiles_odd", 0x00001, 0x20000, NO_DUMP )
+ ROM_REGION( 0x100, "fg_clut", 0 )
+ ROM_LOAD( "fg_clut", 0x000, 0x100, NO_DUMP )
+
+ /* ### MODULE 3 ### Sprite graphics */
+ ROM_REGION( 0x40000, "spr_gfx", 0 )
+ ROM_LOAD16_BYTE( "sprite_tiles_even", 0x00000, 0x20000, NO_DUMP )
+ ROM_LOAD16_BYTE( "sprite_tiles_odd", 0x00001, 0x20000, NO_DUMP )
+ ROM_REGION( 0x100, "spr_clut", 0 )
+ ROM_LOAD( "spr_clut", 0x000, 0x100, NO_DUMP )
+ROM_END
- ROM_REGION( 0x10000, "user1", 0 ) // bg maps
- ROM_LOAD( "2.19j", 0x00000, 0x10000, CRC(842ae6c2) SHA1(0468445e4ab6f42bac786f9a258df3972fd1fde9) )
- ROM_REGION( 0x320, "proms", 0 ) // taken from parent set
- ROM_LOAD( "63s281.16a", 0x0000, 0x0100, CRC(0b8b914b) SHA1(8cf4910b846de79661cc187887171ed8ebfd6719) ) // clut
- ROM_LOAD( "82s123.7a", 0x0100, 0x0020, CRC(93e2d292) SHA1(af8edd0cfe85f28ede9604cfaf4516d54e5277c9) ) // sprite color related? (not used)
- ROM_LOAD( "82s129.9s", 0x0120, 0x0100, CRC(cf14ba30) SHA1(3284b6809075756b3c8e07d9705fc7eacb7556f1) ) // timing? (not used)
- ROM_LOAD( "82s129.4e", 0x0220, 0x0100, CRC(0eaf5158) SHA1(bafd4108708f66cd7b280e47152b108f3e254fc9) ) // timing? (not used)
-ROM_END
-#if 0
-DRIVER_INIT_MEMBER(cshooter_state,cshooter)
+DRIVER_INIT_MEMBER(cshooter_state, cshooter)
{
- /* temp so it boots */
- UINT8 *rom = memregion("maincpu")->base();
-
- rom[0xa2] = 0x00;
- rom[0xa3] = 0x00;
- rom[0xa4] = 0x00;
- membank("bank1")->set_base(&memregion("user1")->base()[0]);
+ membank("bank1")->configure_entries(0, 4, memregion("user1")->base(), 0x4000);
}
-#endif
DRIVER_INIT_MEMBER(cshooter_state,cshootere)
{
@@ -630,11 +804,12 @@ DRIVER_INIT_MEMBER(cshooter_state,cshootere)
rom[A] = BITSWAP8(rom[A],7,6,1,4,3,2,5,0);
}
- membank("bank1")->configure_entries(0, 4, memregion("user1")->base(), 0x4000);
+ DRIVER_INIT_CALL(cshooter);
+
}
-GAME( 1987, cshootere, cshooter, airraid, airraid, cshooter_state, cshootere, ROT270, "Seibu Kaihatsu (J.K.H. license)", "Cross Shooter (encrypted)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_NOT_WORKING )
-GAME( 1987, airraid, cshooter, airraid, airraid, cshooter_state, cshootere, ROT270, "Seibu Kaihatsu", "Air Raid (encrypted)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_NOT_WORKING )
+GAME( 1987, cshootere, cshooter, airraid_crypt, airraid, cshooter_state, cshootere, ROT270, "Seibu Kaihatsu (J.K.H. license)", "Cross Shooter (Single PCB)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_NOT_WORKING )
+GAME( 1987, airraid, cshooter, airraid_crypt, airraid, cshooter_state, cshootere, ROT270, "Seibu Kaihatsu", "Air Raid (Single PCB)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_NOT_WORKING )
// There's also an undumped International Games version
diff --git a/src/mame/drivers/fidel6502.cpp b/src/mame/drivers/fidel6502.cpp
index 75edef3a3c6..18f152899fd 100644
--- a/src/mame/drivers/fidel6502.cpp
+++ b/src/mame/drivers/fidel6502.cpp
@@ -1,5 +1,6 @@
// license:BSD-3-Clause
// copyright-holders:Kevin Horton,Jonathan Gevaryahu,Sandro Ronco,hap
+// thanks-to:Berger
/******************************************************************************
Fidelity Electronics 6502 based board driver
@@ -140,7 +141,22 @@ All three of the above are called "segment H".
******************************************************************************
-Sensory Chess Challenger (SC12-B, 6086)
+Sensory Chess Challenger "9" (SC9)
+2 versions were available, the newer version was 2MHz and included the Budapest program.
+---------------------------------
+
+8*(8+1) buttons, 8*8+1 LEDs
+36-pin edge connector, assume same as SC12
+4KB RAM(TMM2016P), 2*8KB ROM(HN48364P)
+R6502-13, 1.4MHz from resonator
+PCB label 510-1045C01 2-1-82
+
+I/O is via TTL, not further documented here
+
+
+******************************************************************************
+
+Sensory 12 Chess Challenger (SC12-B, 6086)
4 versions are known to exist: A,B,C, and X, with increasing CPU speed.
---------------------------------
RE information from netlist by Berger
@@ -156,7 +172,7 @@ NE556 dual-timer IC:
Memory map:
-----------
-6000-0FFF: 4K RAM (2016 * 2)
+0000-0FFF: 4K RAM (2016 * 2)
2000-5FFF: cartridge
6000-7FFF: control(W)
8000-9FFF: 8K ROM SSS SCM23C65E4
@@ -271,6 +287,7 @@ Z80 D6 to W: (model 6092, tied to VCC otherwise)
// internal artwork
#include "fidel_csc.lh" // clickable
#include "fidel_fev.lh" // clickable
+#include "fidel_sc9.lh" // clickable
#include "fidel_sc12.lh" // clickable
@@ -305,6 +322,12 @@ public:
DECLARE_READ_LINE_MEMBER(csc_pia1_ca1_r);
DECLARE_READ_LINE_MEMBER(csc_pia1_cb1_r);
+ // SC9
+ void sc9_prepare_display();
+ DECLARE_WRITE8_MEMBER(sc9_control_w);
+ DECLARE_WRITE8_MEMBER(sc9_led_w);
+ DECLARE_READ8_MEMBER(sc9_input_r);
+
// SC12/6086
DECLARE_WRITE8_MEMBER(sc12_control_w);
DECLARE_READ8_MEMBER(sc12_input_r);
@@ -452,10 +475,50 @@ WRITE_LINE_MEMBER(fidel6502_state::csc_pia1_ca2_w)
/******************************************************************************
- SC12/6086
+ SC9
******************************************************************************/
+// TTL/generic
+
+void fidel6502_state::sc9_prepare_display()
+{
+ // 8*8 chessboard leds + 1 corner led
+ display_matrix(8, 9, m_led_data, m_inp_mux);
+}
+
+WRITE8_MEMBER(fidel6502_state::sc9_control_w)
+{
+ // d0-d3: 74245 P0-P3
+ // 74245 Q0-Q8: input mux, led select
+ UINT16 sel = 1 << (data & 0xf) & 0x3ff;
+ m_inp_mux = sel & 0x1ff;
+ sc9_prepare_display();
+
+ // 74245 Q9: speaker out
+ m_speaker->level_w(sel >> 9 & 1);
+
+ // d4,d5: ?
+ // d6,d7: N/C
+}
+WRITE8_MEMBER(fidel6502_state::sc9_led_w)
+{
+ // a0-a2,d0: led data via NE591N
+ m_led_data = (data & 1) << offset;
+ sc9_prepare_display();
+}
+
+READ8_MEMBER(fidel6502_state::sc9_input_r)
+{
+ // multiplexed inputs (active low)
+ return read_inputs(9) ^ 0xff;
+}
+
+
+
+/******************************************************************************
+ SC12/6086
+******************************************************************************/
// TTL/generic
@@ -590,6 +653,19 @@ static ADDRESS_MAP_START( csc_map, AS_PROGRAM, 8, fidel6502_state )
ADDRESS_MAP_END
+// SC9
+
+static ADDRESS_MAP_START( sc9_map, AS_PROGRAM, 8, fidel6502_state )
+ ADDRESS_MAP_UNMAP_HIGH
+ AM_RANGE(0x0000, 0x07ff) AM_MIRROR(0x1800) AM_RAM
+ AM_RANGE(0x2000, 0x5fff) AM_READ(sc12_cart_r)
+ AM_RANGE(0x6000, 0x6000) AM_MIRROR(0x1fff) AM_WRITE(sc9_control_w)
+ AM_RANGE(0x8000, 0x8007) AM_MIRROR(0x1ff8) AM_WRITE(sc9_led_w) AM_READNOP
+ AM_RANGE(0xa000, 0xa000) AM_MIRROR(0x1fff) AM_READ(sc9_input_r)
+ AM_RANGE(0xc000, 0xffff) AM_ROM
+ADDRESS_MAP_END
+
+
// SC12/6086
static ADDRESS_MAP_START( sc12_map, AS_PROGRAM, 8, fidel6502_state )
@@ -826,6 +902,28 @@ static MACHINE_CONFIG_START( csc, fidel6502_state )
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.25)
MACHINE_CONFIG_END
+static MACHINE_CONFIG_START( sc9, fidel6502_state )
+
+ /* basic machine hardware */
+ MCFG_CPU_ADD("maincpu", M6502, 1400000) // from ceramic resonator "681 JSA", measured
+ MCFG_CPU_PROGRAM_MAP(sc9_map)
+ MCFG_CPU_PERIODIC_INT_DRIVER(fidelz80base_state, irq0_line_hold, 600) // 555 timer, guessed
+
+ MCFG_TIMER_DRIVER_ADD_PERIODIC("display_decay", fidelz80base_state, display_decay_tick, attotime::from_msec(1))
+ MCFG_DEFAULT_LAYOUT(layout_fidel_sc9)
+
+ /* sound hardware */
+ MCFG_SPEAKER_STANDARD_MONO("mono")
+ MCFG_SOUND_ADD("speaker", SPEAKER_SOUND, 0)
+ MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.25)
+
+ /* cartridge */
+ MCFG_GENERIC_CARTSLOT_ADD("cartslot", generic_plain_slot, "fidel_scc")
+ MCFG_GENERIC_EXTENSIONS("bin,dat")
+ MCFG_GENERIC_LOAD(fidelz80base_state, scc_cartridge)
+ MCFG_SOFTWARE_LIST_ADD("cart_list", "fidel_scc")
+MACHINE_CONFIG_END
+
static MACHINE_CONFIG_START( sc12, fidel6502_state )
/* basic machine hardware */
@@ -932,6 +1030,13 @@ ROM_START( cscfr )
ROM_END
+ROM_START( fscc9 )
+ ROM_REGION( 0x10000, "maincpu", 0 )
+ ROM_LOAD("b30", 0xc000, 0x2000, CRC(b845c458) SHA1(d3fda65dbd9fae44fa4b93f8207839d8fa0c367a) ) // HN48364P
+ ROM_LOAD("b31", 0xe000, 0x2000, CRC(cbaf97d7) SHA1(7ed8e68bb74713d9e2ff1d9c037012320b7bfcbf) ) // "
+ROM_END
+
+
ROM_START( fscc12 )
ROM_REGION( 0x10000, "maincpu", 0 )
ROM_LOAD("101-1068a01", 0x8000, 0x2000, CRC(63c76cdd) SHA1(e0771c98d4483a6b1620791cb99a7e46b0db95c4) ) // SSS SCM23C65E4
@@ -965,6 +1070,7 @@ CONS( 1981, cscsp, csc, 0, csc, cscg, driver_device, 0, "Fideli
CONS( 1981, cscg, csc, 0, csc, cscg, driver_device, 0, "Fidelity Electronics", "Champion Sensory Chess Challenger (German)", MACHINE_SUPPORTS_SAVE | MACHINE_CLICKABLE_ARTWORK )
CONS( 1981, cscfr, csc, 0, csc, cscg, driver_device, 0, "Fidelity Electronics", "Champion Sensory Chess Challenger (French)", MACHINE_SUPPORTS_SAVE | MACHINE_CLICKABLE_ARTWORK )
+CONS( 1982, fscc9, 0, 0, sc9, sc12, driver_device, 0, "Fidelity Electronics", "Sensory Chess Challenger 9", MACHINE_SUPPORTS_SAVE | MACHINE_CLICKABLE_ARTWORK )
CONS( 1984, fscc12, 0, 0, sc12, sc12, driver_device, 0, "Fidelity Electronics", "Sensory Chess Challenger 12-B", MACHINE_SUPPORTS_SAVE | MACHINE_CLICKABLE_ARTWORK )
CONS( 1987, fexcel, 0, 0, fexcel, fexcel, driver_device, 0, "Fidelity Electronics", "Excellence (model 6080/6093)", MACHINE_SUPPORTS_SAVE | MACHINE_CLICKABLE_ARTWORK )
diff --git a/src/mame/drivers/fidel68k.cpp b/src/mame/drivers/fidel68k.cpp
index fcf546c8964..d1239636236 100644
--- a/src/mame/drivers/fidel68k.cpp
+++ b/src/mame/drivers/fidel68k.cpp
@@ -1,5 +1,6 @@
// license:BSD-3-Clause
// copyright-holders:hap
+// thanks-to:Berger
/******************************************************************************
Fidelity Electronics 68000 based board driver
@@ -453,9 +454,9 @@ ROM_END
ROM_START( feagv11 )
ROM_REGION( 0x20000, "maincpu", 0 )
ROM_LOAD32_BYTE("16", 0x00000, 0x08000, CRC(8375d61f) SHA1(e042f6f01480c59ee09a458cf34f135664479824) ) // 27c256
+ ROM_LOAD32_BYTE("17", 0x00001, 0x08000, CRC(bfd14916) SHA1(115af6dfd29ddd8ad6d2ce390f8ecc4d60de6fce) ) // "
ROM_LOAD32_BYTE("18", 0x00002, 0x08000, CRC(9341dcaf) SHA1(686bd4799e89ffaf11a813d4cf5a2aedd4c2d97a) ) // "
ROM_LOAD32_BYTE("19", 0x00003, 0x08000, CRC(a70c5468) SHA1(7f6b4f46577d5cfdaa84d387c7ce35d941e5bbc7) ) // "
- ROM_LOAD32_BYTE("17", 0x00001, 0x08000, CRC(bfd14916) SHA1(115af6dfd29ddd8ad6d2ce390f8ecc4d60de6fce) ) // "
ROM_END
#define rom_feagv10 rom_feagv11
diff --git a/src/mame/drivers/fidelz80.cpp b/src/mame/drivers/fidelz80.cpp
index 31568a6f601..34c06fd105e 100644
--- a/src/mame/drivers/fidelz80.cpp
+++ b/src/mame/drivers/fidelz80.cpp
@@ -1,5 +1,6 @@
// license:BSD-3-Clause
// copyright-holders:Kevin Horton,Jonathan Gevaryahu,Sandro Ronco,hap
+// thanks-to:Berger
/******************************************************************************
Fidelity Electronics Z80 based board driver
diff --git a/src/mame/drivers/harddriv.cpp b/src/mame/drivers/harddriv.cpp
index d895bedb7ff..4d57c28a3c7 100644
--- a/src/mame/drivers/harddriv.cpp
+++ b/src/mame/drivers/harddriv.cpp
@@ -4086,13 +4086,13 @@ ROM_START( racedrivpan )
ROM_LOAD16_BYTE( "088-1016.bin", 0x0e0000, 0x010000, CRC(e83a9c99) SHA1(1d4093902133bb6da981f294e6947544c3564393) ) // == 136077-1016.200y
ROM_LOAD16_BYTE( "088-1015.bin", 0x0e0001, 0x010000, CRC(725806f3) SHA1(0fa4601465dc94f27c71db789ad625bbcd254169) ) // == 136077-4015.210y
- ROM_REGION( 0x60000, "mainpcb:user1", 0 ) /* 384k for object ROM */
- ROM_LOAD16_BYTE( "088-1017.bin", 0x00000, 0x10000, CRC(d92251e8) SHA1(deeeec54c4a61c3adf62f6b1b910135559090ee5) )
- ROM_LOAD16_BYTE( "088-1018.bin", 0x00001, 0x10000, CRC(11a0a8f5) SHA1(d4ccc83fc99331d741bc9b8027ef20d72e3ad71a) )
- ROM_LOAD16_BYTE( "088-1019.bin", 0x20000, 0x10000, CRC(5bb00676) SHA1(cad1cea8e43f9590fc71c00fab4eff0d447f9296) ) // == 136091-0019.2k (strtdriv)
- ROM_LOAD16_BYTE( "088-1020.bin", 0x20001, 0x10000, CRC(311cef99) SHA1(9c466aabad7e80581e477253ec6f2fd245f9b9fd) ) // == 136091-0020.2r (strtdriv)
- ROM_LOAD16_BYTE( "088-1021.bin", 0x40000, 0x10000, CRC(ce8e4886) SHA1(d29cd4761deb80ed179d0e503243739eebc0edb4) )
- ROM_LOAD16_BYTE( "088-1022.bin", 0x40001, 0x10000, CRC(4f1e1c5d) SHA1(3e72813129cae9e9bf084bfb1b747aa46b92591e) )
+ ROM_REGION16_BE( 0x60000, "mainpcb:user1", 0 ) /* 384k for object ROM */
+ ROM_LOAD16_BYTE( "088-1018.bin", 0x00000, 0x10000, CRC(11a0a8f5) SHA1(d4ccc83fc99331d741bc9b8027ef20d72e3ad71a) )
+ ROM_LOAD16_BYTE( "088-1017.bin", 0x00001, 0x10000, CRC(d92251e8) SHA1(deeeec54c4a61c3adf62f6b1b910135559090ee5) )
+ ROM_LOAD16_BYTE( "088-1020.bin", 0x20000, 0x10000, CRC(311cef99) SHA1(9c466aabad7e80581e477253ec6f2fd245f9b9fd) ) // == 136091-0020.2r (strtdriv)
+ ROM_LOAD16_BYTE( "088-1019.bin", 0x20001, 0x10000, CRC(5bb00676) SHA1(cad1cea8e43f9590fc71c00fab4eff0d447f9296) ) // == 136091-0019.2k (strtdriv)
+ ROM_LOAD16_BYTE( "088-1022.bin", 0x40000, 0x10000, CRC(4f1e1c5d) SHA1(3e72813129cae9e9bf084bfb1b747aa46b92591e) )
+ ROM_LOAD16_BYTE( "088-1021.bin", 0x40001, 0x10000, CRC(ce8e4886) SHA1(d29cd4761deb80ed179d0e503243739eebc0edb4) )
/* ----------------------- */
@@ -4142,13 +4142,13 @@ ROM_START( racedrivpan )
ROM_LOAD16_BYTE( "088-2016.bin", 0x0e0000, 0x010000, CRC(6a42b7e2) SHA1(2e0ff4b7e391106a976cb872f6311f6d35dca5b0) )
ROM_LOAD16_BYTE( "088-2015.bin", 0x0e0001, 0x010000, CRC(334e2a3b) SHA1(a19bfa7652845b9453c722091c773819ba248569) )
- ROM_REGION( 0x60000, "leftpcb:user1", 0 ) /* 384k for object ROM */
- ROM_LOAD16_BYTE( "088-1017.bin", 0x00000, 0x10000, CRC(d92251e8) SHA1(deeeec54c4a61c3adf62f6b1b910135559090ee5) )
- ROM_LOAD16_BYTE( "088-1018.bin", 0x00001, 0x10000, CRC(11a0a8f5) SHA1(d4ccc83fc99331d741bc9b8027ef20d72e3ad71a) )
- ROM_LOAD16_BYTE( "088-1019.bin", 0x20000, 0x10000, CRC(5bb00676) SHA1(cad1cea8e43f9590fc71c00fab4eff0d447f9296) ) // == 136091-0019.2k (strtdriv)
- ROM_LOAD16_BYTE( "088-1020.bin", 0x20001, 0x10000, CRC(311cef99) SHA1(9c466aabad7e80581e477253ec6f2fd245f9b9fd) ) // == 136091-0020.2r (strtdriv)
- ROM_LOAD16_BYTE( "088-1021.bin", 0x40000, 0x10000, CRC(ce8e4886) SHA1(d29cd4761deb80ed179d0e503243739eebc0edb4) )
- ROM_LOAD16_BYTE( "088-1022.bin", 0x40001, 0x10000, CRC(4f1e1c5d) SHA1(3e72813129cae9e9bf084bfb1b747aa46b92591e) )
+ ROM_REGION16_BE( 0x60000, "leftpcb:user1", 0 ) /* 384k for object ROM */
+ ROM_LOAD16_BYTE( "088-1018.bin", 0x00000, 0x10000, CRC(11a0a8f5) SHA1(d4ccc83fc99331d741bc9b8027ef20d72e3ad71a) )
+ ROM_LOAD16_BYTE( "088-1017.bin", 0x00001, 0x10000, CRC(d92251e8) SHA1(deeeec54c4a61c3adf62f6b1b910135559090ee5) )
+ ROM_LOAD16_BYTE( "088-1020.bin", 0x20000, 0x10000, CRC(311cef99) SHA1(9c466aabad7e80581e477253ec6f2fd245f9b9fd) ) // == 136091-0020.2r (strtdriv)
+ ROM_LOAD16_BYTE( "088-1019.bin", 0x20001, 0x10000, CRC(5bb00676) SHA1(cad1cea8e43f9590fc71c00fab4eff0d447f9296) ) // == 136091-0019.2k (strtdriv)
+ ROM_LOAD16_BYTE( "088-1022.bin", 0x40000, 0x10000, CRC(4f1e1c5d) SHA1(3e72813129cae9e9bf084bfb1b747aa46b92591e) )
+ ROM_LOAD16_BYTE( "088-1021.bin", 0x40001, 0x10000, CRC(ce8e4886) SHA1(d29cd4761deb80ed179d0e503243739eebc0edb4) )
ROM_REGION( 0x800, "leftpcb:200e", 0 ) // set to display left monitor, controls not calibrated with valid values (don't think they need to be)
ROM_LOAD( "leftpcb_200e", 0x000000, 0x000800, CRC(a618d02e) SHA1(cc1068fe4f6ec9a26b6e8fdbe05f4364a64559c1) )
@@ -4174,13 +4174,13 @@ ROM_START( racedrivpan )
ROM_LOAD16_BYTE( "088-2016.bin", 0x0e0000, 0x010000, CRC(6a42b7e2) SHA1(2e0ff4b7e391106a976cb872f6311f6d35dca5b0) )
ROM_LOAD16_BYTE( "088-2015.bin", 0x0e0001, 0x010000, CRC(334e2a3b) SHA1(a19bfa7652845b9453c722091c773819ba248569) )
- ROM_REGION( 0x60000, "rightpcb:user1", 0 ) /* 384k for object ROM */
- ROM_LOAD16_BYTE( "088-1017.bin", 0x00000, 0x10000, CRC(d92251e8) SHA1(deeeec54c4a61c3adf62f6b1b910135559090ee5) )
- ROM_LOAD16_BYTE( "088-1018.bin", 0x00001, 0x10000, CRC(11a0a8f5) SHA1(d4ccc83fc99331d741bc9b8027ef20d72e3ad71a) )
- ROM_LOAD16_BYTE( "088-1019.bin", 0x20000, 0x10000, CRC(5bb00676) SHA1(cad1cea8e43f9590fc71c00fab4eff0d447f9296) ) // == 136091-0019.2k (strtdriv)
- ROM_LOAD16_BYTE( "088-1020.bin", 0x20001, 0x10000, CRC(311cef99) SHA1(9c466aabad7e80581e477253ec6f2fd245f9b9fd) ) // == 136091-0020.2r (strtdriv)
- ROM_LOAD16_BYTE( "088-1021.bin", 0x40000, 0x10000, CRC(ce8e4886) SHA1(d29cd4761deb80ed179d0e503243739eebc0edb4) )
- ROM_LOAD16_BYTE( "088-1022.bin", 0x40001, 0x10000, CRC(4f1e1c5d) SHA1(3e72813129cae9e9bf084bfb1b747aa46b92591e) )
+ ROM_REGION16_BE( 0x60000, "rightpcb:user1", 0 ) /* 384k for object ROM */
+ ROM_LOAD16_BYTE( "088-1018.bin", 0x00000, 0x10000, CRC(11a0a8f5) SHA1(d4ccc83fc99331d741bc9b8027ef20d72e3ad71a) )
+ ROM_LOAD16_BYTE( "088-1017.bin", 0x00001, 0x10000, CRC(d92251e8) SHA1(deeeec54c4a61c3adf62f6b1b910135559090ee5) )
+ ROM_LOAD16_BYTE( "088-1020.bin", 0x20000, 0x10000, CRC(311cef99) SHA1(9c466aabad7e80581e477253ec6f2fd245f9b9fd) ) // == 136091-0020.2r (strtdriv)
+ ROM_LOAD16_BYTE( "088-1019.bin", 0x20001, 0x10000, CRC(5bb00676) SHA1(cad1cea8e43f9590fc71c00fab4eff0d447f9296) ) // == 136091-0019.2k (strtdriv)
+ ROM_LOAD16_BYTE( "088-1022.bin", 0x40000, 0x10000, CRC(4f1e1c5d) SHA1(3e72813129cae9e9bf084bfb1b747aa46b92591e) )
+ ROM_LOAD16_BYTE( "088-1021.bin", 0x40001, 0x10000, CRC(ce8e4886) SHA1(d29cd4761deb80ed179d0e503243739eebc0edb4) )
ROM_REGION( 0x800, "rightpcb:200e", 0 ) // set to display right monitor, controls not calibrated with valid values (don't think they need to be)
ROM_LOAD( "rightpcb_200e", 0x000000, 0x000800, CRC(6f1b7094) SHA1(6194a5b99aebe43f02c8d267290207b32c5bdbbd) )
@@ -4463,13 +4463,13 @@ ROM_START( strtdriv )
ROM_REGION( 0x10000 + 0x10000, "mainpcb:asic65:asic65cpu", 0 ) /* dummy region for ADSP 2105 */
ROM_LOAD( "136091-0033.10j", 0x000000, 0x010000, CRC(57504ab6) SHA1(ec8361b7da964c07ca0da48a87537badc3986fe0) )
- ROM_REGION( 0x60000, "mainpcb:user1", 0 ) /* 384k for object ROM */
- ROM_LOAD16_BYTE( "136091-0017.2lm", 0x00000, 0x10000, CRC(b0454074) SHA1(9530ea1ef215116da1f0843776fa7a6b4637049d) )
- ROM_LOAD16_BYTE( "136091-0018.2t", 0x00001, 0x10000, CRC(ef432aa8) SHA1(56bce13c111db7874c9b669d479f6ef47976ee14) )
- ROM_LOAD16_BYTE( "136091-0019.2k", 0x20000, 0x10000, CRC(5bb00676) SHA1(cad1cea8e43f9590fc71c00fab4eff0d447f9296) )
- ROM_LOAD16_BYTE( "136091-0020.2r", 0x20001, 0x10000, CRC(311cef99) SHA1(9c466aabad7e80581e477253ec6f2fd245f9b9fd) )
- ROM_LOAD16_BYTE( "136091-0021.2j", 0x40000, 0x10000, CRC(14f2caae) SHA1(ff40dbced58dc910a2b5825b846a5e52933cb8fc) )
- ROM_LOAD16_BYTE( "136091-0022.2p", 0x40001, 0x10000, CRC(bc4dd071) SHA1(ca182451a0a18d343dce1be56090d51950d43906) )
+ ROM_REGION16_BE( 0x60000, "mainpcb:user1", 0 ) /* 384k for object ROM */
+ ROM_LOAD16_BYTE( "136091-0018.2t", 0x00000, 0x10000, CRC(ef432aa8) SHA1(56bce13c111db7874c9b669d479f6ef47976ee14) )
+ ROM_LOAD16_BYTE( "136091-0017.2lm", 0x00001, 0x10000, CRC(b0454074) SHA1(9530ea1ef215116da1f0843776fa7a6b4637049d) )
+ ROM_LOAD16_BYTE( "136091-0020.2r", 0x20000, 0x10000, CRC(311cef99) SHA1(9c466aabad7e80581e477253ec6f2fd245f9b9fd) )
+ ROM_LOAD16_BYTE( "136091-0019.2k", 0x20001, 0x10000, CRC(5bb00676) SHA1(cad1cea8e43f9590fc71c00fab4eff0d447f9296) )
+ ROM_LOAD16_BYTE( "136091-0022.2p", 0x40000, 0x10000, CRC(bc4dd071) SHA1(ca182451a0a18d343dce1be56090d51950d43906) )
+ ROM_LOAD16_BYTE( "136091-0021.2j", 0x40001, 0x10000, CRC(14f2caae) SHA1(ff40dbced58dc910a2b5825b846a5e52933cb8fc) )
ROM_REGION16_BE( 0x50000, "mainpcb:user3", 0 ) /* 256k for DSK ROMs + 64k for RAM */
ROM_LOAD16_BYTE( "136091-0026.30e", 0x000000, 0x020000, CRC(47705109) SHA1(fa40275b71b74be8591282d2fba4215b98fc29c9) )
@@ -4519,13 +4519,13 @@ ROM_START( hdrivair )
ROM_REGION( 0x10000 + 0x10000, "mainpcb:asic65:asic65cpu", 0 ) /* dummy region for ADSP 2105 */
ROM_LOAD( "sboot.bin", 0x000000, 0x010000, CRC(cde4d010) SHA1(853f4b813ff70fe74cd87e92131c46fca045610d) )
- ROM_REGION( 0xc0000, "mainpcb:user1", 0 ) /* 768k for object ROM */
- ROM_LOAD16_BYTE( "obj0l.bin", 0x00000, 0x20000, CRC(1f835f2e) SHA1(9d3419f2c1aa65ddfe9ace4e70ca1212d634afbf) )
- ROM_LOAD16_BYTE( "obj0h.bin", 0x00001, 0x20000, CRC(c321ab55) SHA1(e095e40bb1ebda7c9ff04a5086c10ab41dec2f16) )
- ROM_LOAD16_BYTE( "obj1l.bin", 0x40000, 0x20000, CRC(3d65f264) SHA1(e9232f5bf439bf4e1cf99cc7e81b7f9550563f15) )
- ROM_LOAD16_BYTE( "obj1h.bin", 0x40001, 0x20000, CRC(2c06b708) SHA1(daa16f727f2f500172f88b69d6931aa0fa13641b) )
- ROM_LOAD16_BYTE( "obj2l.bin", 0x80000, 0x20000, CRC(b206cc7e) SHA1(17f05e906c41b804fe99dd6cd8acbade919a6a10) )
- ROM_LOAD16_BYTE( "obj2h.bin", 0x80001, 0x20000, CRC(a666e98c) SHA1(90e380ff87538c7d557cf005a4a5bcedc250eb72) )
+ ROM_REGION16_BE( 0xc0000, "mainpcb:user1", 0 ) /* 768k for object ROM */
+ ROM_LOAD16_BYTE( "obj0h.bin", 0x00000, 0x20000, CRC(c321ab55) SHA1(e095e40bb1ebda7c9ff04a5086c10ab41dec2f16) )
+ ROM_LOAD16_BYTE( "obj0l.bin", 0x00001, 0x20000, CRC(1f835f2e) SHA1(9d3419f2c1aa65ddfe9ace4e70ca1212d634afbf) )
+ ROM_LOAD16_BYTE( "obj1h.bin", 0x40000, 0x20000, CRC(2c06b708) SHA1(daa16f727f2f500172f88b69d6931aa0fa13641b) )
+ ROM_LOAD16_BYTE( "obj1l.bin", 0x40001, 0x20000, CRC(3d65f264) SHA1(e9232f5bf439bf4e1cf99cc7e81b7f9550563f15) )
+ ROM_LOAD16_BYTE( "obj2h.bin", 0x80000, 0x20000, CRC(a666e98c) SHA1(90e380ff87538c7d557cf005a4a5bcedc250eb72) )
+ ROM_LOAD16_BYTE( "obj2l.bin", 0x80001, 0x20000, CRC(b206cc7e) SHA1(17f05e906c41b804fe99dd6cd8acbade919a6a10) )
ROM_REGION16_BE( 0x140000, "mainpcb:user3", 0 )/* 1MB for DSK ROMs + 256k for RAM */
ROM_LOAD16_BYTE( "dsk2phi.bin", 0x00000, 0x80000, CRC(71c268e0) SHA1(c089248a7dfadf2eba3134fe40ebb777c115a886) )
@@ -4582,13 +4582,13 @@ ROM_START( hdrivairp )
ROM_REGION( 0x10000 + 0x10000, "mainpcb:asic65:asic65cpu", 0 ) /* dummy region for ADSP 2105 */
ROM_LOAD( "xboota.bin", 0x10000 + 0x00000, 0x10000, CRC(d9c49901) SHA1(9f90ae3a47eb1ef00c3ec3661f60402c2eae2108) )
- ROM_REGION( 0xc0000, "mainpcb:user1", 0 ) /* 768k for object ROM */
- ROM_LOAD16_BYTE( "objects.0l", 0x00000, 0x20000, CRC(3c9e9078) SHA1(f1daf32117236401f3cb97f332708632003e55f8) )
- ROM_LOAD16_BYTE( "objects.0h", 0x00001, 0x20000, CRC(4480dbae) SHA1(6a455173c38e80093f58bdc322cffcf25e70b6ae) )
- ROM_LOAD16_BYTE( "objects.1l", 0x40000, 0x20000, CRC(700bd978) SHA1(5cd63d4eee00d90fe29fb9697b6a0ea6b86704ae) )
- ROM_LOAD16_BYTE( "objects.1h", 0x40001, 0x20000, CRC(f613adaf) SHA1(9b9456e144a48fb73c5e084b33345667eed4905e) )
- ROM_LOAD16_BYTE( "objects.2l", 0x80000, 0x20000, CRC(e3b512f0) SHA1(080c5a21cb76edcb55d1c2488e9d91cf29cb0665) )
- ROM_LOAD16_BYTE( "objects.2h", 0x80001, 0x20000, CRC(3f83742b) SHA1(4b6e0134a806bcc9bd56432737047f86d0a16424) )
+ ROM_REGION16_BE( 0xc0000, "mainpcb:user1", 0 ) /* 768k for object ROM */
+ ROM_LOAD16_BYTE( "objects.0h", 0x00000, 0x20000, CRC(4480dbae) SHA1(6a455173c38e80093f58bdc322cffcf25e70b6ae) )
+ ROM_LOAD16_BYTE( "objects.0l", 0x00001, 0x20000, CRC(3c9e9078) SHA1(f1daf32117236401f3cb97f332708632003e55f8) )
+ ROM_LOAD16_BYTE( "objects.1h", 0x40000, 0x20000, CRC(f613adaf) SHA1(9b9456e144a48fb73c5e084b33345667eed4905e) )
+ ROM_LOAD16_BYTE( "objects.1l", 0x40001, 0x20000, CRC(700bd978) SHA1(5cd63d4eee00d90fe29fb9697b6a0ea6b86704ae) )
+ ROM_LOAD16_BYTE( "objects.2h", 0x80000, 0x20000, CRC(3f83742b) SHA1(4b6e0134a806bcc9bd56432737047f86d0a16424) )
+ ROM_LOAD16_BYTE( "objects.2l", 0x80001, 0x20000, CRC(e3b512f0) SHA1(080c5a21cb76edcb55d1c2488e9d91cf29cb0665) )
ROM_REGION16_BE( 0x140000, "mainpcb:user3", 0 )/* 1MB for DSK ROMs + 256k for RAM */
ROM_LOAD16_BYTE( "dskpics.hi", 0x00000, 0x80000, CRC(eaa88101) SHA1(ed0ebf8a9a9514d810242b9b552126f6717f9e25) )
diff --git a/src/mame/drivers/hh_hmcs40.cpp b/src/mame/drivers/hh_hmcs40.cpp
index 6687e7f8994..a246450d98e 100644
--- a/src/mame/drivers/hh_hmcs40.cpp
+++ b/src/mame/drivers/hh_hmcs40.cpp
@@ -2073,9 +2073,9 @@ static MACHINE_CONFIG_START( cdkong, cdkong_state )
MCFG_TIMER_DRIVER_ADD_PERIODIC("display_decay", hh_hmcs40_state, display_decay_tick, attotime::from_msec(1))
MCFG_SCREEN_SVG_ADD("screen", "svg")
- MCFG_SCREEN_REFRESH_RATE(10)
- MCFG_SCREEN_SIZE(538, 1001)
- MCFG_SCREEN_VISIBLE_AREA(0, 537, 0, 1000)
+ MCFG_SCREEN_REFRESH_RATE(50)
+ MCFG_SCREEN_SIZE(559, 998)
+ MCFG_SCREEN_VISIBLE_AREA(0, 558, 0, 997)
MCFG_DEFAULT_LAYOUT(layout_svg)
/* sound hardware */
@@ -3967,8 +3967,8 @@ ROM_START( cdkong )
ROM_LOAD( "hd38820a45", 0x0000, 0x1000, CRC(196b8070) SHA1(da85d1eb4b048b77f3168630662ab94ec9baa262) )
ROM_CONTINUE( 0x1e80, 0x0100 )
- ROM_REGION( 714102, "svg", 0)
- ROM_LOAD( "cdkong.svg", 0, 714102, CRC(184bbe69) SHA1(98554341054246e5d76e0779620498e6cb723958) )
+ ROM_REGION( 359199, "svg", 0)
+ ROM_LOAD( "cdkong.svg", 0, 359199, CRC(ba159fd5) SHA1(3188e2ed3234f39ac9ee93a485a7e73314bc3457) ) // version 8 april 2016. by Rik, kevtris
ROM_END
diff --git a/src/mame/drivers/intv.cpp b/src/mame/drivers/intv.cpp
index d1d6f8eab6b..084d7b492ba 100644
--- a/src/mame/drivers/intv.cpp
+++ b/src/mame/drivers/intv.cpp
@@ -136,103 +136,6 @@ static GFXDECODE_START( intvkbd )
GFXDECODE_ENTRY( "gfx1", 0x0000, intvkbd_charlayout, 0, 256 )
GFXDECODE_END
-static INPUT_PORTS_START( intv )
-
- /* Left Player Controller */
- PORT_START("KEYPAD1")
- PORT_BIT( 0x8000, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Left/1") PORT_CODE(KEYCODE_1_PAD)
- PORT_BIT( 0x4000, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Left/2") PORT_CODE(KEYCODE_2_PAD)
- PORT_BIT( 0x2000, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Left/3") PORT_CODE(KEYCODE_3_PAD)
- PORT_BIT( 0x1000, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Left/4") PORT_CODE(KEYCODE_4_PAD)
- PORT_BIT( 0x0800, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Left/5") PORT_CODE(KEYCODE_5_PAD)
- PORT_BIT( 0x0400, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Left/6") PORT_CODE(KEYCODE_6_PAD)
- PORT_BIT( 0x0200, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Left/7") PORT_CODE(KEYCODE_7_PAD)
- PORT_BIT( 0x0100, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Left/8") PORT_CODE(KEYCODE_8_PAD)
- PORT_BIT( 0x0080, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Left/9") PORT_CODE(KEYCODE_9_PAD)
- PORT_BIT( 0x0040, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Left/Clear") PORT_CODE(KEYCODE_DEL_PAD)
- PORT_BIT( 0x0020, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Left/0") PORT_CODE(KEYCODE_0_PAD)
- PORT_BIT( 0x0010, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Left/Enter") PORT_CODE(KEYCODE_ENTER_PAD)
- PORT_BIT( 0x0008, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("Left/Upper") PORT_PLAYER(1)
- PORT_BIT( 0x0004, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("Left/Lower-Left") PORT_PLAYER(1)
- PORT_BIT( 0x0002, IP_ACTIVE_HIGH, IPT_BUTTON3 ) PORT_NAME("Left/Lower-Right") PORT_PLAYER(1)
- PORT_BIT( 0x0001, IP_ACTIVE_HIGH, IPT_UNUSED )
-
- PORT_START("DISC1")
- PORT_BIT( 0x8000, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) PORT_NAME("Left/Up") PORT_PLAYER(1) PORT_CONDITION("OPTIONS",0x01,EQUALS,0x00)
- PORT_BIT( 0x4000, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Left/Up-Up-Right") PORT_CONDITION("OPTIONS",0x01,EQUALS,0x00)
- PORT_BIT( 0x2000, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Left/Up-Right") PORT_CONDITION("OPTIONS",0x01,EQUALS,0x00)
- PORT_BIT( 0x1000, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Left/Right-Up-Right") PORT_CONDITION("OPTIONS",0x01,EQUALS,0x00)
- PORT_BIT( 0x0800, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_NAME("Left/Right") PORT_PLAYER(1) PORT_CONDITION("OPTIONS",0x01,EQUALS,0x00)
- PORT_BIT( 0x0400, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Left/Right-Down-Right") PORT_CONDITION("OPTIONS",0x01,EQUALS,0x00)
- PORT_BIT( 0x0200, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Left/Down-Right") PORT_CONDITION("OPTIONS",0x01,EQUALS,0x00)
- PORT_BIT( 0x0100, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Left/Down-Down-Right") PORT_CONDITION("OPTIONS",0x01,EQUALS,0x00)
- PORT_BIT( 0x0080, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_NAME("Left/Down") PORT_PLAYER(1) PORT_CONDITION("OPTIONS",0x01,EQUALS,0x00)
- PORT_BIT( 0x0040, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Left/Down-Down-Left") PORT_CONDITION("OPTIONS",0x01,EQUALS,0x00)
- PORT_BIT( 0x0020, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Left/Down-Left") PORT_CONDITION("OPTIONS",0x01,EQUALS,0x00)
- PORT_BIT( 0x0010, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Left/Left-Down-Left") PORT_CONDITION("OPTIONS",0x01,EQUALS,0x00)
- PORT_BIT( 0x0008, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_NAME("Left/Left") PORT_PLAYER(1) PORT_CONDITION("OPTIONS",0x01,EQUALS,0x00)
- PORT_BIT( 0x0004, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Left/Left-Up-Left") PORT_CONDITION("OPTIONS",0x01,EQUALS,0x00)
- PORT_BIT( 0x0002, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Left/Up-Left") PORT_CONDITION("OPTIONS",0x01,EQUALS,0x00)
- PORT_BIT( 0x0001, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Left/Up-Up-Left") PORT_CONDITION("OPTIONS",0x01,EQUALS,0x00)
-
- PORT_START("DISCX1")
- PORT_BIT( 0xff, 0x50, IPT_AD_STICK_X ) PORT_NAME("Left/X") PORT_MINMAX(0x00,0x9f) PORT_SENSITIVITY(100) PORT_KEYDELTA(0x50) PORT_CODE_DEC(KEYCODE_LEFT) PORT_CODE_INC(KEYCODE_RIGHT) PORT_PLAYER(1) PORT_CONDITION("OPTIONS",0x01,EQUALS,0x01)
-
- PORT_START("DISCY1")
- PORT_BIT( 0xff, 0x50, IPT_AD_STICK_Y ) PORT_NAME("Left/Y") PORT_MINMAX(0x00,0x9f) PORT_SENSITIVITY(100) PORT_KEYDELTA(0x50) PORT_CODE_DEC(KEYCODE_UP) PORT_CODE_INC(KEYCODE_DOWN) PORT_PLAYER(1) PORT_CONDITION("OPTIONS",0x01,EQUALS,0x01)
-
- /* Right Player Controller */
- PORT_START("KEYPAD2")
- PORT_BIT( 0x8000, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Right/1")
- PORT_BIT( 0x4000, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Right/2")
- PORT_BIT( 0x2000, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Right/3")
- PORT_BIT( 0x1000, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Right/4")
- PORT_BIT( 0x0800, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Right/5")
- PORT_BIT( 0x0400, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Right/6")
- PORT_BIT( 0x0200, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Right/7")
- PORT_BIT( 0x0100, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Right/8")
- PORT_BIT( 0x0080, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Right/9")
- PORT_BIT( 0x0040, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Right/Clear")
- PORT_BIT( 0x0020, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Right/0")
- PORT_BIT( 0x0010, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Right/Enter")
- PORT_BIT( 0x0008, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("Right/Upper") PORT_PLAYER(2)
- PORT_BIT( 0x0004, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("Right/Lower-Left") PORT_PLAYER(2)
- PORT_BIT( 0x0002, IP_ACTIVE_HIGH, IPT_BUTTON3 ) PORT_NAME("Right/Lower-Right") PORT_PLAYER(2)
- PORT_BIT( 0x0001, IP_ACTIVE_HIGH, IPT_UNUSED )
-
- PORT_START("DISC2")
- PORT_BIT( 0x8000, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) PORT_NAME("Right/Up") PORT_PLAYER(2) PORT_CONDITION("OPTIONS",0x02,EQUALS,0x00)
- PORT_BIT( 0x4000, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Right/Up-Up-Right") PORT_CONDITION("OPTIONS",0x02,EQUALS,0x00)
- PORT_BIT( 0x2000, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Right/Up-Right") PORT_CONDITION("OPTIONS",0x02,EQUALS,0x00)
- PORT_BIT( 0x1000, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Right/Right-Up-Right") PORT_CONDITION("OPTIONS",0x02,EQUALS,0x00)
- PORT_BIT( 0x0800, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_NAME("Right/Right") PORT_PLAYER(2) PORT_CONDITION("OPTIONS",0x02,EQUALS,0x00)
- PORT_BIT( 0x0400, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Right/Right-Down-Right") PORT_CONDITION("OPTIONS",0x02,EQUALS,0x00)
- PORT_BIT( 0x0200, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Right/Down-Right") PORT_CONDITION("OPTIONS",0x02,EQUALS,0x00)
- PORT_BIT( 0x0100, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Right/Down-Down-Right") PORT_CONDITION("OPTIONS",0x02,EQUALS,0x00)
- PORT_BIT( 0x0080, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_NAME("Right/Down") PORT_PLAYER(2) PORT_CONDITION("OPTIONS",0x02,EQUALS,0x00)
- PORT_BIT( 0x0040, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Right/Down-Down-Left") PORT_CONDITION("OPTIONS",0x02,EQUALS,0x00)
- PORT_BIT( 0x0020, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Right/Down-Left") PORT_CONDITION("OPTIONS",0x02,EQUALS,0x00)
- PORT_BIT( 0x0010, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Right/Left-Down-Left") PORT_CONDITION("OPTIONS",0x02,EQUALS,0x00)
- PORT_BIT( 0x0008, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_NAME("Right/Left") PORT_PLAYER(2) PORT_CONDITION("OPTIONS",0x02,EQUALS,0x00)
- PORT_BIT( 0x0004, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Right/Left-Up-Left") PORT_CONDITION("OPTIONS",0x02,EQUALS,0x00)
- PORT_BIT( 0x0002, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Right/Up-Left") PORT_CONDITION("OPTIONS",0x02,EQUALS,0x00)
- PORT_BIT( 0x0001, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Right/Up-Up-Left") PORT_CONDITION("OPTIONS",0x02,EQUALS,0x00)
-
- PORT_START("DISCX2")
- PORT_BIT( 0xff, 0x50, IPT_AD_STICK_X ) PORT_NAME("Right/X") PORT_MINMAX(0x00,0x9f) PORT_SENSITIVITY(100) PORT_KEYDELTA(0x50) PORT_CODE_DEC(KEYCODE_D) PORT_CODE_INC(KEYCODE_G) PORT_PLAYER(2) PORT_CONDITION("OPTIONS",0x02,EQUALS,0x02)
-
- PORT_START("DISCY2")
- PORT_BIT( 0xff, 0x50, IPT_AD_STICK_Y ) PORT_NAME("Right/Y") PORT_MINMAX(0x00,0x9f) PORT_SENSITIVITY(100) PORT_KEYDELTA(0x50) PORT_CODE_DEC(KEYCODE_R) PORT_CODE_INC(KEYCODE_F) PORT_PLAYER(2) PORT_CONDITION("OPTIONS",0x02,EQUALS,0x02)
-
- PORT_START("OPTIONS")
- PORT_CONFNAME( 0x01, 0x00, "Left Disc" )
- PORT_CONFSETTING( 0x00, "Digital" )
- PORT_CONFSETTING( 0x01, "Analog" )
- PORT_CONFNAME( 0x02, 0x00, "Right Disc" )
- PORT_CONFSETTING( 0x00, "Digital" )
- PORT_CONFSETTING( 0x02, "Analog" )
-INPUT_PORTS_END
-
/*
Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0
@@ -370,11 +273,6 @@ static INPUT_PORTS_START( intvkbd )
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_5_PAD)
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_6_PAD)
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_7_PAD)
-
- /* 2008-05 FP: I include here the controller inputs to make happy the read_handler.
- Please remove this (and re-tag accordingly the inputs above) if intv_right_control_r
- is supposed to scan the keyboard inputs when the Keyboard Component is connected */
- PORT_INCLUDE( intv )
INPUT_PORTS_END
static ADDRESS_MAP_START( intv_mem, AS_PROGRAM, 16, intv_state )
@@ -551,7 +449,6 @@ INTERRUPT_GEN_MEMBER(intv_state::intv_interrupt2)
timer_set(m_keyboard->cycles_to_attotime(100), TIMER_INTV_INTERRUPT2_COMPLETE);
}
-
static MACHINE_CONFIG_START( intv, intv_state )
/* basic machine hardware */
MCFG_CPU_ADD("maincpu", CP1610, XTAL_3_579545MHz/4) /* Colorburst/4 */
@@ -574,11 +471,14 @@ static MACHINE_CONFIG_START( intv, intv_state )
MCFG_PALETTE_INDIRECT_ENTRIES(32)
MCFG_PALETTE_INIT_OWNER(intv_state, intv)
+ MCFG_INTV_CONTROL_PORT_ADD("iopt_right_ctrl", intv_control_port_devices, "handctrl")
+ MCFG_INTV_CONTROL_PORT_ADD("iopt_left_ctrl", intv_control_port_devices, "handctrl")
+
/* sound hardware */
MCFG_SPEAKER_STANDARD_MONO("mono")
MCFG_SOUND_ADD("ay8914", AY8914, XTAL_3_579545MHz/2)
- MCFG_AY8910_PORT_A_READ_CB(READ8(intv_state, intv_right_control_r))
- MCFG_AY8910_PORT_B_READ_CB(READ8(intv_state, intv_left_control_r))
+ MCFG_AY8910_PORT_A_READ_CB(DEVREAD8("iopt_right_ctrl", intv_control_port_device, ctrl_r))
+ MCFG_AY8910_PORT_B_READ_CB(DEVREAD8("iopt_left_ctrl", intv_control_port_device, ctrl_r))
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.33)
/* cartridge */
@@ -743,11 +643,11 @@ DRIVER_INIT_MEMBER(intv_state,intvkbd)
***************************************************************************/
/* YEAR NAME PARENT COMPAT MACHINE INPUT INIT COMPANY FULLNAME */
-CONS( 1979, intv, 0, 0, intv, intv, intv_state, intv, "Mattel", "Intellivision", MACHINE_SUPPORTS_SAVE )
-CONS( 1981, intvsrs, intv, 0, intv, intv, intv_state, intv, "Sears", "Super Video Arcade", MACHINE_SUPPORTS_SAVE )
+CONS( 1979, intv, 0, 0, intv, 0, intv_state, intv, "Mattel", "Intellivision", MACHINE_SUPPORTS_SAVE )
+CONS( 1981, intvsrs, intv, 0, intv, 0, intv_state, intv, "Sears", "Super Video Arcade", MACHINE_SUPPORTS_SAVE )
COMP( 1981, intvkbd, intv, 0, intvkbd, intvkbd, intv_state, intvkbd, "Mattel", "Intellivision Keyboard Component (Unreleased)", MACHINE_NOT_WORKING | MACHINE_SUPPORTS_SAVE )
-CONS( 1982, intv2, intv, 0, intv2, intv, intv_state, intv, "Mattel", "Intellivision II", MACHINE_SUPPORTS_SAVE )
+CONS( 1982, intv2, intv, 0, intv2, 0, intv_state, intv, "Mattel", "Intellivision II", MACHINE_SUPPORTS_SAVE )
// made up, user friendlier machines with pre-mounted passthu expansions
-COMP( 1982, intvoice, intv, 0, intvoice, intv, intv_state, intv, "Mattel", "Intellivision w/IntelliVoice expansion", MACHINE_SUPPORTS_SAVE )
-COMP( 1983, intvecs, intv, 0, intvecs, intv, intv_state, intv, "Mattel", "Intellivision w/Entertainment Computer System + Intellivoice expansions", MACHINE_SUPPORTS_SAVE )
+COMP( 1982, intvoice, intv, 0, intvoice, 0, intv_state, intv, "Mattel", "Intellivision w/IntelliVoice expansion", MACHINE_SUPPORTS_SAVE )
+COMP( 1983, intvecs, intv, 0, intvecs, 0, intv_state, intv, "Mattel", "Intellivision w/Entertainment Computer System + Intellivoice expansions", MACHINE_SUPPORTS_SAVE )
diff --git a/src/mame/drivers/model2.cpp b/src/mame/drivers/model2.cpp
index 0a12518fe0f..3a92ee24a73 100644
--- a/src/mame/drivers/model2.cpp
+++ b/src/mame/drivers/model2.cpp
@@ -5187,7 +5187,7 @@ ROM_START( dynabb ) /* Dynamite Baseball, Model 2B. Sega game ID# 833-12803 DYNA
ROM_LOAD32_WORD("epr-19169.14", 0x100002, 0x080000, CRC(91a5acef) SHA1(2520a3e4ff15e4d583861ba656570abca5f7c611) )
ROM_REGION32_LE( 0x2000000, "user1", 0 ) // Data
- // 0x0000000 - 0x07fffff unpopulated? (not checked by ROM checks)
+ // IC11, IC12 not populated
ROM_LOAD32_WORD("mpr-19176.9", 0x0800000, 0x400000, CRC(2c4e90f5) SHA1(8d5ed0b26e79dd6476282bc69cb27b42381635f2) )
ROM_LOAD32_WORD("mpr-19177.10", 0x0800002, 0x400000, CRC(b0f1e512) SHA1(81e4124ac7766c7ea6bac7e7f4db110783394ae3) )
ROM_LOAD32_WORD("mpr-19174.7", 0x1000000, 0x400000, CRC(057e5200) SHA1(dd07eb438d91a8132789154a633fb6ec4e2ef0d1) )
@@ -5196,11 +5196,10 @@ ROM_START( dynabb ) /* Dynamite Baseball, Model 2B. Sega game ID# 833-12803 DYNA
ROM_LOAD32_WORD("mpr-19173.6", 0x1800002, 0x400000, CRC(31adbeed) SHA1(3984be892f0dce21c8d423dda055ef7e57df4d4e) )
ROM_REGION( 0x1000000, "user2", 0 ) // Models
- // these IC positions are weird compared to the other games, but these are the correct pairings.
- ROM_LOAD32_WORD("mpr-19178.11", 0x0000000, 0x400000, CRC(0d621e21) SHA1(31adc229258a5d468ff80d789c59bd8a6777f900) )
- ROM_LOAD32_WORD("mpr-19180.17", 0x0000002, 0x400000, CRC(d2e311a5) SHA1(83fb31c6ad7c32f1a7bcf870edb2719653c3db97) )
- ROM_LOAD32_WORD("mpr-19179.12", 0x0800000, 0x400000, CRC(337a4ec2) SHA1(77d7d186344715237895ac1ed0ab219fcc340a7e) )
- ROM_LOAD32_WORD("mpr-19181.21", 0x0800002, 0x400000, CRC(09a86c33) SHA1(30601c5b00fa3c9db815f60a0de16576e34b8c42) )
+ ROM_LOAD32_WORD("mpr-19178.17", 0x0000000, 0x400000, CRC(0d621e21) SHA1(31adc229258a5d468ff80d789c59bd8a6777f900) )
+ ROM_LOAD32_WORD("mpr-19180.21", 0x0000002, 0x400000, CRC(d2e311a5) SHA1(83fb31c6ad7c32f1a7bcf870edb2719653c3db97) )
+ ROM_LOAD32_WORD("mpr-19179.18", 0x0800000, 0x400000, CRC(337a4ec2) SHA1(77d7d186344715237895ac1ed0ab219fcc340a7e) )
+ ROM_LOAD32_WORD("mpr-19181.22", 0x0800002, 0x400000, CRC(09a86c33) SHA1(30601c5b00fa3c9db815f60a0de16576e34b8c42) )
ROM_REGION( 0x800000, "user3", 0 ) // Textures
diff --git a/src/mame/drivers/neogeo_noslot.cpp b/src/mame/drivers/neogeo_noslot.cpp
index 761e234a93b..3dc99c2dc2a 100644
--- a/src/mame/drivers/neogeo_noslot.cpp
+++ b/src/mame/drivers/neogeo_noslot.cpp
@@ -7561,6 +7561,30 @@ ROM_START( kf2k3pcb ) /* Encrypted Set, JAMMA PCB */
ROM_END
+
+ROM_START( unkneo )
+ ROM_REGION( 0x100000, "maincpu", 0 )
+ ROM_LOAD16_BYTE( "EP1.bin", 0x000001, 0x080000, CRC(f353448c) SHA1(f0f966ca15d503e01b40e901765ff0888463b65d) )
+ ROM_LOAD16_BYTE( "EP2.bin", 0x000000, 0x080000, CRC(f25c71ad) SHA1(803fb6cd6a7ada59678ad901ff9788b1e54ddd0c) )
+
+ NEO_SFIX_128K( "s1.s1", CRC(706477a7) SHA1(8cbee7f6832e7edd2dc792ca330420a6a984b879) ) // was a dead AXS512PC 512KB sram card, this data is handcrafted to make the set usable (hence BAD_DUMP)
+
+ NEOGEO_BIOS
+ ROM_REGION( 0x20000, "audiobios", 0 )
+ ROM_LOAD( "sm1.sm1", 0x00000, 0x20000, CRC(94416d67) SHA1(42f9d7ddd6c0931fd64226a60dc73602b2819dcf) )
+ ROM_REGION( 0x30000, "audiocpu", ROMREGION_ERASE00 )
+ /* not present */
+
+ ROM_REGION( 0x400000, "ymsnd", 0 )
+ ROM_LOAD( "sram.v1", 0x000000, 0x200000, NO_DUMP ) // was a dead AXS2000PC 2MB sram card, battery dead, data lost.
+
+ NO_DELTAT_REGION
+
+ ROM_REGION( 0x2000000, "sprites", 0 )
+ ROM_LOAD16_BYTE( "no3.bin", 0x000000, 0x1000000, CRC(81821826) SHA1(b7c1a53e32633383675206a16c68f6f2ff984865) )
+ ROM_LOAD16_BYTE( "no4.bin", 0x000001, 0x1000000, CRC(3601d568) SHA1(800323e52f5d33b402f84d31850b42c688082d67) )
+ROM_END
+
/*************************************
*
* Bootleg sets
@@ -9902,6 +9926,8 @@ GAME( 1995, marukodq, neogeo, neogeo_noslot, neogeo, neogeo_state, neoge
GAME( 1995, doubledr, neogeo, neogeo_noslot, neogeo, neogeo_state, neogeo, ROT0, "Technos Japan", "Double Dragon (Neo-Geo)", MACHINE_SUPPORTS_SAVE )
GAME( 1995, gowcaizr, neogeo, neogeo_noslot, neogeo, neogeo_state, neogeo, ROT0, "Technos Japan", "Voltage Fighter - Gowcaizer / Choujin Gakuen Gowcaizer", MACHINE_SUPPORTS_SAVE )
GAME( 1996, sdodgeb, neogeo, neogeo_noslot, neogeo, neogeo_state, neogeo, ROT0, "Technos Japan", "Super Dodge Ball / Kunio no Nekketsu Toukyuu Densetsu", MACHINE_SUPPORTS_SAVE )
+GAME( 199?, unkneo, neogeo, neogeo_noslot, neogeo, neogeo_state, neogeo, ROT0, "Technos Japan?", "Unknown Neo-Geo Vs. Fighter (prototype)", MACHINE_SUPPORTS_SAVE ) // same ID code as Voltage Fighter Gowkaizer so probably by Technos
+
/* Tecmo */
GAME( 1996, tws96, neogeo, neogeo_noslot, neogeo, neogeo_state, neogeo, ROT0, "Tecmo", "Tecmo World Soccer '96", MACHINE_SUPPORTS_SAVE )
diff --git a/src/mame/drivers/playch10.cpp b/src/mame/drivers/playch10.cpp
index 3de354d2a38..3c43e990d4f 100644
--- a/src/mame/drivers/playch10.cpp
+++ b/src/mame/drivers/playch10.cpp
@@ -1420,6 +1420,27 @@ ROM_START( pc_ngai3 ) /* Ninja Gaiden 3 */
ROM_LOAD( "security.prm", 0x00, 0x10, CRC(13755943) SHA1(b7d809b0f60ef489777ccb35868f5c1e777356e0) )
ROM_END
+// this is identcal to the USA NES release with the generic 'New Game 2' menu rom.
+// TT-CHR.U1 = nes-ni-0 chr nes:ttoonadvu Tiny Toon Adventures (USA)
+// TT-GM2.U3 = u2 pc_virus Virus (Dr. Mario prototype, PlayChoice-10)
+// TT-PRG.U5 = nes-ni-0 prg nes:ttoonadvu Tiny Toon Adventures (USA)
+ROM_START( pc_ttoon ) /* Tiny Toon Adventures */
+ BIOS_CPU
+ ROM_LOAD( "TT-GM2.U3", 0x0c000, 0x2000, CRC(d2764d91) SHA1(393b54148e9250f14d83318aed6686cc04b923e6) ) /* extra bios code for this game */
+ BIOS_GFX
+
+ ROM_REGION( 0x50000, "cart", 0 )
+ ROM_LOAD( "TT-PRG.U5", 0x10000, 0x20000, CRC(9cb55b96) SHA1(437c326a4575895b9d7e567cab4f70b2f44ed8dd) ) /* banked */
+ ROM_RELOAD( 0x30000, 0x20000 )
+
+ ROM_REGION( 0x020000, "gfx2", 0 ) /* cart gfx */
+ ROM_LOAD( "TT-CHR.U1", 0x00000, 0x20000, CRC(a024ae14) SHA1(2e797a173161a61c14ce299e3c5a31c6029f2b50) )
+
+ ROM_REGION( 0x10, "rp5h01", 0 ) /* rp5h01 data */
+ ROM_LOAD( "security.u6", 0x00, 0x10, CRC(5b4f6930) SHA1(bd152d6907fe55f80125b34360fdb44cfc348906) )
+ROM_END
+
+
ROM_START( pc_radr2 ) /* Rad Racer II */
BIOS_CPU
ROM_LOAD( "qr-u3", 0x0c000, 0x2000, CRC(0c8fea63) SHA1(7ac04b151df732bd16708655352b7f13926f004f) ) /* extra bios code for this game */
@@ -1649,6 +1670,20 @@ DRIVER_INIT_MEMBER(playch10_state,virus)
DRIVER_INIT_CALL(pcfboard);
}
+DRIVER_INIT_MEMBER(playch10_state,ttoon)
+{
+ UINT8 *ROM = memregion("rp5h01")->base();
+ UINT32 len = memregion("rp5h01")->bytes();
+ for (int i = 0; i < len; i++)
+ {
+ ROM[i] = BITSWAP8(ROM[i],0,1,2,3,4,5,6,7);
+ ROM[i] ^= 0xff;
+ }
+
+ /* common init */
+ DRIVER_INIT_CALL(pcgboard);
+}
+
/* YEAR NAME PARENT BIOS MACHINE INPUT INIT MONITOR */
/* Standard Games */
@@ -1717,6 +1752,8 @@ GAME( 1990, pc_ngai2, playch10, playch10, playch10, playch10_state, pcgboard, RO
GAME( 1991, pc_ngai3, playch10, playch10, playch10, playch10_state, pcgboard, ROT0, "Tecmo (Nintendo of America license)", "Ninja Gaiden Episode III: The Ancient Ship of Doom (PlayChoice-10)", 0 )
GAME( 1991, pc_pwbld, playch10, playch10, playch10, playch10_state, pcgboard, ROT0, "Taito (Nintendo of America license)", "Power Blade (PlayChoice-10)", 0 )
GAME( 1991, pc_rkats, playch10, playch10, playch10, playch10_state, pcgboard, ROT0, "Atlus (Nintendo of America license)", "Rockin' Kats (PlayChoice-10)", 0 )
+GAME( 1991, pc_ttoon, playch10, playch10, playch10, playch10_state, ttoon, ROT0, "Capcom USA (Nintendo of America license)", "Tiny Toon Adventures (prototype) (PlayChoice-10)", 0 ) // Code is final USA NES version of the game, (which is MMC3C according to nes.xml, but this cart has MMC3B)
+
/* variant with 4 screen mirror */
GAME( 1990, pc_radr2, playch10, playch10, playch10, playch10_state, pcgboard_type2, ROT0, "Square (Nintendo of America license)", "Rad Racer II (PlayChoice-10)", 0 )
GAME( 1985, pc_gntlt, playch10, playch10, playch10, playch10_state, pcgboard_type2, ROT0, "Atari / Tengen (Nintendo of America license)", "Gauntlet (PlayChoice-10)", MACHINE_IMPERFECT_GRAPHICS )
diff --git a/src/mame/drivers/r9751.cpp b/src/mame/drivers/r9751.cpp
index 340c1840352..03266a666ed 100644
--- a/src/mame/drivers/r9751.cpp
+++ b/src/mame/drivers/r9751.cpp
@@ -87,6 +87,8 @@ private:
required_device<generic_terminal_device> m_terminal;
required_shared_ptr<UINT32> m_main_ram;
+ m68000_base_device* ptr_m68000;
+
// Begin registers
UINT32 reg_ff050004;
UINT32 reg_fff80040;
@@ -102,6 +104,9 @@ private:
// functions
UINT32 swap_uint32( UINT32 val );
+ UINT32 debug_a6();
+ UINT32 debug_a5();
+ UINT32 debug_a5_20();
virtual void machine_reset() override;
};
@@ -113,10 +118,25 @@ UINT32 r9751_state::swap_uint32( UINT32 val )
return (val << 16) | (val >> 16);
}
+UINT32 r9751_state::debug_a6()
+{
+ return m_maincpu->space(AS_PROGRAM).read_dword(ptr_m68000->dar[14] + 4);
+}
+
+UINT32 r9751_state::debug_a5()
+{
+ return m_maincpu->space(AS_PROGRAM).read_dword(ptr_m68000->dar[13]);
+}
+
+UINT32 r9751_state::debug_a5_20()
+{
+ return m_maincpu->space(AS_PROGRAM).read_dword(ptr_m68000->dar[13] + 0x20);
+}
+
READ8_MEMBER(r9751_state::pdc_dma_r)
{
/* This callback function takes the value written to 0xFF01000C as the bank offset */
- UINT32 address = (fdd_dma_bank & 0x7FFFF800) + (offset&0xFFFF);
+ UINT32 address = (fdd_dma_bank & 0x7FFFF800) + (offset&0x3FFFF);
if(TRACE_DMA) logerror("DMA READ: %08X DATA: %08X\n", address, m_maincpu->space(AS_PROGRAM).read_byte(address));
return m_maincpu->space(AS_PROGRAM).read_byte(address);
}
@@ -124,7 +144,7 @@ READ8_MEMBER(r9751_state::pdc_dma_r)
WRITE8_MEMBER(r9751_state::pdc_dma_w)
{
/* This callback function takes the value written to 0xFF01000C as the bank offset */
- UINT32 address = (fdd_dma_bank & 0x7FFFF800) + (m_pdc->fdd_68k_dma_address&0xFFFF);
+ UINT32 address = (fdd_dma_bank & 0x7FFFF800) + (m_pdc->fdd_68k_dma_address&0x3FFFF);
m_maincpu->space(AS_PROGRAM).write_byte(address,data);
if(TRACE_DMA) logerror("DMA WRITE: %08X DATA: %08X\n", address,data);
}
@@ -140,6 +160,7 @@ DRIVER_INIT_MEMBER(r9751_state,r9751)
smioc_dma_bank = 0;
m_mem = &m_maincpu->space(AS_PROGRAM);
+ m_maincpu->interface<m68000_base_device>(ptr_m68000);
}
void r9751_state::machine_reset()
@@ -255,7 +276,7 @@ WRITE32_MEMBER( r9751_state::r9751_mmio_5ff_w )
case 0xC0B0:
case 0xC1B0: /* fdd_dest_address register */
fdd_dest_address = data << 1;
- if(TRACE_FDC) logerror("--- FDD destination address: %08X PC: %08X Register: %08X\n", (fdd_dma_bank & 0x7FFFF800) + (fdd_dest_address&0xFFFF), space.machine().firstcpu->pc(), offset << 2 | 0x5FF00000);
+ if(TRACE_FDC) logerror("--- FDD destination address: %08X PC: %08X Register: %08X (A6+4): %08X\n", (fdd_dma_bank & 0x7FFFF800) + (fdd_dest_address&0x3FFFF), space.machine().firstcpu->pc(), offset << 2 | 0x5FF00000, debug_a6());
data_b0 = data & 0xFF;
data_b1 = (data & 0xFF00) >> 8;
m_pdc->reg_p6 = data_b0;
@@ -274,14 +295,14 @@ WRITE32_MEMBER( r9751_state::r9751_mmio_5ff_w )
m_pdc->reg_p5 = 0;
/* Send FDD SCSI command location address to PDC 0x2, 0x3 */
- if(TRACE_FDC) logerror("--- FDD command address: %08X PC: %08X Register: %08X\n", (fdd_dma_bank & 0x7FFFF800) + ((data << 1)&0xFFFF), space.machine().firstcpu->pc(), offset << 2 | 0x5FF00000);
+ if(TRACE_FDC) logerror("--- FDD command address: %08X PC: %08X Register: %08X (A6+4): %08X A4: %08X (A5): %08X (A5+20): %08X\n", (fdd_dma_bank & 0x7FFFF800) + ((data << 1)&0x3FFFF), space.machine().firstcpu->pc(), offset << 2 | 0x5FF00000, debug_a6(), ptr_m68000->dar[12], debug_a5(), debug_a5_20());
data_b0 = data & 0xFF;
data_b1 = (data & 0xFF00) >> 8;
m_pdc->reg_p2 = data_b0;
m_pdc->reg_p3 = data_b1;
- fdd_scsi_command = swap_uint32(m_mem->read_dword((fdd_dma_bank & 0x7FFFF800) + ((data << 1)&0xFFFF)));
- fdd_scsi_command2 = swap_uint32(m_mem->read_dword(((fdd_dma_bank & 0x7FFFF800) + ((data << 1)&0xFFFF))+4));
+ fdd_scsi_command = swap_uint32(m_mem->read_dword((fdd_dma_bank & 0x7FFFF800) + ((data << 1)&0x3FFFF)));
+ fdd_scsi_command2 = swap_uint32(m_mem->read_dword(((fdd_dma_bank & 0x7FFFF800) + ((data << 1)&0x3FFFF))+4));
memcpy(c_fdd_scsi_command,&fdd_scsi_command,4);
memcpy(c_fdd_scsi_command+4,&fdd_scsi_command2,4);
@@ -300,7 +321,7 @@ WRITE32_MEMBER( r9751_state::r9751_mmio_5ff_w )
break;
default:
- if(TRACE_FDC || TRACE_HDC || TRACE_SMIOC) logerror("Instruction: %08x WRITE MMIO(%08x): %08x & %08x\n", space.machine().firstcpu->pc(), offset << 2 | 0x5FF00000, data, mem_mask);
+ if(TRACE_FDC || TRACE_HDC || TRACE_SMIOC) logerror("Instruction: %08x WRITE MMIO(%08x): %08x & %08x (A6+4): %08X\n", space.machine().firstcpu->pc(), offset << 2 | 0x5FF00000, data, mem_mask, debug_a6());
}
}
diff --git a/src/mame/drivers/raiden2.cpp b/src/mame/drivers/raiden2.cpp
index eb29eea28c9..e5bc0fe0f7c 100644
--- a/src/mame/drivers/raiden2.cpp
+++ b/src/mame/drivers/raiden2.cpp
@@ -2456,6 +2456,40 @@ ROM_START( raidendxj )
ROM_END
+ROM_START( raidendxja )
+ ROM_REGION( 0x200000, "maincpu", 0 ) /* v30 main cpu */
+ ROM_LOAD32_BYTE("1.bin", 0x000000, 0x80000, CRC(247e21c7) SHA1(69e9a084407f57e8433f832a592cfbba2757631f) )
+ ROM_LOAD32_BYTE("2.bin", 0x000001, 0x80000, CRC(f2e9855a) SHA1(e27ac94cdb4ce8e8a98b342fbaf0fde11d9ab9ef) )
+ ROM_LOAD32_BYTE("3.bin", 0x000002, 0x80000, CRC(fbab727f) SHA1(5415ff87dd967e52b5cf7d754c046223cfa1147b) )
+ ROM_LOAD32_BYTE("4.bin", 0x000003, 0x80000, CRC(a08d5838) SHA1(ec07770503eefa5f22d30f40e3df2a02813908e4) )
+
+ ROM_REGION( 0x40000, "user2", 0 ) /* COPX */
+ ROM_LOAD( "copx-d2.u0313", 0x00000, 0x40000, CRC(a6732ff9) SHA1(c4856ec77869d9098da24b1bb3d7d58bb74b4cda) ) /* Shared with original Raiden 2 */
+
+ ROM_REGION( 0x20000, "audiocpu", ROMREGION_ERASEFF ) /* 64k code for sound Z80 */
+ ROM_LOAD( "rdxj_5.u1110", 0x000000, 0x08000, CRC(8c46857a) SHA1(8b269cb20adf960ba4eb594d8add7739dbc9a837) )
+ ROM_CONTINUE(0x10000,0x8000)
+ ROM_COPY( "audiocpu", 0x000000, 0x018000, 0x08000 )
+
+ ROM_REGION( 0x020000, "gfx1", 0 ) /* chars */
+ ROM_LOAD( "rdxj_7.u0724", 0x000000, 0x020000, CRC(ec31fa10) SHA1(e39c9d95699dbeb21e3661d863eee503c9011bbc) )
+
+ ROM_REGION( 0x400000, "gfx2", 0 ) /* background gfx */
+ ROM_LOAD( "dx_back-1.u075", 0x000000, 0x200000, CRC(90970355) SHA1(d71d57cd550a800f583550365102adb7b1b779fc) )
+ ROM_LOAD( "dx_back-2.u0714", 0x200000, 0x200000, CRC(5799af3e) SHA1(85d6532abd769da77bcba70bd2e77915af40f987) )
+
+ ROM_REGION32_LE( 0x800000, "gfx3", 0 ) /* sprite gfx (encrypted) */
+ ROM_LOAD32_WORD( "raiden_2_seibu_obj-1.u0811", 0x000000, 0x200000, CRC(ff08ef0b) SHA1(a1858430e8171ca8bab785457ef60e151b5e5cf1) ) /* Shared with original Raiden 2 */
+ ROM_LOAD32_WORD( "raiden_2_seibu_obj-2.u082", 0x000002, 0x200000, CRC(638eb771) SHA1(9774cc070e71668d7d1d20795502dccd21ca557b) ) /* Shared with original Raiden 2 */
+ ROM_LOAD32_WORD( "dx_obj-3.u0837", 0x400000, 0x200000, CRC(ba381227) SHA1(dfc4d659aca1722a981fa56a31afabe66f444d5d) )
+ ROM_LOAD32_WORD( "dx_obj-4.u0836", 0x400002, 0x200000, CRC(65e50d19) SHA1(c46147b4132abce7314b46bf419ce4773e024b05) )
+
+ ROM_REGION( 0x100000, "oki1", 0 ) /* ADPCM samples */
+ ROM_LOAD( "rdxj_6.u1017", 0x00000, 0x40000, CRC(9a9196da) SHA1(3d1ee67fb0d40a231ce04d10718f07ffb76db455) )
+
+ ROM_REGION( 0x100000, "oki2", 0 ) /* ADPCM samples */
+ ROM_LOAD( "pcm.u1018", 0x00000, 0x40000, CRC(8cf0d17e) SHA1(0fbe0b1e1ca5360c7c8329331408e3d799b4714c) ) /* Shared with original Raiden 2 */
+ROM_END
ROM_START( raidendxch )
ROM_REGION( 0x200000, "maincpu", 0 ) /* v30 main cpu */
@@ -3077,7 +3111,8 @@ GAME( 1994, raidendxk, raidendx, raidendx, raidendx, raiden2_state, raidendx, R
GAME( 1994, raidendxu, raidendx, raidendx, raidendx, raiden2_state, raidendx, ROT270, "Seibu Kaihatsu (Fabtek license)", "Raiden DX (US)", MACHINE_SUPPORTS_SAVE )
GAME( 1994, raidendxg, raidendx, raidendx, raidendx, raiden2_state, raidendx, ROT270, "Seibu Kaihatsu (Tuning license)", "Raiden DX (Germany)", MACHINE_SUPPORTS_SAVE )
GAME( 1994, raidendxnl, raidendx, raidendx, raidendx, raiden2_state, raidendx, ROT270, "Seibu Kaihatsu", "Raiden DX (Holland)", MACHINE_SUPPORTS_SAVE )
-GAME( 1994, raidendxj, raidendx, raidendx, raidendx, raiden2_state, raidendx, ROT270, "Seibu Kaihatsu", "Raiden DX (Japan)", MACHINE_SUPPORTS_SAVE )
+GAME( 1994, raidendxj, raidendx, raidendx, raidendx, raiden2_state, raidendx, ROT270, "Seibu Kaihatsu", "Raiden DX (Japan, set 1)", MACHINE_SUPPORTS_SAVE )
+GAME( 1994, raidendxja, raidendx, raidendx, raidendx, raiden2_state, raidendx, ROT270, "Seibu Kaihatsu", "Raiden DX (Japan, set 2)", MACHINE_SUPPORTS_SAVE )
GAME( 1994, raidendxch, raidendx, raidendx, raidendx, raiden2_state, raidendx, ROT270, "Seibu Kaihatsu (Ideal International Development Corp license) ", "Raiden DX (China)", MACHINE_SUPPORTS_SAVE )
GAME( 1993, zeroteam, 0, zeroteam, zeroteam, raiden2_state, zeroteam, ROT0, "Seibu Kaihatsu (Fabtek license)", "Zero Team USA (US)", MACHINE_SUPPORTS_SAVE | MACHINE_NOT_WORKING )
diff --git a/src/mame/drivers/skylncr.cpp b/src/mame/drivers/skylncr.cpp
index cfaba6c0a36..8ba3d10d28b 100644
--- a/src/mame/drivers/skylncr.cpp
+++ b/src/mame/drivers/skylncr.cpp
@@ -1699,8 +1699,9 @@ ROM_START( sstar97 )
ROM_LOAD16_BYTE( "bor_dun_5.u22", 0x40001, 0x20000, CRC(ca17a632) SHA1(d491310ccdbe9b59a1e607f9254646f20700d79d) )
ROM_END
-/* Butterfly Dream 97 / Hudie Meng 97
- Game is encrypted and needs better decoded graphics.
+/*
+ Butterfly Dream 97 / Hudie Meng 97
+ Game is encrypted and needs better decoded graphics.
*/
ROM_START( bdream97 )
ROM_REGION( 0x80000, "maincpu", 0 )
@@ -1719,6 +1720,34 @@ ROM_START( bdream97 )
ROM_LOAD16_BYTE( "27c010.u27", 0x40001, 0x20000, CRC(0a266de4) SHA1(0ff9ad793e77d5419bd446cb73d4968e42305353) )
ROM_END
+/*
+ Sonik Fighter.
+ Greek Version By ZBOUNOS (Z GAMES).
+
+ Multiple Butterfly type with naked girls.
+ + new features and hold a pair.
+ + jackpot.
+ + tetris game?.
+
+ Program ROM is encrypted.
+*/
+ROM_START( sonikfig )
+ ROM_REGION( 0x80000, "maincpu", 0 )
+ ROM_LOAD( "subboard_27c512.bin", 0x00000, 0x10000, CRC(f9b5b03e) SHA1(3832a7d70b41052f9dca46faa6f311ccc5a817b7) )
+
+ ROM_REGION( 0x80000, "gfx1", 0 )
+ ROM_LOAD16_BYTE( "1__am27c100.u29", 0x00000, 0x20000, CRC(69824294) SHA1(a221ab3e5d50435c10e3cd4601cfda1c87038a74) )
+ ROM_LOAD16_BYTE( "2__am27c100.u31", 0x00001, 0x20000, CRC(5224ed08) SHA1(3ba9af7557f13bf31c529bff7b2b8cfd6e71552c) )
+ ROM_LOAD16_BYTE( "3__am27c100.u33", 0x40000, 0x20000, CRC(38fef15c) SHA1(00f7578bac395421fa3289748f85cf3b9d80e04b) )
+ ROM_LOAD16_BYTE( "4__am27c100.u35", 0x40001, 0x20000, CRC(6193d30d) SHA1(390b3f451224eb4236c6c921d34b25b702d366e0) )
+
+ ROM_REGION( 0x80000, "gfx2", 0 )
+ ROM_LOAD16_BYTE( "5__am27c100.u52", 0x00000, 0x20000, CRC(56921033) SHA1(25086b0f5978df04b28b60a30e271f4364112c96) )
+ ROM_LOAD16_BYTE( "6__am27c100.u54", 0x00001, 0x20000, CRC(72802c6c) SHA1(c552d438399fb8c983e995d5e78e591982ef96e5) )
+ ROM_LOAD16_BYTE( "7__am27c100.u56", 0x40000, 0x20000, CRC(90a09327) SHA1(3bb1150ec397627cc04b46d2bf07538c55e7f116) )
+ ROM_LOAD16_BYTE( "8__am27c100.u58", 0x40001, 0x20000, CRC(b02ed0ce) SHA1(ec8ab64210a1b10cdba5ee179e46fc8d6a1a67b6) )
+ROM_END
+
/**********************************
* Driver Init *
@@ -1745,3 +1774,4 @@ GAME( 199?, gallag50, 0, skylncr, gallag50, skylncr_state, skylncr, ROT0
GAME( 199?, neraidou, 0, neraidou, neraidou, skylncr_state, skylncr, ROT0, "bootleg", "Neraidoula (Fairy Butterfly)", 0 )
GAME( 199?, sstar97, 0, sstar97, sstar97, skylncr_state, skylncr, ROT0, "Bordun International", "Super Star 97 / Ming Xing 97 (version V153B)", 0 )
GAME( 199?, bdream97, 0, bdream97, skylncr, skylncr_state, skylncr, ROT0, "bootleg", "Butterfly Dream 97 / Hudie Meng 97", MACHINE_NOT_WORKING )
+GAME( 199?, sonikfig, 0, skylncr, skylncr, skylncr_state, skylncr, ROT0, "Z Games", "Sonik Fighter (encrypted)", MACHINE_NOT_WORKING )
diff --git a/src/mame/drivers/vsnes.cpp b/src/mame/drivers/vsnes.cpp
index 941cb3cb09f..c980ce50981 100644
--- a/src/mame/drivers/vsnes.cpp
+++ b/src/mame/drivers/vsnes.cpp
@@ -2150,21 +2150,22 @@ ROM_START( cluclu )
PALETTE_2C04_0004
ROM_END
-ROM_START( excitebk ) /* EB4-4 A = Excite Bike, Palette 4, rev A */
+
+ROM_START( excitebk ) /* EB4-3 = Excite Bike, Palette 3, revision 'E' */
ROM_REGION( 0x10000,"maincpu", 0 ) /* 6502 memory */
- ROM_LOAD( "mds-eb4-4 a.6d", 0x8000, 0x2000, CRC(6aa87037) SHA1(f3313700955498800a3d59c523ba2a4e0cf443bc) )
- ROM_LOAD( "mds-eb4-4 a.6c", 0xa000, 0x2000, CRC(bdb317db) SHA1(a8b3e8deb1e625d764aaffe86a513bc7ede51a46) )
- ROM_LOAD( "mds-eb4-4 a.6b", 0xc000, 0x2000, CRC(d1afe2dd) SHA1(ef0f44d98464b7dab7c51be4379242f7a4e4fcdd) )
- ROM_LOAD( "mds-eb4-4 a.6a", 0xe000, 0x2000, CRC(46711d0e) SHA1(6ce2f395b3f407671a87c6e1133ab63a637022f2) )
+ ROM_LOAD( "mds-eb4-3e.1d", 0x8000, 0x2000, CRC(f58a392e) SHA1(ca721e47e5dbe72d6f231d9b20b1ca33304c5370) )
+ ROM_LOAD( "mds-eb4-3e.1c", 0xa000, 0x2000, CRC(6ae01102) SHA1(f3f49644f7e2887e14655e8934c7c75d4b92968e) )
+ ROM_LOAD( "mds-eb4-3e.1b", 0xc000, 0x2000, CRC(fbc53465) SHA1(81c9ebac895dfbc5c451b4b32e5990aba3734714) )
+ ROM_LOAD( "mds-eb4-3e.1a", 0xe000, 0x2000, CRC(e2902b4e) SHA1(f559517c735847e2ad622418b8fa525d9c9adac3) )
ROM_REGION( 0x4000,"gfx1", 0 ) /* PPU memory */
- ROM_LOAD( "mds-eb4-4 a.8b", 0x0000, 0x2000, CRC(62a76c52) SHA1(7ebd0dac976abe8636f4f75a3b2a473d7a54934d) )
- ROM_LOAD( "mds-eb4-4 a.8a", 0x2000, 0x2000, CRC(a9b49a05) SHA1(c14706e6a5524f81e79c101e32deef9f3d60de3f) )
+ ROM_LOAD( "mds-eb4-3e.2b", 0x0000, 0x2000, CRC(80be1f50) SHA1(d8544b9a0a9d8719ab601fa9c68c4305385b14c7) )
+ ROM_LOAD( "mds-eb4-3e.2a", 0x2000, 0x2000, CRC(001e8e0b) SHA1(c4c2a11ade7788bac9dd61ea8de319c4111d2592) )
- PALETTE_2C04_0004
+ PALETTE_2C04_0003
ROM_END
-ROM_START( excitebka ) /* EB4-3 = Excite Bike, Palette 3, unknown revision */
+ROM_START( excitebko ) /* EB4-3 = Excite Bike, Palette 3, unknown revision */
ROM_REGION( 0x10000,"maincpu", 0 ) /* 6502 memory */
ROM_LOAD( "mds-eb4-3.1d", 0x8000, 0x2000, CRC(7e54df1d) SHA1(38d878041976386e8608c73133040b18d0e4b9cd) ) /* Need to verify correct label */
ROM_LOAD( "mds-eb4-3.1c", 0xa000, 0x2000, CRC(89baae91) SHA1(6aebf13c415e3246edf7daa847533b7e3ae0425f) ) /* Need to verify correct label */
@@ -2178,6 +2179,20 @@ ROM_START( excitebka ) /* EB4-3 = Excite Bike, Palette 3, unknown revision */
PALETTE_2C04_0003
ROM_END
+ROM_START( excitebkj ) /* EB4-4 A = Excite Bike, Palette 4, rev A */
+ ROM_REGION( 0x10000,"maincpu", 0 ) /* 6502 memory */
+ ROM_LOAD( "mds-eb4-4 a.6d", 0x8000, 0x2000, CRC(6aa87037) SHA1(f3313700955498800a3d59c523ba2a4e0cf443bc) )
+ ROM_LOAD( "mds-eb4-4 a.6c", 0xa000, 0x2000, CRC(bdb317db) SHA1(a8b3e8deb1e625d764aaffe86a513bc7ede51a46) )
+ ROM_LOAD( "mds-eb4-4 a.6b", 0xc000, 0x2000, CRC(d1afe2dd) SHA1(ef0f44d98464b7dab7c51be4379242f7a4e4fcdd) )
+ ROM_LOAD( "mds-eb4-4 a.6a", 0xe000, 0x2000, CRC(46711d0e) SHA1(6ce2f395b3f407671a87c6e1133ab63a637022f2) )
+
+ ROM_REGION( 0x4000,"gfx1", 0 ) /* PPU memory */
+ ROM_LOAD( "mds-eb4-4 a.8b", 0x0000, 0x2000, CRC(62a76c52) SHA1(7ebd0dac976abe8636f4f75a3b2a473d7a54934d) )
+ ROM_LOAD( "mds-eb4-4 a.8a", 0x2000, 0x2000, CRC(a9b49a05) SHA1(c14706e6a5524f81e79c101e32deef9f3d60de3f) )
+
+ PALETTE_2C04_0004
+ROM_END
+
ROM_START( jajamaru )
ROM_REGION( 0x10000,"maincpu", 0 ) /* 6502 memory */
ROM_LOAD( "10.bin", 0x8000, 0x2000, CRC(16af1704) SHA1(ebcf9ad06e302c51ee4432631a6b0fb85a9630ed) )
@@ -2787,8 +2802,9 @@ GAME( 1985, starlstr, 0, vsnes, starlstr, vsnes_state, vsnormal, ROT0,
GAME( 1987, cstlevna, 0, vsnes, cstlevna, vsnes_state, vsvram, ROT0, "Konami", "Vs. Castlevania", 0 )
GAME( 1984, cluclu, 0, vsnes, cluclu, vsnes_state, vsnormal, ROT0, "Nintendo", "Vs. Clu Clu Land", 0 )
GAME( 1990, drmario, 0, vsnes, drmario, vsnes_state, drmario, ROT0, "Nintendo", "Vs. Dr. Mario", 0 )
-GAME( 1984, excitebk, 0, vsnes, excitebk, vsnes_state, vsnormal, ROT0, "Nintendo", "Vs. Excitebike (set EB4-4 A)", 0 )
-GAME( 1984, excitebka,excitebk, vsnes, excitebk, vsnes_state, vsnormal, ROT0, "Nintendo", "Vs. Excitebike (set EB4-3 ?)", 0 )
+GAME( 1984, excitebk, 0, vsnes, excitebk, vsnes_state, vsnormal, ROT0, "Nintendo", "Vs. Excitebike (set EB4-3 E)", 0 )
+GAME( 1984, excitebko,excitebk, vsnes, excitebk, vsnes_state, vsnormal, ROT0, "Nintendo", "Vs. Excitebike (set EB4-3 ?)", 0 ) // older
+GAME( 1984, excitebkj,excitebk, vsnes, excitebk, vsnes_state, vsnormal, ROT0, "Nintendo", "Vs. Excitebike (set EB4-4 A)", 0 ) // likely Japan
GAME( 1986, goonies, 0, vsnes, goonies, vsnes_state, vskonami, ROT0, "Konami", "Vs. The Goonies (set E)", 0 )
GAME( 1984, iceclimb, 0, vsnes, iceclmbj, vsnes_state, vsnormal, ROT0, "Nintendo", "Vs. Ice Climber (set IC4-4 B-1)", 0 )
GAME( 1984, iceclimba,iceclimb, vsnes, iceclimb, vsnes_state, vsnormal, ROT0, "Nintendo", "Vs. Ice Climber (set IC4-4 ?)", 0 )
diff --git a/src/mame/includes/fidelz80.h b/src/mame/includes/fidelz80.h
index 3f57cc38ec6..56d17e7339f 100644
--- a/src/mame/includes/fidelz80.h
+++ b/src/mame/includes/fidelz80.h
@@ -1,5 +1,6 @@
// license:BSD-3-Clause
// copyright-holders:Kevin Horton,Jonathan Gevaryahu,Sandro Ronco,hap
+// thanks-to:Berger
/******************************************************************************
*
* Fidelity Electronics Z80 based board driver
diff --git a/src/mame/includes/intv.h b/src/mame/includes/intv.h
index 7f14c7fb55a..4155499db7d 100644
--- a/src/mame/includes/intv.h
+++ b/src/mame/includes/intv.h
@@ -16,6 +16,9 @@
#include "bus/intv/ecs.h"
//#include "bus/intv/keycomp.h"
+#include "bus/intv_ctrl/ctrl.h"
+#include "bus/intv_ctrl/handctrl.h"
+
#include "bus/generic/slot.h"
#include "bus/generic/carts.h"
@@ -43,7 +46,6 @@ public:
m_iocart2(*this, "ioslot2"),
m_region_maincpu(*this, "maincpu"),
m_region_keyboard(*this, "keyboard"),
- m_io_options(*this, "OPTIONS"),
m_io_test(*this, "TEST"),
m_gfxdecode(*this, "gfxdecode"),
m_palette(*this, "palette")
@@ -118,19 +120,13 @@ protected:
optional_device<generic_slot_device> m_iocart2;
required_memory_region m_region_maincpu;
optional_memory_region m_region_keyboard;
- required_ioport m_io_options;
optional_ioport m_io_test;
optional_device<gfxdecode_device> m_gfxdecode;
required_device<palette_device> m_palette;
- ioport_port *m_keypad[4];
- ioport_port *m_disc[4];
- ioport_port *m_discx[4];
- ioport_port *m_discy[4];
ioport_port *m_intv_keyboard[10];
- UINT8 intv_control_r(int hand);
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
};
diff --git a/src/mame/includes/playch10.h b/src/mame/includes/playch10.h
index a97de718bd3..7878803b073 100644
--- a/src/mame/includes/playch10.h
+++ b/src/mame/includes/playch10.h
@@ -119,6 +119,7 @@ public:
DECLARE_DRIVER_INIT(pcfboard);
DECLARE_DRIVER_INIT(pcfboard_2);
DECLARE_DRIVER_INIT(virus);
+ DECLARE_DRIVER_INIT(ttoon);
DECLARE_DRIVER_INIT(pcgboard);
DECLARE_DRIVER_INIT(pcgboard_type2);
DECLARE_DRIVER_INIT(pchboard);
diff --git a/src/mame/layout/fidel_sc12.lay b/src/mame/layout/fidel_sc12.lay
index 3d087368edf..6d30a74c4af 100644
--- a/src/mame/layout/fidel_sc12.lay
+++ b/src/mame/layout/fidel_sc12.lay
@@ -208,29 +208,54 @@
<disk><color red="0.81" green="0.8" blue="0.79" /></disk>
<text string="CL"><color red="0.17" green="0.15" blue="0.15" /></text>
</element>
+ <element name="text_pb">
+ <disk><color red="0.81" green="0.8" blue="0.79" /></disk>
+ <text string="PB"><color red="0.17" green="0.15" blue="0.15" /></text>
+ </element>
+ <element name="text_pv">
+ <disk><color red="0.81" green="0.8" blue="0.79" /></disk>
+ <text string="PV"><color red="0.17" green="0.15" blue="0.15" /></text>
+ </element>
+ <element name="text_lv">
+ <disk><color red="0.81" green="0.8" blue="0.79" /></disk>
+ <text string="LV"><color red="0.17" green="0.15" blue="0.15" /></text>
+ </element>
+ <element name="text_tb">
+ <disk><color red="0.81" green="0.8" blue="0.79" /></disk>
+ <text string="TB"><color red="0.17" green="0.15" blue="0.15" /></text>
+ </element>
+ <element name="text_dm">
+ <disk><color red="0.81" green="0.8" blue="0.79" /></disk>
+ <text string="DM"><color red="0.17" green="0.15" blue="0.15" /></text>
+ </element>
+ <element name="text_rv">
+ <disk><color red="0.81" green="0.8" blue="0.79" /></disk>
+ <text string="RV"><color red="0.17" green="0.15" blue="0.15" /></text>
+ </element>
+
<element name="text_king">
<disk><color red="0.81" green="0.8" blue="0.79" /></disk>
- <text string="PB/K"><color red="0.17" green="0.15" blue="0.15" /></text>
+ <text string="&#x2654;"><color red="0.17" green="0.15" blue="0.15" /></text>
</element>
<element name="text_queen">
<disk><color red="0.81" green="0.8" blue="0.79" /></disk>
- <text string="PV/Q"><color red="0.17" green="0.15" blue="0.15" /></text>
+ <text string="&#x2655;"><color red="0.17" green="0.15" blue="0.15" /></text>
</element>
<element name="text_rook">
<disk><color red="0.81" green="0.8" blue="0.79" /></disk>
- <text string="LV/R"><color red="0.17" green="0.15" blue="0.15" /></text>
+ <text string="&#x2656;"><color red="0.17" green="0.15" blue="0.15" /></text>
</element>
<element name="text_bishop">
<disk><color red="0.81" green="0.8" blue="0.79" /></disk>
- <text string="TB/B"><color red="0.17" green="0.15" blue="0.15" /></text>
+ <text string="&#x2657;"><color red="0.17" green="0.15" blue="0.15" /></text>
</element>
<element name="text_knight">
<disk><color red="0.81" green="0.8" blue="0.79" /></disk>
- <text string="DM/N"><color red="0.17" green="0.15" blue="0.15" /></text>
+ <text string="&#x2658;"><color red="0.17" green="0.15" blue="0.15" /></text>
</element>
<element name="text_pion">
<disk><color red="0.81" green="0.8" blue="0.79" /></disk>
- <text string="RV/P"><color red="0.17" green="0.15" blue="0.15" /></text>
+ <text string="&#x2659;"><color red="0.17" green="0.15" blue="0.15" /></text>
</element>
@@ -459,42 +484,48 @@
<!-- right side -->
- <bezel element="disk_black"><bounds x="87" y="3.1" width="7.4" height="7.4" /></bezel>
- <bezel element="disk_black"><bounds x="87" y="12.4" width="7.4" height="7.4" /></bezel>
- <bezel element="disk_black"><bounds x="87" y="24.3" width="7.4" height="7.4" /></bezel>
- <bezel element="disk_black"><bounds x="87" y="33.6" width="7.4" height="7.4" /></bezel>
- <bezel element="disk_black"><bounds x="87" y="42.9" width="7.4" height="7.4" /></bezel>
- <bezel element="disk_black"><bounds x="87" y="52.2" width="7.4" height="7.4" /></bezel>
- <bezel element="disk_black"><bounds x="87" y="61.5" width="7.4" height="7.4" /></bezel>
- <bezel element="disk_black"><bounds x="87" y="70.8" width="7.4" height="7.4" /></bezel>
-
- <bezel element="disk_white"><bounds x="87.8" y="3.9" width="5.8" height="5.8" /></bezel>
- <bezel element="disk_white"><bounds x="87.8" y="13.2" width="5.8" height="5.8" /></bezel>
- <bezel element="disk_white"><bounds x="87.8" y="25.1" width="5.8" height="5.8" /></bezel>
- <bezel element="disk_white"><bounds x="87.8" y="34.4" width="5.8" height="5.8" /></bezel>
- <bezel element="disk_white"><bounds x="87.8" y="43.7" width="5.8" height="5.8" /></bezel>
- <bezel element="disk_white"><bounds x="87.8" y="53 " width="5.8" height="5.8" /></bezel>
- <bezel element="disk_white"><bounds x="87.8" y="62.3" width="5.8" height="5.8" /></bezel>
- <bezel element="disk_white"><bounds x="87.8" y="71.6" width="5.8" height="5.8" /></bezel>
-
- <bezel element="text_re"><bounds x="87.8" y="5.6" width="5.8" height="2.4" /></bezel>
- <bezel element="text_cl"><bounds x="87.8" y="14.9" width="5.8" height="2.4" /></bezel>
- <bezel element="text_king"><bounds x="87.8" y="26.8" width="5.8" height="2.4" /></bezel>
- <bezel element="text_queen"><bounds x="87.8" y="36.1" width="5.8" height="2.4" /></bezel>
- <bezel element="text_rook"><bounds x="87.8" y="45.4" width="5.8" height="2.4" /></bezel>
- <bezel element="text_bishop"><bounds x="87.8" y="54.7" width="5.8" height="2.4" /></bezel>
- <bezel element="text_knight"><bounds x="87.8" y="64 " width="5.8" height="2.4" /></bezel>
- <bezel element="text_pion"><bounds x="87.8" y="73.3" width="5.8" height="2.4" /></bezel>
-
- <bezel element="hlb" inputtag="IN.8" inputmask="0x80"><bounds x="87" y="3.1" width="7.4" height="7.4" /><color alpha="0.3" /></bezel>
- <bezel element="hlb" inputtag="IN.8" inputmask="0x40"><bounds x="87" y="12.4" width="7.4" height="7.4" /><color alpha="0.3" /></bezel>
- <bezel element="hlb" inputtag="IN.8" inputmask="0x20"><bounds x="87" y="24.3" width="7.4" height="7.4" /><color alpha="0.3" /></bezel>
- <bezel element="hlb" inputtag="IN.8" inputmask="0x10"><bounds x="87" y="33.6" width="7.4" height="7.4" /><color alpha="0.3" /></bezel>
- <bezel element="hlb" inputtag="IN.8" inputmask="0x08"><bounds x="87" y="42.9" width="7.4" height="7.4" /><color alpha="0.3" /></bezel>
- <bezel element="hlb" inputtag="IN.8" inputmask="0x04"><bounds x="87" y="52.2" width="7.4" height="7.4" /><color alpha="0.3" /></bezel>
- <bezel element="hlb" inputtag="IN.8" inputmask="0x02"><bounds x="87" y="61.5" width="7.4" height="7.4" /><color alpha="0.3" /></bezel>
- <bezel element="hlb" inputtag="IN.8" inputmask="0x01"><bounds x="87" y="70.8" width="7.4" height="7.4" /><color alpha="0.3" /></bezel>
-
+ <bezel element="text_king"><bounds x="87.7" y="20.6" width="4.6" height="4" /></bezel>
+ <bezel element="text_queen"><bounds x="87.7" y="29.9" width="4.6" height="4" /></bezel>
+ <bezel element="text_bishop"><bounds x="87.7" y="39.2" width="4.6" height="4" /></bezel>
+ <bezel element="text_knight"><bounds x="87.7" y="48.5" width="4.6" height="4" /></bezel>
+ <bezel element="text_rook"><bounds x="87.7" y="57.8" width="4.6" height="4" /></bezel>
+ <bezel element="text_pion"><bounds x="87.7" y="67.1" width="4.6" height="4" /></bezel>
+
+ <bezel element="disk_black"><bounds x="87" y="3.1" width="6" height="6" /></bezel>
+ <bezel element="disk_black"><bounds x="87" y="12.4" width="6" height="6" /></bezel>
+ <bezel element="disk_black"><bounds x="87" y="24.3" width="6" height="6" /></bezel>
+ <bezel element="disk_black"><bounds x="87" y="33.6" width="6" height="6" /></bezel>
+ <bezel element="disk_black"><bounds x="87" y="42.9" width="6" height="6" /></bezel>
+ <bezel element="disk_black"><bounds x="87" y="52.2" width="6" height="6" /></bezel>
+ <bezel element="disk_black"><bounds x="87" y="61.5" width="6" height="6" /></bezel>
+ <bezel element="disk_black"><bounds x="87" y="70.8" width="6" height="6" /></bezel>
+
+ <bezel element="disk_white"><bounds x="87.7" y="3.8" width="4.6" height="4.6" /></bezel>
+ <bezel element="disk_white"><bounds x="87.7" y="13.1" width="4.6" height="4.6" /></bezel>
+ <bezel element="disk_white"><bounds x="87.7" y="25.0" width="4.6" height="4.6" /></bezel>
+ <bezel element="disk_white"><bounds x="87.7" y="34.3" width="4.6" height="4.6" /></bezel>
+ <bezel element="disk_white"><bounds x="87.7" y="43.6" width="4.6" height="4.6" /></bezel>
+ <bezel element="disk_white"><bounds x="87.7" y="52.9" width="4.6" height="4.6" /></bezel>
+ <bezel element="disk_white"><bounds x="87.7" y="62.2" width="4.6" height="4.6" /></bezel>
+ <bezel element="disk_white"><bounds x="87.7" y="71.5" width="4.6" height="4.6" /></bezel>
+
+ <bezel element="text_re"><bounds x="87.7" y="4.9" width="4.6" height="2.4" /></bezel>
+ <bezel element="text_cl"><bounds x="87.7" y="14.2" width="4.6" height="2.4" /></bezel>
+ <bezel element="text_pb"><bounds x="87.7" y="26.1" width="4.6" height="2.4" /></bezel>
+ <bezel element="text_pv"><bounds x="87.7" y="35.4" width="4.6" height="2.4" /></bezel>
+ <bezel element="text_lv"><bounds x="87.7" y="44.7" width="4.6" height="2.4" /></bezel>
+ <bezel element="text_tb"><bounds x="87.7" y="54.0" width="4.6" height="2.4" /></bezel>
+ <bezel element="text_dm"><bounds x="87.7" y="63.3" width="4.6" height="2.4" /></bezel>
+ <bezel element="text_rv"><bounds x="87.7" y="72.6" width="4.6" height="2.4" /></bezel>
+
+ <bezel element="hlb" inputtag="IN.8" inputmask="0x80"><bounds x="87" y="3.1" width="6" height="6" /><color alpha="0.3" /></bezel>
+ <bezel element="hlb" inputtag="IN.8" inputmask="0x40"><bounds x="87" y="12.4" width="6" height="6" /><color alpha="0.3" /></bezel>
+ <bezel element="hlb" inputtag="IN.8" inputmask="0x20"><bounds x="87" y="24.3" width="6" height="6" /><color alpha="0.3" /></bezel>
+ <bezel element="hlb" inputtag="IN.8" inputmask="0x10"><bounds x="87" y="33.6" width="6" height="6" /><color alpha="0.3" /></bezel>
+ <bezel element="hlb" inputtag="IN.8" inputmask="0x08"><bounds x="87" y="42.9" width="6" height="6" /><color alpha="0.3" /></bezel>
+ <bezel element="hlb" inputtag="IN.8" inputmask="0x04"><bounds x="87" y="52.2" width="6" height="6" /><color alpha="0.3" /></bezel>
+ <bezel element="hlb" inputtag="IN.8" inputmask="0x02"><bounds x="87" y="61.5" width="6" height="6" /><color alpha="0.3" /></bezel>
+ <bezel element="hlb" inputtag="IN.8" inputmask="0x01"><bounds x="87" y="70.8" width="6" height="6" /><color alpha="0.3" /></bezel>
</view>
</mamelayout>
diff --git a/src/mame/layout/fidel_sc9.lay b/src/mame/layout/fidel_sc9.lay
new file mode 100644
index 00000000000..a3ad25dcafd
--- /dev/null
+++ b/src/mame/layout/fidel_sc9.lay
@@ -0,0 +1,437 @@
+<?xml version="1.0"?>
+<mamelayout version="2">
+
+<!-- other than panel button mappings, layout is identical to vsc -->
+
+<!-- define elements -->
+
+ <element name="static_black"><rect><color red="0.0" green="0.0" blue="0.0" /></rect></element>
+
+ <element name="led" defstate="0">
+ <disk state="1"><color red="1.0" green="0.1" blue="0.15" /></disk>
+ <disk state="0"><color red="0.1" green="0.01" blue="0.015" /></disk>
+ </element>
+
+ <element name="hl" defstate="0">
+ <text string=" ">
+ <bounds x="0.0" y="0.0" width="1.0" height="1.0" />
+ <color red="0.0" green="0.0" blue="0.0" />
+ </text>
+ <disk state="1">
+ <bounds x="0.12" y="0.12" width="0.76" height="0.76" />
+ <color red="1.0" green="1.0" blue="1.0" />
+ </disk>
+ </element>
+ <element name="hlb" defstate="0">
+ <text string=" ">
+ <bounds x="0.0" y="0.0" width="1.0" height="1.0" />
+ <color red="0.0" green="0.0" blue="0.0" />
+ </text>
+ <disk state="1">
+ <bounds x="0.0" y="0.0" width="1.0" height="1.0" />
+ <color red="1.0" green="1.0" blue="1.0" />
+ </disk>
+ </element>
+
+ <element name="black"><rect><color red="0.17" green="0.15" blue="0.15" /></rect></element>
+ <element name="white"><rect><color red="0.81" green="0.8" blue="0.79" /></rect></element>
+ <element name="disk_black"><disk><color red="0.17" green="0.15" blue="0.15" /></disk></element>
+ <element name="disk_white"><disk><color red="0.81" green="0.8" blue="0.79" /></disk></element>
+
+ <element name="text_1">
+ <rect><color red="0.81" green="0.8" blue="0.79" /></rect>
+ <text string="1"><color red="0.01" green="0.01" blue="0.01" /></text>
+ </element>
+ <element name="text_2">
+ <rect><color red="0.81" green="0.8" blue="0.79" /></rect>
+ <text string="2"><color red="0.01" green="0.01" blue="0.01" /></text>
+ </element>
+ <element name="text_3">
+ <rect><color red="0.81" green="0.8" blue="0.79" /></rect>
+ <text string="3"><color red="0.01" green="0.01" blue="0.01" /></text>
+ </element>
+ <element name="text_4">
+ <rect><color red="0.81" green="0.8" blue="0.79" /></rect>
+ <text string="4"><color red="0.01" green="0.01" blue="0.01" /></text>
+ </element>
+ <element name="text_5">
+ <rect><color red="0.81" green="0.8" blue="0.79" /></rect>
+ <text string="5"><color red="0.01" green="0.01" blue="0.01" /></text>
+ </element>
+ <element name="text_6">
+ <rect><color red="0.81" green="0.8" blue="0.79" /></rect>
+ <text string="6"><color red="0.01" green="0.01" blue="0.01" /></text>
+ </element>
+ <element name="text_7">
+ <rect><color red="0.81" green="0.8" blue="0.79" /></rect>
+ <text string="7"><color red="0.01" green="0.01" blue="0.01" /></text>
+ </element>
+ <element name="text_8">
+ <rect><color red="0.81" green="0.8" blue="0.79" /></rect>
+ <text string="8"><color red="0.01" green="0.01" blue="0.01" /></text>
+ </element>
+
+ <element name="text_a">
+ <rect><color red="0.81" green="0.8" blue="0.79" /></rect>
+ <text string="A"><color red="0.01" green="0.01" blue="0.01" /></text>
+ </element>
+ <element name="text_b">
+ <rect><color red="0.81" green="0.8" blue="0.79" /></rect>
+ <text string="B"><color red="0.01" green="0.01" blue="0.01" /></text>
+ </element>
+ <element name="text_c">
+ <rect><color red="0.81" green="0.8" blue="0.79" /></rect>
+ <text string="C"><color red="0.01" green="0.01" blue="0.01" /></text>
+ </element>
+ <element name="text_d">
+ <rect><color red="0.81" green="0.8" blue="0.79" /></rect>
+ <text string="D"><color red="0.01" green="0.01" blue="0.01" /></text>
+ </element>
+ <element name="text_e">
+ <rect><color red="0.81" green="0.8" blue="0.79" /></rect>
+ <text string="E"><color red="0.01" green="0.01" blue="0.01" /></text>
+ </element>
+ <element name="text_f">
+ <rect><color red="0.81" green="0.8" blue="0.79" /></rect>
+ <text string="F"><color red="0.01" green="0.01" blue="0.01" /></text>
+ </element>
+ <element name="text_g">
+ <rect><color red="0.81" green="0.8" blue="0.79" /></rect>
+ <text string="G"><color red="0.01" green="0.01" blue="0.01" /></text>
+ </element>
+ <element name="text_h">
+ <rect><color red="0.81" green="0.8" blue="0.79" /></rect>
+ <text string="H"><color red="0.01" green="0.01" blue="0.01" /></text>
+ </element>
+
+ <element name="text_re">
+ <disk><color red="0.81" green="0.8" blue="0.79" /></disk>
+ <text string="RE"><color red="0.17" green="0.15" blue="0.15" /></text>
+ </element>
+ <element name="text_cl">
+ <disk><color red="0.81" green="0.8" blue="0.79" /></disk>
+ <text string="CL"><color red="0.17" green="0.15" blue="0.15" /></text>
+ </element>
+ <element name="text_pb">
+ <disk><color red="0.81" green="0.8" blue="0.79" /></disk>
+ <text string="PB"><color red="0.17" green="0.15" blue="0.15" /></text>
+ </element>
+ <element name="text_pv">
+ <disk><color red="0.81" green="0.8" blue="0.79" /></disk>
+ <text string="PV"><color red="0.17" green="0.15" blue="0.15" /></text>
+ </element>
+ <element name="text_lv">
+ <disk><color red="0.81" green="0.8" blue="0.79" /></disk>
+ <text string="LV"><color red="0.17" green="0.15" blue="0.15" /></text>
+ </element>
+ <element name="text_tb">
+ <disk><color red="0.81" green="0.8" blue="0.79" /></disk>
+ <text string="TB"><color red="0.17" green="0.15" blue="0.15" /></text>
+ </element>
+ <element name="text_dm">
+ <disk><color red="0.81" green="0.8" blue="0.79" /></disk>
+ <text string="DM"><color red="0.17" green="0.15" blue="0.15" /></text>
+ </element>
+ <element name="text_rv">
+ <disk><color red="0.81" green="0.8" blue="0.79" /></disk>
+ <text string="RV"><color red="0.17" green="0.15" blue="0.15" /></text>
+ </element>
+
+ <element name="text_king">
+ <disk><color red="0.81" green="0.8" blue="0.79" /></disk>
+ <text string="&#x2654;"><color red="0.17" green="0.15" blue="0.15" /></text>
+ </element>
+ <element name="text_queen">
+ <disk><color red="0.81" green="0.8" blue="0.79" /></disk>
+ <text string="&#x2655;"><color red="0.17" green="0.15" blue="0.15" /></text>
+ </element>
+ <element name="text_rook">
+ <disk><color red="0.81" green="0.8" blue="0.79" /></disk>
+ <text string="&#x2656;"><color red="0.17" green="0.15" blue="0.15" /></text>
+ </element>
+ <element name="text_bishop">
+ <disk><color red="0.81" green="0.8" blue="0.79" /></disk>
+ <text string="&#x2657;"><color red="0.17" green="0.15" blue="0.15" /></text>
+ </element>
+ <element name="text_knight">
+ <disk><color red="0.81" green="0.8" blue="0.79" /></disk>
+ <text string="&#x2658;"><color red="0.17" green="0.15" blue="0.15" /></text>
+ </element>
+ <element name="text_pion">
+ <disk><color red="0.81" green="0.8" blue="0.79" /></disk>
+ <text string="&#x2659;"><color red="0.17" green="0.15" blue="0.15" /></text>
+ </element>
+
+
+<!-- build screen -->
+
+ <view name="Internal Layout">
+ <bounds left="-2" right="100" top="-2" bottom="88" />
+ <bezel element="static_black">
+ <bounds left="-2" right="100" top="-2" bottom="88" />
+ </bezel>
+
+ <bezel element="white"><bounds x="-2.5" y="-2.5" width="103" height="90.5" /></bezel>
+
+ <!-- chessboard coords -->
+
+ <bezel element="text_8"><bounds x="-0.8" y="7" width="2" height="2" /></bezel>
+ <bezel element="text_7"><bounds x="-0.8" y="17" width="2" height="2" /></bezel>
+ <bezel element="text_6"><bounds x="-0.8" y="27" width="2" height="2" /></bezel>
+ <bezel element="text_5"><bounds x="-0.8" y="37" width="2" height="2" /></bezel>
+ <bezel element="text_4"><bounds x="-0.8" y="47" width="2" height="2" /></bezel>
+ <bezel element="text_3"><bounds x="-0.8" y="57" width="2" height="2" /></bezel>
+ <bezel element="text_2"><bounds x="-0.8" y="67" width="2" height="2" /></bezel>
+ <bezel element="text_1"><bounds x="-0.8" y="77" width="2" height="2" /></bezel>
+
+ <bezel element="text_a"><bounds x="7" y="85" width="2" height="2" /></bezel>
+ <bezel element="text_b"><bounds x="17" y="85" width="2" height="2" /></bezel>
+ <bezel element="text_c"><bounds x="27" y="85" width="2" height="2" /></bezel>
+ <bezel element="text_d"><bounds x="37" y="85" width="2" height="2" /></bezel>
+ <bezel element="text_e"><bounds x="47" y="85" width="2" height="2" /></bezel>
+ <bezel element="text_f"><bounds x="57" y="85" width="2" height="2" /></bezel>
+ <bezel element="text_g"><bounds x="67" y="85" width="2" height="2" /></bezel>
+ <bezel element="text_h"><bounds x="77" y="85" width="2" height="2" /></bezel>
+
+ <!-- chessboard bezel -->
+
+ <bezel element="black"><bounds x="2" y="2" width="82" height="82" /></bezel>
+ <bezel element="white"><bounds x="3" y="3" width="80" height="80" /></bezel>
+
+ <bezel element="black"><bounds x="13" y="2.5" width="10" height="10.5" /></bezel>
+ <bezel element="black"><bounds x="33" y="2.5" width="10" height="10.5" /></bezel>
+ <bezel element="black"><bounds x="53" y="2.5" width="10" height="10.5" /></bezel>
+ <bezel element="black"><bounds x="73" y="2.5" width="10.5" height="10.5" /></bezel>
+
+ <bezel element="black"><bounds x="2.5" y="13" width="10.5" height="10" /></bezel>
+ <bezel element="black"><bounds x="23" y="13" width="10" height="10" /></bezel>
+ <bezel element="black"><bounds x="43" y="13" width="10" height="10" /></bezel>
+ <bezel element="black"><bounds x="63" y="13" width="10" height="10" /></bezel>
+
+ <bezel element="black"><bounds x="13" y="23" width="10" height="10" /></bezel>
+ <bezel element="black"><bounds x="33" y="23" width="10" height="10" /></bezel>
+ <bezel element="black"><bounds x="53" y="23" width="10" height="10" /></bezel>
+ <bezel element="black"><bounds x="73" y="23" width="10.5" height="10" /></bezel>
+
+ <bezel element="black"><bounds x="2.5" y="33" width="10.5" height="10" /></bezel>
+ <bezel element="black"><bounds x="23" y="33" width="10" height="10" /></bezel>
+ <bezel element="black"><bounds x="43" y="33" width="10" height="10" /></bezel>
+ <bezel element="black"><bounds x="63" y="33" width="10" height="10" /></bezel>
+
+ <bezel element="black"><bounds x="13" y="43" width="10" height="10" /></bezel>
+ <bezel element="black"><bounds x="33" y="43" width="10" height="10" /></bezel>
+ <bezel element="black"><bounds x="53" y="43" width="10" height="10" /></bezel>
+ <bezel element="black"><bounds x="73" y="43" width="10.5" height="10" /></bezel>
+
+ <bezel element="black"><bounds x="2.5" y="53" width="10.5" height="10" /></bezel>
+ <bezel element="black"><bounds x="23" y="53" width="10" height="10" /></bezel>
+ <bezel element="black"><bounds x="43" y="53" width="10" height="10" /></bezel>
+ <bezel element="black"><bounds x="63" y="53" width="10" height="10" /></bezel>
+
+ <bezel element="black"><bounds x="13" y="63" width="10" height="10" /></bezel>
+ <bezel element="black"><bounds x="33" y="63" width="10" height="10" /></bezel>
+ <bezel element="black"><bounds x="53" y="63" width="10" height="10" /></bezel>
+ <bezel element="black"><bounds x="73" y="63" width="10.5" height="10" /></bezel>
+
+ <bezel element="black"><bounds x="2.5" y="73" width="10.5" height="10.5" /></bezel>
+ <bezel element="black"><bounds x="23" y="73" width="10" height="10.5" /></bezel>
+ <bezel element="black"><bounds x="43" y="73" width="10" height="10.5" /></bezel>
+ <bezel element="black"><bounds x="63" y="73" width="10" height="10.5" /></bezel>
+
+ <!-- chessboard leds -->
+
+ <bezel name="0.0" element="led"><bounds x="3.2" y="11.3" width="1.5" height="1.5" /></bezel>
+ <bezel name="1.0" element="led"><bounds x="13.2" y="11.3" width="1.5" height="1.5" /></bezel>
+ <bezel name="2.0" element="led"><bounds x="23.2" y="11.3" width="1.5" height="1.5" /></bezel>
+ <bezel name="3.0" element="led"><bounds x="33.2" y="11.3" width="1.5" height="1.5" /></bezel>
+ <bezel name="4.0" element="led"><bounds x="43.2" y="11.3" width="1.5" height="1.5" /></bezel>
+ <bezel name="5.0" element="led"><bounds x="53.2" y="11.3" width="1.5" height="1.5" /></bezel>
+ <bezel name="6.0" element="led"><bounds x="63.2" y="11.3" width="1.5" height="1.5" /></bezel>
+ <bezel name="7.0" element="led"><bounds x="73.2" y="11.3" width="1.5" height="1.5" /></bezel>
+
+ <bezel name="0.1" element="led"><bounds x="3.2" y="21.3" width="1.5" height="1.5" /></bezel>
+ <bezel name="1.1" element="led"><bounds x="13.2" y="21.3" width="1.5" height="1.5" /></bezel>
+ <bezel name="2.1" element="led"><bounds x="23.2" y="21.3" width="1.5" height="1.5" /></bezel>
+ <bezel name="3.1" element="led"><bounds x="33.2" y="21.3" width="1.5" height="1.5" /></bezel>
+ <bezel name="4.1" element="led"><bounds x="43.2" y="21.3" width="1.5" height="1.5" /></bezel>
+ <bezel name="5.1" element="led"><bounds x="53.2" y="21.3" width="1.5" height="1.5" /></bezel>
+ <bezel name="6.1" element="led"><bounds x="63.2" y="21.3" width="1.5" height="1.5" /></bezel>
+ <bezel name="7.1" element="led"><bounds x="73.2" y="21.3" width="1.5" height="1.5" /></bezel>
+
+ <bezel name="0.2" element="led"><bounds x="3.2" y="31.3" width="1.5" height="1.5" /></bezel>
+ <bezel name="1.2" element="led"><bounds x="13.2" y="31.3" width="1.5" height="1.5" /></bezel>
+ <bezel name="2.2" element="led"><bounds x="23.2" y="31.3" width="1.5" height="1.5" /></bezel>
+ <bezel name="3.2" element="led"><bounds x="33.2" y="31.3" width="1.5" height="1.5" /></bezel>
+ <bezel name="4.2" element="led"><bounds x="43.2" y="31.3" width="1.5" height="1.5" /></bezel>
+ <bezel name="5.2" element="led"><bounds x="53.2" y="31.3" width="1.5" height="1.5" /></bezel>
+ <bezel name="6.2" element="led"><bounds x="63.2" y="31.3" width="1.5" height="1.5" /></bezel>
+ <bezel name="7.2" element="led"><bounds x="73.2" y="31.3" width="1.5" height="1.5" /></bezel>
+
+ <bezel name="0.3" element="led"><bounds x="3.2" y="41.3" width="1.5" height="1.5" /></bezel>
+ <bezel name="1.3" element="led"><bounds x="13.2" y="41.3" width="1.5" height="1.5" /></bezel>
+ <bezel name="2.3" element="led"><bounds x="23.2" y="41.3" width="1.5" height="1.5" /></bezel>
+ <bezel name="3.3" element="led"><bounds x="33.2" y="41.3" width="1.5" height="1.5" /></bezel>
+ <bezel name="4.3" element="led"><bounds x="43.2" y="41.3" width="1.5" height="1.5" /></bezel>
+ <bezel name="5.3" element="led"><bounds x="53.2" y="41.3" width="1.5" height="1.5" /></bezel>
+ <bezel name="6.3" element="led"><bounds x="63.2" y="41.3" width="1.5" height="1.5" /></bezel>
+ <bezel name="7.3" element="led"><bounds x="73.2" y="41.3" width="1.5" height="1.5" /></bezel>
+
+ <bezel name="0.4" element="led"><bounds x="3.2" y="51.3" width="1.5" height="1.5" /></bezel>
+ <bezel name="1.4" element="led"><bounds x="13.2" y="51.3" width="1.5" height="1.5" /></bezel>
+ <bezel name="2.4" element="led"><bounds x="23.2" y="51.3" width="1.5" height="1.5" /></bezel>
+ <bezel name="3.4" element="led"><bounds x="33.2" y="51.3" width="1.5" height="1.5" /></bezel>
+ <bezel name="4.4" element="led"><bounds x="43.2" y="51.3" width="1.5" height="1.5" /></bezel>
+ <bezel name="5.4" element="led"><bounds x="53.2" y="51.3" width="1.5" height="1.5" /></bezel>
+ <bezel name="6.4" element="led"><bounds x="63.2" y="51.3" width="1.5" height="1.5" /></bezel>
+ <bezel name="7.4" element="led"><bounds x="73.2" y="51.3" width="1.5" height="1.5" /></bezel>
+
+ <bezel name="0.5" element="led"><bounds x="3.2" y="61.3" width="1.5" height="1.5" /></bezel>
+ <bezel name="1.5" element="led"><bounds x="13.2" y="61.3" width="1.5" height="1.5" /></bezel>
+ <bezel name="2.5" element="led"><bounds x="23.2" y="61.3" width="1.5" height="1.5" /></bezel>
+ <bezel name="3.5" element="led"><bounds x="33.2" y="61.3" width="1.5" height="1.5" /></bezel>
+ <bezel name="4.5" element="led"><bounds x="43.2" y="61.3" width="1.5" height="1.5" /></bezel>
+ <bezel name="5.5" element="led"><bounds x="53.2" y="61.3" width="1.5" height="1.5" /></bezel>
+ <bezel name="6.5" element="led"><bounds x="63.2" y="61.3" width="1.5" height="1.5" /></bezel>
+ <bezel name="7.5" element="led"><bounds x="73.2" y="61.3" width="1.5" height="1.5" /></bezel>
+
+ <bezel name="0.6" element="led"><bounds x="3.2" y="71.3" width="1.5" height="1.5" /></bezel>
+ <bezel name="1.6" element="led"><bounds x="13.2" y="71.3" width="1.5" height="1.5" /></bezel>
+ <bezel name="2.6" element="led"><bounds x="23.2" y="71.3" width="1.5" height="1.5" /></bezel>
+ <bezel name="3.6" element="led"><bounds x="33.2" y="71.3" width="1.5" height="1.5" /></bezel>
+ <bezel name="4.6" element="led"><bounds x="43.2" y="71.3" width="1.5" height="1.5" /></bezel>
+ <bezel name="5.6" element="led"><bounds x="53.2" y="71.3" width="1.5" height="1.5" /></bezel>
+ <bezel name="6.6" element="led"><bounds x="63.2" y="71.3" width="1.5" height="1.5" /></bezel>
+ <bezel name="7.6" element="led"><bounds x="73.2" y="71.3" width="1.5" height="1.5" /></bezel>
+
+ <bezel name="0.7" element="led"><bounds x="3.2" y="81.3" width="1.5" height="1.5" /></bezel>
+ <bezel name="1.7" element="led"><bounds x="13.2" y="81.3" width="1.5" height="1.5" /></bezel>
+ <bezel name="2.7" element="led"><bounds x="23.2" y="81.3" width="1.5" height="1.5" /></bezel>
+ <bezel name="3.7" element="led"><bounds x="33.2" y="81.3" width="1.5" height="1.5" /></bezel>
+ <bezel name="4.7" element="led"><bounds x="43.2" y="81.3" width="1.5" height="1.5" /></bezel>
+ <bezel name="5.7" element="led"><bounds x="53.2" y="81.3" width="1.5" height="1.5" /></bezel>
+ <bezel name="6.7" element="led"><bounds x="63.2" y="81.3" width="1.5" height="1.5" /></bezel>
+ <bezel name="7.7" element="led"><bounds x="73.2" y="81.3" width="1.5" height="1.5" /></bezel>
+
+ <!-- chessboard sensors -->
+
+ <bezel element="hl" inputtag="IN.0" inputmask="0x80"><bounds x="3" y="3" width="10" height="10" /><color alpha="0.4" /></bezel>
+ <bezel element="hl" inputtag="IN.1" inputmask="0x80"><bounds x="13" y="3" width="10" height="10" /><color alpha="0.2" /></bezel>
+ <bezel element="hl" inputtag="IN.2" inputmask="0x80"><bounds x="23" y="3" width="10" height="10" /><color alpha="0.4" /></bezel>
+ <bezel element="hl" inputtag="IN.3" inputmask="0x80"><bounds x="33" y="3" width="10" height="10" /><color alpha="0.2" /></bezel>
+ <bezel element="hl" inputtag="IN.4" inputmask="0x80"><bounds x="43" y="3" width="10" height="10" /><color alpha="0.4" /></bezel>
+ <bezel element="hl" inputtag="IN.5" inputmask="0x80"><bounds x="53" y="3" width="10" height="10" /><color alpha="0.2" /></bezel>
+ <bezel element="hl" inputtag="IN.6" inputmask="0x80"><bounds x="63" y="3" width="10" height="10" /><color alpha="0.4" /></bezel>
+ <bezel element="hl" inputtag="IN.7" inputmask="0x80"><bounds x="73" y="3" width="10" height="10" /><color alpha="0.2" /></bezel>
+
+ <bezel element="hl" inputtag="IN.0" inputmask="0x40"><bounds x="3" y="13" width="10" height="10" /><color alpha="0.2" /></bezel>
+ <bezel element="hl" inputtag="IN.1" inputmask="0x40"><bounds x="13" y="13" width="10" height="10" /><color alpha="0.4" /></bezel>
+ <bezel element="hl" inputtag="IN.2" inputmask="0x40"><bounds x="23" y="13" width="10" height="10" /><color alpha="0.2" /></bezel>
+ <bezel element="hl" inputtag="IN.3" inputmask="0x40"><bounds x="33" y="13" width="10" height="10" /><color alpha="0.4" /></bezel>
+ <bezel element="hl" inputtag="IN.4" inputmask="0x40"><bounds x="43" y="13" width="10" height="10" /><color alpha="0.2" /></bezel>
+ <bezel element="hl" inputtag="IN.5" inputmask="0x40"><bounds x="53" y="13" width="10" height="10" /><color alpha="0.4" /></bezel>
+ <bezel element="hl" inputtag="IN.6" inputmask="0x40"><bounds x="63" y="13" width="10" height="10" /><color alpha="0.2" /></bezel>
+ <bezel element="hl" inputtag="IN.7" inputmask="0x40"><bounds x="73" y="13" width="10" height="10" /><color alpha="0.4" /></bezel>
+
+ <bezel element="hl" inputtag="IN.0" inputmask="0x20"><bounds x="3" y="23" width="10" height="10" /><color alpha="0.4" /></bezel>
+ <bezel element="hl" inputtag="IN.1" inputmask="0x20"><bounds x="13" y="23" width="10" height="10" /><color alpha="0.2" /></bezel>
+ <bezel element="hl" inputtag="IN.2" inputmask="0x20"><bounds x="23" y="23" width="10" height="10" /><color alpha="0.4" /></bezel>
+ <bezel element="hl" inputtag="IN.3" inputmask="0x20"><bounds x="33" y="23" width="10" height="10" /><color alpha="0.2" /></bezel>
+ <bezel element="hl" inputtag="IN.4" inputmask="0x20"><bounds x="43" y="23" width="10" height="10" /><color alpha="0.4" /></bezel>
+ <bezel element="hl" inputtag="IN.5" inputmask="0x20"><bounds x="53" y="23" width="10" height="10" /><color alpha="0.2" /></bezel>
+ <bezel element="hl" inputtag="IN.6" inputmask="0x20"><bounds x="63" y="23" width="10" height="10" /><color alpha="0.4" /></bezel>
+ <bezel element="hl" inputtag="IN.7" inputmask="0x20"><bounds x="73" y="23" width="10" height="10" /><color alpha="0.2" /></bezel>
+
+ <bezel element="hl" inputtag="IN.0" inputmask="0x10"><bounds x="3" y="33" width="10" height="10" /><color alpha="0.2" /></bezel>
+ <bezel element="hl" inputtag="IN.1" inputmask="0x10"><bounds x="13" y="33" width="10" height="10" /><color alpha="0.4" /></bezel>
+ <bezel element="hl" inputtag="IN.2" inputmask="0x10"><bounds x="23" y="33" width="10" height="10" /><color alpha="0.2" /></bezel>
+ <bezel element="hl" inputtag="IN.3" inputmask="0x10"><bounds x="33" y="33" width="10" height="10" /><color alpha="0.4" /></bezel>
+ <bezel element="hl" inputtag="IN.4" inputmask="0x10"><bounds x="43" y="33" width="10" height="10" /><color alpha="0.2" /></bezel>
+ <bezel element="hl" inputtag="IN.5" inputmask="0x10"><bounds x="53" y="33" width="10" height="10" /><color alpha="0.4" /></bezel>
+ <bezel element="hl" inputtag="IN.6" inputmask="0x10"><bounds x="63" y="33" width="10" height="10" /><color alpha="0.2" /></bezel>
+ <bezel element="hl" inputtag="IN.7" inputmask="0x10"><bounds x="73" y="33" width="10" height="10" /><color alpha="0.4" /></bezel>
+
+ <bezel element="hl" inputtag="IN.0" inputmask="0x08"><bounds x="3" y="43" width="10" height="10" /><color alpha="0.4" /></bezel>
+ <bezel element="hl" inputtag="IN.1" inputmask="0x08"><bounds x="13" y="43" width="10" height="10" /><color alpha="0.2" /></bezel>
+ <bezel element="hl" inputtag="IN.2" inputmask="0x08"><bounds x="23" y="43" width="10" height="10" /><color alpha="0.4" /></bezel>
+ <bezel element="hl" inputtag="IN.3" inputmask="0x08"><bounds x="33" y="43" width="10" height="10" /><color alpha="0.2" /></bezel>
+ <bezel element="hl" inputtag="IN.4" inputmask="0x08"><bounds x="43" y="43" width="10" height="10" /><color alpha="0.4" /></bezel>
+ <bezel element="hl" inputtag="IN.5" inputmask="0x08"><bounds x="53" y="43" width="10" height="10" /><color alpha="0.2" /></bezel>
+ <bezel element="hl" inputtag="IN.6" inputmask="0x08"><bounds x="63" y="43" width="10" height="10" /><color alpha="0.4" /></bezel>
+ <bezel element="hl" inputtag="IN.7" inputmask="0x08"><bounds x="73" y="43" width="10" height="10" /><color alpha="0.2" /></bezel>
+
+ <bezel element="hl" inputtag="IN.0" inputmask="0x04"><bounds x="3" y="53" width="10" height="10" /><color alpha="0.2" /></bezel>
+ <bezel element="hl" inputtag="IN.1" inputmask="0x04"><bounds x="13" y="53" width="10" height="10" /><color alpha="0.4" /></bezel>
+ <bezel element="hl" inputtag="IN.2" inputmask="0x04"><bounds x="23" y="53" width="10" height="10" /><color alpha="0.2" /></bezel>
+ <bezel element="hl" inputtag="IN.3" inputmask="0x04"><bounds x="33" y="53" width="10" height="10" /><color alpha="0.4" /></bezel>
+ <bezel element="hl" inputtag="IN.4" inputmask="0x04"><bounds x="43" y="53" width="10" height="10" /><color alpha="0.2" /></bezel>
+ <bezel element="hl" inputtag="IN.5" inputmask="0x04"><bounds x="53" y="53" width="10" height="10" /><color alpha="0.4" /></bezel>
+ <bezel element="hl" inputtag="IN.6" inputmask="0x04"><bounds x="63" y="53" width="10" height="10" /><color alpha="0.2" /></bezel>
+ <bezel element="hl" inputtag="IN.7" inputmask="0x04"><bounds x="73" y="53" width="10" height="10" /><color alpha="0.4" /></bezel>
+
+ <bezel element="hl" inputtag="IN.0" inputmask="0x02"><bounds x="3" y="63" width="10" height="10" /><color alpha="0.4" /></bezel>
+ <bezel element="hl" inputtag="IN.1" inputmask="0x02"><bounds x="13" y="63" width="10" height="10" /><color alpha="0.2" /></bezel>
+ <bezel element="hl" inputtag="IN.2" inputmask="0x02"><bounds x="23" y="63" width="10" height="10" /><color alpha="0.4" /></bezel>
+ <bezel element="hl" inputtag="IN.3" inputmask="0x02"><bounds x="33" y="63" width="10" height="10" /><color alpha="0.2" /></bezel>
+ <bezel element="hl" inputtag="IN.4" inputmask="0x02"><bounds x="43" y="63" width="10" height="10" /><color alpha="0.4" /></bezel>
+ <bezel element="hl" inputtag="IN.5" inputmask="0x02"><bounds x="53" y="63" width="10" height="10" /><color alpha="0.2" /></bezel>
+ <bezel element="hl" inputtag="IN.6" inputmask="0x02"><bounds x="63" y="63" width="10" height="10" /><color alpha="0.4" /></bezel>
+ <bezel element="hl" inputtag="IN.7" inputmask="0x02"><bounds x="73" y="63" width="10" height="10" /><color alpha="0.2" /></bezel>
+
+ <bezel element="hl" inputtag="IN.0" inputmask="0x01"><bounds x="3" y="73" width="10" height="10" /><color alpha="0.2" /></bezel>
+ <bezel element="hl" inputtag="IN.1" inputmask="0x01"><bounds x="13" y="73" width="10" height="10" /><color alpha="0.4" /></bezel>
+ <bezel element="hl" inputtag="IN.2" inputmask="0x01"><bounds x="23" y="73" width="10" height="10" /><color alpha="0.2" /></bezel>
+ <bezel element="hl" inputtag="IN.3" inputmask="0x01"><bounds x="33" y="73" width="10" height="10" /><color alpha="0.4" /></bezel>
+ <bezel element="hl" inputtag="IN.4" inputmask="0x01"><bounds x="43" y="73" width="10" height="10" /><color alpha="0.2" /></bezel>
+ <bezel element="hl" inputtag="IN.5" inputmask="0x01"><bounds x="53" y="73" width="10" height="10" /><color alpha="0.4" /></bezel>
+ <bezel element="hl" inputtag="IN.6" inputmask="0x01"><bounds x="63" y="73" width="10" height="10" /><color alpha="0.2" /></bezel>
+ <bezel element="hl" inputtag="IN.7" inputmask="0x01"><bounds x="73" y="73" width="10" height="10" /><color alpha="0.4" /></bezel>
+
+ <!-- right side -->
+
+ <bezel name="8.7" element="led"><bounds x="91.95" y="7.25" width="1.5" height="1.5" /></bezel>
+
+ <bezel element="text_king"><bounds x="84.01" y="31.1" width="6" height="6" /></bezel>
+ <bezel element="text_queen"><bounds x="84.01" y="39.9" width="6" height="6" /></bezel>
+ <bezel element="text_bishop"><bounds x="84.01" y="48.7" width="6" height="6" /></bezel>
+ <bezel element="text_knight"><bounds x="84.01" y="57.5" width="6" height="6" /></bezel>
+ <bezel element="text_rook"><bounds x="84.01" y="66.3" width="6" height="6" /></bezel>
+ <bezel element="text_pion"><bounds x="84.01" y="75.1" width="6" height="6" /></bezel>
+
+ <bezel element="disk_black"><bounds x="89" y="13" width="7.4" height="7.4" /></bezel>
+ <bezel element="disk_black"><bounds x="89" y="21.8" width="7.4" height="7.4" /></bezel>
+ <bezel element="disk_black"><bounds x="89" y="30.6" width="7.4" height="7.4" /></bezel>
+ <bezel element="disk_black"><bounds x="89" y="39.4" width="7.4" height="7.4" /></bezel>
+ <bezel element="disk_black"><bounds x="89" y="48.2" width="7.4" height="7.4" /></bezel>
+ <bezel element="disk_black"><bounds x="89" y="57" width="7.4" height="7.4" /></bezel>
+ <bezel element="disk_black"><bounds x="89" y="65.8" width="7.4" height="7.4" /></bezel>
+ <bezel element="disk_black"><bounds x="89" y="74.6" width="7.4" height="7.4" /></bezel>
+
+ <bezel element="disk_white"><bounds x="89.7" y="13.7" width="6" height="6" /></bezel>
+ <bezel element="disk_white"><bounds x="89.7" y="22.5" width="6" height="6" /></bezel>
+ <bezel element="disk_white"><bounds x="89.7" y="31.3" width="6" height="6" /></bezel>
+ <bezel element="disk_white"><bounds x="89.7" y="40.1" width="6" height="6" /></bezel>
+ <bezel element="disk_white"><bounds x="89.7" y="48.9" width="6" height="6" /></bezel>
+ <bezel element="disk_white"><bounds x="89.7" y="57.7" width="6" height="6" /></bezel>
+ <bezel element="disk_white"><bounds x="89.7" y="66.5" width="6" height="6" /></bezel>
+ <bezel element="disk_white"><bounds x="89.7" y="75.3" width="6" height="6" /></bezel>
+
+ <bezel element="text_re"><bounds x="90.2" y="15.2" width="5" height="3" /></bezel>
+ <bezel element="text_cl"><bounds x="90.2" y="24" width="5" height="3" /></bezel>
+ <bezel element="text_pb"><bounds x="90.2" y="32.8" width="5" height="3" /></bezel>
+ <bezel element="text_pv"><bounds x="90.2" y="41.6" width="5" height="3" /></bezel>
+ <bezel element="text_lv"><bounds x="90.2" y="50.4" width="5" height="3" /></bezel>
+ <bezel element="text_tb"><bounds x="90.2" y="59.2" width="5" height="3" /></bezel>
+ <bezel element="text_dm"><bounds x="90.2" y="68" width="5" height="3" /></bezel>
+ <bezel element="text_rv"><bounds x="90.2" y="76.8" width="5" height="3" /></bezel>
+
+ <bezel element="hlb" inputtag="IN.8" inputmask="0x80"><bounds x="89" y="13" width="7.4" height="7.4" /><color alpha="0.3" /></bezel>
+ <bezel element="hlb" inputtag="IN.8" inputmask="0x40"><bounds x="89" y="21.8" width="7.4" height="7.4" /><color alpha="0.3" /></bezel>
+ <bezel element="hlb" inputtag="IN.8" inputmask="0x20"><bounds x="89" y="30.6" width="7.4" height="7.4" /><color alpha="0.3" /></bezel>
+ <bezel element="hlb" inputtag="IN.8" inputmask="0x10"><bounds x="89" y="39.4" width="7.4" height="7.4" /><color alpha="0.3" /></bezel>
+ <bezel element="hlb" inputtag="IN.8" inputmask="0x08"><bounds x="89" y="48.2" width="7.4" height="7.4" /><color alpha="0.3" /></bezel>
+ <bezel element="hlb" inputtag="IN.8" inputmask="0x04"><bounds x="89" y="57" width="7.4" height="7.4" /><color alpha="0.3" /></bezel>
+ <bezel element="hlb" inputtag="IN.8" inputmask="0x02"><bounds x="89" y="65.8" width="7.4" height="7.4" /><color alpha="0.3" /></bezel>
+ <bezel element="hlb" inputtag="IN.8" inputmask="0x01"><bounds x="89" y="74.6" width="7.4" height="7.4" /><color alpha="0.3" /></bezel>
+
+ </view>
+</mamelayout>
diff --git a/src/mame/machine/intv.cpp b/src/mame/machine/intv.cpp
index 391abbd4150..55915b00254 100644
--- a/src/mame/machine/intv.cpp
+++ b/src/mame/machine/intv.cpp
@@ -326,28 +326,6 @@ void intv_state::machine_reset()
void intv_state::machine_start()
{
- // TODO: split these for intvkbd & intvecs??
- for (int i = 0; i < 4; i++)
- {
- char str[8];
- sprintf(str, "KEYPAD%i", i + 1);
- m_keypad[i] = ioport(str);
- }
- for (int i = 0; i < 4; i++)
- {
- char str[6];
- sprintf(str, "DISC%i", i + 1);
- m_disc[i] = ioport(str);
- }
- for (int i = 0; i < 4; i++)
- {
- char str[7];
- sprintf(str, "DISCX%i", i + 1);
- m_discx[i] = ioport(str);
- sprintf(str, "DISCY%i", i + 1);
- m_discy[i] = ioport(str);
- }
-
save_item(NAME(m_bus_copy_mode));
save_item(NAME(m_backtab_row));
save_item(NAME(m_ram16));
@@ -459,74 +437,3 @@ INTERRUPT_GEN_MEMBER(intv_state::intv_interrupt)
m_stic->screenrefresh();
}
-/* hand 0 == left, 1 == right, 2 == ECS hand controller 1, 3 == ECS hand controller 2 */
-UINT8 intv_state::intv_control_r(int hand)
-{
- static const UINT8 keypad_table[] =
- {
- 0xFF, 0x3F, 0x9F, 0x5F, 0xD7, 0xB7, 0x77, 0xDB,
- 0xBB, 0x7B, 0xDD, 0xBD, 0x7D, 0xDE, 0xBE, 0x7E
- };
-
- static const UINT8 disc_table[] =
- {
- 0xF3, 0xE3, 0xE7, 0xF7, 0xF6, 0xE6, 0xEE, 0xFE,
- 0xFC, 0xEC, 0xED, 0xFD, 0xF9, 0xE9, 0xEB, 0xFB
- };
-
- static const UINT8 discyx_table[5][5] =
- {
- { 0xE3, 0xF3, 0xFB, 0xEB, 0xE9 },
- { 0xE7, 0xE3, 0xFB, 0xE9, 0xF9 },
- { 0xF7, 0xF7, 0xFF, 0xFD, 0xFD },
- { 0xF6, 0xE6, 0xFE, 0xEC, 0xED },
- { 0xE6, 0xEE, 0xFE, 0xFC, 0xEC }
- };
-
- int x, y;
- UINT8 rv = 0xFF;
-
- /* keypad */
- x = m_keypad[hand]->read();
- for (y = 0; y < 16; y++)
- {
- if (x & (1 << y))
- {
- rv &= keypad_table[y];
- }
- }
-
- switch ((m_io_options->read() >> hand) & 1)
- {
- case 0: /* disc == digital */
- default:
-
- x = m_disc[hand]->read();
- for (y = 0; y < 16; y++)
- {
- if (x & (1 << y))
- {
- rv &= disc_table[y];
- }
- }
- break;
-
- case 1: /* disc == _fake_ analog */
-
- x = m_discx[hand]->read();
- y = m_discy[hand]->read();
- rv &= discyx_table[y / 32][x / 32];
- }
-
- return rv;
-}
-
-READ8_MEMBER( intv_state::intv_left_control_r )
-{
- return intv_control_r(0);
-}
-
-READ8_MEMBER( intv_state::intv_right_control_r )
-{
- return intv_control_r(1);
-}
diff --git a/src/mame/machine/m3comm.cpp b/src/mame/machine/m3comm.cpp
index 1db44f43a10..34f9460796a 100644
--- a/src/mame/machine/m3comm.cpp
+++ b/src/mame/machine/m3comm.cpp
@@ -7,7 +7,9 @@
// TODO:
-// Find out sources of IRQ 2 (flip comm RAM bank) and IRQ 5 (data frame exchange cycle start signal on MASTER)
+// does IRQ 2 correct ? or it fired at any IO reg write by host
+// IRQ 5 source (data frame exchange cycle start signal on MASTER), can be some timer or 'token acquired' event ?
+// how exactly comm RAM bank flipping works ?
// Is there any IRQs can be fired to host systems ?
// Implement NAOMI G1-DMA mode
// find out and hook actual networking exchange, some sort of token ring ???
@@ -163,6 +165,8 @@ m3comm_device::m3comm_device(const machine_config &mconfig, const char *tag, dev
void m3comm_device::device_start()
{
+ timer = timer_alloc(TIMER_IRQ5);
+ timer->adjust(attotime::from_usec(10000));
}
//-------------------------------------------------
@@ -191,6 +195,16 @@ UINT16 swapb16(UINT16 data)
return (data << 8) | (data >> 8);
}
+
+void m3comm_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+{
+ if(id != TIMER_IRQ5)
+ return;
+
+ m_commcpu->set_input_line(M68K_IRQ_5, ASSERT_LINE);
+ timer.adjust(attotime::from_usec(10000)); // there is it from actually ??????
+}
+
///////////// Internal MMIO
READ16_MEMBER(m3comm_device::ctrl_r)
@@ -228,6 +242,9 @@ WRITE16_MEMBER(m3comm_device::ctrl_w)
READ16_MEMBER(m3comm_device::ioregs_r)
{
switch (offset) {
+ case 0x00 / 2: // UNK, Model3 host wait it to be NZ then write 0
+ // perhaps Model3 IO regs 0-80 mapped not to M68K C0000-80 ?
+ return 1;
case 0x10 / 2: // receive result/status
return 5; // dbg random
case 0x18 / 2: // transmit result/status
@@ -245,18 +262,44 @@ WRITE16_MEMBER(m3comm_device::ioregs_w)
{
switch (offset) {
case 0x14 / 2: // written 80 at data receive enable, 0 then 1 at IRQ6 handler
+ if ((data & 0xFF) != 0x80)
+ m_commcpu->set_input_line(M68K_IRQ_6, CLEAR_LINE);
break; // it seems one of these ^v is IRQ6 ON/ACK, another is data transfer enable
case 0x16 / 2: // written 8C at data receive enable, 0 at IRQ6 handler
if ((data & 0xFF) == 0x8C) {
logerror("M3COMM Receive offs %04x size %04x\n", recv_offset, recv_size);
+/*
+ if (!m_line_rx.is_open())
+ {
+ logerror("M3COMM: listen on %s\n", m_localhost);
+ m_line_rx.open(m_localhost);
+ }
+ if (m_line_rx.is_open())
+ {
+ UINT8 *commram = (UINT8*)membank("comm_ram")->base();
+ m_line_rx.read(&commram[recv_offset], recv_size);
+ }
+*/
+ m_commcpu->set_input_line(M68K_IRQ_6, ASSERT_LINE); // debug hack
}
- m_commcpu->set_input_line(M68K_IRQ_6, ((data & 0xFF) == 0x8C) ? ASSERT_LINE : CLEAR_LINE); // debug hack
break;
case 0x1A / 2: // written 80 at data transmit enable, 0 at IRQ4 handler
break; // it seems one of these ^v is IRQ4 ON/ACK, another is data transfer enable
case 0x1C / 2: // written 8C at data transmit enable, 0 at IRQ4 handler
if ((data & 0xFF) == 0x8C) {
logerror("M3COMM Send offs %04x size %04x\n", send_offset, send_size);
+/*
+ if (!m_line_tx.is_open())
+ {
+ logerror("M3COMM: connect to %s\n", m_remotehost);
+ m_line_tx.open(m_remotehost);
+ }
+ if (m_line_tx.is_open())
+ {
+ UINT8 *commram = (UINT8*)membank("comm_ram")->base();
+ m_line_tx.write(&commram[send_offset], send_size);
+ }
+*/
}
m_commcpu->set_input_line(M68K_IRQ_4, ((data & 0xFF) == 0x8C) ? ASSERT_LINE : CLEAR_LINE); // debug hack
break;
@@ -291,12 +334,12 @@ WRITE16_MEMBER(m3comm_device::ioregs_w)
READ16_MEMBER(m3comm_device::m3_m68k_ram_r)
{
- UINT16 value = m68k_ram[offset];
+ UINT16 value = m68k_ram[offset]; // FIXME endian
return swapb16(value);
}
WRITE16_MEMBER(m3comm_device::m3_m68k_ram_w)
{
- m68k_ram[offset] = swapb16(data);
+ m68k_ram[offset] = swapb16(data); // FIXME endian
}
READ8_MEMBER(m3comm_device::m3_comm_ram_r)
{
@@ -317,6 +360,10 @@ WRITE16_MEMBER(m3comm_device::m3_ioregs_w)
{
UINT16 value = swapb16(data);
ioregs_w(space, offset, value, swapb16(mem_mask));
+
+ // guess, can be asserted at any reg write
+ if (offset == (0x88 / 2))
+ m_commcpu->set_input_line(M68K_IRQ_2, ASSERT_LINE);
}
////////////// NAOMI inerface
@@ -334,11 +381,11 @@ READ16_MEMBER(m3comm_device::naomi_r)
// logerror("M3COMM read @ %08x\n", (naomi_control << 16) | naomi_offset);
UINT16 value;
if (naomi_control & 1)
- value = m68k_ram[naomi_offset / 2];
+ value = m68k_ram[naomi_offset / 2]; // FIXME endian
else {
UINT16 *commram = (UINT16*)membank("comm_ram")->base();
- value = commram[naomi_offset / 2];
+ value = commram[naomi_offset / 2]; // FIXME endian
}
naomi_offset += 2;
return value;
@@ -373,10 +420,10 @@ WRITE16_MEMBER(m3comm_device::naomi_w)
case 2: // 5F7020
// logerror("M3COMM write @ %08x %04x\n", (naomi_control << 16) | naomi_offset, data);
if (naomi_control & 1)
- m68k_ram[naomi_offset / 2] = data;
+ m68k_ram[naomi_offset / 2] = data; // FIXME endian
else {
UINT16 *commram = (UINT16*)membank("comm_ram")->base();
- commram[naomi_offset / 2] = data;
+ commram[naomi_offset / 2] = data; // FIXME endian
}
naomi_offset += 2;
break;
diff --git a/src/mame/machine/m3comm.h b/src/mame/machine/m3comm.h
index 61d2c74f060..6a9a77a4cc4 100644
--- a/src/mame/machine/m3comm.h
+++ b/src/mame/machine/m3comm.h
@@ -46,13 +46,15 @@ public:
DECLARE_WRITE16_MEMBER(naomi_w);
protected:
+ enum { TIMER_IRQ5 = 1 };
+
required_device<ram_device> m_ram;
// device-level overrides
virtual void device_start() override;
virtual void device_reset() override;
virtual void device_reset_after_children() override;
-
+ virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
private:
UINT16 naomi_control;
UINT16 naomi_offset;
@@ -70,6 +72,8 @@ private:
emu_file m_line_tx; // tx line - is differential, simple serial and toslink
char m_localhost[256];
char m_remotehost[256];
+
+ emu_timer *timer;
};
// device type definition
diff --git a/src/mame/mame.lst b/src/mame/mame.lst
index 17183078fa0..1c823acd1d7 100644
--- a/src/mame/mame.lst
+++ b/src/mame/mame.lst
@@ -11806,6 +11806,7 @@ cscg // * German
cscsp // * Spanish
fexcel //
fexcelv //
+fscc9 //
fscc12 //
@source:fidel68k.cpp
@@ -28028,6 +28029,7 @@ garoup // 0253 (c) 1999 SNK
ghostlop // 0228 GhostLop (prototype) 1996? Data East
goalx3 // 0209 (c) 1995 Visco
gowcaizr // 0094 (c) 1995 Technos
+unkneo // prototype
gpilots // 0020 (c) 1991 SNK
gpilotsh // 0020 (c) 1991 SNK
gururin // 0067 (c) 1994 Face
@@ -29946,6 +29948,7 @@ pc_moglf // (c) 1991 Nintendo
pc_mtoid // (c) 1986 Nintendo
pc_ngai2 // (c) 1990 Tecmo (Nintendo of America license)
pc_ngai3 // (c) 1991 Tecmo (Nintendo of America license)
+pc_ttoon //
pc_ngaid // (c) 1989 Tecmo (Nintendo of America license)
pc_pinbt // (c) 1988 Rare (Nintendo of America license)
pc_pwbld // (c) 1991 Taito (Nintendo of America license)
@@ -30709,6 +30712,7 @@ raidendxa2 // (c) 1994 Seibu Kaihatsu + Metrotainment licen
raidendxch //
raidendxg // (c) 1994 Seibu Kaihatsu + Tuning license
raidendxj // (c) 1994 Seibu Kaihatsu
+raidendxja // (c) 1994 Seibu Kaihatsu
raidendxk // (c) 1994 Seibu Kaihatsu
raidendxnl // (c) 1994 Seibu Kaihatsu
raidendxu // (c) 1994 Seibu Kaihatsu + Fabtek license
@@ -32793,6 +32797,7 @@ neraidou // Bootleg?
skylncr // (c) 1995 Bordun International
sstar97 // (c) 199? Bordun International
bdream97 // Bootleg?
+sonikfig // Z Games
@source:skyraid.cpp
skyraid // 009709 1978/03 [6502]
@@ -35817,7 +35822,8 @@ cstlevna // (c) 1987 Konami licensed to Nintendo
drmario // (c) 1990 Nintendo
duckhunt // (c) 1985 Nintendo
excitebk // (c) 1984 Nintendo
-excitebka // (c) 1984 Nintendo
+excitebko // (c) 1984 Nintendo
+excitebkj // (c) 1984 Nintendo
goonies // (c) 1986 Konami
hogalley // (c) 1985 Nintendo
iceclimb // (c) 1984 Nintendo
diff --git a/src/osd/modules/input/input_xinput.cpp b/src/osd/modules/input/input_xinput.cpp
index 7b2a1e5e747..c3725ffbf08 100644
--- a/src/osd/modules/input/input_xinput.cpp
+++ b/src/osd/modules/input/input_xinput.cpp
@@ -98,7 +98,7 @@ xinput_joystick_device * xinput_api_helper::create_xinput_device(running_machine
devinfo = module.devicelist()->create_device1<xinput_joystick_device>(machine, device_name, module, shared_from_this());
// Set the player ID
- devinfo->xinput_state.playerIndex = index;
+ devinfo->xinput_state.player_index = index;
// Assign the caps we captured earlier
devinfo->xinput_state.caps = caps;
@@ -125,7 +125,7 @@ void xinput_joystick_device::poll()
return;
// poll the device first
- HRESULT result = m_xinput_helper->XInputGetState(xinput_state.playerIndex, &xinput_state.xstate);
+ HRESULT result = m_xinput_helper->XInputGetState(xinput_state.player_index, &xinput_state.xstate);
// If we can't poll the device, skip
if (FAILED(result))
@@ -136,27 +136,27 @@ void xinput_joystick_device::poll()
for (int povindex = 0; povindex < XINPUT_MAX_POV; povindex++)
{
int currentPov = xinput_pov_dir[povindex];
- gamepad.rgbPov[currentPov] = (xinput_state.xstate.Gamepad.wButtons & currentPov) ? 0xFF : 0;
+ gamepad.povs[povindex] = (xinput_state.xstate.Gamepad.wButtons & currentPov) ? 0xFF : 0;
}
// Now do the buttons
for (int buttonindex = 0; buttonindex < XINPUT_MAX_BUTTONS; buttonindex++)
{
int currentButton = xinput_buttons[buttonindex];
- gamepad.rgbButtons[buttonindex] = (xinput_state.xstate.Gamepad.wButtons & currentButton) ? 0xFF : 0;
+ gamepad.buttons[buttonindex] = (xinput_state.xstate.Gamepad.wButtons & currentButton) ? 0xFF : 0;
}
// Now grab the axis values
// Each of the thumbstick axis members is a signed value between -32768 and 32767 describing the position of the thumbstick
- // However, the Y axis values are inverted from what MAME expects, so multiply by -1 first
- gamepad.sThumbLX = normalize_absolute_axis(xinput_state.xstate.Gamepad.sThumbLX, XINPUT_AXIS_MINVALUE, XINPUT_AXIS_MAXVALUE);
- gamepad.sThumbLY = normalize_absolute_axis(xinput_state.xstate.Gamepad.sThumbLY * -1, XINPUT_AXIS_MINVALUE, XINPUT_AXIS_MAXVALUE);
- gamepad.sThumbRX = normalize_absolute_axis(xinput_state.xstate.Gamepad.sThumbRX, XINPUT_AXIS_MINVALUE, XINPUT_AXIS_MAXVALUE);
- gamepad.sThumbRY = normalize_absolute_axis(xinput_state.xstate.Gamepad.sThumbRY * -1, XINPUT_AXIS_MINVALUE, XINPUT_AXIS_MAXVALUE);
+ // However, the Y axis values are inverted from what MAME expects, so negate the value
+ gamepad.left_thumb_x = normalize_absolute_axis(xinput_state.xstate.Gamepad.sThumbLX, XINPUT_AXIS_MINVALUE, XINPUT_AXIS_MAXVALUE);
+ gamepad.left_thumb_y = normalize_absolute_axis(-xinput_state.xstate.Gamepad.sThumbLY, XINPUT_AXIS_MINVALUE, XINPUT_AXIS_MAXVALUE);
+ gamepad.right_thumb_x = normalize_absolute_axis(xinput_state.xstate.Gamepad.sThumbRX, XINPUT_AXIS_MINVALUE, XINPUT_AXIS_MAXVALUE);
+ gamepad.right_thumb_y = normalize_absolute_axis(-xinput_state.xstate.Gamepad.sThumbRY, XINPUT_AXIS_MINVALUE, XINPUT_AXIS_MAXVALUE);
// Now the triggers
- gamepad.bLeftTrigger = normalize_absolute_axis(xinput_state.xstate.Gamepad.bLeftTrigger, -255, 255);
- gamepad.bRightTrigger = normalize_absolute_axis(xinput_state.xstate.Gamepad.bRightTrigger, -255, 255);
+ gamepad.left_trigger = normalize_absolute_axis(xinput_state.xstate.Gamepad.bLeftTrigger, 0, 255);
+ gamepad.right_trigger = normalize_absolute_axis(xinput_state.xstate.Gamepad.bRightTrigger, 0, 255);
}
void xinput_joystick_device::reset()
@@ -178,7 +178,7 @@ void xinput_joystick_device::configure()
xinput_axis_name[axisnum],
xinput_axis_ids[axisnum],
generic_axis_get_state,
- &gamepad.sThumbLX + axisnum);
+ &gamepad.left_thumb_x + axisnum);
}
// Populate the POVs
@@ -189,7 +189,7 @@ void xinput_joystick_device::configure()
xinput_pov_names[povnum],
ITEM_ID_OTHER_SWITCH,
generic_button_get_state,
- &gamepad.rgbPov[povnum]);
+ &gamepad.povs[povnum]);
}
// populate the buttons
@@ -199,20 +199,20 @@ void xinput_joystick_device::configure()
xinput_button_names[butnum],
static_cast<input_item_id>(ITEM_ID_BUTTON1 + butnum),
generic_button_get_state,
- &gamepad.rgbButtons[butnum]);
+ &gamepad.buttons[butnum]);
}
device()->add_item(
"Left Trigger",
ITEM_ID_ZAXIS,
generic_axis_get_state,
- &gamepad.bLeftTrigger);
+ &gamepad.left_trigger);
device()->add_item(
"Right Trigger",
ITEM_ID_RZAXIS,
generic_axis_get_state,
- &gamepad.bRightTrigger);
+ &gamepad.right_trigger);
m_configured = true;
}
diff --git a/src/osd/modules/input/input_xinput.h b/src/osd/modules/input/input_xinput.h
index 81ef71ce03f..4474a3f58f7 100644
--- a/src/osd/modules/input/input_xinput.h
+++ b/src/osd/modules/input/input_xinput.h
@@ -70,20 +70,20 @@ static const char *const xinput_button_names[] = {
struct gamepad_state
{
- BYTE rgbButtons[XINPUT_MAX_BUTTONS];
- BYTE rgbPov[XINPUT_MAX_POV];
- LONG bLeftTrigger;
- LONG bRightTrigger;
- LONG sThumbLX;
- LONG sThumbLY;
- LONG sThumbRX;
- LONG sThumbRY;
+ BYTE buttons[XINPUT_MAX_BUTTONS];
+ BYTE povs[XINPUT_MAX_POV];
+ LONG left_trigger;
+ LONG right_trigger;
+ LONG left_thumb_x;
+ LONG left_thumb_y;
+ LONG right_thumb_x;
+ LONG right_thumb_y;
};
// state information for a gamepad; state must be first element
struct xinput_api_state
{
- UINT32 playerIndex;
+ UINT32 player_index;
XINPUT_STATE xstate;
XINPUT_CAPABILITIES caps;
};
diff --git a/src/osd/modules/ipc/raw_tcp_connection.cpp b/src/osd/modules/ipc/raw_tcp_connection.cpp
new file mode 100644
index 00000000000..946aefcafa1
--- /dev/null
+++ b/src/osd/modules/ipc/raw_tcp_connection.cpp
@@ -0,0 +1,29 @@
+// license:BSD-3-Clause
+// copyright-holders:Inaki Baz Castillo,Miodrag Milanovic
+
+#include "raw_tcp_connection.h"
+
+/* Instance methods. */
+
+raw_tcp_connection::raw_tcp_connection(listener* listener, size_t bufferSize) :
+ tcp_connection(bufferSize),
+ m_listener(listener)
+{
+}
+
+raw_tcp_connection::~raw_tcp_connection()
+{
+}
+
+void raw_tcp_connection::user_on_tcp_connection_read()
+{
+ // We may receive multiple packets in the same TCP chunk. If one of them is
+ // a DTLS Close Alert this would be closed (close() called) so we cannot call
+ // our listeners anymore.
+ if (is_closing())
+ return;
+
+ m_listener->on_data_recv(this, m_buffer, m_buffer_data_len);
+
+ m_buffer_data_len = 0;
+}
diff --git a/src/osd/modules/ipc/raw_tcp_connection.h b/src/osd/modules/ipc/raw_tcp_connection.h
new file mode 100644
index 00000000000..7bcfe80bfc6
--- /dev/null
+++ b/src/osd/modules/ipc/raw_tcp_connection.h
@@ -0,0 +1,30 @@
+// license:BSD-3-Clause
+// copyright-holders:Inaki Baz Castillo,Miodrag Milanovic
+
+#ifndef RAW_TCP_CONNECTION_H
+#define RAW_TCP_CONNECTION_H
+
+#include "tcp_connection.h"
+
+
+class raw_tcp_connection : public tcp_connection
+{
+public:
+ class listener
+ {
+ public:
+ virtual ~listener(){ }
+ virtual void on_data_recv(raw_tcp_connection *connection, const uint8_t* data, size_t len) = 0;
+ };
+
+ raw_tcp_connection(listener* listener, size_t bufferSize);
+ virtual ~raw_tcp_connection();
+
+ /* Pure virtual methods inherited from tcp_connection. */
+ virtual void user_on_tcp_connection_read() override;
+
+private:
+ // Passed by argument.
+ listener* m_listener;
+};
+#endif
diff --git a/src/osd/modules/ipc/raw_tcp_server.cpp b/src/osd/modules/ipc/raw_tcp_server.cpp
new file mode 100644
index 00000000000..deaee6c5694
--- /dev/null
+++ b/src/osd/modules/ipc/raw_tcp_server.cpp
@@ -0,0 +1,42 @@
+// license:BSD-3-Clause
+// copyright-holders:Inaki Baz Castillo,Miodrag Milanovic
+
+#include "raw_tcp_server.h"
+#include <string>
+
+#define MAX_TCP_CONNECTIONS_PER_SERVER 10
+
+/* Instance methods. */
+
+raw_tcp_server::raw_tcp_server(uv_loop_t* loop, const std::string &ip, uint16_t port, int backlog, listener* listener, raw_tcp_connection::listener* connListener) :
+ tcp_server(loop, ip, port, backlog),
+ m_listener(listener),
+ m_conn_listener(connListener)
+{
+}
+
+void raw_tcp_server::user_on_tcp_connection_alloc(tcp_connection** connection)
+{
+ // Allocate a new raw_tcp_connection for the raw_tcp_server to handle it.
+ *connection = new raw_tcp_connection(m_conn_listener, 65536);
+}
+
+void raw_tcp_server::user_on_new_tcp_connection(tcp_connection* connection)
+{
+ // Allow just MAX_TCP_CONNECTIONS_PER_SERVER.
+ if (get_num_connections() > MAX_TCP_CONNECTIONS_PER_SERVER)
+ connection->close();
+}
+
+void raw_tcp_server::user_on_tcp_connection_closed(tcp_connection* connection, bool is_closed_by_peer)
+{
+ // Notify the listener.
+ // NOTE: Don't do it if closing (since at this point the listener is already freed).
+ // At the end, this is just called if the connection was remotely closed.
+ if (!is_closing())
+ m_listener->on_raw_tcp_connection_closed(this, static_cast<raw_tcp_connection*>(connection), is_closed_by_peer);
+}
+
+void raw_tcp_server::user_on_tcp_server_closed()
+{
+}
diff --git a/src/osd/modules/ipc/raw_tcp_server.h b/src/osd/modules/ipc/raw_tcp_server.h
new file mode 100644
index 00000000000..576490094e3
--- /dev/null
+++ b/src/osd/modules/ipc/raw_tcp_server.h
@@ -0,0 +1,36 @@
+// license:BSD-3-Clause
+// copyright-holders:Inaki Baz Castillo,Miodrag Milanovic
+
+#ifndef RAW_TCP_SERVER_H
+#define RAW_TCP_SERVER_H
+
+#include "tcp_server.h"
+#include "tcp_connection.h"
+#include "raw_tcp_connection.h"
+#include <uv.h>
+
+class raw_tcp_server : public tcp_server
+{
+public:
+ class listener
+ {
+ public:
+ virtual ~listener() { }
+ virtual void on_raw_tcp_connection_closed(raw_tcp_server* tcpServer, raw_tcp_connection* connection, bool is_closed_by_peer) = 0;
+ };
+
+ raw_tcp_server(uv_loop_t* loop, const std::string &ip, uint16_t port, int backlog, listener* listener, raw_tcp_connection::listener* connListener);
+
+ /* Pure virtual methods inherited from TCPServer. */
+ virtual void user_on_tcp_connection_alloc(tcp_connection** connection) override;
+ virtual void user_on_new_tcp_connection(tcp_connection* connection) override;
+ virtual void user_on_tcp_connection_closed(tcp_connection* connection, bool is_closed_by_peer) override;
+ virtual void user_on_tcp_server_closed() override;
+
+private:
+ // Passed by argument.
+ listener* m_listener;
+ raw_tcp_connection::listener* m_conn_listener;
+};
+
+#endif
diff --git a/src/osd/modules/ipc/rtc_tcp_connection.cpp b/src/osd/modules/ipc/rtc_tcp_connection.cpp
new file mode 100644
index 00000000000..1cc800b7d77
--- /dev/null
+++ b/src/osd/modules/ipc/rtc_tcp_connection.cpp
@@ -0,0 +1,150 @@
+// license:BSD-3-Clause
+// copyright-holders:Inaki Baz Castillo,Miodrag Milanovic
+#include "emu.h"
+#include "rtc_tcp_connection.h"
+
+/* Instance methods. */
+
+rtc_tcp_connection::rtc_tcp_connection(listener* listener, size_t bufferSize) :
+ tcp_connection(bufferSize),
+ m_listener(listener),
+ m_frame_start(0)
+{
+}
+
+rtc_tcp_connection::~rtc_tcp_connection()
+{
+}
+
+inline uint16_t get2bytes(const uint8_t* data, size_t i)
+{
+ return (uint16_t)(data[i + 1]) | ((uint16_t)(data[i])) << 8;
+}
+
+inline void set2bytes(uint8_t* data, size_t i, uint16_t value)
+{
+ data[i + 1] = (uint8_t)(value);
+ data[i] = (uint8_t)(value >> 8);
+}
+
+
+void rtc_tcp_connection::user_on_tcp_connection_read()
+{
+ /*
+ * Framing RFC 4571
+ *
+ * 0 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * ---------------------------------------------------------------
+ * | LENGTH | STUN / DTLS / RTP / RTCP |
+ * ---------------------------------------------------------------
+ *
+ * A 16-bit unsigned integer LENGTH field, coded in network byte order
+ * (big-endian), begins the frame. If LENGTH is non-zero, an RTP or
+ * RTCP packet follows the LENGTH field. The value coded in the LENGTH
+ * field MUST equal the number of octets in the RTP or RTCP packet.
+ * Zero is a valid value for LENGTH, and it codes the null packet.
+ */
+
+ // Be ready to parse more than a single frame in a single TCP chunk.
+ while (true)
+ {
+ // We may receive multiple packets in the same TCP chunk. If one of them is
+ // a DTLS Close Alert this would be closed (Close() called) so we cannot call
+ // our listeners anymore.
+ if (is_closing())
+ return;
+
+ size_t data_len = m_buffer_data_len - m_frame_start;
+ size_t packet_len = 0;
+
+ if (data_len >= 2)
+ packet_len = (size_t)get2bytes(m_buffer + m_frame_start, 0);
+
+ // We have packet_len bytes.
+ if ((data_len >= 2) && data_len >= 2 + packet_len)
+ {
+ const uint8_t* packet = m_buffer + m_frame_start + 2;
+
+ // Notify the listener.
+ if (packet_len != 0)
+ {
+ m_listener->on_packet_recv(this, packet, packet_len);
+ }
+
+ // If there is no more space available in the buffer and that is because
+ // the latest parsed frame filled it, then empty the full buffer.
+ if ((m_frame_start + 2 + packet_len) == m_buffer_size)
+ {
+ osd_printf_error("no more space in the buffer, emptying the buffer data");
+
+ m_frame_start = 0;
+ m_buffer_data_len = 0;
+ }
+ // If there is still space in the buffer, set the beginning of the next
+ // frame to the next position after the parsed frame.
+ else
+ {
+ m_frame_start += 2 + packet_len;
+ }
+
+ // If there is more data in the buffer after the parsed frame then
+ // parse again. Otherwise break here and wait for more data.
+ if (m_buffer_data_len > m_frame_start)
+ {
+ // osd_printf_error("there is more data after the parsed frame, continue parsing");
+
+ continue;
+ }
+ else
+ {
+ break;
+ }
+ }
+ else // Incomplete packet.
+ {
+ // Check if the buffer is full.
+ if (m_buffer_data_len == m_buffer_size)
+ {
+ // First case: the incomplete frame does not begin at position 0 of
+ // the buffer, so move the frame to the position 0.
+ if (m_frame_start != 0)
+ {
+ // osd_printf_error("no more space in the buffer, moving parsed bytes to the beginning of the buffer and wait for more data");
+
+ std::memmove(m_buffer, m_buffer + m_frame_start, m_buffer_size - m_frame_start);
+ m_buffer_data_len = m_buffer_size - m_frame_start;
+ m_frame_start = 0;
+ }
+ // Second case: the incomplete frame begins at position 0 of the buffer.
+ // The frame is too big, so close the connection.
+ else
+ {
+ osd_printf_error("no more space in the buffer for the unfinished frame being parsed, closing the connection");
+
+ // Close the socket.
+ close();
+ }
+ }
+ // The buffer is not full.
+ else
+ {
+ osd_printf_verbose("frame not finished yet, waiting for more data");
+ }
+
+ // Exit the parsing loop.
+ break;
+ }
+ }
+}
+
+void rtc_tcp_connection::send(const uint8_t* data, size_t len)
+{
+ // Write according to Framing RFC 4571.
+
+ uint8_t frame_len[2];
+
+ set2bytes(frame_len, 0, len);
+
+ write(frame_len, 2, data, len);
+}
diff --git a/src/osd/modules/ipc/rtc_tcp_connection.h b/src/osd/modules/ipc/rtc_tcp_connection.h
new file mode 100644
index 00000000000..9ec74b90537
--- /dev/null
+++ b/src/osd/modules/ipc/rtc_tcp_connection.h
@@ -0,0 +1,33 @@
+// license:BSD-3-Clause
+// copyright-holders:Inaki Baz Castillo,Miodrag Milanovic
+
+#ifndef RTC_TCP_CONNECTION_H
+#define RTC_TCP_CONNECTION_H
+
+#include "tcp_connection.h"
+
+
+class rtc_tcp_connection : public tcp_connection
+{
+public:
+ class listener
+ {
+ public:
+ virtual ~listener(){ }
+ virtual void on_packet_recv(rtc_tcp_connection *connection, const uint8_t* data, size_t len) = 0;
+ };
+
+ rtc_tcp_connection(listener* listener, size_t bufferSize);
+ virtual ~rtc_tcp_connection();
+
+ /* Pure virtual methods inherited from tcp_connection. */
+ virtual void user_on_tcp_connection_read() override;
+
+ void send(const uint8_t* data, size_t len);
+
+private:
+ // Passed by argument.
+ listener* m_listener;
+ size_t m_frame_start; // Where the latest frame starts.
+};
+#endif
diff --git a/src/osd/modules/ipc/rtc_tcp_server.cpp b/src/osd/modules/ipc/rtc_tcp_server.cpp
new file mode 100644
index 00000000000..52345454983
--- /dev/null
+++ b/src/osd/modules/ipc/rtc_tcp_server.cpp
@@ -0,0 +1,42 @@
+// license:BSD-3-Clause
+// copyright-holders:Inaki Baz Castillo,Miodrag Milanovic
+
+#include "rtc_tcp_server.h"
+#include <string>
+
+#define MAX_TCP_CONNECTIONS_PER_SERVER 10
+
+/* Instance methods. */
+
+rtc_tcp_server::rtc_tcp_server(uv_loop_t* loop, const std::string &ip, uint16_t port, int backlog, listener* listener, rtc_tcp_connection::listener* connListener) :
+ tcp_server(loop, ip, port, backlog),
+ m_listener(listener),
+ m_conn_listener(connListener)
+{
+}
+
+void rtc_tcp_server::user_on_tcp_connection_alloc(tcp_connection** connection)
+{
+ // Allocate a new rtc_tcp_connection for the rtc_tcp_server to handle it.
+ *connection = new rtc_tcp_connection(m_conn_listener, 65536);
+}
+
+void rtc_tcp_server::user_on_new_tcp_connection(tcp_connection* connection)
+{
+ // Allow just MAX_TCP_CONNECTIONS_PER_SERVER.
+ if (get_num_connections() > MAX_TCP_CONNECTIONS_PER_SERVER)
+ connection->close();
+}
+
+void rtc_tcp_server::user_on_tcp_connection_closed(tcp_connection* connection, bool is_closed_by_peer)
+{
+ // Notify the listener.
+ // NOTE: Don't do it if closing (since at this point the listener is already freed).
+ // At the end, this is just called if the connection was remotely closed.
+ if (!is_closing())
+ m_listener->on_rtc_tcp_connection_closed(this, static_cast<rtc_tcp_connection*>(connection), is_closed_by_peer);
+}
+
+void rtc_tcp_server::user_on_tcp_server_closed()
+{
+}
diff --git a/src/osd/modules/ipc/rtc_tcp_server.h b/src/osd/modules/ipc/rtc_tcp_server.h
new file mode 100644
index 00000000000..f0733c95397
--- /dev/null
+++ b/src/osd/modules/ipc/rtc_tcp_server.h
@@ -0,0 +1,36 @@
+// license:BSD-3-Clause
+// copyright-holders:Inaki Baz Castillo,Miodrag Milanovic
+
+#ifndef RTC_TCP_SERVER_H
+#define RTC_TCP_SERVER_H
+
+#include "tcp_server.h"
+#include "tcp_connection.h"
+#include "rtc_tcp_connection.h"
+#include <uv.h>
+
+class rtc_tcp_server : public tcp_server
+{
+public:
+ class listener
+ {
+ public:
+ virtual ~listener() { }
+ virtual void on_rtc_tcp_connection_closed(rtc_tcp_server* tcpServer, rtc_tcp_connection* connection, bool is_closed_by_peer) = 0;
+ };
+
+ rtc_tcp_server(uv_loop_t* loop, const std::string &ip, uint16_t port, int backlog, listener* listener, rtc_tcp_connection::listener* connListener);
+
+ /* Pure virtual methods inherited from TCPServer. */
+ virtual void user_on_tcp_connection_alloc(tcp_connection** connection) override;
+ virtual void user_on_new_tcp_connection(tcp_connection* connection) override;
+ virtual void user_on_tcp_connection_closed(tcp_connection* connection, bool is_closed_by_peer) override;
+ virtual void user_on_tcp_server_closed() override;
+
+private:
+ // Passed by argument.
+ listener* m_listener;
+ rtc_tcp_connection::listener* m_conn_listener;
+};
+
+#endif
diff --git a/src/osd/modules/ipc/tcp_connection.cpp b/src/osd/modules/ipc/tcp_connection.cpp
new file mode 100644
index 00000000000..fb6af2f976a
--- /dev/null
+++ b/src/osd/modules/ipc/tcp_connection.cpp
@@ -0,0 +1,414 @@
+// license:BSD-3-Clause
+// copyright-holders:Inaki Baz Castillo,Miodrag Milanovic
+
+#include "emu.h"
+#include "tcp_connection.h"
+#include <cstdint> // uint8_t, etc
+#include <cstdlib> // std::malloc(), std::free()
+
+/* Static methods for UV callbacks. */
+
+static inline void on_alloc(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf)
+{
+ static_cast<tcp_connection*>(handle->data)->on_uv_read_alloc(suggested_size, buf);
+}
+
+static inline void on_read(uv_stream_t* handle, ssize_t nread, const uv_buf_t* buf)
+{
+ static_cast<tcp_connection*>(handle->data)->on_uv_read(nread, buf);
+}
+
+static inline void on_write(uv_write_t* req, int status)
+{
+ tcp_connection::tcp_uv_write_data* write_data = static_cast<tcp_connection::tcp_uv_write_data*>(req->data);
+ tcp_connection* connection = write_data->connection;
+
+ // Delete the UvWriteData struct (which includes the uv_req_t and the store char[]).
+ std::free(write_data);
+
+ // Just notify the TCPConnection when error.
+ if (status)
+ connection->on_uv_write_error(status);
+}
+
+static inline void on_shutdown(uv_shutdown_t* req, int status)
+{
+ static_cast<tcp_connection*>(req->data)->on_uv_shutdown(req, status);
+}
+
+static inline void on_close(uv_handle_t* handle)
+{
+ static_cast<tcp_connection*>(handle->data)->on_uv_closed();
+}
+
+/* Instance methods. */
+
+tcp_connection::tcp_connection(size_t bufferSize) :
+ m_listener(nullptr),
+ m_local_addr(nullptr),
+ m_is_closing(false),
+ m_is_closed_by_peer(false),
+ m_has_error(false),
+ m_buffer_size(bufferSize),
+ m_buffer(nullptr),
+ m_buffer_data_len(0),
+ m_local_port(0),
+ m_peer_port(0)
+{
+ m_uv_handle = new uv_tcp_t;
+ m_uv_handle->data = (void*)this;
+
+ // NOTE: Don't allocate the buffer here. Instead wait for the first uv_alloc_cb().
+}
+
+tcp_connection::~tcp_connection()
+{
+ if (m_uv_handle)
+ delete m_uv_handle;
+ if (m_buffer)
+ delete[] m_buffer;
+}
+
+void tcp_connection::setup(uv_loop_t* loop, listener* listener, struct sockaddr_storage* localAddr, const std::string &localIP, uint16_t localPort)
+{
+ int err;
+
+ // Set the UV handle.
+ err = uv_tcp_init(loop, m_uv_handle);
+ if (err)
+ {
+ delete m_uv_handle;
+ m_uv_handle = nullptr;
+ throw emu_fatalerror("uv_tcp_init() failed: %s", uv_strerror(err));
+ }
+
+ // Set the listener.
+ m_listener = listener;
+
+ // Set the local address.
+ m_local_addr = localAddr;
+ m_local_ip = localIP;
+ m_local_port = localPort;
+}
+
+void tcp_connection::close()
+{
+ if (m_is_closing)
+ return;
+
+ int err;
+
+ m_is_closing = true;
+
+ // Don't read more.
+ err = uv_read_stop((uv_stream_t*)m_uv_handle);
+ if (err)
+ throw emu_fatalerror("uv_read_stop() failed: %s", uv_strerror(err));
+
+ // If there is no error and the peer didn't close its connection side then close gracefully.
+ if (!m_has_error && !m_is_closed_by_peer)
+ {
+ // Use uv_shutdown() so pending data to be written will be sent to the peer
+ // before closing.
+ uv_shutdown_t* req = new uv_shutdown_t;
+ req->data = (void*)this;
+ err = uv_shutdown(req, (uv_stream_t*)m_uv_handle, (uv_shutdown_cb)on_shutdown);
+ if (err)
+ throw emu_fatalerror("uv_shutdown() failed: %s", uv_strerror(err));
+ }
+ // Otherwise directly close the socket.
+ else
+ {
+ uv_close((uv_handle_t*)m_uv_handle, (uv_close_cb)on_close);
+ }
+}
+
+void tcp_connection::terminate()
+{
+ if (m_is_closing)
+ return;
+ m_is_closing = true;
+ uv_close((uv_handle_t*)m_uv_handle, (uv_close_cb)on_close);
+}
+
+void tcp_connection::dump()
+{
+ osd_printf_verbose("[TCP, local:%s :%d, remote:%s :%d, status:%s]\r\n",
+ m_local_ip.c_str(), (uint16_t)m_local_port,
+ m_peer_ip.c_str(), (uint16_t)m_peer_port,
+ (!m_is_closing) ? "open" : "closed");
+}
+
+void tcp_connection::start()
+{
+ if (m_is_closing)
+ return;
+
+ int err;
+
+ err = uv_read_start((uv_stream_t*)m_uv_handle, (uv_alloc_cb)on_alloc, (uv_read_cb)on_read);
+ if (err)
+ throw emu_fatalerror("uv_read_start() failed: %s", uv_strerror(err));
+
+ // Get the peer address.
+ if (!set_peer_address())
+ throw emu_fatalerror("error setting peer IP and port");
+}
+
+void tcp_connection::write(const uint8_t* data, size_t len)
+{
+ if (m_is_closing)
+ return;
+
+ if (len == 0)
+ return;
+
+ uv_buf_t buffer;
+ int written;
+ int err;
+
+ // First try uv_try_write(). In case it can not directly write all the given
+ // data then build a uv_req_t and use uv_write().
+
+ buffer = uv_buf_init((char*)data, len);
+ written = uv_try_write((uv_stream_t*)m_uv_handle, &buffer, 1);
+
+ // All the data was written. Done.
+ if (written == (int)len)
+ {
+ return;
+ }
+ // Cannot write any data at first time. Use uv_write().
+ else if (written == UV_EAGAIN || written == UV_ENOSYS)
+ {
+ // Set written to 0 so pending_len can be properly calculated.
+ written = 0;
+ }
+ // Error. Should not happen.
+ else if (written < 0)
+ {
+ osd_printf_warning("uv_try_write() failed, closing the connection: %s", uv_strerror(written));
+
+ close();
+ return;
+ }
+
+ // osd_printf_info("could just write %zu bytes (%zu given) at first time, using uv_write() now", (size_t)written, len);
+
+ size_t pending_len = len - written;
+
+ // Allocate a special UvWriteData struct pointer.
+ tcp_uv_write_data* write_data = (tcp_uv_write_data*)std::malloc(sizeof(tcp_uv_write_data) + pending_len);
+
+ write_data->connection = this;
+ std::memcpy(write_data->store, data + written, pending_len);
+ write_data->req.data = (void*)write_data;
+
+ buffer = uv_buf_init((char*)write_data->store, pending_len);
+
+ err = uv_write(&write_data->req, (uv_stream_t*)m_uv_handle, &buffer, 1, (uv_write_cb)on_write);
+ if (err)
+ throw emu_fatalerror("uv_write() failed: %s", uv_strerror(err));
+}
+
+void tcp_connection::write(const uint8_t* data1, size_t len1, const uint8_t* data2, size_t len2)
+{
+ if (m_is_closing)
+ return;
+
+ if (len1 == 0 && len2 == 0)
+ return;
+
+ size_t total_len = len1 + len2;
+ uv_buf_t buffers[2];
+ int written;
+ int err;
+
+ // First try uv_try_write(). In case it can not directly write all the given
+ // data then build a uv_req_t and use uv_write().
+
+ buffers[0] = uv_buf_init((char*)data1, len1);
+ buffers[1] = uv_buf_init((char*)data2, len2);
+ written = uv_try_write((uv_stream_t*)m_uv_handle, buffers, 2);
+
+ // All the data was written. Done.
+ if (written == (int)total_len)
+ {
+ return;
+ }
+ // Cannot write any data at first time. Use uv_write().
+ else if (written == UV_EAGAIN || written == UV_ENOSYS)
+ {
+ // Set written to 0 so pending_len can be properly calculated.
+ written = 0;
+ }
+ // Error. Should not happen.
+ else if (written < 0)
+ {
+ osd_printf_warning("uv_try_write() failed, closing the connection: %s", uv_strerror(written));
+
+ close();
+ return;
+ }
+
+ // osd_printf_info("could just write %zu bytes (%zu given) at first time, using uv_write() now", (size_t)written, total_len);
+
+ size_t pending_len = total_len - written;
+
+ // Allocate a special UvWriteData struct pointer.
+ tcp_uv_write_data* write_data = (tcp_uv_write_data*)std::malloc(sizeof(tcp_uv_write_data) + pending_len);
+
+ write_data->connection = this;
+ // If the first buffer was not entirely written then splice it.
+ if ((size_t)written < len1)
+ {
+ std::memcpy(write_data->store, data1 + (size_t)written, len1 - (size_t)written);
+ std::memcpy(write_data->store + (len1 - (size_t)written), data2, len2);
+ }
+ // Otherwise just take the pending data in the second buffer.
+ else
+ {
+ std::memcpy(write_data->store, data2 + ((size_t)written - len1), len2 - ((size_t)written - len1));
+ }
+ write_data->req.data = (void*)write_data;
+
+ uv_buf_t buffer = uv_buf_init((char*)write_data->store, pending_len);
+
+ err = uv_write(&write_data->req, (uv_stream_t*)m_uv_handle, &buffer, 1, (uv_write_cb)on_write);
+ if (err)
+ throw emu_fatalerror("uv_write() failed: %s", uv_strerror(err));
+}
+
+void GetAddressInfo(const struct sockaddr* addr, int* family, std::string &ip, uint16_t* port)
+{
+ char _ip[INET6_ADDRSTRLEN + 1];
+ int err;
+
+
+ err = uv_inet_ntop(AF_INET, &((struct sockaddr_in*)addr)->sin_addr, _ip, INET_ADDRSTRLEN);
+ if (err)
+ throw emu_fatalerror("uv_inet_ntop() failed: %s", uv_strerror(err));
+ *port = (uint16_t)ntohs(((struct sockaddr_in*)addr)->sin_port);
+
+ *family = addr->sa_family;
+ ip.assign(_ip);
+}
+bool tcp_connection::set_peer_address()
+{
+ int err;
+ int len = sizeof(m_peer_addr);
+
+ err = uv_tcp_getpeername(m_uv_handle, (struct sockaddr*)&m_peer_addr, &len);
+ if (err)
+ {
+ osd_printf_error("uv_tcp_getpeername() failed: %s", uv_strerror(err));
+
+ return false;
+ }
+
+ int family;
+ GetAddressInfo((const struct sockaddr*)&m_peer_addr, &family, m_peer_ip, &m_peer_port);
+
+ return true;
+}
+
+void tcp_connection::on_uv_read_alloc(size_t suggested_size, uv_buf_t* buf)
+{
+ // If this is the first call to onUvReadAlloc() then allocate the receiving buffer now.
+ if (!m_buffer)
+ m_buffer = new uint8_t[m_buffer_size];
+
+ // Tell UV to write after the last data byte in the buffer.
+ buf->base = (char *)(m_buffer + m_buffer_data_len);
+ // Give UV all the remaining space in the buffer.
+ if (m_buffer_size > m_buffer_data_len)
+ {
+ buf->len = m_buffer_size - m_buffer_data_len;
+ }
+ else
+ {
+ buf->len = 0;
+
+ osd_printf_warning("no available space in the buffer");
+ }
+}
+
+void tcp_connection::on_uv_read(::ssize_t nread, const uv_buf_t* buf)
+{
+ if (m_is_closing)
+ return;
+
+ if (nread == 0)
+ return;
+
+ // Data received.
+ if (nread > 0)
+ {
+ // Update the buffer data length.
+ m_buffer_data_len += (size_t)nread;
+
+ // Notify the subclass.
+ user_on_tcp_connection_read();
+ }
+ // Client disconneted.
+ else if (nread == UV_EOF || nread == UV_ECONNRESET)
+ {
+ osd_printf_info("connection closed by peer, closing server side");
+
+ m_is_closed_by_peer = true;
+
+ // Close server side of the connection.
+ close();
+ }
+ // Some error.
+ else
+ {
+ osd_printf_info("read error, closing the connection: %s", uv_strerror(nread));
+
+ m_has_error = true;
+
+ // Close server side of the connection.
+ close();
+ }
+}
+
+void tcp_connection::on_uv_write_error(int error)
+{
+ if (m_is_closing)
+ return;
+
+ if (error == UV_EPIPE || error == UV_ENOTCONN)
+ {
+ osd_printf_info("write error, closing the connection: %s", uv_strerror(error));
+ }
+ else
+ {
+ osd_printf_info("write error, closing the connection: %s", uv_strerror(error));
+
+ m_has_error = true;
+ }
+
+ close();
+}
+
+void tcp_connection::on_uv_shutdown(uv_shutdown_t* req, int status)
+{
+ delete req;
+
+ if (status == UV_EPIPE || status == UV_ENOTCONN || status == UV_ECANCELED)
+ osd_printf_info("shutdown error: %s", uv_strerror(status));
+ else if (status)
+ osd_printf_info("shutdown error: %s", uv_strerror(status));
+
+ // Now do close the handle.
+ uv_close((uv_handle_t*)m_uv_handle, (uv_close_cb)on_close);
+}
+
+void tcp_connection::on_uv_closed()
+{
+ // Notify the listener.
+ m_listener->on_tcp_connection_closed(this, m_is_closed_by_peer);
+
+ // And delete this.
+ delete this;
+}
diff --git a/src/osd/modules/ipc/tcp_connection.h b/src/osd/modules/ipc/tcp_connection.h
new file mode 100644
index 00000000000..55e70d39688
--- /dev/null
+++ b/src/osd/modules/ipc/tcp_connection.h
@@ -0,0 +1,137 @@
+// license:BSD-3-Clause
+// copyright-holders:Inaki Baz Castillo,Miodrag Milanovic
+
+#ifndef TCP_CONNECTION_H
+#define TCP_CONNECTION_H
+
+#include <string>
+#include <uv.h>
+
+extern void GetAddressInfo(const sockaddr * addr, int * family, std::string & ip, uint16_t * port);
+
+class tcp_connection
+{
+public:
+ class listener
+ {
+ public:
+ virtual ~listener() { }
+ virtual void on_tcp_connection_closed(tcp_connection* connection, bool is_closed_by_peer) = 0;
+ };
+
+ /* Struct for the data field of uv_req_t when writing into the connection. */
+ struct tcp_uv_write_data
+ {
+ tcp_connection* connection;
+ uv_write_t req;
+ uint8_t store[1];
+ };
+
+ tcp_connection(size_t bufferSize);
+ virtual ~tcp_connection();
+
+ void close();
+ void terminate();
+ virtual void dump();
+ void setup(uv_loop_t* loop, listener* listener, struct sockaddr_storage* localAddr, const std::string &localIP, uint16_t localPort);
+ bool is_closing();
+ uv_tcp_t* get_uv_handle();
+ void start();
+ void write(const uint8_t* data, size_t len);
+ void write(const uint8_t* data1, size_t len1, const uint8_t* data2, size_t len2);
+ void write(const std::string &data);
+ const struct sockaddr* get_local_address();
+ const std::string& get_local_ip();
+ uint16_t get_local_port();
+ const struct sockaddr* get_peer_address();
+ const std::string& get_peer_ip();
+ uint16_t get_peer_port();
+
+private:
+ bool set_peer_address();
+
+ /* Callbacks fired by UV events. */
+public:
+ void on_uv_read_alloc(size_t suggested_size, uv_buf_t* buf);
+ void on_uv_read(ssize_t nread, const uv_buf_t* buf);
+ void on_uv_write_error(int error);
+ void on_uv_shutdown(uv_shutdown_t* req, int status);
+ void on_uv_closed();
+
+ /* Pure virtual methods that must be implemented by the subclass. */
+protected:
+ virtual void user_on_tcp_connection_read() = 0;
+
+private:
+ // Passed by argument.
+ listener* m_listener;
+ // Allocated by this.
+ uv_tcp_t* m_uv_handle;
+ // Others.
+ struct sockaddr_storage* m_local_addr;
+ bool m_is_closing;
+ bool m_is_closed_by_peer;
+ bool m_has_error;
+
+protected:
+ // Passed by argument.
+ size_t m_buffer_size;
+ // Allocated by this.
+ uint8_t* m_buffer;
+ // Others.
+ size_t m_buffer_data_len;
+ std::string m_local_ip;
+ uint16_t m_local_port;
+ struct sockaddr_storage m_peer_addr;
+ std::string m_peer_ip;
+ uint16_t m_peer_port;
+};
+
+/* Inline methods. */
+
+inline bool tcp_connection::is_closing()
+{
+ return m_is_closing;
+}
+
+inline uv_tcp_t* tcp_connection::get_uv_handle()
+{
+ return m_uv_handle;
+}
+
+inline void tcp_connection::write(const std::string &data)
+{
+ write((const uint8_t*)data.c_str(), data.size());
+}
+
+inline const sockaddr* tcp_connection::get_local_address()
+{
+ return (const struct sockaddr*)m_local_addr;
+}
+
+inline const std::string& tcp_connection::get_local_ip()
+{
+ return m_local_ip;
+}
+
+inline uint16_t tcp_connection::get_local_port()
+{
+ return m_local_port;
+}
+
+inline const sockaddr* tcp_connection::get_peer_address()
+{
+ return (const struct sockaddr*)&m_peer_addr;
+}
+
+inline const std::string& tcp_connection::get_peer_ip()
+{
+ return m_peer_ip;
+}
+
+inline uint16_t tcp_connection::get_peer_port()
+{
+ return m_peer_port;
+}
+
+#endif
diff --git a/src/osd/modules/ipc/tcp_server.cpp b/src/osd/modules/ipc/tcp_server.cpp
new file mode 100644
index 00000000000..a4de2df12d9
--- /dev/null
+++ b/src/osd/modules/ipc/tcp_server.cpp
@@ -0,0 +1,279 @@
+// license:BSD-3-Clause
+// copyright-holders:Inaki Baz Castillo,Miodrag Milanovic
+
+#include "emu.h"
+#include "tcp_server.h"
+
+/* Static methods for UV callbacks. */
+
+static inline void on_connection(uv_stream_t* handle, int status)
+{
+ static_cast<tcp_server*>(handle->data)->on_uv_connection(status);
+}
+
+static inline void on_close(uv_handle_t* handle)
+{
+ static_cast<tcp_server*>(handle->data)->on_uv_closed();
+}
+
+static inline void on_error_close(uv_handle_t* handle)
+{
+ delete handle;
+}
+
+/* Instance methods. */
+
+tcp_server::tcp_server(uv_loop_t* loop, const std::string &ip, uint16_t port, int backlog)
+ : m_uv_handle(nullptr),
+ m_loop(nullptr),
+ m_is_closing(false),
+ m_local_port(0)
+{
+ int err;
+ int flags = 0;
+
+ m_uv_handle = new uv_tcp_t;
+ m_uv_handle->data = (void*)this;
+ m_loop = loop;
+
+ err = uv_tcp_init(loop, m_uv_handle);
+ if (err)
+ {
+ delete m_uv_handle;
+ m_uv_handle = nullptr;
+ throw emu_fatalerror("uv_tcp_init() failed: %s", uv_strerror(err));
+ }
+
+ struct sockaddr_storage bind_addr;
+
+
+ err = uv_ip4_addr(ip.c_str(), (int)port, (struct sockaddr_in*)&bind_addr);
+ if (err)
+ throw emu_fatalerror("uv_ipv4_addr() failed: %s", uv_strerror(err));
+
+ err = uv_tcp_bind(m_uv_handle, (const struct sockaddr*)&bind_addr, flags);
+ if (err)
+ {
+ uv_close((uv_handle_t*)m_uv_handle, (uv_close_cb)on_error_close);
+ throw emu_fatalerror("uv_tcp_bind() failed: %s", uv_strerror(err));
+ }
+
+ err = uv_listen((uv_stream_t*)m_uv_handle, backlog, (uv_connection_cb)on_connection);
+ if (err)
+ {
+ uv_close((uv_handle_t*)m_uv_handle, (uv_close_cb)on_error_close);
+ throw emu_fatalerror("uv_listen() failed: %s", uv_strerror(err));
+ }
+
+ // Set local address.
+ if (!set_local_address())
+ {
+ uv_close((uv_handle_t*)m_uv_handle, (uv_close_cb)on_error_close);
+ throw emu_fatalerror("error setting local IP and port");
+ }
+}
+
+tcp_server::~tcp_server()
+{
+ if (m_uv_handle)
+ delete m_uv_handle;
+}
+
+void tcp_server::close()
+{
+ if (m_is_closing)
+ return;
+
+ m_is_closing = true;
+
+ // If there are no connections then close now.
+ if (m_connections.empty())
+ {
+ uv_close((uv_handle_t*)m_uv_handle, (uv_close_cb)on_close);
+ }
+ // Otherwise close all the connections (but not the TCP server).
+ else
+ {
+ osd_printf_info("closing %d active connections", (int)m_connections.size());
+
+ for (auto it = m_connections.begin(); it != m_connections.end(); ++it)
+ {
+ tcp_connection* connection = *it;
+ connection->close();
+ }
+ }
+}
+
+void tcp_server::terminate()
+{
+ if (m_is_closing)
+ return;
+
+ m_is_closing = true;
+
+ // If there are no connections then close now.
+ if (m_connections.empty())
+ {
+ uv_close((uv_handle_t*)m_uv_handle, (uv_close_cb)on_close);
+ }
+ // Otherwise close all the connections (but not the TCP server).
+ else
+ {
+ osd_printf_info("closing %d active connections", (int)m_connections.size());
+
+ for (auto it = m_connections.begin(); it != m_connections.end(); ++it)
+ {
+ tcp_connection* connection = *it;
+ connection->terminate();
+ }
+ }
+}
+
+void tcp_server::send_to_all(const uint8_t* data, size_t len)
+{
+ // If there are no connections then close now.
+ if (!m_connections.empty())
+ {
+ for (auto it = m_connections.begin(); it != m_connections.end(); ++it)
+ {
+ tcp_connection* connection = *it;
+ connection->write(data, len);
+ }
+ }
+}
+
+void tcp_server::dump()
+{
+ osd_printf_info("[TCP, local:%s :%d, status:%s, connections:%d]",
+ m_local_ip.c_str(), (uint16_t)m_local_port,
+ (!m_is_closing) ? "open" : "closed",
+ (int)m_connections.size());
+}
+
+const sockaddr* tcp_server::get_local_address()
+{
+ return (const struct sockaddr*)&m_local_addr;
+}
+
+const std::string& tcp_server::get_local_ip()
+{
+ return m_local_ip;
+}
+
+uint16_t tcp_server::get_local_port()
+{
+ return m_local_port;
+}
+
+bool tcp_server::set_local_address()
+{
+ int err;
+ int len = sizeof(m_local_addr);
+
+ err = uv_tcp_getsockname(m_uv_handle, (struct sockaddr*)&m_local_addr, &len);
+ if (err)
+ {
+ osd_printf_error("uv_tcp_getsockname() failed: %s", uv_strerror(err));
+
+ return false;
+ }
+
+ int family;
+ GetAddressInfo((const struct sockaddr*)&m_local_addr, &family, m_local_ip, &m_local_port);
+
+ return true;
+}
+
+inline void tcp_server::on_uv_connection(int status)
+{
+ if (m_is_closing)
+ return;
+
+ int err;
+
+ if (status)
+ {
+ osd_printf_error("error while receiving a new TCP connection: %s", uv_strerror(status));
+
+ return;
+ }
+
+ // Notify the subclass so it provides an allocated derived class of TCPConnection.
+ tcp_connection* connection = nullptr;
+ user_on_tcp_connection_alloc(&connection);
+ if (connection != nullptr)
+ osd_printf_error("tcp_server pointer was not allocated by the user");
+
+ try
+ {
+ connection->setup(m_loop, this, &(m_local_addr), m_local_ip, m_local_port);
+ }
+ catch (...)
+ {
+ delete connection;
+ return;
+ }
+
+ // Accept the connection.
+ err = uv_accept((uv_stream_t*)m_uv_handle, (uv_stream_t*)connection->get_uv_handle());
+ if (err)
+ throw emu_fatalerror("uv_accept() failed: %s", uv_strerror(err));
+
+ // Insert the TCPConnection in the set.
+ m_connections.insert(connection);
+
+ // Start receiving data.
+ try
+ {
+ connection->start();
+ }
+ catch (emu_exception &error)
+ {
+ osd_printf_error("cannot run the TCP connection, closing the connection: %s", error.what());
+ connection->close();
+ // NOTE: Don't return here so the user won't be notified about a "onclose" for a TCP connection
+ // for which there was not a previous "onnew" event.
+ }
+
+ osd_printf_info("new TCP connection:");
+ connection->dump();
+
+ // Notify the subclass.
+ user_on_new_tcp_connection(connection);
+}
+
+void tcp_server::on_uv_closed()
+{
+ // Motify the subclass.
+ user_on_tcp_server_closed();
+}
+
+void tcp_server::on_tcp_connection_closed(tcp_connection* connection, bool is_closed_by_peer)
+{
+ // NOTE:
+ // Worst scenario is that in which this is the latest connection,
+ // which is remotely closed (no tcp_server.Close() was called) and the user
+ // call tcp_server.Close() on userOnTCPConnectionClosed() callback, so Close()
+ // is called with zero connections and calls uv_close(), but then
+ // onTCPConnectionClosed() continues and finds that isClosing is true and
+ // there are zero connections, so calls uv_close() again and get a crash.
+ //
+ // SOLUTION:
+ // Check isClosing value *before* onTCPConnectionClosed() callback.
+
+ bool wasClosing = m_is_closing;
+
+ osd_printf_info("TCP connection closed:");
+ connection->dump();
+
+ // Remove the TCPConnection from the set.
+ m_connections.erase(connection);
+
+ // Notify the subclass.
+ user_on_tcp_connection_closed(connection, is_closed_by_peer);
+
+ // Check if the server was closing connections, and if this is the last
+ // connection then close the server now.
+ if (wasClosing && m_connections.empty())
+ uv_close((uv_handle_t*)m_uv_handle, (uv_close_cb)on_close);
+}
diff --git a/src/osd/modules/ipc/tcp_server.h b/src/osd/modules/ipc/tcp_server.h
new file mode 100644
index 00000000000..3a4c75de2d7
--- /dev/null
+++ b/src/osd/modules/ipc/tcp_server.h
@@ -0,0 +1,72 @@
+// license:BSD-3-Clause
+// copyright-holders:Inaki Baz Castillo,Miodrag Milanovic
+
+#ifndef TCP_SERVER_H
+#define TCP_SERVER_H
+
+#include "tcp_connection.h"
+#include <string>
+#include <unordered_set>
+#include <uv.h>
+
+class tcp_server : public tcp_connection::listener
+{
+public:
+ tcp_server(uv_loop_t* m_loop, const std::string &ip, uint16_t port, int backlog);
+ virtual ~tcp_server();
+
+ void close();
+ void terminate();
+ virtual void dump();
+ void send_to_all(const uint8_t* data, size_t len);
+ bool is_closing();
+ const struct sockaddr* get_local_address();
+ const std::string& get_local_ip();
+ uint16_t get_local_port();
+ size_t get_num_connections();
+
+private:
+ bool set_local_address();
+
+ /* Pure virtual methods that must be implemented by the subclass. */
+protected:
+ virtual void user_on_tcp_connection_alloc(tcp_connection** connection) = 0;
+ virtual void user_on_new_tcp_connection(tcp_connection* connection) = 0;
+ virtual void user_on_tcp_connection_closed(tcp_connection* connection, bool is_closed_by_peer) = 0;
+ virtual void user_on_tcp_server_closed() = 0;
+
+ /* Callbacks fired by UV events. */
+public:
+ void on_uv_connection(int status);
+ void on_uv_closed();
+
+ /* Methods inherited from tcp_connection::listener. */
+ virtual void on_tcp_connection_closed(tcp_connection* connection, bool is_closed_by_peer) override;
+
+private:
+ // Allocated by this (may be passed by argument).
+ uv_tcp_t* m_uv_handle;
+ uv_loop_t* m_loop;
+ // Others.
+ std::unordered_set<tcp_connection*> m_connections;
+ bool m_is_closing;
+
+protected:
+ struct sockaddr_storage m_local_addr;
+ std::string m_local_ip;
+ uint16_t m_local_port;
+};
+
+/* Inline methods. */
+
+inline bool tcp_server::is_closing()
+{
+ return m_is_closing;
+}
+
+inline size_t tcp_server::get_num_connections()
+{
+ return m_connections.size();
+}
+
+#endif
diff --git a/src/osd/modules/lib/osdobj_common.cpp b/src/osd/modules/lib/osdobj_common.cpp
index a8856e4ca76..32f1a6047ac 100644
--- a/src/osd/modules/lib/osdobj_common.cpp
+++ b/src/osd/modules/lib/osdobj_common.cpp
@@ -25,6 +25,9 @@ const options_entry osd_options::s_option_entries[] =
{ nullptr, nullptr, OPTION_HEADER, "OSD FONT OPTIONS" },
{ OSD_FONT_PROVIDER, OSDOPTVAL_AUTO, OPTION_STRING, "provider for ui font: " },
+ { nullptr, nullptr, OPTION_HEADER, "OSD OUTPUT OPTIONS" },
+ { OSD_OUTPUT_PROVIDER, OSDOPTVAL_AUTO, OPTION_STRING, "provider for output: " },
+
{ nullptr, nullptr, OPTION_HEADER, "OSD INPUT OPTIONS" },
{ OSD_KEYBOARDINPUT_PROVIDER, OSDOPTVAL_AUTO, OPTION_STRING, "provider for keyboard input: " },
{ OSD_MOUSEINPUT_PROVIDER, OSDOPTVAL_AUTO, OPTION_STRING, "provider for mouse input: " },
@@ -171,7 +174,8 @@ osd_common_t::osd_common_t(osd_options &options)
m_keyboard_input(nullptr),
m_mouse_input(nullptr),
m_lightgun_input(nullptr),
- m_joystick_input(nullptr)
+ m_joystick_input(nullptr),
+ m_output(nullptr)
{
osd_output::push(this);
}
@@ -246,6 +250,11 @@ void osd_common_t::register_options()
REGISTER_MODULE(m_mod_man, JOYSTICKINPUT_XINPUT);
REGISTER_MODULE(m_mod_man, JOYSTICK_NONE);
+ REGISTER_MODULE(m_mod_man, OUTPUT_NONE);
+ REGISTER_MODULE(m_mod_man, OUTPUT_CONSOLE);
+ REGISTER_MODULE(m_mod_man, OUTPUT_NETWORK);
+
+
// after initialization we know which modules are supported
const char *names[20];
@@ -302,6 +311,12 @@ void osd_common_t::register_options()
dnames.push_back(names[i]);
update_option(OSD_DEBUG_PROVIDER, dnames);
+ m_mod_man.get_module_names(OSD_OUTPUT_PROVIDER, 20, &num, names);
+ dnames.clear();
+ for (int i = 0; i < num; i++)
+ dnames.push_back(names[i]);
+ update_option(OSD_OUTPUT_PROVIDER, dnames);
+
// Register video options and update options
video_options_add("none", nullptr);
#if USE_OPENGL
@@ -522,9 +537,9 @@ void osd_common_t::customize_input_type_list(simple_list<input_type_entry> &type
// list of OS-dependent slider values.
//-------------------------------------------------
-slider_state* osd_common_t::get_slider_list()
+std::vector<ui_menu_item> osd_common_t::get_slider_list()
{
- return nullptr;
+ return m_sliders;
}
//-------------------------------------------------
@@ -565,6 +580,12 @@ bool osd_common_t::execute_command(const char *command)
}
+static void output_notifier_callback(const char *outname, INT32 value, void *param)
+{
+ osd_common_t *osd = (osd_common_t*)param;
+ osd->notify(outname, value);
+}
+
void osd_common_t::init_subsystems()
{
if (!video_init())
@@ -576,8 +597,6 @@ void osd_common_t::init_subsystems()
exit(-1);
}
- output_init();
-
m_keyboard_input = select_module_options<input_module *>(options(), OSD_KEYBOARDINPUT_PROVIDER);
m_mouse_input = select_module_options<input_module *>(options(), OSD_MOUSEINPUT_PROVIDER);
m_lightgun_input = select_module_options<input_module *>(options(), OSD_LIGHTGUNINPUT_PROVIDER);
@@ -594,6 +613,9 @@ void osd_common_t::init_subsystems()
m_midi = select_module_options<midi_module *>(options(), OSD_MIDI_PROVIDER);
+ m_output = select_module_options<output_module *>(options(), OSD_OUTPUT_PROVIDER);
+ machine().output().set_notifier(NULL, output_notifier_callback, this);
+
m_mod_man.init(options());
input_init();
@@ -646,16 +668,10 @@ void osd_common_t::input_resume()
m_joystick_input->resume();
}
-bool osd_common_t::output_init()
-{
- return true;
-}
-
void osd_common_t::exit_subsystems()
{
video_exit();
input_exit();
- output_exit();
}
void osd_common_t::video_exit()
@@ -674,10 +690,6 @@ void osd_common_t::input_exit()
m_joystick_input->exit();
}
-void osd_common_t::output_exit()
-{
-}
-
void osd_common_t::osd_exit()
{
m_mod_man.exit();
diff --git a/src/osd/modules/lib/osdobj_common.h b/src/osd/modules/lib/osdobj_common.h
index 0230cfe090d..cd83ba61e7b 100644
--- a/src/osd/modules/lib/osdobj_common.h
+++ b/src/osd/modules/lib/osdobj_common.h
@@ -21,8 +21,11 @@
#include "modules/debugger/debug_module.h"
#include "modules/netdev/netdev_module.h"
#include "modules/midi/midi_module.h"
+#include "modules/output/output_module.h"
#include "cliopts.h"
+class ui_menu_item;
+
//============================================================
// Defines
//============================================================
@@ -188,7 +191,7 @@ public:
virtual void customize_input_type_list(simple_list<input_type_entry> &typelist) override;
// video overridables
- virtual slider_state *get_slider_list() override;
+ virtual std::vector<ui_menu_item> get_slider_list() override;
// command option overrides
virtual bool execute_command(const char *command) override;
@@ -213,13 +216,11 @@ public:
virtual bool window_init();
virtual void input_resume();
- virtual bool output_init();
virtual void exit_subsystems();
virtual void video_exit();
virtual void window_exit();
virtual void input_exit();
- virtual void output_exit();
virtual void osd_exit();
@@ -232,6 +233,7 @@ public:
bool verbose() const { return m_print_verbose; }
void set_verbose(bool print_verbose) { m_print_verbose = print_verbose; }
+ void notify(const char *outname, INT32 value) { m_output->notify(outname, value); }
protected:
virtual bool input_init();
virtual void input_pause();
@@ -278,6 +280,9 @@ protected:
input_module* m_mouse_input;
input_module* m_lightgun_input;
input_module* m_joystick_input;
+ output_module* m_output;
+ std::vector<ui_menu_item> m_sliders;
+
private:
std::vector<const char *> m_video_names;
};
diff --git a/src/osd/modules/osdwindow.cpp b/src/osd/modules/osdwindow.cpp
index 2894092ac30..cde83c3fe7f 100644
--- a/src/osd/modules/osdwindow.cpp
+++ b/src/osd/modules/osdwindow.cpp
@@ -6,14 +6,6 @@
//
//============================================================
-// standard windows headers
-#ifdef OSD_WINDOWS
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-#include <windowsx.h>
-#include <mmsystem.h>
-#endif
-
#include "osdwindow.h"
#include "render/drawnone.h"
diff --git a/src/osd/modules/osdwindow.h b/src/osd/modules/osdwindow.h
index 6ca515dcf5b..60d2cccc700 100644
--- a/src/osd/modules/osdwindow.h
+++ b/src/osd/modules/osdwindow.h
@@ -11,11 +11,20 @@
#include "emu.h"
#include "ui/ui.h"
+#include "ui/menu.h"
#include "osdhelper.h"
+// standard windows headers
+#ifdef OSD_WINDOWS
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#include <windowsx.h>
+#include <mmsystem.h>
+#endif
+
#ifdef OSD_SDL
-// standard SDL headers
-#include "sdlinc.h"
+// forward declaration
+struct SDL_Window;
#endif
//============================================================
@@ -132,11 +141,11 @@ public:
virtual osd_dim get_size() = 0;
-#ifdef OSD_SDL
virtual osd_monitor_info *monitor() const = 0;
+
+#ifdef OSD_SDL
virtual SDL_Window *sdl_window() = 0;
#else
- virtual osd_monitor_info *monitor() const = 0;
virtual bool win_has_menu() = 0;
// FIXME: cann we replace winwindow_video_window_monitor(NULL) with monitor() ?
virtual osd_monitor_info *winwindow_video_window_monitor(const osd_rect *proposed) = 0;
@@ -189,21 +198,23 @@ public:
virtual int create() = 0;
virtual render_primitive_list *get_primitives() = 0;
- virtual slider_state* get_slider_list() { return nullptr; }
+ virtual std::vector<ui_menu_item> get_slider_list() { return m_sliders; }
virtual int draw(const int update) = 0;
virtual int xy_to_render_target(const int x, const int y, int *xt, int *yt) { return 0; };
virtual void save() { };
virtual void record() { };
virtual void toggle_fsfx() { };
virtual bool sliders_dirty() { return m_sliders_dirty; }
- virtual bool multi_window_sliders() { return false; }
static osd_renderer* make_for_type(int mode, osd_window *window, int extra_flags = FLAG_NONE);
protected:
+ virtual void build_slider_list() { }
+
/* Internal flags */
static const int FI_CHANGED = 0x010000;
- bool m_sliders_dirty;
+ bool m_sliders_dirty;
+ std::vector<ui_menu_item> m_sliders;
private:
osd_window *m_window;
diff --git a/src/osd/modules/output/console.cpp b/src/osd/modules/output/console.cpp
new file mode 100644
index 00000000000..753164171ee
--- /dev/null
+++ b/src/osd/modules/output/console.cpp
@@ -0,0 +1,32 @@
+// license:BSD-3-Clause
+// copyright-holders:Miodrag Milanovic
+/***************************************************************************
+
+ console.cpp
+
+ Console output interface.
+
+*******************************************************************c********/
+
+#include "output_module.h"
+#include "modules/osdmodule.h"
+
+class output_console : public osd_module, public output_module
+{
+public:
+ output_console()
+ : osd_module(OSD_OUTPUT_PROVIDER, "console"), output_module()
+ {
+ }
+ virtual ~output_console() { }
+
+ virtual int init(const osd_options &options) override { return 0; }
+ virtual void exit() override { }
+
+ // output_module
+
+ virtual void notify(const char *outname, INT32 value) override { osd_printf_info("%s = %d\n", ((outname==nullptr) ? "none" : outname), value); }
+
+};
+
+MODULE_DEFINITION(OUTPUT_CONSOLE, output_console)
diff --git a/src/osd/modules/output/network.cpp b/src/osd/modules/output/network.cpp
new file mode 100644
index 00000000000..3bca29f3dbb
--- /dev/null
+++ b/src/osd/modules/output/network.cpp
@@ -0,0 +1,86 @@
+// license:BSD-3-Clause
+// copyright-holders:Miodrag Milanovic
+/***************************************************************************
+
+ network.cpp
+
+ Network output interface.
+
+*******************************************************************c********/
+
+#include "output_module.h"
+#include "modules/osdmodule.h"
+#include "modules/ipc/raw_tcp_server.h"
+#include "modules/ipc/raw_tcp_connection.h"
+#include <uv.h>
+
+#include <mutex>
+#include <thread>
+
+class output_network_server :
+ public raw_tcp_server::listener,
+ public raw_tcp_connection::listener
+{
+
+public:
+ output_network_server(uv_loop_t* loop) { m_tcp_server = new raw_tcp_server(loop, "0.0.0.0", 8000, 256, this, this); }
+
+ virtual ~output_network_server() { delete m_tcp_server; }
+
+ void terminate_all() { m_tcp_server->terminate(); }
+ void send_to_all(const uint8_t* data, size_t len) { m_tcp_server->send_to_all(data,len); }
+
+ /* Pure virtual methods inherited from raw_tcp_server::listener. */
+ virtual void on_raw_tcp_connection_closed(raw_tcp_server* tcpServer, raw_tcp_connection* connection, bool is_closed_by_peer) override { }
+ /* Pure virtual methods inherited from raw_tcp_connection::listener. */
+ virtual void on_data_recv(raw_tcp_connection *connection, const uint8_t* data, size_t len) override { }
+private:
+ raw_tcp_server* m_tcp_server;
+};
+
+class output_network : public osd_module, public output_module
+{
+public:
+ output_network()
+ : osd_module(OSD_OUTPUT_PROVIDER, "network"), output_module(), m_loop(nullptr), m_server(nullptr)
+{
+ }
+ virtual ~output_network() {
+ }
+
+ virtual int init(const osd_options &options) override {
+ m_loop = new uv_loop_t;
+ int err = uv_loop_init(m_loop);
+ if (err) {
+ return 1;
+ }
+ m_working_thread = std::thread([](output_network* self) { self->process_output(); }, this);
+ return 0;
+ }
+
+ virtual void exit() override {
+ m_server->terminate_all();
+ m_working_thread.join();
+ uv_loop_close(m_loop);
+ delete m_loop;
+ delete m_server;
+ }
+
+ // output_module
+
+ virtual void notify(const char *outname, INT32 value) override { m_server->send_to_all((const uint8_t*)outname, strlen(outname)); }
+
+ // implementation
+ void process_output()
+ {
+ m_server = new output_network_server(m_loop);
+ uv_run(m_loop, UV_RUN_DEFAULT);
+ }
+
+private:
+ std::thread m_working_thread;
+ uv_loop_t* m_loop;
+ output_network_server *m_server;
+};
+
+MODULE_DEFINITION(OUTPUT_NETWORK, output_network)
diff --git a/src/osd/modules/output/none.cpp b/src/osd/modules/output/none.cpp
new file mode 100644
index 00000000000..1adf6279ce0
--- /dev/null
+++ b/src/osd/modules/output/none.cpp
@@ -0,0 +1,32 @@
+// license:BSD-3-Clause
+// copyright-holders:Miodrag Milanovic
+/***************************************************************************
+
+ none.cpp
+
+ Dummy output interface.
+
+*******************************************************************c********/
+
+#include "output_module.h"
+#include "modules/osdmodule.h"
+
+class output_none : public osd_module, public output_module
+{
+public:
+ output_none()
+ : osd_module(OSD_OUTPUT_PROVIDER, "none"), output_module()
+ {
+ }
+ virtual ~output_none() { }
+
+ virtual int init(const osd_options &options) override { return 0; }
+ virtual void exit() override { }
+
+ // output_module
+
+ virtual void notify(const char *outname, INT32 value) override { }
+
+};
+
+MODULE_DEFINITION(OUTPUT_NONE, output_none)
diff --git a/src/osd/modules/output/output_module.h b/src/osd/modules/output/output_module.h
new file mode 100644
index 00000000000..81fcaae2cce
--- /dev/null
+++ b/src/osd/modules/output/output_module.h
@@ -0,0 +1,30 @@
+// license:BSD-3-Clause
+// copyright-holders:Miodrag Milanovic
+/*
+ * outpout_module.h
+ *
+ */
+
+#ifndef OUTPUT_MODULE_H_
+#define OUTPUT_MODULE_H_
+
+#include "osdepend.h"
+#include "modules/osdmodule.h"
+
+//============================================================
+// CONSTANTS
+//============================================================
+
+#define OSD_OUTPUT_PROVIDER "output"
+
+class output_module
+{
+public:
+ output_module() { }
+
+ virtual ~output_module() { }
+
+ virtual void notify(const char *outname, INT32 value) = 0;
+};
+
+#endif /* OUTPUT_MODULE_H_ */
diff --git a/src/osd/modules/render/bgfx/chain.cpp b/src/osd/modules/render/bgfx/chain.cpp
index 64e5d36f5ca..3cc6e022573 100644
--- a/src/osd/modules/render/bgfx/chain.cpp
+++ b/src/osd/modules/render/bgfx/chain.cpp
@@ -14,18 +14,23 @@
#include "parameter.h"
#include "entryuniform.h"
#include "texturemanager.h"
+#include "targetmanager.h"
+#include "target.h"
#include "vertex.h"
-#include "window.h"
+#include "modules/osdwindow.h"
#include "chain.h"
-bgfx_chain::bgfx_chain(std::string name, std::string author, std::vector<bgfx_slider*> sliders, std::vector<bgfx_parameter*> params, std::vector<bgfx_chain_entry*> entries)
+bgfx_chain::bgfx_chain(std::string name, std::string author, target_manager& targets, std::vector<bgfx_slider*> sliders, std::vector<bgfx_parameter*> params, std::vector<bgfx_chain_entry*> entries, std::vector<bgfx_target*> target_list, std::uint32_t screen_index)
: m_name(name)
, m_author(author)
+ , m_targets(targets)
, m_sliders(sliders)
, m_params(params)
, m_entries(entries)
+ , m_target_list(target_list)
, m_current_time(0)
+ , m_screen_index(screen_index)
{
for (bgfx_slider* slider : m_sliders)
{
@@ -47,6 +52,10 @@ bgfx_chain::~bgfx_chain()
{
delete entry;
}
+ for (bgfx_target* target : m_target_list)
+ {
+ m_targets.destroy_target(target->name(), m_screen_index);
+ }
}
void bgfx_chain::process(render_primitive* prim, int view, int screen, texture_manager& textures, osd_window& window, uint64_t blend)
diff --git a/src/osd/modules/render/bgfx/chain.h b/src/osd/modules/render/bgfx/chain.h
index 9cc300d56a6..bc68d4d5af2 100644
--- a/src/osd/modules/render/bgfx/chain.h
+++ b/src/osd/modules/render/bgfx/chain.h
@@ -21,12 +21,14 @@ class render_primitive;
class bgfx_slider;
class bgfx_parameter;
class texture_manager;
+class target_manager;
+class bgfx_target;
class osd_window;
class bgfx_chain
{
public:
- bgfx_chain(std::string name, std::string author, std::vector<bgfx_slider*> sliders, std::vector<bgfx_parameter*> params, std::vector<bgfx_chain_entry*> entries);
+ bgfx_chain(std::string name, std::string author, target_manager& targets, std::vector<bgfx_slider*> sliders, std::vector<bgfx_parameter*> params, std::vector<bgfx_chain_entry*> entries, std::vector<bgfx_target*> target_list, uint32_t screen_index);
~bgfx_chain();
void process(render_primitive* prim, int view, int screen, texture_manager& textures, osd_window &window, uint64_t blend = 0L);
@@ -38,11 +40,14 @@ public:
private:
std::string m_name;
std::string m_author;
+ target_manager& m_targets;
std::vector<bgfx_slider*> m_sliders;
std::vector<bgfx_parameter*> m_params;
std::vector<bgfx_chain_entry*> m_entries;
+ std::vector<bgfx_target*> m_target_list;
std::map<std::string, bgfx_slider*> m_slider_map;
int64_t m_current_time;
+ uint32_t m_screen_index;
};
#endif // __DRAWBGFX_CHAIN__
diff --git a/src/osd/modules/render/bgfx/chainentry.cpp b/src/osd/modules/render/bgfx/chainentry.cpp
index b8e47eea624..a5f091a554b 100644
--- a/src/osd/modules/render/bgfx/chainentry.cpp
+++ b/src/osd/modules/render/bgfx/chainentry.cpp
@@ -24,6 +24,9 @@
#include "vertex.h"
#include "suppressor.h"
+#include "render.h"
+
+
bgfx_chain_entry::bgfx_chain_entry(std::string name, bgfx_effect* effect, std::vector<bgfx_suppressor*> suppressors, std::vector<bgfx_input_pair> inputs, std::vector<bgfx_entry_uniform*> uniforms, target_manager& targets, std::string output)
: m_name(name)
, m_effect(effect)
diff --git a/src/osd/modules/render/bgfx/chainmanager.cpp b/src/osd/modules/render/bgfx/chainmanager.cpp
index b921ef164b0..5eaf6fc1378 100644
--- a/src/osd/modules/render/bgfx/chainmanager.cpp
+++ b/src/osd/modules/render/bgfx/chainmanager.cpp
@@ -9,12 +9,16 @@
//
//============================================================
+#include "emu.h"
+#include "ui/ui.h"
+#include "ui/menu.h"
+
+#include "osdcore.h"
+#include "modules/osdwindow.h"
+
#include <rapidjson/document.h>
#include <rapidjson/error/en.h>
-#include "emu.h"
-#include "window.h"
-
#include <bx/readerwriter.h>
#include <bx/crtimpl.h>
@@ -28,31 +32,66 @@
#include "target.h"
#include "slider.h"
+#include "sliderdirtynotifier.h"
+
using namespace rapidjson;
-chain_manager::chain_manager(running_machine& machine, osd_options& options, texture_manager& textures, target_manager& targets, effect_manager& effects, uint32_t window_index)
+const uint32_t chain_manager::CHAIN_NONE = 0;
+
+chain_manager::chain_manager(running_machine& machine, osd_options& options, texture_manager& textures, target_manager& targets, effect_manager& effects, uint32_t window_index, slider_dirty_notifier& slider_notifier)
: m_machine(machine)
, m_options(options)
, m_textures(textures)
, m_targets(targets)
, m_effects(effects)
, m_window_index(window_index)
+ , m_slider_notifier(slider_notifier)
+ , m_screen_count(0)
{
- load_screen_chains(options.bgfx_screen_chains());
+ find_available_chains(options.bgfx_path());
+ parse_chain_selections(options.bgfx_screen_chains());
}
chain_manager::~chain_manager()
{
- for (std::vector<bgfx_chain*> screen_chains : m_screen_chains)
- {
- for (bgfx_chain* chain : screen_chains)
- {
- delete chain;
- }
- }
+ destroy_chains();
+}
+
+void chain_manager::find_available_chains(std::string path)
+{
+ m_available_chains.clear();
+ m_available_chains.push_back("none");
+
+ osd_directory *directory = osd_opendir((path + "/chains").c_str());
+ if (directory != nullptr)
+ {
+ for (const osd_directory_entry *entry = osd_readdir(directory); entry != nullptr; entry = osd_readdir(directory))
+ {
+ if (entry->type == ENTTYPE_FILE)
+ {
+ std::string name(entry->name);
+ std::string extension(".json");
+
+ // Does the name has at least one character in addition to ".json"?
+ if (name.length() > extension.length())
+ {
+ size_t start = name.length() - extension.length();
+ std::string test_segment = name.substr(start, extension.length());
+
+ // Does it end in .json?
+ if (test_segment == extension)
+ {
+ m_available_chains.push_back(name.substr(0, start));
+ }
+ }
+ }
+ }
+
+ osd_closedir(directory);
+ }
}
-bgfx_chain* chain_manager::load_chain(std::string name, running_machine& machine, uint32_t window_index, uint32_t screen_index)
+bgfx_chain* chain_manager::load_chain(std::string name, uint32_t screen_index)
{
if (name.length() < 5 || (name.compare(name.length() - 5, 5, ".json")!= 0))
{
@@ -87,7 +126,7 @@ bgfx_chain* chain_manager::load_chain(std::string name, running_machine& machine
return nullptr;
}
- bgfx_chain* chain = chain_reader::read_from_value(document, name + ": ", m_options, machine, window_index, screen_index, m_textures, m_targets, m_effects);
+ bgfx_chain* chain = chain_reader::read_from_value(document, name + ": ", m_options, m_machine, m_window_index, screen_index, m_textures, m_targets, m_effects);
if (chain == nullptr)
{
@@ -98,27 +137,57 @@ bgfx_chain* chain_manager::load_chain(std::string name, running_machine& machine
return chain;
}
-void chain_manager::load_screen_chains(std::string chain_str)
+void chain_manager::parse_chain_selections(std::string chain_str)
{
- std::vector<std::vector<std::string>> chain_names = split_option_string(chain_str);
- load_chains(chain_names);
+ std::vector<std::string> chain_names = split_option_string(chain_str);
+
+ while (m_current_chain.size() != chain_names.size())
+ {
+ m_screen_chains.push_back(nullptr);
+ m_current_chain.push_back(CHAIN_NONE);
+ }
+
+ for (size_t index = 0; index < chain_names.size(); index++)
+ {
+ size_t chain_index = 0;
+ for (chain_index = 0; chain_index < m_available_chains.size(); chain_index++)
+ {
+ if (m_available_chains[chain_index] == chain_names[index])
+ {
+ break;
+ }
+ }
+
+ if (chain_index < m_available_chains.size())
+ {
+ m_current_chain[index] = chain_index;
+ }
+ else
+ {
+ m_current_chain[index] = CHAIN_NONE;
+ }
+ }
}
-std::vector<std::vector<std::string>> chain_manager::split_option_string(std::string chain_str) const
+std::vector<std::string> chain_manager::split_option_string(std::string chain_str) const
{
- std::vector<std::vector<std::string>> chain_names;
- chain_names.push_back(std::vector<std::string>());
+ std::vector<std::string> chain_names;
uint32_t length = chain_str.length();
uint32_t win = 0;
uint32_t last_start = 0;
- for (uint32_t i = 0; i < length + 1; i++) {
- if (i == length || chain_str[i] == ',' || chain_str[i] == ':') {
- chain_names[win].push_back(chain_str.substr(last_start, i - last_start));
+ for (uint32_t i = 0; i < length + 1; i++)
+ {
+ if (i == length || chain_str[i] == ',' || chain_str[i] == ':')
+ {
+ if (win == m_window_index)
+ {
+ chain_names.push_back(chain_str.substr(last_start, i - last_start));
+ }
last_start = i + 1;
- if (chain_str[i] == ':') {
+ if (chain_str[i] == ':')
+ {
win++;
- chain_names.push_back(std::vector<std::string>());
}
}
}
@@ -126,33 +195,44 @@ std::vector<std::vector<std::string>> chain_manager::split_option_string(std::st
return chain_names;
}
-void chain_manager::load_chains(std::vector<std::vector<std::string>>& chain_names)
+void chain_manager::load_chains()
{
- for (uint32_t win = 0; win < chain_names.size(); win++) {
- m_screen_chains.push_back(std::vector<bgfx_chain*>());
- if (win != m_window_index) {
- continue;
+ for (size_t chain = 0; chain < m_current_chain.size() && chain < m_screen_chains.size(); chain++)
+ {
+ if (m_current_chain[chain] != CHAIN_NONE)
+ {
+ m_screen_chains[chain] = load_chain(m_available_chains[m_current_chain[chain]], uint32_t(chain));
}
- for (uint32_t screen = 0; screen < chain_names[win].size(); screen++) {
- bgfx_chain* chain = load_chain(chain_names[win][screen], m_machine, win, screen);
- if (chain == nullptr) {
- chain_names.clear();
- return;
- }
- m_screen_chains[win].push_back(chain);
+ }
+}
+
+void chain_manager::destroy_chains()
+{
+ for (size_t index = 0; index < m_screen_chains.size(); index++)
+ {
+ if (m_screen_chains[index] != nullptr)
+ {
+ delete m_screen_chains[index];
+ m_screen_chains[index] = nullptr;
}
}
}
+void chain_manager::reload_chains()
+{
+ destroy_chains();
+ load_chains();
+}
+
bgfx_chain* chain_manager::screen_chain(uint32_t screen)
{
- if (screen >= m_screen_chains[m_window_index].size())
+ if (screen >= m_screen_chains.size())
{
- return m_screen_chains[m_window_index][m_screen_chains[m_window_index].size() - 1];
+ return m_screen_chains[m_screen_chains.size() - 1];
}
else
{
- return m_screen_chains[m_window_index][screen];
+ return m_screen_chains[screen];
}
}
@@ -184,16 +264,21 @@ std::vector<render_primitive*> chain_manager::count_screens(render_primitive* pr
int screen_count = 0;
std::vector<void*> bases;
- while (prim != nullptr) {
- if (PRIMFLAG_GET_SCREENTEX(prim->flags)) {
+ while (prim != nullptr)
+ {
+ if (PRIMFLAG_GET_SCREENTEX(prim->flags))
+ {
bool found = false;
- for (void* base : bases) {
- if (base == prim->texture.base) {
+ for (void* base : bases)
+ {
+ if (base == prim->texture.base)
+ {
found = true;
break;
}
}
- if (!found) {
+ if (!found)
+ {
screen_count++;
screens.push_back(prim);
bases.push_back(prim->texture.base);
@@ -202,43 +287,120 @@ std::vector<render_primitive*> chain_manager::count_screens(render_primitive* pr
prim = prim->next();
}
- const uint32_t available_chains = m_screen_chains[m_window_index].size();
- if (screen_count >= available_chains)
+ if (screen_count > 0)
{
- screen_count = available_chains;
- }
-
- if (screen_count > 0) {
+ update_screen_count(screen_count);
m_targets.update_screen_count(screen_count);
}
return screens;
}
-uint32_t chain_manager::handle_screen_chains(uint32_t view, render_primitive *starting_prim, osd_window& window) {
- if (m_screen_chains.size() <= m_window_index || m_screen_chains[m_window_index].size() == 0) {
- return 0;
+void chain_manager::update_screen_count(uint32_t screen_count)
+{
+ if (screen_count != m_screen_count)
+ {
+ m_slider_notifier.set_sliders_dirty();
+ m_screen_count = screen_count;
+
+ // Ensure we have one screen chain entry per screen
+ while (m_screen_chains.size() < m_screen_count)
+ {
+ m_screen_chains.push_back(nullptr);
+ m_current_chain.push_back(CHAIN_NONE);
+ }
+
+ // Ensure we have a screen chain selection slider per screen
+ while (m_selection_sliders.size() < m_screen_count)
+ {
+ create_selection_slider(m_selection_sliders.size());
+ }
+
+ load_chains();
+ }
+}
+
+static INT32 update_trampoline(running_machine &machine, void *arg, int id, std::string *str, INT32 newval)
+{
+ if (arg != nullptr)
+ {
+ return reinterpret_cast<chain_manager*>(arg)->chain_changed(id, str, newval);
+ }
+ return 0;
+}
+
+int32_t chain_manager::chain_changed(int32_t id, std::string *str, int32_t newval)
+{
+ if (newval != SLIDER_NOCHANGE)
+ {
+ m_current_chain[id] = newval;
+
+ reload_chains();
+
+ m_slider_notifier.set_sliders_dirty();
+ }
+
+ if (str != nullptr)
+ {
+ *str = string_format("%s", m_available_chains[m_current_chain[id]].c_str());
}
+ return m_current_chain[id];
+}
+
+void chain_manager::create_selection_slider(uint32_t screen_index)
+{
+ if (screen_index < m_selection_sliders.size())
+ {
+ return;
+ }
+
+ std::string description = "Window " + std::to_string(m_window_index) + ", Screen " + std::to_string(screen_index) + " Effect:";
+ size_t size = sizeof(slider_state) + description.length();
+ slider_state *state = reinterpret_cast<slider_state *>(auto_alloc_array_clear(m_machine, UINT8, size));
+
+ state->minval = 0;
+ state->defval = m_current_chain[screen_index];
+ state->maxval = m_available_chains.size() - 1;
+ state->incval = 1;
+ state->update = update_trampoline;
+ state->arg = this;
+ state->id = screen_index;
+ strcpy(state->description, description.c_str());
+
+ ui_menu_item item;
+ item.text = state->description;
+ item.subtext = "";
+ item.flags = 0;
+ item.ref = state;
+ item.type = ui_menu_item_type::UI_MENU_ITEM_TYPE_SLIDER;
+ m_selection_sliders.push_back(item);
+}
+
+uint32_t chain_manager::handle_screen_chains(uint32_t view, render_primitive *starting_prim, osd_window& window)
+{
std::vector<render_primitive*> screens = count_screens(starting_prim);
- if (screens.size() == 0) {
+ if (screens.size() == 0)
+ {
return 0;
}
- const uint32_t available_chains = m_screen_chains[m_window_index].size();
-
// Process each screen as necessary
uint32_t used_views = 0;
- int screen_index = 0;
- for (render_primitive* prim : screens) {
- if (screen_index >= available_chains) {
- break;
+ uint32_t screen_index = 0;
+ for (render_primitive* prim : screens)
+ {
+ if (m_current_chain[screen_index] == CHAIN_NONE)
+ {
+ screen_index++;
+ continue;
}
uint16_t screen_width(floor((prim->bounds.x1 - prim->bounds.x0) + 0.5f));
uint16_t screen_height(floor((prim->bounds.y1 - prim->bounds.y0) + 0.5f));
- if (window.swap_xy()) {
+ if (window.swap_xy())
+ {
std::swap(screen_width, screen_height);
}
@@ -254,34 +416,63 @@ uint32_t chain_manager::handle_screen_chains(uint32_t view, render_primitive *st
return used_views;
}
-bool chain_manager::has_applicable_pass(uint32_t screen)
+bool chain_manager::has_applicable_chain(uint32_t screen)
+{
+ return screen < m_screen_count && m_current_chain[screen] != CHAIN_NONE && m_screen_chains[screen] != nullptr;
+}
+
+bool chain_manager::needs_sliders()
{
- return m_screen_chains.size() > m_window_index && screen < m_screen_chains[m_window_index].size();
+ return m_screen_count > 0 && m_available_chains.size() > 1;
}
-slider_state* chain_manager::get_slider_list()
+std::vector<ui_menu_item> chain_manager::get_slider_list()
{
- if (m_screen_chains.size() <= m_window_index || m_screen_chains[m_window_index].size() == 0) {
- return nullptr;
+ std::vector<ui_menu_item> sliders;
+
+ if (!needs_sliders())
+ {
+ return sliders;
}
- slider_state *listhead = nullptr;
- slider_state **tailptr = &listhead;
- for (std::vector<bgfx_chain*> screen : m_screen_chains) {
- for (bgfx_chain* chain : screen) {
- std::vector<bgfx_slider*> sliders = chain->sliders();
- for (bgfx_slider* slider : sliders) {
- if (*tailptr == nullptr) {
- *tailptr = slider->core_slider();
- } else {
- (*tailptr)->next = slider->core_slider();
- tailptr = &(*tailptr)->next;
- }
- }
+ for (size_t index = 0; index < m_screen_chains.size(); index++)
+ {
+ bgfx_chain* chain = m_screen_chains[index];
+ sliders.push_back(m_selection_sliders[index]);
+
+ if (chain == nullptr)
+ {
+ continue;
}
+
+ std::vector<bgfx_slider*> chain_sliders = chain->sliders();
+ for (bgfx_slider* slider : chain_sliders)
+ {
+ slider_state* core_slider = slider->core_slider();
+
+ ui_menu_item item;
+ item.text = core_slider->description;
+ item.subtext = "";
+ item.flags = 0;
+ item.ref = core_slider;
+ item.type = ui_menu_item_type::UI_MENU_ITEM_TYPE_SLIDER;
+ m_selection_sliders.push_back(item);
+
+ sliders.push_back(item);
+ }
+
+ if (chain_sliders.size() > 0)
+ {
+ ui_menu_item item;
+ item.text = MENU_SEPARATOR_ITEM;
+ item.subtext = "";
+ item.flags = 0;
+ item.ref = nullptr;
+ item.type = ui_menu_item_type::UI_MENU_ITEM_TYPE_SEPARATOR;
+
+ sliders.push_back(item);
+ }
}
- if (*tailptr != nullptr) {
- (*tailptr)->next = nullptr;
- }
- return listhead;
-} \ No newline at end of file
+
+ return sliders;
+}
diff --git a/src/osd/modules/render/bgfx/chainmanager.h b/src/osd/modules/render/bgfx/chainmanager.h
index 5fad1e4d0cc..7d8d0c16eb3 100644
--- a/src/osd/modules/render/bgfx/chainmanager.h
+++ b/src/osd/modules/render/bgfx/chainmanager.h
@@ -23,37 +23,56 @@
class running_machine;
class osd_window;
+class slider_dirty_notifier;
class bgfx_chain;
+class bgfx_slider;
-class chain_manager {
+class chain_manager
+{
public:
- chain_manager(running_machine& machine, osd_options& options, texture_manager& textures, target_manager& targets, effect_manager& effects, uint32_t window_index);
+ chain_manager(running_machine& machine, osd_options& options, texture_manager& textures, target_manager& targets, effect_manager& effects, uint32_t window_index, slider_dirty_notifier& slider_notifier);
~chain_manager();
uint32_t handle_screen_chains(uint32_t view, render_primitive *starting_prim, osd_window& window);
-
+ int32_t chain_changed(int32_t index, std::string *str, int32_t newval);
+
// Getters
bgfx_chain* screen_chain(uint32_t screen);
- bgfx_chain* load_chain(std::string name, running_machine& machine, uint32_t window_index, uint32_t screen_index);
- bool has_applicable_pass(uint32_t screen);
- slider_state* get_slider_list();
+ bgfx_chain* load_chain(std::string name, uint32_t screen_index);
+ bool has_applicable_chain(uint32_t screen);
+ std::vector<ui_menu_item> get_slider_list();
private:
- void load_screen_chains(std::string chain_str);
- std::vector<std::vector<std::string>> split_option_string(std::string chain_str) const;
- void load_chains(std::vector<std::vector<std::string>>& chains);
-
+ void load_chains();
+ void destroy_chains();
+ void reload_chains();
+
+ void find_available_chains(std::string path);
+ void parse_chain_selections(std::string chain_str);
+ std::vector<std::string> split_option_string(std::string chain_str) const;
+
+ void update_screen_count(uint32_t screen_count);
+ void create_selection_slider(uint32_t screen_index);
+ bool needs_sliders();
+
std::vector<render_primitive*> count_screens(render_primitive* prim);
void process_screen_quad(uint32_t view, uint32_t screen, render_primitive* prim, osd_window &window);
- running_machine& m_machine;
- osd_options& m_options;
- texture_manager& m_textures;
- target_manager& m_targets;
- effect_manager& m_effects;
- uint32_t m_window_index;
- std::vector<std::vector<bgfx_chain*>> m_screen_chains;
+ running_machine& m_machine;
+ osd_options& m_options;
+ texture_manager& m_textures;
+ target_manager& m_targets;
+ effect_manager& m_effects;
+ uint32_t m_window_index;
+ slider_dirty_notifier& m_slider_notifier;
+ uint32_t m_screen_count;
+ std::vector<std::string> m_available_chains;
+ std::vector<bgfx_chain*> m_screen_chains;
+ std::vector<ui_menu_item> m_selection_sliders;
+ std::vector<int32_t> m_current_chain;
+
+ static const uint32_t CHAIN_NONE;
};
#endif // __DRAWBGFX_CHAIN_MANAGER__
diff --git a/src/osd/modules/render/bgfx/chainreader.cpp b/src/osd/modules/render/bgfx/chainreader.cpp
index 204e7f1b6ce..332ba139fd0 100644
--- a/src/osd/modules/render/bgfx/chainreader.cpp
+++ b/src/osd/modules/render/bgfx/chainreader.cpp
@@ -84,16 +84,19 @@ bgfx_chain* chain_reader::read_from_value(const Value& value, std::string prefix
}
// Create targets
+ std::vector<bgfx_target*> target_list;
if (value.HasMember("targets"))
{
const Value& target_array = value["targets"];
// TODO: Move into its own reader
for (UINT32 i = 0; i < target_array.Size(); i++)
{
- if (!target_reader::read_from_value(target_array[i], prefix + "targets[" + std::to_string(i) + "]: ", targets, options, screen_index))
+ bgfx_target* target = target_reader::read_from_value(target_array[i], prefix + "targets[" + std::to_string(i) + "]: ", targets, options, screen_index);
+ if (target == nullptr)
{
return nullptr;
}
+ target_list.push_back(target);
}
}
@@ -113,7 +116,7 @@ bgfx_chain* chain_reader::read_from_value(const Value& value, std::string prefix
}
}
- return new bgfx_chain(name, author, sliders, parameters, entries);
+ return new bgfx_chain(name, author, targets, sliders, parameters, entries, target_list, screen_index);
}
bool chain_reader::validate_parameters(const Value& value, std::string prefix)
diff --git a/src/osd/modules/render/bgfx/shaders/chains/default/varying.def.sc b/src/osd/modules/render/bgfx/shaders/chains/default/varying.def.sc
index 4bbc09efebe..2aa3cb425c0 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/default/varying.def.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/default/varying.def.sc
@@ -1,9 +1,5 @@
vec4 v_color0 : COLOR0 = vec4(1.0, 0.0, 0.0, 1.0);
vec2 v_texcoord0 : TEXCOORD0 = vec2(0.0, 0.0);
-vec2 v_texcoord1 : TEXCOORD1 = vec2(0.0, 0.0);
-vec2 v_texcoord2 : TEXCOORD2 = vec2(0.0, 0.0);
-vec2 v_texcoord3 : TEXCOORD3 = vec2(0.0, 0.0);
-vec3 v_pos : TEXCOORD3 = vec3(0.0, 0.0, 0.0);
vec3 a_position : POSITION;
vec4 a_color0 : COLOR0;
diff --git a/src/osd/modules/render/bgfx/shaders/fs_blit.sc b/src/osd/modules/render/bgfx/shaders/chains/hlsl/fs_blit.sc
index 9af7bcf0ee6..9af7bcf0ee6 100644
--- a/src/osd/modules/render/bgfx/shaders/fs_blit.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/hlsl/fs_blit.sc
diff --git a/src/osd/modules/render/bgfx/shaders/fs_color.sc b/src/osd/modules/render/bgfx/shaders/chains/hlsl/fs_color.sc
index faa707f5aa1..faa707f5aa1 100644
--- a/src/osd/modules/render/bgfx/shaders/fs_color.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/hlsl/fs_color.sc
diff --git a/src/osd/modules/render/bgfx/shaders/fs_deconverge.sc b/src/osd/modules/render/bgfx/shaders/chains/hlsl/fs_deconverge.sc
index 0f7d5c4854f..0f7d5c4854f 100644
--- a/src/osd/modules/render/bgfx/shaders/fs_deconverge.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/hlsl/fs_deconverge.sc
diff --git a/src/osd/modules/render/bgfx/shaders/fs_defocus.sc b/src/osd/modules/render/bgfx/shaders/chains/hlsl/fs_defocus.sc
index 77130d98d13..77130d98d13 100644
--- a/src/osd/modules/render/bgfx/shaders/fs_defocus.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/hlsl/fs_defocus.sc
diff --git a/src/osd/modules/render/bgfx/shaders/fs_distortion.sc b/src/osd/modules/render/bgfx/shaders/chains/hlsl/fs_distortion.sc
index 0f69c288c5b..0f69c288c5b 100644
--- a/src/osd/modules/render/bgfx/shaders/fs_distortion.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/hlsl/fs_distortion.sc
diff --git a/src/osd/modules/render/bgfx/shaders/fs_ntsc_decode.sc b/src/osd/modules/render/bgfx/shaders/chains/hlsl/fs_ntsc_decode.sc
index b196674a094..b196674a094 100644
--- a/src/osd/modules/render/bgfx/shaders/fs_ntsc_decode.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/hlsl/fs_ntsc_decode.sc
diff --git a/src/osd/modules/render/bgfx/shaders/fs_ntsc_encode.sc b/src/osd/modules/render/bgfx/shaders/chains/hlsl/fs_ntsc_encode.sc
index 61964c10c30..61964c10c30 100644
--- a/src/osd/modules/render/bgfx/shaders/fs_ntsc_encode.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/hlsl/fs_ntsc_encode.sc
diff --git a/src/osd/modules/render/bgfx/shaders/fs_phosphor.sc b/src/osd/modules/render/bgfx/shaders/chains/hlsl/fs_phosphor.sc
index 52b624b644b..52b624b644b 100644
--- a/src/osd/modules/render/bgfx/shaders/fs_phosphor.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/hlsl/fs_phosphor.sc
diff --git a/src/osd/modules/render/bgfx/shaders/fs_post.sc b/src/osd/modules/render/bgfx/shaders/chains/hlsl/fs_post.sc
index e4a3a984e6b..e4a3a984e6b 100644
--- a/src/osd/modules/render/bgfx/shaders/fs_post.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/hlsl/fs_post.sc
diff --git a/src/osd/modules/render/bgfx/shaders/fs_prescale.sc b/src/osd/modules/render/bgfx/shaders/chains/hlsl/fs_prescale.sc
index e17d867b621..e17d867b621 100644
--- a/src/osd/modules/render/bgfx/shaders/fs_prescale.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/hlsl/fs_prescale.sc
diff --git a/src/osd/modules/render/bgfx/shaders/chains/hlsl/varying.def.sc b/src/osd/modules/render/bgfx/shaders/chains/hlsl/varying.def.sc
new file mode 100644
index 00000000000..53fe40d0b8a
--- /dev/null
+++ b/src/osd/modules/render/bgfx/shaders/chains/hlsl/varying.def.sc
@@ -0,0 +1,9 @@
+vec4 v_color0 : COLOR0 = vec4(1.0, 0.0, 0.0, 1.0);
+vec2 v_texcoord0 : TEXCOORD0 = vec2(0.0, 0.0);
+vec2 v_texcoord1 : TEXCOORD1 = vec2(0.0, 0.0);
+vec2 v_texcoord2 : TEXCOORD2 = vec2(0.0, 0.0);
+vec2 v_texcoord3 : TEXCOORD3 = vec2(0.0, 0.0);
+
+vec3 a_position : POSITION;
+vec4 a_color0 : COLOR0;
+vec2 a_texcoord0 : TEXCOORD0;
diff --git a/src/osd/modules/render/bgfx/shaders/vs_blit.sc b/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_blit.sc
index 405ef8feb3b..405ef8feb3b 100644
--- a/src/osd/modules/render/bgfx/shaders/vs_blit.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_blit.sc
diff --git a/src/osd/modules/render/bgfx/shaders/vs_color.sc b/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_color.sc
index 405ef8feb3b..405ef8feb3b 100644
--- a/src/osd/modules/render/bgfx/shaders/vs_color.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_color.sc
diff --git a/src/osd/modules/render/bgfx/shaders/vs_deconverge.sc b/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_deconverge.sc
index b77d85d1ea8..b77d85d1ea8 100644
--- a/src/osd/modules/render/bgfx/shaders/vs_deconverge.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_deconverge.sc
diff --git a/src/osd/modules/render/bgfx/shaders/vs_defocus.sc b/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_defocus.sc
index 405ef8feb3b..405ef8feb3b 100644
--- a/src/osd/modules/render/bgfx/shaders/vs_defocus.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_defocus.sc
diff --git a/src/osd/modules/render/bgfx/shaders/vs_distortion.sc b/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_distortion.sc
index 405ef8feb3b..405ef8feb3b 100644
--- a/src/osd/modules/render/bgfx/shaders/vs_distortion.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_distortion.sc
diff --git a/src/osd/modules/render/bgfx/shaders/vs_ntsc_decode.sc b/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_ntsc_decode.sc
index 405ef8feb3b..405ef8feb3b 100644
--- a/src/osd/modules/render/bgfx/shaders/vs_ntsc_decode.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_ntsc_decode.sc
diff --git a/src/osd/modules/render/bgfx/shaders/vs_ntsc_encode.sc b/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_ntsc_encode.sc
index 405ef8feb3b..405ef8feb3b 100644
--- a/src/osd/modules/render/bgfx/shaders/vs_ntsc_encode.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_ntsc_encode.sc
diff --git a/src/osd/modules/render/bgfx/shaders/vs_phosphor.sc b/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_phosphor.sc
index 405ef8feb3b..405ef8feb3b 100644
--- a/src/osd/modules/render/bgfx/shaders/vs_phosphor.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_phosphor.sc
diff --git a/src/osd/modules/render/bgfx/shaders/vs_post.sc b/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_post.sc
index 405ef8feb3b..405ef8feb3b 100644
--- a/src/osd/modules/render/bgfx/shaders/vs_post.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_post.sc
diff --git a/src/osd/modules/render/bgfx/shaders/vs_prescale.sc b/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_prescale.sc
index 405ef8feb3b..405ef8feb3b 100644
--- a/src/osd/modules/render/bgfx/shaders/vs_prescale.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/hlsl/vs_prescale.sc
diff --git a/src/osd/modules/render/bgfx/shaders/chains/unfiltered/fs_blit.sc b/src/osd/modules/render/bgfx/shaders/chains/unfiltered/fs_blit.sc
new file mode 100644
index 00000000000..9af7bcf0ee6
--- /dev/null
+++ b/src/osd/modules/render/bgfx/shaders/chains/unfiltered/fs_blit.sc
@@ -0,0 +1,14 @@
+$input v_color0, v_texcoord0
+
+// license:BSD-3-Clause
+// copyright-holders:Dario Manesku
+
+#include "common.sh"
+
+// Samplers
+SAMPLER2D(s_tex, 0);
+
+void main()
+{
+ gl_FragColor = texture2D(s_tex, v_texcoord0) * v_color0;
+}
diff --git a/src/osd/modules/render/bgfx/shaders/chains/unfiltered/varying.def.sc b/src/osd/modules/render/bgfx/shaders/chains/unfiltered/varying.def.sc
new file mode 100644
index 00000000000..2aa3cb425c0
--- /dev/null
+++ b/src/osd/modules/render/bgfx/shaders/chains/unfiltered/varying.def.sc
@@ -0,0 +1,6 @@
+vec4 v_color0 : COLOR0 = vec4(1.0, 0.0, 0.0, 1.0);
+vec2 v_texcoord0 : TEXCOORD0 = vec2(0.0, 0.0);
+
+vec3 a_position : POSITION;
+vec4 a_color0 : COLOR0;
+vec2 a_texcoord0 : TEXCOORD0;
diff --git a/src/osd/modules/render/bgfx/shaders/chains/unfiltered/vs_blit.sc b/src/osd/modules/render/bgfx/shaders/chains/unfiltered/vs_blit.sc
new file mode 100644
index 00000000000..405ef8feb3b
--- /dev/null
+++ b/src/osd/modules/render/bgfx/shaders/chains/unfiltered/vs_blit.sc
@@ -0,0 +1,14 @@
+$input a_position, a_texcoord0, a_color0
+$output v_texcoord0, v_color0
+
+// license:BSD-3-Clause
+// copyright-holders:Dario Manesku
+
+#include "common.sh"
+
+void main()
+{
+ gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
+ v_texcoord0 = a_texcoord0;
+ v_color0 = a_color0;
+}
diff --git a/src/osd/modules/render/bgfx/shaders/varying.def.sc b/src/osd/modules/render/bgfx/shaders/varying.def.sc
index 4bbc09efebe..2aa3cb425c0 100644
--- a/src/osd/modules/render/bgfx/shaders/varying.def.sc
+++ b/src/osd/modules/render/bgfx/shaders/varying.def.sc
@@ -1,9 +1,5 @@
vec4 v_color0 : COLOR0 = vec4(1.0, 0.0, 0.0, 1.0);
vec2 v_texcoord0 : TEXCOORD0 = vec2(0.0, 0.0);
-vec2 v_texcoord1 : TEXCOORD1 = vec2(0.0, 0.0);
-vec2 v_texcoord2 : TEXCOORD2 = vec2(0.0, 0.0);
-vec2 v_texcoord3 : TEXCOORD3 = vec2(0.0, 0.0);
-vec3 v_pos : TEXCOORD3 = vec3(0.0, 0.0, 0.0);
vec3 a_position : POSITION;
vec4 a_color0 : COLOR0;
diff --git a/src/osd/modules/render/bgfx/slider.cpp b/src/osd/modules/render/bgfx/slider.cpp
index cd27c973451..94e9c26ee0c 100644
--- a/src/osd/modules/render/bgfx/slider.cpp
+++ b/src/osd/modules/render/bgfx/slider.cpp
@@ -42,7 +42,7 @@ bgfx_slider::~bgfx_slider()
{
}
-static INT32 update_trampoline(running_machine &machine, void *arg, std::string *str, INT32 newval)
+static INT32 update_trampoline(running_machine &machine, void *arg, int /*id*/, std::string *str, INT32 newval)
{
if (arg != nullptr)
{
@@ -62,7 +62,7 @@ slider_state* bgfx_slider::create_core_slider(running_machine& machine)
state->incval = m_step;
state->update = update_trampoline;
state->arg = this;
- state->id = 0; // fixme
+ state->id = 0;
strcpy(state->description, m_description.c_str());
return state;
diff --git a/src/osd/modules/render/bgfx/targetmanager.cpp b/src/osd/modules/render/bgfx/targetmanager.cpp
index 6350829a4ed..e17b0e6915a 100644
--- a/src/osd/modules/render/bgfx/targetmanager.cpp
+++ b/src/osd/modules/render/bgfx/targetmanager.cpp
@@ -48,14 +48,26 @@ target_manager::~target_manager()
bgfx_target* target_manager::create_target(std::string name, bgfx::TextureFormat::Enum format, uint16_t width, uint16_t height, uint32_t style, bool double_buffer, bool filter, uint16_t scale, uint32_t screen)
{
bgfx_target* target = new bgfx_target(name, format, width, height, style, double_buffer, filter, scale, screen);
+ std::string full_name = name + std::to_string(screen);
- m_targets[name + std::to_string(screen)] = target;
+ m_targets[full_name] = target;
- m_textures.add_provider(name + std::to_string(screen), target);
+ m_textures.add_provider(full_name, target);
return target;
}
+void target_manager::destroy_target(std::string name, uint32_t screen)
+{
+ std::string full_name = name + std::to_string(screen);
+ if (m_targets[full_name] != nullptr)
+ {
+ delete m_targets[full_name];
+ m_targets[full_name] = nullptr;
+ m_textures.remove_provider(full_name);
+ }
+}
+
bgfx_target* target_manager::create_backbuffer(void *handle, uint16_t width, uint16_t height)
{
bgfx_target* target = new bgfx_target(handle, width, height);
@@ -161,3 +173,15 @@ void target_manager::create_target_if_nonexistent(uint32_t screen, std::string n
create_target(name, bgfx::TextureFormat::RGBA8, width, height, style, double_buffered, filter, 1, screen);
}
+
+uint16_t target_manager::width(uint32_t style, uint32_t screen)
+{
+ std::vector<osd_dim>& sizes = style == TARGET_STYLE_GUEST ? m_guest_dims : m_native_dims;
+ return screen < sizes.size() ? sizes[screen].width() : 0;
+}
+
+uint16_t target_manager::height(uint32_t style, uint32_t screen)
+{
+ std::vector<osd_dim>& sizes = style == TARGET_STYLE_GUEST ? m_guest_dims : m_native_dims;
+ return screen < sizes.size() ? sizes[screen].height() : 0;
+}
diff --git a/src/osd/modules/render/bgfx/targetmanager.h b/src/osd/modules/render/bgfx/targetmanager.h
index fe3ff2ef22f..04ac4252f9d 100644
--- a/src/osd/modules/render/bgfx/targetmanager.h
+++ b/src/osd/modules/render/bgfx/targetmanager.h
@@ -31,6 +31,7 @@ public:
~target_manager();
bgfx_target* create_target(std::string name, bgfx::TextureFormat::Enum format, uint16_t width, uint16_t height, uint32_t style, bool double_buffer, bool filter, uint16_t scale, uint32_t screen);
+ void destroy_target(std::string name, uint32_t screen);
bgfx_target* create_backbuffer(void *handle, uint16_t width, uint16_t height);
void update_target_sizes(uint32_t screen, uint16_t width, uint16_t height, uint32_t style);
@@ -38,6 +39,8 @@ public:
// Getters
bgfx_target* target(uint32_t screen, std::string name);
+ uint16_t width(uint32_t style, uint32_t screen);
+ uint16_t height(uint32_t style, uint32_t screen);
private:
void rebuild_targets(uint32_t screen, uint32_t style);
diff --git a/src/osd/modules/render/bgfx/targetreader.cpp b/src/osd/modules/render/bgfx/targetreader.cpp
index 26a2e21bfc3..c63d05ec015 100644
--- a/src/osd/modules/render/bgfx/targetreader.cpp
+++ b/src/osd/modules/render/bgfx/targetreader.cpp
@@ -21,11 +21,11 @@ const target_reader::string_to_enum target_reader::STYLE_NAMES[target_reader::ST
{ "custom", TARGET_STYLE_CUSTOM }
};
-bool target_reader::read_from_value(const Value& value, std::string prefix, target_manager& targets, osd_options& options, uint32_t screen_index)
+bgfx_target* target_reader::read_from_value(const Value& value, std::string prefix, target_manager& targets, osd_options& options, uint32_t screen_index)
{
if (!validate_parameters(value, prefix))
{
- return false;
+ return nullptr;
}
std::string target_name = value["name"].GetString();
@@ -43,21 +43,24 @@ bool target_reader::read_from_value(const Value& value, std::string prefix, targ
switch (mode)
{
case TARGET_STYLE_GUEST:
- break;
+ width = targets.width(TARGET_STYLE_GUEST, screen_index);
+ height = targets.height(TARGET_STYLE_GUEST, screen_index);
+ break;
case TARGET_STYLE_NATIVE:
- break;
+ width = targets.width(TARGET_STYLE_NATIVE, screen_index);
+ height = targets.height(TARGET_STYLE_NATIVE, screen_index);
+ break;
case TARGET_STYLE_CUSTOM:
- if (!READER_CHECK(value.HasMember("width"), (prefix + "Target '" + target_name + "': Must have numeric value 'width'\n").c_str())) return false;
- if (!READER_CHECK(value["width"].IsNumber(), (prefix + "Target '" + target_name + "': Value 'width' must be a number\n").c_str())) return false;
- if (!READER_CHECK(value.HasMember("height"), (prefix + "Target '" + target_name + "': Must have numeric value 'height'\n").c_str())) return false;
- if (!READER_CHECK(value["height"].IsNumber(), (prefix + "Target '" + target_name + "': Value 'height' must be a number\n").c_str())) return false;
+ if (!READER_CHECK(value.HasMember("width"), (prefix + "Target '" + target_name + "': Must have numeric value 'width'\n").c_str())) return nullptr;
+ if (!READER_CHECK(value["width"].IsNumber(), (prefix + "Target '" + target_name + "': Value 'width' must be a number\n").c_str())) return nullptr;
+ if (!READER_CHECK(value.HasMember("height"), (prefix + "Target '" + target_name + "': Must have numeric value 'height'\n").c_str())) return nullptr;
+ if (!READER_CHECK(value["height"].IsNumber(), (prefix + "Target '" + target_name + "': Value 'height' must be a number\n").c_str())) return nullptr;
width = uint16_t(value["width"].GetDouble());
height = uint16_t(value["height"].GetDouble());
break;
}
- targets.create_target(target_name, bgfx::TextureFormat::RGBA8, width, height, mode, double_buffer, bilinear, scale, screen_index);
- return true;
+ return targets.create_target(target_name, bgfx::TextureFormat::RGBA8, width, height, mode, double_buffer, bilinear, scale, screen_index);
}
bool target_reader::validate_parameters(const Value& value, std::string prefix)
diff --git a/src/osd/modules/render/bgfx/targetreader.h b/src/osd/modules/render/bgfx/targetreader.h
index 78e97665f5f..abbc4f9a805 100644
--- a/src/osd/modules/render/bgfx/targetreader.h
+++ b/src/osd/modules/render/bgfx/targetreader.h
@@ -15,13 +15,14 @@
#include "statereader.h"
+class bgfx_target;
class target_manager;
class osd_options;
class target_reader : public state_reader
{
public:
- static bool read_from_value(const Value& value, std::string prefix, target_manager& targets, osd_options& options, uint32_t screen_index);
+ static bgfx_target* read_from_value(const Value& value, std::string prefix, target_manager& targets, osd_options& options, uint32_t screen_index);
private:
static bool validate_parameters(const Value& value, std::string prefix);
diff --git a/src/osd/modules/render/bgfx/texturemanager.cpp b/src/osd/modules/render/bgfx/texturemanager.cpp
index 753585fe3f3..0b2d0bb9969 100644
--- a/src/osd/modules/render/bgfx/texturemanager.cpp
+++ b/src/osd/modules/render/bgfx/texturemanager.cpp
@@ -62,23 +62,25 @@ bgfx_texture* texture_manager::create_png_texture(std::string path, std::string
return nullptr;
}
- uint8_t *texture_data = new uint8_t[bitmap.width() * bitmap.height() * 4];
-
- uint32_t width = bitmap.width();
- uint32_t height = bitmap.height();
- uint32_t rowpixels = bitmap.rowpixels();
- void *base = bitmap.raw_pixptr(0);
- for (int y = 0; y < height; y++) {
- copy_util::copyline_argb32(reinterpret_cast<UINT32 *>(texture_data) + y * width, reinterpret_cast<UINT32 *>(base) + y * rowpixels, width, nullptr);
+ uint8_t *data = new uint8_t[bitmap.width() * bitmap.height() * 4];
+ UINT32 *data32 = reinterpret_cast<UINT32 *>(data);
+
+ const uint32_t width = bitmap.width();
+ const uint32_t height = bitmap.height();
+ const uint32_t rowpixels = bitmap.rowpixels();
+ UINT32* base = reinterpret_cast<UINT32 *>(bitmap.raw_pixptr(0));
+ for (int y = 0; y < height; y++)
+ {
+ copy_util::copyline_argb32(data32 + y * width, base + y * rowpixels, width, nullptr);
}
if (screen >= 0)
{
texture_name += std::to_string(screen);
}
- bgfx_texture* texture = create_texture(texture_name, bgfx::TextureFormat::RGBA8, width, height, texture_data, flags);
+ bgfx_texture* texture = create_texture(texture_name, bgfx::TextureFormat::RGBA8, width, height, data, flags);
- delete[] texture_data;
+ delete [] data;
return texture;
}
@@ -106,3 +108,16 @@ bgfx_texture_handle_provider* texture_manager::provider(std::string name)
return nullptr;
}
+
+void texture_manager::remove_provider(std::string name, bool delete_provider)
+{
+ if (provider(name) != nullptr)
+ {
+ if (delete_provider)
+ {
+ delete m_textures[name];
+ }
+ m_textures[name] = nullptr;
+ }
+}
+
diff --git a/src/osd/modules/render/bgfx/texturemanager.h b/src/osd/modules/render/bgfx/texturemanager.h
index 20da9ff8b3e..117fc36c502 100644
--- a/src/osd/modules/render/bgfx/texturemanager.h
+++ b/src/osd/modules/render/bgfx/texturemanager.h
@@ -30,6 +30,7 @@ public:
bgfx_texture* create_texture(std::string name, bgfx::TextureFormat::Enum format, uint32_t width, uint32_t height, void* data = nullptr, uint32_t flags = BGFX_TEXTURE_U_CLAMP | BGFX_TEXTURE_V_CLAMP);
bgfx_texture* create_png_texture(std::string path, std::string file_name, std::string texture_name, uint32_t flags = BGFX_TEXTURE_U_CLAMP | BGFX_TEXTURE_V_CLAMP, uint32_t screen = -1);
void add_provider(std::string name, bgfx_texture_handle_provider* texture);
+ void remove_provider(std::string name, bool delete_provider = false);
// Getters
bgfx::TextureHandle handle(std::string name);
diff --git a/src/osd/modules/render/bgfxutil.cpp b/src/osd/modules/render/bgfxutil.cpp
index 2382e7981da..a5099534220 100644
--- a/src/osd/modules/render/bgfxutil.cpp
+++ b/src/osd/modules/render/bgfxutil.cpp
@@ -11,6 +11,9 @@
#include "bgfxutil.h"
#include "copyutil.h"
+#include "render.h"
+
+
const bgfx::Memory* bgfx_util::mame_texture_data_to_bgfx_texture_data(UINT32 format, int width, int height, int rowpixels, const rgb_t *palette, void *base)
{
const bgfx::Memory* mem = bgfx::alloc(width * height * 4);
diff --git a/src/osd/modules/render/d3d/d3dhlsl.cpp b/src/osd/modules/render/d3d/d3dhlsl.cpp
index 712b80b71af..4cf8c96a164 100644
--- a/src/osd/modules/render/d3d/d3dhlsl.cpp
+++ b/src/osd/modules/render/d3d/d3dhlsl.cpp
@@ -23,6 +23,7 @@
#include "aviio.h"
#include "png.h"
#include "screen.h"
+#include "ui/ui.h"
// MAMEOS headers
#include "winmain.h"
@@ -37,7 +38,6 @@
// GLOBALS
//============================================================
-static slider_state *g_slider_list;
static osd_file::error open_next(renderer_d3d9 *d3d, emu_file &file, const char *templ, const char *extension, int idx);
//============================================================
@@ -86,7 +86,7 @@ shaders::shaders() :
shaders::~shaders()
{
- for (slider* slider : sliders)
+ for (slider* slider : internal_sliders)
{
delete slider;
}
@@ -400,7 +400,7 @@ void shaders::end_avi_recording()
// shaders::toggle
//============================================================
-void shaders::toggle()
+void shaders::toggle(std::vector<ui_menu_item>& sliders)
{
if (master_enable)
{
@@ -427,7 +427,7 @@ void shaders::toggle()
if (!initialized)
{
// re-create shader resources after renderer resources
- bool failed = create_resources(false);
+ bool failed = create_resources(false, sliders);
if (failed)
{
master_enable = false;
@@ -827,7 +827,7 @@ void shaders::init_fsfx_quad(void *vertbuf)
// shaders::create_resources
//============================================================
-int shaders::create_resources(bool reset)
+int shaders::create_resources(bool reset, std::vector<ui_menu_item>& sliders)
{
if (!master_enable || !d3dintf->post_fx_available)
{
@@ -1003,7 +1003,8 @@ int shaders::create_resources(bool reset)
initialized = true;
- init_slider_list();
+ std::vector<ui_menu_item> my_sliders = init_slider_list();
+ sliders.insert(sliders.end(), my_sliders.begin(), my_sliders.end());
return 0;
}
@@ -2103,8 +2104,6 @@ void shaders::delete_resources(bool reset)
}
shadow_bitmap.reset();
-
- g_slider_list = nullptr;
}
@@ -2226,7 +2225,7 @@ INT32 slider::update(std::string *str, INT32 newval)
return 0;
}
-static INT32 slider_update_trampoline(running_machine &machine, void *arg, std::string *str, INT32 newval)
+static INT32 slider_update_trampoline(running_machine &machine, void *arg, int id, std::string *str, INT32 newval)
{
if (arg != nullptr)
{
@@ -2379,10 +2378,6 @@ slider_desc shaders::s_sliders[] =
};
-//============================================================
-// init_slider_list
-//============================================================
-
void *shaders::get_slider_option(int id, int index)
{
switch (id)
@@ -2452,15 +2447,15 @@ void *shaders::get_slider_option(int id, int index)
return nullptr;
}
-void shaders::init_slider_list()
+std::vector<ui_menu_item> shaders::init_slider_list()
{
- if (!master_enable || !d3dintf->post_fx_available)
+ std::vector<ui_menu_item> sliders;
+
+ for (slider* slider : internal_sliders)
{
- g_slider_list = nullptr;
+ delete slider;
}
-
- slider_state *listhead = nullptr;
- slider_state **tailptr = &listhead;
+ internal_sliders.clear();
for (int i = 0; s_sliders[i].name != nullptr; i++)
{
@@ -2488,7 +2483,7 @@ void shaders::init_slider_list()
for (int j = 0; j < count; j++)
{
slider* slider_arg = new slider(desc, get_slider_option(desc->id, j), &options->params_dirty);
- sliders.push_back(slider_arg);
+ internal_sliders.push_back(slider_arg);
std::string name = desc->name;
switch (desc->slider_type)
{
@@ -2507,13 +2502,21 @@ void shaders::init_slider_list()
default:
break;
}
- *tailptr = slider_alloc(*machine, desc->id, name.c_str(), desc->minval, desc->defval, desc->maxval, desc->step, slider_update_trampoline, slider_arg);
- tailptr = &(*tailptr)->next;
+
+ slider_state* core_slider = slider_alloc(*machine, desc->id, name.c_str(), desc->minval, desc->defval, desc->maxval, desc->step, slider_update_trampoline, slider_arg);
+
+ ui_menu_item item;
+ item.text = core_slider->description;
+ item.subtext = "";
+ item.flags = 0;
+ item.ref = core_slider;
+ item.type = ui_menu_item_type::UI_MENU_ITEM_TYPE_SLIDER;
+ sliders.push_back(item);
}
}
}
- g_slider_list = listhead;
+ return sliders;
}
@@ -3052,20 +3055,6 @@ ULONG effect::release()
}
-//============================================================
-// get_slider_list
-//============================================================
-
-slider_state *renderer_d3d9::get_slider_list()
-{
- if (window().m_index > 0)
- {
- return nullptr;
- }
- return g_slider_list;
-}
-
-
// NOTE: The function below is taken directly from src/emu/video.c and should likely be moved into a global helper function.
//-------------------------------------------------
// open_next - open the next non-existing file of
diff --git a/src/osd/modules/render/d3d/d3dhlsl.h b/src/osd/modules/render/d3d/d3dhlsl.h
index 0cf6f0b3de9..e5e6ad600b7 100644
--- a/src/osd/modules/render/d3d/d3dhlsl.h
+++ b/src/osd/modules/render/d3d/d3dhlsl.h
@@ -303,7 +303,7 @@ public:
void init(d3d_base *d3dintf, running_machine *machine, renderer_d3d9 *renderer);
bool enabled() { return master_enable; }
- void toggle();
+ void toggle(std::vector<ui_menu_item>& sliders);
bool vector_enabled() { return master_enable && vector_enable; }
d3d_render_target* get_vector_target(render_primitive *prim);
@@ -338,11 +338,11 @@ public:
void remove_render_target(int source_width, int source_height, UINT32 screen_index, UINT32 page_index);
void remove_render_target(d3d_render_target *rt);
- int create_resources(bool reset);
+ int create_resources(bool reset, std::vector<ui_menu_item>& sliders);
void delete_resources(bool reset);
// slider-related functions
- void init_slider_list();
+ std::vector<ui_menu_item> init_slider_list();
void *get_slider_option(int id, int index = 0);
private:
@@ -438,7 +438,7 @@ private:
d3d_render_target * targethead;
cache_target * cachehead;
- std::vector<slider*> sliders;
+ std::vector<slider*> internal_sliders;
static slider_desc s_sliders[];
static hlsl_options last_options; // last used options
diff --git a/src/osd/modules/render/drawbgfx.cpp b/src/osd/modules/render/drawbgfx.cpp
index 917a0397e9e..32f45515a08 100644
--- a/src/osd/modules/render/drawbgfx.cpp
+++ b/src/osd/modules/render/drawbgfx.cpp
@@ -190,7 +190,7 @@ int renderer_bgfx::create()
m_screen_effect[2] = m_effects->effect("screen_multiply");
m_screen_effect[3] = m_effects->effect("screen_add");
- m_chains = new chain_manager(window().machine(), options, *m_textures, *m_targets, *m_effects, window().m_index);
+ m_chains = new chain_manager(window().machine(), options, *m_textures, *m_targets, *m_effects, window().m_index, *this);
m_sliders_dirty = true;
uint32_t flags = BGFX_TEXTURE_U_CLAMP | BGFX_TEXTURE_V_CLAMP | BGFX_TEXTURE_MIN_POINT | BGFX_TEXTURE_MAG_POINT | BGFX_TEXTURE_MIP_POINT;
@@ -907,7 +907,7 @@ renderer_bgfx::buffer_status renderer_bgfx::buffer_primitives(bool atlas_valid,
return BUFFER_PRE_FLUSH;
}
- if (PRIMFLAG_GET_SCREENTEX((*prim)->flags) && m_chains->has_applicable_pass(screen))
+ if (PRIMFLAG_GET_SCREENTEX((*prim)->flags) && m_chains->has_applicable_chain(screen))
{
#if SCENE_VIEW
setup_view(s_current_view, true);
@@ -1118,8 +1118,13 @@ void renderer_bgfx::allocate_buffer(render_primitive *prim, UINT32 blend, bgfx::
}
}
-slider_state* renderer_bgfx::get_slider_list()
+std::vector<ui_menu_item> renderer_bgfx::get_slider_list()
{
m_sliders_dirty = false;
return m_chains->get_slider_list();
}
+
+void renderer_bgfx::set_sliders_dirty()
+{
+ m_sliders_dirty = true;
+} \ No newline at end of file
diff --git a/src/osd/modules/render/drawbgfx.h b/src/osd/modules/render/drawbgfx.h
index 7bd821e8e72..d48bb5914e6 100644
--- a/src/osd/modules/render/drawbgfx.h
+++ b/src/osd/modules/render/drawbgfx.h
@@ -12,6 +12,7 @@
#include "binpacker.h"
#include "bgfx/vertex.h"
+#include "sliderdirtynotifier.h"
class texture_manager;
class target_manager;
@@ -24,7 +25,7 @@ class bgfx_target;
class bgfx_chain;
/* sdl_info is the information about SDL for the current screen */
-class renderer_bgfx : public osd_renderer
+class renderer_bgfx : public osd_renderer, public slider_dirty_notifier
{
public:
renderer_bgfx(osd_window *w)
@@ -39,9 +40,10 @@ public:
static void exit();
virtual int create() override;
- virtual slider_state* get_slider_list() override;
- virtual bool multi_window_sliders() override { return true; }
- virtual int draw(const int update) override;
+ virtual int draw(const int update) override;
+
+ virtual std::vector<ui_menu_item> get_slider_list() override;
+ virtual void set_sliders_dirty() override;
#ifdef OSD_SDL
virtual int xy_to_render_target(const int x, const int y, int *xt, int *yt) override;
diff --git a/src/osd/modules/render/drawd3d.cpp b/src/osd/modules/render/drawd3d.cpp
index 2da64508647..020e4ee3de5 100644
--- a/src/osd/modules/render/drawd3d.cpp
+++ b/src/osd/modules/render/drawd3d.cpp
@@ -598,7 +598,8 @@ int renderer_d3d9::pre_window_draw_check()
// if we're restarting the renderer, leave things alone
if (m_restarting)
{
- m_shaders->toggle();
+ m_sliders.clear();
+ m_shaders->toggle(m_sliders);
m_restarting = false;
}
@@ -896,14 +897,16 @@ try_again:
m_shaders = (shaders*)global_alloc_clear<shaders>();
m_shaders->init(d3dintf, &window().machine(), this);
- m_sliders_dirty = true;
- int failed = m_shaders->create_resources(false);
+ m_sliders.clear();
+ int failed = m_shaders->create_resources(false, m_sliders);
if (failed)
{
return failed;
}
+ m_sliders_dirty = true;
+
return device_create_resources();
}
@@ -1002,6 +1005,7 @@ void renderer_d3d9::device_delete()
if (m_shaders != nullptr)
{
// free our effects
+ m_sliders.clear();
m_shaders->delete_resources(false);
// delete the HLSL interface
@@ -1130,6 +1134,7 @@ int renderer_d3d9::device_test_cooperative()
osd_printf_verbose("Direct3D: resetting device\n");
// free all existing resources and call reset on the device
+ m_sliders.clear();
m_shaders->delete_resources(true);
device_delete_resources();
result = (*d3dintf->device.reset)(m_device, &m_presentation);
@@ -1149,7 +1154,8 @@ int renderer_d3d9::device_test_cooperative()
return 1;
}
- if (m_shaders->create_resources(true))
+ m_sliders.clear();
+ if (m_shaders->create_resources(true, m_sliders))
{
osd_printf_verbose("Direct3D: failed to recreate HLSL resources for device; failing permanently\n");
device_delete();
diff --git a/src/osd/modules/render/drawd3d.h b/src/osd/modules/render/drawd3d.h
index a35f896c40e..672ff6482bb 100644
--- a/src/osd/modules/render/drawd3d.h
+++ b/src/osd/modules/render/drawd3d.h
@@ -47,7 +47,6 @@ public:
static void exit();
virtual int create() override;
- virtual slider_state* get_slider_list() override;
virtual render_primitive_list *get_primitives() override;
virtual int draw(const int update) override;
virtual void save() override;
diff --git a/src/osd/modules/render/sdlglcontext.h b/src/osd/modules/render/sdlglcontext.h
index 5a284ef289d..9a3194582ac 100644
--- a/src/osd/modules/render/sdlglcontext.h
+++ b/src/osd/modules/render/sdlglcontext.h
@@ -13,6 +13,7 @@
#ifndef __SDL_GL_CONTEXT__
#define __SDL_GL_CONTEXT__
+#include "sdlinc.h"
#include "modules/opengl/osd_opengl.h"
class sdl_gl_context : public osd_gl_context
diff --git a/src/osd/modules/render/sliderdirtynotifier.h b/src/osd/modules/render/sliderdirtynotifier.h
new file mode 100644
index 00000000000..bf9f645b894
--- /dev/null
+++ b/src/osd/modules/render/sliderdirtynotifier.h
@@ -0,0 +1,22 @@
+// license:BSD-3-Clause
+// copyright-holders:Ryan Holtz
+//====================================================================
+//
+// sliderdirtynotifier.cpp - Interface for a slider-changed callback
+//
+//====================================================================
+
+#pragma once
+
+#ifndef __RENDER_SLIDER_DIRTY_NOTIFIER__
+#define __RENDER_SLIDER_DIRTY_NOTIFIER__
+
+class slider_dirty_notifier
+{
+public:
+ virtual ~slider_dirty_notifier() { }
+
+ virtual void set_sliders_dirty() = 0;
+};
+
+#endif // __RENDER_SLIDER_DIRTY_NOTIFIER__ \ No newline at end of file
diff --git a/src/osd/modules/sync/osdsync.cpp b/src/osd/modules/sync/osdsync.cpp
index 46b321369b0..98690149358 100644
--- a/src/osd/modules/sync/osdsync.cpp
+++ b/src/osd/modules/sync/osdsync.cpp
@@ -11,122 +11,4 @@
#include <stdlib.h>
-// C++ headers
-#include <mutex>
-#include <atomic>
-#include <condition_variable>
-//============================================================
-// TYPE DEFINITIONS
-//============================================================
-
-struct osd_event {
- std::mutex *mutex;
- std::condition_variable *cond;
- std::atomic<INT32> autoreset;
- std::atomic<INT32> signalled;
-};
-
-//============================================================
-// osd_event_alloc
-//============================================================
-
-osd_event *osd_event_alloc(int manualreset, int initialstate)
-{
- osd_event *ev;
-
- ev = (osd_event *)calloc(1, sizeof(osd_event));
- if (ev == nullptr)
- return nullptr;
-
- ev->mutex = new std::mutex();
- ev->cond = new std::condition_variable();
- ev->signalled = initialstate;
- ev->autoreset = !manualreset;
-
- return ev;
-}
-
-//============================================================
-// osd_event_free
-//============================================================
-
-void osd_event_free(osd_event *event)
-{
- delete event->mutex;
- delete event->cond;
- free(event);
-}
-
-//============================================================
-// osd_event_set
-//============================================================
-
-void osd_event_set(osd_event *event)
-{
- event->mutex->lock();
- if (event->signalled == FALSE)
- {
- event->signalled = TRUE;
- if (event->autoreset)
- event->cond->notify_one();
- else
- event->cond->notify_all();
- }
- event->mutex->unlock();
-}
-
-//============================================================
-// osd_event_reset
-//============================================================
-
-void osd_event_reset(osd_event *event)
-{
- event->mutex->lock();
- event->signalled = FALSE;
- event->mutex->unlock();
-}
-
-//============================================================
-// osd_event_wait
-//============================================================
-
-int osd_event_wait(osd_event *event, osd_ticks_t timeout)
-{
- if (timeout == OSD_EVENT_WAIT_INFINITE)
- timeout = osd_ticks_per_second() * (osd_ticks_t)10000;
-
- std::unique_lock<std::mutex> lock(*event->mutex);
- if (!timeout)
- {
- if (!event->signalled)
- {
- return FALSE;
- }
- }
- else
- {
- if (!event->signalled)
- {
- UINT64 msec = timeout * 1000 / osd_ticks_per_second();
-
- do {
- if (event->cond->wait_for(lock, std::chrono::milliseconds(msec)) == std::cv_status::timeout)
- {
- if (!event->signalled)
- {
- return FALSE;
- }
- else
- break;
- } else
- break;
-
- } while (TRUE);
- }
- }
-
- if (event->autoreset)
- event->signalled = 0;
- return TRUE;
-}
diff --git a/src/osd/modules/sync/osdsync.h b/src/osd/modules/sync/osdsync.h
index e88d4a223f2..a0eb8d36682 100644
--- a/src/osd/modules/sync/osdsync.h
+++ b/src/osd/modules/sync/osdsync.h
@@ -9,8 +9,12 @@
#ifndef __OSDSYNC__
#define __OSDSYNC__
+// C++ headers
+#include <mutex>
+#include <atomic>
+#include <condition_variable>
+
#include "osdcomm.h"
-#include "osdcore.h"
/***************************************************************************
SYNCHRONIZATION INTERFACES - Events
@@ -20,87 +24,143 @@
/* osd_event is an opaque type which represents a setable/resetable event */
-struct osd_event;
-
-
-/*-----------------------------------------------------------------------------
- osd_event_alloc: allocate a new event
-
- Parameters:
-
- manualreset - boolean. If true, the event will be automatically set
- to non-signalled after a thread successfully waited for
- it.
- initialstate - boolean. If true, the event is signalled initially.
-
- Return value:
-
- A pointer to the allocated event.
------------------------------------------------------------------------------*/
-osd_event *osd_event_alloc(int manualreset, int initialstate);
-
-
-/*-----------------------------------------------------------------------------
- osd_event_wait: wait for an event to be signalled
-
- Parameters:
-
- event - The event to wait for. If the event is in signalled state, the
- function returns immediately. If not it will wait for the event
- to become signalled.
- timeout - timeout in osd_ticks
-
- Return value:
-
- TRUE: The event was signalled
- FALSE: A timeout occurred
------------------------------------------------------------------------------*/
-int osd_event_wait(osd_event *event, osd_ticks_t timeout);
-
-
-/*-----------------------------------------------------------------------------
- osd_event_reset: reset an event to non-signalled state
-
- Parameters:
-
- event - The event to set to non-signalled state
-
- Return value:
-
- None
------------------------------------------------------------------------------*/
-void osd_event_reset(osd_event *event);
-
-
-/*-----------------------------------------------------------------------------
- osd_event_set: set an event to signalled state
-
- Parameters:
-
- event - The event to set to signalled state
-
- Return value:
-
- None
-
- Notes:
-
- All threads waiting for the event will be signalled.
------------------------------------------------------------------------------*/
-void osd_event_set(osd_event *event);
-
-
-/*-----------------------------------------------------------------------------
- osd_event_free: free the memory and resources associated with an osd_event
-
- Parameters:
-
- event - a pointer to a previously allocated osd_event.
+class osd_event
+{
+public:
+ /*-----------------------------------------------------------------------------
+ constructor: allocate a new event
+
+ Parameters:
+
+ manualreset - boolean. If true, the event will be automatically set
+ to non-signalled after a thread successfully waited for
+ it.
+ initialstate - boolean. If true, the event is signalled initially.
- Return value:
+ Return value:
- None.
------------------------------------------------------------------------------*/
-void osd_event_free(osd_event *event);
+ A pointer to the allocated event.
+ -----------------------------------------------------------------------------*/
+ osd_event(int manualreset, int initialstate)
+ {
+ m_signalled = initialstate;
+ m_autoreset = !manualreset;
+ }
+
+ ~osd_event()
+ {
+ }
+
+ /*-----------------------------------------------------------------------------
+ wait: wait for an event to be signalled
+ If the event is in signalled state, the
+ function returns immediately. If not it will wait for the event
+ to become signalled.
+
+ Parameters:
+
+ timeout - timeout in osd_ticks
+
+ Return value:
+
+ true: The event was signalled
+ false: A timeout occurred
+ -----------------------------------------------------------------------------*/
+
+ bool wait(osd_ticks_t timeout)
+ {
+ if (timeout == OSD_EVENT_WAIT_INFINITE)
+ timeout = osd_ticks_per_second() * (osd_ticks_t)10000;
+
+ std::unique_lock<std::mutex> lock(m_mutex);
+ if (!timeout)
+ {
+ if (!m_signalled)
+ {
+ return false;
+ }
+ }
+ else
+ {
+ if (!m_signalled)
+ {
+ UINT64 msec = timeout * 1000 / osd_ticks_per_second();
+
+ do {
+ if (m_cond.wait_for(lock, std::chrono::milliseconds(msec)) == std::cv_status::timeout)
+ {
+ if (!m_signalled)
+ {
+ return FALSE;
+ }
+ else
+ break;
+ } else
+ break;
+
+ } while (true);
+ }
+ }
+
+ if (m_autoreset)
+ m_signalled = 0;
+
+ return true;
+ }
+
+ /*-----------------------------------------------------------------------------
+ osd_event_reset: reset an event to non-signalled state
+
+ Parameters:
+
+ None
+
+ Return value:
+
+ None
+ -----------------------------------------------------------------------------*/
+ void reset()
+ {
+ m_mutex.lock();
+ m_signalled = FALSE;
+ m_mutex.unlock();
+ }
+
+ /*-----------------------------------------------------------------------------
+ osd_event_set: set an event to signalled state
+
+ Parameters:
+
+ None
+
+ Return value:
+
+ None
+
+ Notes:
+
+ All threads waiting for the event will be signalled.
+ -----------------------------------------------------------------------------*/
+ void set()
+ {
+ m_mutex.lock();
+ if (m_signalled == FALSE)
+ {
+ m_signalled = TRUE;
+ if (m_autoreset)
+ m_cond.notify_one();
+ else
+ m_cond.notify_all();
+ }
+ m_mutex.unlock();
+ }
+
+private:
+ std::mutex m_mutex;
+ std::condition_variable m_cond;
+ std::atomic<INT32> m_autoreset;
+ std::atomic<INT32> m_signalled;
+
+};
#endif /* __OSDSYNC__ */
diff --git a/src/osd/modules/sync/work_osd.cpp b/src/osd/modules/sync/work_osd.cpp
index 72d074e97fc..3afe4e6c273 100644
--- a/src/osd/modules/sync/work_osd.cpp
+++ b/src/osd/modules/sync/work_osd.cpp
@@ -20,6 +20,7 @@
#include <mutex>
#include <atomic>
#include <thread>
+#include <vector>
// MAME headers
#include "osdcore.h"
@@ -32,9 +33,6 @@
#if defined(SDLMAME_LINUX) || defined(SDLMAME_BSD) || defined(SDLMAME_HAIKU) || defined(SDLMAME_EMSCRIPTEN) || defined(SDLMAME_MACOSX)
#include <pthread.h>
#endif
-#if defined(OSD_SDL)
-typedef void *PVOID;
-#endif
//============================================================
// DEBUGGING
@@ -93,10 +91,26 @@ static void spin_while_not(const volatile _AtomType * volatile atom, const _Main
struct work_thread_info
{
- osd_work_queue * queue; // pointer back to the queue
+ work_thread_info(UINT32 aid, osd_work_queue &aqueue)
+ : queue(aqueue)
+ , handle(nullptr)
+ , wakeevent(FALSE, FALSE) // auto-reset, not signalled
+ , active(0)
+ , id(aid)
+#if KEEP_STATISTICS
+ , itemsdone(0)
+ , actruntime(0)
+ , runtime(0)
+ , spintime(0)
+ , waittime(0)
+#endif
+ {
+ }
+ osd_work_queue & queue; // pointer back to the queue
std::thread * handle; // handle to the thread
- osd_event * wakeevent; // wake event for the thread
+ osd_event wakeevent; // wake event for the thread
std::atomic<INT32> active; // are we actively processing work?
+ UINT32 id;
#if KEEP_STATISTICS
INT32 itemsdone;
@@ -110,7 +124,28 @@ struct work_thread_info
struct osd_work_queue
{
- std::mutex *lock; // lock for protecting the queue
+ osd_work_queue()
+ : list(nullptr)
+ , tailptr(nullptr)
+ , free(nullptr)
+ , items(0)
+ , livethreads(0)
+ , waiting(0)
+ , exiting(0)
+ , threads(0)
+ , flags(0)
+ , doneevent(TRUE, TRUE) // manual reset, signalled
+#if KEEP_STATISTICS
+ , itemsqueued(0)
+ , setevents(0)
+ , extraitems(0)
+ , spinloops(0)
+#endif
+ {
+
+ }
+
+ std::mutex lock; // lock for protecting the queue
std::atomic<osd_work_item *> list; // list of items in the queue
osd_work_item ** volatile tailptr; // pointer to the tail pointer of work items in the queue
std::atomic<osd_work_item *> free; // free list of work items
@@ -120,8 +155,8 @@ struct osd_work_queue
std::atomic<INT32> exiting; // should the threads exit on their next opportunity?
UINT32 threads; // number of threads in this queue
UINT32 flags; // creation flags
- work_thread_info * thread; // array of thread information
- osd_event * doneevent; // event signalled when work is complete
+ std::vector<work_thread_info *> thread; // array of thread information
+ osd_event doneevent; // event signalled when work is complete
#if KEEP_STATISTICS
std::atomic<INT32> itemsqueued; // total items queued
@@ -134,8 +169,20 @@ struct osd_work_queue
struct osd_work_item
{
+ osd_work_item(osd_work_queue &aqueue)
+ : next(nullptr)
+ , queue(aqueue)
+ , callback(nullptr)
+ , param(nullptr)
+ , result(nullptr)
+ , event(nullptr) // manual reset, not signalled
+ , flags(0)
+ , done(FALSE)
+ {
+ }
+
osd_work_item * next; // pointer to next item
- osd_work_queue * queue; // pointer back to the owning queue
+ osd_work_queue & queue; // pointer back to the owning queue
osd_work_callback callback; // callback function
void * param; // callback parameter
void * result; // callback result
@@ -201,25 +248,12 @@ osd_work_queue *osd_work_queue_alloc(int flags)
const char *osdworkqueuemaxthreads = osd_getenv(ENV_WORKQUEUEMAXTHREADS);
// allocate a new queue
- queue = (osd_work_queue *)osd_malloc(sizeof(*queue));
- if (queue == NULL)
- goto error;
- memset(queue, 0, sizeof(*queue));
+ queue = new osd_work_queue();
// initialize basic queue members
queue->tailptr = (osd_work_item **)&queue->list;
queue->flags = flags;
- // allocate events for the queue
- queue->doneevent = osd_event_alloc(TRUE, TRUE); // manual reset, signalled
- if (queue->doneevent == NULL)
- goto error;
-
- // initialize the critical section
- queue->lock = new std::mutex();
- if (queue->lock == NULL)
- goto error;
-
// determine how many threads to create...
// on a single-CPU system, create 1 thread for I/O queues, and 0 threads for everything else
if (numprocs == 1)
@@ -244,23 +278,13 @@ osd_work_queue *osd_work_queue_alloc(int flags)
printf("osdprocs: %d effecprocs: %d threads: %d allocthreads: %d osdthreads: %d maxthreads: %d queuethreads: %d\n", osd_num_processors, numprocs, threadnum, allocthreadnum, osdthreadnum, WORK_MAX_THREADS, queue->threads);
#endif
- queue->thread = (work_thread_info *)osd_malloc_array(allocthreadnum * sizeof(queue->thread[0]));
- if (queue->thread == NULL)
- goto error;
- memset(queue->thread, 0, allocthreadnum * sizeof(queue->thread[0]));
+ for (threadnum = 0; threadnum < allocthreadnum; threadnum++)
+ queue->thread.push_back(new work_thread_info(threadnum, *queue));
// iterate over threads
for (threadnum = 0; threadnum < queue->threads; threadnum++)
{
- work_thread_info *thread = &queue->thread[threadnum];
-
- // set a pointer back to the queue
- thread->queue = queue;
-
- // create the per-thread wake event
- thread->wakeevent = osd_event_alloc(FALSE, FALSE); // auto-reset, not signalled
- if (thread->wakeevent == NULL)
- goto error;
+ work_thread_info *thread = queue->thread[threadnum];
// create the thread
thread->handle = new std::thread(worker_thread_entry, thread);
@@ -278,7 +302,7 @@ osd_work_queue *osd_work_queue_alloc(int flags)
// start a timer going for "waittime" on the main thread
if (flags & WORK_QUEUE_FLAG_MULTI)
{
- begin_timing(queue->thread[queue->threads].waittime);
+ begin_timing(queue->thread[queue->threads]->waittime);
}
return queue;
@@ -316,7 +340,7 @@ int osd_work_queue_wait(osd_work_queue *queue, osd_ticks_t timeout)
// if this is a multi queue, help out rather than doing nothing
if (queue->flags & WORK_QUEUE_FLAG_MULTI)
{
- work_thread_info *thread = &queue->thread[queue->threads];
+ work_thread_info *thread = queue->thread[queue->threads];
end_timing(thread->waittime);
@@ -338,10 +362,10 @@ int osd_work_queue_wait(osd_work_queue *queue, osd_ticks_t timeout)
}
// reset our done event and double-check the items before waiting
- osd_event_reset(queue->doneevent);
+ queue->doneevent.reset();
queue->waiting = TRUE;
if (queue->items != 0)
- osd_event_wait(queue->doneevent, timeout);
+ queue->doneevent.wait(timeout);
queue->waiting = FALSE;
// return TRUE if we actually hit 0
@@ -355,73 +379,53 @@ int osd_work_queue_wait(osd_work_queue *queue, osd_ticks_t timeout)
void osd_work_queue_free(osd_work_queue *queue)
{
- // if we have threads, clean them up
- if (queue->thread != NULL)
+ // stop the timer for "waittime" on the main thread
+ if (queue->flags & WORK_QUEUE_FLAG_MULTI)
{
- int threadnum;
+ end_timing(queue->thread[queue->threads]->waittime);
+ }
- // stop the timer for "waittime" on the main thread
- if (queue->flags & WORK_QUEUE_FLAG_MULTI)
- {
- end_timing(queue->thread[queue->threads].waittime);
- }
+ // signal all the threads to exit
+ queue->exiting = TRUE;
+ for (int threadnum = 0; threadnum < queue->threads; threadnum++)
+ {
+ work_thread_info *thread = queue->thread[threadnum];
+ thread->wakeevent.set();
+ }
- // signal all the threads to exit
- queue->exiting = TRUE;
- for (threadnum = 0; threadnum < queue->threads; threadnum++)
- {
- work_thread_info *thread = &queue->thread[threadnum];
- if (thread->wakeevent != NULL)
- osd_event_set(thread->wakeevent);
- }
+ // wait for all the threads to go away
+ for (int threadnum = 0; threadnum < queue->threads; threadnum++)
+ {
+ work_thread_info *thread = queue->thread[threadnum];
- // wait for all the threads to go away
- for (threadnum = 0; threadnum < queue->threads; threadnum++)
+ // block on the thread going away, then close the handle
+ if (thread->handle != NULL)
{
- work_thread_info *thread = &queue->thread[threadnum];
-
- // block on the thread going away, then close the handle
- if (thread->handle != NULL)
- {
- thread->handle->join();
- delete thread->handle;
- }
-
- // clean up the wake event
- if (thread->wakeevent != NULL)
- osd_event_free(thread->wakeevent);
+ thread->handle->join();
+ delete thread->handle;
}
-#if KEEP_STATISTICS
- int allocthreadnum;
- if (queue->flags & WORK_QUEUE_FLAG_MULTI)
- allocthreadnum = queue->threads + 1;
- else
- allocthreadnum = queue->threads;
+ }
- // output per-thread statistics
- for (threadnum = 0; threadnum < allocthreadnum; threadnum++)
- {
- work_thread_info *thread = &queue->thread[threadnum];
- osd_ticks_t total = thread->runtime + thread->waittime + thread->spintime;
- printf("Thread %d: items=%9d run=%5.2f%% (%5.2f%%) spin=%5.2f%% wait/other=%5.2f%% total=%9d\n",
- threadnum, thread->itemsdone,
- (double)thread->runtime * 100.0 / (double)total,
- (double)thread->actruntime * 100.0 / (double)total,
- (double)thread->spintime * 100.0 / (double)total,
- (double)thread->waittime * 100.0 / (double)total,
- (UINT32) total);
- }
-#endif
+#if KEEP_STATISTICS
+ // output per-thread statistics
+ for (work_thread_info *thread : queue->thread)
+ {
+ osd_ticks_t total = thread->runtime + thread->waittime + thread->spintime;
+ printf("Thread %d: items=%9d run=%5.2f%% (%5.2f%%) spin=%5.2f%% wait/other=%5.2f%% total=%9d\n",
+ thread->id, thread->itemsdone,
+ (double)thread->runtime * 100.0 / (double)total,
+ (double)thread->actruntime * 100.0 / (double)total,
+ (double)thread->spintime * 100.0 / (double)total,
+ (double)thread->waittime * 100.0 / (double)total,
+ (UINT32) total);
}
+#endif
// free the list
- if (queue->thread != NULL)
- osd_free(queue->thread);
-
- // free all the events
- if (queue->doneevent != NULL)
- osd_event_free(queue->doneevent);
+ for (auto & th : queue->thread)
+ delete th;
+ queue->thread.clear();
// free all items in the free list
while (queue->free.load() != nullptr)
@@ -429,8 +433,8 @@ void osd_work_queue_free(osd_work_queue *queue)
osd_work_item *item = (osd_work_item *)queue->free;
queue->free = item->next;
if (item->event != NULL)
- osd_event_free(item->event);
- osd_free(item);
+ delete item->event;
+ delete item;
}
// free all items in the active list
@@ -439,20 +443,19 @@ void osd_work_queue_free(osd_work_queue *queue)
osd_work_item *item = (osd_work_item *)queue->list;
queue->list = item->next;
if (item->event != NULL)
- osd_event_free(item->event);
- osd_free(item);
+ delete item->event;
+ delete item;
}
#if KEEP_STATISTICS
- printf("Items queued = %9d\n", queue->itemsqueued);
- printf("SetEvent calls = %9d\n", queue->setevents);
- printf("Extra items = %9d\n", queue->extraitems);
- printf("Spin loops = %9d\n", queue->spinloops);
+ printf("Items queued = %9d\n", queue->itemsqueued.load());
+ printf("SetEvent calls = %9d\n", queue->setevents.load());
+ printf("Extra items = %9d\n", queue->extraitems.load());
+ printf("Spin loops = %9d\n", queue->spinloops.load());
#endif
- delete queue->lock;
// free the queue itself
- osd_free(queue);
+ delete queue;
}
@@ -473,7 +476,7 @@ osd_work_item *osd_work_item_queue_multiple(osd_work_queue *queue, osd_work_call
// first allocate a new work item; try the free list first
{
- std::lock_guard<std::mutex> lock(*queue->lock);
+ std::lock_guard<std::mutex> lock(queue->lock);
do
{
item = (osd_work_item *)queue->free;
@@ -484,12 +487,9 @@ osd_work_item *osd_work_item_queue_multiple(osd_work_queue *queue, osd_work_call
if (item == NULL)
{
// allocate the item
- item = (osd_work_item *)osd_malloc(sizeof(*item));
+ item = new osd_work_item(*queue);
if (item == NULL)
return NULL;
- item->event = NULL;
- item->queue = queue;
- item->done = FALSE;
}
else
{
@@ -512,7 +512,7 @@ osd_work_item *osd_work_item_queue_multiple(osd_work_queue *queue, osd_work_call
// enqueue the whole thing within the critical section
{
- std::lock_guard<std::mutex> lock(*queue->lock);
+ std::lock_guard<std::mutex> lock(queue->lock);
*queue->tailptr = itemlist;
queue->tailptr = item_tailptr;
}
@@ -529,12 +529,12 @@ osd_work_item *osd_work_item_queue_multiple(osd_work_queue *queue, osd_work_call
// iterate over all the threads
for (threadnum = 0; threadnum < queue->threads; threadnum++)
{
- work_thread_info *thread = &queue->thread[threadnum];
+ work_thread_info *thread = queue->thread[threadnum];
// if this thread is not active, wake him up
if (!thread->active)
{
- osd_event_set(thread->wakeevent);
+ thread->wakeevent.set();
add_to_stat(queue->setevents, 1);
// for non-shared, the first one we find is good enough
@@ -547,9 +547,9 @@ osd_work_item *osd_work_item_queue_multiple(osd_work_queue *queue, osd_work_call
// if no threads, run the queue now on this thread
if (queue->threads == 0)
{
- end_timing(queue->thread[0].waittime);
- worker_thread_process(queue, &queue->thread[0]);
- begin_timing(queue->thread[0].waittime);
+ end_timing(queue->thread[0]->waittime);
+ worker_thread_process(queue, queue->thread[0]);
+ begin_timing(queue->thread[0]->waittime);
}
// only return the item if it won't get released automatically
return (flags & WORK_ITEM_FLAG_AUTO_RELEASE) ? NULL : lastitem;
@@ -569,11 +569,11 @@ int osd_work_item_wait(osd_work_item *item, osd_ticks_t timeout)
// if we don't have an event, create one
if (item->event == NULL)
{
- std::lock_guard<std::mutex> lock(*item->queue->lock);
- item->event = osd_event_alloc(TRUE, FALSE); // manual reset, not signalled
+ std::lock_guard<std::mutex> lock(item->queue.lock);
+ item->event = new osd_event(TRUE, FALSE); // manual reset, not signalled
}
else
- osd_event_reset(item->event);
+ item->event->reset();
// if we don't have an event, we need to spin (shouldn't ever really happen)
if (item->event == NULL)
@@ -584,7 +584,7 @@ int osd_work_item_wait(osd_work_item *item, osd_ticks_t timeout)
// otherwise, block on the event until done
else if (!item->done)
- osd_event_wait(item->event, timeout);
+ item->event->wait(timeout);
// return TRUE if the refcount actually hit 0
return item->done;
@@ -613,12 +613,12 @@ void osd_work_item_release(osd_work_item *item)
osd_work_item_wait(item, 100 * osd_ticks_per_second());
// add us to the free list on our queue
- std::lock_guard<std::mutex> lock(*item->queue->lock);
+ std::lock_guard<std::mutex> lock(item->queue.lock);
do
{
- next = (osd_work_item *)item->queue->free;
+ next = (osd_work_item *) item->queue.free;
item->next = next;
- } while (!item->queue->free.compare_exchange_weak(next, item, std::memory_order_release, std::memory_order_relaxed));
+ } while (!item->queue.free.compare_exchange_weak(next, item, std::memory_order_release, std::memory_order_relaxed));
}
@@ -658,54 +658,54 @@ static int effective_num_processors(void)
static void *worker_thread_entry(void *param)
{
work_thread_info *thread = (work_thread_info *)param;
- osd_work_queue *queue = thread->queue;
+ osd_work_queue &queue = thread->queue;
// loop until we exit
for ( ;; )
{
// block waiting for work or exit
// bail on exit, and only wait if there are no pending items in queue
- if (queue->exiting)
+ if (queue.exiting)
break;
- if (!queue_has_list_items(queue))
+ if (!queue_has_list_items(&queue))
{
begin_timing(thread->waittime);
- osd_event_wait(thread->wakeevent, OSD_EVENT_WAIT_INFINITE);
+ thread->wakeevent.wait( OSD_EVENT_WAIT_INFINITE);
end_timing(thread->waittime);
}
- if (queue->exiting)
+ if (queue.exiting)
break;
// indicate that we are live
thread->active = TRUE;
- ++queue->livethreads;
+ ++queue.livethreads;
// process work items
for ( ;; )
{
// process as much as we can
- worker_thread_process(queue, thread);
+ worker_thread_process(&queue, thread);
// if we're a high frequency queue, spin for a while before giving up
- if (queue->flags & WORK_QUEUE_FLAG_HIGH_FREQ && queue->list.load() == nullptr)
+ if (queue.flags & WORK_QUEUE_FLAG_HIGH_FREQ && queue.list.load() == nullptr)
{
// spin for a while looking for more work
begin_timing(thread->spintime);
- spin_while<std::atomic<osd_work_item *>, osd_work_item *>(&queue->list, (osd_work_item *)nullptr, SPIN_LOOP_TIME);
+ spin_while<std::atomic<osd_work_item *>, osd_work_item *>(&queue.list, (osd_work_item *)nullptr, SPIN_LOOP_TIME);
end_timing(thread->spintime);
}
// if nothing more, release the processor
- if (!queue_has_list_items(queue))
+ if (!queue_has_list_items(&queue))
break;
- add_to_stat(queue->spinloops, 1);
+ add_to_stat(queue.spinloops, 1);
}
// decrement the live thread count
thread->active = FALSE;
- --queue->livethreads;
+ --queue.livethreads;
}
return NULL;
@@ -718,7 +718,7 @@ static void *worker_thread_entry(void *param)
static void worker_thread_process(osd_work_queue *queue, work_thread_info *thread)
{
- int threadid = thread - queue->thread;
+ int threadid = thread->id;
begin_timing(thread->runtime);
@@ -731,7 +731,7 @@ static void worker_thread_process(osd_work_queue *queue, work_thread_info *threa
// use a critical section to synchronize the removal of items
{
- std::lock_guard<std::mutex> lock(*queue->lock);
+ std::lock_guard<std::mutex> lock(queue->lock);
if (queue->list.load() == nullptr)
{
@@ -773,12 +773,12 @@ static void worker_thread_process(osd_work_queue *queue, work_thread_info *threa
// set the result and signal the event
else
{
- std::lock_guard<std::mutex> lock(*queue->lock);
+ std::lock_guard<std::mutex> lock(queue->lock);
if (item->event != NULL)
{
- osd_event_set(item->event);
- add_to_stat(item->queue->setevents, 1);
+ item->event->set();
+ add_to_stat(item->queue.setevents, 1);
}
}
@@ -791,7 +791,7 @@ static void worker_thread_process(osd_work_queue *queue, work_thread_info *threa
// we don't need to set the doneevent for multi queues because they spin
if (queue->waiting)
{
- osd_event_set(queue->doneevent);
+ queue->doneevent.set();
add_to_stat(queue->setevents, 1);
}
@@ -800,7 +800,7 @@ static void worker_thread_process(osd_work_queue *queue, work_thread_info *threa
bool queue_has_list_items(osd_work_queue *queue)
{
- std::lock_guard<std::mutex> lock(*queue->lock);
+ std::lock_guard<std::mutex> lock(queue->lock);
bool has_list_items = (queue->list.load() != nullptr);
return has_list_items;
}
diff --git a/src/osd/osdepend.h b/src/osd/osdepend.h
index b6ab45003e1..661160cb271 100644
--- a/src/osd/osdepend.h
+++ b/src/osd/osdepend.h
@@ -17,6 +17,7 @@
#include "osdcore.h"
#include "unicode.h"
#include "cliopts.h"
+#include "ui/menu.h"
#include <memory>
#include <string>
@@ -56,8 +57,6 @@ public:
// ======================> osd_interface
-struct slider_state;
-
// description of the currently-running machine
class osd_interface
{
@@ -80,7 +79,7 @@ public:
virtual void customize_input_type_list(simple_list<input_type_entry> &typelist) = 0;
// video overridables
- virtual slider_state *get_slider_list() = 0;
+ virtual std::vector<ui_menu_item> get_slider_list() = 0;
// font interface
virtual osd_font::ptr font_alloc() = 0;
diff --git a/src/osd/sdl/ledutil.sh b/src/osd/sdl/ledutil.sh
deleted file mode 100644
index e91e44200de..00000000000
--- a/src/osd/sdl/ledutil.sh
+++ /dev/null
@@ -1,95 +0,0 @@
-#!/bin/sh
-# license:BSD-3-Clause
-# copyright-holders:Olivier Galibert, R. Belmont
-# ============================================================
-#
-# ledutil.sh - Example script for output notifiers
-#
-# This is a very basic implementation which
-#
-# a) Sets kbd leds if led0, led1, led2 is received
-# b) Beeps if led0 is set to on (state=1)
-# c) Writes a message when pause is received
-#
-# use "sh ledutil.sh -h" to get more information
-#
-# ============================================================
-
-SDLMAME_OUTPUT=/tmp/sdlmame_out
-
-verbose=0
-autoclose=0
-myname=`basename $0`
-paused=0
-
-while [ $# -gt 0 ]; do
- case $1 in
- -v)
- verbose=1
- ;;
- -a)
- autoclose=1
- ;;
- -h)
- echo "Usage: $myname [-a] [-v]"
- echo ""
- echo " -a Automatically close when sdlmame ends game"
- echo " -v LOG all messages received"
- echo " -h Get help"
- echo ""
- exit
- ;;
- *)
- echo "$myname: invalid option $1"
- echo "Try \`$myname -h' for more information."
- exit
- ;;
- esac
- shift
-done
-
-if [ ! -e ${SDLMAME_OUTPUT} ]; then
- mkfifo ${SDLMAME_OUTPUT}
-fi
-
-while true; do
- cat ${SDLMAME_OUTPUT} | while read class pidnum what state; do
- [ $verbose = 1 ] && echo LOG: $class $pidnum $what $state
- if [ "$class" = "MAME" ]; then
- case "$what" in
- START)
- echo Process $pidnum starting game $state
- paused=0
- ;;
- STOP)
- echo Process $pidnum stopping game $state
- ;;
- esac
- fi
- if [ "$class" = "OUT" ]; then
- case "$what" in
- led0)
- [ "$state" = 1 ] && beep
- [ "$state" = 1 ] && xset led 1
- [ "$state" = 0 ] && xset -led 1
- ;;
- led1)
- [ "$state" = 1 ] && xset led 2
- [ "$state" = 0 ] && xset -led 2
- ;;
- led2)
- [ "$state" = 1 ] && xset led 3
- [ "$state" = 0 ] && xset -led 3
- ;;
- pause)
- paused=$state
- echo Pause $paused!
- ;;
- esac
- fi
- done
- [ $autoclose = 1 ] && break;
-done
-
-rm -f ${SDLMAME_OUTPUT}
-
diff --git a/src/osd/sdl/osdsdl.h b/src/osd/sdl/osdsdl.h
index ddeabebc386..d3ce734b4d2 100644
--- a/src/osd/sdl/osdsdl.h
+++ b/src/osd/sdl/osdsdl.h
@@ -3,8 +3,6 @@
#ifndef _osdsdl_h_
#define _osdsdl_h_
-#include "sdlinc.h"
-
#include "watchdog.h"
#include "clifront.h"
#include "modules/lib/osdobj_common.h"
@@ -142,9 +140,6 @@ public:
virtual void init(running_machine &machine) override;
virtual void update(bool skip_redraw) override;
- // video overridables
- virtual slider_state *get_slider_list() override;
-
// input overridables
virtual void customize_input_type_list(simple_list<input_type_entry> &typelist) override;
@@ -152,13 +147,9 @@ public:
virtual bool video_init() override;
virtual bool window_init() override;
- virtual bool output_init() override;
- //virtual bool midi_init();
virtual void video_exit() override;
virtual void window_exit() override;
- virtual void output_exit() override;
- //virtual void midi_exit();
// sdl specific
void poll_inputs(running_machine &machine);
@@ -180,7 +171,6 @@ private:
sdl_options &m_options;
watchdog *m_watchdog;
- slider_state * m_sliders;
};
//============================================================
diff --git a/src/osd/sdl/output.cpp b/src/osd/sdl/output.cpp
deleted file mode 100644
index a2eb5b3dad1..00000000000
--- a/src/osd/sdl/output.cpp
+++ /dev/null
@@ -1,138 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Olivier Galibert, R. Belmont
-//============================================================
-//
-// output.c - Generic implementation of MAME output routines
-//
-//============================================================
-
-#if !defined(SDLMAME_WIN32)
-
-#include <stdio.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <inttypes.h>
-
-// MAME headers
-#include "emu.h"
-
-// MAMEOS headers
-#include "osdsdl.h"
-
-
-
-//============================================================
-// CONSTANTS
-//============================================================
-
-#define SDLMAME_OUTPUT "/tmp/sdlmame_out"
-
-/*
- * Using long/int should be sufficient on all
- * architectures.
- */
-
-
-//============================================================
-// TYPEDEFS
-//============================================================
-
-//============================================================
-// PRIVATE VARIABLES
-//============================================================
-
-static FILE *output;
-
-//============================================================
-// FUNCTION PROTOTYPES
-//============================================================
-
-static void notifier_callback(const char *outname, INT32 value, void *param);
-
-//============================================================
-// osd_get_pid
-//============================================================
-
-intptr_t osd_getpid(void)
-{
- return intptr_t(getpid());
-}
-
-//============================================================
-// output_init
-//============================================================
-
-bool sdl_osd_interface::output_init()
-{
- int fildes;
-
- fildes = open(SDLMAME_OUTPUT, O_RDWR | O_NONBLOCK);
-
- if (fildes < 0)
- {
- output = NULL;
- osd_printf_verbose("output: unable to open output notifier file %s\n", SDLMAME_OUTPUT);
- }
- else
- {
- output = fdopen(fildes, "w");
-
- osd_printf_verbose("output: opened output notifier file %s\n", SDLMAME_OUTPUT);
- fprintf(output, "MAME %" PRIxPTR " START %s\n", osd_getpid(), this->machine().system().name);
- fflush(output);
- }
-
- machine().output().set_notifier(NULL, notifier_callback, NULL);
- return true;
-}
-
-
-//============================================================
-// winoutput_exit
-//============================================================
-
-void sdl_osd_interface::output_exit()
-{
- if (output != NULL)
- {
- fprintf(output, "MAME %" PRIxPTR " STOP %s\n", osd_getpid(), machine().system().name);
- fflush(output);
- fclose(output);
- output = NULL;
- osd_printf_verbose("output: closed output notifier file\n");
- }
-}
-
-//============================================================
-// notifier_callback
-//============================================================
-
-static void notifier_callback(const char *outname, INT32 value, void *param)
-{
- if (output != NULL)
- {
- fprintf(output, "OUT %" PRIxPTR " %s %d\n", osd_getpid(), outname, value);
- fflush(output);
- }
-}
-
-#else /* SDLMAME_WIN32 */
-
-#include "emu.h"
-#include "osdsdl.h"
-#include "emucore.h"
-
-//============================================================
-// Stub for win32
-//============================================================
-
-bool sdl_osd_interface::output_init()
-{
- return true;
-}
-
-void sdl_osd_interface::output_exit()
-{
-}
-
-#endif /* SDLMAME_WIN32 */
diff --git a/src/osd/sdl/sdlmain.cpp b/src/osd/sdl/sdlmain.cpp
index 8f978560642..270bc714320 100644
--- a/src/osd/sdl/sdlmain.cpp
+++ b/src/osd/sdl/sdlmain.cpp
@@ -250,7 +250,7 @@ static void output_oslog(const running_machine &machine, const char *buffer)
//============================================================
sdl_osd_interface::sdl_osd_interface(sdl_options &options)
-: osd_common_t(options), m_options(options), m_watchdog(nullptr), m_sliders(nullptr)
+: osd_common_t(options), m_options(options), m_watchdog(nullptr)
{
}
diff --git a/src/osd/sdl/video.cpp b/src/osd/sdl/video.cpp
index 65d80d77432..582836f0c8e 100644
--- a/src/osd/sdl/video.cpp
+++ b/src/osd/sdl/video.cpp
@@ -91,16 +91,6 @@ bool sdl_osd_interface::video_init()
return true;
}
-
-//============================================================
-// get_slider_list
-//============================================================
-
-slider_state *sdl_osd_interface::get_slider_list()
-{
- return m_sliders;
-}
-
//============================================================
// video_exit
//============================================================
@@ -116,6 +106,11 @@ void sdl_osd_interface::video_exit()
// sdlvideo_monitor_refresh
//============================================================
+inline osd_rect SDL_Rect_to_osd_rect(const SDL_Rect &r)
+{
+ return osd_rect(r.x, r.y, r.w, r.h);
+}
+
void sdl_monitor_info::refresh()
{
SDL_DisplayMode dmode;
diff --git a/src/osd/sdl/video.h b/src/osd/sdl/video.h
index 0d9d66a5e61..1c6993c0c0b 100644
--- a/src/osd/sdl/video.h
+++ b/src/osd/sdl/video.h
@@ -18,11 +18,6 @@
// TYPE DEFINITIONS
//============================================================
-inline osd_rect SDL_Rect_to_osd_rect(const SDL_Rect &r)
-{
- return osd_rect(r.x, r.y, r.w, r.h);
-}
-
class sdl_monitor_info : public osd_monitor_info
{
public:
diff --git a/src/osd/sdl/watchdog.cpp b/src/osd/sdl/watchdog.cpp
index eaa216dd0f8..8a86464cb56 100644
--- a/src/osd/sdl/watchdog.cpp
+++ b/src/osd/sdl/watchdog.cpp
@@ -21,13 +21,13 @@ static void *watchdog_thread(void *param)
while (TRUE)
{
- if (osd_event_wait(thiz->event(), thiz->getTimeout()))
+ if (thiz->event().wait(thiz->getTimeout()))
{
if (thiz->do_exit())
break;
else
{
- osd_event_reset(thiz->event());
+ thiz->event().reset();
continue;
}
}
@@ -42,9 +42,9 @@ static void *watchdog_thread(void *param)
}
watchdog::watchdog(void)
+: m_event(1,0)
{
m_do_exit = 0;
- m_event = osd_event_alloc(1, 0);
m_thread = new std::thread(watchdog_thread, this);
m_timeout = 60 * osd_ticks_per_second();
}
@@ -52,10 +52,9 @@ watchdog::watchdog(void)
watchdog::~watchdog(void)
{
m_do_exit = 1;
- osd_event_set(m_event);
+ m_event.set();
m_thread->join();
delete m_thread;
- osd_event_free(m_event);
}
void watchdog::setTimeout(int timeout)
diff --git a/src/osd/sdl/watchdog.h b/src/osd/sdl/watchdog.h
index cddba0100ef..9cc2ee03322 100644
--- a/src/osd/sdl/watchdog.h
+++ b/src/osd/sdl/watchdog.h
@@ -20,15 +20,15 @@ public:
watchdog(void);
~watchdog(void);
- void reset() { osd_event_set(m_event); }
+ void reset() { m_event.set(); }
- osd_event * event(void) { return m_event; }
+ osd_event & event(void) { return m_event; }
INT32 do_exit(void) { return m_do_exit; }
osd_ticks_t getTimeout(void) { return m_timeout; }
void setTimeout(int timeout);
private:
- osd_event * m_event;
- std::thread* m_thread;
+ osd_event m_event;
+ std::thread* m_thread;
std::atomic<INT32> m_do_exit;
osd_ticks_t m_timeout;
diff --git a/src/osd/sdl/window.cpp b/src/osd/sdl/window.cpp
index 18274b6ecb2..7cec35d400a 100644
--- a/src/osd/sdl/window.cpp
+++ b/src/osd/sdl/window.cpp
@@ -89,6 +89,14 @@ sdl_window_info *sdl_window_list;
static sdl_window_info **last_window_ptr;
+class SDL_DM_Wrapper
+{
+public:
+ SDL_DisplayMode mode;
+};
+
+
+
// event handling
static SDL_threadID main_threadid;
static SDL_threadID window_threadid;
@@ -300,33 +308,13 @@ void sdl_osd_interface::update_slider_list()
void sdl_osd_interface::build_slider_list()
{
- m_sliders = nullptr;
- slider_state* full_list = nullptr;
- slider_state* curr = nullptr;
+ m_sliders.clear();
+
for (sdl_window_info *window = sdl_window_list; window != nullptr; window = window->m_next)
{
- // take the sliders of the first window
- slider_state* window_sliders = window->renderer().get_slider_list();
- if (window_sliders == nullptr)
- {
- continue;
- }
-
- if (full_list == nullptr)
- {
- full_list = curr = window_sliders;
- }
- else
- {
- curr->next = window_sliders;
- }
-
- while (curr->next != nullptr) {
- curr = curr->next;
- }
+ std::vector<ui_menu_item> window_sliders = window->renderer().get_slider_list();
+ m_sliders.insert(m_sliders.end(), window_sliders.begin(), window_sliders.end());
}
-
- m_sliders = full_list;
}
//============================================================
@@ -488,7 +476,7 @@ OSDWORK_CALLBACK( sdl_window_info::sdlwindow_toggle_full_screen_wt )
if (window->fullscreen() && (video_config.switchres || is_osx))
{
SDL_SetWindowFullscreen(window->sdl_window(), 0); // Try to set mode
- SDL_SetWindowDisplayMode(window->sdl_window(), &window->m_original_mode); // Try to set mode
+ SDL_SetWindowDisplayMode(window->sdl_window(), &window->m_original_mode->mode); // Try to set mode
SDL_SetWindowFullscreen(window->sdl_window(), SDL_WINDOW_FULLSCREEN); // Try to set mode
}
SDL_DestroyWindow(window->sdl_window());
@@ -623,9 +611,6 @@ int sdl_window_info::window_init()
set_renderer(osd_renderer::make_for_type(video_config.mode, reinterpret_cast<osd_window *>(this)));
- // create an event that we can use to skip blitting
- m_rendered_event = osd_event_alloc(FALSE, TRUE);
-
// load the layout
m_target = m_machine.render().target_alloc();
@@ -673,7 +658,7 @@ OSDWORK_CALLBACK( sdl_window_info::sdlwindow_video_window_destroy_wt )
if (window->fullscreen() && video_config.switchres)
{
SDL_SetWindowFullscreen(window->sdl_window(), 0); // Try to set mode
- SDL_SetWindowDisplayMode(window->sdl_window(), &window->m_original_mode); // Try to set mode
+ SDL_SetWindowDisplayMode(window->sdl_window(), &window->m_original_mode->mode); // Try to set mode
SDL_SetWindowFullscreen(window->sdl_window(), SDL_WINDOW_FULLSCREEN); // Try to set mode
}
SDL_DestroyWindow(window->sdl_window());
@@ -706,9 +691,6 @@ void sdl_window_info::destroy()
// free the render target, after the textures!
this->machine().render().target_free(m_target);
- // free the event
- osd_event_free(m_rendered_event);
-
}
@@ -828,7 +810,7 @@ void sdl_window_info::update()
else
event_wait_ticks = 0;
- if (osd_event_wait(m_rendered_event, event_wait_ticks))
+ if (m_rendered_event.wait(event_wait_ticks))
{
// ensure the target bounds are up-to-date, and then get the primitives
@@ -967,7 +949,7 @@ OSDWORK_CALLBACK( sdl_window_info::complete_create_wt )
SDL_DisplayMode mode;
//SDL_GetCurrentDisplayMode(window().monitor()->handle, &mode);
SDL_GetWindowDisplayMode(window->sdl_window(), &mode);
- window->m_original_mode = mode;
+ window->m_original_mode->mode = mode;
mode.w = temp.width();
mode.h = temp.height();
if (window->m_win_config.refresh)
@@ -1130,7 +1112,7 @@ OSDWORK_CALLBACK( sdl_window_info::draw_video_contents_wt )
}
/* all done, ready for next */
- osd_event_set(window->m_rendered_event);
+ window->m_rendered_event.set();
osd_free(wp);
return nullptr;
@@ -1319,6 +1301,16 @@ osd_dim sdl_window_info::get_min_bounds(int constrain)
return osd_dim(minwidth, minheight);
}
+//============================================================
+// get_size
+//============================================================
+
+osd_dim sdl_window_info::get_size()
+{
+ int w=0; int h=0;
+ SDL_GetWindowSize(m_sdl_window, &w, &h);
+ return osd_dim(w,h);
+}
//============================================================
@@ -1361,3 +1353,37 @@ osd_dim sdl_window_info::get_max_bounds(int constrain)
return maximum.dim();
}
+
+//============================================================
+// construction and destruction
+//============================================================
+
+sdl_window_info::sdl_window_info(running_machine &a_machine, int index, osd_monitor_info *a_monitor,
+ const osd_window_config *config)
+: osd_window(), m_next(NULL),
+ // Following three are used by input code to defer resizes
+ m_resize_width(0),
+ m_resize_height(0),
+ m_last_resize(0),
+ m_minimum_dim(0,0),
+ m_windowed_dim(0,0),
+ m_rendered_event(0, 1), m_target(0),
+ m_sdl_window(NULL),
+ m_machine(a_machine), m_monitor(a_monitor), m_fullscreen(0)
+{
+ m_win_config = *config;
+ m_index = index;
+
+ //FIXME: these should be per_window in config-> or even better a bit set
+ m_fullscreen = !video_config.windowed;
+ m_prescale = video_config.prescale;
+
+ m_windowed_dim = osd_dim(config->width, config->height);
+ m_original_mode = global_alloc(SDL_DM_Wrapper);
+}
+
+sdl_window_info::~sdl_window_info()
+{
+ global_free(m_renderer);
+ global_free(m_original_mode);
+}
diff --git a/src/osd/sdl/window.h b/src/osd/sdl/window.h
index 5e3e58f92ed..7a62d3a5925 100644
--- a/src/osd/sdl/window.h
+++ b/src/osd/sdl/window.h
@@ -11,7 +11,6 @@
#ifndef __SDLWINDOW__
#define __SDLWINDOW__
-#include "sdlinc.h"
#include "osdsdl.h"
#include "video.h"
@@ -24,6 +23,10 @@
// TYPE DEFINITIONS
//============================================================
+// forward of SDL_DisplayMode not possible (typedef struct) - define wrapper
+
+class SDL_DM_Wrapper;
+
typedef uintptr_t HashT;
#define OSDWORK_CALLBACK(name) void *name(void *param, ATTR_UNUSED int threadid)
@@ -32,32 +35,9 @@ class sdl_window_info : public osd_window
{
public:
sdl_window_info(running_machine &a_machine, int index, osd_monitor_info *a_monitor,
- const osd_window_config *config)
- : osd_window(), m_next(NULL),
- // Following three are used by input code to defer resizes
- m_resize_width(0),
- m_resize_height(0),
- m_last_resize(0),
- m_minimum_dim(0,0),
- m_windowed_dim(0,0),
- m_rendered_event(0), m_target(0),
- m_sdl_window(NULL),
- m_machine(a_machine), m_monitor(a_monitor), m_fullscreen(0)
- {
- m_win_config = *config;
- m_index = index;
-
- //FIXME: these should be per_window in config-> or even better a bit set
- m_fullscreen = !video_config.windowed;
- m_prescale = video_config.prescale;
-
- m_windowed_dim = osd_dim(config->width, config->height);
- }
+ const osd_window_config *config);
- ~sdl_window_info()
- {
- global_free(m_renderer);
- }
+ ~sdl_window_info();
int window_init();
@@ -69,12 +49,7 @@ public:
void notify_changed();
- osd_dim get_size() override
- {
- int w=0; int h=0;
- SDL_GetWindowSize(m_sdl_window, &w, &h);
- return osd_dim(w,h);
- }
+ osd_dim get_size() override;
int xy_to_render_target(int x, int y, int *xt, int *yt);
@@ -106,13 +81,13 @@ private:
osd_dim m_windowed_dim;
// rendering info
- osd_event * m_rendered_event;
+ osd_event m_rendered_event;
render_target * m_target;
// Needs to be here as well so we can identify window
SDL_Window *m_sdl_window;
// Original display_mode
- SDL_DisplayMode m_original_mode;
+ SDL_DM_Wrapper *m_original_mode;
int m_extra_flags;
diff --git a/src/osd/strconv.h b/src/osd/strconv.h
index 6d23d78fbb1..aaab2527d25 100644
--- a/src/osd/strconv.h
+++ b/src/osd/strconv.h
@@ -33,6 +33,17 @@ char *utf8_from_astring(const CHAR *s);
WCHAR *wstring_from_utf8(const char *s);
char *utf8_from_wstring(const WCHAR *s);
+struct osd_wstr_deleter
+{
+ void operator () (wchar_t* wstr)
+ {
+ if (wstr != nullptr)
+ osd_free(wstr);
+ }
+};
+
+typedef std::unique_ptr<wchar_t, osd_wstr_deleter> osd_unique_wstr;
+
#ifdef UNICODE
#define tstring_from_utf8 wstring_from_utf8
#define utf8_from_tstring utf8_from_wstring
diff --git a/src/osd/windows/ledutil.cpp b/src/osd/windows/ledutil.cpp
deleted file mode 100644
index 85c7cca1fe1..00000000000
--- a/src/osd/windows/ledutil.cpp
+++ /dev/null
@@ -1,710 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Aaron Giles,Paul Priest
-//============================================================
-//
-// ledutil.c - Win32 example code that tracks changing
-// outputs and updates the keyboard LEDs in response
-//
-//============================================================
-//
-// This is sample code. To use it as a starting point, you
-// should do the following:
-//
-// 1. Change the CLIENT_ID define to something unique.
-//
-// 2. Change the WINDOW_CLASS and WINDOW_NAME defines to
-// something unique.
-//
-// 3. Delete all the code from the >8 snip 8< comment and
-// downward.
-//
-// 4. Implement the following functions:
-//
-// output_startup - called at app init time
-// output_shutdown - called before the app exits
-// output_mame_start - called when MAME starts
-// output_mame_stop - called when MAME exits
-// output_set_state - called whenever state changes
-//
-//============================================================
-
-// standard windows headers
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-#include <winioctl.h>
-
-// standard C headers
-#include <conio.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-// MAME output header file
-typedef int running_machine;
-#include "osdcomm.h"
-#include "output.h"
-
-
-
-//============================================================
-// DEBUGGING
-//============================================================
-
-// note you need to compile as a console app to have any of
-// these printfs show up
-#define DEBUG_VERSION 0
-
-#if DEBUG_VERSION
-#define DEBUG_PRINTF(x) printf x
-#else
-#define DEBUG_PRINTF(x)
-#endif
-
-
-//============================================================
-// CONSTANTS
-//============================================================
-
-// unique client ID
-#define CLIENT_ID (('M' << 24) | ('L' << 16) | ('E' << 8) | ('D' << 0))
-
-// LED methods
-#define LED_METHOD_PS2 0
-#define LED_METHOD_USB 1
-
-// window parameters
-#define WINDOW_CLASS TEXT("LEDSample")
-#define WINDOW_NAME TEXT("LEDSample")
-
-// window styles
-#define WINDOW_STYLE WS_OVERLAPPEDWINDOW
-#define WINDOW_STYLE_EX 0
-
-// Define the keyboard indicators.
-// (Definitions borrowed from ntddkbd.h)
-
-#define IOCTL_KEYBOARD_SET_INDICATORS CTL_CODE(FILE_DEVICE_KEYBOARD, 0x0002, METHOD_BUFFERED, FILE_ANY_ACCESS)
-#define IOCTL_KEYBOARD_QUERY_TYPEMATIC CTL_CODE(FILE_DEVICE_KEYBOARD, 0x0008, METHOD_BUFFERED, FILE_ANY_ACCESS)
-#define IOCTL_KEYBOARD_QUERY_INDICATORS CTL_CODE(FILE_DEVICE_KEYBOARD, 0x0010, METHOD_BUFFERED, FILE_ANY_ACCESS)
-
-#define KEYBOARD_SCROLL_LOCK_ON 1
-#define KEYBOARD_NUM_LOCK_ON 2
-#define KEYBOARD_CAPS_LOCK_ON 4
-
-
-
-//============================================================
-// TYPE DEFINITIONS
-//============================================================
-
-struct KEYBOARD_INDICATOR_PARAMETERS
-{
- USHORT UnitId; // Unit identifier.
- USHORT LedFlags; // LED indicator state.
-};
-
-
-struct id_map_entry
-{
- id_map_entry * next;
- const char * name;
- WPARAM id;
-};
-
-
-
-//============================================================
-// GLOBAL VARIABLES
-//============================================================
-
-static int ledmethod;
-static int original_state;
-static int current_state;
-static int pause_state;
-static HANDLE hKbdDev;
-
-static HWND mame_target;
-static HWND listener_hwnd;
-
-static id_map_entry * idmaplist;
-
-// message IDs
-static UINT om_mame_start;
-static UINT om_mame_stop;
-static UINT om_mame_update_state;
-static UINT om_mame_register_client;
-static UINT om_mame_unregister_client;
-static UINT om_mame_get_id_string;
-
-
-
-//============================================================
-// FUNCTION PROTOTYPES
-//============================================================
-
-static int create_window_class(void);
-static LRESULT CALLBACK listener_window_proc(HWND wnd, UINT message, WPARAM wparam, LPARAM lparam);
-static LRESULT handle_mame_start(WPARAM wparam, LPARAM lparam);
-static LRESULT handle_mame_stop(WPARAM wparam, LPARAM lparam);
-static LRESULT handle_copydata(WPARAM wparam, LPARAM lparam);
-static void reset_id_to_outname_cache(void);
-static const char *map_id_to_outname(WPARAM id);
-static LRESULT handle_update_state(WPARAM wparam, LPARAM lparam);
-
-// these functions provide the meat
-static void output_startup(const char *commandline);
-static void output_mame_start(void);
-static void output_set_state(const char *name, INT32 state);
-static void output_mame_stop(void);
-static void output_shutdown(void);
-
-static int led_get_state(void);
-static void led_set_state(int state);
-
-
-//============================================================
-// main
-//============================================================
-
-int main(int argc, char *argv[])
-{
- const char *arg = (argc > 1) ? argv[1] : "";
- int exitcode = 1;
- HWND otherwnd;
- MSG message;
- int result;
-
- // see if there is another instance of us running
- otherwnd = FindWindow(WINDOW_CLASS, WINDOW_NAME);
-
- // if the argument is "-kill", post a close message
- if (strcmp(arg, "-kill") == 0)
- {
- if (otherwnd != nullptr)
- PostMessage(otherwnd, WM_QUIT, 0, 0);
- return (otherwnd != nullptr) ? 1 : 0;
- }
-
- // if we had another instance, defer to it
- if (otherwnd != nullptr)
- return 0;
-
- // call the startup code
- output_startup(arg);
-
- // create our window class
- result = create_window_class();
- if (result != 0)
- goto error;
-
- // create a window
- listener_hwnd = CreateWindowEx(
- WINDOW_STYLE_EX,
- WINDOW_CLASS,
- WINDOW_NAME,
- WINDOW_STYLE,
- 0, 0,
- 1, 1,
- nullptr,
- nullptr,
- GetModuleHandle(nullptr),
- nullptr);
- if (listener_hwnd == nullptr)
- goto error;
-
- // allocate message ids
- om_mame_start = RegisterWindowMessage(OM_MAME_START);
- if (om_mame_start == 0)
- goto error;
- om_mame_stop = RegisterWindowMessage(OM_MAME_STOP);
- if (om_mame_stop == 0)
- goto error;
- om_mame_update_state = RegisterWindowMessage(OM_MAME_UPDATE_STATE);
- if (om_mame_update_state == 0)
- goto error;
-
- om_mame_register_client = RegisterWindowMessage(OM_MAME_REGISTER_CLIENT);
- if (om_mame_register_client == 0)
- goto error;
- om_mame_unregister_client = RegisterWindowMessage(OM_MAME_UNREGISTER_CLIENT);
- if (om_mame_unregister_client == 0)
- goto error;
- om_mame_get_id_string = RegisterWindowMessage(OM_MAME_GET_ID_STRING);
- if (om_mame_get_id_string == 0)
- goto error;
-
- // see if MAME is already running
- otherwnd = FindWindow(OUTPUT_WINDOW_CLASS, OUTPUT_WINDOW_NAME);
- if (otherwnd != nullptr)
- handle_mame_start((WPARAM)otherwnd, 0);
-
- // process messages
- while (GetMessage(&message, nullptr, 0, 0))
- {
- TranslateMessage(&message);
- DispatchMessage(&message);
- }
-
- // reset on the way out if still live
- if (mame_target != nullptr)
- handle_mame_stop((WPARAM)mame_target, 0);
- exitcode = 0;
-
-error:
- // call the shutdown code
- output_shutdown();
-
- return exitcode;
-}
-
-
-//============================================================
-// create_window_class
-//============================================================
-
-static int create_window_class(void)
-{
- static int classes_created = FALSE;
-
- /* only do this once */
- if (!classes_created)
- {
- WNDCLASS wc = { 0 };
-
- // initialize the description of the window class
- wc.lpszClassName = WINDOW_CLASS;
- wc.hInstance = GetModuleHandle(nullptr);
- wc.lpfnWndProc = listener_window_proc;
-
- // register the class; fail if we can't
- if (!RegisterClass(&wc))
- return 1;
- classes_created = TRUE;
- }
-
- return 0;
-}
-
-
-//============================================================
-// window_proc
-//============================================================
-
-static LRESULT CALLBACK listener_window_proc(HWND wnd, UINT message, WPARAM wparam, LPARAM lparam)
-{
- // OM_MAME_START: register ourselves with the new MAME (first instance only)
- if (message == om_mame_start)
- return handle_mame_start(wparam, lparam);
-
- // OM_MAME_STOP: no need to unregister, just note that we've stopped caring and reset the LEDs
- else if (message == om_mame_stop)
- return handle_mame_stop(wparam, lparam);
-
- // OM_MAME_UPDATE_STATE: update the state of this item if we care
- else if (message == om_mame_update_state)
- return handle_update_state(wparam, lparam);
-
- // WM_COPYDATA: extract the string and create an ID map entry
- else if (message == WM_COPYDATA)
- return handle_copydata(wparam, lparam);
-
- // everything else is default
- else
- return DefWindowProc(wnd, message, wparam, lparam);
-}
-
-
-//============================================================
-// handle_mame_start
-//============================================================
-
-static LRESULT handle_mame_start(WPARAM wparam, LPARAM lparam)
-{
- DEBUG_PRINTF(("mame_start (%08X)\n", (UINT32)wparam));
-
- // make this the targeted version of MAME
- mame_target = (HWND)wparam;
-
- // initialize the LED states
- output_mame_start();
- reset_id_to_outname_cache();
-
- // register ourselves as a client
- PostMessage(mame_target, om_mame_register_client, (WPARAM)listener_hwnd, CLIENT_ID);
-
- // get the game name
- map_id_to_outname(0);
- return 0;
-}
-
-
-//============================================================
-// handle_mame_stop
-//============================================================
-
-static LRESULT handle_mame_stop(WPARAM wparam, LPARAM lparam)
-{
- DEBUG_PRINTF(("mame_stop (%08X)\n", (UINT32)wparam));
-
- // ignore if this is not the instance we care about
- if (mame_target != (HWND)wparam)
- return 1;
-
- // clear our target out
- mame_target = nullptr;
- reset_id_to_outname_cache();
-
- // reset the LED states
- output_mame_stop();
- return 0;
-}
-
-
-//============================================================
-// handle_copydata
-//============================================================
-
-static LRESULT handle_copydata(WPARAM wparam, LPARAM lparam)
-{
- COPYDATASTRUCT *copydata = (COPYDATASTRUCT *)lparam;
- copydata_id_string *data = (copydata_id_string *)copydata->lpData;
- id_map_entry *entry;
- char *string;
-
- DEBUG_PRINTF(("copydata (%08X)\n", (UINT32)wparam));
-
- // ignore requests we don't care about
- if (mame_target != (HWND)wparam)
- return 1;
-
- // allocate memory
- entry = (id_map_entry *)malloc(sizeof(*entry));
- if (entry == nullptr)
- return 0;
-
- string = (char *)malloc(strlen(data->string) + 1);
- if (string == nullptr)
- {
- free(entry);
- return 0;
- }
-
- // if all allocations worked, make a new entry
- entry->next = idmaplist;
- entry->name = string;
- entry->id = data->id;
-
- // copy the string and hook us into the list
- strcpy(string, data->string);
- idmaplist = entry;
-
- DEBUG_PRINTF((" id %d = '%s'\n", (int)entry->id, entry->name));
-
- return 0;
-}
-
-
-//============================================================
-// reset_id_to_outname_cache
-//============================================================
-
-static void reset_id_to_outname_cache(void)
-{
- // free our ID list
- while (idmaplist != nullptr)
- {
- id_map_entry *temp = idmaplist;
- idmaplist = temp->next;
- free((void*)temp->name);
- free(temp);
- }
-}
-
-
-//============================================================
-// map_id_to_outname
-//============================================================
-
-static const char *map_id_to_outname(WPARAM id)
-{
- id_map_entry *entry;
-
- // see if we have an entry in our map
- for (entry = idmaplist; entry != nullptr; entry = entry->next)
- if (entry->id == id)
- return entry->name;
-
- // no entry yet; we have to ask
- SendMessage(mame_target, om_mame_get_id_string, (WPARAM)listener_hwnd, id);
-
- // now see if we have the entry in our map
- for (entry = idmaplist; entry != nullptr; entry = entry->next)
- if (entry->id == id)
- return entry->name;
-
- // if not, use an empty string
- return "";
-}
-
-
-//============================================================
-// handle_update_state
-//============================================================
-
-static LRESULT handle_update_state(WPARAM wparam, LPARAM lparam)
-{
- DEBUG_PRINTF(("update_state: id=%d state=%d\n", (UINT32)wparam, (UINT32)lparam));
- output_set_state(map_id_to_outname(wparam), lparam);
- return 0;
-}
-
-
-//
-// END BOILERPLATE CODE
-//
-// ------------------------>8 snip 8<-------------------------
-//
-// BEGIN LED-SPECIFIC CODE
-//
-
-
-//============================================================
-// output_startup
-//============================================================
-
-static void output_startup(const char *commandline)
-{
- // default to PS/2, override if USB is specified as a parameter
- ledmethod = LED_METHOD_PS2;
- if (commandline != nullptr && strcmp(commandline, "-usb") == 0)
- ledmethod = LED_METHOD_USB;
-
- // output the method
- switch (ledmethod)
- {
- case LED_METHOD_PS2:
- DEBUG_PRINTF(("Using PS/2 method\n"));
- break;
-
- case LED_METHOD_USB:
- DEBUG_PRINTF(("Using USB method\n"));
- break;
- }
-}
-
-
-//============================================================
-// output_shutdown
-//============================================================
-
-static void output_shutdown(void)
-{
- // nothing to do here
-}
-
-
-//============================================================
-// output_mame_start
-//============================================================
-
-static void output_mame_start(void)
-{
- HRESULT error_number;
-
- // initialize the system based on the method
- switch (ledmethod)
- {
- case LED_METHOD_PS2:
- if (!DefineDosDevice(DDD_RAW_TARGET_PATH, TEXT("Kbd"), TEXT("\\Device\\KeyboardClass0")))
- {
- error_number = GetLastError();
- fprintf(stderr, "Unable to open the keyboard device. (error %d)\n", (UINT32)error_number);
- return;
- }
-
- hKbdDev = CreateFile(TEXT("\\\\.\\Kbd"), GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, 0, nullptr);
- if (hKbdDev == INVALID_HANDLE_VALUE)
- {
- error_number = GetLastError();
- fprintf(stderr, "Unable to open the keyboard device. (error %d)\n", (UINT32)error_number);
- return;
- }
- break;
- }
-
- // remember the initial LED states
- original_state = current_state = led_get_state();
-}
-
-
-//============================================================
-// output_mame_stop
-//============================================================
-
-static void output_mame_stop(void)
-{
- int error_number = 0;
-
- // restore the initial LED states
- led_set_state(original_state);
-
- switch (ledmethod)
- {
- case LED_METHOD_PS2:
- if (!DefineDosDevice(DDD_REMOVE_DEFINITION, TEXT("Kbd"), nullptr))
- {
- error_number = GetLastError();
- fprintf(stderr, "Unable to close the keyboard device. (error %d)\n", error_number);
- return;
- }
- if (!CloseHandle(hKbdDev))
- {
- error_number = GetLastError();
- fprintf(stderr, "Unable to close the keyboard device. (error %d)\n", error_number);
- return;
- }
- break;
- }
-}
-
-
-//============================================================
-// output_set_state
-//============================================================
-
-static void output_set_state(const char *outname, INT32 state)
-{
- // look for pause state
- if (strcmp(outname, "pause") == 0)
- {
- if (state)
- {
- pause_state = led_get_state();
- led_set_state(original_state);
- }
- else
- {
- original_state = led_get_state();
- led_set_state(pause_state);
- }
- }
- // look for LED0/LED1/LED2 states and update accordingly
- else if (strcmp(outname, "led0") == 0)
- led_set_state((current_state & ~1) | (state & 1));
- else if (strcmp(outname, "led1") == 0)
- led_set_state((current_state & ~2) | ((state & 1) << 1));
- else if (strcmp(outname, "led2") == 0)
- led_set_state((current_state & ~4) | ((state & 1) << 2));
-}
-
-
-//============================================================
-// led_get_state
-//============================================================
-
-static int led_get_state(void)
-{
- int result = 0;
-
- switch (ledmethod)
- {
- case LED_METHOD_USB:
- {
- BYTE key_states[256];
-
- // get the current state
- GetKeyboardState(&key_states[0]);
-
- // set the numlock bit
- result |= (key_states[VK_NUMLOCK] & 1);
- result |= (key_states[VK_CAPITAL] & 1) << 1;
- result |= (key_states[VK_SCROLL] & 1) << 2;
- break;
- }
-
- case LED_METHOD_PS2:
- {
- KEYBOARD_INDICATOR_PARAMETERS OutputBuffer; // Output buffer for DeviceIoControl
- ULONG DataLength = sizeof(KEYBOARD_INDICATOR_PARAMETERS);
- ULONG ReturnedLength; // Number of bytes returned in output buffer
-
- // Address first keyboard
- OutputBuffer.UnitId = 0;
-
- DeviceIoControl(hKbdDev, IOCTL_KEYBOARD_QUERY_INDICATORS,
- nullptr, 0,
- &OutputBuffer, DataLength,
- &ReturnedLength, nullptr);
-
- // Demangle lights to match 95/98
- if (OutputBuffer.LedFlags & KEYBOARD_NUM_LOCK_ON) result |= 0x1;
- if (OutputBuffer.LedFlags & KEYBOARD_CAPS_LOCK_ON) result |= 0x2;
- if (OutputBuffer.LedFlags & KEYBOARD_SCROLL_LOCK_ON) result |= 0x4;
- break;
- }
- }
-
- return result;
-}
-
-
-//============================================================
-// led_set_state
-//============================================================
-
-static void led_set_state(int state)
-{
- current_state = state;
-
- switch (ledmethod)
- {
- case LED_METHOD_USB:
- {
- static const BYTE vk[3] = { VK_NUMLOCK, VK_CAPITAL, VK_SCROLL };
- BYTE keyState[256];
- int k;
-
- GetKeyboardState((LPBYTE)&keyState);
- for (k = 0; k < 3; k++)
- {
- if ((((state >> k) & 1) && !(keyState[vk[k]] & 1)) ||
- (!((state >> k) & 1) && (keyState[vk[k]] & 1)))
- {
- // Simulate a key press
- keybd_event(vk[k], 0x45, KEYEVENTF_EXTENDEDKEY | 0, 0);
-
- // Simulate a key release
- keybd_event(vk[k], 0x45, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
- }
- }
-
- keyState[VK_NUMLOCK] = (keyState[VK_NUMLOCK] & ~1) | ((state >> 0) & 1);
- keyState[VK_CAPITAL] = (keyState[VK_CAPITAL] & ~1) | ((state >> 1) & 1);
- keyState[VK_SCROLL] = (keyState[VK_SCROLL] & ~1) | ((state >> 2) & 1);
- SetKeyboardState(&keyState[0]);
- break;
- }
-
- case LED_METHOD_PS2:
- {
- KEYBOARD_INDICATOR_PARAMETERS InputBuffer; // Input buffer for DeviceIoControl
- ULONG DataLength = sizeof(KEYBOARD_INDICATOR_PARAMETERS);
- ULONG ReturnedLength; // Number of bytes returned in output buffer
- UINT LedFlags=0;
-
- // Demangle lights to match 95/98
- if (state & 0x1) LedFlags |= KEYBOARD_NUM_LOCK_ON;
- if (state & 0x2) LedFlags |= KEYBOARD_CAPS_LOCK_ON;
- if (state & 0x4) LedFlags |= KEYBOARD_SCROLL_LOCK_ON;
-
- // Address first keyboard
- InputBuffer.UnitId = 0;
- InputBuffer.LedFlags = LedFlags;
- DeviceIoControl(hKbdDev, IOCTL_KEYBOARD_SET_INDICATORS,
- &InputBuffer, DataLength,
- nullptr, 0,
- &ReturnedLength, nullptr);
- break;
- }
- }
-}
diff --git a/src/osd/windows/main.cpp b/src/osd/windows/main.cpp
index 4ef0baf1c98..6e7717349bb 100644
--- a/src/osd/windows/main.cpp
+++ b/src/osd/windows/main.cpp
@@ -17,6 +17,8 @@
#include "strconv.h"
+#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
+
extern int utf8_main(int argc, char *argv[]);
//============================================================
// main
@@ -50,3 +52,18 @@ extern "C" int _tmain(int argc, TCHAR **argv)
return rc;
}
#endif
+
+#else
+
+#include "winmain.h"
+
+// The main function is only used to initialize our IFrameworkView class.
+[Platform::MTAThread]
+int main(Platform::Array<Platform::String^>^)
+{
+ auto app_source = ref new MameViewSource();
+ Windows::ApplicationModel::Core::CoreApplication::Run(app_source);
+ return 0;
+}
+
+#endif
diff --git a/src/osd/windows/output.cpp b/src/osd/windows/output.cpp
deleted file mode 100644
index ef3c563e3ac..00000000000
--- a/src/osd/windows/output.cpp
+++ /dev/null
@@ -1,320 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Aaron Giles
-//============================================================
-//
-// output.c - Win32 implementation of MAME output routines
-//
-//============================================================
-
-// standard windows headers
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-
-// MAME headers
-#include "emu.h"
-#include "winmain.h"
-// MAMEOS headers
-#include "output.h"
-
-#include "winutil.h"
-
-
-
-//============================================================
-// CONSTANTS
-//============================================================
-
-// window styles
-#define WINDOW_STYLE WS_OVERLAPPEDWINDOW
-#define WINDOW_STYLE_EX 0
-
-
-
-//============================================================
-// TYPEDEFS
-//============================================================
-
-struct registered_client
-{
- registered_client * next; // next client in the list
- LPARAM id; // client-specified ID
- HWND hwnd; // client HWND
- running_machine * machine;
-};
-
-
-
-//============================================================
-// GLOBAL VARIABLES
-//============================================================
-
-// our HWND
-static HWND output_hwnd;
-
-// client list
-static registered_client * clientlist;
-
-// message IDs
-static UINT om_mame_start;
-static UINT om_mame_stop;
-static UINT om_mame_update_state;
-static UINT om_mame_register_client;
-static UINT om_mame_unregister_client;
-static UINT om_mame_get_id_string;
-
-
-
-//============================================================
-// FUNCTION PROTOTYPES
-//============================================================
-
-static int create_window_class(void);
-static LRESULT CALLBACK output_window_proc(HWND wnd, UINT message, WPARAM wparam, LPARAM lparam);
-static LRESULT register_client(running_machine &machine, HWND hwnd, LPARAM id);
-static LRESULT unregister_client(running_machine &machine, HWND hwnd, LPARAM id);
-static LRESULT send_id_string(running_machine &machine, HWND hwnd, LPARAM id);
-static void notifier_callback(const char *outname, INT32 value, void *param);
-
-
-
-//============================================================
-// output_init
-//============================================================
-
-bool windows_osd_interface::output_init()
-{
- int result;
-
- // reset globals
- clientlist = nullptr;
-
- // create our window class
- result = create_window_class();
- assert(result == 0);
- (void)result; // to silence gcc 4.6
-
- // create a window
- output_hwnd = CreateWindowEx(
- WINDOW_STYLE_EX,
- OUTPUT_WINDOW_CLASS,
- OUTPUT_WINDOW_NAME,
- WINDOW_STYLE,
- 0, 0,
- 1, 1,
- nullptr,
- nullptr,
- GetModuleHandleUni(),
- nullptr);
- assert(output_hwnd != nullptr);
-
- // set a pointer to the running machine
- SetWindowLongPtr(output_hwnd, GWLP_USERDATA, (LONG_PTR)&machine());
-
- // allocate message ids
- om_mame_start = RegisterWindowMessage(OM_MAME_START);
- assert(om_mame_start != 0);
- om_mame_stop = RegisterWindowMessage(OM_MAME_STOP);
- assert(om_mame_stop != 0);
- om_mame_update_state = RegisterWindowMessage(OM_MAME_UPDATE_STATE);
- assert(om_mame_update_state != 0);
-
- om_mame_register_client = RegisterWindowMessage(OM_MAME_REGISTER_CLIENT);
- assert(om_mame_register_client != 0);
- om_mame_unregister_client = RegisterWindowMessage(OM_MAME_UNREGISTER_CLIENT);
- assert(om_mame_unregister_client != 0);
- om_mame_get_id_string = RegisterWindowMessage(OM_MAME_GET_ID_STRING);
- assert(om_mame_get_id_string != 0);
-
- // broadcast a startup message
- PostMessage(HWND_BROADCAST, om_mame_start, (WPARAM)output_hwnd, 0);
-
- // register a notifier for output changes
- machine().output().set_notifier(nullptr, notifier_callback, &machine());
-
- return true;
-}
-
-
-//============================================================
-// output_exit
-//============================================================
-
-void windows_osd_interface::output_exit()
-{
- // free all the clients
- while (clientlist != nullptr)
- {
- registered_client *temp = clientlist;
- clientlist = temp->next;
- global_free(temp);
- }
-
- // broadcast a shutdown message
- PostMessage(HWND_BROADCAST, om_mame_stop, (WPARAM)output_hwnd, 0);
-}
-
-
-//============================================================
-// create_window_class
-//============================================================
-
-static int create_window_class(void)
-{
- static UINT8 classes_created = FALSE;
-
- /* only do this once */
- if (!classes_created)
- {
- WNDCLASS wc = { 0 };
-
- // initialize the description of the window class
- wc.lpszClassName = OUTPUT_WINDOW_CLASS;
- wc.hInstance = GetModuleHandleUni();
- wc.lpfnWndProc = output_window_proc;
-
- UnregisterClass(wc.lpszClassName, wc.hInstance);
-
- // register the class; fail if we can't
- if (!RegisterClass(&wc))
- return 1;
- classes_created = TRUE;
- }
-
- return 0;
-}
-
-
-//============================================================
-// output_window_proc
-//============================================================
-
-static LRESULT CALLBACK output_window_proc(HWND wnd, UINT message, WPARAM wparam, LPARAM lparam)
-{
- LONG_PTR ptr = GetWindowLongPtr(wnd, GWLP_USERDATA);
- running_machine &machine = *(running_machine *)ptr;
-
- // register a new client
- if (message == om_mame_register_client)
- return register_client(machine,(HWND)wparam, lparam);
-
- // unregister a client
- else if (message == om_mame_unregister_client)
- return unregister_client(machine,(HWND)wparam, lparam);
-
- // get a string for an ID
- else if (message == om_mame_get_id_string)
- return send_id_string(machine, (HWND)wparam, lparam);
-
- else
- return DefWindowProc(wnd, message, wparam, lparam);
-}
-
-
-//============================================================
-// register_client
-//============================================================
-
-static LRESULT register_client(running_machine &machine, HWND hwnd, LPARAM id)
-{
- registered_client **client;
-
- // find the end of the list; if we find ourself already registered,
- // return 1
- for (client = &clientlist; *client != nullptr; client = &(*client)->next)
- if ((*client)->id == id)
- {
- (*client)->hwnd = hwnd;
- machine.output().notify_all(notifier_callback, *client);
- return 1;
- }
-
- // add us to the end
- *client = global_alloc(registered_client);
- (*client)->next = nullptr;
- (*client)->id = id;
- (*client)->hwnd = hwnd;
- (*client)->machine = &machine;
-
- // request a notification for all outputs
- machine.output().notify_all(notifier_callback, *client);
- return 0;
-}
-
-
-//============================================================
-// unregister_client
-//============================================================
-
-static LRESULT unregister_client(running_machine &machine, HWND hwnd, LPARAM id)
-{
- registered_client **client;
- int found = FALSE;
-
- // find any matching IDs in the list and remove them
- for (client = &clientlist; *client != nullptr; client = &(*client)->next)
- if ((*client)->id == id)
- {
- registered_client *temp = *client;
- *client = (*client)->next;
- global_free(temp);
- found = TRUE;
- break;
- }
-
- // return an error if not found
- return found ? 0 : 1;
-}
-
-
-//============================================================
-// send_id_string
-//============================================================
-
-static LRESULT send_id_string(running_machine &machine, HWND hwnd, LPARAM id)
-{
- COPYDATASTRUCT copydata;
- const char *name;
- int datalen;
-
- // id 0 is the name of the game
- if (id == 0)
- name = machine.system().name;
- else
- name = machine.output().id_to_name(id);
-
- // a NULL name is an empty string
- if (name == nullptr)
- name = "";
-
- // allocate memory for the message
- datalen = sizeof(copydata_id_string) + strlen(name) + 1;
- dynamic_buffer buffer(datalen);
- copydata_id_string *temp = (copydata_id_string *)&buffer[0];
- temp->id = id;
- strcpy(temp->string, name);
-
- // reply by using SendMessage with WM_COPYDATA
- copydata.dwData = COPYDATA_MESSAGE_ID_STRING;
- copydata.cbData = datalen;
- copydata.lpData = temp;
- SendMessage(hwnd, WM_COPYDATA, (WPARAM)output_hwnd, (LPARAM)&copydata);
-
- return 0;
-}
-
-
-//============================================================
-// notifier_callback
-//============================================================
-
-static void notifier_callback(const char *outname, INT32 value, void *param)
-{
- registered_client *client;
- // loop over clients and notify them
- for (client = clientlist; client != nullptr; client = client->next)
- {
- if (param == nullptr || param == client->machine) {
- PostMessage(client->hwnd, om_mame_update_state, client->machine->output().name_to_id(outname), value);
- }
- }
-}
diff --git a/src/osd/windows/output.h b/src/osd/windows/output.h
deleted file mode 100644
index 9d71332b44b..00000000000
--- a/src/osd/windows/output.h
+++ /dev/null
@@ -1,86 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Aaron Giles
-//============================================================
-//
-// output.h - Win32 implementation of MAME output routines
-//
-//============================================================
-
-#ifndef __WINDOWS_OUTPUT_H__
-#define __WINDOWS_OUTPUT_H__
-
-
-//============================================================
-// CONSTANTS
-//============================================================
-
-// window parameters
-#define OUTPUT_WINDOW_CLASS TEXT("MAMEOutput")
-#define OUTPUT_WINDOW_NAME TEXT("MAMEOutput")
-
-//
-// These messages are sent by MAME:
-//
-
-// OM_MAME_START: broadcast when MAME initializes
-// WPARAM = HWND of MAME's output window
-// LPARAM = unused
-#define OM_MAME_START TEXT("MAMEOutputStart")
-
-// OM_MAME_STOP: broadcast when MAME shuts down
-// WPARAM = HWND of MAME's output window
-// LPARAM = unused
-#define OM_MAME_STOP TEXT("MAMEOutputStop")
-
-// OM_MAME_UPDATE_STATE: sent to registered clients when the state
-// of an output changes
-// WPARAM = ID of the output
-// LPARAM = new value for the output
-#define OM_MAME_UPDATE_STATE TEXT("MAMEOutputUpdateState")
-
-
-//
-// These messages are sent by external clients to MAME:
-//
-
-// OM_MAME_REGISTER_CLIENT: sent to MAME to register a client
-// WPARAM = HWND of client's listener window
-// LPARAM = client-specified ID (must be unique)
-#define OM_MAME_REGISTER_CLIENT TEXT("MAMEOutputRegister")
-
-// OM_MAME_UNREGISTER_CLIENT: sent to MAME to unregister a client
-// WPARAM = HWND of client's listener window
-// LPARAM = client-specified ID (must match registration)
-#define OM_MAME_UNREGISTER_CLIENT TEXT("MAMEOutputUnregister")
-
-// OM_MAME_GET_ID_STRING: requests the string associated with a
-// given ID. ID=0 is always the name of the game. Other IDs are
-// only discoverable from a OM_MAME_UPDATE_STATE message. The
-// result will be sent back as a WM_COPYDATA message with MAME's
-// output window as the sender, dwData = the ID of the string,
-// and lpData pointing to a NULL-terminated string.
-// WPARAM = HWND of client's listener window
-// LPARAM = ID you wish to know about
-#define OM_MAME_GET_ID_STRING TEXT("MAMEOutputGetIDString")
-
-
-//
-// These constants are used to identify WM_COPYDATA messages
-// coming from MAME:
-//
-
-#define COPYDATA_MESSAGE_ID_STRING 1
-
-
-
-//============================================================
-// TYPE DEFINITIONS
-//============================================================
-
-struct copydata_id_string
-{
- UINT32 id; // ID that was requested
- char string[1]; // string array containing the data
-};
-
-#endif /* __WINDOWS_OUTPUT_H__ */
diff --git a/src/osd/windows/video.cpp b/src/osd/windows/video.cpp
index 2da04f8b155..f6de9222c50 100644
--- a/src/osd/windows/video.cpp
+++ b/src/osd/windows/video.cpp
@@ -89,15 +89,6 @@ bool windows_osd_interface::video_init()
}
//============================================================
-// get_slider_list
-//============================================================
-
-slider_state *windows_osd_interface::get_slider_list()
-{
- return m_sliders;
-}
-
-//============================================================
// video_exit
//============================================================
diff --git a/src/osd/windows/window.cpp b/src/osd/windows/window.cpp
index ad8de3d2890..0e30da1b93d 100644
--- a/src/osd/windows/window.cpp
+++ b/src/osd/windows/window.cpp
@@ -272,33 +272,14 @@ int windows_osd_interface::window_count()
void windows_osd_interface::build_slider_list()
{
- m_sliders = nullptr;
- slider_state* full_list = nullptr;
- slider_state* curr = nullptr;
+ m_sliders.clear();
+
for (win_window_info *window = win_window_list; window != nullptr; window = window->m_next)
{
// take the sliders of the first window
- slider_state* window_sliders = window->m_renderer->get_slider_list();
- if (window_sliders == nullptr)
- {
- continue;
- }
-
- if (full_list == nullptr)
- {
- full_list = curr = window_sliders;
- }
- else
- {
- curr->next = window_sliders;
- }
-
- while (curr->next != nullptr) {
- curr = curr->next;
- }
+ std::vector<ui_menu_item> window_sliders = window->m_renderer->get_slider_list();
+ m_sliders.insert(m_sliders.end(), window_sliders.begin(), window_sliders.end());
}
-
- m_sliders = full_list;
}
//============================================================
diff --git a/src/osd/windows/winmain.cpp b/src/osd/windows/winmain.cpp
index c7b1cb619e8..7249c9ee747 100644
--- a/src/osd/windows/winmain.cpp
+++ b/src/osd/windows/winmain.cpp
@@ -33,6 +33,13 @@
#include "winutil.h"
#include "debugger.h"
#include "winfile.h"
+#include "strconv.h"
+
+#if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
+using namespace Windows::ApplicationModel;
+using namespace Windows::ApplicationModel::Core;
+using namespace Windows::UI::Popups;
+#endif
#define DEBUG_SLOW_LOCKS 0
@@ -219,6 +226,33 @@ public:
}
};
+#else
+
+//============================================================
+// winuniversal_output_error
+//============================================================
+
+class winuniversal_output_error : public osd_output
+{
+public:
+ virtual void output_callback(osd_output_channel channel, const char *msg, va_list args) override
+ {
+ if (channel == OSD_OUTPUT_CHANNEL_ERROR)
+ {
+ char buffer[1024];
+ vsnprintf(buffer, ARRAY_LENGTH(buffer), msg, args);
+
+ osd_unique_wstr wcbuffer(wstring_from_utf8(buffer));
+ osd_unique_wstr wcappname(wstring_from_utf8(emulator_info::get_appname()));
+
+ auto dlg = ref new MessageDialog(ref new Platform::String(wcbuffer.get()), ref new Platform::String(wcappname.get()));
+ dlg->ShowAsync();
+ }
+ else
+ chain_output(channel, msg, args);
+ }
+};
+
#endif
@@ -474,6 +508,70 @@ static BOOL WINAPI control_handler(DWORD type)
return TRUE;
}
+#else
+
+MameMainApp::MameMainApp()
+{
+}
+
+void MameMainApp::Initialize(Windows::ApplicationModel::Core::CoreApplicationView^ applicationView)
+{
+ // Register event handlers for app lifecycle.
+}
+
+// Called when the CoreWindow object is created (or re-created).
+void MameMainApp::SetWindow(Windows::UI::Core::CoreWindow^ window)
+{
+ // Attach event handlers on the window for input, etc.
+}
+
+// Initializes scene resources, or loads a previously saved app state.
+void MameMainApp::Load(Platform::String^ entryPoint)
+{
+}
+
+void MameMainApp::Run()
+{
+ // use small output buffers on non-TTYs (i.e. pipes)
+ if (!isatty(fileno(stdout)))
+ setvbuf(stdout, (char *) nullptr, _IOFBF, 64);
+ if (!isatty(fileno(stderr)))
+ setvbuf(stderr, (char *) nullptr, _IOFBF, 64);
+
+ // parse config and cmdline options
+ m_options = std::make_unique<windows_options>();
+ m_osd = std::make_unique<windows_osd_interface>(m_options);
+
+ // Since we're a GUI app, out errors to message boxes
+ // Initialize this after the osd interface so that we are first in the
+ // output order
+ winuniversal_output_error winerror;
+ osd_output::push(&winerror);
+
+ m_osd->register_options();
+ m_frontend = std::make_unique<cli_frontend>(*m_options.get(), *m_osd.get());
+
+ // To satisfy the latter things, pass in the module path name
+ char exe_path[MAX_PATH];
+ GetModuleFileNameA(NULL, exe_path, MAX_PATH);
+ char* args[2] = { exe_path, (char*)"-verbose" };
+
+ DWORD result = m_frontend->execute(ARRAY_LENGTH(args), args);
+ osd_output::pop(&winerror);
+}
+
+// Required for IFrameworkView.
+void MameMainApp::Uninitialize()
+{
+ // Terminate events do not cause Uninitialize to be called. It will be called if your IFrameworkView
+ // class is torn down while the app is in the foreground.
+}
+
+IFrameworkView^ MameViewSource::CreateView()
+{
+ return ref new MameMainApp();
+}
+
#endif
@@ -506,7 +604,6 @@ static void output_oslog(const running_machine &machine, const char *buffer)
windows_osd_interface::windows_osd_interface(windows_options &options)
: osd_common_t(options)
, m_options(options)
- , m_sliders(nullptr)
{
}
diff --git a/src/osd/windows/winmain.h b/src/osd/windows/winmain.h
index 162c2ada1dd..f4d1a611191 100644
--- a/src/osd/windows/winmain.h
+++ b/src/osd/windows/winmain.h
@@ -9,6 +9,7 @@
#ifndef __WINDOWS_WINMAIN_H__
#define __WINDOWS_WINMAIN_H__
+#include <winapifamily.h>
#include "clifront.h"
#include "osdepend.h"
#include "modules/lib/osdobj_common.h"
@@ -210,8 +211,6 @@ private:
static const options_entry s_option_entries[];
};
-
-
//============================================================
// MACROS
//============================================================
@@ -263,19 +262,15 @@ public:
virtual void update(bool skip_redraw) override;
// video overridables
- virtual slider_state *get_slider_list() override;
-
virtual void customize_input_type_list(simple_list<input_type_entry> &typelist) override;
virtual void video_register() override;
virtual bool video_init() override;
virtual bool window_init() override;
- virtual bool output_init() override;
virtual void video_exit() override;
virtual void window_exit() override;
- virtual void output_exit() override;
void extract_video_config();
@@ -296,12 +291,37 @@ private:
virtual void osd_exit() override;
windows_options & m_options;
- slider_state * m_sliders;
static const int DEFAULT_FONT_HEIGHT = 200;
};
+#if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
+
+ref class MameMainApp sealed : public Windows::ApplicationModel::Core::IFrameworkView
+{
+private:
+ std::unique_ptr<windows_options> m_options;
+ std::unique_ptr<windows_osd_interface> m_osd;
+ std::unique_ptr<cli_frontend> m_frontend;
+
+public:
+ MameMainApp();
+
+ // IFrameworkView Methods.
+ virtual void Initialize(Windows::ApplicationModel::Core::CoreApplicationView^ applicationView);
+ virtual void SetWindow(Windows::UI::Core::CoreWindow^ window);
+ virtual void Load(Platform::String^ entryPoint);
+ virtual void Run();
+ virtual void Uninitialize();
+};
+
+ref class MameViewSource sealed : Windows::ApplicationModel::Core::IFrameworkViewSource
+{
+public:
+ virtual Windows::ApplicationModel::Core::IFrameworkView^ CreateView();
+};
+#endif
//============================================================
// GLOBAL VARIABLES